aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@arm.com>2016-05-20 18:11:27 +0100
committerPeter Smith <peter.smith@arm.com>2016-05-24 09:40:06 +0100
commit4a3ae84d63da3b5f01aa870febc928eb6b05c218 (patch)
treebc898ad8f77dc770f4822ad388cfc4953bef4de4
parent828ade39dc0888d6b5366553ccd75bc06a2b381c (diff)
Add relocations and GOT entries for undefined weak referenceslinaro-local/ARMport
It is far from clear that this is the best way of doing this. More investigation is needed to check the GNU behaviour for undefined weak references. It may just be better to add these as shared references regardless if a GOT generating relocation is needed. Also corrected some relocation entries. Change-Id: I8256816e40e2474264c6c9193080d6cb65b1cd9f
-rw-r--r--ELF/Symbols.cpp2
-rw-r--r--ELF/Target.cpp26
-rw-r--r--ELF/Writer.cpp32
3 files changed, 41 insertions, 19 deletions
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 2f7749ffc..c349a8ace 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -264,7 +264,7 @@ bool Symbol::includeInDynsym() const {
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return false;
return (ExportDynamic && VersionScriptGlobal) || body()->isShared() ||
- (body()->isUndefined() && Config->Shared);
+ (body()->isUndefined() && (Config->Shared || isWeak()));
}
template InputFile *SymbolBody::template getSourceFile<ELF32LE>();
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index d1e8a9c92..af285c369 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -1268,19 +1268,24 @@ RelExpr ARMTargetInfo::getRelExpr(uint32_t Type,
default:
return R_ABS;
case R_ARM_CALL:
- case R_ARM_PLT32:
if (!S.isLocal() && S.symbol()->isWeak() && S.isUndefined())
return R_ARM_UNDEF_WEAK_PC;
+ case R_ARM_PLT32:
+ case R_ARM_PC24:
case R_ARM_JUMP24:
- return (S.isPreemptible()) ? R_PLT_PC : R_PC;
+ return (S.isPreemptible() || S.isUndefined()) ? R_PLT_PC : R_PC;
case R_ARM_GOTOFF32:
- return R_GOT_OFF;
- case R_ARM_GOT_BREL:
+ // ((S + A) - GOT_ORG
return R_GOTREL;
+ case R_ARM_GOT_BREL:
+ // GOT(S) + A - GOT_ORG
+ return R_GOT_OFF;
case R_ARM_GOT_PREL:
+ // GOT(S) + A - P
return R_GOT_PC;
case R_ARM_BASE_PREL:
// Fixme, This is only true if S is _GLOBAL_OFFSET_TABLE_
+ // B(S) + A - P
return R_PC;
case R_ARM_PREL31:
// Fixme, this probably needs special handling
@@ -1373,6 +1378,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
break;
case R_ARM_CALL:
case R_ARM_JUMP24:
+ case R_ARM_PC24:
case R_ARM_PLT32:
checkInt<26>(Val, Type);
write32le(Loc,
@@ -1412,16 +1418,16 @@ uint64_t ARMTargetInfo::getImplicitAddend(const uint8_t *Buf,
break;
case R_ARM_CALL:
case R_ARM_JUMP24:
+ case R_ARM_PC24:
case R_ARM_PLT32:
return SignExtend32<26>((read32le(Buf) & 0x00ffffff) << 2);
- case R_ARM_MOVW_ABS_NC: {
- int64_t Val = read32le(Buf) & ~0x000f0fff;
- return ((Val & 0x000f0000) >> 4) | (Val & 0x00fff);
- }
+ case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS: {
+ // ELF for the ARM Architecture, the interpretation for the initial
+ // addend for MOVW and MOVT is always in range -32768 <= A < 32768
int64_t Val = read32le(Buf) & ~0x000f0fff;
- return ((Val & 0x000f0000) << 12) | (Val & 0x00fff) << 16;
- }
+ return SignExtend32<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
+ }
}
}
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 6738327c6..f0bb2ffd2 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -512,7 +512,7 @@ static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body,
bool Preemptible = Body.isPreemptible();
if (Body.isGnuIFunc())
Expr = toPlt(Expr);
- else if (needsPlt(Expr) && !Preemptible)
+ else if (needsPlt(Expr) && !Preemptible && !Body.isUndefined())
Expr = fromPlt(Expr);
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
@@ -626,12 +626,15 @@ void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
};
const elf::ObjectFile<ELFT> &File = *C.getFile();
+ llvm::outs() << "Scan Relocs for File: " << File.getName() << "\n";
ArrayRef<uint8_t> SectionData = C.getSectionData();
const uint8_t *Buf = SectionData.begin();
for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) {
const RelTy &RI = *I;
SymbolBody &Body = File.getRelocTargetSym(RI);
uint32_t Type = RI.getType(Config->Mips64EL);
+ if (!Body.isLocal())
+ llvm::outs() << "Target Symbol: " << Body.getName() << "\n";
RelExpr Expr = Target->getRelExpr(Type, Body);
// Ignore "hint" relocation because it is for optional code optimization.
@@ -720,9 +723,15 @@ void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
else
Rel = Target->PltRel;
+ if (Body.isUndefined() && Body.symbol() && Body.symbol()->isWeak()) {
+ Symbol *S = Body.symbol();
+ S->ExportDynamic=1;
+ }
+
Out<ELFT>::GotPlt->addEntry(Body);
Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
- Body.getGotPltOffset<ELFT>(), !Preemptible,
+ Body.getGotPltOffset<ELFT>(),
+ !Preemptible && !Body.isUndefined(),
&Body, 0});
continue;
}
@@ -740,16 +749,22 @@ void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
continue;
- if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) {
+ if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body)) ||
+ (!Body.isLocal() && Body.isUndefined())) {
uint32_t DynType;
if (Body.isTls())
DynType = Target->TlsGotRel;
- else if (Preemptible)
+ else if (Preemptible || (!Body.isLocal() && Body.isUndefined())) {
DynType = Target->GotRel;
+ if (Body.isUndefined() && Body.symbol() && Body.symbol()->isWeak()) {
+ Symbol *S = Body.symbol();
+ S->ExportDynamic=1;
+ }
+ }
else
DynType = Target->RelativeRel;
AddDyn({DynType, Out<ELFT>::Got, Body.getGotOffset<ELFT>(),
- !Preemptible, &Body, 0});
+ !Preemptible && !Body.isUndefined(), &Body, 0});
}
continue;
}
@@ -1235,8 +1250,8 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
if (!Config->Relocatable) {
if(Config->EMachine == EM_ARM) {
// ARM Requires _GLOBAL_OFFSET_TABLE_ to be at the base of the
- // .got.plt section
- addOptionalSynthetic(Symtab, "_GLOBAL_OFFSET_TABLE_", Out<ELFT>::GotPlt,
+ // .got
+ addOptionalSynthetic(Symtab, "_GLOBAL_OFFSET_TABLE_", Out<ELFT>::Got,
0);
}
else
@@ -1383,7 +1398,8 @@ template <class ELFT> void Writer<ELFT>::createSections() {
std::vector<DefinedCommon *> CommonSymbols;
for (Symbol *S : Symtab.getSymbols()) {
SymbolBody *Body = S->body();
-
+ if (!Body->isLocal())
+ llvm::outs() << "Symbol for output " << Body->getName() << "\n";
// Set "used" bit for --as-needed.
if (S->IsUsedInRegularObj && !S->isWeak())
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))