mirror of
git://repo.or.cz/tinycc.git
synced 2026-11-04 21:26:36 +08:00
tccelf: rework linker_sym (_end/end) logic
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-arm64-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
build and test / test-i386-linux (push) Has been cancelled
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-arm64-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
build and test / test-i386-linux (push) Has been cancelled
- tcc_add_linker_symbols():
don't add for dlls
- bind_exe_dynsym():
update _end symbol when done
allow data definition in the .so override a bss symbol
in the exe. For example
exe: int x;
.so: int x = 123;
- set_elf_sym():
cannot compare section numbers with symbols from dlls
tcc_load_obj():
return -1 from symbol conflict errors
tests/tests2/148_linker_symbols:
- use only one file
- make it print useful output rather than just "2 errors."
In general, the tests2 setup with .expect files is meant
to compare text output. For example:
printf("val = %d\n", val);
.expect file can be generated or refreshed using
make tests2.nnn+
or in order to force generation with tcc itself
make tests2.nnn+ GEN-CC='$(GEN-TCC)'
tccgen.c:
- __attribute__((section(...))) : set section type/flags
according to first usage
- fix bcheck bounds for -fcommon
This commit is contained in:
parent
128e78930e
commit
64552b3faa
2
Makefile
2
Makefile
@ -336,7 +336,7 @@ FORCE:
|
|||||||
# some versions of gnu-make do not recognize 'command' as a shell builtin
|
# some versions of gnu-make do not recognize 'command' as a shell builtin
|
||||||
WHICH = sh -c 'command -v $1'
|
WHICH = sh -c 'command -v $1'
|
||||||
|
|
||||||
run-if = $(if $(shell $(call WHICH,$1)),$S $1 $2,echo "(skipping $@ - no $1)")
|
run-if = $(if $(shell $(call WHICH,$1)),$S $1 $2,@echo "(skipping $@ - no $1)")
|
||||||
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
|
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|||||||
1
tcc.h
1
tcc.h
@ -675,6 +675,7 @@ typedef struct AttributeDef {
|
|||||||
int alias_target; /* token */
|
int alias_target; /* token */
|
||||||
int asm_label; /* associated asm label */
|
int asm_label; /* associated asm label */
|
||||||
char attr_mode; /* __attribute__((__mode__(...))) */
|
char attr_mode; /* __attribute__((__mode__(...))) */
|
||||||
|
char new_section; /* section is new */
|
||||||
} AttributeDef;
|
} AttributeDef;
|
||||||
|
|
||||||
/* inline functions */
|
/* inline functions */
|
||||||
|
|||||||
180
tccelf.c
180
tccelf.c
@ -742,6 +742,8 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
|
|||||||
/* keep first-found weak definition, ignore subsequents */
|
/* keep first-found weak definition, ignore subsequents */
|
||||||
} else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
|
} else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
|
||||||
/* ignore hidden symbols after */
|
/* ignore hidden symbols after */
|
||||||
|
} else if (s->sh_flags & SHF_DYNSYM) {
|
||||||
|
/* we accept that two DLL define the same symbol */
|
||||||
} else if ((esym->st_shndx == SHN_COMMON
|
} else if ((esym->st_shndx == SHN_COMMON
|
||||||
|| esym->st_shndx == bss_section->sh_num)
|
|| esym->st_shndx == bss_section->sh_num)
|
||||||
&& (shndx < SHN_LORESERVE
|
&& (shndx < SHN_LORESERVE
|
||||||
@ -750,8 +752,6 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
|
|||||||
goto do_patch;
|
goto do_patch;
|
||||||
} else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) {
|
} else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) {
|
||||||
/* data symbol keeps precedence over common/bss */
|
/* data symbol keeps precedence over common/bss */
|
||||||
} else if (s->sh_flags & SHF_DYNSYM) {
|
|
||||||
/* we accept that two DLL define the same symbol */
|
|
||||||
} else if (esym->st_other & ST_ASM_SET) {
|
} else if (esym->st_other & ST_ASM_SET) {
|
||||||
/* If the existing symbol came from an asm .set
|
/* If the existing symbol came from an asm .set
|
||||||
we can override. */
|
we can override. */
|
||||||
@ -761,7 +761,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
|
|||||||
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
|
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
|
||||||
sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis);
|
sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis);
|
||||||
#endif
|
#endif
|
||||||
tcc_error_noabort("'%s' defined twice", name);
|
tcc_error_noabort("link symbol '%s' defined twice", name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
esym->st_other = other;
|
esym->st_other = other;
|
||||||
@ -1560,94 +1560,6 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
|
|||||||
ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
|
ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
static int set_linker_sym(TCCState *s1, const char *name,
|
|
||||||
Section *sec, addr_t offs)
|
|
||||||
{
|
|
||||||
int sym_index = find_elf_sym(symtab_section, name);
|
|
||||||
ElfW(Sym) *sym = sym_index
|
|
||||||
? &((ElfW(Sym) *)symtab_section->data)[sym_index] : NULL;
|
|
||||||
/* Mirror the set_elf_sym cases where the new definition wins. */
|
|
||||||
int is_linker_sym = !sym || sym->st_shndx == SHN_UNDEF
|
|
||||||
|| ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
|
||||||
|| (sec && sec != bss_section
|
|
||||||
&& ((sym->st_other & ST_ASM_SET)
|
|
||||||
|| sym->st_shndx == SHN_COMMON
|
|
||||||
|| sym->st_shndx == bss_section->sh_num));
|
|
||||||
|
|
||||||
sym_index = set_global_sym(s1, name, sec, offs);
|
|
||||||
if (is_linker_sym)
|
|
||||||
get_sym_attr(s1, sym_index, 1)->linker_sym = 1;
|
|
||||||
return sym_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void provide_linker_sym(TCCState *s1, const char *name,
|
|
||||||
Section *sec, addr_t offs)
|
|
||||||
{
|
|
||||||
int sym_index = find_elf_sym(symtab_section, name);
|
|
||||||
|
|
||||||
if (sym_index) {
|
|
||||||
if (((ElfW(Sym) *)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF)
|
|
||||||
return;
|
|
||||||
} else if (!s1->dynsymtab_section
|
|
||||||
|| !find_elf_sym(s1->dynsymtab_section, name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
set_linker_sym(s1, name, sec, offs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_linker_sym(TCCState *s1, const char *name,
|
|
||||||
Section *sec, addr_t offs)
|
|
||||||
{
|
|
||||||
int sym_index = find_elf_sym(symtab_section, name);
|
|
||||||
|
|
||||||
if (sym_index && sym_index < s1->nb_sym_attrs
|
|
||||||
&& s1->sym_attrs[sym_index].linker_sym) {
|
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
|
|
||||||
sym->st_value = offs;
|
|
||||||
sym->st_shndx = sec->sh_num;
|
|
||||||
if (s1->dynsym) {
|
|
||||||
sym_index = find_elf_sym(s1->dynsym, name);
|
|
||||||
if (sym_index) {
|
|
||||||
sym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
|
|
||||||
sym->st_value = offs;
|
|
||||||
sym->st_shndx = sec->sh_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void finalize_linker_symbols(TCCState *s1, int *sec_order)
|
|
||||||
{
|
|
||||||
Section *etext = text_section;
|
|
||||||
Section *edata = data_section;
|
|
||||||
Section *end = bss_section;
|
|
||||||
Section *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Follow the final loadable-section order rather than assuming that
|
|
||||||
.text, .data and .bss are the last sections of their regions. */
|
|
||||||
for (i = 1; i < s1->nb_sections; ++i) {
|
|
||||||
s = s1->sections[sec_order[i]];
|
|
||||||
if (!(s->sh_flags & SHF_ALLOC))
|
|
||||||
continue;
|
|
||||||
end = s;
|
|
||||||
if (!(s->sh_flags & SHF_WRITE))
|
|
||||||
etext = s;
|
|
||||||
if (s->sh_type != SHT_NOBITS)
|
|
||||||
edata = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_linker_sym(s1, "_etext", etext, etext->sh_size);
|
|
||||||
update_linker_sym(s1, "etext", etext, etext->sh_size);
|
|
||||||
update_linker_sym(s1, "_edata", edata, edata->sh_size);
|
|
||||||
update_linker_sym(s1, "edata", edata, edata->sh_size);
|
|
||||||
update_linker_sym(s1, "_end", end, end->sh_size);
|
|
||||||
update_linker_sym(s1, "end", end, end->sh_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void add_init_array_defines(TCCState *s1, const char *section_name)
|
static void add_init_array_defines(TCCState *s1, const char *section_name)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
@ -1963,6 +1875,39 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||||||
}
|
}
|
||||||
#endif /* ndef TCC_TARGET_PE */
|
#endif /* ndef TCC_TARGET_PE */
|
||||||
|
|
||||||
|
/* set _etext/_edata/_end f=0:set f=1:when_needed f=2,3:just_update */
|
||||||
|
static void set_linker_sym(TCCState *s1, const char *name, Section *sec, int f)
|
||||||
|
{
|
||||||
|
int sym_index, esym_index, defined;
|
||||||
|
ElfW(Sym) *sym, *esym;
|
||||||
|
sym_index = find_elf_sym(symtab_section, name);
|
||||||
|
sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
||||||
|
esym_index = find_elf_sym(s1->dynsymtab_section, name);
|
||||||
|
esym = (ElfW(Sym) *)s1->dynsymtab_section->data + esym_index;
|
||||||
|
defined = sym->st_shndx != SHN_UNDEF
|
||||||
|
|| (esym->st_shndx != SHN_UNDEF && esym->st_size);
|
||||||
|
switch (f) {
|
||||||
|
case 1: /* old symbols w/o '_' */
|
||||||
|
if (!(sym_index || esym_index) || defined)
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
if (defined) {
|
||||||
|
tcc_warning("linker symbol '%s' already defined", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sym_index = set_global_sym(s1, name, sec, -1);
|
||||||
|
get_sym_attr(s1, sym_index, 1)->linker_sym = 1;
|
||||||
|
break;
|
||||||
|
default: /* update (bss only) */
|
||||||
|
if (get_sym_attr(s1, sym_index, 0)->linker_sym)
|
||||||
|
sym->st_value = sec->data_offset;
|
||||||
|
}
|
||||||
|
#ifndef ELF_OBJ_ONLY
|
||||||
|
if (name[0] == '_')
|
||||||
|
set_linker_sym(s1, name + 1, sec, f + 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* add various standard linker symbols (must be done after the
|
/* add various standard linker symbols (must be done after the
|
||||||
sections are filled (for example after allocating common
|
sections are filled (for example after allocating common
|
||||||
symbols)) */
|
symbols)) */
|
||||||
@ -1972,22 +1917,13 @@ static void tcc_add_linker_symbols(TCCState *s1)
|
|||||||
int i;
|
int i;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
set_linker_sym(s1, "_etext", text_section, 0);
|
||||||
set_linker_sym(s1, "_etext", text_section, -1);
|
set_linker_sym(s1, "_edata", data_section, 0);
|
||||||
set_linker_sym(s1, "_edata", data_section, -1);
|
set_linker_sym(s1, "_end", bss_section, 0);
|
||||||
set_linker_sym(s1, "_end", bss_section, -1);
|
|
||||||
/* These conventional ELF symbols have PROVIDE semantics. */
|
|
||||||
provide_linker_sym(s1, "etext", text_section, -1);
|
|
||||||
provide_linker_sym(s1, "edata", data_section, -1);
|
|
||||||
provide_linker_sym(s1, "end", bss_section, -1);
|
|
||||||
#else
|
|
||||||
set_global_sym(s1, "_etext", text_section, -1);
|
|
||||||
set_global_sym(s1, "_edata", data_section, -1);
|
|
||||||
set_global_sym(s1, "_end", bss_section, -1);
|
|
||||||
#endif
|
|
||||||
#if TARGETOS_OpenBSD
|
#if TARGETOS_OpenBSD
|
||||||
set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
|
set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
#ifdef TCC_TARGET_RISCV64
|
||||||
/* XXX should be .sdata+0x800, not .data+0x800 */
|
/* XXX should be .sdata+0x800, not .data+0x800 */
|
||||||
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
|
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
|
||||||
@ -2032,7 +1968,7 @@ ST_FUNC void resolve_common_syms(TCCState *s1)
|
|||||||
|
|
||||||
/* Allocate common symbols in BSS. */
|
/* Allocate common symbols in BSS. */
|
||||||
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
if (sym->st_shndx == SHN_COMMON) {
|
if (sym->st_shndx == SHN_COMMON && sym->st_size) {
|
||||||
/* symbol alignment is in st_value for SHN_COMMONs */
|
/* symbol alignment is in st_value for SHN_COMMONs */
|
||||||
sym->st_value = section_add(bss_section, sym->st_size,
|
sym->st_value = section_add(bss_section, sym->st_size,
|
||||||
sym->st_value);
|
sym->st_value);
|
||||||
@ -2041,7 +1977,8 @@ ST_FUNC void resolve_common_syms(TCCState *s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now assign linker provided symbols their value. */
|
/* Now assign linker provided symbols their value. */
|
||||||
tcc_add_linker_symbols(s1);
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_linker_symbols(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
@ -2129,13 +2066,16 @@ static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
|
|||||||
- if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
|
- if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
|
||||||
- if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
|
- if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
|
||||||
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|
/* bss symbols may be initialized in the shared library */
|
||||||
|
|| sym->st_shndx == SHN_COMMON
|
||||||
|
|| sym->st_shndx == bss_section->sh_num) {
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
sym_index = find_elf_sym(s1->dynsymtab_section, name);
|
sym_index = find_elf_sym(s1->dynsymtab_section, name);
|
||||||
if (sym_index) {
|
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
|
||||||
|
if (sym_index && esym->st_shndx != SHN_UNDEF) {
|
||||||
if (is_PIE)
|
if (is_PIE)
|
||||||
continue;
|
continue;
|
||||||
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
|
|
||||||
type = ELFW(ST_TYPE)(esym->st_info);
|
type = ELFW(ST_TYPE)(esym->st_info);
|
||||||
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
|
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
|
||||||
/* Indirect functions shall have STT_FUNC type in executable
|
/* Indirect functions shall have STT_FUNC type in executable
|
||||||
@ -2154,15 +2094,19 @@ static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
|
|||||||
} else if (type == STT_OBJECT) {
|
} else if (type == STT_OBJECT) {
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
ElfW(Sym) *dynsym;
|
ElfW(Sym) *dynsym;
|
||||||
offset = bss_section->data_offset;
|
if (sym->st_shndx == bss_section->sh_num) {
|
||||||
/* XXX: which alignment ? */
|
offset = sym->st_value;
|
||||||
offset = (offset + 16 - 1) & -16;
|
} else {
|
||||||
|
offset = bss_section->data_offset;
|
||||||
|
/* XXX: which alignment ? */
|
||||||
|
offset = (offset + 16 - 1) & -16;
|
||||||
|
bss_section->data_offset = offset + esym->st_size;
|
||||||
|
}
|
||||||
set_elf_sym (s1->symtab, offset, esym->st_size,
|
set_elf_sym (s1->symtab, offset, esym->st_size,
|
||||||
esym->st_info, 0, bss_section->sh_num, name);
|
esym->st_info, 0, bss_section->sh_num, name);
|
||||||
index = put_elf_sym(s1->dynsym, offset, esym->st_size,
|
index = put_elf_sym(s1->dynsym, offset, esym->st_size,
|
||||||
esym->st_info, 0, bss_section->sh_num,
|
esym->st_info, 0, bss_section->sh_num,
|
||||||
name);
|
name);
|
||||||
|
|
||||||
/* Ensure R_COPY works for weak symbol aliases */
|
/* Ensure R_COPY works for weak symbol aliases */
|
||||||
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
|
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
|
||||||
for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
|
for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
|
||||||
@ -2177,13 +2121,10 @@ static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
put_elf_reloc(s1->dynsym, bss_section,
|
put_elf_reloc(s1->dynsym, bss_section,
|
||||||
offset, R_COPY, index);
|
offset, R_COPY, index);
|
||||||
offset += esym->st_size;
|
|
||||||
bss_section->data_offset = offset;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (sym->st_shndx == SHN_UNDEF) {
|
||||||
/* STB_WEAK undefined symbols are accepted */
|
/* STB_WEAK undefined symbols are accepted */
|
||||||
/* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
|
/* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
|
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
|
||||||
@ -2194,6 +2135,8 @@ static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* update _end symbol with new bss length */
|
||||||
|
set_linker_sym(s1, "_end", bss_section, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bind symbols of libraries: export all non local symbols of executable that
|
/* Bind symbols of libraries: export all non local symbols of executable that
|
||||||
@ -3179,7 +3122,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
|
sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
|
||||||
/* compute section to program header mapping */
|
/* compute section to program header mapping */
|
||||||
layout_sections(s1, sec_order, &dyninf);
|
layout_sections(s1, sec_order, &dyninf);
|
||||||
finalize_linker_symbols(s1, sec_order);
|
|
||||||
|
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
/* put in GOT the dynamic section address and relocate PLT */
|
/* put in GOT the dynamic section address and relocate PLT */
|
||||||
@ -3627,7 +3569,7 @@ invalid:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
ret = 0;
|
ret = !s1->nb_errors - 1; /* errors possibly from set_elf_sym() */
|
||||||
the_end:
|
the_end:
|
||||||
tcc_free(symtab);
|
tcc_free(symtab);
|
||||||
tcc_free(strtab);
|
tcc_free(strtab);
|
||||||
|
|||||||
43
tccgen.c
43
tccgen.c
@ -3966,7 +3966,9 @@ redo:
|
|||||||
case TOK_SECTION2:
|
case TOK_SECTION2:
|
||||||
skip('(');
|
skip('(');
|
||||||
astr = parse_mult_str("section name")->data;
|
astr = parse_mult_str("section name")->data;
|
||||||
|
n = tcc_state->nb_sections;
|
||||||
ad->section = find_section(tcc_state, astr);
|
ad->section = find_section(tcc_state, astr);
|
||||||
|
ad->new_section = n < tcc_state->nb_sections;
|
||||||
skip(')');
|
skip(')');
|
||||||
break;
|
break;
|
||||||
case TOK_ALIAS1:
|
case TOK_ALIAS1:
|
||||||
@ -8393,17 +8395,21 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
vset(type, r, addr);
|
vset(type, r, addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
CType *tp = type;
|
||||||
|
int is_const;
|
||||||
|
|
||||||
|
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
||||||
|
tp = &tp->ref->type;
|
||||||
|
is_const = tp->t & VT_CONSTANT;
|
||||||
|
|
||||||
/* allocate symbol in corresponding section */
|
/* allocate symbol in corresponding section */
|
||||||
sec = ad->section;
|
sec = ad->section;
|
||||||
if (!sec) {
|
if (!sec) {
|
||||||
CType *tp = type;
|
|
||||||
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
|
||||||
tp = &tp->ref->type;
|
|
||||||
if (type->t & VT_TLS) {
|
if (type->t & VT_TLS) {
|
||||||
sec = find_section(tcc_state, has_init ? ".tdata" : ".tbss");
|
sec = find_section(tcc_state, has_init ? ".tdata" : ".tbss");
|
||||||
sec->sh_flags = SHF_ALLOC | SHF_WRITE | SHF_TLS;
|
sec->sh_flags = SHF_ALLOC | SHF_WRITE | SHF_TLS;
|
||||||
sec->sh_type = has_init ? SHT_PROGBITS : SHT_NOBITS;
|
sec->sh_type = has_init ? SHT_PROGBITS : SHT_NOBITS;
|
||||||
} else if (tp->t & VT_CONSTANT) {
|
} else if (is_const) {
|
||||||
sec = rodata_section;
|
sec = rodata_section;
|
||||||
} else if (has_init) {
|
} else if (has_init) {
|
||||||
sec = data_section;
|
sec = data_section;
|
||||||
@ -8411,15 +8417,21 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
|
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
|
||||||
} else if (tcc_state->nocommon)
|
} else if (tcc_state->nocommon)
|
||||||
sec = bss_section;
|
sec = bss_section;
|
||||||
|
} else if (ad->new_section) {
|
||||||
|
/* XXX: DWIM logic: set section flags according to first usage */
|
||||||
|
if (!is_const) {
|
||||||
|
sec->sh_flags |= SHF_WRITE;
|
||||||
|
if (!has_init)
|
||||||
|
sec->sh_type = SHT_NOBITS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (bcheck)
|
||||||
|
size = size + 1; /* add padding */
|
||||||
|
#endif
|
||||||
if (sec) {
|
if (sec) {
|
||||||
addr = section_add(sec, size, align);
|
addr = section_add(sec, size, align);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* add padding if bound check */
|
|
||||||
if (bcheck)
|
|
||||||
section_add(sec, 1, 1);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
addr = align; /* SHN_COMMON is special, symbol value is align */
|
addr = align; /* SHN_COMMON is special, symbol value is align */
|
||||||
sec = common_section;
|
sec = common_section;
|
||||||
@ -8449,7 +8461,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
/* then add global bound info */
|
/* then add global bound info */
|
||||||
bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t));
|
bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t));
|
||||||
bounds_ptr[0] = 0; /* relocated */
|
bounds_ptr[0] = 0; /* relocated */
|
||||||
bounds_ptr[1] = size;
|
bounds_ptr[1] = size - 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -8871,11 +8883,12 @@ static int decl(int l)
|
|||||||
skip_or_save_block(&fn->func_str);
|
skip_or_save_block(&fn->func_str);
|
||||||
} else {
|
} else {
|
||||||
/* compute text section */
|
/* compute text section */
|
||||||
cur_text_section = ad.section;
|
cur_text_section = text_section;
|
||||||
if (!cur_text_section)
|
if (ad.section) {
|
||||||
cur_text_section = text_section;
|
cur_text_section = ad.section;
|
||||||
else if (cur_text_section->sh_num > bss_section->sh_num)
|
if (ad.new_section)
|
||||||
cur_text_section->sh_flags = text_section->sh_flags;
|
ad.section->sh_flags = text_section->sh_flags;
|
||||||
|
}
|
||||||
gen_function(sym);
|
gen_function(sym);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -83,6 +84,17 @@ static void child_handler(int sig)
|
|||||||
sem_post (&sem_child);
|
sem_post (&sem_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned getclock_ms(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return GetTickCount();
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
@ -112,8 +124,8 @@ main (void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* sleep does not work !!! */
|
/* sleep does not work !!! */
|
||||||
end = time(NULL) + 2;
|
end = getclock_ms() + 200;
|
||||||
while (time(NULL) < end) ;
|
while (getclock_ms() < end) ;
|
||||||
run = 0;
|
run = 0;
|
||||||
|
|
||||||
pthread_join(id1, NULL);
|
pthread_join(id1, NULL);
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#define NR_THREADS 16
|
#define NR_THREADS 16
|
||||||
#define NR_STEPS ((uint32_t)UINT16_MAX)
|
#define NR_STEPS 10000
|
||||||
|
|
||||||
#define BUG_ON(COND) \
|
#define BUG_ON(COND) \
|
||||||
do { \
|
do { \
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
__thread signed short extern_tls_short = 1234;
|
|
||||||
__thread float extern_tls_float = 1.5f;
|
|
||||||
@ -1,7 +1,10 @@
|
|||||||
#include <stdio.h>
|
#ifdef DEFS
|
||||||
|
__thread signed short extern_tls_short = 1234;
|
||||||
|
__thread float extern_tls_float = 1.5f;
|
||||||
|
#else
|
||||||
extern __thread signed short extern_tls_short;
|
extern __thread signed short extern_tls_short;
|
||||||
extern __thread float extern_tls_float;
|
extern __thread float extern_tls_float;
|
||||||
|
int printf(const char *, ...);
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -20,3 +23,4 @@ int main(void)
|
|||||||
printf("extern tls errors: %d\n", errors);
|
printf("extern tls errors: %d\n", errors);
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
extern char etext[], _etext[];
|
|
||||||
extern char edata[], _edata[];
|
|
||||||
extern char end[], _end[];
|
|
||||||
|
|
||||||
int check_linker_symbols(void)
|
|
||||||
{
|
|
||||||
int errors = 0;
|
|
||||||
|
|
||||||
errors += etext != _etext;
|
|
||||||
errors += edata != _edata;
|
|
||||||
errors += end != _end;
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int etext(void) { return 1; }
|
|
||||||
int edata(void) { return 2; }
|
|
||||||
int end(void) { return 3; }
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int errors = etext() + edata() + end() != 6;
|
|
||||||
|
|
||||||
printf("user definitions errors: %d\n", errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1,11 +1,153 @@
|
|||||||
#include <stdio.h>
|
int printf(const char *, ...);
|
||||||
|
|
||||||
|
#define assert(x) ((x) \
|
||||||
|
? (printf(" 1 (%s)\n",#x),1) \
|
||||||
|
: (printf("%s:%d: error: (%s)\n",__FILE__,__LINE__,#x),0))
|
||||||
|
|
||||||
|
#define O 100
|
||||||
|
#define SO 200
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#if TEST-O == 1
|
||||||
|
extern char etext[], _etext[];
|
||||||
|
extern char edata[], _edata[];
|
||||||
|
extern char end[], _end[];
|
||||||
|
int check_linker_symbols(void)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
errors += !assert(etext == _etext);
|
||||||
|
errors += !assert(edata == _edata);
|
||||||
|
errors += !assert(end == _end);
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif TEST-MAIN == 1
|
||||||
int check_linker_symbols(void);
|
int check_linker_symbols(void);
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("linker symbols test\n");
|
||||||
|
assert(check_linker_symbols() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#elif TEST-SO == 2
|
||||||
|
extern char etext[], edata[], end[];
|
||||||
|
void get_dso_end(char **p)
|
||||||
|
{
|
||||||
|
p[0] = etext;
|
||||||
|
p[1] = edata;
|
||||||
|
p[2] = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif TEST-MAIN == 2
|
||||||
|
extern char _etext[], _edata[], _end[];
|
||||||
|
extern void get_dso_end(char **);
|
||||||
|
static int fill_data = 123;
|
||||||
|
static int fill_bss;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int errors = check_linker_symbols();
|
char *p[3];
|
||||||
|
printf("DSO linker symbols test\n");
|
||||||
printf("linker symbols errors: %d\n", errors);
|
get_dso_end(p);
|
||||||
return errors;
|
assert(p[0] == _etext) || printf("-- %p %p\n", p[0], _etext);
|
||||||
|
assert(p[1] == _edata) || printf("-- %p %p\n", p[1], _edata);
|
||||||
|
assert(p[2] == _end) || printf("-- %p %p\n", p[2], _end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#elif TEST-MAIN == 3
|
||||||
|
|
||||||
|
int etext(void) { return 1; }
|
||||||
|
int edata(void) { return 2; }
|
||||||
|
int end(void) { return 3; }
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("user definition test\n");
|
||||||
|
assert(etext() + edata() + end() == 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#elif TEST-SO == 4
|
||||||
|
unsigned char copy_reloc_data[257];
|
||||||
|
|
||||||
|
#elif TEST-MAIN == 4
|
||||||
|
extern unsigned char copy_reloc_data[257];
|
||||||
|
extern char end[], _end[];
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
unsigned long data_end;
|
||||||
|
printf("end copy relocation test\n");
|
||||||
|
copy_reloc_data[256] = 42;
|
||||||
|
data_end = (unsigned long)(copy_reloc_data + sizeof copy_reloc_data);
|
||||||
|
assert(end == _end);
|
||||||
|
assert((unsigned long)end >= data_end);
|
||||||
|
assert(copy_reloc_data[256] == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#elif TEST-O == 5
|
||||||
|
void __attribute__((section(".text.linker_test"), noinline, used))
|
||||||
|
linker_test_text(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
__attribute__((section(".bss.linker_test"), used))
|
||||||
|
unsigned char linker_test_bss[257];
|
||||||
|
|
||||||
|
__attribute__((section(".data.linker_test"), used))
|
||||||
|
unsigned char linker_test_data[23] = { 1 };
|
||||||
|
|
||||||
|
#elif TEST-MAIN == 5
|
||||||
|
extern void linker_test_text(void);
|
||||||
|
extern unsigned char linker_test_data[23];
|
||||||
|
extern unsigned char linker_test_bss[257];
|
||||||
|
extern char etext[], _etext[];
|
||||||
|
extern char edata[], _edata[];
|
||||||
|
extern char end[], _end[];
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char* text_addr = (void*)linker_test_text;
|
||||||
|
char* data_end = linker_test_data + sizeof linker_test_data;
|
||||||
|
char* bss_end = linker_test_bss + sizeof linker_test_bss;
|
||||||
|
|
||||||
|
printf("linker boundary test\n");
|
||||||
|
linker_test_data[22] = 42;
|
||||||
|
linker_test_bss[256] = 42;
|
||||||
|
assert(linker_test_bss > linker_test_data);
|
||||||
|
assert(etext == _etext);
|
||||||
|
assert(edata == _edata);
|
||||||
|
assert(end == _end);
|
||||||
|
assert(etext >= text_addr);
|
||||||
|
assert(edata >= data_end);
|
||||||
|
assert(end >= bss_end);
|
||||||
|
assert(linker_test_data[22] == 42);
|
||||||
|
assert(linker_test_bss[256] == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#elif TEST-SO == 6
|
||||||
|
int end;
|
||||||
|
int eight = 8;
|
||||||
|
int nine;
|
||||||
|
int dso_add() { return end + eight + nine; }
|
||||||
|
|
||||||
|
#elif TEST-MAIN == 6
|
||||||
|
int end = 7;
|
||||||
|
int eight;
|
||||||
|
int nine = 9;
|
||||||
|
int dso_add();
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int sum;
|
||||||
|
printf("DSO initialized data test\n");
|
||||||
|
sum = dso_add();
|
||||||
|
assert(end == 7);
|
||||||
|
assert(eight == 8);
|
||||||
|
assert(nine == 9);
|
||||||
|
assert(sum == 24) || printf("-- %d + %d + %d = %d\n", end, eight, nine, sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,2 +1,42 @@
|
|||||||
linker symbols errors: 0
|
|
||||||
user definitions errors: 0
|
--- TEST 1 ---
|
||||||
|
linker symbols test
|
||||||
|
1 (etext == _etext)
|
||||||
|
1 (edata == _edata)
|
||||||
|
1 (end == _end)
|
||||||
|
1 (check_linker_symbols() == 0)
|
||||||
|
|
||||||
|
--- TEST 2 ---
|
||||||
|
DSO linker symbols test
|
||||||
|
1 (p[0] == _etext)
|
||||||
|
1 (p[1] == _edata)
|
||||||
|
1 (p[2] == _end)
|
||||||
|
|
||||||
|
--- TEST 3 ---
|
||||||
|
user definition test
|
||||||
|
1 (etext() + edata() + end() == 6)
|
||||||
|
|
||||||
|
--- TEST 4 ---
|
||||||
|
end copy relocation test
|
||||||
|
1 (end == _end)
|
||||||
|
1 ((unsigned long)end >= data_end)
|
||||||
|
1 (copy_reloc_data[256] == 42)
|
||||||
|
|
||||||
|
--- TEST 5 ---
|
||||||
|
linker boundary test
|
||||||
|
1 (linker_test_bss > linker_test_data)
|
||||||
|
1 (etext == _etext)
|
||||||
|
1 (edata == _edata)
|
||||||
|
1 (end == _end)
|
||||||
|
1 (etext >= text_addr)
|
||||||
|
1 (edata >= data_end)
|
||||||
|
1 (end >= bss_end)
|
||||||
|
1 (linker_test_data[22] == 42)
|
||||||
|
1 (linker_test_bss[256] == 42)
|
||||||
|
|
||||||
|
--- TEST 6 ---
|
||||||
|
DSO initialized data test
|
||||||
|
1 (end == 7)
|
||||||
|
1 (eight == 8)
|
||||||
|
1 (nine == 9)
|
||||||
|
1 (sum == 24)
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
unsigned char copy_reloc_data[257];
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
extern unsigned char copy_reloc_data[257];
|
|
||||||
|
|
||||||
int end(void) { return 42; }
|
|
||||||
int _end(void) { return 24; }
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int errors;
|
|
||||||
|
|
||||||
copy_reloc_data[256] = 42;
|
|
||||||
errors = end() != 42;
|
|
||||||
errors += _end() != 24;
|
|
||||||
errors += copy_reloc_data[256] != 42;
|
|
||||||
printf("user end copy relocation errors: %d\n", errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
extern unsigned char copy_reloc_data[257];
|
|
||||||
extern char end[], _end[];
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
unsigned long data_end;
|
|
||||||
int errors = 0;
|
|
||||||
|
|
||||||
copy_reloc_data[256] = 42;
|
|
||||||
data_end = (unsigned long)(copy_reloc_data + sizeof copy_reloc_data);
|
|
||||||
errors += end != _end;
|
|
||||||
errors += (unsigned long)end < data_end;
|
|
||||||
errors += copy_reloc_data[256] != 42;
|
|
||||||
printf("end copy relocation errors: %d\n", errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
end copy relocation errors: 0
|
|
||||||
user end copy relocation errors: 0
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
void __attribute__((section(".text.linker_test"), noinline, used))
|
|
||||||
linker_test_text(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char linker_test_data[23]
|
|
||||||
__attribute__((section(".data.linker_test"), used)) = { 1 };
|
|
||||||
|
|
||||||
unsigned char linker_test_bss[257]
|
|
||||||
__attribute__((section(".bss.linker_test"), used));
|
|
||||||
|
|
||||||
/* set_global_sym replaces BSS/common definitions of these symbols. */
|
|
||||||
unsigned char _etext;
|
|
||||||
unsigned char _edata;
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
extern void linker_test_text(void);
|
|
||||||
extern unsigned char linker_test_data[23];
|
|
||||||
extern unsigned char linker_test_bss[257];
|
|
||||||
extern char etext[], _etext[];
|
|
||||||
extern char edata[], _edata[];
|
|
||||||
extern char end[], _end[];
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
unsigned long text_addr = (unsigned long)linker_test_text;
|
|
||||||
unsigned long data_end = (unsigned long)(linker_test_data
|
|
||||||
+ sizeof linker_test_data);
|
|
||||||
unsigned long bss_end = (unsigned long)(linker_test_bss
|
|
||||||
+ sizeof linker_test_bss);
|
|
||||||
int errors = 0;
|
|
||||||
|
|
||||||
linker_test_data[22] = 42;
|
|
||||||
linker_test_bss[256] = 42;
|
|
||||||
errors += etext != _etext;
|
|
||||||
errors += edata != _edata;
|
|
||||||
errors += end != _end;
|
|
||||||
errors += (unsigned long)etext <= text_addr;
|
|
||||||
errors += (unsigned long)edata < data_end;
|
|
||||||
errors += (unsigned long)end < bss_end;
|
|
||||||
errors += linker_test_data[22] != 42;
|
|
||||||
errors += linker_test_bss[256] != 42;
|
|
||||||
printf("linker boundary errors: %d\n", errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
linker boundary errors: 0
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
char end = 7;
|
|
||||||
|
|
||||||
char *get_dso_end(void)
|
|
||||||
{
|
|
||||||
return &end;
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
extern char _end[];
|
|
||||||
extern char *get_dso_end(void);
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int errors = get_dso_end() != _end;
|
|
||||||
|
|
||||||
printf("DSO linker symbol errors: %d\n", errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
DSO linker symbol errors: 0
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static unsigned short data[844];
|
|
||||||
|
|
||||||
static uint64_t address_for_index(int index)
|
|
||||||
{
|
|
||||||
return (uint64_t)(uintptr_t)data - 845186ULL
|
|
||||||
+ (uint64_t)index * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
printf("%d\n", address_for_index(422593)
|
|
||||||
== (uint64_t)(uintptr_t)data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
1
|
|
||||||
@ -35,7 +35,7 @@ ifeq ($(CONFIG_bcheck),no)
|
|||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_dll),no)
|
ifeq ($(CONFIG_dll),no)
|
||||||
SKIP += 113_btdll.test # no shared lib support yet
|
SKIP += 113_btdll.test # no shared lib support yet
|
||||||
SKIP += 149_end_copy_reloc.test 151_dso_linker_symbol.test
|
SKIP += 148_linker_symbols.test
|
||||||
endif
|
endif
|
||||||
ifeq (-$(findstring gcc,$(CC))-,--)
|
ifeq (-$(findstring gcc,$(CC))-,--)
|
||||||
SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
|
SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
|
||||||
@ -47,8 +47,7 @@ ifeq (-$(CONFIG_WIN32)-,-yes-)
|
|||||||
SKIP += 106_versym.test # No pthread support
|
SKIP += 106_versym.test # No pthread support
|
||||||
SKIP += 114_bound_signal.test # No pthread support
|
SKIP += 114_bound_signal.test # No pthread support
|
||||||
SKIP += 117_builtins.test # win32 port doesn't define __builtins
|
SKIP += 117_builtins.test # win32 port doesn't define __builtins
|
||||||
SKIP += 148_linker_symbols.test 149_end_copy_reloc.test # ELF linker tests
|
SKIP += 148_linker_symbols.test # ELF linker tests
|
||||||
SKIP += 150_linker_boundaries.test 151_dso_linker_symbol.test
|
|
||||||
endif
|
endif
|
||||||
ifneq (,$(filter OpenBSD FreeBSD NetBSD DragonFly,$(TARGETOS)))
|
ifneq (,$(filter OpenBSD FreeBSD NetBSD DragonFly,$(TARGETOS)))
|
||||||
SKIP += 106_versym.test # no pthread_condattr_setpshared
|
SKIP += 106_versym.test # no pthread_condattr_setpshared
|
||||||
@ -58,11 +57,10 @@ ifneq (,$(filter OpenBSD FreeBSD NetBSD DragonFly,$(TARGETOS)))
|
|||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_OSX),yes)
|
ifeq ($(CONFIG_OSX),yes)
|
||||||
SKIP += 144_tls.test 146_tls_extern.test # TLS runtime not supported on Mach-O
|
SKIP += 144_tls.test 146_tls_extern.test # TLS runtime not supported on Mach-O
|
||||||
SKIP += 148_linker_symbols.test 149_end_copy_reloc.test # ELF linker tests
|
SKIP += 148_linker_symbols.test # ELF linker tests
|
||||||
SKIP += 150_linker_boundaries.test 151_dso_linker_symbol.test
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_pie),yes)
|
ifeq ($(CONFIG_pie),yes)
|
||||||
SKIP += 149_end_copy_reloc.test # PIE executables do not use copy relocations
|
SKIP += 148_linker_symbols.test # PIE executables do not use copy relocations
|
||||||
endif
|
endif
|
||||||
ifeq (-$(ARCH)-,-arm-)
|
ifeq (-$(ARCH)-,-arm-)
|
||||||
SKIP += 144_tls.test 146_tls_extern.test # doesn't work currently
|
SKIP += 144_tls.test 146_tls_extern.test # doesn't work currently
|
||||||
@ -124,62 +122,6 @@ GEN-ALWAYS =
|
|||||||
# constructor/destructor
|
# constructor/destructor
|
||||||
108_constructor.test: NORUN = true
|
108_constructor.test: NORUN = true
|
||||||
|
|
||||||
# TLS needs executable and pthread, not -run
|
|
||||||
144_tls.test: FLAGS += -pthread
|
|
||||||
144_tls.test: NORUN = true
|
|
||||||
# Verify that undefined TLS symbols in TCC objects work with the system linker.
|
|
||||||
146_tls_extern.test: NORUN = true
|
|
||||||
146_tls_extern.test: T1 = \
|
|
||||||
$(TCC) -c $1 -o 146_tls_extern-main.o && \
|
|
||||||
$(TCC) -c $(subst 146,146+,$1) -o 146_tls_extern-def.o && \
|
|
||||||
$(CC) -no-pie -Wl,-z,noexecstack 146_tls_extern-main.o \
|
|
||||||
146_tls_extern-def.o -o $(basename $@).exe && \
|
|
||||||
./$(basename $@).exe
|
|
||||||
ifeq (-$(CONFIG_WIN32)-,-yes-)
|
|
||||||
146_tls_extern.test : CC=$(TCC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Check optional ELF linker symbols, including references from an archive.
|
|
||||||
148_linker_symbols.test: NORUN = true
|
|
||||||
148_linker_symbols.test: T1 = ( \
|
|
||||||
$(TCC) -c $(subst 148,148+,$1) -o 148_linker_symbols.o && \
|
|
||||||
$(AR) rcs 148_linker_symbols.a 148_linker_symbols.o && \
|
|
||||||
$(TCC) $1 148_linker_symbols.a -o $(basename $@).exe && \
|
|
||||||
./$(basename $@).exe && \
|
|
||||||
$(TCC) $(subst 148,148+override,$1) -o 148_linker_symbols-override.exe && \
|
|
||||||
./148_linker_symbols-override.exe \
|
|
||||||
)
|
|
||||||
|
|
||||||
# Copy relocations must be included in the final end symbols.
|
|
||||||
149_end_copy_reloc.test: NORUN = true
|
|
||||||
149_end_copy_reloc.test: T1 = ( \
|
|
||||||
$(TCC) -shared $(subst 149,149+,$1) -o 149_end_copy_reloc$(DLLSUF) && \
|
|
||||||
$(TCC) $1 ./149_end_copy_reloc$(DLLSUF) -Wl,-rpath=. \
|
|
||||||
-o $(basename $@).exe && \
|
|
||||||
./$(basename $@).exe && \
|
|
||||||
$(TCC) $(subst 149,149+override,$1) ./149_end_copy_reloc$(DLLSUF) \
|
|
||||||
-Wl,-rpath=. -o 149_end_copy_reloc-override.exe && \
|
|
||||||
./149_end_copy_reloc-override.exe \
|
|
||||||
)
|
|
||||||
|
|
||||||
# Boundary symbols must cover separately named sections from external objects.
|
|
||||||
150_linker_boundaries.test: NORUN = true
|
|
||||||
150_linker_boundaries.test: T1 = ( \
|
|
||||||
$(CC) -fcommon -fno-pic -fno-pie -c $(subst 150,150+,$1) \
|
|
||||||
-o 150_linker_boundaries.o && \
|
|
||||||
$(TCC) $1 150_linker_boundaries.o -o $(basename $@).exe && \
|
|
||||||
./$(basename $@).exe \
|
|
||||||
)
|
|
||||||
|
|
||||||
# A linker symbol needed only by a DSO must be provided by the executable.
|
|
||||||
151_dso_linker_symbol.test: NORUN = true
|
|
||||||
151_dso_linker_symbol.test: T1 = ( \
|
|
||||||
$(TCC) -shared $(subst 151,151+,$1) -o 151_dso_linker_symbol$(DLLSUF) && \
|
|
||||||
$(TCC) $1 ./151_dso_linker_symbol$(DLLSUF) -Wl,-rpath=. \
|
|
||||||
-o $(basename $@).exe && \
|
|
||||||
./$(basename $@).exe \
|
|
||||||
)
|
|
||||||
|
|
||||||
112_backtrace.test: FLAGS += -dt -b
|
112_backtrace.test: FLAGS += -dt -b
|
||||||
112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
|
112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
|
||||||
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
|
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
|
||||||
@ -189,9 +131,8 @@ endif
|
|||||||
113_btdll.test: T1 = \
|
113_btdll.test: T1 = \
|
||||||
$(TCC) -bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && \
|
$(TCC) -bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && \
|
||||||
$(TCC) -bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && \
|
$(TCC) -bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && \
|
||||||
$(TCC) -bt $1 a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=. -o $(basename $@).exe && \
|
$(TCC) -bt $1 a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=. -o $*.exe && \
|
||||||
./$(basename $@).exe
|
./$*.exe
|
||||||
|
|
||||||
|
|
||||||
114_bound_signal.test: FLAGS += -b
|
114_bound_signal.test: FLAGS += -b
|
||||||
114_bound_signal.test: NORUN = true # tcc -run does not support fork and -b and SELINUX
|
114_bound_signal.test: NORUN = true # tcc -run does not support fork and -b and SELINUX
|
||||||
@ -211,6 +152,32 @@ endif
|
|||||||
140_arm64_extasm.test: GEN = $(GEN-TCC)
|
140_arm64_extasm.test: GEN = $(GEN-TCC)
|
||||||
141_riscv_asm.test: GEN = $(GEN-TCC)
|
141_riscv_asm.test: GEN = $(GEN-TCC)
|
||||||
|
|
||||||
|
# TLS needs executable and pthread, not -run
|
||||||
|
144_tls.test: FLAGS += -pthread
|
||||||
|
144_tls.test: NORUN = true
|
||||||
|
|
||||||
|
# Verify that undefined TLS symbols in TCC objects work with the system linker.
|
||||||
|
# (note: '$*' is '146_tls_extern' here)
|
||||||
|
146_tls_extern.test: T1 = \
|
||||||
|
$(TCC) -c $1 -o $*-main.o && \
|
||||||
|
$(TCC) -c $1 -DDEFS -o $*-defs.o && \
|
||||||
|
$(CC) -no-pie -Wl,-z,noexecstack $*-main.o $*-defs.o -o $*.exe && \
|
||||||
|
./$*.exe
|
||||||
|
ifeq (-$(CONFIG_WIN32)-,-yes-)
|
||||||
|
146_tls_extern.test : CC=$(TCC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Check ELF linker symbols
|
||||||
|
148_linker_symbols.test: T1 = \
|
||||||
|
for T in 1 2 3 4 5 6; do \
|
||||||
|
echo; echo "--- TEST $$T ---"; F=$*-$$T; \
|
||||||
|
$(TCC) $1 -DTEST=$$T+100 -c -fcommon -o $$F.o && \
|
||||||
|
$(TCC) $1 -DTEST=$$T+200 -shared -o $$F.so -fPIC && \
|
||||||
|
$(TCC) $1 -DTEST=$$T -Wl,-rpath=. -o $$F.exe $$F.o $$F.so -no-pie && \
|
||||||
|
./$$F.exe; \
|
||||||
|
done
|
||||||
|
148_linker_symbols.test: GEN=$(T1)
|
||||||
|
|
||||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||||
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
|
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
|
||||||
|
|
||||||
@ -222,7 +189,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS))
|
|||||||
@$(call T1,$<) $(T3)
|
@$(call T1,$<) $(T3)
|
||||||
|
|
||||||
T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
|
T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
|
||||||
T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1)
|
T2 = $(if $(NORUN),$1 -o $*.exe && ./$*.exe,-run $1)
|
||||||
T3 = $(FILTER) >$*.output 2>&1 || true \
|
T3 = $(FILTER) >$*.output 2>&1 || true \
|
||||||
&& diff -Nbu $(filter %.expect,$^) $*.output \
|
&& diff -Nbu $(filter %.expect,$^) $*.output \
|
||||||
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
|
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
|
||||||
@ -250,9 +217,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
|
|||||||
|
|
||||||
# using TCC for .expect if -dt in FLAGS
|
# using TCC for .expect if -dt in FLAGS
|
||||||
GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
|
GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
|
||||||
GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o $(basename $@).exe && ./$(basename $@).exe $(ARGS)
|
GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o $*.exe && ./$*.exe $(ARGS)
|
||||||
GEN-TCC = $(T1)
|
GEN-TCC = $(T1)
|
||||||
GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe
|
GEN-MSC = $(MS-CC) $1 && ./$*.exe
|
||||||
MS-CC = cl
|
MS-CC = cl
|
||||||
|
|
||||||
# tell make not to delete
|
# tell make not to delete
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user