1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

[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
This commit is contained in:
Jonas Devlieghere 2021-01-11 16:17:51 -08:00
parent 90ddcdef81
commit db48aa1fa2
4 changed files with 88 additions and 17 deletions

Binary file not shown.

View File

@ -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

View File

@ -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.