A few fixes for llvm-symbolizer on Windows.

Specifically, this patch correctly respects the -demangle option,
and additionally adds a hidden --relative-address option allows
input addresses to be relative to the module load address instead
of absolute addresses into the image.

llvm-svn: 236653
diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
index 328bcc6..83f27c7 100644
--- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -14,43 +14,44 @@
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
 #include "llvm/Object/COFF.h"
 
 using namespace llvm;
 using namespace llvm::object;
 
 PDBContext::PDBContext(const COFFObjectFile &Object,
-                       std::unique_ptr<IPDBSession> PDBSession)
+                       std::unique_ptr<IPDBSession> PDBSession,
+                       bool RelativeAddress)
     : DIContext(CK_PDB), Session(std::move(PDBSession)) {
-  uint64_t ImageBase = 0;
-  if (Object.is64()) {
-    const pe32plus_header *Header = nullptr;
-    Object.getPE32PlusHeader(Header);
-    if (Header)
-      ImageBase = Header->ImageBase;
-  } else {
-    const pe32_header *Header = nullptr;
-    Object.getPE32Header(Header);
-    if (Header)
-      ImageBase = static_cast<uint64_t>(Header->ImageBase);
+  if (!RelativeAddress) {
+    uint64_t ImageBase = 0;
+    if (Object.is64()) {
+      const pe32plus_header *Header = nullptr;
+      Object.getPE32PlusHeader(Header);
+      if (Header)
+        ImageBase = Header->ImageBase;
+    } else {
+      const pe32_header *Header = nullptr;
+      Object.getPE32Header(Header);
+      if (Header)
+        ImageBase = static_cast<uint64_t>(Header->ImageBase);
+    }
+    Session->setLoadAddress(ImageBase);
   }
-  Session->setLoadAddress(ImageBase);
 }
 
 void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {}
 
 DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
                                              DILineInfoSpecifier Specifier) {
-  auto Symbol = Session->findSymbolByAddress(Address, PDB_SymType::None);
+  DILineInfo Result;
+  Result.FunctionName = getFunctionName(Address, Specifier.FNKind);
 
   uint32_t Length = 1;
-  DILineInfo Result;
+  std::unique_ptr<PDBSymbol> Symbol =
+      Session->findSymbolByAddress(Address, PDB_SymType::None);
   if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
-    if (Specifier.FNKind == DINameKind::LinkageName)
-      Result.FunctionName = Func->getUndecoratedName();
-    else if (Specifier.FNKind == DINameKind::ShortName)
-      Result.FunctionName = Func->getName();
-
     Length = Func->getLength();
   } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
     Length = Data->getLength();
@@ -101,3 +102,32 @@
   InlineInfo.addFrame(Frame);
   return InlineInfo;
 }
+
+std::string PDBContext::getFunctionName(uint64_t Address,
+                                        DINameKind NameKind) const {
+  if (NameKind == DINameKind::None)
+    return std::string();
+
+  if (NameKind == DINameKind::LinkageName) {
+    // It is not possible to get the mangled linkage name through a
+    // PDBSymbolFunc.  For that we have to specifically request a
+    // PDBSymbolPublicSymbol.
+    auto PublicSym =
+        Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
+    if (auto PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get()))
+      return PS->getName();
+  }
+
+  auto FuncSymbol =
+      Session->findSymbolByAddress(Address, PDB_SymType::Function);
+
+  // This could happen either if there was no public symbol (e.g. not
+  // external) or the user requested the short name.  In the former case,
+  // although they technically requested the linkage name, if the linkage
+  // name is not available we fallback to at least returning a non-empty
+  // string.
+  if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get()))
+      return Func->getName();
+
+  return std::string();
+}