function pointer compare

tccelf.c:
- Check if symbol is in data section and UNDEF. Then generate new
  relocation and let dynamic linker solve it.

tests/tests2/42_function_pointer.c:
- Add new test code
This commit is contained in:
herman ten brugge 2020-09-21 09:18:48 +02:00
parent ffac4e7688
commit 8f9bf3f223
3 changed files with 32 additions and 2 deletions

View File

@ -996,12 +996,25 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
tgt += rel->r_addend; tgt += rel->r_addend;
#endif #endif
addr = s->sh_addr + rel->r_offset; addr = s->sh_addr + rel->r_offset;
relocate(s1, rel, type, ptr, addr, tgt); {
#if !(defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
defined(TCC_TARGET_MACHO))
int dynindex;
if (s == data_section && sym->st_shndx == SHN_UNDEF &&
s1->dynsym &&
(dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index)) {
rel->r_info = ELFW(R_INFO)(dynindex, type);
*qrel++ = *rel;
}
else
#endif
relocate(s1, rel, type, ptr, addr, tgt);
}
} }
/* if the relocation is allocated, we change its symbol table */ /* if the relocation is allocated, we change its symbol table */
if (sr->sh_flags & SHF_ALLOC) { if (sr->sh_flags & SHF_ALLOC) {
sr->link = s1->dynsym; sr->link = s1->dynsym;
if (s1->output_type == TCC_OUTPUT_DLL) { if (qrel != (ElfW_Rel *)sr->data) {
size_t r = (uint8_t*)qrel - sr->data; size_t r = (uint8_t*)qrel - sr->data;
if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
&& 0 == strcmp(s->name, ".stab")) && 0 == strcmp(s->name, ".stab"))
@ -1242,6 +1255,12 @@ ST_FUNC void build_got_entries(TCCState *s1)
/* dynsym isn't set for -run :-/ */ /* dynsym isn't set for -run :-/ */
dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index; dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index;
esym = (ElfW(Sym) *)s1->dynsym->data + dynindex; esym = (ElfW(Sym) *)s1->dynsym->data + dynindex;
#if !(defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
defined(TCC_TARGET_MACHO))
if (dynindex && s == data_section->reloc)
s->sh_flags |= SHF_ALLOC;
else
#endif
if (dynindex if (dynindex
&& (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC
|| (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE || (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE

View File

@ -12,10 +12,18 @@ int (*f)(int) = &fred;
(fprint here) must not be called directly anywhere in the test. */ (fprint here) must not be called directly anywhere in the test. */
int (*fprintfptr)(FILE *, const char *, ...) = &fprintf; int (*fprintfptr)(FILE *, const char *, ...) = &fprintf;
typedef int (*func) (int);
static int dummy1(int i) { return 0; }
int dummy2(int i) { return 0; }
static func allfunc[] = { putchar, dummy1, dummy2 };
int main() int main()
{ {
fprintfptr(stdout, "%d\n", (*f)(24)); fprintfptr(stdout, "%d\n", (*f)(24));
printf ("%d\n", allfunc[0] == putchar);
printf ("%d\n", allfunc[1] == dummy1);
printf ("%d\n", allfunc[2] == dummy2);
return 0; return 0;
} }

View File

@ -1,2 +1,5 @@
yo 24 yo 24
42 42
1
1
1