x86-64: fix shared libs

The introduction of read32le everywhere created a subtle issue, going
from
   x = *(int*)p;
to
   x = read32le(p);
is not equivalent if x is a larger than 32bit quantity, like an
address on x86_64, because read32le returns an unsigned int.  The first
sign extends, the latter zero extends.  This broke shared library
creation for gawk.  It's enough to amend the case of the above
situation, cases like "write32le(p, read32le(p) +- something)" are okay,
no extensions happen or matter.
master
Michael Matz 2015-12-17 19:41:20 +01:00
parent e264243adc
commit f15c0a9333
1 changed files with 4 additions and 2 deletions

View File

@ -898,7 +898,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_X86_64_32 even for a 64bit pointer */
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
qrel->r_addend = read32le(ptr) + val;
/* Use sign extension! */
qrel->r_addend = (int)read32le(ptr) + val;
qrel++;
}
write32le(ptr, read32le(ptr) + val);
@ -911,7 +912,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
qrel->r_addend = read32le(ptr);
/* Use sign extension! */
qrel->r_addend = (int)read32le(ptr);
qrel++;
break;
}