diff options
Diffstat (limited to 'src/buildvm_peobj.c')
-rw-r--r-- | src/buildvm_peobj.c | 70 |
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++) { |