@@ -325,7 +325,7 @@ static void section_reserve(Section *sec, unsigned long size)
325
325
}
326
326
#endif
327
327
328
- static Section * find_section_create (TCCState * s1 , const char * name , int create )
328
+ static Section * have_section (TCCState * s1 , const char * name )
329
329
{
330
330
Section * sec ;
331
331
int i ;
@@ -334,15 +334,18 @@ static Section *find_section_create (TCCState *s1, const char *name, int create)
334
334
if (!strcmp (name , sec -> name ))
335
335
return sec ;
336
336
}
337
- /* sections are created as PROGBITS */
338
- return create ? new_section (s1 , name , SHT_PROGBITS , SHF_ALLOC ) : NULL ;
337
+ return NULL ;
339
338
}
340
339
341
340
/* return a reference to a section, and create it if it does not
342
341
exists */
343
342
ST_FUNC Section * find_section (TCCState * s1 , const char * name )
344
343
{
345
- return find_section_create (s1 , name , 1 );
344
+ Section * sec = have_section (s1 , name );
345
+ if (sec )
346
+ return sec ;
347
+ /* sections are created as PROGBITS */
348
+ return new_section (s1 , name , SHT_PROGBITS , SHF_ALLOC );
346
349
}
347
350
348
351
/* ------------------------------------------------------------------------- */
@@ -360,9 +363,9 @@ ST_FUNC int put_elf_str(Section *s, const char *sym)
360
363
}
361
364
362
365
/* elf symbol hashing function */
363
- static unsigned long elf_hash (const unsigned char * name )
366
+ static ElfW ( Word ) elf_hash (const unsigned char * name )
364
367
{
365
- unsigned long h = 0 , g ;
368
+ ElfW ( Word ) h = 0 , g ;
366
369
367
370
while (* name ) {
368
371
h = (h << 4 ) + * name ++ ;
@@ -374,16 +377,6 @@ static unsigned long elf_hash(const unsigned char *name)
374
377
return h ;
375
378
}
376
379
377
- static unsigned long elf_gnu_hash (const unsigned char * name )
378
- {
379
- unsigned long h = 5381 ;
380
- unsigned char c ;
381
-
382
- while ((c = * name ++ ))
383
- h = h * 33 + c ;
384
- return h ;
385
- }
386
-
387
380
/* rebuild hash table of section s */
388
381
/* NOTE: we do factorize the hash table code to go faster */
389
382
static void rebuild_hash (Section * s , unsigned int nb_buckets )
@@ -863,22 +856,18 @@ static void sort_syms(TCCState *s1, Section *s)
863
856
tcc_free (old_to_new_syms );
864
857
}
865
858
859
+ #ifndef ELF_OBJ_ONLY
866
860
/* See: https://flapenguin.me/elf-dt-gnu-hash */
867
-
868
861
#define ELFCLASS_BITS (PTR_SIZE * 8)
869
862
870
- #ifndef ELF_OBJ_ONLY
871
- static void create_gnu_hash (TCCState * s1 )
863
+ static Section * create_gnu_hash (TCCState * s1 )
872
864
{
873
865
int nb_syms , i , ndef , nbuckets , symoffset , bloom_size , bloom_shift ;
874
866
ElfW (Sym ) * p ;
875
867
Section * gnu_hash ;
876
868
Section * dynsym = s1 -> dynsym ;
877
869
Elf32_Word * ptr ;
878
870
879
- if (dynsym == NULL )
880
- return ;
881
-
882
871
gnu_hash = new_section (s1 , ".gnu.hash" , SHT_GNU_HASH , SHF_ALLOC );
883
872
gnu_hash -> link = dynsym -> hash -> link ;
884
873
@@ -905,31 +894,33 @@ static void create_gnu_hash(TCCState *s1)
905
894
ptr [1 ] = symoffset ;
906
895
ptr [2 ] = bloom_size ;
907
896
ptr [3 ] = bloom_shift ;
897
+ return gnu_hash ;
908
898
}
909
- #endif
910
899
911
- static void update_gnu_hash (TCCState * s1 )
900
+ static Elf32_Word elf_gnu_hash (const unsigned char * name )
901
+ {
902
+ Elf32_Word h = 5381 ;
903
+ unsigned char c ;
904
+
905
+ while ((c = * name ++ ))
906
+ h = h * 33 + c ;
907
+ return h ;
908
+ }
909
+
910
+ static void update_gnu_hash (TCCState * s1 , Section * gnu_hash )
912
911
{
913
912
int * old_to_new_syms ;
914
913
ElfW (Sym ) * new_syms ;
915
914
int nb_syms , i , nbuckets , bloom_size , bloom_shift ;
916
915
ElfW (Sym ) * p , * q ;
917
916
Section * vs ;
918
- Section * gnu_hash ;
919
917
Section * dynsym = s1 -> dynsym ;
920
918
Elf32_Word * ptr , * buckets , * chain , * hash ;
921
919
unsigned int * nextbuck ;
922
920
addr_t * bloom ;
923
921
unsigned char * strtab ;
924
922
struct { int first , last ; } * buck ;
925
923
926
- if (dynsym == NULL )
927
- return ;
928
-
929
- gnu_hash = find_section_create (s1 , ".gnu.hash" , 0 );
930
- if (gnu_hash == NULL )
931
- return ;
932
-
933
924
strtab = dynsym -> link -> data ;
934
925
nb_syms = dynsym -> data_offset / sizeof (ElfW (Sym ));
935
926
new_syms = tcc_malloc (nb_syms * sizeof (ElfW (Sym )));
@@ -1012,11 +1003,11 @@ static void update_gnu_hash(TCCState *s1)
1012
1003
modify_reloctions_old_to_new (s1 , dynsym , old_to_new_syms );
1013
1004
1014
1005
/* modify the versions */
1015
- vs = find_section_create ( s1 , ".gnu.version" , 0 ) ;
1006
+ vs = versym_section ;
1016
1007
if (vs ) {
1017
1008
ElfW (Half ) * newver , * versym = (ElfW (Half ) * )vs -> data ;
1018
1009
1019
- if (versym ) {
1010
+ if (1 /* versym*/ ) {
1020
1011
newver = tcc_malloc (nb_syms * sizeof (* newver ));
1021
1012
for (i = 0 ; i < nb_syms ; i ++ )
1022
1013
newver [old_to_new_syms [i ]] = versym [i ];
@@ -1031,6 +1022,7 @@ static void update_gnu_hash(TCCState *s1)
1031
1022
ptr = (Elf32_Word * ) dynsym -> hash -> data ;
1032
1023
rebuild_hash (dynsym , ptr [0 ]);
1033
1024
}
1025
+ #endif /* ELF_OBJ_ONLY */
1034
1026
1035
1027
/* relocate symbol table, resolve undefined symbols if do_resolve is
1036
1028
true and output error if undefined symbol. */
@@ -1043,6 +1035,8 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
1043
1035
for_each_elem (symtab , 1 , sym , ElfW (Sym )) {
1044
1036
sh_num = sym -> st_shndx ;
1045
1037
if (sh_num == SHN_UNDEF ) {
1038
+ if (do_resolve == 2 ) /* relocating dynsym */
1039
+ continue ;
1046
1040
name = (char * ) s1 -> symtab -> link -> data + sym -> st_name ;
1047
1041
/* Use ld.so to resolve symbol for us (for tcc -run) */
1048
1042
if (do_resolve ) {
@@ -1486,7 +1480,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name)
1486
1480
Section * s ;
1487
1481
addr_t end_offset ;
1488
1482
char buf [1024 ];
1489
- s = find_section_create (s1 , section_name , 0 );
1483
+ s = have_section (s1 , section_name );
1490
1484
if (!s || !(s -> sh_flags & SHF_ALLOC )) {
1491
1485
end_offset = 0 ;
1492
1486
s = data_section ;
@@ -2067,6 +2061,7 @@ struct dyn_inf {
2067
2061
int phnum ;
2068
2062
Section * interp ;
2069
2063
Section * note ;
2064
+ Section * gnu_hash ;
2070
2065
2071
2066
/* read only segment mapping for GNU_RELRO */
2072
2067
Section _roinf , * roinf ;
@@ -2352,12 +2347,8 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2352
2347
Section * s ;
2353
2348
2354
2349
/* put dynamic section entries */
2355
- s = find_section_create (s1 , ".hash" , 0 );
2356
- if (s && s -> sh_flags == SHF_ALLOC )
2357
- put_dt (dynamic , DT_HASH , s -> sh_addr );
2358
- s = find_section_create (s1 , ".gnu.hash" , 0 );
2359
- if (s && s -> sh_flags == SHF_ALLOC )
2360
- put_dt (dynamic , DT_GNU_HASH , s -> sh_addr );
2350
+ put_dt (dynamic , DT_HASH , s1 -> dynsym -> hash -> sh_addr );
2351
+ put_dt (dynamic , DT_GNU_HASH , dyninf -> gnu_hash -> sh_addr );
2361
2352
put_dt (dynamic , DT_STRTAB , dyninf -> dynstr -> sh_addr );
2362
2353
put_dt (dynamic , DT_SYMTAB , s1 -> dynsym -> sh_addr );
2363
2354
put_dt (dynamic , DT_STRSZ , dyninf -> dynstr -> data_offset );
@@ -2391,26 +2382,26 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2391
2382
put_dt (dynamic , DT_VERNEED , verneed_section -> sh_addr );
2392
2383
put_dt (dynamic , DT_VERNEEDNUM , dt_verneednum );
2393
2384
}
2394
- s = find_section_create (s1 , ".preinit_array" , 0 );
2385
+ s = have_section (s1 , ".preinit_array" );
2395
2386
if (s && s -> data_offset ) {
2396
2387
put_dt (dynamic , DT_PREINIT_ARRAY , s -> sh_addr );
2397
2388
put_dt (dynamic , DT_PREINIT_ARRAYSZ , s -> data_offset );
2398
2389
}
2399
- s = find_section_create (s1 , ".init_array" , 0 );
2390
+ s = have_section (s1 , ".init_array" );
2400
2391
if (s && s -> data_offset ) {
2401
2392
put_dt (dynamic , DT_INIT_ARRAY , s -> sh_addr );
2402
2393
put_dt (dynamic , DT_INIT_ARRAYSZ , s -> data_offset );
2403
2394
}
2404
- s = find_section_create (s1 , ".fini_array" , 0 );
2395
+ s = have_section (s1 , ".fini_array" );
2405
2396
if (s && s -> data_offset ) {
2406
2397
put_dt (dynamic , DT_FINI_ARRAY , s -> sh_addr );
2407
2398
put_dt (dynamic , DT_FINI_ARRAYSZ , s -> data_offset );
2408
2399
}
2409
- s = find_section_create (s1 , ".init" , 0 );
2400
+ s = have_section (s1 , ".init" );
2410
2401
if (s && s -> data_offset ) {
2411
2402
put_dt (dynamic , DT_INIT , s -> sh_addr );
2412
2403
}
2413
- s = find_section_create (s1 , ".fini" , 0 );
2404
+ s = have_section (s1 , ".fini" );
2414
2405
if (s && s -> data_offset ) {
2415
2406
put_dt (dynamic , DT_FINI , s -> sh_addr );
2416
2407
}
@@ -2530,7 +2521,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2530
2521
offset = sizeof (ElfW (Ehdr )) + phnum * sizeof (ElfW (Phdr ));
2531
2522
2532
2523
sort_syms (s1 , symtab_section );
2533
- update_gnu_hash ( s1 );
2524
+
2534
2525
for (i = 1 ; i < shnum ; i ++ ) {
2535
2526
s = s1 -> sections [sec_order ? sec_order [i ] : i ];
2536
2527
if (s -> sh_type != SHT_NOBITS ) {
@@ -2811,7 +2802,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
2811
2802
/* shared library case: simply export all global symbols */
2812
2803
export_global_syms (s1 );
2813
2804
}
2814
- create_gnu_hash (s1 );
2805
+ dyninf . gnu_hash = create_gnu_hash (s1 );
2815
2806
} else {
2816
2807
build_got_entries (s1 , 0 );
2817
2808
}
@@ -2863,21 +2854,13 @@ static int elf_output_file(TCCState *s1, const char *filename)
2863
2854
file_offset = layout_sections (s1 , sec_order , & dyninf );
2864
2855
2865
2856
if (dynamic ) {
2866
- ElfW (Sym ) * sym ;
2867
-
2868
2857
/* put in GOT the dynamic section address and relocate PLT */
2869
2858
write32le (s1 -> got -> data , dynamic -> sh_addr );
2870
2859
if (file_type == TCC_OUTPUT_EXE
2871
2860
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN )))
2872
2861
relocate_plt (s1 );
2873
-
2874
2862
/* relocate symbols in .dynsym now that final addresses are known */
2875
- for_each_elem (s1 -> dynsym , 1 , sym , ElfW (Sym )) {
2876
- if (sym -> st_shndx != SHN_UNDEF && sym -> st_shndx < SHN_LORESERVE ) {
2877
- /* do symbol relocation */
2878
- sym -> st_value += s1 -> sections [sym -> st_shndx ]-> sh_addr ;
2879
- }
2880
- }
2863
+ relocate_syms (s1 , s1 -> dynsym , 2 );
2881
2864
}
2882
2865
2883
2866
/* if building executable or DLL, then relocate each section
@@ -2897,6 +2880,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
2897
2880
else if (s1 -> got )
2898
2881
fill_local_got_entries (s1 );
2899
2882
2883
+ if (dyninf .gnu_hash )
2884
+ update_gnu_hash (s1 , dyninf .gnu_hash );
2885
+
2900
2886
/* Create the ELF file with name 'filename' */
2901
2887
ret = tcc_write_elf_file (s1 , filename , dyninf .phnum , dyninf .phdr , file_offset , sec_order );
2902
2888
the_end :
0 commit comments