diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -241,8 +241,6 @@ } // Process relocs by ascending address, i.e., ascending offset within isec std::vector &relocs = isec->relocs; - assert(is_sorted(relocs, - [](Reloc &a, Reloc &b) { return a.offset > b.offset; })); for (Reloc &r : reverse(relocs)) { ++relocCount; if (!target->hasAttr(r.type, RelocAttrBits::BRANCH)) diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -366,6 +366,7 @@ ArrayRef relInfos( reinterpret_cast(buf + sec.reloff), sec.nreloc); + auto subsecIt = subsecMap.rbegin(); for (size_t i = 0; i < relInfos.size(); i++) { // Paired relocations serve as Mach-O's method for attaching a // supplemental datum to a primary relocation record. ELF does not @@ -442,7 +443,19 @@ r.addend = referentOffset; } - InputSection *subsec = findContainingSubsection(subsecMap, &r.offset); + // Find the subsection that this relocation belongs to. + // Though not required by the Mach-O format, clang and gcc seem to emit + // relocations in order, so let's take advantage of it. + while (subsecIt != subsecMap.rend() && subsecIt->offset > r.offset) + ++subsecIt; + if (subsecIt == subsecMap.rend() || + subsecIt->offset + subsecIt->isec->getSize() <= r.offset) { + error(toString(this) + + ": relocations not sorted in reverse order of address"); + break; + } + InputSection *subsec = subsecIt->isec; + r.offset -= subsecIt->offset; subsec->relocs.push_back(r); if (isSubtrahend) { diff --git a/lld/test/MachO/invalid/unsorted-relocations.yaml b/lld/test/MachO/invalid/unsorted-relocations.yaml new file mode 100644 --- /dev/null +++ b/lld/test/MachO/invalid/unsorted-relocations.yaml @@ -0,0 +1,96 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not %lld -o %t %t.o 2>&1 | FileCheck %s -DFILE=%t.o +# +# CHECK: error: [[FILE]]: relocations not sorted in reverse order of address +# CHECk-EMPTY: + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x1 + ncmds: 2 + sizeofcmds: 280 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: '' + vmaddr: 0 + vmsize: 24 + fileoff: 312 + filesize: 24 + maxprot: 7 + initprot: 7 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 24 + offset: 0x138 + align: 0 + reloff: 0x150 + nreloc: 3 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '000000000000000000000000000000000000000000000000' + relocations: + - address: 0x0 + symbolnum: 1 + pcrel: false + length: 3 + extern: true + type: 0 + scattered: false + value: 0 + - address: 0x10 + symbolnum: 0 + pcrel: false + length: 3 + extern: true + type: 0 + scattered: false + value: 0 + - address: 0x8 + symbolnum: 2 + pcrel: false + length: 3 + extern: true + type: 0 + scattered: false + value: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 360 + nsyms: 3 + stroff: 408 + strsize: 16 +LinkEditData: + NameList: + - n_strx: 11 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 1 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 16 + - n_strx: 6 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 8 + StringTable: + - '' + - _baz + - _bar + - _foo +...