[dsymutil] Add function size to the debug map.

The debug map embedded by ld64 in binaries conatins function sizes.
These sizes are less precise than the ones given by the debug information
(byte granularity vs linker atom granularity), but they might cover code
that is referenced in the line table but not in the DIE tree (that might
very well be a compiler bug that I need to investigate later).
Anyway, extracting that information is necessary to be able to mimic
dsymutil's behavior exactly.

llvm-svn: 232300
diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp
index c04b2fe..9fa3f78 100644
--- a/llvm/tools/dsymutil/DebugMap.cpp
+++ b/llvm/tools/dsymutil/DebugMap.cpp
@@ -23,9 +23,9 @@
     : Filename(ObjectFilename) {}
 
 bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
-                               uint64_t LinkedAddress) {
+                               uint64_t LinkedAddress, uint32_t Size) {
   auto InsertResult = Symbols.insert(
-      std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress)));
+      std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
 
   if (InsertResult.second)
     AddressToMapping[ObjectAddress] = &*InsertResult.first;
@@ -45,9 +45,9 @@
       Entries.begin(), Entries.end(),
       [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; });
   for (const auto &Sym : Entries) {
-    OS << format("\t%016" PRIx64 " => %016" PRIx64 "\t%s\n",
+    OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n",
                  Sym.second.ObjectAddress, Sym.second.BinaryAddress,
-                 Sym.first.data());
+                 Sym.second.Size, Sym.first.data());
   }
   OS << '\n';
 }
diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h
index 5bcf7a5..b24efa9f 100644
--- a/llvm/tools/dsymutil/DebugMap.h
+++ b/llvm/tools/dsymutil/DebugMap.h
@@ -101,8 +101,10 @@
   struct SymbolMapping {
     uint64_t ObjectAddress;
     uint64_t BinaryAddress;
-    SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress)
-        : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress) {}
+    uint32_t Size;
+    SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress, uint32_t Size)
+        : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress),
+          Size(Size) {}
   };
 
   typedef StringMapEntry<SymbolMapping> DebugMapEntry;
@@ -111,7 +113,7 @@
   /// \returns false if the symbol was already registered. The request
   /// is discarded in this case.
   bool addSymbol(llvm::StringRef SymName, uint64_t ObjectAddress,
-                 uint64_t LinkedAddress);
+                 uint64_t LinkedAddress, uint32_t Size);
 
   /// \brief Lookup a symbol mapping.
   /// \returns null if the symbol isn't found.
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 2f4a987..bf64303 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -51,6 +51,10 @@
   /// 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);
@@ -149,6 +153,7 @@
   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
@@ -159,11 +164,18 @@
       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:
@@ -174,7 +186,8 @@
   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.");
 }