buildvm_peobj.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. ** LuaJIT VM builder: PE object emitter.
  3. ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
  4. **
  5. ** Only used for building on Windows, since we cannot assume the presence
  6. ** of a suitable assembler. The host and target byte order must match.
  7. */
  8. #include "buildvm.h"
  9. #include "lj_bc.h"
  10. #if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
  11. /* Context for PE object emitter. */
  12. static char *strtab;
  13. static size_t strtabofs;
  14. /* -- PE object definitions ----------------------------------------------- */
  15. /* PE header. */
  16. typedef struct PEheader {
  17. uint16_t arch;
  18. uint16_t nsects;
  19. uint32_t time;
  20. uint32_t symtabofs;
  21. uint32_t nsyms;
  22. uint16_t opthdrsz;
  23. uint16_t flags;
  24. } PEheader;
  25. /* PE section. */
  26. typedef struct PEsection {
  27. char name[8];
  28. uint32_t vsize;
  29. uint32_t vaddr;
  30. uint32_t size;
  31. uint32_t ofs;
  32. uint32_t relocofs;
  33. uint32_t lineofs;
  34. uint16_t nreloc;
  35. uint16_t nline;
  36. uint32_t flags;
  37. } PEsection;
  38. /* PE relocation. */
  39. typedef struct PEreloc {
  40. uint32_t vaddr;
  41. uint32_t symidx;
  42. uint16_t type;
  43. } PEreloc;
  44. /* Cannot use sizeof, because it pads up to the max. alignment. */
  45. #define PEOBJ_RELOC_SIZE (4+4+2)
  46. /* PE symbol table entry. */
  47. typedef struct PEsym {
  48. union {
  49. char name[8];
  50. uint32_t nameref[2];
  51. } n;
  52. uint32_t value;
  53. int16_t sect;
  54. uint16_t type;
  55. uint8_t scl;
  56. uint8_t naux;
  57. } PEsym;
  58. /* PE symbol table auxiliary entry for a section. */
  59. typedef struct PEsymaux {
  60. uint32_t size;
  61. uint16_t nreloc;
  62. uint16_t nline;
  63. uint32_t cksum;
  64. uint16_t assoc;
  65. uint8_t comdatsel;
  66. uint8_t unused[3];
  67. } PEsymaux;
  68. /* Cannot use sizeof, because it pads up to the max. alignment. */
  69. #define PEOBJ_SYM_SIZE (8+4+2+2+1+1)
  70. /* PE object CPU specific defines. */
  71. #if LJ_TARGET_X86
  72. #define PEOBJ_ARCH_TARGET 0x014c
  73. #define PEOBJ_RELOC_REL32 0x14 /* MS: REL32, GNU: DISP32. */
  74. #define PEOBJ_RELOC_DIR32 0x06
  75. #define PEOBJ_RELOC_OFS 0
  76. #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */
  77. #elif LJ_TARGET_X64
  78. #define PEOBJ_ARCH_TARGET 0x8664
  79. #define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */
  80. #define PEOBJ_RELOC_DIR32 0x02
  81. #define PEOBJ_RELOC_ADDR32NB 0x03
  82. #define PEOBJ_RELOC_OFS 0
  83. #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */
  84. #elif LJ_TARGET_PPC
  85. #define PEOBJ_ARCH_TARGET 0x01f2
  86. #define PEOBJ_RELOC_REL32 0x06
  87. #define PEOBJ_RELOC_DIR32 0x02
  88. #define PEOBJ_RELOC_OFS (-4)
  89. #define PEOBJ_TEXT_FLAGS 0x60400020 /* 60=r+x, 40=align8, 20=code. */
  90. #endif
  91. /* Section numbers (0-based). */
  92. enum {
  93. PEOBJ_SECT_ABS = -2,
  94. PEOBJ_SECT_UNDEF = -1,
  95. PEOBJ_SECT_TEXT,
  96. #if LJ_TARGET_X64
  97. PEOBJ_SECT_PDATA,
  98. PEOBJ_SECT_XDATA,
  99. #endif
  100. PEOBJ_SECT_RDATA_Z,
  101. PEOBJ_NSECTIONS
  102. };
  103. /* Symbol types. */
  104. #define PEOBJ_TYPE_NULL 0
  105. #define PEOBJ_TYPE_FUNC 0x20
  106. /* Symbol storage class. */
  107. #define PEOBJ_SCL_EXTERN 2
  108. #define PEOBJ_SCL_STATIC 3
  109. /* -- PE object emitter --------------------------------------------------- */
  110. /* Emit PE object symbol. */
  111. static void emit_peobj_sym(BuildCtx *ctx, const char *name, uint32_t value,
  112. int sect, int type, int scl)
  113. {
  114. PEsym sym;
  115. size_t len = strlen(name);
  116. if (!strtab) { /* Pass 1: only calculate string table length. */
  117. if (len > 8) strtabofs += len+1;
  118. return;
  119. }
  120. if (len <= 8) {
  121. memcpy(sym.n.name, name, len);
  122. memset(sym.n.name+len, 0, 8-len);
  123. } else {
  124. sym.n.nameref[0] = 0;
  125. sym.n.nameref[1] = (uint32_t)strtabofs;
  126. memcpy(strtab + strtabofs, name, len);
  127. strtab[strtabofs+len] = 0;
  128. strtabofs += len+1;
  129. }
  130. sym.value = value;
  131. sym.sect = (int16_t)(sect+1); /* 1-based section number. */
  132. sym.type = (uint16_t)type;
  133. sym.scl = (uint8_t)scl;
  134. sym.naux = 0;
  135. owrite(ctx, &sym, PEOBJ_SYM_SIZE);
  136. }
  137. /* Emit PE object section symbol. */
  138. static void emit_peobj_sym_sect(BuildCtx *ctx, PEsection *pesect, int sect)
  139. {
  140. PEsym sym;
  141. PEsymaux aux;
  142. if (!strtab) return; /* Pass 1: no output. */
  143. memcpy(sym.n.name, pesect[sect].name, 8);
  144. sym.value = 0;
  145. sym.sect = (int16_t)(sect+1); /* 1-based section number. */
  146. sym.type = PEOBJ_TYPE_NULL;
  147. sym.scl = PEOBJ_SCL_STATIC;
  148. sym.naux = 1;
  149. owrite(ctx, &sym, PEOBJ_SYM_SIZE);
  150. memset(&aux, 0, sizeof(PEsymaux));
  151. aux.size = pesect[sect].size;
  152. aux.nreloc = pesect[sect].nreloc;
  153. owrite(ctx, &aux, PEOBJ_SYM_SIZE);
  154. }
  155. /* Emit Windows PE object file. */
  156. void emit_peobj(BuildCtx *ctx)
  157. {
  158. PEheader pehdr;
  159. PEsection pesect[PEOBJ_NSECTIONS];
  160. uint32_t sofs;
  161. int i, nrsym;
  162. union { uint8_t b; uint32_t u; } host_endian;
  163. sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection);
  164. /* Fill in PE sections. */
  165. memset(&pesect, 0, PEOBJ_NSECTIONS*sizeof(PEsection));
  166. memcpy(pesect[PEOBJ_SECT_TEXT].name, ".text", sizeof(".text")-1);
  167. pesect[PEOBJ_SECT_TEXT].ofs = sofs;
  168. sofs += (pesect[PEOBJ_SECT_TEXT].size = (uint32_t)ctx->codesz);
  169. pesect[PEOBJ_SECT_TEXT].relocofs = sofs;
  170. sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE;
  171. /* Flags: 60 = read+execute, 50 = align16, 20 = code. */
  172. pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS;
  173. #if LJ_TARGET_X64
  174. memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
  175. pesect[PEOBJ_SECT_PDATA].ofs = sofs;
  176. sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4);
  177. pesect[PEOBJ_SECT_PDATA].relocofs = sofs;
  178. sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE;
  179. /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  180. pesect[PEOBJ_SECT_PDATA].flags = 0x40300040;
  181. memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1);
  182. pesect[PEOBJ_SECT_XDATA].ofs = sofs;
  183. sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2); /* See below. */
  184. pesect[PEOBJ_SECT_XDATA].relocofs = sofs;
  185. sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
  186. /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  187. pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
  188. #endif
  189. memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
  190. pesect[PEOBJ_SECT_RDATA_Z].ofs = sofs;
  191. sofs += (pesect[PEOBJ_SECT_RDATA_Z].size = (uint32_t)strlen(ctx->dasm_ident)+1);
  192. /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  193. pesect[PEOBJ_SECT_RDATA_Z].flags = 0x40300040;
  194. /* Fill in PE header. */
  195. pehdr.arch = PEOBJ_ARCH_TARGET;
  196. pehdr.nsects = PEOBJ_NSECTIONS;
  197. pehdr.time = 0; /* Timestamp is optional. */
  198. pehdr.symtabofs = sofs;
  199. pehdr.opthdrsz = 0;
  200. pehdr.flags = 0;
  201. /* Compute the size of the symbol table:
  202. ** @feat.00 + nsections*2
  203. ** + asm_start + nsym
  204. ** + nrsym
  205. */
  206. nrsym = ctx->nrelocsym;
  207. pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
  208. #if LJ_TARGET_X64
  209. pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */
  210. #endif
  211. /* Write PE object header and all sections. */
  212. owrite(ctx, &pehdr, sizeof(PEheader));
  213. owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS);
  214. /* Write .text section. */
  215. host_endian.u = 1;
  216. if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
  217. #if LJ_TARGET_PPC
  218. uint32_t *p = (uint32_t *)ctx->code;
  219. int n = (int)(ctx->codesz >> 2);
  220. for (i = 0; i < n; i++, p++)
  221. *p = lj_bswap(*p); /* Byteswap .text section. */
  222. #else
  223. fprintf(stderr, "Error: different byte order for host and target\n");
  224. exit(1);
  225. #endif
  226. }
  227. owrite(ctx, ctx->code, ctx->codesz);
  228. for (i = 0; i < ctx->nreloc; i++) {
  229. PEreloc reloc;
  230. reloc.vaddr = (uint32_t)ctx->reloc[i].ofs + PEOBJ_RELOC_OFS;
  231. reloc.symidx = 1+2+ctx->reloc[i].sym; /* Reloc syms are after .text sym. */
  232. reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32;
  233. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  234. }
  235. #if LJ_TARGET_X64
  236. { /* Write .pdata section. */
  237. uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs;
  238. uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */
  239. PEreloc reloc;
  240. pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0;
  241. owrite(ctx, &pdata, sizeof(pdata));
  242. pdata[0] = fcofs; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 20;
  243. owrite(ctx, &pdata, sizeof(pdata));
  244. reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1;
  245. reloc.type = PEOBJ_RELOC_ADDR32NB;
  246. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  247. reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2+2+1;
  248. reloc.type = PEOBJ_RELOC_ADDR32NB;
  249. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  250. reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2;
  251. reloc.type = PEOBJ_RELOC_ADDR32NB;
  252. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  253. reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2+2+1;
  254. reloc.type = PEOBJ_RELOC_ADDR32NB;
  255. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  256. reloc.vaddr = 16; reloc.symidx = 1+2+nrsym+2+2+1;
  257. reloc.type = PEOBJ_RELOC_ADDR32NB;
  258. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  259. reloc.vaddr = 20; reloc.symidx = 1+2+nrsym+2;
  260. reloc.type = PEOBJ_RELOC_ADDR32NB;
  261. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  262. }
  263. { /* Write .xdata section. */
  264. uint16_t xdata[8+2+6];
  265. PEreloc reloc;
  266. xdata[0] = 0x01|0x08|0x10; /* Ver. 1, uhandler/ehandler, prolog size 0. */
  267. xdata[1] = 0x0005; /* Number of unwind codes, no frame pointer. */
  268. xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */
  269. xdata[3] = 0x3000; /* Push rbx. */
  270. xdata[4] = 0x6000; /* Push rsi. */
  271. xdata[5] = 0x7000; /* Push rdi. */
  272. xdata[6] = 0x5000; /* Push rbp. */
  273. xdata[7] = 0; /* Alignment. */
  274. xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */
  275. xdata[10] = 0x01; /* Ver. 1, no handler, prolog size 0. */
  276. xdata[11] = 0x1504; /* Number of unwind codes, fp = rbp, fpofs = 16. */
  277. xdata[12] = 0x0300; /* set_fpreg. */
  278. xdata[13] = 0x0200; /* stack offset 0*8+8 = aword*1. */
  279. xdata[14] = 0x3000; /* Push rbx. */
  280. xdata[15] = 0x5000; /* Push rbp. */
  281. owrite(ctx, &xdata, sizeof(xdata));
  282. reloc.vaddr = 2*8; reloc.symidx = 1+2+nrsym+2+2;
  283. reloc.type = PEOBJ_RELOC_ADDR32NB;
  284. owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  285. }
  286. #endif
  287. /* Write .rdata$Z section. */
  288. owrite(ctx, ctx->dasm_ident, strlen(ctx->dasm_ident)+1);
  289. /* Write symbol table. */
  290. strtab = NULL; /* 1st pass: collect string sizes. */
  291. for (;;) {
  292. strtabofs = 4;
  293. /* Mark as SafeSEH compliant. */
  294. emit_peobj_sym(ctx, "@feat.00", 1,
  295. PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC);
  296. emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT);
  297. for (i = 0; i < nrsym; i++)
  298. emit_peobj_sym(ctx, ctx->relocsym[i], 0,
  299. PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
  300. #if LJ_TARGET_X64
  301. emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
  302. emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
  303. emit_peobj_sym(ctx, "lj_err_unwind_win64", 0,
  304. PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
  305. #endif
  306. emit_peobj_sym(ctx, ctx->beginsym, 0,
  307. PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
  308. for (i = 0; i < ctx->nsym; i++)
  309. emit_peobj_sym(ctx, ctx->sym[i].name, (uint32_t)ctx->sym[i].ofs,
  310. PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
  311. emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z);
  312. if (strtab)
  313. break;
  314. /* 2nd pass: alloc strtab, write syms and copy strings. */
  315. strtab = (char *)malloc(strtabofs);
  316. *(uint32_t *)strtab = (uint32_t)strtabofs;
  317. }
  318. /* Write string table. */
  319. owrite(ctx, strtab, strtabofs);
  320. }
  321. #else
  322. void emit_peobj(BuildCtx *ctx)
  323. {
  324. UNUSED(ctx);
  325. fprintf(stderr, "Error: no PE object support for this target\n");
  326. exit(1);
  327. }
  328. #endif