Simplify getSymbolType.
[oota-llvm.git] / tools / dsymutil / MachODebugMapParser.cpp
index 6fabe00ac919bd71f182ac6fcf907039ccb00e69..16b95b5567056104c5d1d985bb6a5572ad721d00 100644 (file)
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "dsymutil.h"
 #include "llvm/Object/MachO.h"
@@ -20,8 +21,11 @@ using namespace llvm::object;
 
 class MachODebugMapParser {
 public:
-  MachODebugMapParser(StringRef BinaryPath, StringRef PathPrefix = "")
-      : BinaryPath(BinaryPath), PathPrefix(PathPrefix) {}
+  MachODebugMapParser(StringRef BinaryPath, StringRef PathPrefix = "",
+                      bool Verbose = false)
+      : BinaryPath(BinaryPath), PathPrefix(PathPrefix),
+        MainBinaryHolder(Verbose), CurrentObjectHolder(Verbose),
+        CurrentDebugMapObject(nullptr) {}
 
   /// \brief Parses and returns the DebugMap of the input binary.
   /// \returns an error in case the provided BinaryPath doesn't exist
@@ -32,21 +36,25 @@ private:
   std::string BinaryPath;
   std::string PathPrefix;
 
-  /// OwningBinary constructed from the BinaryPath.
-  object::OwningBinary<object::MachOObjectFile> MainOwningBinary;
+  /// Owns the MemoryBuffer for the main binary.
+  BinaryHolder MainBinaryHolder;
   /// Map of the binary symbol addresses.
   StringMap<uint64_t> MainBinarySymbolAddresses;
   StringRef MainBinaryStrings;
   /// The constructed DebugMap.
   std::unique_ptr<DebugMap> Result;
 
-  /// Handle to the currently processed object file.
-  object::OwningBinary<object::MachOObjectFile> CurrentObjectFile;
+  /// Owns the MemoryBuffer for the currently handled object file.
+  BinaryHolder CurrentObjectHolder;
   /// Map of the currently processed object file symbol addresses.
   StringMap<uint64_t> CurrentObjectAddresses;
   /// Element of the debug map corresponfing to the current object file.
   DebugMapObject *CurrentDebugMapObject;
 
+  /// Holds function info while function scope processing.
+  const char *CurrentFunctionName;
+  uint64_t CurrentFunctionAddress;
+
   void switchToNewDebugMapObject(StringRef Filename);
   void resetParserState();
   uint64_t getMainBinarySymbolAddress(StringRef Name);
@@ -65,26 +73,10 @@ private:
 static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; }
 }
 
-static ErrorOr<OwningBinary<MachOObjectFile>>
-createMachOBinary(StringRef File) {
-  auto MemBufOrErr = MemoryBuffer::getFile(File);
-  if (auto Error = MemBufOrErr.getError())
-    return Error;
-
-  MemoryBufferRef BufRef = (*MemBufOrErr)->getMemBufferRef();
-  auto MachOOrErr = ObjectFile::createMachOObjectFile(BufRef);
-  if (auto Error = MachOOrErr.getError())
-    return Error;
-
-  return OwningBinary<MachOObjectFile>(std::move(*MachOOrErr),
-                                       std::move(*MemBufOrErr));
-}
-
 /// Reset the parser state coresponding to the current object
 /// file. This is to be called after an object file is finished
 /// processing.
 void MachODebugMapParser::resetParserState() {
-  CurrentObjectFile = OwningBinary<object::MachOObjectFile>();
   CurrentObjectAddresses.clear();
   CurrentDebugMapObject = nullptr;
 }
@@ -98,30 +90,35 @@ void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename) {
   SmallString<80> Path(PathPrefix);
   sys::path::append(Path, Filename);
 
-  auto MachOOrError = createMachOBinary(Path);
+  auto MachOOrError = CurrentObjectHolder.GetFileAs<MachOObjectFile>(Path);
   if (auto Error = MachOOrError.getError()) {
     Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
             Error.message() + "\n");
     return;
   }
 
-  CurrentObjectFile = std::move(*MachOOrError);
   loadCurrentObjectFileSymbols();
   CurrentDebugMapObject = &Result->addDebugMapObject(Path);
 }
 
+static Triple getTriple(const object::MachOObjectFile &Obj) {
+  Triple TheTriple("unknown-unknown-unknown");
+  TheTriple.setArch(Triple::ArchType(Obj.getArch()));
+  TheTriple.setObjectFormat(Triple::MachO);
+  return TheTriple;
+}
+
 /// This main parsing routine tries to open the main binary and if
 /// successful iterates over the STAB entries. The real parsing is
 /// done in handleStabSymbolTableEntry.
 ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
-  auto MainBinaryOrError = createMachOBinary(BinaryPath);
-  if (auto Error = MainBinaryOrError.getError())
+  auto MainBinOrError = MainBinaryHolder.GetFileAs<MachOObjectFile>(BinaryPath);
+  if (auto Error = MainBinOrError.getError())
     return Error;
 
