diff options
Diffstat (limited to 'src/host/buildvm_peobj.c')
-rw-r--r-- | src/host/buildvm_peobj.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c index 876b0add..01f9dac4 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 || LJ_TARGET_PPC | 12 | #if LJ_TARGET_X86ORX64 |
13 | 13 | ||
14 | /* Context for PE object emitter. */ | 14 | /* Context for PE object emitter. */ |
15 | static char *strtab; | 15 | static char *strtab; |
@@ -93,12 +93,6 @@ 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 | #elif LJ_TARGET_PPC | ||
97 | #define PEOBJ_ARCH_TARGET 0x01f2 | ||
98 | #define PEOBJ_RELOC_REL32 0x06 | ||
99 | #define PEOBJ_RELOC_DIR32 0x02 | ||
100 | #define PEOBJ_RELOC_OFS (-4) | ||
101 | #define PEOBJ_TEXT_FLAGS 0x60400020 /* 60=r+x, 40=align8, 20=code. */ | ||
102 | #endif | 96 | #endif |
103 | 97 | ||
104 | /* Section numbers (0-based). */ | 98 | /* Section numbers (0-based). */ |
@@ -109,6 +103,8 @@ enum { | |||
109 | #if LJ_TARGET_X64 | 103 | #if LJ_TARGET_X64 |
110 | PEOBJ_SECT_PDATA, | 104 | PEOBJ_SECT_PDATA, |
111 | PEOBJ_SECT_XDATA, | 105 | PEOBJ_SECT_XDATA, |
106 | #elif LJ_TARGET_X86 | ||
107 | PEOBJ_SECT_SXDATA, | ||
112 | #endif | 108 | #endif |
113 | PEOBJ_SECT_RDATA_Z, | 109 | PEOBJ_SECT_RDATA_Z, |
114 | PEOBJ_NSECTIONS | 110 | PEOBJ_NSECTIONS |
@@ -208,6 +204,13 @@ void emit_peobj(BuildCtx *ctx) | |||
208 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; | 204 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; |
209 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 205 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
210 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; | 206 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; |
207 | #elif LJ_TARGET_X86 | ||
208 | memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1); | ||
209 | pesect[PEOBJ_SECT_SXDATA].ofs = sofs; | ||
210 | sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4); | ||
211 | pesect[PEOBJ_SECT_SXDATA].relocofs = sofs; | ||
212 | /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */ | ||
213 | pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240; | ||
211 | #endif | 214 | #endif |
212 | 215 | ||
213 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); | 216 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); |
@@ -232,7 +235,7 @@ void emit_peobj(BuildCtx *ctx) | |||
232 | nrsym = ctx->nrelocsym; | 235 | nrsym = ctx->nrelocsym; |
233 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; | 236 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; |
234 | #if LJ_TARGET_X64 | 237 | #if LJ_TARGET_X64 |
235 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ | 238 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */ |
236 | #endif | 239 | #endif |
237 | 240 | ||
238 | /* Write PE object header and all sections. */ | 241 | /* Write PE object header and all sections. */ |
@@ -242,15 +245,8 @@ void emit_peobj(BuildCtx *ctx) | |||
242 | /* Write .text section. */ | 245 | /* Write .text section. */ |
243 | host_endian.u = 1; | 246 | host_endian.u = 1; |
244 | if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { | 247 | if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { |
245 | #if LJ_TARGET_PPC | ||
246 | uint32_t *p = (uint32_t *)ctx->code; | ||
247 | int n = (int)(ctx->codesz >> 2); | ||
248 | for (i = 0; i < n; i++, p++) | ||
249 | *p = lj_bswap(*p); /* Byteswap .text section. */ | ||
250 | #else | ||
251 | fprintf(stderr, "Error: different byte order for host and target\n"); | 248 | fprintf(stderr, "Error: different byte order for host and target\n"); |
252 | exit(1); | 249 | exit(1); |
253 | #endif | ||
254 | } | 250 | } |
255 | owrite(ctx, ctx->code, ctx->codesz); | 251 | owrite(ctx, ctx->code, ctx->codesz); |
256 | for (i = 0; i < ctx->nreloc; i++) { | 252 | for (i = 0; i < ctx->nreloc; i++) { |
@@ -312,6 +308,19 @@ void emit_peobj(BuildCtx *ctx) | |||
312 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 308 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
313 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 309 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
314 | } | 310 | } |
311 | #elif LJ_TARGET_X86 | ||
312 | /* Write .sxdata section. */ | ||
313 | for (i = 0; i < nrsym; i++) { | ||
314 | if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) { | ||
315 | uint32_t symidx = 1+2+i; | ||
316 | owrite(ctx, &symidx, 4); | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | if (i == nrsym) { | ||
321 | fprintf(stderr, "Error: extern lj_err_unwind_win not used\n"); | ||
322 | exit(1); | ||
323 | } | ||
315 | #endif | 324 | #endif |
316 | 325 | ||
317 | /* Write .rdata$Z section. */ | 326 | /* Write .rdata$Z section. */ |
@@ -333,8 +342,10 @@ void emit_peobj(BuildCtx *ctx) | |||
333 | #if LJ_TARGET_X64 | 342 | #if LJ_TARGET_X64 |
334 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); | 343 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); |
335 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); | 344 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); |
336 | emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, | 345 | emit_peobj_sym(ctx, "lj_err_unwind_win", 0, |
337 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 346 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
347 | #elif LJ_TARGET_X86 | ||
348 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA); | ||
338 | #endif | 349 | #endif |
339 | 350 | ||
340 | emit_peobj_sym(ctx, ctx->beginsym, 0, | 351 | emit_peobj_sym(ctx, ctx->beginsym, 0, |