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:
grischka 2022-11-25 11:58:29 +01:00
parent 28fa4d3db6
commit 312d28b0a8
2 changed files with 51 additions and 65 deletions

View File

@ -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
View File

@ -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: