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.
This commit is contained in:
herman ten brugge
2025-12-21 07:05:55 +01:00
parent 34eed88a70
commit 96119149fe
7 changed files with 37 additions and 10 deletions

View File

@@ -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)

View File

@@ -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;
}

1
configure vendored
View File

@@ -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]

6
elf.h
View File

@@ -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 */

View File

@@ -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 },

View File

@@ -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;

View File

@@ -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);
}