* coff-objfmt.c (coff_objfmt_output_expr): Try to match the new ML64's

output better by generating relocs directly to the symbol being relocated
rather than to the section.  Use a new coff_objfmt->win64 flag to
conditionalize this rather than just COFF_MACHINE_AMD64.
(coff_objfmt): New win64 flag.
(coff_objfmt_create, win32_objfmt_create, win64_objfmt_create): Initialize
flag.
(coff_objfmt_output): Turn on outputting all symbols in win64 mode so they
can be referenced by relocs.  This isn't quite correct: we should only turn
on the symbols that are actually used by relocs, but having them there
doesn't hurt linking; it only exposes all of the internal symbol names.

With these changes, yasm output matches the new ML64 output except for a
very few cases:
 - ML64 generates REL32 relocs when referencing objects in the same .text
section.  I cannot see how this is necessary because call instructions
don't generate REL32 relocs!  I currently do not plan on fixing this unless
it causes a problem.
 - ML64 generates ADDR32 relocs instead of REL32 relocs when loading a
32-bit register with the address of an object.  I will probably try to fix
this.

Extended test case for this a bit.

svn path=/trunk/yasm/; revision=1256
0.5.0rc2
Peter Johnson 20 years ago
parent 0c901cf837
commit fc6e94054e
  1. 20
      modules/objfmts/coff/coff-objfmt.c
  2. 46
      modules/objfmts/win64/tests/win64-dataref.asm
  3. 1110
      modules/objfmts/win64/tests/win64-dataref.hex
  4. 31
      modules/objfmts/win64/tests/win64-dataref.masm

@ -173,7 +173,8 @@ typedef struct yasm_objfmt_coff {
yasm_objfmt_base objfmt; /* base structure*/
unsigned int parse_scnum; /* sect numbering in parser */
int win32; /* nonzero for win32 output */
int win32; /* nonzero for win32/64 output */
int win64; /* nonzero for win64 output */
unsigned int machine; /* COFF machine to use */
@ -284,6 +285,7 @@ coff_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a)
objfmt_coff->objfmt.module = &yasm_coff_LTX_objfmt;
objfmt_coff->win32 = 0;
objfmt_coff->win64 = 0;
}
return (yasm_objfmt *)objfmt_coff;
}
@ -304,6 +306,7 @@ win32_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a)
} else if (yasm__strcasecmp(yasm_arch_get_machine(a), "amd64") == 0) {
objfmt_coff->machine = COFF_MACHINE_AMD64;
objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
objfmt_coff->win64 = 1;
} else {
yasm_xfree(objfmt_coff);
return NULL;
@ -331,6 +334,7 @@ win64_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a)
objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
objfmt_coff->win32 = 1;
objfmt_coff->win64 = 1;
}
return (yasm_objfmt *)objfmt_coff;
}
@ -388,7 +392,8 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
}
/* Handle integer expressions, with relocation if necessary */
sym = yasm_expr_extract_symrec(ep, 1, yasm_common_calc_bc_dist);
sym = yasm_expr_extract_symrec(ep, !objfmt_coff->win64,
yasm_common_calc_bc_dist);
if (sym) {
unsigned long addr;
coff_reloc *reloc;
@ -413,7 +418,7 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
csymd->size->line);
*ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);
}
} else if (!(vis & YASM_SYM_EXTERN)) {
} else if (!(vis & YASM_SYM_EXTERN) && !objfmt_coff->win64) {
/* Local symbols need relocation to their section's start */
if (yasm_symrec_get_label(sym, &label_precbc)) {
/*@null@*/ coff_section_data *label_csd;
@ -450,6 +455,7 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
* $$ in.
* For Win32 COFF, need to reference to next bytecode, so add '$'
* (really $+$.len) in.
* For Win64 COFF, don't add anything in.
*/
if (objfmt_coff->win32)
*ep = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(*ep),
@ -472,7 +478,7 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
if (valsize == 32) {
if (info->csd->flags2 & COFF_FLAG_NOBASE)
reloc->type = COFF_RELOC_AMD64_ADDR32NB;
else if (yasm_bc_is_data(bc))
else if (!objfmt_coff->win64 || yasm_bc_is_data(bc))
reloc->type = COFF_RELOC_AMD64_ADDR32;
else {
/* I don't understand this, but ML64 generates REL32
@ -905,6 +911,12 @@ coff_objfmt_output(yasm_objfmt *objfmt, FILE *f, const char *obj_filename,
unsigned long symtab_count;
unsigned int flags;
/* Force all syms for win64 because they're needed for relocations.
* FIXME: Not *all* syms need to be output, only the ones needed for
* relocation. Find a way to do that someday.
*/
all_syms |= objfmt_coff->win64;
info.strtab_offset = 4;
info.objfmt_coff = objfmt_coff;
info.f = f;

@ -24,10 +24,13 @@ xptr2 dq x
[SECTION .bss]
x resq 1
y resq 1
[SECTION .text]
x86ident:
; with :proc
; extern with :proc
; This instruction generates a different relocation than
; MASM does at present.
mov ebx, foobar ; WTF ML64.. this had []
mov rcx, foobar
lea rdx, [foobar wrt rip]
@ -37,6 +40,25 @@ x86ident:
movzx rax, byte [foobar wrt rip]
movzx rax, byte [foobar+rax]
; local "proc"
; See note above
mov ebx, trap
mov rcx, trap
; MASM generates a REL32 reloc for this even though it's in
; the same section. I don't know why, as the call instruction
; below doesn't cause a reloc, so the linker can't be moving
; functions around within an object!
lea rdx, [trap wrt rip]
mov rax, [trap+rcx]
mov rax, trap
mov rbx, trap
; MASM generates a REL32 reloc for this even though it's in
; the same section. I don't know why, as the call instruction
; below doesn't cause a reloc, so the linker can't be moving
; functions around within an object!
movzx rax, byte [trap wrt rip]
movzx rax, byte [trap+rax]
; with :abs
;mov ebx,[foobar2]
;mov rcx,offset foobar2
@ -48,6 +70,8 @@ x86ident:
;movzx rax, byte ptr foobar2[rax]
; with :qword
; See note above
mov ebx, foobar3
mov ebx, [foobar3 wrt rip]
mov rcx, foobar3
lea rdx, [foobar3 wrt rip]
@ -58,6 +82,8 @@ x86ident:
movzx rax, byte [foobar3+rax]
; local var (dword)
; See note above
mov ebx, __savident
mov ebx,[__savident wrt rip]
mov rcx, __savident
lea rdx, [__savident wrt rip]
@ -68,6 +94,8 @@ x86ident:
movzx rax, byte [__savident+rax]
; local var (qword)
; See note above
mov ebx, savidentptr2
mov ebx, [savidentptr2 wrt rip]
mov rcx, savidentptr2
lea rdx, [savidentptr2 wrt rip]
@ -77,8 +105,22 @@ x86ident:
movzx rax, byte [savidentptr2 wrt rip]
movzx rax, byte [savidentptr2+rax]
; bss local var (qword)
; See note above
mov ebx, y
mov ebx, [y wrt rip]
mov rcx, y
lea rdx, [y wrt rip]
mov rax, [y+rcx]
mov rax, [y wrt rip]
mov rbx, [y wrt rip]
movzx rax, byte [y wrt rip]
movzx rax, byte [y+rax]
call foobar
call trap
ret
trap: sub rsp, 256
@ -88,7 +130,7 @@ trap: sub rsp, 256
[SECTION .pdata]
dd trap
dd trap.end
dd trap+(trap.end-trap)
dd $xdatasym
[SECTION .xdata]

File diff suppressed because it is too large Load Diff

@ -27,11 +27,12 @@ xptr2 dq x
_DATA ENDS
_BSS SEGMENT
x dq ?
y dq ?
_BSS ENDS
_TEXT SEGMENT
x86ident:
; with :proc
; extern with :proc
mov ebx,[foobar]
mov rcx,offset foobar
lea rdx, foobar
@ -41,6 +42,18 @@ x86ident:
movzx rax, byte ptr foobar
movzx rax, byte ptr foobar[rax]
; local proc
mov ebx,[trap]
mov rcx,offset trap
; See note in YASM file
lea rdx, trap
mov rax, qword ptr trap[rcx]
mov rax, trap
mov rbx, trap
; See note in YASM file
movzx rax, byte ptr trap
movzx rax, byte ptr trap[rax]
; with :abs
;mov ebx,[foobar2]
;mov rcx,offset foobar2
@ -52,6 +65,7 @@ x86ident:
;movzx rax, byte ptr foobar2[rax]
; with :qword
mov ebx, offset foobar3
mov ebx, dword ptr [foobar3]
mov rcx,offset foobar3
lea rdx, foobar3
@ -62,6 +76,7 @@ x86ident:
movzx rax, byte ptr foobar3[rax]
; local var (dword)
mov ebx, offset __savident
mov ebx,[__savident]
mov rcx,offset __savident
lea rdx, __savident
@ -72,6 +87,7 @@ x86ident:
movzx rax, byte ptr __savident[rax]
; local var (qword)
mov ebx, offset savidentptr2
mov ebx, dword ptr [savidentptr2]
mov rcx,offset savidentptr2
lea rdx, savidentptr2
@ -81,8 +97,21 @@ x86ident:
movzx rax, byte ptr savidentptr2
movzx rax, byte ptr savidentptr2[rax]
; bss local var (qword)
mov ebx, offset y
mov ebx, dword ptr [y]
mov rcx,offset y
lea rdx, y
mov rax, y[rcx]
mov rax, y
mov rbx, y
movzx rax, byte ptr y
movzx rax, byte ptr y[rax]
call foobar
call trap
ret
trap proc public frame

Loading…
Cancel
Save