mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
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:
parent
e2e62fcb8b
commit
50b4f320dc
14
arm-link.c
14
arm-link.c
@ -145,7 +145,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
||||||
write32le(s1->plt->data + 16, x - 16);
|
write32le(s1->plt->data + 16, x - 4);
|
||||||
p += 20;
|
p += 20;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
||||||
@ -157,6 +157,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 12;
|
p += 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->got->relocplt) {
|
||||||
|
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
|
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 : s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
15
arm64-link.c
15
arm64-link.c
@ -113,7 +113,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
uint64_t plt = s1->plt->sh_addr;
|
uint64_t plt = s1->plt->sh_addr;
|
||||||
uint64_t got = s1->got->sh_addr;
|
uint64_t got = s1->got->sh_addr + 16;
|
||||||
uint64_t off = (got >> 12) - (plt >> 12);
|
uint64_t off = (got >> 12) - (plt >> 12);
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
||||||
@ -129,6 +129,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
write32le(p + 24, 0xd503201f); // nop
|
write32le(p + 24, 0xd503201f); // nop
|
||||||
write32le(p + 28, 0xd503201f); // nop
|
write32le(p + 28, 0xd503201f); // nop
|
||||||
p += 32;
|
p += 32;
|
||||||
|
got = s1->got->sh_addr;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
uint64_t pc = plt + (p - s1->plt->data);
|
uint64_t pc = plt + (p - s1->plt->data);
|
||||||
uint64_t addr = got + read64le(p);
|
uint64_t addr = got + read64le(p);
|
||||||
@ -145,6 +146,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->got->relocplt) {
|
||||||
|
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
|
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];
|
||||||
|
write64le(p + rel->r_offset, mem ? sym->st_value : s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
|
22
i386-link.c
22
i386-link.c
@ -16,7 +16,7 @@
|
|||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
#define PCRELATIVE_DLLPLT 0
|
#define PCRELATIVE_DLLPLT 0
|
||||||
#define RELOCATE_DLLPLT 0
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
#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 PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
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 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
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;
|
p[1] = modrm;
|
||||||
write32le(p + 2, got_offset);
|
write32le(p + 2, got_offset);
|
||||||
p[6] = 0x68; /* push $xxx */
|
p[6] = 0x68; /* push $xxx */
|
||||||
write32le(p + 7, relofs);
|
write32le(p + 7, relofs - sizeof (ElfW_Rel));
|
||||||
p[11] = 0xe9; /* jmp plt_start */
|
p[11] = 0xe9; /* jmp plt_start */
|
||||||
write32le(p + 12, -(plt->data_offset));
|
write32le(p + 12, -(plt->data_offset));
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
@ -147,7 +147,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p = s1->plt->data;
|
p = s1->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
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 + 2, s1->got->sh_addr);
|
||||||
add32le(p + 8, s1->got->sh_addr);
|
add32le(p + 8, s1->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
@ -156,6 +156,20 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 16;
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -1153,7 +1153,8 @@ void __attribute__((destructor)) __bound_exit(void)
|
|||||||
dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
|
dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
|
||||||
|
|
||||||
if (inited) {
|
if (inited) {
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) && !defined TCC_MUSL
|
#if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \
|
||||||
|
!defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||||
if (print_heap) {
|
if (print_heap) {
|
||||||
extern void __libc_freeres (void);
|
extern void __libc_freeres (void);
|
||||||
__libc_freeres ();
|
__libc_freeres ();
|
||||||
|
@ -153,6 +153,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->got->relocplt) {
|
||||||
|
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
|
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];
|
||||||
|
write64le(p + rel->r_offset, mem ? sym->st_value + rel->r_addend : s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
|
3
tcc.h
3
tcc.h
@ -397,6 +397,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
# define ElfW_Rel ElfW(Rela)
|
# define ElfW_Rel ElfW(Rela)
|
||||||
# define SHT_RELX SHT_RELA
|
# define SHT_RELX SHT_RELA
|
||||||
# define REL_SECTION_FMT ".rela%s"
|
# define REL_SECTION_FMT ".rela%s"
|
||||||
|
# define RELPLT_SECTION_FMT ".rel.plt"
|
||||||
#else
|
#else
|
||||||
# define ELFCLASSW ELFCLASS32
|
# define ELFCLASSW ELFCLASS32
|
||||||
# define ElfW(type) Elf##32##_##type
|
# define ElfW(type) Elf##32##_##type
|
||||||
@ -404,6 +405,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
# define ElfW_Rel ElfW(Rel)
|
# define ElfW_Rel ElfW(Rel)
|
||||||
# define SHT_RELX SHT_REL
|
# define SHT_RELX SHT_REL
|
||||||
# define REL_SECTION_FMT ".rel%s"
|
# define REL_SECTION_FMT ".rel%s"
|
||||||
|
# define RELPLT_SECTION_FMT ".rel.plt"
|
||||||
#endif
|
#endif
|
||||||
/* target address type */
|
/* target address type */
|
||||||
#define addr_t ElfW(Addr)
|
#define addr_t ElfW(Addr)
|
||||||
@ -565,6 +567,7 @@ typedef struct Section {
|
|||||||
struct Section *reloc; /* corresponding section for relocation, if any */
|
struct Section *reloc; /* corresponding section for relocation, if any */
|
||||||
struct Section *hash; /* hash table for symbols */
|
struct Section *hash; /* hash table for symbols */
|
||||||
struct Section *prev; /* previous section on section stack */
|
struct Section *prev; /* previous section on section stack */
|
||||||
|
struct Section *relocplt;/* reloc with JMP_SLOTs */
|
||||||
char name[1]; /* section name */
|
char name[1]; /* section name */
|
||||||
} Section;
|
} Section;
|
||||||
|
|
||||||
|
107
tccelf.c
107
tccelf.c
@ -735,18 +735,25 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
Section *sr;
|
Section *sr;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
|
int jmp_slot = type == R_JMP_SLOT;
|
||||||
|
|
||||||
sr = s->reloc;
|
sr = jmp_slot ? s->relocplt : s->reloc;
|
||||||
if (!sr) {
|
if (!sr) {
|
||||||
/* if no relocation section, create it */
|
/* if no relocation section, create it */
|
||||||
snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
|
if (jmp_slot)
|
||||||
|
snprintf(buf, sizeof(buf), RELPLT_SECTION_FMT);
|
||||||
|
else
|
||||||
|
snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
|
||||||
/* if the symtab is allocated, then we consider the relocation
|
/* if the symtab is allocated, then we consider the relocation
|
||||||
are also */
|
are also */
|
||||||
sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
|
sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
|
||||||
sr->sh_entsize = sizeof(ElfW_Rel);
|
sr->sh_entsize = sizeof(ElfW_Rel);
|
||||||
sr->link = symtab;
|
sr->link = symtab;
|
||||||
sr->sh_info = s->sh_num;
|
sr->sh_info = s->sh_num;
|
||||||
s->reloc = sr;
|
if (jmp_slot)
|
||||||
|
s->relocplt = sr;
|
||||||
|
else
|
||||||
|
s->reloc = sr;
|
||||||
}
|
}
|
||||||
rel = section_ptr_add(sr, sizeof(ElfW_Rel));
|
rel = section_ptr_add(sr, sizeof(ElfW_Rel));
|
||||||
rel->r_offset = offset;
|
rel->r_offset = offset;
|
||||||
@ -1164,7 +1171,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build GOT and PLT entries */
|
/* build GOT and PLT entries */
|
||||||
ST_FUNC void build_got_entries(TCCState *s1)
|
static void build_got_entries_pass(TCCState *s1, int pass)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
@ -1235,6 +1242,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
|
|||||||
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
||||||
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
||||||
s1->output_type == TCC_OUTPUT_EXE)) {
|
s1->output_type == TCC_OUTPUT_EXE)) {
|
||||||
|
if (pass == 0)
|
||||||
|
continue;
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1248,6 +1257,11 @@ ST_FUNC void build_got_entries(TCCState *s1)
|
|||||||
} else
|
} else
|
||||||
reloc_type = R_GLOB_DAT;
|
reloc_type = R_GLOB_DAT;
|
||||||
|
|
||||||
|
|
||||||
|
if ((pass == 0 && reloc_type == R_GLOB_DAT) ||
|
||||||
|
(pass == 1 && reloc_type == R_JMP_SLOT))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!s1->got)
|
if (!s1->got)
|
||||||
build_got(s1);
|
build_got(s1);
|
||||||
|
|
||||||
@ -1261,6 +1275,16 @@ ST_FUNC void build_got_entries(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void build_got_entries(TCCState *s1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Two passes because R_JMP_SLOT should become first.
|
||||||
|
Some targets (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
build_got_entries_pass(s1, i);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
|
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
|
||||||
@ -1801,7 +1825,7 @@ struct dyn_inf {
|
|||||||
unsigned long data_offset;
|
unsigned long data_offset;
|
||||||
addr_t rel_addr;
|
addr_t rel_addr;
|
||||||
addr_t rel_size;
|
addr_t rel_size;
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||||
addr_t bss_addr;
|
addr_t bss_addr;
|
||||||
addr_t bss_size;
|
addr_t bss_size;
|
||||||
#endif
|
#endif
|
||||||
@ -1861,11 +1885,13 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
|||||||
|
|
||||||
/* dynamic relocation table information, for .dynamic section */
|
/* dynamic relocation table information, for .dynamic section */
|
||||||
dyninf->rel_addr = dyninf->rel_size = 0;
|
dyninf->rel_addr = dyninf->rel_size = 0;
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||||
dyninf->bss_addr = dyninf->bss_size = 0;
|
dyninf->bss_addr = dyninf->bss_size = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(j = 0; j < (phnum == 6 ? 3 : 2); j++) {
|
for(j = 0; j < (phnum == 6 ? 3 : 2); j++) {
|
||||||
|
Section *relocplt = s1->got ? s1->got->relocplt : NULL;
|
||||||
|
|
||||||
ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
|
ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
ph->p_flags = PF_R | PF_X;
|
ph->p_flags = PF_R | PF_X;
|
||||||
@ -1878,7 +1904,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
|||||||
info about the layout. We do the following ordering: interp,
|
info about the layout. We do the following ordering: interp,
|
||||||
symbol tables, relocations, progbits, nobits */
|
symbol tables, relocations, progbits, nobits */
|
||||||
/* XXX: do faster and simpler sorting */
|
/* XXX: do faster and simpler sorting */
|
||||||
for(k = 0; k < 5; k++) {
|
for(k = 0; k < 6; k++) {
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
/* compute if section should be included */
|
/* compute if section should be included */
|
||||||
@ -1905,13 +1931,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
|||||||
if (k != 1)
|
if (k != 1)
|
||||||
continue;
|
continue;
|
||||||
} else if (s->sh_type == SHT_RELX) {
|
} else if (s->sh_type == SHT_RELX) {
|
||||||
if (k != 2)
|
if (k != 2 && s != relocplt)
|
||||||
|
continue;
|
||||||
|
else if (k != 3 && s == relocplt)
|
||||||
continue;
|
continue;
|
||||||
} else if (s->sh_type == SHT_NOBITS) {
|
} else if (s->sh_type == SHT_NOBITS) {
|
||||||
if (k != 4)
|
if (k != 5)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (k != 3)
|
if (k != 4)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sec_order[sh_order_index++] = i;
|
sec_order[sh_order_index++] = i;
|
||||||
@ -1931,8 +1959,8 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
|||||||
ph->p_paddr = ph->p_vaddr;
|
ph->p_paddr = ph->p_vaddr;
|
||||||
}
|
}
|
||||||
/* update dynamic relocation infos */
|
/* update dynamic relocation infos */
|
||||||
if (s->sh_type == SHT_RELX) {
|
if (s->sh_type == SHT_RELX && s != relocplt) {
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||||
if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
|
if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
|
||||||
dyninf->rel_addr = addr;
|
dyninf->rel_addr = addr;
|
||||||
dyninf->rel_size += s->sh_size; /* XXX only first rel. */
|
dyninf->rel_size += s->sh_size; /* XXX only first rel. */
|
||||||
@ -2079,16 +2107,17 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
|||||||
put_dt(dynamic, DT_RELA, dyninf->rel_addr);
|
put_dt(dynamic, DT_RELA, dyninf->rel_addr);
|
||||||
put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
|
put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
|
||||||
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
|
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
|
||||||
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
if (s1->got && s1->got->relocplt) {
|
||||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
|
put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset);
|
||||||
put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
|
put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTREL, DT_RELA);
|
put_dt(dynamic, DT_PLTREL, DT_RELA);
|
||||||
put_dt(dynamic, DT_BIND_NOW, 1); /* Dirty hack */
|
}
|
||||||
#endif
|
put_dt(dynamic, DT_RELACOUNT, 0);
|
||||||
#else
|
#else
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
if (s1->got)
|
||||||
|
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
|
put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
|
||||||
put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
|
put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
|
||||||
put_dt(dynamic, DT_PLTREL, DT_REL);
|
put_dt(dynamic, DT_PLTREL, DT_REL);
|
||||||
@ -2098,11 +2127,18 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
|||||||
put_dt(dynamic, DT_REL, dyninf->rel_addr);
|
put_dt(dynamic, DT_REL, dyninf->rel_addr);
|
||||||
put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
|
put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
|
||||||
put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
|
put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
|
||||||
|
if (s1->got && s1->got->relocplt) {
|
||||||
|
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||||
|
put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset);
|
||||||
|
put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr);
|
||||||
|
put_dt(dynamic, DT_PLTREL, DT_REL);
|
||||||
|
}
|
||||||
|
put_dt(dynamic, DT_RELCOUNT, 0);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (versym_section)
|
if (versym_section && verneed_section) {
|
||||||
|
/* The dynamic linker can not handle VERSYM without VERNEED */
|
||||||
put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
|
put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
|
||||||
if (verneed_section) {
|
|
||||||
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
||||||
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
||||||
}
|
}
|
||||||
@ -2406,10 +2442,12 @@ static void create_arm_attribute_section(TCCState *s1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARGETOS_OpenBSD
|
#if TARGETOS_OpenBSD || TARGETOS_NetBSD
|
||||||
static Section *create_openbsd_note_section(TCCState *s1)
|
static Section *create_bsd_note_section(TCCState *s1,
|
||||||
|
const char *name,
|
||||||
|
const char *value)
|
||||||
{
|
{
|
||||||
Section *s = find_section (s1, ".note.openbsd.ident");
|
Section *s = find_section (s1, name);
|
||||||
|
|
||||||
if (s->data_offset == 0) {
|
if (s->data_offset == 0) {
|
||||||
unsigned char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
|
unsigned char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
|
||||||
@ -2419,7 +2457,7 @@ static Section *create_openbsd_note_section(TCCState *s1)
|
|||||||
note->n_namesz = 8;
|
note->n_namesz = 8;
|
||||||
note->n_descsz = 4;
|
note->n_descsz = 4;
|
||||||
note->n_type = ELF_NOTE_OS_GNU;
|
note->n_type = ELF_NOTE_OS_GNU;
|
||||||
strcpy (ptr + sizeof(ElfW(Nhdr)), "OpenBSD");
|
strcpy (ptr + sizeof(ElfW(Nhdr)), value);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -2441,7 +2479,11 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
#endif
|
#endif
|
||||||
#if TARGETOS_OpenBSD
|
#if TARGETOS_OpenBSD
|
||||||
if (file_type != TCC_OUTPUT_OBJ)
|
if (file_type != TCC_OUTPUT_OBJ)
|
||||||
note = create_openbsd_note_section (s1);
|
note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
|
||||||
|
#endif
|
||||||
|
#if TARGETOS_NetBSD
|
||||||
|
if (file_type != TCC_OUTPUT_OBJ)
|
||||||
|
note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
@ -2814,8 +2856,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
|
|||||||
sm_table[i].new_section = 1;
|
sm_table[i].new_section = 1;
|
||||||
found:
|
found:
|
||||||
if (sh->sh_type != s->sh_type) {
|
if (sh->sh_type != s->sh_type) {
|
||||||
tcc_error_noabort("invalid section type");
|
#if TARGETOS_OpenBSD
|
||||||
goto fail;
|
if (strcmp (s->name, ".eh_frame") || sh->sh_type != SHT_PROGBITS)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
tcc_error_noabort("invalid section type");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* align start of section */
|
/* align start of section */
|
||||||
s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
|
s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
|
||||||
|
@ -61,6 +61,9 @@ endif
|
|||||||
ifeq ($(CC_NAME),msvc)
|
ifeq ($(CC_NAME),msvc)
|
||||||
test.ref abitest : CC = gcc
|
test.ref abitest : CC = gcc
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(TARGETOS),OpenBSD)
|
||||||
|
dlltest: CFLAGS+=-fno-stack-protector
|
||||||
|
endif
|
||||||
|
|
||||||
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||||
DISAS = objdump -d
|
DISAS = objdump -d
|
||||||
|
@ -48,6 +48,10 @@ ifeq (-$(CONFIG_WIN32)-,-yes-)
|
|||||||
SKIP += 106_pthread.test # No pthread support
|
SKIP += 106_pthread.test # No pthread support
|
||||||
SKIP += 114_bound_signal.test # No pthread support
|
SKIP += 114_bound_signal.test # No pthread support
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
|
||||||
|
SKIP += 106_pthread.test # no pthread_condattr_setpshared
|
||||||
|
SKIP += 114_bound_signal.test # libc problem signal/fork
|
||||||
|
endif
|
||||||
|
|
||||||
# Some tests might need arguments
|
# Some tests might need arguments
|
||||||
ARGS =
|
ARGS =
|
||||||
|
@ -131,7 +131,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 PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
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 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 16);
|
||||||
@ -140,7 +140,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
write32le(p + 2, got_offset);
|
write32le(p + 2, got_offset);
|
||||||
p[6] = 0x68; /* push $xxx */
|
p[6] = 0x68; /* push $xxx */
|
||||||
/* On x86-64, the relocation is referred to by _index_ */
|
/* On x86-64, the relocation is referred to by _index_ */
|
||||||
write32le(p + 7, relofs / sizeof (ElfW_Rel));
|
write32le(p + 7, relofs / sizeof (ElfW_Rel) - 1);
|
||||||
p[11] = 0xe9; /* jmp plt_start */
|
p[11] = 0xe9; /* jmp plt_start */
|
||||||
write32le(p + 12, -(plt->data_offset));
|
write32le(p + 12, -(plt->data_offset));
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
@ -168,6 +168,20 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 16;
|
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];
|
||||||
|
write64le(p + rel->r_offset, mem ? sym->st_value : x);
|
||||||
|
x += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user