Skip to content

Commit 1673e1b

Browse files
committed
Enable LLDB to load large dSYM files.
llvm-dsymutil can produce mach-o files where some sections in __DWARF exceed the 4GB barrier and subsequent sections in the dSYM will be inaccessible because the mach-o section_64 structure only has a 32 bit file offset. This patch enables LLDB to load a large dSYM file by figuring out when this happens and properly adjusting the file offset of the LLDB sections. I was unable to add a test as obj2yaml and yaml2obj are broken for mach-o files and they can't convert a yaml file back into a valid mach-o object file. Any suggestions for adding a test would be appreciated.
1 parent 975fba1 commit 1673e1b

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,10 @@ void ObjectFileMachO::ProcessSegmentCommand(
16741674
uint32_t segment_sect_idx;
16751675
const lldb::user_id_t first_segment_sectID = context.NextSectionIdx + 1;
16761676

1677+
// dSYM files can create sections whose data exceeds the 4GB barrier, but
1678+
// mach-o sections only have 32 bit offsets. So keep track of when we
1679+
// overflow and fix the sections offsets as we iterate.
1680+
uint64_t section_offset_adjust = 0;
16771681
const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
16781682
for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects;
16791683
++segment_sect_idx) {
@@ -1697,6 +1701,14 @@ void ObjectFileMachO::ProcessSegmentCommand(
16971701
// isn't stored in the abstracted Sections.
16981702
m_mach_sections.push_back(sect64);
16991703

1704+
// Make sure we can load dSYM files whose __DWARF sections exceed the 4GB
1705+
// barrier. llvm::MachO::section_64 have only 32 bit file offsets for the
1706+
// section contents.
1707+
const uint64_t section_file_offset = sect64.offset + section_offset_adjust;
1708+
// If this section overflows a 4GB barrier, then we need to adjust any
1709+
// subsequent the section offsets.
1710+
if (is_dsym && ((uint64_t)sect64.offset + sect64.size) >= UINT32_MAX)
1711+
section_offset_adjust += 0x100000000ull;
17001712
if (add_section) {
17011713
ConstString section_name(
17021714
sect64.sectname, strnlen(sect64.sectname, sizeof(sect64.sectname)));
@@ -1736,13 +1748,13 @@ void ObjectFileMachO::ProcessSegmentCommand(
17361748
}
17371749

17381750
// Grow the section size as needed.
1739-
if (sect64.offset) {
1751+
if (section_file_offset) {
17401752
const lldb::addr_t segment_min_file_offset =
17411753
segment->GetFileOffset();
17421754
const lldb::addr_t segment_max_file_offset =
17431755
segment_min_file_offset + segment->GetFileSize();
17441756

1745-
const lldb::addr_t section_min_file_offset = sect64.offset;
1757+
const lldb::addr_t section_min_file_offset = section_file_offset;
17461758
const lldb::addr_t section_max_file_offset =
17471759
section_min_file_offset + sect64.size;
17481760
const lldb::addr_t new_file_offset =
@@ -1770,9 +1782,9 @@ void ObjectFileMachO::ProcessSegmentCommand(
17701782
sect64.addr, // File VM address == addresses as they are
17711783
// found in the object file
17721784
sect64.size, // VM size in bytes of this section
1773-
sect64.offset, // Offset to the data for this section in
1785+
section_file_offset, // Offset to the data for this section in
17741786
// the file
1775-
sect64.offset ? sect64.size : 0, // Size in bytes of
1787+
section_file_offset ? sect64.size : 0, // Size in bytes of
17761788
// this section as
17771789
// found in the file
17781790
sect64.align,
@@ -1792,14 +1804,14 @@ void ObjectFileMachO::ProcessSegmentCommand(
17921804
SectionSP section_sp(new Section(
17931805
segment_sp, module_sp, this, ++context.NextSectionIdx, section_name,
17941806
sect_type, sect64.addr - segment_sp->GetFileAddress(), sect64.size,
1795-
sect64.offset, sect64.offset == 0 ? 0 : sect64.size, sect64.align,
1796-
sect64.flags));
1807+
section_file_offset, section_file_offset == 0 ? 0 : sect64.size,
1808+
sect64.align, sect64.flags));
17971809
// Set the section to be encrypted to match the segment
17981810

17991811
bool section_is_encrypted = false;
18001812
if (!segment_is_encrypted && load_cmd.filesize != 0)
18011813
section_is_encrypted = context.EncryptedRanges.FindEntryThatContains(
1802-
sect64.offset) != nullptr;
1814+
section_file_offset) != nullptr;
18031815

18041816
section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted);
18051817
section_sp->SetPermissions(segment_permissions);

0 commit comments

Comments
 (0)