Russ, this code works with the files that jmk sent me, which appear to be in the same format as those spit out by vl -H5. It is a major departure from how the code used to work, though. Previously it would load up elf sections by name using the SHDRs and string table. The vl -H5 files and the files jmk sent me do not have this information. So the result is libmach can load up the vl -H5 files with this patch, but probably can no longer load up some elf files that it previously was capable of loading. If you would prefer keeping the old functionality rather than the vl ELF file support, I can fix up the endian issues if someone provides me with the appropriate Irix elf files to test against. Notes: Thu Feb 3 10:33:26 EST 2005 rsc I agree that the right thing to do is use the phdr info instead of the shdr. The shdr is only there as a courtesy, while the phdr is required for the binary to be loaded by the OS. However, I'd prefer not to use constant offsets into the phdr. There are type bits in the phdr that can be used to figure out which section is the text, which is the data, and which is the symbols. See http://cvs.pdos.lcs.mit.edu/cvs/plan9/src/libmach/elf.c?rev=HEAD for how I parse the ELF files from Linux and FreeBSD. Russ Reference: /n/sources/patch/sorry/libmach-elf Date: Sat Feb 5 14:30:04 CET 2005 Reviewed-by: rsc --- /sys/src/libmach/executable.c Sat Feb 5 14:30:03 2005 +++ /sys/src/libmach/executable.c Sat Feb 5 14:30:03 2005 @@ -438,24 +438,7 @@ return 1; } -static Shdr* -elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) -{ - int i, offset, n; - char s[64]; - offset = sp[hp->shstrndx].offset; - for(i = 1; i < hp->shnum; i++) { - seek(fd, offset+sp[i].name, 0); - n = read(fd, s, sizeof(s)-1); - if(n < 0) - continue; - s[n] = 0; - if(strcmp(s, name) == 0) - return &sp[i]; - } - return 0; -} /* * Decode an Irix 5.x ELF header */ @@ -464,96 +447,49 @@ { Ehdr *ep; - Shdr *es, *txt, *init, *s; - long addr, size, offset, bsize; + Phdr ph[3]; + /* undo the previous incorrect swap and redo it properly */ ep = &hp->e; - if(ep->type != 8 || ep->machine != 2 || ep->version != 1) + hswal((long*)ep, sizeof *ep / sizeof(long), beswal); + ep->type = beswab(ep->type); + ep->machine = beswab(ep->machine); + ep->version = beswal(ep->version); + ep->elfentry = beswal(ep->elfentry); + ep->phoff = beswal(ep->phoff); + ep->shoff = beswal(ep->shoff); + ep->flags = beswal(ep->flags); + ep->ehsize = beswab(ep->ehsize); + ep->phentsize = beswab(ep->phentsize); + ep->phnum = beswab(ep->phnum); + ep->shentsize = beswab(ep->shentsize); + ep->shnum = beswab(ep->shnum); + ep->shstrndx = beswab(ep->shstrndx); + if(ep->type != 2 || ep->machine != 8 || ep->version != 1) return 0; fp->magic = ELF_MAG; fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; - if(ep->shnum <= 0) { - werrstr("no ELF header sections"); + if(ep->phnum != 3) { + werrstr("unexpected ELF headers"); return 0; } - es = malloc(sizeof(Shdr)*ep->shnum); - if(es == 0) - return 0; - seek(fd, ep->shoff, 0); - if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ - free(es); + seek(fd, ep->phoff, 0); + if(read(fd, ph, sizeof(Phdr)*ep->phnum) < 0) return 0; - } - - txt = elfsectbyname(fd, ep, es, ".text"); - init = elfsectbyname(fd, ep, es, ".init"); - if(txt == 0 || init == 0 || init != txt+1) - goto bad; - if(txt->addr+txt->size != init->addr) - goto bad; - settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); - - addr = 0; - offset = 0; - size = 0; - s = elfsectbyname(fd, ep, es, ".data"); - if(s) { - addr = s->addr; - size = s->size; - offset = s->offset; - } + hswal((long*)ph, sizeof(Phdr)*ep->phnum/sizeof(long), beswal); - s = elfsectbyname(fd, ep, es, ".rodata"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - size += s->size; - } - - s = elfsectbyname(fd, ep, es, ".got"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - size += s->size; - } - - bsize = 0; - s = elfsectbyname(fd, ep, es, ".bss"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - bsize = s->size; + if(ph[0].type != LOAD || ph[1].type != LOAD || ph[2].type != NOPTYPE) { + werrstr("unexpected ELF headers"); + return 0; } - if(addr == 0) - goto bad; - - setdata(fp, addr, size, offset, bsize); - fp->name = "IRIX Elf a.out executable"; - free(es); + settext(fp, ep->elfentry, ph[0].vaddr, ph[0].memsz, ph[0].offset); + setdata(fp, ph[1].vaddr, ph[1].memsz, ph[1].offset, ph[1].memsz - ph[1].filesz); + setsym(fp, ph[2].filesz, 0, ph[2].memsz, ph[2].offset); return 1; -bad: - free(es); - werrstr("ELF sections scrambled"); - return 0; } /*