llvm-symbolizer: Untag addresses in object files by default.
authorPeter Collingbourne <peter@pcc.me.uk>
Mon, 5 Aug 2019 20:59:25 +0000 (20:59 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Mon, 5 Aug 2019 20:59:25 +0000 (20:59 +0000)
Any addresses that we pass to llvm-symbolizer are going to be untagged,
while any HWASAN instrumented globals are going to be tagged in the
symbol table. Therefore we need to untag the addresses before using them.

Differential Revision: https://reviews.llvm.org/D65769

llvm-svn: 367926

llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
llvm/test/tools/llvm-symbolizer/untag-addresses.test [new file with mode: 0644]
llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp

index d3da28ca0b7bf47cb236f19537109aee9881a762..11599fc1797d8ad9356bc001832960876b601735 100644 (file)
@@ -39,6 +39,7 @@ public:
     bool UseSymbolTable = true;
     bool Demangle = true;
     bool RelativeAddresses = false;
+    bool UntagAddresses = false;
     std::string DefaultArch;
     std::vector<std::string> DsymHints;
     std::string FallbackDebugPath;
index 2765bf44d504d86a5061ea7ae0f268ed33033fde..03c5c6b8e10ed726ed830bfc3b198b3f8bb7ad4a 100644 (file)
@@ -43,10 +43,11 @@ getDILineInfoSpecifier(FunctionNameKind FNKind) {
 
 ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
 SymbolizableObjectFile::create(const object::ObjectFile *Obj,
-                               std::unique_ptr<DIContext> DICtx) {
+                               std::unique_ptr<DIContext> DICtx,
+                               bool UntagAddresses) {
   assert(DICtx);
   std::unique_ptr<SymbolizableObjectFile> res(
-      new SymbolizableObjectFile(Obj, std::move(DICtx)));
+      new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses));
   std::unique_ptr<DataExtractor> OpdExtractor;
   uint64_t OpdAddress = 0;
   // Find the .opd (function descriptor) section if any, for big-endian
@@ -103,8 +104,10 @@ SymbolizableObjectFile::create(const object::ObjectFile *Obj,
 }
 
 SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj,
-                                               std::unique_ptr<DIContext> DICtx)
-    : Module(Obj), DebugInfoContext(std::move(DICtx)) {}
+                                               std::unique_ptr<DIContext> DICtx,
+                                               bool UntagAddresses)
+    : Module(Obj), DebugInfoContext(std::move(DICtx)),
+      UntagAddresses(UntagAddresses) {}
 
 namespace {
 
@@ -172,6 +175,11 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
   if (!SymbolAddressOrErr)
     return errorToErrorCode(SymbolAddressOrErr.takeError());
   uint64_t SymbolAddress = *SymbolAddressOrErr;
+  if (UntagAddresses) {
+    // For kernel addresses, bits 56-63 need to be set, so we sign extend bit 55
+    // into bits 56-63 instead of masking them out.
+    SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8;
+  }
   if (OpdExtractor) {
     // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
     // function descriptors. The first word of the descriptor is a pointer to
index 9cab94178c1b245d357355220a27819b3ce45259..b5b9793a44d9992e9908fd806fb9123dbde2186b 100644 (file)
@@ -31,7 +31,8 @@ namespace symbolize {
 class SymbolizableObjectFile : public SymbolizableModule {
 public:
   static ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
-  create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx);
+  create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx,
+         bool UntagAddresses);
 
   DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset,
                            FunctionNameKind FNKind,
@@ -70,6 +71,7 @@ private:
 
   const object::ObjectFile *Module;
   std::unique_ptr<DIContext> DebugInfoContext;
+  bool UntagAddresses;
 
   struct SymbolDesc {
     uint64_t Addr;
@@ -85,7 +87,8 @@ private:
   std::vector<std::pair<SymbolDesc, StringRef>> Objects;
 
   SymbolizableObjectFile(const object::ObjectFile *Obj,
-                         std::unique_ptr<DIContext> DICtx);
+                         std::unique_ptr<DIContext> DICtx,
+                         bool UntagAddresses);
 };
 
 } // end namespace symbolize
index 6a619f8f2f37518a19257203dc9488814260ef64..51aa0d781f629717a039ee91097682a6401aaaa3 100644 (file)
@@ -418,8 +418,8 @@ Expected<SymbolizableModule *>
 LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj,
                                  std::unique_ptr<DIContext> Context,
                                  StringRef ModuleName) {
-  auto InfoOrErr =
-      SymbolizableObjectFile::create(Obj, std::move(Context));
+  auto InfoOrErr = SymbolizableObjectFile::create(Obj, std::move(Context),
+                                                  Opts.UntagAddresses);
   std::unique_ptr<SymbolizableModule> SymMod;
   if (InfoOrErr)
     SymMod = std::move(*InfoOrErr);
diff --git a/llvm/test/tools/llvm-symbolizer/untag-addresses.test b/llvm/test/tools/llvm-symbolizer/untag-addresses.test
new file mode 100644 (file)
index 0000000..aa4c5c5
--- /dev/null
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo DATA %t.o 0 | llvm-symbolizer | FileCheck --check-prefix=UNTAG %s
+# RUN: echo DATA %t.o 0 | llvm-symbolizer -untag-addresses=0 | FileCheck --check-prefix=NOUNTAG %s
+# RUN: echo DATA %t.o 0 | llvm-addr2line | FileCheck --check-prefix=NOUNTAG %s
+
+# UNTAG: foo
+# UNTAG: 0 4
+# NOUNTAG: ??
+# NOUNTAG: 0 0
+
+.data
+.globl foo
+.type foo, @object
+.size foo, 4
+foo = . + 0x1100000000000000
+.4byte 1
index ea94cf9b69a19212b133c9d15441c0c2ffe4e6a8..54ce87d47979082efc7f6cbb99597972c7ee253b 100644 (file)
@@ -55,6 +55,10 @@ static cl::opt<bool>
                          cl::desc("Interpret addresses as relative addresses"),
                          cl::ReallyHidden);
 
+static cl::opt<bool> ClUntagAddresses(
+    "untag-addresses", cl::init(true),
+    cl::desc("Remove memory tags from addresses before symbolization"));
+
 static cl::opt<bool>
     ClPrintInlining("inlining", cl::init(true),
                     cl::desc("Print all inlined frames for a given address"));
@@ -274,6 +278,7 @@ int main(int argc, char **argv) {
     ClDemangle.setInitialValue(false);
     ClPrintFunctions.setInitialValue(FunctionNameKind::None);
     ClPrintInlining.setInitialValue(false);
+    ClUntagAddresses.setInitialValue(false);
     ClOutputStyle.setInitialValue(DIPrinter::OutputStyle::GNU);
   }
 
@@ -290,6 +295,7 @@ int main(int argc, char **argv) {
   Opts.UseSymbolTable = ClUseSymbolTable;
   Opts.Demangle = ClDemangle;
   Opts.RelativeAddresses = ClUseRelativeAddress;
+  Opts.UntagAddresses = ClUntagAddresses;
   Opts.DefaultArch = ClDefaultArch;
   Opts.FallbackDebugPath = ClFallbackDebugPath;
   Opts.DWPName = ClDwpName;