@@ -4701,10 +4701,26 @@ static bool _read_symbols_from_phdr(ELFOBJ *eo, ReadPhdrSymbolState *state) {
47014701 return true;
47024702}
47034703
4704+ // exact symtab entry count for the layouts that state one, 0 when none does
4705+ static ut64 get_phdr_symtab_count (ELFOBJ * eo ) {
4706+ const RBinElfDynamicInfo * di = & eo -> dyn_info ;
4707+ if (eo -> ehdr .e_machine == EM_MIPS && di -> dt_mips_symtabno ) {
4708+ return di -> dt_mips_symtabno ;
4709+ }
4710+ if (di -> dt_hash != R_BIN_ELF_ADDR_MAX ) {
4711+ const ut64 off = Elf_ (v2p ) (eo , di -> dt_hash );
4712+ // sysv hash is nbucket, nchain, and nchain counts the symtab entries
4713+ if (off != UT64_MAX && off + 8 <= eo -> size ) {
4714+ return r_buf_read_ble32_at (eo -> b , off + 4 , eo -> endian );
4715+ }
4716+ }
4717+ return 0 ;
4718+ }
4719+
47044720static ut64 get_phdr_symtab_upper_bound (ELFOBJ * eo , ut64 addr_sym_table ) {
47054721 ut64 bound = eo -> size ;
47064722 const RBinElfDynamicInfo * di = & eo -> dyn_info ;
4707- // no tag holds the symtab size, so it ends where the next table starts
4723+ // with no exact count the symtab ends where the next table starts
47084724 const ut64 vsym = eo -> version_info [DT_VERSIONTAGIDX (DT_VERSYM )];
47094725 const Elf_ (Addr ) table_vaddrs [] = {
47104726 di -> dt_strtab , di -> dt_gnu_hash , di -> dt_hash ,
@@ -4760,6 +4776,10 @@ static RVecRBinElfSymbol* load_symbols_from_phdr(ELFOBJ *eo, int type) {
47604776 // Stop at the next table boundary so the phdr fallback does not decode
47614777 // adjacent dynamic metadata as synthetic dynsym entries.
47624778 int nsym = (symtab_end - addr_sym_table ) / sym_size ;
4779+ const ut64 nexact = get_phdr_symtab_count (eo );
4780+ if (nexact && nexact < (ut64 )nsym ) {
4781+ nsym = (int )nexact ;
4782+ }
47634783 if (nsym < 1 ) {
47644784 return NULL ;
47654785 }
0 commit comments