Commit 261cae38 by Jan Voung

Track undefined sym in the symtab. Remove hack for missing relocs against undef.

Preliminary linking tests, seems to show that the linker and objcopy are happy to use 'em on spec2k, and the result runs! (Had to be careful to clobber the old .s and .o files to make it's testing the right copy). Haven't tried crosstests yet. BUG=none R=stichnot@chromium.org Review URL: https://codereview.chromium.org/889613004
parent 046ec2e0
...@@ -532,12 +532,23 @@ void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) { ...@@ -532,12 +532,23 @@ void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) {
writeRelocationSections(IsELF64, RelRODataSections); writeRelocationSections(IsELF64, RelRODataSections);
} }
void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
for (const Constant *S : UndefSyms) {
const auto Sym = llvm::cast<ConstantRelocatable>(S);
IceString Name = Sym->getName();
assert(Sym->getOffset() == 0);
assert(Sym->getSuppressMangling());
SymTab->noteUndefinedSym(Name, NullSection);
StrTab->add(Name);
}
}
void ELFObjectWriter::writeRelocationSections(bool IsELF64, void ELFObjectWriter::writeRelocationSections(bool IsELF64,
RelSectionList &RelSections) { RelSectionList &RelSections) {
for (ELFRelocationSection *RelSec : RelSections) { for (ELFRelocationSection *RelSec : RelSections) {
Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
RelSec->setFileOffset(Offset); RelSec->setFileOffset(Offset);
RelSec->setSize(RelSec->getSectionDataSize(Ctx, SymTab)); RelSec->setSize(RelSec->getSectionDataSize());
if (IsELF64) { if (IsELF64) {
RelSec->writeData<true>(Ctx, Str, SymTab); RelSec->writeData<true>(Ctx, Str, SymTab);
} else { } else {
......
...@@ -33,7 +33,8 @@ namespace Ice { ...@@ -33,7 +33,8 @@ namespace Ice {
// (2) writeDataSection (invoke once) // (2) writeDataSection (invoke once)
// (3) writeFunctionCode (must invoke once per function) // (3) writeFunctionCode (must invoke once per function)
// (4) writeConstantPool (must invoke once per pooled primitive type) // (4) writeConstantPool (must invoke once per pooled primitive type)
// (5) writeNonUserSections (invoke once) // (5) setUndefinedSyms (invoke once)
// (6) writeNonUserSections (invoke once)
// //
// The requirement for writeDataSection to be invoked only once can // The requirement for writeDataSection to be invoked only once can
// be relaxed if using -fdata-sections. The requirement to invoke only once // be relaxed if using -fdata-sections. The requirement to invoke only once
...@@ -76,6 +77,9 @@ public: ...@@ -76,6 +77,9 @@ public:
// fills the symbol table with labels for each constant pool entry. // fills the symbol table with labels for each constant pool entry.
template <typename ConstType> void writeConstantPool(Type Ty); template <typename ConstType> void writeConstantPool(Type Ty);
// Populate the symbol table with a list of external/undefined symbols.
void setUndefinedSyms(const ConstantList &UndefSyms);
// Do final layout and write out the rest of the object file. // Do final layout and write out the rest of the object file.
// Finally, patch up the initial ELF header with the final info. // Finally, patch up the initial ELF header with the final info.
void writeNonUserSections(); void writeNonUserSections();
......
...@@ -74,18 +74,8 @@ void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, ...@@ -74,18 +74,8 @@ void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
} }
} }
size_t ELFRelocationSection::getSectionDataSize( size_t ELFRelocationSection::getSectionDataSize() const {
const GlobalContext &Ctx, const ELFSymbolTableSection *SymTab) const { return Fixups.size() * Header.sh_entsize;
size_t NumWriteableRelocs = 0;
for (const AssemblerFixup &Fixup : Fixups) {
const ELFSym *Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx));
// TODO(jvoung): When the symbol table finally tracks everything,
// just use the Fixups.size() as the count, and remove the
// SymTab and Ctx params.
if (Symbol)
++NumWriteableRelocs;
}
return NumWriteableRelocs * Header.sh_entsize;
} }
// Symbol tables. // Symbol tables.
......
...@@ -217,8 +217,7 @@ public: ...@@ -217,8 +217,7 @@ public:
// Track a single additional relocation. // Track a single additional relocation.
void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); } void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
size_t getSectionDataSize(const GlobalContext &Ctx, size_t getSectionDataSize() const;
const ELFSymbolTableSection *SymTab) const;
template <bool IsELF64> template <bool IsELF64>
void writeData(const GlobalContext &Ctx, ELFStreamer &Str, void writeData(const GlobalContext &Ctx, ELFStreamer &Str,
...@@ -333,25 +332,23 @@ void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str, ...@@ -333,25 +332,23 @@ void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str,
const ELFSymbolTableSection *SymTab) { const ELFSymbolTableSection *SymTab) {
for (const AssemblerFixup &Fixup : Fixups) { for (const AssemblerFixup &Fixup : Fixups) {
const ELFSym *Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx)); const ELFSym *Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx));
// TODO(jvoung): Make sure this always succeeds. if (!Symbol)
// We currently don't track data symbols, so they aren't even marked llvm::report_fatal_error("Missing symbol mentioned in reloc");
// as undefined symbols.
if (Symbol) { if (IsELF64) {
if (IsELF64) { Elf64_Rela Rela;
Elf64_Rela Rela; Rela.r_offset = Fixup.position();
Rela.r_offset = Fixup.position(); Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind());
Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); Rela.r_addend = Fixup.offset();
Rela.r_addend = Fixup.offset(); Str.writeAddrOrOffset<IsELF64>(Rela.r_offset);
Str.writeAddrOrOffset<IsELF64>(Rela.r_offset); Str.writeELFXword<IsELF64>(Rela.r_info);
Str.writeELFXword<IsELF64>(Rela.r_info); Str.writeELFXword<IsELF64>(Rela.r_addend);
Str.writeELFXword<IsELF64>(Rela.r_addend); } else {
} else { Elf32_Rel Rel;
Elf32_Rel Rel; Rel.r_offset = Fixup.position();
Rel.r_offset = Fixup.position(); Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind());
Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); Str.writeAddrOrOffset<IsELF64>(Rel.r_offset);
Str.writeAddrOrOffset<IsELF64>(Rel.r_offset); Str.writeELFWord<IsELF64>(Rel.r_info);
Str.writeELFWord<IsELF64>(Rel.r_info);
}
} }
} }
} }
......
...@@ -105,6 +105,8 @@ public: ...@@ -105,6 +105,8 @@ public:
TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32; TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64; TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables; TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable>
ExternRelocatables;
UndefPool Undefs; UndefPool Undefs;
}; };
...@@ -422,6 +424,13 @@ Constant *GlobalContext::getConstantSym(RelocOffsetT Offset, ...@@ -422,6 +424,13 @@ Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
this, RelocatableTuple(Offset, Name, SuppressMangling)); this, RelocatableTuple(Offset, Name, SuppressMangling));
} }
Constant *GlobalContext::getConstantExternSym(const IceString &Name) {
const RelocOffsetT Offset = 0;
const bool SuppressMangling = true;
return getConstPool()->ExternRelocatables.getOrAdd(
this, RelocatableTuple(Offset, Name, SuppressMangling));
}
Constant *GlobalContext::getConstantUndef(Type Ty) { Constant *GlobalContext::getConstantUndef(Type Ty) {
return getConstPool()->Undefs.getOrAdd(this, Ty); return getConstPool()->Undefs.getOrAdd(this, Ty);
} }
...@@ -494,6 +503,10 @@ ConstantList GlobalContext::getConstantPool(Type Ty) { ...@@ -494,6 +503,10 @@ ConstantList GlobalContext::getConstantPool(Type Ty) {
llvm_unreachable("Unknown type"); llvm_unreachable("Unknown type");
} }
ConstantList GlobalContext::getConstantExternSyms() {
return getConstPool()->ExternRelocatables.getConstantPool();
}
TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) { TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
if (!ALLOW_DUMP) if (!ALLOW_DUMP)
return 0; return 0;
......
...@@ -188,6 +188,7 @@ public: ...@@ -188,6 +188,7 @@ public:
// Returns a symbolic constant. // Returns a symbolic constant.
Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name, Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name,
bool SuppressMangling); bool SuppressMangling);
Constant *getConstantExternSym(const IceString &Name);
// Returns an undef. // Returns an undef.
Constant *getConstantUndef(Type Ty); Constant *getConstantUndef(Type Ty);
// Returns a zero value. // Returns a zero value.
...@@ -195,6 +196,8 @@ public: ...@@ -195,6 +196,8 @@ public:
// getConstantPool() returns a copy of the constant pool for // getConstantPool() returns a copy of the constant pool for
// constants of a given type. // constants of a given type.
ConstantList getConstantPool(Type Ty); ConstantList getConstantPool(Type Ty);
// Returns a copy of the list of external symbols.
ConstantList getConstantExternSyms();
const ClFlags &getFlags() const { return Flags; } const ClFlags &getFlags() const { return Flags; }
......
...@@ -153,12 +153,11 @@ protected: ...@@ -153,12 +153,11 @@ protected:
OperandX8632Mem *FormMemoryOperand(Operand *Ptr, Type Ty); OperandX8632Mem *FormMemoryOperand(Operand *Ptr, Type Ty);
Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
// Make a call to an external helper function.
InstCall *makeHelperCall(const IceString &Name, Variable *Dest, InstCall *makeHelperCall(const IceString &Name, Variable *Dest,
SizeT MaxSrcs) { SizeT MaxSrcs) {
const bool SuppressMangling = true;
const bool HasTailCall = false; const bool HasTailCall = false;
const RelocOffsetT Offset = 0; Constant *CallTarget = Ctx->getConstantExternSym(Name);
Constant *CallTarget = Ctx->getConstantSym(Offset, Name, SuppressMangling);
InstCall *Call = InstCall *Call =
InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall); InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
return Call; return Call;
......
...@@ -398,6 +398,7 @@ int main(int argc, char **argv) { ...@@ -398,6 +398,7 @@ int main(int argc, char **argv) {
if (UseELFWriter) { if (UseELFWriter) {
Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
Ctx.getObjectWriter()->writeNonUserSections(); Ctx.getObjectWriter()->writeNonUserSections();
} }
if (SubzeroTimingEnabled) if (SubzeroTimingEnabled)
......
...@@ -385,12 +385,8 @@ define void @_start(i32) { ...@@ -385,12 +385,8 @@ define void @_start(i32) {
; CHECK: 0x24 R_386_32 .L$double$0 0x0 ; CHECK: 0x24 R_386_32 .L$double$0 0x0
; CHECK: 0x2C R_386_32 .L$double$1 0x0 ; CHECK: 0x2C R_386_32 .L$double$1 0x0
; CHECK: 0x34 R_386_32 .L$double$2 0x0 ; CHECK: 0x34 R_386_32 .L$double$2 0x0
; The set of relocations between llvm-mc and integrated elf-writer ; CHECK: 0x{{.*}} R_386_PC32 memcpy
; are different. The integrated elf-writer does not yet handle ; CHECK: 0x{{.*}} R_386_PC32 memset
; external/undef functions like memcpy. Also, it does not resolve internal
; function calls and instead writes out the relocation. However, there's
; probably some function call so check for a PC32 relocation at least.
; CHECK: 0x{{.*}} R_386_PC32
; CHECK: } ; CHECK: }
; CHECK: Section ({{[0-9]+}}) .rel.data { ; CHECK: Section ({{[0-9]+}}) .rel.data {
; The set of relocations between llvm-mc and the integrated elf-writer ; The set of relocations between llvm-mc and the integrated elf-writer
...@@ -617,4 +613,22 @@ define void @_start(i32) { ...@@ -617,4 +613,22 @@ define void @_start(i32) {
; CHECK-NEXT: Other: 0 ; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: .text ; CHECK-NEXT: Section: .text
; CHECK-NEXT: } ; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: memcpy
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Global
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: Undefined
; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: memset
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Global
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: Undefined
; CHECK-NEXT: }
; CHECK: ] ; CHECK: ]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment