ref: c06291a2d7cf50b6d4fb8599edee4a608b886124
parent: 9e9960029dabc06b5c136f11944a54bea6a14f78
author: Lennart Jablonka <humm@ljabl.com>
date: Sun Dec 29 08:55:02 EST 2024
6l: relocate operands with REX correctly
If rexflag is non-zero, it's used to insert an REX prefix byte in
asmins. That's a while after put4 and put8 take note of the address
of a relocation. So let them be aware that if rexflag is non-zero,
the relocation's address is to be higher.
Reproduction:
The program
int global;
int f(void){return global;}
is compiled to the IR assembly
TEXT f+0(SB),0,$0
MOVL global+0(SB),AX
RET ,
RET ,
GLOBL global+0(SB),$4
END ,
and (using 6l -u) the machine code
8b042508 000000c3
The relocation (see a.out(6)) correctly applies to the 08 00 00 00.
The program
int *global;
int *f(void){return global;}
is compiled to
TEXT f+0(SB),0,$0
MOVQ global+0(SB),AX
RET ,
RET ,
GLOBL global+0(SB),$8
END ,
and the machine code
488b0425 10000000 c3020000 00000000
What's different is the added REX prefix 0x48, but the relocation is
done at the same place in the binary, which now is 25 10 00 00 instead
of the correct 10 00 00 00.
--- a/sys/src/cmd/6l/span.c
+++ b/sys/src/cmd/6l/span.c
@@ -596,7 +596,7 @@
put4(long v)
{ if(dlm && curp != P && reloca != nil){- dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
+ dynreloc(reloca->sym, curp->pc + andptr - &and[0] + !!rexflag, 1);
reloca = nil;
}
andptr[0] = v;
@@ -610,7 +610,7 @@
put8(vlong v)
{ if(dlm && curp != P && reloca != nil){- dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1); /* TO DO */
+ dynreloc(reloca->sym, curp->pc + andptr - &and[0] + !!rexflag, 1); /* TO DO */
reloca = nil;
}
andptr[0] = v;
--
⑨