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.
Unified · Split
| @@ -898,7 +898,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 897 unmodified lines | ||
| 898 | 898 | /* XXX: this logic may depend on TCC's codegen |
| 899 | 899 | now TCC uses R_X86_64_32 even for a 64bit pointer */ |
| 900 | 900 | qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); |
| 901 | − qrel->r_addend = read32le(ptr) + val; | |
| 901 | + /* Use sign extension! */ | |
| 902 | + qrel->r_addend = (int)read32le(ptr) + val; | |
| 902 | 903 | qrel++; |
| 903 | 904 | } |
| 904 | 905 | write32le(ptr, read32le(ptr) + val); |
| @@ -911,7 +912,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 6 unmodified lines | ||
| 911 | 912 | if (esym_index) { |
| 912 | 913 | qrel->r_offset = rel->r_offset; |
| 913 | 914 | qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32); |
| 914 | − qrel->r_addend = read32le(ptr); | |
| 915 | + /* Use sign extension! */ | |
| 916 | + qrel->r_addend = (int)read32le(ptr); | |
| 915 | 917 | qrel++; |
| 916 | 918 | break; |
| 917 | 919 | } |