aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--elf.h1
-rw-r--r--tccelf.c14
-rw-r--r--tccrun.c6
3 files changed, 14 insertions, 7 deletions
diff --git a/elf.h b/elf.h
index ebb9a8b..6c08f3d 100644
--- a/elf.h
+++ b/elf.h
@@ -436,6 +436,7 @@ typedef struct
#define STT_SECTION 3 /* Symbol associated with a section */
#define STT_FILE 4 /* Symbol's name is file name */
#define STT_NUM 5 /* Number of defined types. */
+#define STT_GNU_IFUNC 10 /* Symbol is a indirect code object */
#define STT_LOOS 11 /* Start of OS-specific */
#define STT_HIOS 12 /* End of OS-specific */
#define STT_LOPROC 13 /* Start of processor-specific */
diff --git a/tccelf.c b/tccelf.c
index fb5f3f9..e5603eb 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1514,9 +1514,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
build_got(s1);
/* scan for undefined symbols and see if they are in the
- dynamic symbols. If a symbol STT_FUNC is found, then we
- add it in the PLT. If a symbol STT_OBJECT is found, we
- add it in the .bss section with a suitable relocation */
+ dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
+ is found, then we add it in the PLT. If a symbol
+ STT_OBJECT is found, we add it in the .bss section with
+ a suitable relocation */
sym_end = (ElfW(Sym) *)(symtab_section->data +
symtab_section->data_offset);
if (file_type == TCC_OUTPUT_EXE) {
@@ -1529,7 +1530,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
if (sym_index) {
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
type = ELFW(ST_TYPE)(esym->st_info);
- if (type == STT_FUNC) {
+ if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
esym->st_info,
sym - (ElfW(Sym) *)symtab_section->data);
@@ -1626,8 +1627,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
sym++) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
- if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
- sym->st_shndx == SHN_UNDEF) {
+ if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
+ ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
+ && sym->st_shndx == SHN_UNDEF) {
put_got_entry(s1, R_JMP_SLOT, sym->st_size,
sym->st_info,
sym - (ElfW(Sym) *)symtab_section->data);
diff --git a/tccrun.c b/tccrun.c
index 9ef903d..e24d95e 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -306,7 +306,11 @@ static uplong rt_printline(uplong wanted_pc)
sym < sym_end;
sym++) {
type = ELFW(ST_TYPE)(sym->st_info);
- if (type == STT_FUNC) {
+ if (type == STT_FUNC
+#ifdef STT_GNU_IFUNC
+ || type == STT_GNU_IFUNC
+#endif
+ ) {
if (wanted_pc >= sym->st_value &&
wanted_pc < sym->st_value + sym->st_size) {
pstrcpy(last_func_name, sizeof(last_func_name),