1*0b57cec5SDimitry Andric //===- SymbolizableObjectFile.cpp -----------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Implementation of SymbolizableObjectFile class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "SymbolizableObjectFile.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 17*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 18*0b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 19*0b57cec5SDimitry Andric #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" 20*0b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 21*0b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 22*0b57cec5SDimitry Andric #include "llvm/Object/SymbolSize.h" 23*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/Error.h" 26*0b57cec5SDimitry Andric #include <algorithm> 27*0b57cec5SDimitry Andric #include <cstdint> 28*0b57cec5SDimitry Andric #include <memory> 29*0b57cec5SDimitry Andric #include <string> 30*0b57cec5SDimitry Andric #include <system_error> 31*0b57cec5SDimitry Andric #include <utility> 32*0b57cec5SDimitry Andric #include <vector> 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric using namespace llvm; 35*0b57cec5SDimitry Andric using namespace object; 36*0b57cec5SDimitry Andric using namespace symbolize; 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric static DILineInfoSpecifier 39*0b57cec5SDimitry Andric getDILineInfoSpecifier(FunctionNameKind FNKind) { 40*0b57cec5SDimitry Andric return DILineInfoSpecifier( 41*0b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FNKind); 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric ErrorOr<std::unique_ptr<SymbolizableObjectFile>> 45*0b57cec5SDimitry Andric SymbolizableObjectFile::create(const object::ObjectFile *Obj, 46*0b57cec5SDimitry Andric std::unique_ptr<DIContext> DICtx) { 47*0b57cec5SDimitry Andric assert(DICtx); 48*0b57cec5SDimitry Andric std::unique_ptr<SymbolizableObjectFile> res( 49*0b57cec5SDimitry Andric new SymbolizableObjectFile(Obj, std::move(DICtx))); 50*0b57cec5SDimitry Andric std::unique_ptr<DataExtractor> OpdExtractor; 51*0b57cec5SDimitry Andric uint64_t OpdAddress = 0; 52*0b57cec5SDimitry Andric // Find the .opd (function descriptor) section if any, for big-endian 53*0b57cec5SDimitry Andric // PowerPC64 ELF. 54*0b57cec5SDimitry Andric if (Obj->getArch() == Triple::ppc64) { 55*0b57cec5SDimitry Andric for (section_iterator Section : Obj->sections()) { 56*0b57cec5SDimitry Andric StringRef Name; 57*0b57cec5SDimitry Andric if (auto EC = Section->getName(Name)) 58*0b57cec5SDimitry Andric return EC; 59*0b57cec5SDimitry Andric if (Name == ".opd") { 60*0b57cec5SDimitry Andric Expected<StringRef> E = Section->getContents(); 61*0b57cec5SDimitry Andric if (!E) 62*0b57cec5SDimitry Andric return errorToErrorCode(E.takeError()); 63*0b57cec5SDimitry Andric OpdExtractor.reset(new DataExtractor(*E, Obj->isLittleEndian(), 64*0b57cec5SDimitry Andric Obj->getBytesInAddress())); 65*0b57cec5SDimitry Andric OpdAddress = Section->getAddress(); 66*0b57cec5SDimitry Andric break; 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric } 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric std::vector<std::pair<SymbolRef, uint64_t>> Symbols = 71*0b57cec5SDimitry Andric computeSymbolSizes(*Obj); 72*0b57cec5SDimitry Andric for (auto &P : Symbols) 73*0b57cec5SDimitry Andric res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric // If this is a COFF object and we didn't find any symbols, try the export 76*0b57cec5SDimitry Andric // table. 77*0b57cec5SDimitry Andric if (Symbols.empty()) { 78*0b57cec5SDimitry Andric if (auto *CoffObj = dyn_cast<COFFObjectFile>(Obj)) 79*0b57cec5SDimitry Andric if (auto EC = res->addCoffExportSymbols(CoffObj)) 80*0b57cec5SDimitry Andric return EC; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric std::vector<std::pair<SymbolDesc, StringRef>> &Fs = res->Functions, 84*0b57cec5SDimitry Andric &Os = res->Objects; 85*0b57cec5SDimitry Andric auto Uniquify = [](std::vector<std::pair<SymbolDesc, StringRef>> &S) { 86*0b57cec5SDimitry Andric // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr, 87*0b57cec5SDimitry Andric // pick the one with the largest Size. This helps us avoid symbols with no 88*0b57cec5SDimitry Andric // size information (Size=0). 89*0b57cec5SDimitry Andric llvm::sort(S); 90*0b57cec5SDimitry Andric auto I = S.begin(), E = S.end(), J = S.begin(); 91*0b57cec5SDimitry Andric while (I != E) { 92*0b57cec5SDimitry Andric auto OI = I; 93*0b57cec5SDimitry Andric while (++I != E && OI->first.Addr == I->first.Addr) { 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric *J++ = I[-1]; 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric S.erase(J, S.end()); 98*0b57cec5SDimitry Andric }; 99*0b57cec5SDimitry Andric Uniquify(Fs); 100*0b57cec5SDimitry Andric Uniquify(Os); 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric return std::move(res); 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj, 106*0b57cec5SDimitry Andric std::unique_ptr<DIContext> DICtx) 107*0b57cec5SDimitry Andric : Module(Obj), DebugInfoContext(std::move(DICtx)) {} 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric namespace { 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric struct OffsetNamePair { 112*0b57cec5SDimitry Andric uint32_t Offset; 113*0b57cec5SDimitry Andric StringRef Name; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric bool operator<(const OffsetNamePair &R) const { 116*0b57cec5SDimitry Andric return Offset < R.Offset; 117*0b57cec5SDimitry Andric } 118*0b57cec5SDimitry Andric }; 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric } // end anonymous namespace 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric std::error_code SymbolizableObjectFile::addCoffExportSymbols( 123*0b57cec5SDimitry Andric const COFFObjectFile *CoffObj) { 124*0b57cec5SDimitry Andric // Get all export names and offsets. 125*0b57cec5SDimitry Andric std::vector<OffsetNamePair> ExportSyms; 126*0b57cec5SDimitry Andric for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) { 127*0b57cec5SDimitry Andric StringRef Name; 128*0b57cec5SDimitry Andric uint32_t Offset; 129*0b57cec5SDimitry Andric if (auto EC = Ref.getSymbolName(Name)) 130*0b57cec5SDimitry Andric return EC; 131*0b57cec5SDimitry Andric if (auto EC = Ref.getExportRVA(Offset)) 132*0b57cec5SDimitry Andric return EC; 133*0b57cec5SDimitry Andric ExportSyms.push_back(OffsetNamePair{Offset, Name}); 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric if (ExportSyms.empty()) 136*0b57cec5SDimitry Andric return std::error_code(); 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric // Sort by ascending offset. 139*0b57cec5SDimitry Andric array_pod_sort(ExportSyms.begin(), ExportSyms.end()); 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric // Approximate the symbol sizes by assuming they run to the next symbol. 142*0b57cec5SDimitry Andric // FIXME: This assumes all exports are functions. 143*0b57cec5SDimitry Andric uint64_t ImageBase = CoffObj->getImageBase(); 144*0b57cec5SDimitry Andric for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) { 145*0b57cec5SDimitry Andric OffsetNamePair &Export = *I; 146*0b57cec5SDimitry Andric // FIXME: The last export has a one byte size now. 147*0b57cec5SDimitry Andric uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1; 148*0b57cec5SDimitry Andric uint64_t SymbolStart = ImageBase + Export.Offset; 149*0b57cec5SDimitry Andric uint64_t SymbolSize = NextOffset - Export.Offset; 150*0b57cec5SDimitry Andric SymbolDesc SD = {SymbolStart, SymbolSize}; 151*0b57cec5SDimitry Andric Functions.emplace_back(SD, Export.Name); 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric return std::error_code(); 154*0b57cec5SDimitry Andric } 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, 157*0b57cec5SDimitry Andric uint64_t SymbolSize, 158*0b57cec5SDimitry Andric DataExtractor *OpdExtractor, 159*0b57cec5SDimitry Andric uint64_t OpdAddress) { 160*0b57cec5SDimitry Andric // Avoid adding symbols from an unknown/undefined section. 161*0b57cec5SDimitry Andric const ObjectFile *Obj = Symbol.getObject(); 162*0b57cec5SDimitry Andric Expected<section_iterator> Sec = Symbol.getSection(); 163*0b57cec5SDimitry Andric if (!Sec || (Obj && Obj->section_end() == *Sec)) 164*0b57cec5SDimitry Andric return std::error_code(); 165*0b57cec5SDimitry Andric Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType(); 166*0b57cec5SDimitry Andric if (!SymbolTypeOrErr) 167*0b57cec5SDimitry Andric return errorToErrorCode(SymbolTypeOrErr.takeError()); 168*0b57cec5SDimitry Andric SymbolRef::Type SymbolType = *SymbolTypeOrErr; 169*0b57cec5SDimitry Andric if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) 170*0b57cec5SDimitry Andric return std::error_code(); 171*0b57cec5SDimitry Andric Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress(); 172*0b57cec5SDimitry Andric if (!SymbolAddressOrErr) 173*0b57cec5SDimitry Andric return errorToErrorCode(SymbolAddressOrErr.takeError()); 174*0b57cec5SDimitry Andric uint64_t SymbolAddress = *SymbolAddressOrErr; 175*0b57cec5SDimitry Andric if (OpdExtractor) { 176*0b57cec5SDimitry Andric // For big-endian PowerPC64 ELF, symbols in the .opd section refer to 177*0b57cec5SDimitry Andric // function descriptors. The first word of the descriptor is a pointer to 178*0b57cec5SDimitry Andric // the function's code. 179*0b57cec5SDimitry Andric // For the purposes of symbolization, pretend the symbol's address is that 180*0b57cec5SDimitry Andric // of the function's code, not the descriptor. 181*0b57cec5SDimitry Andric uint64_t OpdOffset = SymbolAddress - OpdAddress; 182*0b57cec5SDimitry Andric uint32_t OpdOffset32 = OpdOffset; 183*0b57cec5SDimitry Andric if (OpdOffset == OpdOffset32 && 184*0b57cec5SDimitry Andric OpdExtractor->isValidOffsetForAddress(OpdOffset32)) 185*0b57cec5SDimitry Andric SymbolAddress = OpdExtractor->getAddress(&OpdOffset32); 186*0b57cec5SDimitry Andric } 187*0b57cec5SDimitry Andric Expected<StringRef> SymbolNameOrErr = Symbol.getName(); 188*0b57cec5SDimitry Andric if (!SymbolNameOrErr) 189*0b57cec5SDimitry Andric return errorToErrorCode(SymbolNameOrErr.takeError()); 190*0b57cec5SDimitry Andric StringRef SymbolName = *SymbolNameOrErr; 191*0b57cec5SDimitry Andric // Mach-O symbol table names have leading underscore, skip it. 192*0b57cec5SDimitry Andric if (Module->isMachO() && !SymbolName.empty() && SymbolName[0] == '_') 193*0b57cec5SDimitry Andric SymbolName = SymbolName.drop_front(); 194*0b57cec5SDimitry Andric // FIXME: If a function has alias, there are two entries in symbol table 195*0b57cec5SDimitry Andric // with same address size. Make sure we choose the correct one. 196*0b57cec5SDimitry Andric auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; 197*0b57cec5SDimitry Andric SymbolDesc SD = { SymbolAddress, SymbolSize }; 198*0b57cec5SDimitry Andric M.emplace_back(SD, SymbolName); 199*0b57cec5SDimitry Andric return std::error_code(); 200*0b57cec5SDimitry Andric } 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric // Return true if this is a 32-bit x86 PE COFF module. 203*0b57cec5SDimitry Andric bool SymbolizableObjectFile::isWin32Module() const { 204*0b57cec5SDimitry Andric auto *CoffObject = dyn_cast<COFFObjectFile>(Module); 205*0b57cec5SDimitry Andric return CoffObject && CoffObject->getMachine() == COFF::IMAGE_FILE_MACHINE_I386; 206*0b57cec5SDimitry Andric } 207*0b57cec5SDimitry Andric 208*0b57cec5SDimitry Andric uint64_t SymbolizableObjectFile::getModulePreferredBase() const { 209*0b57cec5SDimitry Andric if (auto *CoffObject = dyn_cast<COFFObjectFile>(Module)) 210*0b57cec5SDimitry Andric return CoffObject->getImageBase(); 211*0b57cec5SDimitry Andric return 0; 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type, 215*0b57cec5SDimitry Andric uint64_t Address, 216*0b57cec5SDimitry Andric std::string &Name, 217*0b57cec5SDimitry Andric uint64_t &Addr, 218*0b57cec5SDimitry Andric uint64_t &Size) const { 219*0b57cec5SDimitry Andric const auto &Symbols = Type == SymbolRef::ST_Function ? Functions : Objects; 220*0b57cec5SDimitry Andric std::pair<SymbolDesc, StringRef> SD{{Address, UINT64_C(-1)}, StringRef()}; 221*0b57cec5SDimitry Andric auto SymbolIterator = llvm::upper_bound(Symbols, SD); 222*0b57cec5SDimitry Andric if (SymbolIterator == Symbols.begin()) 223*0b57cec5SDimitry Andric return false; 224*0b57cec5SDimitry Andric --SymbolIterator; 225*0b57cec5SDimitry Andric if (SymbolIterator->first.Size != 0 && 226*0b57cec5SDimitry Andric SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address) 227*0b57cec5SDimitry Andric return false; 228*0b57cec5SDimitry Andric Name = SymbolIterator->second.str(); 229*0b57cec5SDimitry Andric Addr = SymbolIterator->first.Addr; 230*0b57cec5SDimitry Andric Size = SymbolIterator->first.Size; 231*0b57cec5SDimitry Andric return true; 232*0b57cec5SDimitry Andric } 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric bool SymbolizableObjectFile::shouldOverrideWithSymbolTable( 235*0b57cec5SDimitry Andric FunctionNameKind FNKind, bool UseSymbolTable) const { 236*0b57cec5SDimitry Andric // When DWARF is used with -gline-tables-only / -gmlt, the symbol table gives 237*0b57cec5SDimitry Andric // better answers for linkage names than the DIContext. Otherwise, we are 238*0b57cec5SDimitry Andric // probably using PEs and PDBs, and we shouldn't do the override. PE files 239*0b57cec5SDimitry Andric // generally only contain the names of exported symbols. 240*0b57cec5SDimitry Andric return FNKind == FunctionNameKind::LinkageName && UseSymbolTable && 241*0b57cec5SDimitry Andric isa<DWARFContext>(DebugInfoContext.get()); 242*0b57cec5SDimitry Andric } 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric DILineInfo 245*0b57cec5SDimitry Andric SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset, 246*0b57cec5SDimitry Andric FunctionNameKind FNKind, 247*0b57cec5SDimitry Andric bool UseSymbolTable) const { 248*0b57cec5SDimitry Andric if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) 249*0b57cec5SDimitry Andric ModuleOffset.SectionIndex = 250*0b57cec5SDimitry Andric getModuleSectionIndexForAddress(ModuleOffset.Address); 251*0b57cec5SDimitry Andric DILineInfo LineInfo = DebugInfoContext->getLineInfoForAddress( 252*0b57cec5SDimitry Andric ModuleOffset, getDILineInfoSpecifier(FNKind)); 253*0b57cec5SDimitry Andric 254*0b57cec5SDimitry Andric // Override function name from symbol table if necessary. 255*0b57cec5SDimitry Andric if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { 256*0b57cec5SDimitry Andric std::string FunctionName; 257*0b57cec5SDimitry Andric uint64_t Start, Size; 258*0b57cec5SDimitry Andric if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, 259*0b57cec5SDimitry Andric FunctionName, Start, Size)) { 260*0b57cec5SDimitry Andric LineInfo.FunctionName = FunctionName; 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric return LineInfo; 264*0b57cec5SDimitry Andric } 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( 267*0b57cec5SDimitry Andric object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, 268*0b57cec5SDimitry Andric bool UseSymbolTable) const { 269*0b57cec5SDimitry Andric if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) 270*0b57cec5SDimitry Andric ModuleOffset.SectionIndex = 271*0b57cec5SDimitry Andric getModuleSectionIndexForAddress(ModuleOffset.Address); 272*0b57cec5SDimitry Andric DIInliningInfo InlinedContext = DebugInfoContext->getInliningInfoForAddress( 273*0b57cec5SDimitry Andric ModuleOffset, getDILineInfoSpecifier(FNKind)); 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric // Make sure there is at least one frame in context. 276*0b57cec5SDimitry Andric if (InlinedContext.getNumberOfFrames() == 0) 277*0b57cec5SDimitry Andric InlinedContext.addFrame(DILineInfo()); 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric // Override the function name in lower frame with name from symbol table. 280*0b57cec5SDimitry Andric if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { 281*0b57cec5SDimitry Andric std::string FunctionName; 282*0b57cec5SDimitry Andric uint64_t Start, Size; 283*0b57cec5SDimitry Andric if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, 284*0b57cec5SDimitry Andric FunctionName, Start, Size)) { 285*0b57cec5SDimitry Andric InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1) 286*0b57cec5SDimitry Andric ->FunctionName = FunctionName; 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric return InlinedContext; 291*0b57cec5SDimitry Andric } 292*0b57cec5SDimitry Andric 293*0b57cec5SDimitry Andric DIGlobal SymbolizableObjectFile::symbolizeData( 294*0b57cec5SDimitry Andric object::SectionedAddress ModuleOffset) const { 295*0b57cec5SDimitry Andric DIGlobal Res; 296*0b57cec5SDimitry Andric getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name, 297*0b57cec5SDimitry Andric Res.Start, Res.Size); 298*0b57cec5SDimitry Andric return Res; 299*0b57cec5SDimitry Andric } 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric std::vector<DILocal> SymbolizableObjectFile::symbolizeFrame( 302*0b57cec5SDimitry Andric object::SectionedAddress ModuleOffset) const { 303*0b57cec5SDimitry Andric if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) 304*0b57cec5SDimitry Andric ModuleOffset.SectionIndex = 305*0b57cec5SDimitry Andric getModuleSectionIndexForAddress(ModuleOffset.Address); 306*0b57cec5SDimitry Andric return DebugInfoContext->getLocalsForAddress(ModuleOffset); 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric /// Search for the first occurence of specified Address in ObjectFile. 310*0b57cec5SDimitry Andric uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress( 311*0b57cec5SDimitry Andric uint64_t Address) const { 312*0b57cec5SDimitry Andric 313*0b57cec5SDimitry Andric for (SectionRef Sec : Module->sections()) { 314*0b57cec5SDimitry Andric if (!Sec.isText() || Sec.isVirtual()) 315*0b57cec5SDimitry Andric continue; 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric if (Address >= Sec.getAddress() && 318*0b57cec5SDimitry Andric Address < Sec.getAddress() + Sec.getSize()) 319*0b57cec5SDimitry Andric return Sec.getIndex(); 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric return object::SectionedAddress::UndefSection; 323*0b57cec5SDimitry Andric } 324