[PATCH] D124223: [lld-macho] Fix ICF crash when comparing symbol relocs
Jez Ng via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 21 19:08:37 PDT 2022
int3 created this revision.
int3 added a reviewer: lld-macho.
Herald added projects: lld-macho, All.
int3 requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Previously, when encountering a symbol reloc located in a literal section, we
would look up the contents of the literal at the `symbol value + addend` offset
within the literal section. However, it seems that this offset is not guaranteed
to be valid. Instead, we should use just the symbol value to retrieve the
literal's contents, and compare the addend values separately. ld64 seems to do
this.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D124223
Files:
lld/MachO/ICF.cpp
lld/test/MachO/icf-literals.s
Index: lld/test/MachO/icf-literals.s
===================================================================
--- lld/test/MachO/icf-literals.s
+++ lld/test/MachO/icf-literals.s
@@ -7,6 +7,10 @@
# CHECK: _main:
# CHECK-NEXT: callq _foo2_ref
# CHECK-NEXT: callq _foo2_ref
+# CHECK-NEXT: callq _foo2_neg_offset_ref
+# CHECK-NEXT: callq _foo2_neg_offset_ref
+# CHECK-NEXT: callq _foo2_pos_offset_ref
+# CHECK-NEXT: callq _foo2_pos_offset_ref
# CHECK-NEXT: callq _bar2_ref
# CHECK-NEXT: callq _bar2_ref
# CHECK-NEXT: callq _baz2_ref
@@ -28,6 +32,10 @@
# CHECK-NEXT: [[#%.16x,QUX:]] l O __TEXT,__literals _qux2
# CHECK-NEXT: [[#%.16x,FOO_REF:]] l F __TEXT,__text _foo1_ref
# CHECK-NEXT: [[#%.16x,FOO_REF:]] l F __TEXT,__text _foo2_ref
+# CHECK-NEXT: [[#%.16x,FOO_NEG:]] l F __TEXT,__text _foo1_neg_offset_ref
+# CHECK-NEXT: [[#%.16x,FOO_NEG]] l F __TEXT,__text _foo2_neg_offset_ref
+# CHECK-NEXT: [[#%.16x,FOO_POS:]] l F __TEXT,__text _foo1_pos_offset_ref
+# CHECK-NEXT: [[#%.16x,FOO_POS]] l F __TEXT,__text _foo2_pos_offset_ref
# CHECK-NEXT: [[#%.16x,BAR_REF:]] l F __TEXT,__text _bar1_ref
# CHECK-NEXT: [[#%.16x,BAR_REF:]] l F __TEXT,__text _bar2_ref
# CHECK-NEXT: [[#%.16x,BAZ_REF:]] l F __TEXT,__text _baz1_ref
@@ -63,6 +71,18 @@
leaq _foo1(%rip), %rax
_foo2_ref:
leaq _foo2(%rip), %rax
+_foo1_neg_offset_ref:
+## Check that we can correctly handle `_foo1-32` even though it points outside
+## the __cstring section.
+ leaq _foo1-32(%rip), %rax
+_foo2_neg_offset_ref:
+ leaq _foo2-32(%rip), %rax
+_foo1_pos_offset_ref:
+ leaq _foo1+4(%rip), %rax
+_foo2_pos_offset_ref:
+## Although `_foo2+4` points at _bar1 in the input object file, we shouldn't
+## dedup references to _foo2+4 with references to _bar1.
+ leaq _foo2+4(%rip), %rax
_bar1_ref:
leaq _bar1(%rip), %rax
_bar2_ref:
@@ -101,6 +121,10 @@
_main:
callq _foo1_ref
callq _foo2_ref
+ callq _foo1_neg_offset_ref
+ callq _foo2_neg_offset_ref
+ callq _foo1_pos_offset_ref
+ callq _foo2_pos_offset_ref
callq _bar1_ref
callq _bar2_ref
callq _baz1_ref
Index: lld/MachO/ICF.cpp
===================================================================
--- lld/MachO/ICF.cpp
+++ lld/MachO/ICF.cpp
@@ -152,8 +152,15 @@
return ra.addend == rb.addend;
// Else we have two literal sections. References to them are equal iff their
// offsets in the output section are equal.
- return isecA->getOffset(valueA + ra.addend) ==
- isecB->getOffset(valueB + rb.addend);
+ if (ra.referent.is<Symbol *>())
+ // For symbol relocs, we compare the contents at the symbol address. We
+ // don't do `getOffset(value + addend)` because value + addend may not be
+ // a valid offset in the literal section.
+ return isecA->getOffset(valueA) == isecB->getOffset(valueB) &&
+ ra.addend == rb.addend;
+ else
+ // For section relocs, we compare the content at the section offset.
+ return isecA->getOffset(ra.addend) == isecB->getOffset(rb.addend);
};
return std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(),
f);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D124223.424353.patch
Type: text/x-patch
Size: 3165 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220422/2c27eae5/attachment.bin>
More information about the llvm-commits
mailing list