executable.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <mach.h>
  13. #include "elf.h"
  14. /*
  15. * All a.out header types. The dummy entry allows canonical
  16. * processing of the union as a sequence of longs
  17. */
  18. typedef struct {
  19. union{
  20. struct {
  21. /* this will die soon. For now, just include it here. */
  22. int32_t magic; /* magic number */
  23. int32_t text; /* size of text segment */
  24. int32_t data; /* size of initialized data */
  25. int32_t bss; /* size of uninitialized data */
  26. int32_t syms; /* size of symbol table */
  27. int32_t entry; /* entry point */
  28. int32_t spsz; /* size of pc/sp offset table */
  29. int32_t pcsz; /* size of pc/line number table */
  30. };
  31. E64hdr E64hdr;
  32. } e;
  33. int32_t dummy; /* padding to ensure extra long */
  34. } ExecHdr;
  35. static int elfdotout(int, Fhdr*, ExecHdr*);
  36. static void setsym(Fhdr*, int32_t, int32_t, int32_t, int64_t);
  37. static void setdata(Fhdr*, uint64_t, int32_t, int64_t,
  38. int32_t);
  39. static void settext(Fhdr*, uint64_t, uint64_t, int32_t,
  40. int64_t);
  41. static void hswal(void*, int, uint32_t(*)(uint32_t));
  42. /*
  43. * definition of per-executable file type structures
  44. */
  45. typedef struct Exectable{
  46. int32_t magic; /* big-endian magic number of file */
  47. char *name; /* executable identifier */
  48. char *dlmname; /* dynamically loadable module identifier */
  49. uint8_t type; /* Internal code */
  50. uint8_t _magic; /* _MAGIC() magic */
  51. Mach *mach; /* Per-machine data */
  52. int32_t hsize; /* header size */
  53. uint32_t (*swal)(uint32_t); /* beswal or leswal */
  54. int (*hparse)(int, Fhdr*, ExecHdr*);
  55. } ExecTable;
  56. extern Mach mamd64;
  57. ExecTable exectab[] =
  58. {
  59. { ELF_MAG, /* any ELF */
  60. "elf executable",
  61. nil,
  62. FNONE,
  63. 0,
  64. /* &mi386,
  65. sizeof(Ehdr), */
  66. &mamd64,
  67. sizeof(E64hdr),
  68. nil,
  69. elfdotout },
  70. { 0 },
  71. };
  72. Mach *mach = &mamd64;
  73. static ExecTable*
  74. couldbe4k(ExecTable *mp)
  75. {
  76. // Dir *d;
  77. ExecTable *f;
  78. /* undefined for use with kernel
  79. if((d=dirstat("/proc/1/regs")) == nil)
  80. return mp;
  81. if(d->length < 32*8){ / * R3000 * /
  82. free(d);
  83. return mp;
  84. }
  85. free(d); */
  86. for (f = exectab; f->magic; f++)
  87. if(f->magic == M_MAGIC) {
  88. f->name = "mips plan 9 executable on mips2 kernel";
  89. return f;
  90. }
  91. return mp;
  92. }
  93. int
  94. crackhdr(int fd, Fhdr *fp)
  95. {
  96. ExecTable *mp;
  97. ExecHdr d;
  98. int nb, ret;
  99. uint32_t magic;
  100. fp->type = FNONE;
  101. nb = read(fd, (char *)&d.e, sizeof(d.e));
  102. if (nb <= 0)
  103. return 0;
  104. ret = 0;
  105. magic = beswal(d.e.magic); /* big-endian */
  106. for (mp = exectab; mp->magic; mp++) {
  107. if (nb < mp->hsize)
  108. continue;
  109. /*
  110. * The magic number has morphed into something
  111. * with fields (the straw was DYN_MAGIC) so now
  112. * a flag is needed in Fhdr to distinguish _MAGIC()
  113. * magic numbers from foreign magic numbers.
  114. *
  115. * This code is creaking a bit and if it has to
  116. * be modified/extended much more it's probably
  117. * time to step back and redo it all.
  118. */
  119. if(mp->_magic){
  120. if(mp->magic != (magic & ~DYN_MAGIC))
  121. continue;
  122. if(mp->magic == V_MAGIC)
  123. mp = couldbe4k(mp);
  124. if ((magic & DYN_MAGIC) && mp->dlmname != nil)
  125. fp->name = mp->dlmname;
  126. else
  127. fp->name = mp->name;
  128. }
  129. else{
  130. if(mp->magic != magic)
  131. continue;
  132. fp->name = mp->name;
  133. }
  134. fp->type = mp->type;
  135. fp->hdrsz = mp->hsize; /* will be zero on bootables */
  136. fp->_magic = mp->_magic;
  137. fp->magic = magic;
  138. mach = mp->mach;
  139. if(mp->swal != nil)
  140. hswal(&d, sizeof(d.e)/sizeof(uint32_t), mp->swal);
  141. ret = mp->hparse(fd, fp, &d);
  142. seek(fd, mp->hsize, 0); /* seek to end of header */
  143. break;
  144. }
  145. if(mp->magic == 0)
  146. werrstr("unknown header type");
  147. return ret;
  148. }
  149. /*
  150. * Convert header to canonical form
  151. */
  152. static void
  153. hswal(void *v, int n, uint32_t (*swap)(uint32_t))
  154. {
  155. uint32_t *ulp;
  156. for(ulp = v; n--; ulp++)
  157. *ulp = (*swap)(*ulp);
  158. }
  159. /*
  160. * ELF64 binaries.
  161. */
  162. static int
  163. elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
  164. {
  165. E64hdr *ep;
  166. P64hdr *ph;
  167. uint16_t (*swab)(uint16_t);
  168. uint32_t (*swal)(uint32_t);
  169. uint64_t (*swav)(uint64_t);
  170. int i, it, id, is, phsz;
  171. uint64_t uvl;
  172. ep = &hp->e.E64hdr;
  173. if(ep->ident[DATA] == ELFDATA2LSB) {
  174. swab = leswab;
  175. swal = leswal;
  176. swav = leswav;
  177. } else if(ep->ident[DATA] == ELFDATA2MSB) {
  178. swab = beswab;
  179. swal = beswal;
  180. swav = beswav;
  181. } else {
  182. werrstr("bad ELF64 encoding - not big or little endian");
  183. return 0;
  184. }
  185. ep->type = swab(ep->type);
  186. ep->machine = swab(ep->machine);
  187. ep->version = swal(ep->version);
  188. if(ep->type != EXEC || ep->version != CURRENT)
  189. return 0;
  190. ep->elfentry = swav(ep->elfentry);
  191. ep->phoff = swav(ep->phoff);
  192. ep->shoff = swav(ep->shoff);
  193. ep->flags = swal(ep->flags);
  194. ep->ehsize = swab(ep->ehsize);
  195. ep->phentsize = swab(ep->phentsize);
  196. ep->phnum = swab(ep->phnum);
  197. ep->shentsize = swab(ep->shentsize);
  198. ep->shnum = swab(ep->shnum);
  199. ep->shstrndx = swab(ep->shstrndx);
  200. fp->magic = ELF_MAG;
  201. fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
  202. switch(ep->machine) {
  203. default:
  204. return 0;
  205. case AMD64:
  206. mach = &mamd64;
  207. fp->type = FAMD64;
  208. fp->name = "amd64 ELF64 executable";
  209. break;
  210. case POWER64:
  211. fp->type = FPOWER64;
  212. fp->name = "power64 ELF64 executable";
  213. break;
  214. }
  215. if(ep->phentsize != sizeof(P64hdr)) {
  216. werrstr("bad ELF64 header size");
  217. return 0;
  218. }
  219. phsz = sizeof(P64hdr)*ep->phnum;
  220. ph = malloc(phsz);
  221. if(!ph)
  222. return 0;
  223. seek(fd, ep->phoff, 0);
  224. if(read(fd, ph, phsz) < 0) {
  225. free(ph);
  226. return 0;
  227. }
  228. for(i = 0; i < ep->phnum; i++) {
  229. ph[i].type = swal(ph[i].type);
  230. ph[i].flags = swal(ph[i].flags);
  231. ph[i].offset = swav(ph[i].offset);
  232. ph[i].vaddr = swav(ph[i].vaddr);
  233. ph[i].paddr = swav(ph[i].paddr);
  234. ph[i].filesz = swav(ph[i].filesz);
  235. ph[i].memsz = swav(ph[i].memsz);
  236. ph[i].align = swav(ph[i].align);
  237. }
  238. /* find text, data and symbols and install them */
  239. it = id = is = -1;
  240. for(i = 0; i < ep->phnum; i++) {
  241. if(ph[i].type == LOAD
  242. && (ph[i].flags & (R|X)) == (R|X) && it == -1)
  243. it = i;
  244. else if(ph[i].type == LOAD
  245. && (ph[i].flags & (R|W)) == (R|W) && id == -1)
  246. id = i;
  247. else if(ph[i].type == NOPTYPE && is == -1)
  248. is = i;
  249. }
  250. if(it == -1 || id == -1) {
  251. werrstr("No ELF64 TEXT or DATA sections");
  252. free(ph);
  253. return 0;
  254. }
  255. settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
  256. /* 8c: out of fixed registers */
  257. uvl = ph[id].memsz - ph[id].filesz;
  258. setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl);
  259. if(is != -1)
  260. setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset);
  261. free(ph);
  262. return 1;
  263. }
  264. /*
  265. * Elf binaries.
  266. */
  267. static int
  268. elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
  269. {
  270. // Ehdr *ep;
  271. E64hdr *ep;
  272. /* bitswap the header according to the DATA format */
  273. ep = &hp->e.E64hdr;
  274. // if(ep->ident[CLASS] == ELFCLASS32)
  275. // return elf32dotout(fd, fp, hp);
  276. // else if(ep->ident[CLASS] == ELFCLASS64)
  277. if(ep->ident[CLASS] == ELFCLASS64)
  278. return elf64dotout(fd, fp, hp);
  279. // werrstr("bad ELF class - not 32- nor 64-bit");
  280. werrstr("bad ELF class - not 64-bit");
  281. return 0;
  282. }
  283. static void
  284. settext(Fhdr *fp, uint64_t e, uint64_t a, int32_t s, int64_t off)
  285. {
  286. fp->txtaddr = a;
  287. fp->entry = e;
  288. fp->txtsz = s;
  289. fp->txtoff = off;
  290. }
  291. static void
  292. setdata(Fhdr *fp, uint64_t a, int32_t s, int64_t off, int32_t bss)
  293. {
  294. fp->dataddr = a;
  295. fp->datsz = s;
  296. fp->datoff = off;
  297. fp->bsssz = bss;
  298. }
  299. static void
  300. setsym(Fhdr *fp, int32_t symsz, int32_t sppcsz, int32_t lnpcsz,
  301. int64_t symoff)
  302. {
  303. fp->symsz = symsz;
  304. fp->symoff = symoff;
  305. fp->sppcsz = sppcsz;
  306. fp->sppcoff = fp->symoff+fp->symsz;
  307. fp->lnpcsz = lnpcsz;
  308. fp->lnpcoff = fp->sppcoff+fp->sppcsz;
  309. }