summaryrefslogtreecommitdiff
path: root/src/buildvm_peobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildvm_peobj.c')
-rw-r--r--src/buildvm_peobj.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/src/buildvm_peobj.c b/src/buildvm_peobj.c
index d45f3c97..68af79c7 100644
--- a/src/buildvm_peobj.c
+++ b/src/buildvm_peobj.c
@@ -90,6 +90,7 @@ typedef struct PEsymaux {
90#define PEOBJ_ARCH_TARGET 0x8664 90#define PEOBJ_ARCH_TARGET 0x8664
91#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ 91#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */
92#define PEOBJ_RELOC_DIR32 0x02 92#define PEOBJ_RELOC_DIR32 0x02
93#define PEOBJ_RELOC_ADDR32NB 0x03
93#define PEOBJ_SYM_PREFIX "" 94#define PEOBJ_SYM_PREFIX ""
94#endif 95#endif
95 96
@@ -98,7 +99,10 @@ enum {
98 PEOBJ_SECT_ABS = -2, 99 PEOBJ_SECT_ABS = -2,
99 PEOBJ_SECT_UNDEF = -1, 100 PEOBJ_SECT_UNDEF = -1,
100 PEOBJ_SECT_TEXT, 101 PEOBJ_SECT_TEXT,
101 /* TODO: add .pdata/.xdata for x64. */ 102#if LJ_TARGET_X64
103 PEOBJ_SECT_PDATA,
104 PEOBJ_SECT_XDATA,
105#endif
102 PEOBJ_SECT_RDATA, 106 PEOBJ_SECT_RDATA,
103 PEOBJ_SECT_RDATA_Z, 107 PEOBJ_SECT_RDATA_Z,
104 PEOBJ_NSECTIONS 108 PEOBJ_NSECTIONS
@@ -196,6 +200,24 @@ void emit_peobj(BuildCtx *ctx)
196 /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ 200 /* Flags: 60 = read+execute, 50 = align16, 20 = code. */
197 pesect[PEOBJ_SECT_TEXT].flags = 0x60500020; 201 pesect[PEOBJ_SECT_TEXT].flags = 0x60500020;
198 202
203#if LJ_TARGET_X64
204 memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
205 pesect[PEOBJ_SECT_PDATA].ofs = sofs;
206 sofs += (pesect[PEOBJ_SECT_PDATA].size = 3*4);
207 pesect[PEOBJ_SECT_PDATA].relocofs = sofs;
208 sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 3) * PEOBJ_RELOC_SIZE;
209 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
210 pesect[PEOBJ_SECT_PDATA].flags = 0x40300040;
211
212 memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1);
213 pesect[PEOBJ_SECT_XDATA].ofs = sofs;
214 sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4); /* See below. */
215 pesect[PEOBJ_SECT_XDATA].relocofs = sofs;
216 sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
217 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
218 pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
219#endif
220
199 memcpy(pesect[PEOBJ_SECT_RDATA].name, ".rdata", sizeof(".rdata")-1); 221 memcpy(pesect[PEOBJ_SECT_RDATA].name, ".rdata", sizeof(".rdata")-1);
200 pesect[PEOBJ_SECT_RDATA].ofs = sofs; 222 pesect[PEOBJ_SECT_RDATA].ofs = sofs;
201 sofs += (pesect[PEOBJ_SECT_RDATA].size = ctx->npc*sizeof(uint16_t)); 223 sofs += (pesect[PEOBJ_SECT_RDATA].size = ctx->npc*sizeof(uint16_t));
@@ -228,6 +250,9 @@ void emit_peobj(BuildCtx *ctx)
228#if !LJ_HASJIT 250#if !LJ_HASJIT
229 pehdr.nsyms -= 7; 251 pehdr.nsyms -= 7;
230#endif 252#endif
253#if LJ_TARGET_X64
254 pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */
255#endif
231 256
232 /* Write PE object header and all sections. */ 257 /* Write PE object header and all sections. */
233 owrite(ctx, &pehdr, sizeof(PEheader)); 258 owrite(ctx, &pehdr, sizeof(PEheader));
@@ -243,6 +268,41 @@ void emit_peobj(BuildCtx *ctx)
243 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); 268 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
244 } 269 }
245 270
271#if LJ_TARGET_X64
272 { /* Write .pdata section. */
273 uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */
274 PEreloc reloc;
275 pdata[0] = 0; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 0;
276 owrite(ctx, &pdata, sizeof(pdata));
277 reloc.vaddr = 0; reloc.symidx = 1+2+relocsyms+2+2+1;
278 reloc.type = PEOBJ_RELOC_ADDR32NB;
279 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
280 reloc.vaddr = 4; reloc.symidx = 1+2+relocsyms+2+2+1;
281 reloc.type = PEOBJ_RELOC_ADDR32NB;
282 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
283 reloc.vaddr = 8; reloc.symidx = 1+2+relocsyms+2;
284 reloc.type = PEOBJ_RELOC_ADDR32NB;
285 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
286 }
287 { /* Write .xdata section. */
288 uint16_t xdata[8+2];
289 PEreloc reloc;
290 xdata[0] = 0x01|0x08|0x10; /* Ver. 1, uhander/ehandler, prolog size 0. */
291 xdata[1] = 5; /* Number of unwind codes, no frame pointer. */
292 xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */
293 xdata[3] = 0x3000; /* Push rbx. */
294 xdata[4] = 0x6000; /* Push rsi. */
295 xdata[5] = 0x7000; /* Push rdi. */
296 xdata[6] = 0x5000; /* Push rbp. */
297 xdata[7] = 0; /* Alignment. */
298 xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */
299 owrite(ctx, &xdata, sizeof(xdata));
300 reloc.vaddr = sizeof(xdata)-4; reloc.symidx = 1+2+relocsyms+2+2;
301 reloc.type = PEOBJ_RELOC_ADDR32NB;
302 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
303 }
304#endif
305
246 /* Write .rdata section. */ 306 /* Write .rdata section. */
247 for (i = 0; i < ctx->npc; i++) { 307 for (i = 0; i < ctx->npc; i++) {
248 uint16_t pcofs = (uint16_t)ctx->sym_ofs[i]; 308 uint16_t pcofs = (uint16_t)ctx->sym_ofs[i];
@@ -279,6 +339,14 @@ void emit_peobj(BuildCtx *ctx)
279 emit_peobj_sym(ctx, name, 0, 339 emit_peobj_sym(ctx, name, 0,
280 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); 340 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
281 } 341 }
342
343#if LJ_TARGET_X64
344 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
345 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
346 emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX "lj_err_unwind_win64", 0,
347 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
348#endif
349
282 emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0, 350 emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0,
283 PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN); 351 PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
284 for (i = nzsym; i < ctx->nsym; i++) { 352 for (i = nzsym; i < ctx->nsym; i++) {