diff --git a/i386-asm.c b/i386-asm.c index b875aade..a7563ab0 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -891,7 +891,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) /* after immediate operands, adjust pc-relative address */ if (pc) - *(int*)(text_section->data + pc - 4) -= ind - pc; + add32le(text_section->data + pc - 4, pc - ind); } /* return the constraint priority (we allocate first the lowest diff --git a/tcc.h b/tcc.h index ed134d7b..180838dd 100644 --- a/tcc.h +++ b/tcc.h @@ -1423,12 +1423,18 @@ static inline uint32_t read32le(unsigned char *p) { static inline void write32le(unsigned char *p, uint32_t x) { write16le(p, x), write16le(p + 2, x >> 16); } +static inline void add32le(unsigned char *p, int32_t x) { + write32le(p, read32le(p) + x); +} static inline uint64_t read64le(unsigned char *p) { return read32le(p) | (uint64_t)read32le(p + 4) << 32; } static inline void write64le(unsigned char *p, uint64_t x) { write32le(p, x), write32le(p + 4, x >> 32); } +static inline void add64le(unsigned char *p, int64_t x) { + write64le(p, read64le(p) + x); +} /* ------------ i386-gen.c ------------ */ #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 diff --git a/tccelf.c b/tccelf.c index 6fa10dc2..2f8df1d0 100644 --- a/tccelf.c +++ b/tccelf.c @@ -722,7 +722,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) qrel++; } } - write32le(ptr, read32le(ptr) + val); + add32le(ptr, val); break; case R_386_PC32: if (s1->output_type == TCC_OUTPUT_DLL) { @@ -735,25 +735,25 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) break; } } - write32le(ptr, read32le(ptr) + val - addr); + add32le(ptr, val - addr); break; case R_386_PLT32: - write32le(ptr, read32le(ptr) + val - addr); + add32le(ptr, val - addr); break; case R_386_GLOB_DAT: case R_386_JMP_SLOT: write32le(ptr, val); break; case R_386_GOTPC: - write32le(ptr, read32le(ptr) + s1->got->sh_addr - addr); + add32le(ptr, s1->got->sh_addr - addr); break; case R_386_GOTOFF: - write32le(ptr, read32le(ptr) + val - s1->got->sh_addr); + add32le(ptr, val - s1->got->sh_addr); break; case R_386_GOT32: case R_386_GOT32X: /* we load the got offset */ - write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset); + add32le(ptr, s1->sym_attrs[sym_index].got_offset); break; case R_386_16: if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) { @@ -1110,7 +1110,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) qrel++; } } - write64le(ptr, read64le(ptr) + val); + add64le(ptr, val); break; case R_X86_64_32: case R_X86_64_32S: @@ -1122,7 +1122,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) qrel->r_addend = (int)read32le(ptr) + val; qrel++; } - write32le(ptr, read32le(ptr) + val); + add32le(ptr, val); break; case R_X86_64_PC32: @@ -1154,7 +1154,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) if (diff < -2147483648LL || diff > 2147483647LL) { tcc_error("internal error: relocation failed"); } - write32le(ptr, read32le(ptr) + diff); + add32le(ptr, diff); } break; case R_X86_64_GLOB_DAT: @@ -1165,16 +1165,15 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: - write32le(ptr, read32le(ptr) + - (s1->got->sh_addr - addr + - s1->sym_attrs[sym_index].got_offset - 4)); + add32le(ptr, s1->got->sh_addr - addr + + s1->sym_attrs[sym_index].got_offset - 4); break; case R_X86_64_GOTTPOFF: - write32le(ptr, read32le(ptr) + val - s1->got->sh_addr); + add32le(ptr, val - s1->got->sh_addr); break; case R_X86_64_GOT32: /* we load the got offset */ - write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset); + add32le(ptr, s1->sym_attrs[sym_index].got_offset); break; #ifdef TCC_TARGET_PE case R_X86_64_RELATIVE: /* handled in pe_relocate_rva() */ @@ -2126,30 +2125,29 @@ ST_FUNC void relocate_plt(TCCState *s1) p_end = p + s1->plt->data_offset; if (p < p_end) { #if defined(TCC_TARGET_I386) - write32le(p + 2, read32le(p + 2) + s1->got->sh_addr); - write32le(p + 8, read32le(p + 8) + s1->got->sh_addr); + add32le(p + 2, s1->got->sh_addr); + add32le(p + 8, s1->got->sh_addr); p += 16; while (p < p_end) { - write32le(p + 2, read32le(p + 2) + s1->got->sh_addr); + add32le(p + 2, s1->got->sh_addr); p += 16; } #elif defined(TCC_TARGET_X86_64) int x = s1->got->sh_addr - s1->plt->sh_addr - 6; - write32le(p + 2, read32le(p + 2) + x); - write32le(p + 8, read32le(p + 8) + x - 6); + add32le(p + 2, x); + add32le(p + 8, x - 6); p += 16; while (p < p_end) { - write32le(p + 2, read32le(p + 2) + x + s1->plt->data - p); + add32le(p + 2, x + s1->plt->data - p); p += 16; } #elif defined(TCC_TARGET_ARM) - int x; - x=s1->got->sh_addr - s1->plt->sh_addr - 12; + int x = s1->got->sh_addr - s1->plt->sh_addr - 12; p += 16; while (p < p_end) { if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */ p += 4; - write32le(p + 12, x + read32le(p + 12) + s1->plt->data - p); + add32le(p + 12, x + s1->plt->data - p); p += 16; } #elif defined(TCC_TARGET_ARM64)