Index: tools/llvm-symbolizer/LLVMSymbolize.h =================================================================== --- tools/llvm-symbolizer/LLVMSymbolize.h +++ tools/llvm-symbolizer/LLVMSymbolize.h @@ -130,6 +130,8 @@ }; std::map Functions; std::map Objects; + // The .opd (function descriptor) section if any, for PowerPC64 ELF. + section_iterator OpdSection; }; } // namespace symbolize Index: tools/llvm-symbolizer/LLVMSymbolize.cpp =================================================================== --- tools/llvm-symbolizer/LLVMSymbolize.cpp +++ tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -44,7 +44,15 @@ } ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx) - : Module(Obj), DebugInfoContext(DICtx) { + : Module(Obj), DebugInfoContext(DICtx), OpdSection(Module->section_end()) { + // Find the .opd (function descriptor) section if any, for PowerPC64 ELF. + for (section_iterator Section : Module->sections()) { + StringRef Name; + if (!error(Section->getName(Name)) && Name == ".opd") { + OpdSection = Section; + break; + } + } for (const SymbolRef &Symbol : Module->symbols()) { addSymbol(Symbol); } @@ -69,6 +77,26 @@ if (error(Symbol.getAddress(SymbolAddress)) || SymbolAddress == UnknownAddressOrSize) return; + if (OpdSection != Module->section_end()) { + // For PowerPC64 ELF, symbols in the .opd section refer to function + // descriptors. The first word of the descriptor is a pointer to the + // function's code. + // For the purposes of symbolization, pretend the symbol's address is that + // of the function's code, not the descriptor. + section_iterator SymbolSection = Module->section_end(); + if (error(Symbol.getSection(SymbolSection))) + return; + if (SymbolSection == OpdSection) { + StringRef Data; + if (error(OpdSection->getContents(Data))) + return; + DataExtractor DE(Data, Module->isLittleEndian(), 0); + uint32_t Offset = SymbolAddress - SymbolSection->getAddress(); + SymbolAddress = DE.getUnsigned(&Offset, Module->getBytesInAddress()); + if (SymbolAddress == 0) + return; + } + } uint64_t SymbolSize; // Getting symbol size is linear for Mach-O files, so assume that symbol // occupies the memory range up to the following symbol.