summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-12-17 16:45:04 -0800
committerFangrui Song <maskray@google.com>2019-12-29 23:05:11 -0800
commitbb87364f26ce6b1fbb2cc5e155fd8ff82aafbe8d (patch)
tree94d733f419e1b8308cc9a3b2c9670726c676aa8f /lld/ELF
parentfb2944bd7f8ac6d7c4bccd3ac2033ba58c690038 (diff)
downloadbcm5719-llvm-bb87364f26ce6b1fbb2cc5e155fd8ff82aafbe8d.tar.gz
bcm5719-llvm-bb87364f26ce6b1fbb2cc5e155fd8ff82aafbe8d.zip
[ELF][PPC64] Improve "call lacks nop" diagnostic and make it compatible with GCC<5.5 and GCC<6.4
GCC before r245813 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79439) did not emit nop after b/bl. This can happen with recursive calls. r245813 was back ported to GCC 5.5 and GCC 6.4. This is common, for example, libstdc++.a(locale.o) shipped with GCC 4.9 and many objects in netlib lapack can cause lld to error. gold allows such calls to the same section. Our __plt_foo symbol's `section` field is used for ThunkSection, so we can't implement a similar loosen rule easily. But we can make use of its `file` field which is currently NULL. Differential Revision: https://reviews.llvm.org/D71639
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/InputSection.cpp12
-rw-r--r--lld/ELF/Thunks.cpp1
2 files changed, 11 insertions, 2 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 959dcb8533d..7dceddb5659 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -971,8 +971,16 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
// Patch a nop (0x60000000) to a ld.
if (rel.sym->needsTocRestore) {
- if (bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) {
- error(getErrorLocation(bufLoc) + "call lacks nop, can't restore toc");
+ // gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for
+ // recursive calls even if the function is preemptible. This is not
+ // wrong in the common case where the function is not preempted at
+ // runtime. Just ignore.
+ if ((bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) &&
+ rel.sym->file != file) {
+ // Use substr(6) to remove the "__plt_" prefix.
+ errorOrWarn(getErrorLocation(bufLoc) + "call to " +
+ lld::toString(*rel.sym).substr(6) +
+ " lacks nop, can't restore toc");
break;
}
write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 446c88c92d9..7b927a434e3 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -786,6 +786,7 @@ void PPC64PltCallStub::addSymbols(ThunkSection &isec) {
Defined *s = addSymbol(saver.save("__plt_" + destination.getName()), STT_FUNC,
0, isec);
s->needsTocRestore = true;
+ s->file = destination.file;
}
void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
OpenPOWER on IntegriCloud