/// ELF relocation entry.
virtual bool hasRelocationAddend() const = 0;
- /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
- /// based on the target relocation type. If addend is not used returns 0.
+ /// getDefaultAddendForRelTy - Gets the default addend value for a
+ /// relocation entry based on the target ELF relocation type.
virtual long int getDefaultAddendForRelTy(unsigned RelTy) const = 0;
/// getRelTySize - Returns the size of relocatable field in bits
virtual unsigned getRelocationTySize(unsigned RelTy) const = 0;
+ /// isPCRelativeRel - True if the relocation type is pc relative
+ virtual bool isPCRelativeRel(unsigned RelTy) const = 0;
+
/// getJumpTableRelocationTy - Returns the machine relocation type used
/// to reference a jumptable.
virtual unsigned getAbsoluteLabelMachineRelTy() const = 0;
+
+ /// computeRelocation - Some relocatable fields could be relocated
+ /// directly, avoiding the emission of a relocation symbol, compute the
+ /// final relocation value for this symbol.
+ virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset,
+ unsigned RelTy) const = 0;
};
} // end llvm namespace
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(),
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();
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()) {
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
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
} 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);
}
}
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
}
- /// Return the relocation section of section 'S'. 'RelA' is true
- /// if the relocation section contains entries with addends.
- ELFSection &getRelocSection(std::string SName, bool RelA, unsigned Align) {
- std::string RelSName(".rel");
- unsigned SHdrTy = RelA ? ELFSection::SHT_RELA : ELFSection::SHT_REL;
-
- if (RelA) RelSName.append("a");
- RelSName.append(SName);
-
- return getSection(RelSName, SHdrTy, 0, Align);
- }
-
ELFSection &getNonExecStackSection() {
return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
}
ELFSection &getJumpTableSection();
ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE);
+ ELFSection &getRelocSection(ELFSection &S);
// Helpers for obtaining ELF specific info.
unsigned getGlobalELFBinding(const GlobalValue *GV);
void EmitSymbolTable();
void EmitStringTable();
void OutputSectionsAndSectionTable();
+ void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value,
+ unsigned Size);
unsigned SortSymbols();
};
}