mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
Add more methods to gather target specific elf stuff
Support for .text relocations, implementing TargetELFWriter overloaded methods for x86/x86_64. Use a map to track global values to their symbol table indexes Code cleanup and small fixes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73894 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -61,6 +61,11 @@ public:
|
|||||||
return Relocations;
|
return Relocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// hasRelocations - Return true if 'Relocations' is not empty
|
||||||
|
bool hasRelocations() const {
|
||||||
|
return !Relocations.empty();
|
||||||
|
}
|
||||||
|
|
||||||
/// emitByte - This callback is invoked when a byte needs to be
|
/// emitByte - This callback is invoked when a byte needs to be
|
||||||
/// written to the data stream.
|
/// written to the data stream.
|
||||||
inline void emitByte(uint8_t B) {
|
inline void emitByte(uint8_t B) {
|
||||||
@ -317,6 +322,7 @@ public:
|
|||||||
void addRelocation(const MachineRelocation& relocation) {
|
void addRelocation(const MachineRelocation& relocation) {
|
||||||
Relocations.push_back(relocation);
|
Relocations.push_back(relocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -78,11 +78,32 @@ namespace llvm {
|
|||||||
|
|
||||||
/// Symbol Table Info
|
/// Symbol Table Info
|
||||||
unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; }
|
unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; }
|
||||||
unsigned getSymTabAlignment() const { return is64Bit ? 8 : 4; }
|
|
||||||
|
/// getPrefELFAlignment - Returns the preferred alignment for ELF. This
|
||||||
|
/// is used to align some sections.
|
||||||
|
unsigned getPrefELFAlignment() const { return is64Bit ? 8 : 4; }
|
||||||
|
|
||||||
|
/// getRelocationEntrySize - Entry size used in the relocation section
|
||||||
|
unsigned getRelocationEntrySize() const {
|
||||||
|
return is64Bit ? (hasRelocationAddend() ? 24 : 16)
|
||||||
|
: (hasRelocationAddend() ? 12 : 8);
|
||||||
|
}
|
||||||
|
|
||||||
/// getFunctionAlignment - Returns the alignment for function 'F', targets
|
/// getFunctionAlignment - Returns the alignment for function 'F', targets
|
||||||
/// with different alignment constraints should overload this method
|
/// with different alignment constraints should overload this method
|
||||||
virtual unsigned getFunctionAlignment(const Function *F) const;
|
virtual unsigned getFunctionAlignment(const Function *F) const;
|
||||||
|
|
||||||
|
/// getRelocationType - Returns the target specific ELF Relocation type.
|
||||||
|
/// 'MachineRelTy' contains the object code independent relocation type
|
||||||
|
virtual unsigned getRelocationType(unsigned MachineRelTy) const = 0;
|
||||||
|
|
||||||
|
/// hasRelocationAddend - True if the target uses an addend in the
|
||||||
|
/// 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.
|
||||||
|
virtual long int getAddendForRelTy(unsigned RelTy) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
@ -128,7 +128,13 @@ namespace llvm {
|
|||||||
/// added to logical symbol table for the module. This is eventually
|
/// added to logical symbol table for the module. This is eventually
|
||||||
/// turned into a real symbol table in the file.
|
/// turned into a real symbol table in the file.
|
||||||
struct ELFSym {
|
struct ELFSym {
|
||||||
const GlobalValue *GV; // The global value this corresponds to.
|
// The global value this corresponds to. Global symbols can be on of the
|
||||||
|
// 3 types : if this symbol has a zero initializer, it is common or should
|
||||||
|
// be placed in bss section otherwise it's a constant.
|
||||||
|
const GlobalValue *GV;
|
||||||
|
bool IsCommon;
|
||||||
|
bool IsBss;
|
||||||
|
bool IsConstant;
|
||||||
|
|
||||||
// ELF specific fields
|
// ELF specific fields
|
||||||
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
||||||
@ -159,8 +165,9 @@ namespace llvm {
|
|||||||
STV_PROTECTED = 3 // Visible in other components but not preemptable
|
STV_PROTECTED = 3 // Visible in other components but not preemptable
|
||||||
};
|
};
|
||||||
|
|
||||||
ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
|
ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false),
|
||||||
Size(0), Info(0), Other(0),
|
IsConstant(false), NameIdx(0), Value(0),
|
||||||
|
Size(0), Info(0), Other(STV_DEFAULT),
|
||||||
SectionIdx(ELFSection::SHN_UNDEF) {
|
SectionIdx(ELFSection::SHN_UNDEF) {
|
||||||
if (!GV)
|
if (!GV)
|
||||||
return;
|
return;
|
||||||
@ -180,16 +187,47 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBind(unsigned X) {
|
unsigned getBind() {
|
||||||
|
return (Info >> 4) & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBind(unsigned X) {
|
||||||
assert(X == (X & 0xF) && "Bind value out of range!");
|
assert(X == (X & 0xF) && "Bind value out of range!");
|
||||||
Info = (Info & 0x0F) | (X << 4);
|
Info = (Info & 0x0F) | (X << 4);
|
||||||
}
|
}
|
||||||
void SetType(unsigned X) {
|
void setType(unsigned X) {
|
||||||
assert(X == (X & 0xF) && "Type value out of range!");
|
assert(X == (X & 0xF) && "Type value out of range!");
|
||||||
Info = (Info & 0xF0) | X;
|
Info = (Info & 0xF0) | X;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// ELFRelocation - This class contains all the information necessary to
|
||||||
|
/// to generate any 32-bit or 64-bit ELF relocation entry.
|
||||||
|
class ELFRelocation {
|
||||||
|
uint64_t r_offset; // offset in the section of the object this applies to
|
||||||
|
uint32_t r_symidx; // symbol table index of the symbol to use
|
||||||
|
uint32_t r_type; // machine specific relocation type
|
||||||
|
int64_t r_add; // explicit relocation addend
|
||||||
|
bool r_rela; // if true then the addend is part of the entry
|
||||||
|
// otherwise the addend is at the location specified
|
||||||
|
// by r_offset
|
||||||
|
public:
|
||||||
|
uint64_t getInfo(bool is64Bit) const {
|
||||||
|
if (is64Bit)
|
||||||
|
return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL);
|
||||||
|
else
|
||||||
|
return (r_symidx << 8) + (r_type & 0xFFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getOffset() const { return r_offset; }
|
||||||
|
int64_t getAddend() const { return r_add; }
|
||||||
|
|
||||||
|
ELFRelocation(uint64_t off, uint32_t sym, uint32_t type,
|
||||||
|
bool rela = true, int64_t addend = 0) :
|
||||||
|
r_offset(off), r_symidx(sym), r_type(type),
|
||||||
|
r_add(addend), r_rela(rela) {}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,38 +71,37 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
|||||||
// Update Section Size
|
// Update Section Size
|
||||||
ES->Size = CurBufferPtr - BufferBegin;
|
ES->Size = CurBufferPtr - BufferBegin;
|
||||||
|
|
||||||
// Figure out the binding (linkage) of the symbol.
|
|
||||||
switch (MF.getFunction()->getLinkage()) {
|
|
||||||
default:
|
|
||||||
// appending linkage is illegal for functions.
|
|
||||||
assert(0 && "Unknown linkage type!");
|
|
||||||
case GlobalValue::ExternalLinkage:
|
|
||||||
FnSym.SetBind(ELFSym::STB_GLOBAL);
|
|
||||||
break;
|
|
||||||
case GlobalValue::LinkOnceAnyLinkage:
|
|
||||||
case GlobalValue::LinkOnceODRLinkage:
|
|
||||||
case GlobalValue::WeakAnyLinkage:
|
|
||||||
case GlobalValue::WeakODRLinkage:
|
|
||||||
FnSym.SetBind(ELFSym::STB_WEAK);
|
|
||||||
break;
|
|
||||||
case GlobalValue::PrivateLinkage:
|
|
||||||
assert (0 && "PrivateLinkage should not be in the symbol table.");
|
|
||||||
case GlobalValue::InternalLinkage:
|
|
||||||
FnSym.SetBind(ELFSym::STB_LOCAL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the symbol type as a function
|
// Set the symbol type as a function
|
||||||
FnSym.SetType(ELFSym::STT_FUNC);
|
FnSym.setType(ELFSym::STT_FUNC);
|
||||||
|
|
||||||
FnSym.SectionIdx = ES->SectionIdx;
|
FnSym.SectionIdx = ES->SectionIdx;
|
||||||
FnSym.Size = CurBufferPtr-FnStartPtr;
|
FnSym.Size = CurBufferPtr-FnStartPtr;
|
||||||
|
|
||||||
// Offset from start of Section
|
// Offset from start of Section
|
||||||
FnSym.Value = FnStartPtr-BufferBegin;
|
FnSym.Value = FnStartPtr-BufferBegin;
|
||||||
|
|
||||||
// Finally, add it to the symtab.
|
// Figure out the binding (linkage) of the symbol.
|
||||||
EW.SymbolList.push_back(FnSym);
|
switch (MF.getFunction()->getLinkage()) {
|
||||||
|
default:
|
||||||
|
// appending linkage is illegal for functions.
|
||||||
|
assert(0 && "Unknown linkage type!");
|
||||||
|
case GlobalValue::ExternalLinkage:
|
||||||
|
FnSym.setBind(ELFSym::STB_GLOBAL);
|
||||||
|
EW.SymbolList.push_back(FnSym);
|
||||||
|
break;
|
||||||
|
case GlobalValue::LinkOnceAnyLinkage:
|
||||||
|
case GlobalValue::LinkOnceODRLinkage:
|
||||||
|
case GlobalValue::WeakAnyLinkage:
|
||||||
|
case GlobalValue::WeakODRLinkage:
|
||||||
|
FnSym.setBind(ELFSym::STB_WEAK);
|
||||||
|
EW.SymbolList.push_back(FnSym);
|
||||||
|
break;
|
||||||
|
case GlobalValue::PrivateLinkage:
|
||||||
|
assert (0 && "PrivateLinkage should not be in the symbol table.");
|
||||||
|
case GlobalValue::InternalLinkage:
|
||||||
|
FnSym.setBind(ELFSym::STB_LOCAL);
|
||||||
|
EW.SymbolList.push_front(FnSym);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Relocations
|
// Relocations
|
||||||
// -----------
|
// -----------
|
||||||
@ -113,7 +112,6 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
|||||||
for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
|
||||||
MachineRelocation &MR = Relocations[i];
|
MachineRelocation &MR = Relocations[i];
|
||||||
intptr_t Addr;
|
intptr_t Addr;
|
||||||
|
|
||||||
if (MR.isBasicBlock()) {
|
if (MR.isBasicBlock()) {
|
||||||
Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
|
Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
|
||||||
MR.setConstantVal(ES->SectionIdx);
|
MR.setConstantVal(ES->SectionIdx);
|
||||||
|
@ -136,105 +136,41 @@ bool ELFWriter::doInitialization(Module &M) {
|
|||||||
ElfHdr.emitWord16(0); // Placeholder
|
ElfHdr.emitWord16(0); // Placeholder
|
||||||
|
|
||||||
// Add the null section, which is required to be first in the file.
|
// Add the null section, which is required to be first in the file.
|
||||||
getSection("", ELFSection::SHT_NULL, 0);
|
getNullSection();
|
||||||
|
|
||||||
// Start up the symbol table. The first entry in the symtab is the null
|
|
||||||
// entry.
|
|
||||||
SymbolList.push_back(ELFSym(0));
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFWriter::EmitGlobal(GlobalVariable *GV) {
|
unsigned ELFWriter::getGlobalELFLinkage(const GlobalVariable *GV) {
|
||||||
|
if (GV->hasInternalLinkage())
|
||||||
|
return ELFSym::STB_LOCAL;
|
||||||
|
|
||||||
// XXX: put local symbols *before* global ones!
|
if (GV->hasWeakLinkage())
|
||||||
|
return ELFSym::STB_WEAK;
|
||||||
|
|
||||||
|
return ELFSym::STB_GLOBAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For global symbols without a section, return the Null section as a
|
||||||
|
// placeholder
|
||||||
|
ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
|
||||||
|
ELFSym &Sym) {
|
||||||
const Section *S = TAI->SectionForGlobal(GV);
|
const Section *S = TAI->SectionForGlobal(GV);
|
||||||
DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
|
unsigned Flags = S->getFlags();
|
||||||
|
unsigned SectionType = ELFSection::SHT_PROGBITS;
|
||||||
// If this is an external global, emit it now. TODO: Note that it would be
|
unsigned SHdrFlags = ELFSection::SHF_ALLOC;
|
||||||
// better to ignore the symbol here and only add it to the symbol table if
|
|
||||||
// referenced.
|
|
||||||
if (!GV->hasInitializer()) {
|
|
||||||
ELFSym ExternalSym(GV);
|
|
||||||
ExternalSym.SetBind(ELFSym::STB_GLOBAL);
|
|
||||||
ExternalSym.SetType(ELFSym::STT_NOTYPE);
|
|
||||||
ExternalSym.SectionIdx = ELFSection::SHN_UNDEF;
|
|
||||||
SymbolList.push_back(ExternalSym);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TargetData *TD = TM.getTargetData();
|
const TargetData *TD = TM.getTargetData();
|
||||||
unsigned Align = TD->getPreferredAlignment(GV);
|
unsigned Align = TD->getPreferredAlignment(GV);
|
||||||
Constant *CV = GV->getInitializer();
|
Constant *CV = GV->getInitializer();
|
||||||
unsigned Size = TD->getTypeAllocSize(CV->getType());
|
|
||||||
|
|
||||||
// If this global has a zero initializer, go to .bss or common section.
|
DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
|
||||||
if (CV->isNullValue() || isa<UndefValue>(CV)) {
|
|
||||||
// If this global is part of the common block, add it now. Variables are
|
|
||||||
// part of the common block if they are zero initialized and allowed to be
|
|
||||||
// merged with other symbols.
|
|
||||||
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
|
||||||
GV->hasCommonLinkage()) {
|
|
||||||
ELFSym CommonSym(GV);
|
|
||||||
// Value for common symbols is the alignment required.
|
|
||||||
CommonSym.Value = Align;
|
|
||||||
CommonSym.Size = Size;
|
|
||||||
CommonSym.SetBind(ELFSym::STB_GLOBAL);
|
|
||||||
CommonSym.SetType(ELFSym::STT_OBJECT);
|
|
||||||
CommonSym.SectionIdx = ELFSection::SHN_COMMON;
|
|
||||||
SymbolList.push_back(CommonSym);
|
|
||||||
getSection(S->getName(), ELFSection::SHT_NOBITS,
|
|
||||||
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, this symbol is part of the .bss section. Emit it now.
|
// If this is an external global, the symbol does not have a section.
|
||||||
// Handle alignment. Ensure section is aligned at least as much as required
|
if (!GV->hasInitializer()) {
|
||||||
// by this symbol.
|
Sym.SectionIdx = ELFSection::SHN_UNDEF;
|
||||||
ELFSection &BSSSection = getBSSSection();
|
return getNullSection();
|
||||||
BSSSection.Align = std::max(BSSSection.Align, Align);
|
|
||||||
|
|
||||||
// Within the section, emit enough virtual padding to get us to an alignment
|
|
||||||
// boundary.
|
|
||||||
if (Align)
|
|
||||||
BSSSection.Size = (BSSSection.Size + Align - 1) & ~(Align-1);
|
|
||||||
|
|
||||||
ELFSym BSSSym(GV);
|
|
||||||
BSSSym.Value = BSSSection.Size;
|
|
||||||
BSSSym.Size = Size;
|
|
||||||
BSSSym.SetType(ELFSym::STT_OBJECT);
|
|
||||||
|
|
||||||
switch (GV->getLinkage()) {
|
|
||||||
default: // weak/linkonce/common handled above
|
|
||||||
assert(0 && "Unexpected linkage type!");
|
|
||||||
case GlobalValue::AppendingLinkage: // FIXME: This should be improved!
|
|
||||||
case GlobalValue::ExternalLinkage:
|
|
||||||
BSSSym.SetBind(ELFSym::STB_GLOBAL);
|
|
||||||
break;
|
|
||||||
case GlobalValue::InternalLinkage:
|
|
||||||
BSSSym.SetBind(ELFSym::STB_LOCAL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the idx of the .bss section
|
|
||||||
BSSSym.SectionIdx = BSSSection.SectionIdx;
|
|
||||||
if (!GV->hasPrivateLinkage())
|
|
||||||
SymbolList.push_back(BSSSym);
|
|
||||||
|
|
||||||
// Reserve space in the .bss section for this symbol.
|
|
||||||
BSSSection.Size += Size;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit the Global symbol to the right ELF section
|
|
||||||
ELFSym GblSym(GV);
|
|
||||||
GblSym.Size = Size;
|
|
||||||
GblSym.SetType(ELFSym::STT_OBJECT);
|
|
||||||
GblSym.SetBind(ELFSym::STB_GLOBAL);
|
|
||||||
unsigned Flags = S->getFlags();
|
|
||||||
unsigned SectType = ELFSection::SHT_PROGBITS;
|
|
||||||
unsigned SHdrFlags = ELFSection::SHF_ALLOC;
|
|
||||||
|
|
||||||
if (Flags & SectionFlags::Code)
|
if (Flags & SectionFlags::Code)
|
||||||
SHdrFlags |= ELFSection::SHF_EXECINSTR;
|
SHdrFlags |= ELFSection::SHF_EXECINSTR;
|
||||||
if (Flags & SectionFlags::Writeable)
|
if (Flags & SectionFlags::Writeable)
|
||||||
@ -246,29 +182,78 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
|
|||||||
if (Flags & SectionFlags::Strings)
|
if (Flags & SectionFlags::Strings)
|
||||||
SHdrFlags |= ELFSection::SHF_STRINGS;
|
SHdrFlags |= ELFSection::SHF_STRINGS;
|
||||||
|
|
||||||
// Remove tab from section name prefix
|
// If this global has a zero initializer, go to .bss or common section.
|
||||||
std::string SectionName(S->getName());
|
// Variables are part of the common block if they are zero initialized
|
||||||
size_t Pos = SectionName.find("\t");
|
// and allowed to be merged with other symbols.
|
||||||
if (Pos != std::string::npos)
|
if (CV->isNullValue() || isa<UndefValue>(CV)) {
|
||||||
SectionName.erase(Pos, 1);
|
SectionType = ELFSection::SHT_NOBITS;
|
||||||
|
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
||||||
|
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
||||||
|
GV->hasCommonLinkage()) {
|
||||||
|
Sym.SectionIdx = ELFSection::SHN_COMMON;
|
||||||
|
Sym.IsCommon = true;
|
||||||
|
return ElfS;
|
||||||
|
}
|
||||||
|
Sym.IsBss = true;
|
||||||
|
Sym.SectionIdx = ElfS.SectionIdx;
|
||||||
|
if (Align) ElfS.Size = (ElfS.Size + Align-1) & ~(Align-1);
|
||||||
|
ElfS.Align = std::max(ElfS.Align, Align);
|
||||||
|
return ElfS;
|
||||||
|
}
|
||||||
|
|
||||||
// The section alignment should be bound to the element with
|
Sym.IsConstant = true;
|
||||||
// the largest alignment
|
ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
|
||||||
ELFSection &ElfS = getSection(SectionName, SectType, SHdrFlags);
|
Sym.SectionIdx = ElfS.SectionIdx;
|
||||||
GblSym.SectionIdx = ElfS.SectionIdx;
|
ElfS.Align = std::max(ElfS.Align, Align);
|
||||||
if (Align > ElfS.Align)
|
return ElfS;
|
||||||
ElfS.Align = Align;
|
}
|
||||||
|
|
||||||
// S.Value should contain the symbol index inside the section,
|
void ELFWriter::EmitFunctionDeclaration(const Function *F) {
|
||||||
// and all symbols should start on their required alignment boundary
|
ELFSym GblSym(F);
|
||||||
GblSym.Value = (ElfS.size() + (Align-1)) & (-Align);
|
GblSym.setBind(ELFSym::STB_GLOBAL);
|
||||||
ElfS.emitAlignment(Align);
|
GblSym.setType(ELFSym::STT_NOTYPE);
|
||||||
|
GblSym.SectionIdx = ELFSection::SHN_UNDEF;
|
||||||
// Emit the constant symbol to its section
|
|
||||||
EmitGlobalConstant(CV, ElfS);
|
|
||||||
SymbolList.push_back(GblSym);
|
SymbolList.push_back(GblSym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) {
|
||||||
|
unsigned SymBind = getGlobalELFLinkage(GV);
|
||||||
|
ELFSym GblSym(GV);
|
||||||
|
GblSym.setBind(SymBind);
|
||||||
|
|
||||||
|
if (GV->hasInitializer())
|
||||||
|
GblSym.setType(ELFSym::STT_OBJECT);
|
||||||
|
else
|
||||||
|
GblSym.setType(ELFSym::STT_NOTYPE);
|
||||||
|
|
||||||
|
ELFSection &GblSection = getGlobalSymELFSection(GV, GblSym);
|
||||||
|
const TargetData *TD = TM.getTargetData();
|
||||||
|
unsigned Align = TD->getPreferredAlignment(GV);
|
||||||
|
unsigned Size = TD->getTypeAllocSize(GV->getInitializer()->getType());
|
||||||
|
GblSym.Size = Size;
|
||||||
|
|
||||||
|
if (GblSym.IsCommon) {
|
||||||
|
GblSym.Value = Align;
|
||||||
|
} else if (GblSym.IsBss) {
|
||||||
|
GblSym.Value = GblSection.Size;
|
||||||
|
GblSection.Size += Size;
|
||||||
|
} else if (GblSym.IsConstant){
|
||||||
|
// GblSym.Value should contain the symbol index inside the section,
|
||||||
|
// and all symbols should start on their required alignment boundary
|
||||||
|
GblSym.Value = (GblSection.size() + (Align-1)) & (-Align);
|
||||||
|
GblSection.emitAlignment(Align);
|
||||||
|
EmitGlobalConstant(GV->getInitializer(), GblSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local symbols should come first on the symbol table.
|
||||||
|
if (!GV->hasPrivateLinkage()) {
|
||||||
|
if (SymBind == ELFSym::STB_LOCAL)
|
||||||
|
SymbolList.push_front(GblSym);
|
||||||
|
else
|
||||||
|
SymbolList.push_back(GblSym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
||||||
ELFSection &GblS) {
|
ELFSection &GblS) {
|
||||||
|
|
||||||
@ -306,6 +291,7 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
|
|||||||
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
|
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
|
||||||
if (CVA->isString()) {
|
if (CVA->isString()) {
|
||||||
std::string GblStr = CVA->getAsString();
|
std::string GblStr = CVA->getAsString();
|
||||||
|
GblStr.resize(GblStr.size()-1);
|
||||||
GblS.emitString(GblStr);
|
GblS.emitString(GblStr);
|
||||||
} else { // Not a string. Print the values in successive locations
|
} else { // Not a string. Print the values in successive locations
|
||||||
for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
|
||||||
@ -370,8 +356,31 @@ bool ELFWriter::doFinalization(Module &M) {
|
|||||||
|
|
||||||
// Build and emit data, bss and "common" sections.
|
// Build and emit data, bss and "common" sections.
|
||||||
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; ++I)
|
I != E; ++I) {
|
||||||
EmitGlobal(I);
|
EmitGlobalVar(I);
|
||||||
|
GblSymLookup[I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit all pending globals
|
||||||
|
// TODO: this should be done only for referenced symbols
|
||||||
|
for (SetVector<GlobalValue*>::const_iterator I = PendingGlobals.begin(),
|
||||||
|
E = PendingGlobals.end(); I != E; ++I) {
|
||||||
|
|
||||||
|
// No need to emit the symbol again
|
||||||
|
if (GblSymLookup.find(*I) != GblSymLookup.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
|
||||||
|
EmitGlobalVar(GV);
|
||||||
|
} else if (Function *F = dyn_cast<Function>(*I)) {
|
||||||
|
// If function is not in GblSymLookup, it doesn't have a body,
|
||||||
|
// so emit the symbol as a function declaration (no section associated)
|
||||||
|
EmitFunctionDeclaration(F);
|
||||||
|
} else {
|
||||||
|
assert("unknown howto handle pending global");
|
||||||
|
}
|
||||||
|
GblSymLookup[*I] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Emit non-executable stack note
|
// Emit non-executable stack note
|
||||||
if (TAI->getNonexecutableStackDirective())
|
if (TAI->getNonexecutableStackDirective())
|
||||||
@ -400,6 +409,67 @@ bool ELFWriter::doFinalization(Module &M) {
|
|||||||
|
|
||||||
/// EmitRelocations - Emit relocations
|
/// EmitRelocations - Emit relocations
|
||||||
void ELFWriter::EmitRelocations() {
|
void ELFWriter::EmitRelocations() {
|
||||||
|
|
||||||
|
// Create Relocation sections for each section which needs it.
|
||||||
|
for (std::list<ELFSection>::iterator I = SectionList.begin(),
|
||||||
|
E = SectionList.end(); I != E; ++I) {
|
||||||
|
|
||||||
|
// This section does not have relocations
|
||||||
|
if (!I->hasRelocations()) continue;
|
||||||
|
|
||||||
|
// Get the relocation section for section 'I'
|
||||||
|
bool HasRelA = TEW->hasRelocationAddend();
|
||||||
|
ELFSection &RelSec = getRelocSection(I->getName(), HasRelA);
|
||||||
|
|
||||||
|
// 'Link' - Section hdr idx of the associated symbol table
|
||||||
|
// 'Info' - Section hdr idx of the section to which the relocation applies
|
||||||
|
ELFSection &SymTab = getSymbolTableSection();
|
||||||
|
RelSec.Link = SymTab.SectionIdx;
|
||||||
|
RelSec.Info = I->SectionIdx;
|
||||||
|
RelSec.EntSize = TEW->getRelocationEntrySize();
|
||||||
|
|
||||||
|
// Get the relocations from Section
|
||||||
|
std::vector<MachineRelocation> Relos = I->getRelocations();
|
||||||
|
for (std::vector<MachineRelocation>::iterator MRI = Relos.begin(),
|
||||||
|
MRE = Relos.end(); MRI != MRE; ++MRI) {
|
||||||
|
MachineRelocation &MR = *MRI;
|
||||||
|
|
||||||
|
// Offset from the start of the section containing the symbol
|
||||||
|
unsigned Offset = MR.getMachineCodeOffset();
|
||||||
|
|
||||||
|
// Symbol index in the symbol table
|
||||||
|
unsigned SymIdx = 0;
|
||||||
|
|
||||||
|
// Target specific ELF relocation type
|
||||||
|
unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
|
||||||
|
|
||||||
|
// Constant addend used to compute the value to be stored
|
||||||
|
// into the relocatable field
|
||||||
|
int64_t Addend = TEW->getAddendForRelTy(RelType);
|
||||||
|
|
||||||
|
// There are several machine relocations types, and each one of
|
||||||
|
// them needs a different approach to retrieve the symbol table index.
|
||||||
|
if (MR.isGlobalValue()) {
|
||||||
|
const GlobalValue *G = MR.getGlobalValue();
|
||||||
|
SymIdx = GblSymLookup[G];
|
||||||
|
} else {
|
||||||
|
assert(0 && "dunno how to handle other relocation types");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the relocation entry and emit to the relocation section
|
||||||
|
ELFRelocation Rel(Offset, SymIdx, RelType, HasRelA, Addend);
|
||||||
|
EmitRelocation(RelSec, Rel, HasRelA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel'
|
||||||
|
void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel,
|
||||||
|
bool HasRelA) {
|
||||||
|
RelSec.emitWord(Rel.getOffset());
|
||||||
|
RelSec.emitWord(Rel.getInfo(is64Bit));
|
||||||
|
if (HasRelA)
|
||||||
|
RelSec.emitWord(Rel.getAddend());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
|
/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
|
||||||
@ -451,25 +521,27 @@ void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
|
|||||||
/// EmitSymbolTable - If the current symbol table is non-empty, emit the string
|
/// EmitSymbolTable - If the current symbol table is non-empty, emit the string
|
||||||
/// table for it and then the symbol table itself.
|
/// table for it and then the symbol table itself.
|
||||||
void ELFWriter::EmitSymbolTable() {
|
void ELFWriter::EmitSymbolTable() {
|
||||||
if (SymbolList.size() == 1) return; // Only the null entry.
|
if (!SymbolList.size()) return; // Empty symbol table.
|
||||||
|
|
||||||
// FIXME: compact all local symbols to the start of the symtab.
|
|
||||||
unsigned FirstNonLocalSymbol = 1;
|
unsigned FirstNonLocalSymbol = 1;
|
||||||
|
|
||||||
ELFSection &StrTab = getStringTableSection();
|
ELFSection &StrTab = getStringTableSection();
|
||||||
|
|
||||||
// Set the zero'th symbol to a null byte, as required.
|
// Set the zero'th symbol to a null byte, as required.
|
||||||
StrTab.emitByte(0);
|
StrTab.emitByte(0);
|
||||||
|
|
||||||
|
// Walk on the symbol list and write symbol names into the
|
||||||
|
// string table.
|
||||||
unsigned Index = 1;
|
unsigned Index = 1;
|
||||||
for (unsigned i = 1, e = SymbolList.size(); i != e; ++i) {
|
for (std::list<ELFSym>::iterator I = SymbolList.begin(),
|
||||||
|
E = SymbolList.end(); I != E; ++I) {
|
||||||
|
|
||||||
// Use the name mangler to uniquify the LLVM symbol.
|
// Use the name mangler to uniquify the LLVM symbol.
|
||||||
std::string Name = Mang->getValueName(SymbolList[i].GV);
|
std::string Name = Mang->getValueName(I->GV);
|
||||||
|
|
||||||
if (Name.empty()) {
|
if (Name.empty()) {
|
||||||
SymbolList[i].NameIdx = 0;
|
I->NameIdx = 0;
|
||||||
} else {
|
} else {
|
||||||
SymbolList[i].NameIdx = Index;
|
I->NameIdx = Index;
|
||||||
StrTab.emitString(Name);
|
StrTab.emitString(Name);
|
||||||
|
|
||||||
// Keep track of the number of bytes emitted to this section.
|
// Keep track of the number of bytes emitted to this section.
|
||||||
@ -482,16 +554,33 @@ void ELFWriter::EmitSymbolTable() {
|
|||||||
// Now that we have emitted the string table and know the offset into the
|
// Now that we have emitted the string table and know the offset into the
|
||||||
// string table of each symbol, emit the symbol table itself.
|
// string table of each symbol, emit the symbol table itself.
|
||||||
ELFSection &SymTab = getSymbolTableSection();
|
ELFSection &SymTab = getSymbolTableSection();
|
||||||
SymTab.Align = TEW->getSymTabAlignment();
|
SymTab.Align = TEW->getPrefELFAlignment();
|
||||||
SymTab.Link = StrTab.SectionIdx; // Section Index of .strtab.
|
SymTab.Link = StrTab.SectionIdx; // Section Index of .strtab.
|
||||||
SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol.
|
|
||||||
|
|
||||||
// Size of each symtab entry.
|
// Size of each symtab entry.
|
||||||
SymTab.EntSize = TEW->getSymTabEntrySize();
|
SymTab.EntSize = TEW->getSymTabEntrySize();
|
||||||
|
|
||||||
for (unsigned i = 0, e = SymbolList.size(); i != e; ++i)
|
// The first entry in the symtab is the null symbol
|
||||||
EmitSymbol(SymTab, SymbolList[i]);
|
ELFSym NullSym = ELFSym(0);
|
||||||
|
EmitSymbol(SymTab, NullSym);
|
||||||
|
|
||||||
|
// Emit all the symbols to the symbol table. Skip the null
|
||||||
|
// symbol, cause it's emitted already
|
||||||
|
Index = 1;
|
||||||
|
for (std::list<ELFSym>::iterator I = SymbolList.begin(),
|
||||||
|
E = SymbolList.end(); I != E; ++I, ++Index) {
|
||||||
|
// Keep track of the first non-local symbol
|
||||||
|
if (I->getBind() == ELFSym::STB_LOCAL)
|
||||||
|
FirstNonLocalSymbol++;
|
||||||
|
|
||||||
|
// Emit symbol to the symbol table
|
||||||
|
EmitSymbol(SymTab, *I);
|
||||||
|
|
||||||
|
// Record the symbol table index for each global value
|
||||||
|
GblSymLookup[I->GV] = Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymTab.Info = FirstNonLocalSymbol;
|
||||||
SymTab.Size = SymTab.size();
|
SymTab.Size = SymTab.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +648,7 @@ void ELFWriter::OutputSectionsAndSectionTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Align Section Header.
|
// Align Section Header.
|
||||||
unsigned TableAlign = is64Bit ? 8 : 4;
|
unsigned TableAlign = TEW->getPrefELFAlignment();
|
||||||
FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);
|
FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);
|
||||||
|
|
||||||
// Now that we know where all of the sections will be emitted, set the e_shnum
|
// Now that we know where all of the sections will be emitted, set the e_shnum
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
#include "llvm/Support/OutputBuffer.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Target/TargetAsmInfo.h"
|
#include "llvm/Target/TargetAsmInfo.h"
|
||||||
#include "llvm/Target/TargetELFWriterInfo.h"
|
#include "llvm/Target/TargetELFWriterInfo.h"
|
||||||
#include "ELF.h"
|
#include "ELF.h"
|
||||||
@ -89,7 +89,7 @@ namespace llvm {
|
|||||||
bool doFinalization(Module &M);
|
bool doFinalization(Module &M);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Blob containing the Elf header
|
/// Blob containing the Elf header
|
||||||
BinaryObject ElfHdr;
|
BinaryObject ElfHdr;
|
||||||
|
|
||||||
/// SectionList - This is the list of sections that we have emitted to the
|
/// SectionList - This is the list of sections that we have emitted to the
|
||||||
@ -102,14 +102,35 @@ namespace llvm {
|
|||||||
/// the SectionList.
|
/// the SectionList.
|
||||||
std::map<std::string, ELFSection*> SectionLookup;
|
std::map<std::string, ELFSection*> SectionLookup;
|
||||||
|
|
||||||
|
/// GblSymLookup - This is a mapping from global value to a symbol index
|
||||||
|
/// in the symbol table. This is useful since relocations symbol references
|
||||||
|
/// must be quickly mapped to a symbol table index
|
||||||
|
std::map<const GlobalValue*, uint32_t> GblSymLookup;
|
||||||
|
|
||||||
|
/// SymbolList - This is the list of symbols emitted to the symbol table
|
||||||
|
/// Local symbols go to the front and Globals to the back.
|
||||||
|
std::list<ELFSym> SymbolList;
|
||||||
|
|
||||||
|
/// PendingGlobals - List of externally defined symbols that we have been
|
||||||
|
/// asked to emit, but have not seen a reference to. When a reference
|
||||||
|
/// is seen, the symbol will move from this list to the SymbolList.
|
||||||
|
SetVector<GlobalValue*> PendingGlobals;
|
||||||
|
|
||||||
/// getSection - Return the section with the specified name, creating a new
|
/// getSection - Return the section with the specified name, creating a new
|
||||||
/// section if one does not already exist.
|
/// section if one does not already exist.
|
||||||
ELFSection &getSection(const std::string &Name, unsigned Type,
|
ELFSection &getSection(const std::string &Name, unsigned Type,
|
||||||
unsigned Flags = 0, unsigned Align = 0) {
|
unsigned Flags = 0, unsigned Align = 0) {
|
||||||
ELFSection *&SN = SectionLookup[Name];
|
ELFSection *&SN = SectionLookup[Name];
|
||||||
if (SN) return *SN;
|
if (SN) return *SN;
|
||||||
|
|
||||||
SectionList.push_back(ELFSection(Name, isLittleEndian, is64Bit));
|
// Remove tab from section name prefix. This is necessary becase TAI
|
||||||
|
// sometimes return a section name prefixed with a "\t" char.
|
||||||
|
std::string SectionName(Name);
|
||||||
|
size_t Pos = SectionName.find("\t");
|
||||||
|
if (Pos != std::string::npos)
|
||||||
|
SectionName.erase(Pos, 1);
|
||||||
|
|
||||||
|
SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
|
||||||
SN = &SectionList.back();
|
SN = &SectionList.back();
|
||||||
SN->SectionIdx = NumSections++;
|
SN->SectionIdx = NumSections++;
|
||||||
SN->Type = Type;
|
SN->Type = Type;
|
||||||
@ -119,11 +140,25 @@ namespace llvm {
|
|||||||
return *SN;
|
return *SN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: support mangled names here to emit the right .text section
|
||||||
|
/// for c++ object files.
|
||||||
ELFSection &getTextSection() {
|
ELFSection &getTextSection() {
|
||||||
return getSection(".text", ELFSection::SHT_PROGBITS,
|
return getSection(".text", ELFSection::SHT_PROGBITS,
|
||||||
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
|
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) {
|
||||||
|
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, TEW->getPrefELFAlignment());
|
||||||
|
}
|
||||||
|
|
||||||
ELFSection &getNonExecStackSection() {
|
ELFSection &getNonExecStackSection() {
|
||||||
return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
|
return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
|
||||||
}
|
}
|
||||||
@ -146,15 +181,9 @@ namespace llvm {
|
|||||||
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
|
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SymbolList - This is the list of symbols we have emitted to the file.
|
ELFSection &getNullSection() {
|
||||||
/// This actually gets rearranged before emission to the file (to put the
|
return getSection("", ELFSection::SHT_NULL, 0);
|
||||||
/// local symbols first in the list).
|
}
|
||||||
std::vector<ELFSym> SymbolList;
|
|
||||||
|
|
||||||
/// PendingGlobals - List of externally defined symbols that we have been
|
|
||||||
/// asked to emit, but have not seen a reference to. When a reference
|
|
||||||
/// is seen, the symbol will move from this list to the SymbolList.
|
|
||||||
SetVector<GlobalValue*> PendingGlobals;
|
|
||||||
|
|
||||||
// As we complete the ELF file, we need to update fields in the ELF header
|
// As we complete the ELF file, we need to update fields in the ELF header
|
||||||
// (e.g. the location of the section table). These members keep track of
|
// (e.g. the location of the section table). These members keep track of
|
||||||
@ -165,11 +194,15 @@ namespace llvm {
|
|||||||
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EmitGlobal(GlobalVariable *GV);
|
void EmitFunctionDeclaration(const Function *F);
|
||||||
|
void EmitGlobalVar(const GlobalVariable *GV);
|
||||||
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
|
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
|
||||||
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
|
||||||
ELFSection &GblS);
|
ELFSection &GblS);
|
||||||
|
unsigned getGlobalELFLinkage(const GlobalVariable *GV);
|
||||||
|
ELFSection &getGlobalSymELFSection(const GlobalVariable *GV, ELFSym &Sym);
|
||||||
void EmitRelocations();
|
void EmitRelocations();
|
||||||
|
void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA);
|
||||||
void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
|
void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
|
||||||
void EmitSectionTableStringTable();
|
void EmitSectionTableStringTable();
|
||||||
void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
|
void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
|
||||||
|
@ -12,11 +12,17 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "X86ELFWriterInfo.h"
|
#include "X86ELFWriterInfo.h"
|
||||||
|
#include "X86Relocations.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Implementation of the X86ELFWriterInfo class
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM)
|
X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM)
|
||||||
: TargetELFWriterInfo(TM) {
|
: TargetELFWriterInfo(TM) {
|
||||||
bool is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
|
bool is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
|
||||||
@ -25,6 +31,34 @@ X86ELFWriterInfo::X86ELFWriterInfo(TargetMachine &TM)
|
|||||||
|
|
||||||
X86ELFWriterInfo::~X86ELFWriterInfo() {}
|
X86ELFWriterInfo::~X86ELFWriterInfo() {}
|
||||||
|
|
||||||
|
unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const {
|
||||||
|
if (is64Bit) {
|
||||||
|
switch(MachineRelTy) {
|
||||||
|
case X86::reloc_pcrel_word:
|
||||||
|
return R_X86_64_PC32;
|
||||||
|
case X86::reloc_absolute_word:
|
||||||
|
return R_X86_64_32;
|
||||||
|
case X86::reloc_absolute_dword:
|
||||||
|
return R_X86_64_64;
|
||||||
|
case X86::reloc_picrel_word:
|
||||||
|
default:
|
||||||
|
assert(0 && "unknown relocation type");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(MachineRelTy) {
|
||||||
|
case X86::reloc_pcrel_word:
|
||||||
|
return R_386_PC32;
|
||||||
|
case X86::reloc_absolute_word:
|
||||||
|
return R_386_32;
|
||||||
|
case X86::reloc_absolute_dword:
|
||||||
|
case X86::reloc_picrel_word:
|
||||||
|
default:
|
||||||
|
assert(0 && "unknown relocation type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned X86ELFWriterInfo::getFunctionAlignment(const Function *F) const {
|
unsigned X86ELFWriterInfo::getFunctionAlignment(const Function *F) const {
|
||||||
unsigned FnAlign = 4;
|
unsigned FnAlign = 4;
|
||||||
|
|
||||||
@ -36,3 +70,15 @@ unsigned X86ELFWriterInfo::getFunctionAlignment(const Function *F) const {
|
|||||||
|
|
||||||
return (1 << FnAlign);
|
return (1 << FnAlign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long int X86ELFWriterInfo::getAddendForRelTy(unsigned RelTy) const {
|
||||||
|
if (is64Bit) {
|
||||||
|
switch(RelTy) {
|
||||||
|
case R_X86_64_PC32: return -4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0 && "unknown x86 relocation type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -19,11 +19,43 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class X86ELFWriterInfo : public TargetELFWriterInfo {
|
class X86ELFWriterInfo : public TargetELFWriterInfo {
|
||||||
|
|
||||||
|
// ELF Relocation types for X86
|
||||||
|
enum X86RelocationType {
|
||||||
|
R_386_NONE = 0,
|
||||||
|
R_386_32 = 1,
|
||||||
|
R_386_PC32 = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// ELF Relocation types for X86_64
|
||||||
|
enum X86_64RelocationType {
|
||||||
|
R_X86_64_NONE = 0,
|
||||||
|
R_X86_64_64 = 1,
|
||||||
|
R_X86_64_PC32 = 2,
|
||||||
|
R_X86_64_32 = 10,
|
||||||
|
R_X86_64_32S = 11,
|
||||||
|
R_X86_64_PC64 = 24
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
X86ELFWriterInfo(TargetMachine &TM);
|
X86ELFWriterInfo(TargetMachine &TM);
|
||||||
virtual ~X86ELFWriterInfo();
|
virtual ~X86ELFWriterInfo();
|
||||||
|
|
||||||
|
/// getFunctionAlignment - Returns the alignment for function 'F', targets
|
||||||
|
/// with different alignment constraints should overload this method
|
||||||
virtual unsigned getFunctionAlignment(const Function *F) const;
|
virtual unsigned getFunctionAlignment(const Function *F) const;
|
||||||
|
|
||||||
|
/// getRelocationType - Returns the target specific ELF Relocation type.
|
||||||
|
/// 'MachineRelTy' contains the object code independent relocation type
|
||||||
|
virtual unsigned getRelocationType(unsigned MachineRelTy) const;
|
||||||
|
|
||||||
|
/// hasRelocationAddend - True if the target uses an addend in the
|
||||||
|
/// ELF relocation entry.
|
||||||
|
virtual bool hasRelocationAddend() const { return is64Bit ? true : false; }
|
||||||
|
|
||||||
|
/// getAddendForRelTy - Gets the addend value for an ELF relocation entry
|
||||||
|
/// based on the target relocation type
|
||||||
|
virtual long int getAddendForRelTy(unsigned RelTy) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
Reference in New Issue
Block a user