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, |
