[dsymutil] Add function size to the debug map.
authorFrederic Riss <friss@apple.com>
Sun, 15 Mar 2015 01:29:30 +0000 (01:29 +0000)
committerFrederic Riss <friss@apple.com>
Sun, 15 Mar 2015 01:29:30 +0000 (01:29 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232300 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/dsymutil/debug-map-parsing.test
tools/dsymutil/DebugMap.cpp
tools/dsymutil/DebugMap.h
tools/dsymutil/MachODebugMapParser.cpp

index b64ad9ff2e4d122814fa8638761a12e6eb3fba82..3422316191febc7add226baf5f0208ddfb733eb1 100644 (file)
@@ -10,16 +10,16 @@ Check that We can parse the debug map of the basic executable.
 CHECK-NOT: error
 CHECK: DEBUG MAP: x86_64-unknown-unknown-macho
 CHECK: /Inputs/basic1.macho.x86_64.o:
-CHECK:         0000000000000000 => 0000000100000ea0    _main
+CHECK:         0000000000000000 => 0000000100000ea0+0x24       _main
 CHECK: /Inputs/basic2.macho.x86_64.o:
-CHECK:         0000000000000310 => 0000000100001000    _baz
-CHECK:         0000000000000020 => 0000000100000ed0    _foo
-CHECK:         0000000000000070 => 0000000100000f20    _inc
-CHECK:         0000000000000560 => 0000000100001008    _private_int
+CHECK:         0000000000000310 => 0000000100001000+0x0        _baz
+CHECK:         0000000000000020 => 0000000100000ed0+0x50       _foo
+CHECK:         0000000000000070 => 0000000100000f20+0x17       _inc
+CHECK:         0000000000000560 => 0000000100001008+0x0        _private_int
 CHECK: /Inputs/basic3.macho.x86_64.o:
-CHECK:         0000000000000020 => 0000000100000f40    _bar
-CHECK:         0000000000000070 => 0000000100000f90    _inc
-CHECK:         0000000000000004 => 0000000100001004    _val
+CHECK:         0000000000000020 => 0000000100000f40+0x50       _bar
+CHECK:         0000000000000070 => 0000000100000f90+0x19       _inc
+CHECK:         0000000000000004 => 0000000100001004+0x0        _val
 CHECK: END DEBUG MAP
 
 
@@ -28,12 +28,12 @@ Check that we can parse the debug-map of the basic-lto executable
 CHECK-LTO-NOT: error
 CHECK-LTO: DEBUG MAP: x86_64-unknown-unknown-macho
 CHECK-LTO: /Inputs/basic-lto.macho.x86_64.o:
-CHECK-LTO:     0000000000000050 => 0000000100000f90    _bar
-CHECK-LTO:     0000000000000658 => 0000000100001000    _baz
-CHECK-LTO:     0000000000000010 => 0000000100000f50    _foo
-CHECK-LTO:     0000000000000000 => 0000000100000f40    _main
-CHECK-LTO:     00000000000008e8 => 0000000100001008    _private_int
-CHECK-LTO:     00000000000008ec => 0000000100001004    _val
+CHECK-LTO:     0000000000000050 => 0000000100000f90+0x24       _bar
+CHECK-LTO:     0000000000000658 => 0000000100001000+0x0        _baz
+CHECK-LTO:     0000000000000010 => 0000000100000f50+0x40       _foo
+CHECK-LTO:     0000000000000000 => 0000000100000f40+0x10       _main
+CHECK-LTO:     00000000000008e8 => 0000000100001008+0x0        _private_int
+CHECK-LTO:     00000000000008ec => 0000000100001004+0x0        _val
 CHECK-LTO: END DEBUG MAP
 
 Check thet we correctly handle debug maps with archive members (including only
@@ -51,16 +51,16 @@ CHECK-ARCHIVE-NEXT:         found member in current archive.
 CHECK-ARCHIVE: DEBUG MAP: x86_64-unknown-unknown-macho
 CHECK-ARCHIVE:       object addr =>  executable addr   symbol name
 CHECK-ARCHIVE: /Inputs/basic1.macho.x86_64.o:
-CHECK-ARCHIVE:         0000000000000000 => 0000000100000ea0    _main
+CHECK-ARCHIVE:         0000000000000000 => 0000000100000ea0+0x24       _main
 CHECK-ARCHIVE: /Inputs/./libbasic.a(basic2.macho.x86_64.o):
-CHECK-ARCHIVE:         0000000000000310 => 0000000100001000    _baz
-CHECK-ARCHIVE:         0000000000000020 => 0000000100000ed0    _foo
-CHECK-ARCHIVE:         0000000000000070 => 0000000100000f20    _inc
-CHECK-ARCHIVE:         0000000000000560 => 0000000100001004    _private_int
+CHECK-ARCHIVE:         0000000000000310 => 0000000100001000+0x0        _baz
+CHECK-ARCHIVE:         0000000000000020 => 0000000100000ed0+0x50       _foo
+CHECK-ARCHIVE:         0000000000000070 => 0000000100000f20+0x17       _inc
+CHECK-ARCHIVE:         0000000000000560 => 0000000100001004+0x0        _private_int
 CHECK-ARCHIVE: /Inputs/./libbasic.a(basic3.macho.x86_64.o):
-CHECK-ARCHIVE:         0000000000000020 => 0000000100000f40    _bar
-CHECK-ARCHIVE:         0000000000000070 => 0000000100000f90    _inc
-CHECK-ARCHIVE:         0000000000000004 => 0000000100001008    _val
+CHECK-ARCHIVE:         0000000000000020 => 0000000100000f40+0x50       _bar
+CHECK-ARCHIVE:         0000000000000070 => 0000000100000f90+0x19       _inc
+CHECK-ARCHIVE:         0000000000000004 => 0000000100001008+0x0        _val
 CHECK-ARCHIVE: END DEBUG MAP
 
 Check that we warn about missing object files (this presumes that the files aren't
index c04b2fe89f6d0dcc2bcc62022da11b18deb71628..9fa3f788a89f2fcdd7a1933085270ac67277a840 100644 (file)
@@ -23,9 +23,9 @@ DebugMapObject::DebugMapObject(StringRef ObjectFilename)
     : 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 @@ void DebugMapObject::print(raw_ostream &OS) const {
       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';
 }
index 5bcf7a53b99aa8984676830b53d0576edee57eb7..b24efa9f40507c4cf9cf8b9727de1a4adfac1c66 100644 (file)
@@ -101,8 +101,10 @@ public:
   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 @@ public:
   /// \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.
index 2f4a9876a24f2fa0fefa3c72c06b821714da64b5..bf64303b9eab2872ffcea0abffcbbc3837b98602 100644 (file)
@@ -51,6 +51,10 @@ private:
   /// 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 @@ 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
@@ -159,11 +164,18 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
       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 @@ 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.");
 }