mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-28 04:00:06 +08:00
tccelf: avoid find_section() for known section
- remove calls to "find_..." for stuff that we know to exist and where. - rename find_section_create(s1,name,0) -> have_section(s1,name) Also: - call update_gnu_hash() from elf_output_file() gnu_hasn() functions could be moved down into an already existing !ELF_OBJ_ONLY clause, but in order to avoid too many diff lines I didn't. - avoid 'long' (elf_hash). sizeof (long) is host-dependent (4 or 8) - remove unnecessary checks (for dynsym, versym). Someone reading "if (dynsym == NULL) ..." must conclude that it actually can happen under certain circumstances, or otherwise, might conclude that the person who wrote that felt unsure what's going on exactly. arm64-gen.c: TCC_TARGET_MACHO instead of __APPLE__ (to support cross-compilers for the apple/M1 target)
This commit is contained in:
parent
28fa4d3db6
commit
312d28b0a8
16
arm64-gen.c
16
arm64-gen.c
@ -53,7 +53,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
ST_DATA const char * const target_machine_defs =
|
||||
#if defined(__APPLE__)
|
||||
#if defined(TCC_TARGET_MACHO)
|
||||
"__aarch64__\0"
|
||||
"__arm64__\0"
|
||||
#else
|
||||
@ -829,7 +829,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
else
|
||||
size = type_size(type[i], &align);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(TCC_TARGET_MACHO)
|
||||
if (variadic && i == variadic) {
|
||||
nx = 8;
|
||||
nv = 8;
|
||||
@ -1202,7 +1202,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
|
||||
arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, n - 1, t, a);
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
if (variadic) {
|
||||
use_x8 = 1;
|
||||
last_int = 4;
|
||||
@ -1304,7 +1304,7 @@ ST_FUNC void gen_va_start(void)
|
||||
o(0x910383be); // add x30,x29,#224
|
||||
o(0xf900001e | r << 5); // str x30,[x(r)]
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
if (arm64_func_va_list_gr_offs) {
|
||||
if (arm64_func_va_list_stack)
|
||||
o(0x910383be); // add x30,x29,#224
|
||||
@ -1345,7 +1345,7 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
|
||||
if (!hfa) {
|
||||
uint32_t n = size > 16 ? 8 : (size + 7) & -8;
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
o(0xb940181e | r0 << 5); // ldr w30,[x(r0),#24] // __gr_offs
|
||||
if (align == 16) {
|
||||
assert(0); // this path untested but needed for __uint128_t
|
||||
@ -1358,7 +1358,7 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack
|
||||
o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n)
|
||||
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
o(0x14000004); // b .+16
|
||||
o(0xb9001800 | r1 | r0 << 5); // str w(r1),[x(r0),#24] // __gr_offs
|
||||
o(0xf9400400 | r1 | r0 << 5); // ldr x(r1),[x(r0),#8] // __gr_top
|
||||
@ -1369,7 +1369,7 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
}
|
||||
else {
|
||||
uint32_t ssz = (size + 7) & -(uint32_t)8;
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
uint32_t rsz = hfa << 4;
|
||||
uint32_t b1, b2;
|
||||
o(0xb9401c1e | r0 << 5); // ldr w30,[x(r0),#28] // __vr_offs
|
||||
@ -1383,7 +1383,7 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
}
|
||||
o(0x9100001e | r1 << 5 | ssz << 10); // add x30,x(r1),#(ssz)
|
||||
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
|
||||
#if !defined(__APPLE__)
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
b2 = ind; o(0x14000000); // b lab2
|
||||
// lab1:
|
||||
write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3);
|
||||
|
100
tccelf.c
100
tccelf.c
@ -325,7 +325,7 @@ static void section_reserve(Section *sec, unsigned long size)
|
||||
}
|
||||
#endif
|
||||
|
||||
static Section *find_section_create (TCCState *s1, const char *name, int create)
|
||||
static Section *have_section(TCCState *s1, const char *name)
|
||||
{
|
||||
Section *sec;
|
||||
int i;
|
||||
@ -334,15 +334,18 @@ static Section *find_section_create (TCCState *s1, const char *name, int create)
|
||||
if (!strcmp(name, sec->name))
|
||||
return sec;
|
||||
}
|
||||
/* sections are created as PROGBITS */
|
||||
return create ? new_section(s1, name, SHT_PROGBITS, SHF_ALLOC) : NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* return a reference to a section, and create it if it does not
|
||||
exists */
|
||||
ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
||||
{
|
||||
return find_section_create (s1, name, 1);
|
||||
Section *sec = have_section(s1, name);
|
||||
if (sec)
|
||||
return sec;
|
||||
/* sections are created as PROGBITS */
|
||||
return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@ -360,9 +363,9 @@ ST_FUNC int put_elf_str(Section *s, const char *sym)
|
||||
}
|
||||
|
||||
/* elf symbol hashing function */
|
||||
static unsigned long elf_hash(const unsigned char *name)
|
||||
static ElfW(Word) elf_hash(const unsigned char *name)
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
ElfW(Word) h = 0, g;
|
||||
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
@ -374,16 +377,6 @@ static unsigned long elf_hash(const unsigned char *name)
|
||||
return h;
|
||||
}
|
||||
|
||||
static unsigned long elf_gnu_hash (const unsigned char *name)
|
||||
{
|
||||
unsigned long h = 5381;
|
||||
unsigned char c;
|
||||
|
||||
while ((c = *name++))
|
||||
h = h * 33 + c;
|
||||
return h;
|
||||
}
|
||||
|
||||
/* rebuild hash table of section s */
|
||||
/* NOTE: we do factorize the hash table code to go faster */
|
||||
static void rebuild_hash(Section *s, unsigned int nb_buckets)
|
||||
@ -863,12 +856,11 @@ static void sort_syms(TCCState *s1, Section *s)
|
||||
tcc_free(old_to_new_syms);
|
||||
}
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
/* See: https://flapenguin.me/elf-dt-gnu-hash */
|
||||
|
||||
#define ELFCLASS_BITS (PTR_SIZE * 8)
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
static void create_gnu_hash(TCCState *s1)
|
||||
static Section *create_gnu_hash(TCCState *s1)
|
||||
{
|
||||
int nb_syms, i, ndef, nbuckets, symoffset, bloom_size, bloom_shift;
|
||||
ElfW(Sym) *p;
|
||||
@ -876,9 +868,6 @@ static void create_gnu_hash(TCCState *s1)
|
||||
Section *dynsym = s1->dynsym;
|
||||
Elf32_Word *ptr;
|
||||
|
||||
if (dynsym == NULL)
|
||||
return;
|
||||
|
||||
gnu_hash = new_section(s1, ".gnu.hash", SHT_GNU_HASH, SHF_ALLOC);
|
||||
gnu_hash->link = dynsym->hash->link;
|
||||
|
||||
@ -905,17 +894,26 @@ static void create_gnu_hash(TCCState *s1)
|
||||
ptr[1] = symoffset;
|
||||
ptr[2] = bloom_size;
|
||||
ptr[3] = bloom_shift;
|
||||
return gnu_hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void update_gnu_hash(TCCState *s1)
|
||||
static Elf32_Word elf_gnu_hash (const unsigned char *name)
|
||||
{
|
||||
Elf32_Word h = 5381;
|
||||
unsigned char c;
|
||||
|
||||
while ((c = *name++))
|
||||
h = h * 33 + c;
|
||||
return h;
|
||||
}
|
||||
|
||||
static void update_gnu_hash(TCCState *s1, Section *gnu_hash)
|
||||
{
|
||||
int *old_to_new_syms;
|
||||
ElfW(Sym) *new_syms;
|
||||
int nb_syms, i, nbuckets, bloom_size, bloom_shift;
|
||||
ElfW(Sym) *p, *q;
|
||||
Section *vs;
|
||||
Section *gnu_hash;
|
||||
Section *dynsym = s1->dynsym;
|
||||
Elf32_Word *ptr, *buckets, *chain, *hash;
|
||||
unsigned int *nextbuck;
|
||||
@ -923,13 +921,6 @@ static void update_gnu_hash(TCCState *s1)
|
||||
unsigned char *strtab;
|
||||
struct { int first, last; } *buck;
|
||||
|
||||
if (dynsym == NULL)
|
||||
return;
|
||||
|
||||
gnu_hash = find_section_create(s1, ".gnu.hash", 0);
|
||||
if (gnu_hash == NULL)
|
||||
return;
|
||||
|
||||
strtab = dynsym->link->data;
|
||||
nb_syms = dynsym->data_offset / sizeof(ElfW(Sym));
|
||||
new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
|
||||
@ -1012,11 +1003,11 @@ static void update_gnu_hash(TCCState *s1)
|
||||
modify_reloctions_old_to_new(s1, dynsym, old_to_new_syms);
|
||||
|
||||
/* modify the versions */
|
||||
vs = find_section_create(s1, ".gnu.version", 0);
|
||||
vs = versym_section;
|
||||
if (vs) {
|
||||
ElfW(Half) *newver, *versym = (ElfW(Half) *)vs->data;
|
||||
|
||||
if (versym) {
|
||||
if (1/*versym*/) {
|
||||
newver = tcc_malloc(nb_syms * sizeof(*newver));
|
||||
for (i = 0; i < nb_syms; i++)
|
||||
newver[old_to_new_syms[i]] = versym[i];
|
||||
@ -1031,6 +1022,7 @@ static void update_gnu_hash(TCCState *s1)
|
||||
ptr = (Elf32_Word *) dynsym->hash->data;
|
||||
rebuild_hash(dynsym, ptr[0]);
|
||||
}
|
||||
#endif /* ELF_OBJ_ONLY */
|
||||
|
||||
/* relocate symbol table, resolve undefined symbols if do_resolve is
|
||||
true and output error if undefined symbol. */
|
||||
@ -1043,6 +1035,8 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||
for_each_elem(symtab, 1, sym, ElfW(Sym)) {
|
||||
sh_num = sym->st_shndx;
|
||||
if (sh_num == SHN_UNDEF) {
|
||||
if (do_resolve == 2) /* relocating dynsym */
|
||||
continue;
|
||||
name = (char *) s1->symtab->link->data + sym->st_name;
|
||||
/* Use ld.so to resolve symbol for us (for tcc -run) */
|
||||
if (do_resolve) {
|
||||
@ -1486,7 +1480,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name)
|
||||
Section *s;
|
||||
addr_t end_offset;
|
||||
char buf[1024];
|
||||
s = find_section_create(s1, section_name, 0);
|
||||
s = have_section(s1, section_name);
|
||||
if (!s || !(s->sh_flags & SHF_ALLOC)) {
|
||||
end_offset = 0;
|
||||
s = data_section;
|
||||
@ -2067,6 +2061,7 @@ struct dyn_inf {
|
||||
int phnum;
|
||||
Section *interp;
|
||||
Section *note;
|
||||
Section *gnu_hash;
|
||||
|
||||
/* read only segment mapping for GNU_RELRO */
|
||||
Section _roinf, *roinf;
|
||||
@ -2352,12 +2347,8 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||
Section *s;
|
||||
|
||||
/* put dynamic section entries */
|
||||
s = find_section_create (s1, ".hash", 0);
|
||||
if (s && s->sh_flags == SHF_ALLOC)
|
||||
put_dt(dynamic, DT_HASH, s->sh_addr);
|
||||
s = find_section_create (s1, ".gnu.hash", 0);
|
||||
if (s && s->sh_flags == SHF_ALLOC)
|
||||
put_dt(dynamic, DT_GNU_HASH, s->sh_addr);
|
||||
put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
|
||||
put_dt(dynamic, DT_GNU_HASH, dyninf->gnu_hash->sh_addr);
|
||||
put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
|
||||
put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
|
||||
put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
|
||||
@ -2391,26 +2382,26 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
||||
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
||||
}
|
||||
s = find_section_create (s1, ".preinit_array", 0);
|
||||
s = have_section(s1, ".preinit_array");
|
||||
if (s && s->data_offset) {
|
||||
put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
|
||||
put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
|
||||
}
|
||||
s = find_section_create (s1, ".init_array", 0);
|
||||
s = have_section(s1, ".init_array");
|
||||
if (s && s->data_offset) {
|
||||
put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
|
||||
put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
|
||||
}
|
||||
s = find_section_create (s1, ".fini_array", 0);
|
||||
s = have_section(s1, ".fini_array");
|
||||
if (s && s->data_offset) {
|
||||
put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
|
||||
put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
|
||||
}
|
||||
s = find_section_create (s1, ".init", 0);
|
||||
s = have_section(s1, ".init");
|
||||
if (s && s->data_offset) {
|
||||
put_dt(dynamic, DT_INIT, s->sh_addr);
|
||||
}
|
||||
s = find_section_create (s1, ".fini", 0);
|
||||
s = have_section(s1, ".fini");
|
||||
if (s && s->data_offset) {
|
||||
put_dt(dynamic, DT_FINI, s->sh_addr);
|
||||
}
|
||||
@ -2530,7 +2521,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
||||
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
||||
|
||||
sort_syms(s1, symtab_section);
|
||||
update_gnu_hash(s1);
|
||||
|
||||
for(i = 1; i < shnum; i++) {
|
||||
s = s1->sections[sec_order ? sec_order[i] : i];
|
||||
if (s->sh_type != SHT_NOBITS) {
|
||||
@ -2811,7 +2802,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
/* shared library case: simply export all global symbols */
|
||||
export_global_syms(s1);
|
||||
}
|
||||
create_gnu_hash(s1);
|
||||
dyninf.gnu_hash = create_gnu_hash(s1);
|
||||
} else {
|
||||
build_got_entries(s1, 0);
|
||||
}
|
||||
@ -2863,21 +2854,13 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
file_offset = layout_sections(s1, sec_order, &dyninf);
|
||||
|
||||
if (dynamic) {
|
||||
ElfW(Sym) *sym;
|
||||
|
||||
/* put in GOT the dynamic section address and relocate PLT */
|
||||
write32le(s1->got->data, dynamic->sh_addr);
|
||||
if (file_type == TCC_OUTPUT_EXE
|
||||
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
|
||||
relocate_plt(s1);
|
||||
|
||||
/* relocate symbols in .dynsym now that final addresses are known */
|
||||
for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
|
||||
if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) {
|
||||
/* do symbol relocation */
|
||||
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
|
||||
}
|
||||
}
|
||||
relocate_syms(s1, s1->dynsym, 2);
|
||||
}
|
||||
|
||||
/* if building executable or DLL, then relocate each section
|
||||
@ -2897,6 +2880,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
else if (s1->got)
|
||||
fill_local_got_entries(s1);
|
||||
|
||||
if (dyninf.gnu_hash)
|
||||
update_gnu_hash(s1, dyninf.gnu_hash);
|
||||
|
||||
/* Create the ELF file with name 'filename' */
|
||||
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr, file_offset, sec_order);
|
||||
the_end:
|
||||
|
Loading…
Reference in New Issue
Block a user