@@ -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+ // 64 bit mach-o files have sections with 32 bit file offsets. If any section
1678+ // data end will exceed UINT32_MAX, then we need to do some bookkeeping to
1679+ // ensure we can access this data correctly.
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,16 @@ 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 sections in mach-o files where some sections cross
1705+ // a 4GB boundary. llvm::MachO::section_64 have only 32 bit file offsets
1706+ // for the file offset of the section contents, so we need to track and
1707+ // sections that overflow and adjust the offsets accordingly.
1708+ const uint64_t section_file_offset =
1709+ (uint64_t )sect64.offset + section_offset_adjust;
1710+ const uint64_t end_section_offset = (uint64_t )sect64.offset + sect64.size ;
1711+ if (end_section_offset >= UINT32_MAX)
1712+ section_offset_adjust += end_section_offset & 0xFFFFFFFF00000000ull ;
1713+
17001714 if (add_section) {
17011715 ConstString section_name (
17021716 sect64.sectname , strnlen (sect64.sectname , sizeof (sect64.sectname )));
@@ -1736,13 +1750,13 @@ void ObjectFileMachO::ProcessSegmentCommand(
17361750 }
17371751
17381752 // Grow the section size as needed.
1739- if (sect64. offset ) {
1753+ if (section_file_offset ) {
17401754 const lldb::addr_t segment_min_file_offset =
17411755 segment->GetFileOffset ();
17421756 const lldb::addr_t segment_max_file_offset =
17431757 segment_min_file_offset + segment->GetFileSize ();
17441758
1745- const lldb::addr_t section_min_file_offset = sect64. offset ;
1759+ const lldb::addr_t section_min_file_offset = section_file_offset ;
17461760 const lldb::addr_t section_max_file_offset =
17471761 section_min_file_offset + sect64.size ;
17481762 const lldb::addr_t new_file_offset =
@@ -1769,10 +1783,10 @@ void ObjectFileMachO::ProcessSegmentCommand(
17691783 // other sections.
17701784 sect64.addr , // File VM address == addresses as they are
17711785 // found in the object file
1772- sect64.size , // VM size in bytes of this section
1773- sect64. offset , // Offset to the data for this section in
1786+ sect64.size , // VM size in bytes of this section
1787+ section_file_offset , // Offset to the data for this section in
17741788 // the file
1775- sect64. offset ? sect64.size : 0 , // Size in bytes of
1789+ section_file_offset ? sect64.size : 0 , // Size in bytes of
17761790 // this section as
17771791 // found in the file
17781792 sect64.align ,
@@ -1792,14 +1806,14 @@ void ObjectFileMachO::ProcessSegmentCommand(
17921806 SectionSP section_sp (new Section (
17931807 segment_sp, module_sp, this , ++context.NextSectionIdx , section_name,
17941808 sect_type, sect64.addr - segment_sp->GetFileAddress (), sect64.size ,
1795- sect64. offset , sect64. offset == 0 ? 0 : sect64.size , sect64. align ,
1796- sect64.flags ));
1809+ section_file_offset, section_file_offset == 0 ? 0 : sect64.size ,
1810+ sect64.align , sect64. flags ));
17971811 // Set the section to be encrypted to match the segment
17981812
17991813 bool section_is_encrypted = false ;
18001814 if (!segment_is_encrypted && load_cmd.filesize != 0 )
18011815 section_is_encrypted = context.EncryptedRanges .FindEntryThatContains (
1802- sect64. offset ) != nullptr ;
1816+ section_file_offset ) != nullptr ;
18031817
18041818 section_sp->SetIsEncrypted (segment_is_encrypted || section_is_encrypted);
18051819 section_sp->SetPermissions (segment_permissions);
0 commit comments