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:
parent
90ddcdef81
commit
db48aa1fa2
BIN
test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o
Normal file
BIN
test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.o
Normal file
Binary file not shown.
BIN
test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out
Executable file
BIN
test/tools/dsymutil/Inputs/private/tmp/eh_frame/eh_frame.out
Executable file
Binary file not shown.
25
test/tools/dsymutil/X86/eh_frame.test
Normal file
25
test/tools/dsymutil/X86/eh_frame.test
Normal 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
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user