diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -72,10 +72,17 @@ // Sort symbols by address. We want to print out symbols in the // order in the output file rather than the order they appeared // in the input files. - for (auto &it : ret) + SmallPtrSet set; + for (auto &it : ret) { + // Deduplicate symbols which need a canonical PLT entry/copy relocation. + set.clear(); + llvm::erase_if(it.second, + [&](Defined *sym) { return !set.insert(sym).second; }); + llvm::stable_sort(it.second, [](Defined *a, Defined *b) { return a->getVA() < b->getVA(); }); + } return ret; } diff --git a/lld/test/ELF/map-file-copy.s b/lld/test/ELF/map-file-copy.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/map-file-copy.s @@ -0,0 +1,52 @@ +# REQUIRES: x86 + +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/1.s -o %t/1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/2.s -o %t/2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/3.s -o %t/3.o +# RUN: ld.lld -shared -soname=3 --version-script=%t/3.ver %t/3.o -o %t/3.so +# RUN: ld.lld -Map=%t/1.map %t/1.o %t/2.o %t/3.so -o %t/1 +# RUN: FileCheck %s --input-file=%t/1.map + +## Both TUs reference func/copy which need a canonical PLT entry/copy relocation. +## Test we print func/copy just once. +# CHECK: {{ }}.plt +# CHECK-NEXT: :(.plt) +# CHECK-NEXT: func@v1{{$}} +# CHECK-NEXT: .dynamic + +# CHECK: .bss.rel.ro +# CHECK-NEXT: :(.bss.rel.ro) +## Ideally this is displayed as copy@v2. +# CHECK-NEXT: copy{{$}} +# CHECK-NEXT: .got.plt + +#--- 1.s +.global _start +_start: +.symver func, func@@@v1 + mov $copy, %eax + mov $func - ., %eax + +#--- 2.s +.symver func, func@@@v1 + mov $copy, %eax + mov $func - ., %eax + +#--- 3.s +.globl func +.symver func, func@v1, remove +.type func, @function +func: + ret + +.section .rodata,"a" +.globl copy +.type copy, @object +copy: +.byte 1 +.size copy, 1 + +#--- 3.ver +v1 { func; }; +v2 { copy; };