diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh index a7b78f885eea4..fe49d944d3a2f 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -145,7 +145,7 @@ if [[ ! -f ${LLVM_BUILD}/build.ninja ]]; then $LLVM_SRC fi cd ${LLVM_BUILD} -ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI LLVMTargetParser LLVMCore +ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMDebugInfoGSYM LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI LLVMTargetParser LLVMCore cd ${BUILD_DIR} rm -rf ${SYMBOLIZER_BUILD} @@ -174,6 +174,7 @@ $LINK $LIBCXX_ARCHIVE_DIR/libc++.a \ $LLVM_BUILD/lib/libLLVMObject.a \ $LLVM_BUILD/lib/libLLVMBinaryFormat.a \ $LLVM_BUILD/lib/libLLVMDebugInfoDWARF.a \ + $LLVM_BUILD/lib/libLLVMDebugInfoGSYM.a \ $LLVM_BUILD/lib/libLLVMSupport.a \ $LLVM_BUILD/lib/libLLVMDebugInfoPDB.a \ $LLVM_BUILD/lib/libLLVMDebugInfoMSF.a \ diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h index c90b99987f1db..0347f90c236d1 100644 --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -238,7 +238,7 @@ struct DIDumpOptions { class DIContext { public: - enum DIContextKind { CK_DWARF, CK_PDB, CK_BTF }; + enum DIContextKind { CK_DWARF, CK_PDB, CK_BTF, CK_GSYM }; DIContext(DIContextKind K) : Kind(K) {} virtual ~DIContext() = default; diff --git a/llvm/include/llvm/DebugInfo/GSYM/GsymDIContext.h b/llvm/include/llvm/DebugInfo/GSYM/GsymDIContext.h new file mode 100644 index 0000000000000..396c08c608d25 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/GSYM/GsymDIContext.h @@ -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 +#include +#include + +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 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 getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + std::optional + 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 + getLocalsForAddress(object::SectionedAddress Address) override; + +private: + const std::unique_ptr Reader; +}; + +} // end namespace gsym + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBCONTEXT_H diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h index 5747ad99d0f13..7c6beaa2189b7 100644 --- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -58,11 +58,13 @@ class LLVMSymbolizer { bool RelativeAddresses = false; bool UntagAddresses = false; bool UseDIA = false; + bool DisableGsym = false; std::string DefaultArch; std::vector DsymHints; std::string FallbackDebugPath; std::string DWPName; std::vector DebugFileDirectory; + std::vector GsymFileDirectory; size_t MaxCacheSize = sizeof(size_t) == 4 ? 512 * 1024 * 1024 /* 512 MiB */ @@ -177,6 +179,7 @@ class LLVMSymbolizer { ObjectFile *lookUpBuildIDObject(const std::string &Path, const ELFObjectFileBase *Obj, const std::string &ArchName); + std::string lookUpGsymFile(const std::string &Path); bool findDebugBinary(const std::string &OrigPath, const std::string &DebuglinkName, uint32_t CRCHash, diff --git a/llvm/lib/DebugInfo/GSYM/CMakeLists.txt b/llvm/lib/DebugInfo/GSYM/CMakeLists.txt index c27d648db62f6..724b5b213d643 100644 --- a/llvm/lib/DebugInfo/GSYM/CMakeLists.txt +++ b/llvm/lib/DebugInfo/GSYM/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_component_library(LLVMDebugInfoGSYM FileWriter.cpp FunctionInfo.cpp GsymCreator.cpp + GsymDIContext.cpp GsymReader.cpp InlineInfo.cpp LineTable.cpp diff --git a/llvm/lib/DebugInfo/GSYM/GsymDIContext.cpp b/llvm/lib/DebugInfo/GSYM/GsymDIContext.cpp new file mode 100644 index 0000000000000..68024a9c9e782 --- /dev/null +++ b/llvm/lib/DebugInfo/GSYM/GsymDIContext.cpp @@ -0,0 +1,166 @@ +//===-- 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 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(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 +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 +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 +GsymDIContext::getLocalsForAddress(object::SectionedAddress Address) { + // We can't implement this, there's no such information in the GSYM file. + + return {}; +} diff --git a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt index 29f62bf6156fc..7aef3b0d79a3a 100644 --- a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt +++ b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt @@ -10,6 +10,7 @@ add_llvm_component_library(LLVMSymbolize LINK_COMPONENTS DebugInfoDWARF + DebugInfoGSYM DebugInfoPDB DebugInfoBTF Object diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 1d8217ad587ec..78a1421005de2 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -15,6 +15,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/BTF/BTFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/GSYM/GsymDIContext.h" +#include "llvm/DebugInfo/GSYM/GsymReader.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBContext.h" #include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h" @@ -498,6 +500,34 @@ bool LLVMSymbolizer::getOrFindDebugBinary(const ArrayRef BuildID, return false; } +std::string LLVMSymbolizer::lookUpGsymFile(const std::string &Path) { + if (Opts.DisableGsym) + return {}; + + auto CheckGsymFile = [](const llvm::StringRef &GsymPath) { + sys::fs::file_status Status; + std::error_code EC = llvm::sys::fs::status(GsymPath, Status); + return !EC && !llvm::sys::fs::is_directory(Status); + }; + + // First, look beside the binary file + if (const auto GsymPath = Path + ".gsym"; CheckGsymFile(GsymPath)) + return GsymPath; + + // Then, look in the directories specified by GsymFileDirectory + + for (const auto &Directory : Opts.GsymFileDirectory) { + SmallString<16> GsymPath = llvm::StringRef{Directory}; + llvm::sys::path::append(GsymPath, + llvm::sys::path::filename(Path) + ".gsym"); + + if (CheckGsymFile(GsymPath)) + return static_cast(GsymPath); + } + + return {}; +} + Expected LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, const std::string &ArchName) { @@ -634,30 +664,48 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) { std::unique_ptr Context; // If this is a COFF object containing PDB info and not containing DWARF // section, use a PDBContext to symbolize. Otherwise, use DWARF. - if (auto CoffObject = dyn_cast(Objects.first)) { - const codeview::DebugInfo *DebugInfo; - StringRef PDBFileName; - auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName); - // Use DWARF if there're DWARF sections. - bool HasDwarf = - llvm::any_of(Objects.first->sections(), [](SectionRef Section) -> bool { - if (Expected SectionName = Section.getName()) - return SectionName.get() == ".debug_info"; - return false; - }); - if (!EC && !HasDwarf && DebugInfo != nullptr && !PDBFileName.empty()) { - using namespace pdb; - std::unique_ptr Session; - - PDB_ReaderType ReaderType = - Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native; - if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(), - Session)) { - Modules.emplace(ModuleName, std::unique_ptr()); - // Return along the PDB filename to provide more context - return createFileError(PDBFileName, std::move(Err)); + // Create a DIContext to symbolize as follows: + // - If there is a GSYM file, create a GsymDIContext. + // - Otherwise, if this is a COFF object containing PDB info, create a + // PDBContext. + // - Otherwise, create a DWARFContext. + const auto GsymFile = lookUpGsymFile(BinaryName.str()); + if (!GsymFile.empty()) { + auto ReaderOrErr = gsym::GsymReader::openFile(GsymFile); + + if (ReaderOrErr) { + std::unique_ptr Reader = + std::make_unique(std::move(*ReaderOrErr)); + + Context = std::make_unique(std::move(Reader)); + } + } + if (!Context) { + if (auto CoffObject = dyn_cast(Objects.first)) { + const codeview::DebugInfo *DebugInfo; + StringRef PDBFileName; + auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName); + // Use DWARF if there're DWARF sections. + bool HasDwarf = llvm::any_of( + Objects.first->sections(), [](SectionRef Section) -> bool { + if (Expected SectionName = Section.getName()) + return SectionName.get() == ".debug_info"; + return false; + }); + if (!EC && !HasDwarf && DebugInfo != nullptr && !PDBFileName.empty()) { + using namespace pdb; + std::unique_ptr Session; + + PDB_ReaderType ReaderType = + Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native; + if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(), + Session)) { + Modules.emplace(ModuleName, std::unique_ptr()); + // Return along the PDB filename to provide more context + return createFileError(PDBFileName, std::move(Err)); + } + Context.reset(new PDBContext(*CoffObject, std::move(Session))); } - Context.reset(new PDBContext(*CoffObject, std::move(Session))); } } if (!Context) diff --git a/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe b/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe new file mode 100755 index 0000000000000..f6f013b245822 Binary files /dev/null and b/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe differ diff --git a/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe.gsym b/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe.gsym new file mode 100644 index 0000000000000..a46f78b9d880c Binary files /dev/null and b/llvm/test/tools/llvm-symbolizer/Inputs/addr-gsymonly.exe.gsym differ diff --git a/llvm/test/tools/llvm-symbolizer/sym-gsymonly.test b/llvm/test/tools/llvm-symbolizer/sym-gsymonly.test new file mode 100644 index 0000000000000..0d00c002a2bdb --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/sym-gsymonly.test @@ -0,0 +1,93 @@ +# This test is a variant of sym.test. It uses a binary without DWARF debug +# info, but a corresponding .gsym file. The expectations are the same, except +# for the fact that GSYM doesn't provide us with column numbers. +# +# Source: +# #include +# static inline int inctwo (int *a) { +# printf ("%d\n",(*a)++); +# return (*a)++; +# } +# static inline int inc (int *a) { +# printf ("%d\n",inctwo(a)); +# return (*a)++; +# } +# +# +# int main () { +# int x = 1; +# return inc(&x); +# } +# +# Build as : clang -g -O2 addr.c +extrat gsym file as : llvm-gsymutil --convert=%p/Inputs/addr.exe --out-file=%p/Inputs/addr-gsymonly.exe.gsym +strip debug as : llvm-objcopy --strip-debug %p/Inputs/addr.exe %p/Inputs/addr-gsymonly.exe + + +RUN: llvm-symbolizer --print-address --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck %s +RUN: llvm-symbolizer --addresses --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck %s +RUN: llvm-symbolizer -a --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck %s + +CHECK: ??:0:0 +CHECK-EMPTY: +CHECK-NEXT: 0x40054d +CHECK-NEXT: inctwo +CHECK-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:3:0 +CHECK-NEXT: inc +CHECK-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:7:0 +CHECK-NEXT: main +CHECK-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:14:0 +CHECK-EMPTY: +CHECK-NEXT: ?? +CHECK-NEXT: ??:0:0 + +RUN: llvm-symbolizer --inlining --print-address --pretty-print --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s +RUN: llvm-symbolizer --inlining --print-address -p --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s +RUN: llvm-symbolizer --inlines --print-address --pretty-print --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s +RUN: llvm-symbolizer --inlines --print-address -p --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s +RUN: llvm-symbolizer -i --print-address --pretty-print --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s +RUN: llvm-symbolizer -i --print-address -p --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s + +# Before 2020-08-04, asan_symbolize.py passed --inlining=true. +# Support this compatibility alias for a while. +RUN: llvm-symbolizer --inlining=true --print-address -p --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix="PRETTY" %s + +PRETTY: ??:0:0 +PRETTY: {{[0x]+}}40054d: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3:0 +PRETTY: (inlined by) inc at {{[/\]+}}tmp{{[/\]+}}x.c:7:0 +PRETTY: (inlined by) main at {{[/\]+}}tmp{{[/\]+}}x.c:14:0 +PRETTY: ??:0:0 + +RUN: llvm-addr2line --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefix=A2L %s +RUN: llvm-addr2line -a --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_A %s +RUN: llvm-addr2line -f --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_F %s +RUN: llvm-addr2line -i --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_I %s +RUN: llvm-addr2line -fi --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2L,A2L_F,A2L_I,A2L_FI %s + +RUN: llvm-addr2line -pa --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_A %s +RUN: llvm-addr2line -pf --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_F %s +RUN: llvm-addr2line -paf --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_AF %s +RUN: llvm-addr2line -pai --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_A,A2LP_I %s +RUN: llvm-addr2line -pfi --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_F,A2LP_FI %s +RUN: llvm-addr2line -pafi --obj=%p/Inputs/addr-gsymonly.exe < %p/Inputs/addr.inp | FileCheck -check-prefixes=A2LP,A2LP_AF,A2LP_FI %s + +A2L: ??:0 +A2L_A-NEXT: 0x40054d +A2L_F-NEXT: inctwo +A2L-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:3{{$}} +A2L_FI-NEXT: inc{{$}} +A2L_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:7{{$}} +A2L_FI-NEXT: main +A2L_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:14{{$}} +A2L_F-NEXT: ?? +A2L-NEXT: ??:0 + +A2LP: ??:0 +A2LP_A-NEXT: 0x40054d: {{[/\]+}}tmp{{[/\]+}}x.c:3{{$}} +A2LP_F-NEXT: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3{{$}} +A2LP_AF-NEXT: 0x40054d: inctwo at {{[/\]+}}tmp{{[/\]+}}x.c:3{{$}} +A2LP_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:7{{$}} +A2LP_I-NEXT: {{[/\]+}}tmp{{[/\]+}}x.c:14{{$}} +A2LP_FI-NEXT: (inlined by) inc at {{[/\]+}}tmp{{[/\]+}}x.c:7{{$}} +A2LP_FI-NEXT: (inlined by) main at {{[/\]+}}tmp{{[/\]+}}x.c:14{{$}} +A2LP-NEXT: ??:0 diff --git a/llvm/tools/llvm-symbolizer/Opts.td b/llvm/tools/llvm-symbolizer/Opts.td index d0b227af9db46..10f1e6dbbddf7 100644 --- a/llvm/tools/llvm-symbolizer/Opts.td +++ b/llvm/tools/llvm-symbolizer/Opts.td @@ -16,6 +16,9 @@ class F: Flag<["--"], name>, HelpText; def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-symbolizer Mach-O Specific Options">; +def grp_gsym : OptionGroup<"kind">, + HelpText<"llvm-symbolizer GSYM Related Options">; + def addresses : F<"addresses", "Show address before line information">; defm adjust_vma : Eq<"adjust-vma", "Add specified offset to object file addresses">, @@ -31,9 +34,11 @@ defm default_arch : Eq<"default-arch", "Default architecture (for multi-arch objects)">, Group; defm demangle : B<"demangle", "Demangle function names", "Don't demangle function names">; +def disable_gsym : F<"disable-gsym", "Don't consider using GSYM files for symbolication">, Group; def filter_markup : Flag<["--"], "filter-markup">, HelpText<"Filter symbolizer markup from stdin.">; def functions : F<"functions", "Print function name for a given address">; def functions_EQ : Joined<["--"], "functions=">, HelpText<"Print function name for a given address">, Values<"none,short,linkage">; +defm gsym_file_directory : Eq<"gsym-file-directory", "Path to directory where to look for GSYM files">, MetaVarName<"">, Group; def help : F<"help", "Display this help">; defm dwp : Eq<"dwp", "Path to DWP file to be use for any split CUs">, MetaVarName<"">; defm dsym_hint diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 3ba7f59d5b847..b80f79200ba42 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -499,6 +499,8 @@ int llvm_symbolizer_main(int argc, char **argv, const llvm::ToolContext &) { Opts.DWPName = Args.getLastArgValue(OPT_dwp_EQ).str(); Opts.FallbackDebugPath = Args.getLastArgValue(OPT_fallback_debug_path_EQ).str(); + Opts.GsymFileDirectory = Args.getAllArgValues(OPT_gsym_file_directory_EQ); + Opts.DisableGsym = Args.hasArg(OPT_disable_gsym); Opts.PrintFunctions = decideHowToPrintFunctions(Args, IsAddr2Line); parseIntArg(Args, OPT_print_source_context_lines_EQ, Config.SourceContextLines); diff --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/GSYM/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/GSYM/BUILD.gn index cadd34ddd908a..157fa6e885afc 100644 --- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/GSYM/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/GSYM/BUILD.gn @@ -12,6 +12,7 @@ static_library("GSYM") { "FileWriter.cpp", "FunctionInfo.cpp", "GsymCreator.cpp", + "GsymDIContext.cpp", "GsymReader.cpp", "Header.cpp", "InlineInfo.cpp",