- 
                Notifications
    
You must be signed in to change notification settings  - Fork 15.1k
 
LLVM symbolizer gsym support #134847
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LLVM symbolizer gsym support #134847
Changes from 7 commits
f04cbe9
              978438d
              9df4bc1
              4c3db2c
              632b969
              3a32530
              3208744
              0476b8b
              9f3bf66
              b1f6a05
              3c61b39
              0c74ff4
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| //===-- GsymDIContext.h --------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===/ | ||
| 
     | 
||
| #ifndef LLVM_DEBUGINFO_GSYM_GSYMDICONTEXT_H | ||
| #define LLVM_DEBUGINFO_GSYM_GSYMDICONTEXT_H | ||
| 
     | 
||
| #include "llvm/DebugInfo/DIContext.h" | ||
| #include <cstdint> | ||
| #include <memory> | ||
| #include <string> | ||
| 
     | 
||
| namespace llvm { | ||
| 
     | 
||
| namespace gsym { | ||
| 
     | 
||
| class GsymReader; | ||
| 
     | 
||
| /// GSYM DI Context | ||
| /// This data structure is the top level entity that deals with GSYM | ||
| /// symbolication. | ||
| /// This data structure exists only when there is a need for a transparent | ||
| /// interface to different symbolication formats (e.g. GSYM, PDB and DWARF). | ||
| /// More control and power over the debug information access can be had by using | ||
| /// the GSYM interfaces directly. | ||
| class GsymDIContext : public DIContext { | ||
| public: | ||
| GsymDIContext(std::unique_ptr<GsymReader> Reader); | ||
| 
     | 
||
| GsymDIContext(GsymDIContext &) = delete; | ||
| GsymDIContext &operator=(GsymDIContext &) = delete; | ||
| 
     | 
||
| static bool classof(const DIContext *DICtx) { | ||
| return DICtx->getKind() == CK_GSYM; | ||
| } | ||
| 
     | 
||
| void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override; | ||
| 
     | 
||
| std::optional<DILineInfo> getLineInfoForAddress( | ||
| object::SectionedAddress Address, | ||
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; | ||
| std::optional<DILineInfo> | ||
| getLineInfoForDataAddress(object::SectionedAddress Address) override; | ||
| DILineInfoTable getLineInfoForAddressRange( | ||
| object::SectionedAddress Address, uint64_t Size, | ||
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; | ||
| DIInliningInfo getInliningInfoForAddress( | ||
| object::SectionedAddress Address, | ||
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; | ||
| 
     | 
||
| std::vector<DILocal> | ||
| getLocalsForAddress(object::SectionedAddress Address) override; | ||
| 
     | 
||
| private: | ||
| const std::unique_ptr<GsymReader> Reader; | ||
| }; | ||
| 
     | 
||
| } // end namespace gsym | ||
| 
     | 
||
| } // end namespace llvm | ||
| 
     | 
||
| #endif // LLVM_DEBUGINFO_PDB_PDBCONTEXT_H | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| //===-- GsymDIContext.cpp ------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===/ | ||
| 
     | 
||
| #include "llvm/DebugInfo/GSYM/GsymDIContext.h" | ||
| 
     | 
||
| #include "llvm/DebugInfo/GSYM/GsymReader.h" | ||
| #include "llvm/Support/Path.h" | ||
| 
     | 
||
| using namespace llvm; | ||
| using namespace llvm::gsym; | ||
| 
     | 
||
| GsymDIContext::GsymDIContext(std::unique_ptr<GsymReader> Reader) | ||
| : DIContext(CK_GSYM), Reader(std::move(Reader)) {} | ||
| 
     | 
||
| void GsymDIContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {} | ||
| 
     | 
||
| static bool fillLineInfoFromLocation(const SourceLocation &Location, | ||
| DILineInfoSpecifier Specifier, | ||
| DILineInfo &LineInfo) { | ||
| // FIXME Demangle in case of DINameKind::ShortName | ||
| if (Specifier.FNKind != DINameKind::None) { | ||
| LineInfo.FunctionName = Location.Name.str(); | ||
| } | ||
| 
     | 
||
| switch (Specifier.FLIKind) { | ||
| case DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath: | ||
| // We have no information to determine the relative path, so we fall back to | ||
| // returning the absolute path. | ||
| case DILineInfoSpecifier::FileLineInfoKind::RawValue: | ||
| case DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath: | ||
| if (Location.Dir.empty()) { | ||
| if (Location.Base.empty()) | ||
| LineInfo.FileName = DILineInfo::BadString; | ||
| else | ||
| LineInfo.FileName = Location.Base.str(); | ||
| } else { | ||
| SmallString<128> Path(Location.Dir); | ||
| sys::path::append(Path, Location.Base); | ||
| LineInfo.FileName = static_cast<std::string>(Path); | ||
| } | ||
| break; | ||
| 
     | 
||
| case DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly: | ||
| LineInfo.FileName = Location.Base.str(); | ||
| break; | ||
| 
     | 
||
| default: | ||
| return false; | ||
| } | ||
| LineInfo.Line = Location.Line; | ||
| 
     | 
||
| // We don't have information in GSYM to fill any of the Source, Column, | ||
| // StartFileName or StartLine attributes. | ||
| 
     | 
||
| return true; | ||
| } | ||
| 
     | 
||
| std::optional<DILineInfo> | ||
| GsymDIContext::getLineInfoForAddress(object::SectionedAddress Address, | ||
| DILineInfoSpecifier Specifier) { | ||
| if (Address.SectionIndex != object::SectionedAddress::UndefSection) | ||
| return {}; | ||
| 
     | 
||
| auto ResultOrErr = Reader->lookup(Address.Address); | ||
| 
     | 
||
| if (!ResultOrErr) { | ||
| consumeError(ResultOrErr.takeError()); | ||
| return {}; | ||
| } | ||
| 
     | 
||
| const auto &Result = *ResultOrErr; | ||
| 
     | 
||
| DILineInfo LineInfo; | ||
| 
     | 
||
| if (Result.Locations.empty()) { | ||
| // No debug info for this, we just had a symbol from the symbol table. | ||
| 
     | 
||
| // FIXME Demangle in case of DINameKind::ShortName | ||
| if (Specifier.FNKind != DINameKind::None) { | ||
| LineInfo.FunctionName = Result.FuncName.str(); | ||
| } | ||
| } else { | ||
| if (!fillLineInfoFromLocation(Result.Locations.front(), Specifier, | ||
                
       | 
||
| LineInfo)) | ||
| return {}; | ||
| } | ||
| 
     | 
||
| LineInfo.StartAddress = Result.FuncRange.start(); | ||
| 
     | 
||
| return LineInfo; | ||
| } | ||
| 
     | 
||
| std::optional<DILineInfo> | ||
| GsymDIContext::getLineInfoForDataAddress(object::SectionedAddress Address) { | ||
| // We can't implement this, there's no such information in the GSYM file. | ||
| 
     | 
||
| return {}; | ||
| } | ||
| 
     | 
||
| DILineInfoTable | ||
| GsymDIContext::getLineInfoForAddressRange(object::SectionedAddress Address, | ||
| uint64_t Size, | ||
| DILineInfoSpecifier Specifier) { | ||
| if (Size == 0) | ||
| return DILineInfoTable(); | ||
| 
     | 
||
| if (Address.SectionIndex != llvm::object::SectionedAddress::UndefSection) | ||
| return DILineInfoTable(); | ||
| 
     | 
||
| if (auto FuncInfoOrErr = Reader->getFunctionInfo(Address.Address)) { | ||
| DILineInfoTable Table; | ||
| if (FuncInfoOrErr->OptLineTable) { | ||
| const gsym::LineTable < = *FuncInfoOrErr->OptLineTable; | ||
| const uint64_t StartAddr = Address.Address; | ||
| const uint64_t EndAddr = Address.Address + Size; | ||
| for (const auto &LineEntry : LT) { | ||
| if (StartAddr <= LineEntry.Addr && LineEntry.Addr < EndAddr) { | ||
| // Use LineEntry.Addr, LineEntry.File (which is a file index into the | ||
| // files tables from the GsymReader), and LineEntry.Line (source line | ||
| // number) to add stuff to the DILineInfoTable | ||
| } | ||
| } | ||
| } | ||
| return Table; | ||
| } else { | ||
| consumeError(FuncInfoOrErr.takeError()); | ||
| return DILineInfoTable(); | ||
| } | ||
| } | ||
| 
     | 
||
| DIInliningInfo | ||
| GsymDIContext::getInliningInfoForAddress(object::SectionedAddress Address, | ||
| DILineInfoSpecifier Specifier) { | ||
| auto ResultOrErr = Reader->lookup(Address.Address); | ||
| 
     | 
||
| if (!ResultOrErr) | ||
| return {}; | ||
| 
     | 
||
| const auto &Result = *ResultOrErr; | ||
| 
     | 
||
| DIInliningInfo InlineInfo; | ||
| 
     | 
||
| for (const auto &Location : Result.Locations) { | ||
| DILineInfo LineInfo; | ||
| 
     | 
||
| if (!fillLineInfoFromLocation(Location, Specifier, LineInfo)) | ||
| return {}; | ||
| 
     | 
||
| // Hm, that's probably something that should only be filled in the first or | ||
| // last frame? | ||
| LineInfo.StartAddress = Result.FuncRange.start(); | ||
| 
     | 
||
| InlineInfo.addFrame(LineInfo); | ||
| } | ||
| 
     | 
||
| return InlineInfo; | ||
| } | ||
| 
     | 
||
| std::vector<DILocal> | ||
| GsymDIContext::getLocalsForAddress(object::SectionedAddress Address) { | ||
| // We can't implement this, there's no such information in the GSYM file. | ||
| 
     | 
||
| return std::vector<DILocal>(); | ||
                
       | 
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we usually skip the braces if the body is just one line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. removed