aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2013-01-25 20:01:43 +0100
committerThomas Preud'homme <robotux@celest.fr>2013-01-25 20:06:51 +0100
commitf8cde529843ba15ba2f6981d4401b5be1009c5c5 (patch)
treed34e7b67fed2ffa832fca0f1c87b2674f3b4df25
parentb89793d10a8cf1c3fa237d98cf4b656ac5aabf55 (diff)
downloadtinycc-f8cde529843ba15ba2f6981d4401b5be1009c5c5.tar.gz
tinycc-f8cde529843ba15ba2f6981d4401b5be1009c5c5.tar.bz2
Link STT_GNU_IFUNC into STT_FUNC in executable.
Indirect functions shall have STT_FUNC type in executable dynsym section. Indeed, a dlsym call following a lazy resolution would pick the symbol value from the executable dynsym entry. This would contain the address of the function wanted by the caller of dlsym instead of the address of the function that would return that address.
-rw-r--r--tccelf.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/tccelf.c b/tccelf.c
index da81d03..b5eea07 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1632,8 +1632,16 @@ static int elf_output_file(TCCState *s1, const char *filename)
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
type = ELFW(ST_TYPE)(esym->st_info);
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
+ /* Indirect functions shall have STT_FUNC type
+ * in executable dynsym section. Indeed, a dlsym
+ * call following a lazy resolution would pick
+ * the symbol value from the executable dynsym
+ * entry which would contain the address of the
+ * function wanted by the caller of dlsym
+ * instead of the address of the function that
+ * would return that address */
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
- ELFW(ST_INFO)(STB_GLOBAL,type),
+ ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
@@ -1733,8 +1741,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
&& sym->st_shndx == SHN_UNDEF) {
+ int visibility = ELFW(ST_BIND)(sym->st_info);
put_got_entry(s1, R_JMP_SLOT, sym->st_size,
- sym->st_info,
+ ELFW(ST_INFO)(visibility,STT_FUNC),
sym - (ElfW(Sym) *)symtab_section->data);
}
else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {