Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,10 @@ void ObjectFileMachO::ProcessSegmentCommand(
uint32_t segment_sect_idx;
const lldb::user_id_t first_segment_sectID = context.NextSectionIdx + 1;

// 64 bit mach-o files have sections with 32 bit file offsets. If any section
// data end will exceed UINT32_MAX, then we need to do some bookkeeping to
// ensure we can access this data correctly.
uint64_t section_offset_adjust = 0;
const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects;
++segment_sect_idx) {
Expand All @@ -1697,6 +1701,16 @@ void ObjectFileMachO::ProcessSegmentCommand(
// isn't stored in the abstracted Sections.
m_mach_sections.push_back(sect64);

// Make sure we can load sections in mach-o files where some sections cross
// a 4GB boundary. llvm::MachO::section_64 have only 32 bit file offsets
// for the file offset of the section contents, so we need to track and
// sections that overflow and adjust the offsets accordingly.
const uint64_t section_file_offset =
(uint64_t)sect64.offset + section_offset_adjust;
const uint64_t end_section_offset = (uint64_t)sect64.offset + sect64.size;
if (end_section_offset >= UINT32_MAX)
section_offset_adjust += end_section_offset & 0xFFFFFFFF00000000ull;

if (add_section) {
ConstString section_name(
sect64.sectname, strnlen(sect64.sectname, sizeof(sect64.sectname)));
Expand Down Expand Up @@ -1736,13 +1750,13 @@ void ObjectFileMachO::ProcessSegmentCommand(
}

// Grow the section size as needed.
if (sect64.offset) {
if (section_file_offset) {
const lldb::addr_t segment_min_file_offset =
segment->GetFileOffset();
const lldb::addr_t segment_max_file_offset =
segment_min_file_offset + segment->GetFileSize();

const lldb::addr_t section_min_file_offset = sect64.offset;
const lldb::addr_t section_min_file_offset = section_file_offset;
const lldb::addr_t section_max_file_offset =
section_min_file_offset + sect64.size;
const lldb::addr_t new_file_offset =
Expand All @@ -1769,10 +1783,10 @@ void ObjectFileMachO::ProcessSegmentCommand(
// other sections.
sect64.addr, // File VM address == addresses as they are
// found in the object file
sect64.size, // VM size in bytes of this section
sect64.offset, // Offset to the data for this section in
sect64.size, // VM size in bytes of this section
section_file_offset, // Offset to the data for this section in
// the file
sect64.offset ? sect64.size : 0, // Size in bytes of
section_file_offset ? sect64.size : 0, // Size in bytes of
// this section as
// found in the file
sect64.align,
Expand All @@ -1792,14 +1806,14 @@ void ObjectFileMachO::ProcessSegmentCommand(
SectionSP section_sp(new Section(
segment_sp, module_sp, this, ++context.NextSectionIdx, section_name,
sect_type, sect64.addr - segment_sp->GetFileAddress(), sect64.size,
sect64.offset, sect64.offset == 0 ? 0 : sect64.size, sect64.align,
sect64.flags));
section_file_offset, section_file_offset == 0 ? 0 : sect64.size,
sect64.align, sect64.flags));
// Set the section to be encrypted to match the segment

bool section_is_encrypted = false;
if (!segment_is_encrypted && load_cmd.filesize != 0)
section_is_encrypted = context.EncryptedRanges.FindEntryThatContains(
sect64.offset) != nullptr;
section_file_offset) != nullptr;

section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted);
section_sp->SetPermissions(segment_permissions);
Expand Down
Binary file not shown.
13 changes: 13 additions & 0 deletions lldb/test/Shell/ObjectFile/MachO/section-overflow-binary.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
RUN: %lldb -b %p/Inputs/section-overflow-binary \
RUN: -o 'script dwarf = lldb.target.module[0].sections[0]' \
RUN: -o 'script section = dwarf.GetSubSectionAtIndex(0)' \
RUN: -o "script print(f'{section.GetName()} file_offset=0x{section.GetFileOffset():016x}')" \
RUN: -o 'script section = dwarf.GetSubSectionAtIndex(1)' \
RUN: -o "script print(f'{section.GetName()} file_offset=0x{section.GetFileOffset():016x}')" \
RUN: -o 'script section = dwarf.GetSubSectionAtIndex(2)' \
RUN: -o "script print(f'{section.GetName()} file_offset=0x{section.GetFileOffset():016x}')" \
RUN: | FileCheck %s

CHECK: __debug_abbrev file_offset=0x00000000fffffff0
CHECK: __debug_info file_offset=0x0000000100000010
CHECK: __debug_line file_offset=0x0000000300000010
Loading