3030#undef has_rel_mcount
3131#undef tot_relsize
3232#undef get_mcountsym
33+ #undef find_symtab
34+ #undef get_shnum
35+ #undef set_shnum
36+ #undef get_shstrndx
37+ #undef get_symindex
3338#undef get_sym_str_and_relp
3439#undef do_func
3540#undef Elf_Addr
5964# define __has_rel_mcount __has64_rel_mcount
6065# define has_rel_mcount has64_rel_mcount
6166# define tot_relsize tot64_relsize
67+ # define find_symtab find_symtab64
68+ # define get_shnum get_shnum64
69+ # define set_shnum set_shnum64
70+ # define get_shstrndx get_shstrndx64
71+ # define get_symindex get_symindex64
6272# define get_sym_str_and_relp get_sym_str_and_relp_64
6373# define do_func do64
6474# define get_mcountsym get_mcountsym_64
92102# define __has_rel_mcount __has32_rel_mcount
93103# define has_rel_mcount has32_rel_mcount
94104# define tot_relsize tot32_relsize
105+ # define find_symtab find_symtab32
106+ # define get_shnum get_shnum32
107+ # define set_shnum set_shnum32
108+ # define get_shstrndx get_shstrndx32
109+ # define get_symindex get_symindex32
95110# define get_sym_str_and_relp get_sym_str_and_relp_32
96111# define do_func do32
97112# define get_mcountsym get_mcountsym_32
@@ -174,6 +189,67 @@ static int MIPS_is_fake_mcount(Elf_Rel const *rp)
174189 return is_fake ;
175190}
176191
192+ static unsigned int get_symindex (Elf_Sym const * sym , Elf32_Word const * symtab ,
193+ Elf32_Word const * symtab_shndx )
194+ {
195+ unsigned long offset ;
196+ int index ;
197+
198+ if (sym -> st_shndx != SHN_XINDEX )
199+ return w2 (sym -> st_shndx );
200+
201+ offset = (unsigned long )sym - (unsigned long )symtab ;
202+ index = offset / sizeof (* sym );
203+
204+ return w (symtab_shndx [index ]);
205+ }
206+
207+ static unsigned int get_shnum (Elf_Ehdr const * ehdr , Elf_Shdr const * shdr0 )
208+ {
209+ if (shdr0 && !ehdr -> e_shnum )
210+ return w (shdr0 -> sh_size );
211+
212+ return w2 (ehdr -> e_shnum );
213+ }
214+
215+ static void set_shnum (Elf_Ehdr * ehdr , Elf_Shdr * shdr0 , unsigned int new_shnum )
216+ {
217+ if (new_shnum >= SHN_LORESERVE ) {
218+ ehdr -> e_shnum = 0 ;
219+ shdr0 -> sh_size = w (new_shnum );
220+ } else
221+ ehdr -> e_shnum = w2 (new_shnum );
222+ }
223+
224+ static int get_shstrndx (Elf_Ehdr const * ehdr , Elf_Shdr const * shdr0 )
225+ {
226+ if (ehdr -> e_shstrndx != SHN_XINDEX )
227+ return w2 (ehdr -> e_shstrndx );
228+
229+ return w (shdr0 -> sh_link );
230+ }
231+
232+ static void find_symtab (Elf_Ehdr * const ehdr , Elf_Shdr const * shdr0 ,
233+ unsigned const nhdr , Elf32_Word * * symtab ,
234+ Elf32_Word * * symtab_shndx )
235+ {
236+ Elf_Shdr const * relhdr ;
237+ unsigned k ;
238+
239+ * symtab = NULL ;
240+ * symtab_shndx = NULL ;
241+
242+ for (relhdr = shdr0 , k = nhdr ; k ; -- k , ++ relhdr ) {
243+ if (relhdr -> sh_type == SHT_SYMTAB )
244+ * symtab = (void * )ehdr + relhdr -> sh_offset ;
245+ else if (relhdr -> sh_type == SHT_SYMTAB_SHNDX )
246+ * symtab_shndx = (void * )ehdr + relhdr -> sh_offset ;
247+
248+ if (* symtab && * symtab_shndx )
249+ break ;
250+ }
251+ }
252+
177253/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
178254static void append_func (Elf_Ehdr * const ehdr ,
179255 Elf_Shdr * const shstr ,
@@ -189,10 +265,12 @@ static void append_func(Elf_Ehdr *const ehdr,
189265 char const * mc_name = (sizeof (Elf_Rela ) == rel_entsize )
190266 ? ".rela__mcount_loc"
191267 : ".rel__mcount_loc" ;
192- unsigned const old_shnum = w2 (ehdr -> e_shnum );
193268 uint_t const old_shoff = _w (ehdr -> e_shoff );
194269 uint_t const old_shstr_sh_size = _w (shstr -> sh_size );
195270 uint_t const old_shstr_sh_offset = _w (shstr -> sh_offset );
271+ Elf_Shdr * const shdr0 = (Elf_Shdr * )(old_shoff + (void * )ehdr );
272+ unsigned int const old_shnum = get_shnum (ehdr , shdr0 );
273+ unsigned int const new_shnum = 2 + old_shnum ; /* {.rel,}__mcount_loc */
196274 uint_t t = 1 + strlen (mc_name ) + _w (shstr -> sh_size );
197275 uint_t new_e_shoff ;
198276
@@ -202,6 +280,8 @@ static void append_func(Elf_Ehdr *const ehdr,
202280 t += (_align & - t ); /* word-byte align */
203281 new_e_shoff = t ;
204282
283+ set_shnum (ehdr , shdr0 , new_shnum );
284+
205285 /* body for new shstrtab */
206286 ulseek (fd_map , sb .st_size , SEEK_SET );
207287 uwrite (fd_map , old_shstr_sh_offset + (void * )ehdr , old_shstr_sh_size );
@@ -246,7 +326,6 @@ static void append_func(Elf_Ehdr *const ehdr,
246326 uwrite (fd_map , mrel0 , (void * )mrelp - (void * )mrel0 );
247327
248328 ehdr -> e_shoff = _w (new_e_shoff );
249- ehdr -> e_shnum = w2 (2 + w2 (ehdr -> e_shnum )); /* {.rel,}__mcount_loc */
250329 ulseek (fd_map , 0 , SEEK_SET );
251330 uwrite (fd_map , ehdr , sizeof (* ehdr ));
252331}
@@ -419,6 +498,8 @@ static unsigned find_secsym_ndx(unsigned const txtndx,
419498 char const * const txtname ,
420499 uint_t * const recvalp ,
421500 Elf_Shdr const * const symhdr ,
501+ Elf32_Word const * symtab ,
502+ Elf32_Word const * symtab_shndx ,
422503 Elf_Ehdr const * const ehdr )
423504{
424505 Elf_Sym const * const sym0 = (Elf_Sym const * )(_w (symhdr -> sh_offset )
@@ -430,7 +511,7 @@ static unsigned find_secsym_ndx(unsigned const txtndx,
430511 for (symp = sym0 , t = nsym ; t ; -- t , ++ symp ) {
431512 unsigned int const st_bind = ELF_ST_BIND (symp -> st_info );
432513
433- if (txtndx == w2 (symp -> st_shndx )
514+ if (txtndx == get_symindex (symp , symtab , symtab_shndx )
434515 /* avoid STB_WEAK */
435516 && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind )) {
436517 /* function symbols on ARM have quirks, avoid them */
@@ -498,21 +579,23 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
498579 return totrelsz ;
499580}
500581
501-
502582/* Overall supervision for Elf32 ET_REL file. */
503583static void
504584do_func (Elf_Ehdr * const ehdr , char const * const fname , unsigned const reltype )
505585{
506586 Elf_Shdr * const shdr0 = (Elf_Shdr * )(_w (ehdr -> e_shoff )
507587 + (void * )ehdr );
508- unsigned const nhdr = w2 (ehdr -> e_shnum );
509- Elf_Shdr * const shstr = & shdr0 [w2 (ehdr -> e_shstrndx )];
588+ unsigned const nhdr = get_shnum (ehdr , shdr0 );
589+ Elf_Shdr * const shstr = & shdr0 [get_shstrndx (ehdr , shdr0 )];
510590 char const * const shstrtab = (char const * )(_w (shstr -> sh_offset )
511591 + (void * )ehdr );
512592
513593 Elf_Shdr const * relhdr ;
514594 unsigned k ;
515595
596+ Elf32_Word * symtab ;
597+ Elf32_Word * symtab_shndx ;
598+
516599 /* Upper bound on space: assume all relevant relocs are for mcount. */
517600 unsigned const totrelsz = tot_relsize (shdr0 , nhdr , shstrtab , fname );
518601 Elf_Rel * const mrel0 = umalloc (totrelsz );
@@ -525,6 +608,8 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
525608 unsigned rel_entsize = 0 ;
526609 unsigned symsec_sh_link = 0 ;
527610
611+ find_symtab (ehdr , shdr0 , nhdr , & symtab , & symtab_shndx );
612+
528613 for (relhdr = shdr0 , k = nhdr ; k ; -- k , ++ relhdr ) {
529614 char const * const txtname = has_rel_mcount (relhdr , shdr0 ,
530615 shstrtab , fname );
@@ -533,6 +618,7 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
533618 unsigned const recsym = find_secsym_ndx (
534619 w (relhdr -> sh_info ), txtname , & recval ,
535620 & shdr0 [symsec_sh_link = w (relhdr -> sh_link )],
621+ symtab , symtab_shndx ,
536622 ehdr );
537623
538624 rel_entsize = _w (relhdr -> sh_entsize );
0 commit comments