diff options
| author | Peter Collingbourne <peter@pcc.me.uk> | 2019-06-24 20:03:23 +0000 |
|---|---|---|
| committer | Peter Collingbourne <peter@pcc.me.uk> | 2019-06-24 20:03:23 +0000 |
| commit | 9c8282a9b33084d95c579e9f76daddfcd2f74c32 (patch) | |
| tree | 31ff6a19c89f57ee9f3d040c93823bc5a5a3e6dd /llvm/lib | |
| parent | 94b43160963daa7fbbf561f00f3a4e682f60d91d (diff) | |
| download | bcm5719-llvm-9c8282a9b33084d95c579e9f76daddfcd2f74c32.tar.gz bcm5719-llvm-9c8282a9b33084d95c579e9f76daddfcd2f74c32.zip | |
llvm-symbolizer: Add a FRAME command.
This command prints a description of the referenced function's stack frame.
For each formal parameter and local variable, the tool prints:
- function name
- variable name
- file/line of declaration
- FP-relative variable location (if available)
- size in bytes
- HWASAN tag offset
This information will be used by the HWASAN runtime to identify local
variables in UAR reports.
Differential Revision: https://reviews.llvm.org/D63468
llvm-svn: 364225
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 119 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBContext.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h | 2 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/Symbolize/Symbolize.cpp | 23 |
6 files changed, 180 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 09a42a66ed1..321e157665a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetRegistry.h" @@ -972,6 +973,124 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, return FoundResult; } +static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { + if (auto SizeAttr = Type.find(DW_AT_byte_size)) + if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) + return Size; + + switch (Type.getTag()) { + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + return PointerSize; + case DW_TAG_ptr_to_member_type: { + if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) + if (BaseType.getTag() == DW_TAG_subroutine_type) + return 2 * PointerSize; + return PointerSize; + } + case DW_TAG_const_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_typedef: { + if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) + return getTypeSize(BaseType, PointerSize); + break; + } + case DW_TAG_array_type: { + DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type); + if (!BaseType) + return Optional<uint64_t>(); + Optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize); + if (!BaseSize) + return Optional<uint64_t>(); + uint64_t Size = *BaseSize; + for (DWARFDie Child : Type) { + if (Child.getTag() != DW_TAG_subrange_type) + continue; + + if (auto ElemCountAttr = Child.find(DW_AT_count)) + if (Optional<uint64_t> ElemCount = + ElemCountAttr->getAsUnsignedConstant()) + Size *= *ElemCount; + if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) + if (Optional<int64_t> UpperBound = + UpperBoundAttr->getAsSignedConstant()) { + int64_t LowerBound = 0; + if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) + LowerBound = LowerBoundAttr->getAsSignedConstant().getValueOr(0); + Size *= *UpperBound - LowerBound + 1; + } + } + return Size; + } + default: + break; + } + return Optional<uint64_t>(); +} + +void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + DWARFDie Die, std::vector<DILocal> &Result) { + if (Die.getTag() == DW_TAG_variable || + Die.getTag() == DW_TAG_formal_parameter) { + DILocal Local; + if (auto NameAttr = Subprogram.find(DW_AT_name)) + if (Optional<const char *> Name = NameAttr->getAsCString()) + Local.FunctionName = *Name; + if (auto LocationAttr = Die.find(DW_AT_location)) + if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock()) + if (!Location->empty() && (*Location)[0] == DW_OP_fbreg) + Local.FrameOffset = + decodeSLEB128(Location->data() + 1, nullptr, Location->end()); + if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) + Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); + + if (auto Origin = + Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Die = Origin; + if (auto NameAttr = Die.find(DW_AT_name)) + if (Optional<const char *> Name = NameAttr->getAsCString()) + Local.Name = *Name; + if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) + Local.Size = getTypeSize(Type, getCUAddrSize()); + if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { + if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) + LT->getFileNameByIndex( + DeclFileAttr->getAsUnsignedConstant().getValue(), + CU->getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + Local.DeclFile); + } + if (auto DeclLineAttr = Die.find(DW_AT_decl_line)) + Local.DeclLine = DeclLineAttr->getAsUnsignedConstant().getValue(); + + Result.push_back(Local); + return; + } + + if (Die.getTag() == DW_TAG_inlined_subroutine) + if (auto Origin = + Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Subprogram = Origin; + + for (auto Child : Die) + addLocalsForDie(CU, Subprogram, Child, Result); +} + +std::vector<DILocal> +DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + std::vector<DILocal> Result; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + + DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address); + if (Subprogram.isValid()) + addLocalsForDie(CU, Subprogram, Subprogram, Result); + return Result; +} + DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DILineInfo Result; diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp index 89c20e67413..e452f1d4ced 100644 --- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -91,6 +91,11 @@ PDBContext::getInliningInfoForAddress(object::SectionedAddress Address, return InlineInfo; } +std::vector<DILocal> +PDBContext::getLocalsForAddress(object::SectionedAddress Address) { + return std::vector<DILocal>(); +} + std::string PDBContext::getFunctionName(uint64_t Address, DINameKind NameKind) const { if (NameKind == DINameKind::None) diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp index f6c7ef84958..b2bfef25148 100644 --- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -122,5 +122,28 @@ DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) { return *this; } +DIPrinter &DIPrinter::operator<<(const DILocal &Local) { + OS << Local.FunctionName << '\n'; + OS << Local.Name << '\n'; + if (Local.DeclFile.empty()) + OS << "??"; + else + OS << Local.DeclFile; + OS << ':' << Local.DeclLine << '\n'; + if (Local.FrameOffset) + OS << *Local.FrameOffset << ' '; + else + OS << "?? "; + if (Local.Size) + OS << *Local.Size << ' '; + else + OS << "?? "; + if (Local.TagOffset) + OS << *Local.TagOffset << '\n'; + else + OS << "??\n"; + return *this; +} + } // end namespace symbolize } // end namespace llvm diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index 62f849f5a95..60925841696 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -298,6 +298,14 @@ DIGlobal SymbolizableObjectFile::symbolizeData( return Res; } +std::vector<DILocal> SymbolizableObjectFile::symbolizeFrame( + object::SectionedAddress ModuleOffset) const { + if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) + ModuleOffset.SectionIndex = + getModuleSectionIndexForAddress(ModuleOffset.Address); + return DebugInfoContext->getLocalsForAddress(ModuleOffset); +} + /// Search for the first occurence of specified Address in ObjectFile. uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress( uint64_t Address) const { diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h index d5510cb1b8e..3a511dcb4d4 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h @@ -40,6 +40,8 @@ public: FunctionNameKind FNKind, bool UseSymbolTable) const override; DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override; + std::vector<DILocal> + symbolizeFrame(object::SectionedAddress ModuleOffset) const override; // Return true if this is a 32-bit x86 PE COFF module. bool isWin32Module() const override; diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 1bfd4e8904a..1cb8a7a829e 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -133,6 +133,29 @@ LLVMSymbolizer::symbolizeData(const std::string &ModuleName, return Global; } +Expected<std::vector<DILocal>> +LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName, + object::SectionedAddress ModuleOffset) { + SymbolizableModule *Info; + if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) + Info = InfoOrErr.get(); + else + return InfoOrErr.takeError(); + + // A null module means an error has already been reported. Return an empty + // result. + if (!Info) + return std::vector<DILocal>(); + + // If the user is giving us relative addresses, add the preferred base of + // the object to the offset before we do the query. It's what DIContext + // expects. + if (Opts.RelativeAddresses) + ModuleOffset.Address += Info->getModulePreferredBase(); + + return Info->symbolizeFrame(ModuleOffset); +} + void LLVMSymbolizer::flush() { ObjectForUBPathAndArch.clear(); BinaryForPath.clear(); |

