diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -1528,6 +1528,13 @@ Defined *funcSym; if (funcAddrRelocIt != isec->relocs.end()) { funcSym = targetSymFromCanonicalSubtractor(isec, funcAddrRelocIt); + // Canonicalize the symbol. If there are multiple symbols at the same + // address, we want both `registerEhFrame` and `registerCompactUnwind` + // to register the unwind entry under same symbol. + // This is not particularly efficient, but we should run into this case + // infrequently (only when handling the output of `ld -r`). + funcSym = findSymbolAtOffset(cast(funcSym->isec), + funcSym->value); } else { funcSym = findSymbolAtAddress(sections, funcAddr); ehRelocator.makePcRel(funcAddrOff, funcSym, target->p2WordSize); diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -211,7 +211,7 @@ // we use that as the key here. auto p = symbols.insert({{d->isec, d->value}, d}); // If we have multiple symbols at the same address, only one of them can have - // an associated CUE. + // an associated unwind entry. if (!p.second && d->unwindEntry) { assert(!p.first->second->unwindEntry); p.first->second = d; diff --git a/lld/test/MachO/Inputs/double-unwind-info.yaml b/lld/test/MachO/Inputs/double-unwind-info.yaml new file mode 100644 --- /dev/null +++ b/lld/test/MachO/Inputs/double-unwind-info.yaml @@ -0,0 +1,159 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x1 + ncmds: 4 + sizeofcmds: 384 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: '' + vmaddr: 0 + vmsize: 96 + fileoff: 448 + filesize: 96 + maxprot: 7 + initprot: 7 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 2 + offset: 0x1C0 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '9090' + - sectname: __eh_frame + segname: __TEXT + addr: 0x8 + size: 56 + offset: 0x1C8 + align: 3 + reloff: 0x220 + nreloc: 4 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C0708900100001C00000004000000F8FFFFFFFFFFFFFF0100000000000000000E080000000000 + relocations: + - address: 0x1C + symbolnum: 3 + pcrel: false + length: 2 + extern: true + type: 5 + scattered: false + value: 0 + - address: 0x1C + symbolnum: 4 + pcrel: false + length: 2 + extern: true + type: 0 + scattered: false + value: 0 + - address: 0x20 + symbolnum: 4 + pcrel: false + length: 3 + extern: true + type: 5 + scattered: false + value: 0 + - address: 0x20 + symbolnum: 2 + pcrel: false + length: 3 + extern: true + type: 0 + scattered: false + value: 0 + - sectname: __compact_unwind + segname: __LD + addr: 0x40 + size: 32 + offset: 0x200 + align: 3 + reloff: 0x240 + nreloc: 1 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000000010000000000010200000000000000000000000000000000' + relocations: + - address: 0x0 + symbolnum: 2 + pcrel: false + length: 3 + extern: true + type: 0 + scattered: false + value: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 584 + nsyms: 5 + stroff: 664 + strsize: 40 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 659200 + sdk: 0 + ntools: 1 + Tools: + - tool: 3 + version: 50069504 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 584 + datasize: 0 +LinkEditData: + NameList: + - n_strx: 2 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 10 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 1 + - n_strx: 16 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 1 + - n_strx: 21 + n_type: 0xE + n_sect: 2 + n_desc: 0 + n_value: 8 + - n_strx: 31 + n_type: 0xE + n_sect: 2 + n_desc: 0 + n_value: 32 + StringTable: + - ' ' + - _spacer + - ltmp1 + - _foo + - EH_Frame1 + - func.eh + - '' +... diff --git a/lld/test/MachO/double-unwind-info.s b/lld/test/MachO/double-unwind-info.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/double-unwind-info.s @@ -0,0 +1,26 @@ +## When changing the assembly input, uncomment these lines to re-generate the +## YAML. +# COM: llvm-mc --emit-dwarf-unwind=always -filetype=obj -triple=x86_64-apple-macos10.15 %s -o %t.o +# COM: ld -r %t.o -o %t-r.o +# COM: obj2yaml %t-r.o > %S/Inputs/double-unwind-info.yaml + +# RUN: yaml2obj %S/Inputs/double-unwind-info.yaml > %t-r.o +# RUN: %lld -dylib -lSystem %t-r.o -o /dev/null + +.text +## eh_frame function address relocations are only emitted if the function isn't +## at address 0x0. +_spacer: + nop + +## Check that we perform unwind info registration correctly when there are +## multiple symbols at the same address. This would previously hit an assertion +## error (PR56570). +_foo: +ltmp1: + .cfi_startproc + .cfi_def_cfa_offset 8 + nop + .cfi_endproc + +.subsections_via_symbols