-  MainOwningBinary = std::move(*MainBinaryOrError);
+  const MachOObjectFile &MainBinary = *MainBinOrError;
   loadMainBinarySymbols();
-  Result = make_unique<DebugMap>();
-  const auto &MainBinary = *MainOwningBinary.getBinary();
+  Result = make_unique<DebugMap>(getTriple(MainBinary));
   MainBinaryStrings = MainBinary.getStringTableData();
   for (const SymbolRef &Symbol : MainBinary.symbols()) {
     const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
@@ -156,21 +153,29 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
   if (!CurrentDebugMapObject)
     return;
 
+  uint32_t Size = 0;
   switch (Type) {
   case MachO::N_GSYM:
     // This is a global variable. We need to query the main binary
     // symbol table to find its address as it might not be in the
     // debug map (for common symbols).
     Value = getMainBinarySymbolAddress(Name);
-    if (Value == UnknownAddressOrSize)
+    if (Value == UnknownAddress)
       return;
     break;
   case MachO::N_FUN:
-    // Functions are scopes in STABS. They have an end marker that we
-    // need to ignore.
-    if (Name[0] == '\0')
+    // Functions are scopes in STABS. They have an end marker that
+    // contains the function size.
+    if (Name[0] == '\0') {
+      Size = Value;
+      Value = CurrentFunctionAddress;
+      Name = CurrentFunctionName;
+      break;
+    } else {
+      CurrentFunctionName = Name;
+      CurrentFunctionAddress = Value;
       return;
-    break;
+    }
   case MachO::N_STSYM:
     break;
   default:
@@ -181,7 +186,8 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
   if (ObjectSymIt == CurrentObjectAddresses.end())
     return Warning("could not find object file symbol for symbol " +
                    Twine(Name));
-  if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value))
+  if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
+                                        Size))
     return Warning(Twine("failed to insert symbol '") + Name +
                    "' in the debug map.");
 }
@@ -189,13 +195,11 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
 /// Load the current object file symbols into CurrentObjectAddresses.
 void MachODebugMapParser::loadCurrentObjectFileSymbols() {
   CurrentObjectAddresses.clear();
-  const auto &Binary = *CurrentObjectFile.getBinary();
 
-  for (auto Sym : Binary.symbols()) {
+  for (auto Sym : CurrentObjectHolder.Get().symbols()) {
     StringRef Name;
     uint64_t Addr;
-    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
-        Sym.getName(Name))
+    if (Sym.getAddress(Addr) || Addr == UnknownAddress || Sym.getName(Name))
       continue;
     CurrentObjectAddresses[Name] = Addr;
   }
@@ -207,20 +211,19 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols() {
 uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
   auto Sym = MainBinarySymbolAddresses.find(Name);
   if (Sym == MainBinarySymbolAddresses.end())
-    return UnknownAddressOrSize;
+    return UnknownAddress;
   return Sym->second;
 }
 
 /// Load the interesting main binary symbols' addresses into
 /// MainBinarySymbolAddresses.
 void MachODebugMapParser::loadMainBinarySymbols() {
-  const MachOObjectFile &Binary = *MainOwningBinary.getBinary();
-  section_iterator Section = Binary.section_end();
-  for (const auto &Sym : Binary.symbols()) {
-    SymbolRef::Type Type;
+  const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs<MachOObjectFile>();
+  section_iterator Section = MainBinary.section_end();
+  for (const auto &Sym : MainBinary.symbols()) {
+    SymbolRef::Type Type = Sym.getType();
     // Skip undefined and STAB entries.
-    if (Sym.getType(Type) || (Type & SymbolRef::ST_Debug) ||
-        (Type & SymbolRef::ST_Unknown))
+    if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown))
       continue;
     StringRef Name;
     uint64_t Addr;
@@ -228,7 +231,7 @@ void MachODebugMapParser::loadMainBinarySymbols() {
     // are the only ones that need to be queried because the address
     // of common data won't be described in the debug map. All other
     // addresses should be fetched for the debug map.
-    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
+    if (Sym.getAddress(Addr) || Addr == UnknownAddress ||
         !(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) ||
         Section->isText() || Sym.getName(Name) || Name.size() == 0 ||
         Name[0] == '\0')
@@ -241,9 +244,14 @@ namespace llvm {
 namespace dsymutil {
 llvm::ErrorOr<std::unique_ptr<DebugMap>> parseDebugMap(StringRef InputFile,
                                                        StringRef PrependPath,
-                                                       bool Verbose) {
-  MachODebugMapParser Parser(InputFile, PrependPath);
-  return Parser.parse();
+                                                       bool Verbose,
+                                                       bool InputIsYAML) {
+  if (!InputIsYAML) {
+    MachODebugMapParser Parser(InputFile, PrependPath, Verbose);
+    return Parser.parse();
+  } else {
+    return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
+  }
 }
 }
 }