summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@freebsd.org>2014-01-07 20:17:03 +0000
committerRoman Divacky <rdivacky@freebsd.org>2014-01-07 20:17:03 +0000
commit5a1c54999d6e008dd4111701c14721b77838c929 (patch)
tree7bc5970c6cdcb728d375b966d50ff64f7fd227fb /llvm/lib
parent92e28e876d67f8f632dee423eeacde5e9f31227f (diff)
downloadbcm5719-llvm-5a1c54999d6e008dd4111701c14721b77838c929.tar.gz
bcm5719-llvm-5a1c54999d6e008dd4111701c14721b77838c929.zip
In the ELFWriter when writing aliased (.set) symbols dont blindly
take type from the new symbol but merge them so that the type is never "downgraded". This is probably quite rare, except for IFUNC symbols which we used to misassemble, losing the IFUNC type. Fixes #18372. llvm-svn: 198706
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MC/ELFObjectWriter.cpp37
1 files changed, 36 insertions, 1 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 6a48d62c8e1..9490a9941ac 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -532,6 +532,41 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
}
}
+static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
+ uint8_t Type = newType;
+
+ // Propagation rules:
+ // IFUNC > FUNC > OBJECT > NOTYPE
+ // TLS_OBJECT > OBJECT > NOTYPE
+ //
+ // dont let the new type degrade the old type
+ switch (origType) {
+ default:
+ break;
+ case ELF::STT_GNU_IFUNC:
+ if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
+ Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS)
+ Type = ELF::STT_GNU_IFUNC;
+ break;
+ case ELF::STT_FUNC:
+ if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
+ Type == ELF::STT_TLS)
+ Type = ELF::STT_FUNC;
+ break;
+ case ELF::STT_OBJECT:
+ if (Type == ELF::STT_NOTYPE)
+ Type = ELF::STT_OBJECT;
+ break;
+ case ELF::STT_TLS:
+ if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
+ Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC)
+ Type = ELF::STT_TLS;
+ break;
+ }
+
+ return Type;
+}
+
void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
MCDataFragment *ShndxF,
ELFSymbolData &MSD,
@@ -545,7 +580,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
// Binding and Type share the same byte as upper and lower nibbles
uint8_t Binding = MCELF::GetBinding(OrigData);
- uint8_t Type = MCELF::GetType(Data);
+ uint8_t Type = mergeTypeForSet(MCELF::GetType(OrigData), MCELF::GetType(Data));
uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift);
// Other and Visibility share the same byte with Visibility using the lower
OpenPOWER on IntegriCloud