@@ -854,11 +854,12 @@ void ProfiledBinary::loadSymbolsFromSymtab(const ObjectFile *Obj) {
854854 if (Size == 0 || Type != SymbolRef::ST_Function)
855855 continue ;
856856
857+ const uint64_t EndAddr = StartAddr + Size;
857858 const StringRef SymName =
858859 FunctionSamples::getCanonicalFnName (Name, Suffixes);
859860
860861 auto Range = findFuncRange (StartAddr);
861- if (!Range || Range-> StartAddress != StartAddr ) {
862+ if (!Range) {
862863 // Function from symbol table not found previously in DWARF, store ranges.
863864 auto Ret = BinaryFunctions.emplace (SymName, BinaryFunction ());
864865 auto &Func = Ret.first ->second ;
@@ -868,23 +869,67 @@ void ProfiledBinary::loadSymbolsFromSymtab(const ObjectFile *Obj) {
868869 }
869870
870871 Func.FromSymtab = true ;
871- Func.Ranges .emplace_back (StartAddr, StartAddr + Size );
872+ Func.Ranges .emplace_back (StartAddr, EndAddr );
872873
873874 auto R = StartAddrToFuncRangeMap.emplace (StartAddr, FuncRange ());
874875 FuncRange &FRange = R.first ->second ;
875876
876877 FRange.Func = &Func;
877878 FRange.StartAddress = StartAddr;
878- FRange.EndAddress = StartAddr + Size ;
879+ FRange.EndAddress = EndAddr ;
879880
880- } else if (SymName != Range->getFuncName () && ShowDetailedWarning) {
881- // Function already found from DWARF, check consistency between symbol
882- // table and DWARF.
883- WithColor::warning () << " Conflicting name for symbol" << Name
884- << " at address " << format (" %8" PRIx64, StartAddr)
881+ } else if (SymName != Range->getFuncName ()) {
882+ // Function range already found from DWARF, but the symbol name from
883+ // symbol table is inconsistent with debug info.
884+ if (ShowDetailedWarning)
885+ WithColor::warning ()
886+ << " Conflicting name for symbol " << Name << " with range ("
887+ << format (" %8" PRIx64, StartAddr) << " , "
888+ << format (" %8" PRIx64, EndAddr) << " )"
889+ << " , but the DWARF symbol " << Range->getFuncName ()
890+ << " indicates an overlapping range ("
891+ << format (" %8" PRIx64, Range->StartAddress ) << " , "
892+ << format (" %8" PRIx64, Range->EndAddress ) << " )\n " ;
893+
894+ assert (StartAddr == Range->StartAddress && EndAddr == Range->EndAddress &&
895+ " Mismatched function range" );
896+
897+ auto ErrSym = BinaryFunctions.find (Range->getFuncName ().str ());
898+ auto Ret = BinaryFunctions.emplace (SymName, BinaryFunction ());
899+ auto &Func = Ret.first ->second ;
900+
901+ // Symbol table may contain multiple symbol names of the same starting
902+ // address. Only need to pick one from these.
903+ if (!Ret.second )
904+ continue ;
905+
906+ Func.FuncName = Ret.first ->first ;
907+ Func.Ranges = ErrSym->second .Ranges ;
908+ Func.FromSymtab = true ;
909+
910+ HashBinaryFunctions.erase (MD5Hash (Range->getFuncName ()));
911+ BinaryFunctions.erase (ErrSym);
912+
913+ HashBinaryFunctions[MD5Hash (StringRef (SymName))] = &Func;
914+ Range->Func = &Func;
915+ for (auto [RangeStart, _] : Func.Ranges ) {
916+ if (auto FRange = findFuncRangeForStartAddr (RangeStart)) {
917+ assert (FRange && " Cannot find function range" );
918+ FRange->Func = &Func;
919+ }
920+ }
921+ } else if (StartAddr != Range->StartAddress &&
922+ EndAddr != Range->EndAddress ) {
923+ // Function already found in DWARF, but the address range from symbol
924+ // table conflicts/overlaps with the debug info.
925+ WithColor::warning () << " Conflicting range for symbol " << Name
926+ << " with range (" << format (" %8" PRIx64, StartAddr)
927+ << " , " << format (" %8" PRIx64, EndAddr) << " )"
885928 << " , but the DWARF symbol " << Range->getFuncName ()
886- << " indicates a starting address at "
887- << format (" %8" PRIx64, Range->StartAddress ) << " \n " ;
929+ << " indicates another range ("
930+ << format (" %8" PRIx64, Range->StartAddress ) << " , "
931+ << format (" %8" PRIx64, Range->EndAddress ) << " )\n " ;
932+ llvm_unreachable (" invalid function range" );
888933 }
889934 }
890935}
0 commit comments