aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/ELFWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/ELFWriter.cpp')
-rw-r--r--lib/CodeGen/ELFWriter.cpp80
1 files changed, 53 insertions, 27 deletions
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 527adb821e..f04efd5c8c 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -145,7 +145,7 @@ bool ELFWriter::doInitialization(Module &M) {
return false;
}
-/// Get jump table section on the section name returned by TAI
+// Get jump table section on the section name returned by TAI
ELFSection &ELFWriter::getJumpTableSection() {
unsigned Align = TM.getTargetData()->getPointerABIAlignment();
return getSection(TAI->getJumpTableDataSection(),
@@ -153,7 +153,7 @@ ELFSection &ELFWriter::getJumpTableSection() {
ELFSection::SHF_ALLOC, Align);
}
-/// Get a constant pool section based on the section name returned by TAI
+// Get a constant pool section based on the section name returned by TAI
ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
std::string CstPoolName =
TAI->SelectSectionForMachineConst(CPE.getType())->getName();
@@ -163,6 +163,19 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
CPE.getAlignment());
}
+// Return the relocation section of section 'S'. 'RelA' is true
+// if the relocation section contains entries with addends.
+ELFSection &ELFWriter::getRelocSection(ELFSection &S) {
+ unsigned SectionHeaderTy = TEW->hasRelocationAddend() ?
+ ELFSection::SHT_RELA : ELFSection::SHT_REL;
+ std::string RelSName(".rel");
+ if (TEW->hasRelocationAddend())
+ RelSName.append("a");
+ RelSName.append(S.getName());
+
+ return getSection(RelSName, SectionHeaderTy, 0, TEW->getPrefELFAlignment());
+}
+
// getGlobalELFVisibility - Returns the ELF specific visibility type
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
switch (GV->getVisibility()) {
@@ -474,20 +487,32 @@ bool ELFWriter::doFinalization(Module &M) {
return false;
}
+// RelocateField - Patch relocatable field with 'Offset' in 'BO'
+// using a 'Value' of known 'Size'
+void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset,
+ int64_t Value, unsigned Size) {
+ if (Size == 32)
+ BO.fixWord32(Value, Offset);
+ else if (Size == 64)
+ BO.fixWord64(Value, Offset);
+ else
+ llvm_unreachable("don't know howto patch relocatable field");
+}
+
/// EmitRelocations - Emit relocations
void ELFWriter::EmitRelocations() {
+ // True if the target uses the relocation entry to hold the addend,
+ // otherwise the addend is written directly to the relocatable field.
+ bool HasRelA = TEW->hasRelocationAddend();
+
// Create Relocation sections for each section which needs it.
for (unsigned i=0, e=SectionList.size(); i != e; ++i) {
ELFSection &S = *SectionList[i];
// This section does not have relocations
if (!S.hasRelocations()) continue;
-
- // Get the relocation section for section 'S'
- bool HasRelA = TEW->hasRelocationAddend();
- ELFSection &RelSec = getRelocSection(S.getName(), HasRelA,
- TEW->getPrefELFAlignment());
+ ELFSection &RelSec = getRelocSection(S);
// 'Link' - Section hdr idx of the associated symbol table
// 'Info' - Section hdr idx of the section to which the relocation applies
@@ -502,18 +527,15 @@ void ELFWriter::EmitRelocations() {
MRE = Relos.end(); MRI != MRE; ++MRI) {
MachineRelocation &MR = *MRI;
- // Holds the relocatable field address as an offset from the
- // beginning of the section where it lives
- unsigned Offset = MR.getMachineCodeOffset();
+ // Relocatable field offset from the section start
+ unsigned RelOffset = MR.getMachineCodeOffset();
// Symbol index in the symbol table
unsigned SymIdx = 0;
- // Target specific ELF relocation type
+ // Target specific relocation field type and size
unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
-
- // Constant addend used to compute the value to be stored
- // into the relocatable field
+ unsigned RelTySize = TEW->getRelocationTySize(RelType);
int64_t Addend = 0;
// There are several machine relocations types, and each one of
@@ -533,29 +555,33 @@ void ELFWriter::EmitRelocations() {
} else {
// Get the symbol index for the section symbol
unsigned SectionIdx = MR.getConstantVal();
+ SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
+ Addend = (uint64_t)MR.getResultPointer();
+
+ // For pc relative relocations where symbols are defined in the same
+ // section they are referenced, ignore the relocation entry and patch
+ // the relocatable field with the symbol offset directly.
+ if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) {
+ int64_t Value = TEW->computeRelocation(Addend, RelOffset, RelType);
+ RelocateField(S, RelOffset, Value, RelTySize);
+ continue;
+ }
// Handle Jump Table Index relocation
if ((SectionIdx == getJumpTableSection().SectionIdx) &&
- TEW->hasCustomJumpTableIndexRelTy())
+ TEW->hasCustomJumpTableIndexRelTy()) {
RelType = TEW->getJumpTableIndexRelTy();
-
- SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
- Addend = (uint64_t)MR.getResultPointer();
+ RelTySize = TEW->getRelocationTySize(RelType);
+ }
}
// The target without addend on the relocation symbol must be
// patched in the relocation place itself to contain the addend
- if (!HasRelA) {
- if (TEW->getRelocationTySize(RelType) == 32)
- S.fixWord32(Addend, Offset);
- else if (TEW->getRelocationTySize(RelType) == 64)
- S.fixWord64(Addend, Offset);
- else
- llvm_unreachable("don't know howto patch relocatable field");
- }
+ if (!HasRelA)
+ RelocateField(S, RelOffset, Addend, RelTySize);
// Get the relocation entry and emit to the relocation section
- ELFRelocation Rel(Offset, SymIdx, RelType, HasRelA, Addend);
+ ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend);
EmitRelocation(RelSec, Rel, HasRelA);
}
}