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) {
|
||||
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;
|
||||
while (p < p_end) {
|
||||
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
||||
@ -157,6 +157,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
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
|
||||
|
||||
|
15
arm64-link.c
15
arm64-link.c
@ -113,7 +113,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
|
||||
if (p < p_end) {
|
||||
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);
|
||||
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);
|
||||
@ -129,6 +129,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
write32le(p + 24, 0xd503201f); // nop
|
||||
write32le(p + 28, 0xd503201f); // nop
|
||||
p += 32;
|
||||
got = s1->got->sh_addr;
|
||||
while (p < p_end) {
|
||||
uint64_t pc = plt + (p - s1->plt->data);
|
||||
uint64_t addr = got + read64le(p);
|
||||
@ -145,6 +146,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
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)
|
||||
|
22
i386-link.c
22
i386-link.c
@ -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
|
||||
|
||||
|
@ -1153,7 +1153,8 @@ void __attribute__((destructor)) __bound_exit(void)
|
||||
dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
|
||||
|
||||
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) {
|
||||
extern void __libc_freeres (void);
|
||||
__libc_freeres ();
|
||||
|
@ -153,6 +153,18 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
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,
|
||||
|
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 SHT_RELX SHT_RELA
|
||||
# define REL_SECTION_FMT ".rela%s"
|
||||
# define RELPLT_SECTION_FMT ".rel.plt"
|
||||
#else
|
||||
# define ELFCLASSW ELFCLASS32
|
||||
# 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 SHT_RELX SHT_REL
|
||||
# define REL_SECTION_FMT ".rel%s"
|
||||
# define RELPLT_SECTION_FMT ".rel.plt"
|
||||
#endif
|
||||
/* target address type */
|
||||
#define addr_t ElfW(Addr)
|
||||
@ -565,6 +567,7 @@ typedef struct Section {
|
||||
struct Section *reloc; /* corresponding section for relocation, if any */
|
||||
struct Section *hash; /* hash table for symbols */
|
||||
struct Section *prev; /* previous section on section stack */
|
||||
struct Section *relocplt;/* reloc with JMP_SLOTs */
|
||||
char name[1]; /* section name */
|
||||
} 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];
|
||||
Section *sr;
|
||||
ElfW_Rel *rel;
|
||||
int jmp_slot = type == R_JMP_SLOT;
|
||||
|
||||
sr = s->reloc;
|
||||
sr = jmp_slot ? s->relocplt : s->reloc;
|
||||
if (!sr) {
|
||||
/* 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
|
||||
are also */
|
||||
sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
|
||||
sr->sh_entsize = sizeof(ElfW_Rel);
|
||||
sr->link = symtab;
|
||||
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->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 */
|
||||
ST_FUNC void build_got_entries(TCCState *s1)
|
||||
static void build_got_entries_pass(TCCState *s1, int pass)
|
||||
{
|
||||
Section *s;
|
||||
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_BIND)(sym->st_info) == STB_LOCAL ||
|
||||
s1->output_type == TCC_OUTPUT_EXE)) {
|
||||
if (pass == 0)
|
||||
continue;
|
||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
||||
continue;
|
||||
}
|
||||
@ -1248,6 +1257,11 @@ ST_FUNC void build_got_entries(TCCState *s1)
|
||||
} else
|
||||
reloc_type = R_GLOB_DAT;
|
||||
|
||||
|
||||
if ((pass == 0 && reloc_type == R_GLOB_DAT) ||
|
||||
(pass == 1 && reloc_type == R_JMP_SLOT))
|
||||
continue;
|
||||
|
||||
if (!s1->got)
|
||||
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
|
||||
|
||||
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;
|
||||
addr_t rel_addr;
|
||||
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_size;
|
||||
#endif
|
||||
@ -1861,11 +1885,13 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
||||
|
||||
/* dynamic relocation table information, for .dynamic section */
|
||||
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;
|
||||
#endif
|
||||
|
||||
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;
|
||||
if (j == 0)
|
||||
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,
|
||||
symbol tables, relocations, progbits, nobits */
|
||||
/* 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++) {
|
||||
s = s1->sections[i];
|
||||
/* compute if section should be included */
|
||||
@ -1905,13 +1931,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
|
||||
if (k != 1)
|
||||
continue;
|
||||
} else if (s->sh_type == SHT_RELX) {
|
||||
if (k != 2)
|
||||
if (k != 2 && s != relocplt)
|
||||
continue;
|
||||
else if (k != 3 && s == relocplt)
|
||||
continue;
|
||||
} else if (s->sh_type == SHT_NOBITS) {
|
||||
if (k != 4)
|
||||
if (k != 5)
|
||||
continue;
|
||||
} else {
|
||||
if (k != 3)
|
||||
if (k != 4)
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* update dynamic relocation infos */
|
||||
if (s->sh_type == SHT_RELX) {
|
||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
||||
if (s->sh_type == SHT_RELX && s != relocplt) {
|
||||
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||
if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
|
||||
dyninf->rel_addr = addr;
|
||||
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_RELASZ, dyninf->rel_size);
|
||||
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
|
||||
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||
put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
|
||||
put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
|
||||
put_dt(dynamic, DT_PLTREL, DT_RELA);
|
||||
put_dt(dynamic, DT_BIND_NOW, 1); /* Dirty hack */
|
||||
#endif
|
||||
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_RELA);
|
||||
}
|
||||
put_dt(dynamic, DT_RELACOUNT, 0);
|
||||
#else
|
||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||
#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel)
|
||||
if (s1->got)
|
||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||
put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
|
||||
put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
|
||||
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_RELSZ, dyninf->rel_size);
|
||||
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
|
||||
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);
|
||||
if (verneed_section) {
|
||||
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
||||
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
||||
}
|
||||
@ -2406,10 +2442,12 @@ static void create_arm_attribute_section(TCCState *s1)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGETOS_OpenBSD
|
||||
static Section *create_openbsd_note_section(TCCState *s1)
|
||||
#if TARGETOS_OpenBSD || TARGETOS_NetBSD
|
||||
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) {
|
||||
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_descsz = 4;
|
||||
note->n_type = ELF_NOTE_OS_GNU;
|
||||
strcpy (ptr + sizeof(ElfW(Nhdr)), "OpenBSD");
|
||||
strcpy (ptr + sizeof(ElfW(Nhdr)), value);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -2441,7 +2479,11 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
#endif
|
||||
#if TARGETOS_OpenBSD
|
||||
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
|
||||
|
||||
s1->nb_errors = 0;
|
||||
@ -2814,8 +2856,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
|
||||
sm_table[i].new_section = 1;
|
||||
found:
|
||||
if (sh->sh_type != s->sh_type) {
|
||||
tcc_error_noabort("invalid section type");
|
||||
goto fail;
|
||||
#if TARGETOS_OpenBSD
|
||||
if (strcmp (s->name, ".eh_frame") || sh->sh_type != SHT_PROGBITS)
|
||||
#endif
|
||||
{
|
||||
tcc_error_noabort("invalid section type");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* align start of section */
|
||||
s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
|
||||
|
@ -61,6 +61,9 @@ endif
|
||||
ifeq ($(CC_NAME),msvc)
|
||||
test.ref abitest : CC = gcc
|
||||
endif
|
||||
ifeq ($(TARGETOS),OpenBSD)
|
||||
dlltest: CFLAGS+=-fno-stack-protector
|
||||
endif
|
||||
|
||||
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||
DISAS = objdump -d
|
||||
|
@ -48,6 +48,10 @@ ifeq (-$(CONFIG_WIN32)-,-yes-)
|
||||
SKIP += 106_pthread.test # No pthread support
|
||||
SKIP += 114_bound_signal.test # No pthread support
|
||||
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
|
||||
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 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);
|
||||
@ -140,7 +140,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
||||
write32le(p + 2, got_offset);
|
||||
p[6] = 0x68; /* push $xxx */
|
||||
/* 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 */
|
||||
write32le(p + 12, -(plt->data_offset));
|
||||
return plt_offset;
|
||||
@ -168,6 +168,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];
|
||||
write64le(p + rel->r_offset, mem ? sym->st_value : x);
|
||||
x += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user