executable.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. /*
  14. * All a.out header types. The dummy entry allows canonical
  15. * processing of the union as a sequence of longs
  16. */
  17. typedef struct {
  18. union{
  19. struct {
  20. /* this will die soon. For now, just include it here. */
  21. int32_t magic; /* magic number */
  22. int32_t text; /* size of text segment */
  23. int32_t data; /* size of initialized data */
  24. int32_t bss; /* size of uninitialized data */
  25. int32_t syms; /* size of symbol table */
  26. int32_t entry; /* entry point */
  27. int32_t spsz; /* size of pc/sp offset table */
  28. int32_t pcsz; /* size of pc/line number table */
  29. };
  30. E64hdr E64hdr;
  31. } e;
  32. int32_t dummy; /* padding to ensure extra long */
  33. } ExecHdr;
  34. static int elfdotout(int, Fhdr*, ExecHdr*);
  35. static void setsym(Fhdr*, int32_t, int32_t, int32_t, int64_t);
  36. static void setdata(Fhdr*, uint64_t, int32_t, int64_t, int32_t);
  37. static void settext(Fhdr*, uint64_t, uint64_t, int32_t, int64_t);
  38. static void setstr(Fhdr *fp, int64_t stroff, uint64_t strsz);
  39. static void setbssidx(Fhdr *fp, uint16_t bssidx);
  40. static void hswal(void*, int, uint32_t(*)(uint32_t));
  41. /*
  42. * definition of per-executable file type structures
  43. */
  44. typedef struct Exectable{
  45. int32_t magic; /* big-endian magic number of file */
  46. char *name; /* executable identifier */
  47. char *dlmname; /* dynamically loadable module identifier */
  48. uint8_t type; /* Internal code */
  49. Mach *mach; /* Per-machine data */
  50. int32_t hsize; /* header size */
  51. uint32_t (*swal)(uint32_t); /* beswal or leswal */
  52. int (*hparse)(int, Fhdr*, ExecHdr*);
  53. } ExecTable;
  54. extern Mach mamd64;
  55. ExecTable exectab[] =
  56. {
  57. { ELF_MAG, /* any ELF */
  58. "elf executable",
  59. nil,
  60. FNONE,
  61. &mamd64,
  62. sizeof(E64hdr),
  63. nil,
  64. elfdotout },
  65. { 0 },
  66. };
  67. Mach *mach = &mamd64;
  68. int
  69. crackhdr(int fd, Fhdr *fp)
  70. {
  71. ExecTable *mp;
  72. ExecHdr d;
  73. int nb, ret;
  74. uint32_t magic;
  75. fp->type = FNONE;
  76. nb = read(fd, (char *)&d.e, sizeof(d.e));
  77. if (nb <= 0)
  78. return 0;
  79. ret = 0;
  80. magic = beswal(d.e.magic); /* big-endian */
  81. for (mp = exectab; mp->magic; mp++) {
  82. if (nb < mp->hsize)
  83. continue;
  84. if(mp->magic != magic)
  85. continue;
  86. fp->name = mp->name;
  87. fp->type = mp->type;
  88. fp->hdrsz = mp->hsize; /* will be zero on bootables */
  89. fp->magic = magic;
  90. mach = mp->mach;
  91. if(mp->swal != nil)
  92. hswal(&d, sizeof(d.e)/sizeof(uint32_t), mp->swal);
  93. ret = mp->hparse(fd, fp, &d);
  94. seek(fd, mp->hsize, 0); /* seek to end of header */
  95. break;
  96. }
  97. if(mp->magic == 0)
  98. werrstr("unknown header type");
  99. return ret;
  100. }
  101. /*
  102. * Convert header to canonical form
  103. */
  104. static void
  105. hswal(void *v, int n, uint32_t (*swap)(uint32_t))
  106. {
  107. uint32_t *ulp;
  108. for(ulp = v; n--; ulp++)
  109. *ulp = (*swap)(*ulp);
  110. }
  111. /*
  112. * ELF64 binaries.
  113. */
  114. static int
  115. elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
  116. {
  117. uint16_t (*swab)(uint16_t);
  118. uint32_t (*swal)(uint32_t);
  119. uint64_t (*swav)(uint64_t);
  120. E64hdr *ep = &hp->e.E64hdr;
  121. if(ep->ident[DATA] == ELFDATA2LSB) {
  122. swab = leswab;
  123. swal = leswal;
  124. swav = leswav;
  125. } else if(ep->ident[DATA] == ELFDATA2MSB) {
  126. swab = beswab;
  127. swal = beswal;
  128. swav = beswav;
  129. } else {
  130. werrstr("bad ELF64 encoding - not big or little endian");
  131. return 0;
  132. }
  133. fp->bigendian = ep->ident[DATA] == ELFDATA2MSB;
  134. ep->type = swab(ep->type);
  135. ep->machine = swab(ep->machine);
  136. ep->version = swal(ep->version);
  137. if(ep->type != EXEC || ep->version != CURRENT)
  138. return 0;
  139. ep->elfentry = swav(ep->elfentry);
  140. ep->phoff = swav(ep->phoff);
  141. ep->shoff = swav(ep->shoff);
  142. ep->flags = swal(ep->flags);
  143. ep->ehsize = swab(ep->ehsize);
  144. ep->phentsize = swab(ep->phentsize);
  145. ep->phnum = swab(ep->phnum);
  146. ep->shentsize = swab(ep->shentsize);
  147. ep->shnum = swab(ep->shnum);
  148. ep->shstrndx = swab(ep->shstrndx);
  149. fp->magic = ELF_MAG;
  150. fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
  151. switch(ep->machine) {
  152. default:
  153. return 0;
  154. case AMD64:
  155. mach = &mamd64;
  156. fp->type = FAMD64;
  157. fp->name = "amd64 ELF64 executable";
  158. break;
  159. }
  160. // Program headers
  161. if(ep->phentsize != sizeof(P64hdr)) {
  162. werrstr("bad ELF64 program header size");
  163. return 0;
  164. }
  165. int phsz = sizeof(P64hdr)*ep->phnum;
  166. P64hdr *ph = malloc(phsz);
  167. if(!ph)
  168. return 0;
  169. seek(fd, ep->phoff, 0);
  170. if(read(fd, ph, phsz) < 0) {
  171. free(ph);
  172. return 0;
  173. }
  174. for(int i = 0; i < ep->phnum; i++) {
  175. ph[i].type = swal(ph[i].type);
  176. ph[i].flags = swal(ph[i].flags);
  177. ph[i].offset = swav(ph[i].offset);
  178. ph[i].vaddr = swav(ph[i].vaddr);
  179. ph[i].paddr = swav(ph[i].paddr);
  180. ph[i].filesz = swav(ph[i].filesz);
  181. ph[i].memsz = swav(ph[i].memsz);
  182. ph[i].align = swav(ph[i].align);
  183. }
  184. /* find text, data and symbols and install them */
  185. int it = -1, id = -1;
  186. for(int i = 0; i < ep->phnum; i++) {
  187. if(ph[i].type == LOAD && (ph[i].flags & (R|X)) == (R|X) && it == -1)
  188. it = i;
  189. else if(ph[i].type == LOAD && (ph[i].flags & (R|W)) == (R|W) && id == -1)
  190. id = i;
  191. //else if(ph[i].type == NOPTYPE && is == -1)
  192. // is = i;
  193. }
  194. if(it == -1 || id == -1) {
  195. werrstr("No ELF64 TEXT or DATA sections");
  196. free(ph);
  197. return 0;
  198. }
  199. settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
  200. uint64_t uvl = ph[id].memsz - ph[id].filesz;
  201. setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl);
  202. free(ph);
  203. // Section headers - get the symbol table offset from here
  204. if (ep->shentsize != sizeof(S64hdr)) {
  205. werrstr("bad ELF64 section header size");
  206. return 0;
  207. }
  208. int shsz = sizeof(S64hdr)*ep->shnum;
  209. S64hdr *sh = malloc(shsz);
  210. if (!sh) {
  211. return 0;
  212. }
  213. seek(fd, ep->shoff, 0);
  214. if (read(fd, sh, shsz) < 0) {
  215. free(sh);
  216. return 0;
  217. }
  218. for (int i = 0; i < ep->shnum; i++) {
  219. sh[i].name = swal(sh[i].name);
  220. sh[i].type = swal(sh[i].type);
  221. sh[i].flags = swav(sh[i].flags);
  222. sh[i].addr = swav(sh[i].addr);
  223. sh[i].offset = swav(sh[i].offset);
  224. sh[i].size = swav(sh[i].size);
  225. sh[i].link = swal(sh[i].link);
  226. sh[i].info = swal(sh[i].info);
  227. sh[i].addralign = swav(sh[i].addralign);
  228. sh[i].entsize = swav(sh[i].entsize);
  229. }
  230. int isym = -1, istr = -1, ibss = -1;
  231. for (int i = 0; i < ep->shnum; i++) {
  232. if (sh[i].type == SHT_SYMTAB && isym == -1) {
  233. // Assume the first is the one we want for now
  234. // There may be more than one if it's dynamic, but we
  235. // don't support than, so hopefully this is ok for now
  236. isym = i;
  237. } else if (sh[i].type == SHT_STRTAB && istr == -1) {
  238. // Assume first is the one we want for now, but we
  239. // should probably check that the name is '.strtab' to
  240. // distinguish from .shstrtab.
  241. istr = i;
  242. } else if (sh[i].type == SHT_NOBITS && ibss == -1) {
  243. ibss = i;
  244. }
  245. }
  246. if (isym != -1) {
  247. //print("isym: %d\n", isym);
  248. setsym(fp, sh[isym].size, 0, sh[isym].size, sh[isym].offset);
  249. }
  250. if (istr != -1) {
  251. //print("istr: %d\n", istr);
  252. setstr(fp, sh[istr].offset, sh[istr].size);
  253. }
  254. if (ibss != -1) {
  255. //print("ibss: %d\n", ibss);
  256. setbssidx(fp, ibss);
  257. }
  258. free(sh);
  259. return 1;
  260. }
  261. /*
  262. * Elf binaries.
  263. */
  264. static int
  265. elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
  266. {
  267. /* bitswap the header according to the DATA format */
  268. E64hdr *ep = &hp->e.E64hdr;
  269. if(ep->ident[CLASS] == ELFCLASS64)
  270. return elf64dotout(fd, fp, hp);
  271. werrstr("bad ELF class - not 64-bit");
  272. return 0;
  273. }
  274. static void
  275. settext(Fhdr *fp, uint64_t e, uint64_t a, int32_t s, int64_t off)
  276. {
  277. fp->txtaddr = a;
  278. fp->entry = e;
  279. fp->txtsz = s;
  280. fp->txtoff = off;
  281. }
  282. static void
  283. setdata(Fhdr *fp, uint64_t a, int32_t s, int64_t off, int32_t bss)
  284. {
  285. fp->dataddr = a;
  286. fp->datsz = s;
  287. fp->datoff = off;
  288. fp->bsssz = bss;
  289. }
  290. static void
  291. setsym(Fhdr *fp, int32_t symsz, int32_t sppcsz, int32_t lnpcsz, int64_t symoff)
  292. {
  293. fp->symsz = symsz;
  294. fp->symoff = symoff;
  295. fp->sppcsz = sppcsz;
  296. fp->sppcoff = fp->symoff+fp->symsz;
  297. fp->lnpcsz = lnpcsz;
  298. fp->lnpcoff = fp->sppcoff+fp->sppcsz;
  299. }
  300. static void
  301. setstr(Fhdr *fp, int64_t stroff, uint64_t strsz)
  302. {
  303. fp->stroff = stroff;
  304. fp->strsz = strsz;
  305. }
  306. static void
  307. setbssidx(Fhdr *fp, uint16_t bssidx)
  308. {
  309. fp->bssidx = bssidx;
  310. }