diff options
Diffstat (limited to 'src/buildvm_peobj.c')
-rw-r--r-- | src/buildvm_peobj.c | 86 |
1 files changed, 16 insertions, 70 deletions
diff --git a/src/buildvm_peobj.c b/src/buildvm_peobj.c index 2ff274f9..4cde6e00 100644 --- a/src/buildvm_peobj.c +++ b/src/buildvm_peobj.c | |||
@@ -84,14 +84,11 @@ 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_SYM_PREFIX "_" | ||
88 | #define PEOBJ_SYMF_PREFIX "@" | ||
89 | #elif LJ_TARGET_X64 | 87 | #elif LJ_TARGET_X64 |
90 | #define PEOBJ_ARCH_TARGET 0x8664 | 88 | #define PEOBJ_ARCH_TARGET 0x8664 |
91 | #define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ | 89 | #define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ |
92 | #define PEOBJ_RELOC_DIR32 0x02 | 90 | #define PEOBJ_RELOC_DIR32 0x02 |
93 | #define PEOBJ_RELOC_ADDR32NB 0x03 | 91 | #define PEOBJ_RELOC_ADDR32NB 0x03 |
94 | #define PEOBJ_SYM_PREFIX "" | ||
95 | #endif | 92 | #endif |
96 | 93 | ||
97 | /* Section numbers (0-based). */ | 94 | /* Section numbers (0-based). */ |
@@ -164,18 +161,13 @@ static void emit_peobj_sym_sect(BuildCtx *ctx, PEsection *pesect, int sect) | |||
164 | owrite(ctx, &aux, PEOBJ_SYM_SIZE); | 161 | owrite(ctx, &aux, PEOBJ_SYM_SIZE); |
165 | } | 162 | } |
166 | 163 | ||
167 | #define emit_peobj_sym_func(ctx, name, ofs) \ | ||
168 | emit_peobj_sym(ctx, name, (uint32_t)(ofs), \ | ||
169 | PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN) | ||
170 | |||
171 | /* Emit Windows PE object file. */ | 164 | /* Emit Windows PE object file. */ |
172 | void emit_peobj(BuildCtx *ctx) | 165 | void emit_peobj(BuildCtx *ctx) |
173 | { | 166 | { |
174 | PEheader pehdr; | 167 | PEheader pehdr; |
175 | PEsection pesect[PEOBJ_NSECTIONS]; | 168 | PEsection pesect[PEOBJ_NSECTIONS]; |
176 | int nzsym, relocsyms; | ||
177 | uint32_t sofs; | 169 | uint32_t sofs; |
178 | int i; | 170 | int i, nrsym; |
179 | union { uint8_t b; uint32_t u; } host_endian; | 171 | union { uint8_t b; uint32_t u; } host_endian; |
180 | 172 | ||
181 | host_endian.u = 1; | 173 | host_endian.u = 1; |
@@ -230,16 +222,11 @@ void emit_peobj(BuildCtx *ctx) | |||
230 | 222 | ||
231 | /* Compute the size of the symbol table: | 223 | /* Compute the size of the symbol table: |
232 | ** @feat.00 + nsections*2 | 224 | ** @feat.00 + nsections*2 |
233 | ** + asm_start + (nsyms-nzsym) | 225 | ** + asm_start + nsym |
234 | ** + relocsyms | 226 | ** + nrsym |
235 | */ | 227 | */ |
236 | /* Skip _Z syms. */ | 228 | nrsym = ctx->nrelocsym; |
237 | for (nzsym = 0; ctx->sym_ofs[ctx->perm[nzsym]] < 0; nzsym++) ; | 229 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; |
238 | for (relocsyms = 0; ctx->extnames[relocsyms]; relocsyms++) ; | ||
239 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+(ctx->nsym-nzsym) + relocsyms; | ||
240 | #if !LJ_HASJIT | ||
241 | pehdr.nsyms -= 11; /* See below, removes [IJ]* opcode symbols. */ | ||
242 | #endif | ||
243 | #if LJ_TARGET_X64 | 230 | #if LJ_TARGET_X64 |
244 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ | 231 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ |
245 | #endif | 232 | #endif |
@@ -264,13 +251,13 @@ void emit_peobj(BuildCtx *ctx) | |||
264 | PEreloc reloc; | 251 | PEreloc reloc; |
265 | pdata[0] = 0; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 0; | 252 | pdata[0] = 0; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 0; |
266 | owrite(ctx, &pdata, sizeof(pdata)); | 253 | owrite(ctx, &pdata, sizeof(pdata)); |
267 | reloc.vaddr = 0; reloc.symidx = 1+2+relocsyms+2+2+1; | 254 | reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1; |
268 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 255 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
269 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 256 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
270 | reloc.vaddr = 4; reloc.symidx = 1+2+relocsyms+2+2+1; | 257 | reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2+2+1; |
271 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 258 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
272 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 259 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
273 | reloc.vaddr = 8; reloc.symidx = 1+2+relocsyms+2; | 260 | reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2; |
274 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 261 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
275 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 262 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
276 | } | 263 | } |
@@ -287,7 +274,7 @@ void emit_peobj(BuildCtx *ctx) | |||
287 | xdata[7] = 0; /* Alignment. */ | 274 | xdata[7] = 0; /* Alignment. */ |
288 | xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */ | 275 | xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */ |
289 | owrite(ctx, &xdata, sizeof(xdata)); | 276 | owrite(ctx, &xdata, sizeof(xdata)); |
290 | reloc.vaddr = sizeof(xdata)-4; reloc.symidx = 1+2+relocsyms+2+2; | 277 | reloc.vaddr = sizeof(xdata)-4; reloc.symidx = 1+2+nrsym+2+2; |
291 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 278 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
292 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 279 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
293 | } | 280 | } |
@@ -299,69 +286,28 @@ void emit_peobj(BuildCtx *ctx) | |||
299 | /* Write symbol table. */ | 286 | /* Write symbol table. */ |
300 | strtab = NULL; /* 1st pass: collect string sizes. */ | 287 | strtab = NULL; /* 1st pass: collect string sizes. */ |
301 | for (;;) { | 288 | for (;;) { |
302 | char name[80]; | ||
303 | |||
304 | strtabofs = 4; | 289 | strtabofs = 4; |
305 | /* Mark as SafeSEH compliant. */ | 290 | /* Mark as SafeSEH compliant. */ |
306 | emit_peobj_sym(ctx, "@feat.00", 1, | 291 | emit_peobj_sym(ctx, "@feat.00", 1, |
307 | PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC); | 292 | PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC); |
308 | 293 | ||
309 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT); | 294 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT); |
310 | for (i = 0; ctx->extnames[i]; i++) { | 295 | for (i = 0; i < nrsym; i++) |
311 | const char *sym = ctx->extnames[i]; | 296 | emit_peobj_sym(ctx, ctx->relocsym[i], 0, |
312 | const char *p = strchr(sym, '@'); | ||
313 | if (p) { | ||
314 | #ifdef PEOBJ_SYMF_PREFIX | ||
315 | sprintf(name, PEOBJ_SYMF_PREFIX "%s", sym); | ||
316 | #else | ||
317 | strncpy(name, sym, p-sym); | ||
318 | name[p-sym] = '\0'; | ||
319 | #endif | ||
320 | } else { | ||
321 | sprintf(name, PEOBJ_SYM_PREFIX "%s", sym); | ||
322 | } | ||
323 | emit_peobj_sym(ctx, name, 0, | ||
324 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 297 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
325 | } | ||
326 | 298 | ||
327 | #if LJ_TARGET_X64 | 299 | #if LJ_TARGET_X64 |
328 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); | 300 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); |
329 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); | 301 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); |
330 | emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX "lj_err_unwind_win64", 0, | 302 | emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, |
331 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 303 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
332 | #endif | 304 | #endif |
333 | 305 | ||
334 | emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0, | 306 | emit_peobj_sym(ctx, ctx->beginsym, 0, |
335 | PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN); | 307 | PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN); |
336 | for (i = nzsym; i < ctx->nsym; i++) { | 308 | for (i = 0; i < ctx->nsym; i++) |
337 | int pi = ctx->perm[i]; | 309 | emit_peobj_sym(ctx, ctx->sym[i].name, (uint32_t)ctx->sym[i].ofs, |
338 | if (pi >= ctx->npc) { | 310 | PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
339 | const char *sym = ctx->globnames[pi-ctx->npc]; | ||
340 | const char *p = strchr(sym, '@'); | ||
341 | if (p) { | ||
342 | #ifdef PEOBJ_SYMF_PREFIX | ||
343 | sprintf(name, PEOBJ_SYMF_PREFIX LABEL_PREFIX "%s", sym); | ||
344 | #else | ||
345 | sprintf(name, LABEL_PREFIX "%s", sym); | ||
346 | name[(p-sym)+sizeof(LABEL_PREFIX)-1] = '\0'; | ||
347 | #endif | ||
348 | } else { | ||
349 | sprintf(name, PEOBJ_SYM_PREFIX LABEL_PREFIX "%s", sym); | ||
350 | } | ||
351 | emit_peobj_sym_func(ctx, name, ctx->sym_ofs[pi]); | ||
352 | #if LJ_HASJIT | ||
353 | } else { | ||
354 | #else | ||
355 | } else if (!(pi == BC_JFORI || pi == BC_JFORL || pi == BC_JITERL || | ||
356 | pi == BC_JLOOP || pi == BC_JFUNCF || pi == BC_JFUNCV || | ||
357 | pi == BC_IFORL || pi == BC_IITERL || pi == BC_ILOOP || | ||
358 | pi == BC_IFUNCF || pi == BC_IFUNCV)) { | ||
359 | #endif | ||
360 | sprintf(name, PEOBJ_SYM_PREFIX LABEL_PREFIX_BC "%s", | ||
361 | bc_names[pi]); | ||
362 | emit_peobj_sym_func(ctx, name, ctx->sym_ofs[pi]); | ||
363 | } | ||
364 | } | ||
365 | 311 | ||
366 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z); | 312 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z); |
367 | 313 | ||