[llvm-branch-commits] [llvm] 8a47d87 - [dsymutil] Copy eh_frame content into the dSYM companion file.

Jonas Devlieghere via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 12 19:55:36 PST 2021


Author: Jonas Devlieghere
Date: 2021-01-12T19:50:34-08:00
New Revision: 8a47d875b071823455931bbc119ca1e455559176

URL: https://github.com/llvm/llvm-project/commit/8a47d875b071823455931bbc119ca1e455559176
DIFF: https://github.com/llvm/llvm-project/commit/8a47d875b071823455931bbc119ca1e455559176.diff

LOG: [dsymutil] Copy eh_frame content into the dSYM companion file.

Copy over the __eh_frame from the binary into the dSYM. This helps
kernel developers that are working with only dSYMs (i.e. no binaries)
when debugging a core file. This only kicks in when the __eh_frame
exists in the linked binary. Most of the time ld64 will remove the
section in favor of compact unwind info. When it is emitted, it's
generally small enough and should not bloat the dSYM.

rdar://69774935

Differential revision: https://reviews.llvm.org/D94460

Added: 
    llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o
    llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out
    llvm/test/tools/dsymutil/X86/eh_frame.test

Modified: 
    llvm/tools/dsymutil/MachOUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o
new file mode 100644
index 000000000000..45ec4097c6a6
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o 
diff er

diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out b/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out
new file mode 100755
index 000000000000..1b5705db193d
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out 
diff er

diff  --git a/llvm/test/tools/dsymutil/X86/eh_frame.test b/llvm/test/tools/dsymutil/X86/eh_frame.test
new file mode 100644
index 000000000000..1e31a51cc5c2
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/eh_frame.test
@@ -0,0 +1,25 @@
+FIXME: Replace otool with llvm-objcopy --dump-section=__TEXT,__eh_frame.
+REQUIRES : system-darwin
+
+$ cat eh_frame.cpp
+int f1()
+{
+  volatile int i;
+  return i;
+}
+
+int main(int argc, char** argv)
+{
+  return f1();
+}
+
+$ clang eh_frame.cpp -g -c -o eh_frame.o
+$ ld -no_compact_unwind eh_frame.o -o eh_frame.out
+
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/eh_frame/eh_frame.out -o %t.dSYM
+RUN: dwarfdump --verify %t.dSYM
+RUN: otool -s __TEXT __eh_frame %p/../Inputs/private/tmp/eh_frame/eh_frame.out | FileCheck %s
+RUN: otool -s __TEXT __eh_frame %t.dSYM/Contents/Resources/DWARF/eh_frame.out | FileCheck %s
+
+CHECK: 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01
+CHECK: 10 0c 07 08 90 01 00 00

