diff options
author | Mike Pall <mike> | 2023-09-10 05:20:22 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2023-09-10 05:20:22 +0200 |
commit | cb413bf8f4814fe3e47c8c619602c7a161469faf (patch) | |
tree | de88d398f115fca8d258e818e226a75ba0326336 /src/host | |
parent | 566532b8071c82125a65ad1bea0d5784991fa7a2 (diff) | |
download | luajit-cb413bf8f4814fe3e47c8c619602c7a161469faf.tar.gz luajit-cb413bf8f4814fe3e47c8c619602c7a161469faf.tar.bz2 luajit-cb413bf8f4814fe3e47c8c619602c7a161469faf.zip |
Windows/ARM64: Add initial support.
Only builds with native ARM64 Visual Studio for now.
Thanks to vanc and Stephen Just. #593 #964
Diffstat (limited to 'src/host')
-rw-r--r-- | src/host/buildvm_peobj.c | 113 |
1 files changed, 104 insertions, 9 deletions
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c index 5bca6df8..e3e1026e 100644 --- a/src/host/buildvm_peobj.c +++ b/src/host/buildvm_peobj.c | |||
@@ -9,7 +9,7 @@ | |||
9 | #include "buildvm.h" | 9 | #include "buildvm.h" |
10 | #include "lj_bc.h" | 10 | #include "lj_bc.h" |
11 | 11 | ||
12 | #if LJ_TARGET_X86ORX64 | 12 | #if LJ_TARGET_WINDOWS |
13 | 13 | ||
14 | /* Context for PE object emitter. */ | 14 | /* Context for PE object emitter. */ |
15 | static char *strtab; | 15 | static char *strtab; |
@@ -93,6 +93,17 @@ typedef struct PEsymaux { | |||
93 | #define PEOBJ_RELOC_ADDR32NB 0x03 | 93 | #define PEOBJ_RELOC_ADDR32NB 0x03 |
94 | #define PEOBJ_RELOC_OFS 0 | 94 | #define PEOBJ_RELOC_OFS 0 |
95 | #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ | 95 | #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ |
96 | #define PEOBJ_PDATA_NRELOC 6 | ||
97 | #define PEOBJ_XDATA_SIZE (8*2+4+6*2) | ||
98 | #elif LJ_TARGET_ARM64 | ||
99 | #define PEOBJ_ARCH_TARGET 0xaa64 | ||
100 | #define PEOBJ_RELOC_REL32 0x03 /* MS: BRANCH26. */ | ||
101 | #define PEOBJ_RELOC_DIR32 0x01 | ||
102 | #define PEOBJ_RELOC_ADDR32NB 0x02 | ||
103 | #define PEOBJ_RELOC_OFS (-4) | ||
104 | #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ | ||
105 | #define PEOBJ_PDATA_NRELOC 4 | ||
106 | #define PEOBJ_XDATA_SIZE (4+24+4 +4+8) | ||
96 | #endif | 107 | #endif |
97 | 108 | ||
98 | /* Section numbers (0-based). */ | 109 | /* Section numbers (0-based). */ |
@@ -100,7 +111,7 @@ enum { | |||
100 | PEOBJ_SECT_ABS = -2, | 111 | PEOBJ_SECT_ABS = -2, |
101 | PEOBJ_SECT_UNDEF = -1, | 112 | PEOBJ_SECT_UNDEF = -1, |
102 | PEOBJ_SECT_TEXT, | 113 | PEOBJ_SECT_TEXT, |
103 | #if LJ_TARGET_X64 | 114 | #ifdef PEOBJ_PDATA_NRELOC |
104 | PEOBJ_SECT_PDATA, | 115 | PEOBJ_SECT_PDATA, |
105 | PEOBJ_SECT_XDATA, | 116 | PEOBJ_SECT_XDATA, |
106 | #elif LJ_TARGET_X86 | 117 | #elif LJ_TARGET_X86 |
@@ -175,6 +186,9 @@ void emit_peobj(BuildCtx *ctx) | |||
175 | uint32_t sofs; | 186 | uint32_t sofs; |
176 | int i, nrsym; | 187 | int i, nrsym; |
177 | union { uint8_t b; uint32_t u; } host_endian; | 188 | union { uint8_t b; uint32_t u; } host_endian; |
189 | #ifdef PEOBJ_PDATA_NRELOC | ||
190 | uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; | ||
191 | #endif | ||
178 | 192 | ||
179 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); | 193 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); |
180 | 194 | ||
@@ -188,18 +202,18 @@ void emit_peobj(BuildCtx *ctx) | |||
188 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ | 202 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ |
189 | pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS; | 203 | pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS; |
190 | 204 | ||
191 | #if LJ_TARGET_X64 | 205 | #ifdef PEOBJ_PDATA_NRELOC |
192 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); | 206 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); |
193 | pesect[PEOBJ_SECT_PDATA].ofs = sofs; | 207 | pesect[PEOBJ_SECT_PDATA].ofs = sofs; |
194 | sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4); | 208 | sofs += (pesect[PEOBJ_SECT_PDATA].size = PEOBJ_PDATA_NRELOC*4); |
195 | pesect[PEOBJ_SECT_PDATA].relocofs = sofs; | 209 | pesect[PEOBJ_SECT_PDATA].relocofs = sofs; |
196 | sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE; | 210 | sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = PEOBJ_PDATA_NRELOC) * PEOBJ_RELOC_SIZE; |
197 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 211 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
198 | pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; | 212 | pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; |
199 | 213 | ||
200 | memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); | 214 | memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); |
201 | pesect[PEOBJ_SECT_XDATA].ofs = sofs; | 215 | pesect[PEOBJ_SECT_XDATA].ofs = sofs; |
202 | sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2); /* See below. */ | 216 | sofs += (pesect[PEOBJ_SECT_XDATA].size = PEOBJ_XDATA_SIZE); /* See below. */ |
203 | pesect[PEOBJ_SECT_XDATA].relocofs = sofs; | 217 | pesect[PEOBJ_SECT_XDATA].relocofs = sofs; |
204 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; | 218 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; |
205 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 219 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
@@ -234,7 +248,7 @@ void emit_peobj(BuildCtx *ctx) | |||
234 | */ | 248 | */ |
235 | nrsym = ctx->nrelocsym; | 249 | nrsym = ctx->nrelocsym; |
236 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; | 250 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; |
237 | #if LJ_TARGET_X64 | 251 | #ifdef PEOBJ_PDATA_NRELOC |
238 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */ | 252 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */ |
239 | #endif | 253 | #endif |
240 | 254 | ||
@@ -259,7 +273,6 @@ void emit_peobj(BuildCtx *ctx) | |||
259 | 273 | ||
260 | #if LJ_TARGET_X64 | 274 | #if LJ_TARGET_X64 |
261 | { /* Write .pdata section. */ | 275 | { /* Write .pdata section. */ |
262 | uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; | ||
263 | uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ | 276 | uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ |
264 | PEreloc reloc; | 277 | PEreloc reloc; |
265 | pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; | 278 | pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; |
@@ -308,6 +321,88 @@ void emit_peobj(BuildCtx *ctx) | |||
308 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 321 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
309 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 322 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
310 | } | 323 | } |
324 | #elif LJ_TARGET_ARM64 | ||
325 | /* https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling */ | ||
326 | { /* Write .pdata section. */ | ||
327 | uint32_t pdata[4]; | ||
328 | PEreloc reloc; | ||
329 | pdata[0] = 0; | ||
330 | pdata[1] = 0; | ||
331 | pdata[2] = fcofs; | ||
332 | pdata[3] = 4+24+4; | ||
333 | owrite(ctx, &pdata, sizeof(pdata)); | ||
334 | /* Start of .text and start of .xdata. */ | ||
335 | reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1; | ||
336 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
337 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
338 | reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2; | ||
339 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
340 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
341 | /* Start of vm_ffi_call and start of second part of .xdata. */ | ||
342 | reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2+2+1; | ||
343 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
344 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
345 | reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2; | ||
346 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
347 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
348 | } | ||
349 | { /* Write .xdata section. */ | ||
350 | uint32_t u32; | ||
351 | uint8_t *p, uwc[24]; | ||
352 | PEreloc reloc; | ||
353 | |||
354 | #define CBE16(x) (*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2) | ||
355 | #define CALLOC_S(s) (*p++ = ((s) >> 4)) /* s < 512 */ | ||
356 | #define CSAVE_FPLR(o) (*p++ = 0x40 | ((o) >> 3)) /* o <= 504 */ | ||
357 | #define CSAVE_REGP(r,o) CBE16(0xc800 | (((r)-19)<< 6) | ((o) >> 3)) | ||
358 | #define CSAVE_REGS(r1,r2,o1) do { \ | ||
359 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \ | ||
360 | } while (0) | ||
361 | #define CSAVE_FREGP(r,o) CBE16(0xd800 | (((r) - 8) << 6) | ((o) >> 3)) | ||
362 | #define CSAVE_FREGS(r1,r2,o1) do { \ | ||
363 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \ | ||
364 | } while (0) | ||
365 | #define CSAVE_REGX(r,o) CBE16(0xd400 | (((r) - 19) << 5) | (~(o) >> 3)) | ||
366 | #define CADD_FP(s) CBE16(0xe200 | ((s) >> 3)) /* s < 8*256 */ | ||
367 | #define CODE_NOP 0xe3 | ||
368 | #define CODE_END 0xe4 | ||
369 | #define CEND_ALIGN do { \ | ||
370 | *p++ = CODE_END; \ | ||
371 | while ((p - uwc) & 3) *p++ = CODE_NOP; \ | ||
372 | } while (0) | ||
373 | |||
374 | /* Unwind codes for .text section with handler. */ | ||
375 | p = uwc; | ||
376 | CALLOC_S(208); /* +1 */ | ||
377 | CSAVE_FPLR(192); /* +1 */ | ||
378 | CADD_FP(192); /* +2 */ | ||
379 | CSAVE_REGS(19, 28, 184); /* +5*2 */ | ||
380 | CSAVE_FREGS(8, 15, 104); /* +4*2 */ | ||
381 | CEND_ALIGN; /* +1 +1 -> 24 */ | ||
382 | |||
383 | u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2); | ||
384 | owrite(ctx, &u32, 4); | ||
385 | owrite(ctx, &uwc, 24); | ||
386 | |||
387 | u32 = 0; /* Handler RVA to be relocated at 4 + 24. */ | ||
388 | owrite(ctx, &u32, 4); | ||
389 | |||
390 | /* Unwind codes for vm_ffi_call without handler. */ | ||
391 | p = uwc; | ||
392 | CSAVE_FPLR(16); /* +1 */ | ||
393 | CADD_FP(16); /* +2 */ | ||
394 | CSAVE_REGX(19, -24); /* +2 */ | ||
395 | CSAVE_REGX(20, -32); /* +2 */ | ||
396 | CEND_ALIGN; /* +1 +0 -> 8 */ | ||
397 | |||
398 | u32 = ((8u >> 2) << 27) | (((uint32_t)ctx->codesz - fcofs) >> 2); | ||
399 | owrite(ctx, &u32, 4); | ||
400 | owrite(ctx, &uwc, 8); | ||
401 | |||
402 | reloc.vaddr = 4 + 24; reloc.symidx = 1+2+nrsym+2+2; | ||
403 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
404 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
405 | } | ||
311 | #elif LJ_TARGET_X86 | 406 | #elif LJ_TARGET_X86 |
312 | /* Write .sxdata section. */ | 407 | /* Write .sxdata section. */ |
313 | for (i = 0; i < nrsym; i++) { | 408 | for (i = 0; i < nrsym; i++) { |
@@ -339,7 +434,7 @@ void emit_peobj(BuildCtx *ctx) | |||
339 | emit_peobj_sym(ctx, ctx->relocsym[i], 0, | 434 | emit_peobj_sym(ctx, ctx->relocsym[i], 0, |
340 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 435 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
341 | 436 | ||
342 | #if LJ_TARGET_X64 | 437 | #ifdef PEOBJ_PDATA_NRELOC |
343 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); | 438 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); |
344 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); | 439 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); |
345 | emit_peobj_sym(ctx, "lj_err_unwind_win", 0, | 440 | emit_peobj_sym(ctx, "lj_err_unwind_win", 0, |