From 96119149feffe0b7a2900f1fda2e420af430f4a4 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Sun, 21 Dec 2025 07:05:55 +0100 Subject: [PATCH] Problems solved on for libtcc, pie, riscv64, arm64 I found some problems with a testcase from mailing list. On x86_64 an overflow on reloc R_X86_64_32 occurred that was not reported when using -run -ltcc. The problem could be solved by compiling tcc with -fPIE, -pie or --disable-static. Makefile, configure, libtcc.c, x86_64-link.c: - add --config-pie to configure help. Ignore -pie in libtcc.c and check reloc overflow in x86_64-link.c arm64-gen.c: - Fix reading from constant like '*(int *)0x7fffb7f1280c' elf.h, riscv64-link.c: - fix for -run -ltcc. Ignore reloc R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128 that are used in .debug_loclists section. --- Makefile | 5 +++++ arm64-gen.c | 20 ++++++++++++-------- configure | 1 + elf.h | 6 +++++- libtcc.c | 1 + riscv64-link.c | 8 ++++++++ x86_64-link.c | 6 +++++- 7 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 981eed26..d9641d2e 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,11 @@ CFLAGS += $(CPPFLAGS) VPATH = $(TOPSRC) -LTCC = $(TOP)/$(LIBTCC) +ifeq ($(CONFIG_pie),yes) +CFLAGS += -fPIE +LDFLAGS += -pie +endif + ifdef CONFIG_WIN32 CFG = -win ifneq ($(CONFIG_static),yes) diff --git a/arm64-gen.c b/arm64-gen.c index 03ae56c3..01ea3909 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -503,17 +503,19 @@ ST_FUNC void load(int r, SValue *sv) } if (svr == (VT_CONST | VT_LVAL)) { + uint64_t i = sv->c.i; + if (sv->sym) arm64_sym(30, sv->sym, // use x30 for address - arm64_check_offset(0, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(0, arm64_type_size(svtt), i)); else - arm64_movimm (30, sv->c.i); + arm64_movimm (30, i), i = 0; if (IS_FREG(r)) arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, - arm64_check_offset(1, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(1, arm64_type_size(svtt), i)); else arm64_ldrx(!(svtt&VT_UNSIGNED), arm64_type_size(svtt), intr(r), 30, - arm64_check_offset(1, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(1, arm64_type_size(svtt), i)); return; } @@ -621,17 +623,19 @@ ST_FUNC void store(int r, SValue *sv) } if (svr == (VT_CONST | VT_LVAL)) { + uint64_t i = sv->c.i; + if (sv->sym) arm64_sym(30, sv->sym, // use x30 for address - arm64_check_offset(0, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(0, arm64_type_size(svtt), i)); else - arm64_movimm (30, sv->c.i); + arm64_movimm (30, i), i = 0; if (IS_FREG(r)) arm64_strv(arm64_type_size(svtt), fltr(r), 30, - arm64_check_offset(1, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(1, arm64_type_size(svtt), i)); else arm64_strx(arm64_type_size(svtt), intr(r), 30, - arm64_check_offset(1, arm64_type_size(svtt), sv->c.i)); + arm64_check_offset(1, arm64_type_size(svtt), i)); return; } diff --git a/configure b/configure index 8ce07811..f26a8ab8 100755 --- a/configure +++ b/configure @@ -230,6 +230,7 @@ Advanced options (experts only): --config-new_dtags=yes use new ELF DTAGs (DT_RUNPATH instead of DT_RPATH) --config-codesign=no do not use codesign on apple to sign executables --config-dwarf=x use dwarf debug info instead of stabs (x=2..5) + --config-pie compile with pie Cross build options (experimental): --cpu=CPU target CPU [$cpu] diff --git a/elf.h b/elf.h index 14cfdcff..15645ee8 100644 --- a/elf.h +++ b/elf.h @@ -3313,8 +3313,12 @@ typedef Elf32_Addr Elf32_Conflict; #define R_RISCV_SET16 55 #define R_RISCV_SET32 56 #define R_RISCV_32_PCREL 57 +#define R_RISCV_IRELATIVE 58 +#define R_RISCV_PLT32 59 +#define R_RISCV_SET_ULEB128 60 +#define R_RISCV_SUB_ULEB128 61 -#define R_RISCV_NUM 58 +#define R_RISCV_NUM 62 #endif /* elf.h */ diff --git a/libtcc.c b/libtcc.c index 01c4c7fd..c430d1a2 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1674,6 +1674,7 @@ static const TCCOption tcc_options[] = { { "C", 0, 0 }, { "-param", 0, TCC_OPTION_HAS_ARG }, { "pedantic", 0, 0 }, + { "pie", 0, 0 }, { "pipe", 0, 0 }, { "s", 0, 0 }, { "traditional", 0, 0 }, diff --git a/riscv64-link.c b/riscv64-link.c index bdc8c242..98722a20 100644 --- a/riscv64-link.c +++ b/riscv64-link.c @@ -51,6 +51,8 @@ ST_FUNC int code_reloc (int reloc_type) case R_RISCV_SUB64: case R_RISCV_32: case R_RISCV_64: + case R_RISCV_SET_ULEB128: + case R_RISCV_SUB_ULEB128: return 0; case R_RISCV_CALL_PLT: @@ -77,6 +79,8 @@ ST_FUNC int gotplt_entry_type (int reloc_type) case R_RISCV_ADD16: case R_RISCV_SUB8: case R_RISCV_SUB16: + case R_RISCV_SET_ULEB128: + case R_RISCV_SUB_ULEB128: return NO_GOTPLT_ENTRY; case R_RISCV_BRANCH: @@ -367,6 +371,10 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, } add32le(ptr, val - addr); return; + case R_RISCV_SET_ULEB128: + case R_RISCV_SUB_ULEB128: + /* ignore. used in section .debug_loclists */ + return; case R_RISCV_COPY: /* XXX */ return; diff --git a/x86_64-link.c b/x86_64-link.c index 42f753c9..e367ee90 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -221,6 +221,10 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, qrel->r_addend = (int)read32le(ptr) + val; qrel++; } + if ((type == R_X86_64_32 && (unsigned long long)val > 4294967295ULL) || + (type == R_X86_64_32S && + ((long long)val < -2147483648LL || (long long)val > 2147483647LL))) + tcc_error_noabort("internal error: relocation %d failed", type); add32le(ptr, val); break; @@ -251,7 +255,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, /* ignore overflow with undefined weak symbols */ if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) #endif - tcc_error_noabort("internal error: relocation failed"); + tcc_error_noabort("internal error: relocation %d failed", type); } add32le(ptr, diff); }