lazy binding

Currently tcc does not use lazy binding. It puts all relocations in the RELX
section and solve them all at startup.
This was not working on bsd.

tcc.h:
- New RELPLT_SECTION_FMT for plt relocations
- New entry relocplt in struct Section

tccelf.c:
- put_elf_reloca: put R_JMP_SLOT in relocplt section
- build_got_entries*: Use two passes because R_JMP_SLOT and R_GLOB_DAT
                      can not be intermixed on some targets (arm, arm64)
- layout_sections: Calculate correct size relocplt section for DT_ values.
                   Make sure relocplt is last
- fill_dynamic: Add DT_ values when got is filled
                move DT_VERSYM because dynamic linker cannot handle it standone
- Add note section for NetBSD

arm-link.c/arm64-link.c/i386-link.c/riscv64-link.c/x86_64-link.c:
- fill got table with pointer to plt section or symbol value in case
  of TCC_OUTPUT_MEMORY

arm-link.c/arm64-link.c:
- fix offset first plt entry

i386-link.c/x86_64-link.c:
- use correct reloc entry
- use relofs - sizeof (ElfW_Rel) because the reloc is already done

lib/bcheck.c:
- no __libc_freeres on FreeBSD and NetBSD

tests/Makefile:
- Add -fno-stack-protector for OpenBSD

tests/tests2/Makefile:
- disable 106_pthread/114_bound_signal
This commit is contained in:
herman ten brugge
2020-12-18 15:24:32 +01:00
parent e2e62fcb8b
commit 50b4f320dc
10 changed files with 162 additions and 39 deletions

View File

@@ -16,7 +16,7 @@
#define ELF_PAGE_SIZE 0x1000
#define PCRELATIVE_DLLPLT 0
#define RELOCATE_DLLPLT 0
#define RELOCATE_DLLPLT 1
#else /* !TARGET_DEFS_ONLY */
@@ -121,7 +121,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
/* The PLT slot refers to the relocation entry it needs via offset.
The reloc entry is created below, so its offset is the current
data_offset */
relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
relofs = s1->got->relocplt ? s1->got->relocplt->data_offset : 0;
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
p = section_ptr_add(plt, 16);
@@ -129,7 +129,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
p[1] = modrm;
write32le(p + 2, got_offset);
p[6] = 0x68; /* push $xxx */
write32le(p + 7, relofs);
write32le(p + 7, relofs - sizeof (ElfW_Rel));
p[11] = 0xe9; /* jmp plt_start */
write32le(p + 12, -(plt->data_offset));
return plt_offset;
@@ -147,7 +147,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) {
add32le(p + 2, s1->got->sh_addr);
add32le(p + 8, s1->got->sh_addr);
p += 16;
@@ -156,6 +156,20 @@ ST_FUNC void relocate_plt(TCCState *s1)
p += 16;
}
}
if (s1->got->relocplt) {
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
ElfW_Rel *rel;
int x = s1->plt->sh_addr + 16 + 6;
p = s1->got->data;
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
int sym_index = ELFW(R_SYM)(rel->r_info);
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
write32le(p + rel->r_offset, mem ? sym->st_value : x);
x += 16;
}
}
}
#endif