diff  --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index 0f38525e45c2..943af430584d 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -239,27 +239,36 @@ getSection(const object::MachOObjectFile &Obj,
 // Transfer \a Segment from \a Obj to the output file. This calls into \a Writer
 // to write these load commands directly in the output file at the current
 // position.
+//
 // The function also tries to find a hole in the address map to fit the __DWARF
 // segment of \a DwarfSegmentSize size. \a EndAddress is updated to point at the
 // highest segment address.
+//
 // When the __LINKEDIT segment is transferred, its offset and size are set resp.
 // to \a LinkeditOffset and \a LinkeditSize.
+//
+// When the eh_frame section is transferred, its offset and size are set resp.
+// to \a EHFrameOffset and \a EHFrameSize.
 template <typename SegmentTy>
 static void transferSegmentAndSections(
     const object::MachOObjectFile::LoadCommandInfo &LCI, SegmentTy Segment,
     const object::MachOObjectFile &Obj, MachObjectWriter &Writer,
-    uint64_t LinkeditOffset, uint64_t LinkeditSize, uint64_t DwarfSegmentSize,
-    uint64_t &GapForDwarf, uint64_t &EndAddress) {
+    uint64_t LinkeditOffset, uint64_t LinkeditSize, uint64_t EHFrameOffset,
+    uint64_t EHFrameSize, uint64_t DwarfSegmentSize, uint64_t &GapForDwarf,
+    uint64_t &EndAddress) {
   if (StringRef("__DWARF") == Segment.segname)
     return;
 
-  Segment.fileoff = Segment.filesize = 0;
-
-  if (StringRef("__LINKEDIT") == Segment.segname) {
+  if (StringRef("__TEXT") == Segment.segname && EHFrameSize > 0) {
+    Segment.fileoff = EHFrameOffset;
+    Segment.filesize = EHFrameSize;
+  } else if (StringRef("__LINKEDIT") == Segment.segname) {
     Segment.fileoff = LinkeditOffset;
     Segment.filesize = LinkeditSize;
     // Resize vmsize by rounding to the page size.
     Segment.vmsize = alignTo(LinkeditSize, 0x1000);
+  } else {
+    Segment.fileoff = Segment.filesize = 0;
   }
 
   // Check if the end address of the last segment and our current
@@ -280,7 +289,12 @@ static void transferSegmentAndSections(
   Writer.W.OS.write(reinterpret_cast<char *>(&Segment), sizeof(Segment));
   for (unsigned i = 0; i < nsects; ++i) {
     auto Sect = getSection(Obj, Segment, LCI, i);
-    Sect.offset = Sect.reloff = Sect.nreloc = 0;
+    if (StringRef("__eh_frame") == Sect.sectname) {
+      Sect.offset = EHFrameOffset;
+      Sect.reloff = Sect.nreloc = 0;
+    } else {
+      Sect.offset = Sect.reloff = Sect.nreloc = 0;
+    }
     if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
       MachO::swapStruct(Sect);
     Writer.W.OS.write(reinterpret_cast<char *>(&Sect), sizeof(Sect));
@@ -417,6 +431,27 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
     ++NumLoadCommands;
   }
 
+  // If we have a valid eh_frame to copy, do it.
+  uint64_t EHFrameSize = 0;
+  StringRef EHFrameData;
+  for (const object::SectionRef &Section : InputBinary.sections()) {
+    Expected<StringRef> NameOrErr = Section.getName();
+    if (!NameOrErr) {
+      consumeError(NameOrErr.takeError());
+      continue;
+    }
+    StringRef SectionName = *NameOrErr;
+    SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
+    if (SectionName == "eh_frame") {
+      if (Expected<StringRef> ContentsOrErr = Section.getContents()) {
+        EHFrameData = *ContentsOrErr;
+        EHFrameSize = Section.getSize();
+      } else {
+        consumeError(ContentsOrErr.takeError());
+      }
+    }
+  }
+
   unsigned HeaderSize =
       Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
   // We will copy every segment that isn't __DWARF.
@@ -496,7 +531,10 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
     Writer.writeSymtabLoadCommand(SymtabStart, NumSyms, StringStart,
                                   NewStringsSize);
 
-  uint64_t DwarfSegmentStart = StringStart + NewStringsSize;
+  uint64_t EHFrameStart = StringStart + NewStringsSize;
+  EHFrameStart = alignTo(EHFrameStart, 0x1000);
+
+  uint64_t DwarfSegmentStart = EHFrameStart + EHFrameSize;
   DwarfSegmentStart = alignTo(DwarfSegmentStart, 0x1000);
 
   // Write the load commands for the segments and sections we 'import' from
@@ -505,15 +543,15 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
   uint64_t GapForDwarf = UINT64_MAX;
   for (auto &LCI : InputBinary.load_commands()) {
     if (LCI.C.cmd == MachO::LC_SEGMENT)
-      transferSegmentAndSections(LCI, InputBinary.getSegmentLoadCommand(LCI),
-                                 InputBinary, Writer, SymtabStart,
-                                 StringStart + NewStringsSize - SymtabStart,
-                                 DwarfSegmentSize, GapForDwarf, EndAddress);
+      transferSegmentAndSections(
+          LCI, InputBinary.getSegmentLoadCommand(LCI), InputBinary, Writer,
+          SymtabStart, StringStart + NewStringsSize - SymtabStart, EHFrameStart,
+          EHFrameSize, DwarfSegmentSize, GapForDwarf, EndAddress);
     else if (LCI.C.cmd == MachO::LC_SEGMENT_64)
-      transferSegmentAndSections(LCI, InputBinary.getSegment64LoadCommand(LCI),
-                                 InputBinary, Writer, SymtabStart,
-                                 StringStart + NewStringsSize - SymtabStart,
-                                 DwarfSegmentSize, GapForDwarf, EndAddress);
+      transferSegmentAndSections(
+          LCI, InputBinary.getSegment64LoadCommand(LCI), InputBinary, Writer,
+          SymtabStart, StringStart + NewStringsSize - SymtabStart, EHFrameStart,
+          EHFrameSize, DwarfSegmentSize, GapForDwarf, EndAddress);
   }
 
   uint64_t DwarfVMAddr = alignTo(EndAddress, 0x1000);
@@ -554,11 +592,19 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
                     EntryRef.getString().size() + 1);
     }
   }
-
   assert(OutFile.tell() == StringStart + NewStringsSize);
 
+  // Pad till the EH frame start.
+  OutFile.write_zeros(EHFrameStart - (StringStart + NewStringsSize));
+  assert(OutFile.tell() == EHFrameStart);
+
+  // Transfer eh_frame.
+  if (EHFrameSize > 0)
+    OutFile << EHFrameData;
+  assert(OutFile.tell() == EHFrameStart + EHFrameSize);
+
   // Pad till the Dwarf segment start.
-  OutFile.write_zeros(DwarfSegmentStart - (StringStart + NewStringsSize));
+  OutFile.write_zeros(DwarfSegmentStart - (EHFrameStart + EHFrameSize));
   assert(OutFile.tell() == DwarfSegmentStart);
 
   // Emit the Dwarf sections contents.


        


More information about the llvm-branch-commits mailing list