diff options
Diffstat (limited to 'src/host/buildvm_peobj.c')
-rw-r--r-- | src/host/buildvm_peobj.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c index 17b3293a..28b771a3 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_X86ORX64 || LJ_TARGET_PPC |
13 | 13 | ||
14 | /* Context for PE object emitter. */ | 14 | /* Context for PE object emitter. */ |
15 | static char *strtab; | 15 | static char *strtab; |
@@ -84,11 +84,21 @@ typedef struct PEsymaux { | |||
84 | #define PEOBJ_ARCH_TARGET 0x014c | 84 | #define PEOBJ_ARCH_TARGET 0x014c |
85 | #define PEOBJ_RELOC_REL32 0x14 /* MS: REL32, GNU: DISP32. */ | 85 | #define PEOBJ_RELOC_REL32 0x14 /* MS: REL32, GNU: DISP32. */ |
86 | #define PEOBJ_RELOC_DIR32 0x06 | 86 | #define PEOBJ_RELOC_DIR32 0x06 |
87 | #define PEOBJ_RELOC_OFS 0 | ||
88 | #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ | ||
87 | #elif LJ_TARGET_X64 | 89 | #elif LJ_TARGET_X64 |
88 | #define PEOBJ_ARCH_TARGET 0x8664 | 90 | #define PEOBJ_ARCH_TARGET 0x8664 |
89 | #define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ | 91 | #define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ |
90 | #define PEOBJ_RELOC_DIR32 0x02 | 92 | #define PEOBJ_RELOC_DIR32 0x02 |
91 | #define PEOBJ_RELOC_ADDR32NB 0x03 | 93 | #define PEOBJ_RELOC_ADDR32NB 0x03 |
94 | #define PEOBJ_RELOC_OFS 0 | ||
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. */ | ||
92 | #endif | 102 | #endif |
93 | 103 | ||
94 | /* Section numbers (0-based). */ | 104 | /* Section numbers (0-based). */ |
@@ -170,12 +180,6 @@ void emit_peobj(BuildCtx *ctx) | |||
170 | int i, nrsym; | 180 | int i, nrsym; |
171 | union { uint8_t b; uint32_t u; } host_endian; | 181 | union { uint8_t b; uint32_t u; } host_endian; |
172 | 182 | ||
173 | host_endian.u = 1; | ||
174 | if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { | ||
175 | fprintf(stderr, "Error: different byte order for host and target\n"); | ||
176 | exit(1); | ||
177 | } | ||
178 | |||
179 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); | 183 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); |
180 | 184 | ||
181 | /* Fill in PE sections. */ | 185 | /* Fill in PE sections. */ |
@@ -186,7 +190,7 @@ void emit_peobj(BuildCtx *ctx) | |||
186 | pesect[PEOBJ_SECT_TEXT].relocofs = sofs; | 190 | pesect[PEOBJ_SECT_TEXT].relocofs = sofs; |
187 | sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE; | 191 | sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE; |
188 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ | 192 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ |
189 | pesect[PEOBJ_SECT_TEXT].flags = 0x60500020; | 193 | pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS; |
190 | 194 | ||
191 | #if LJ_TARGET_X64 | 195 | #if LJ_TARGET_X64 |
192 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); | 196 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); |
@@ -236,10 +240,22 @@ void emit_peobj(BuildCtx *ctx) | |||
236 | owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS); | 240 | owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS); |
237 | 241 | ||
238 | /* Write .text section. */ | 242 | /* Write .text section. */ |
243 | host_endian.u = 1; | ||
244 | 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"); | ||
252 | exit(1); | ||
253 | #endif | ||
254 | } | ||
239 | owrite(ctx, ctx->code, ctx->codesz); | 255 | owrite(ctx, ctx->code, ctx->codesz); |
240 | for (i = 0; i < ctx->nreloc; i++) { | 256 | for (i = 0; i < ctx->nreloc; i++) { |
241 | PEreloc reloc; | 257 | PEreloc reloc; |
242 | reloc.vaddr = (uint32_t)ctx->reloc[i].ofs; | 258 | reloc.vaddr = (uint32_t)ctx->reloc[i].ofs + PEOBJ_RELOC_OFS; |
243 | reloc.symidx = 1+2+ctx->reloc[i].sym; /* Reloc syms are after .text sym. */ | 259 | reloc.symidx = 1+2+ctx->reloc[i].sym; /* Reloc syms are after .text sym. */ |
244 | reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32; | 260 | reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32; |
245 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 261 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |