//===- ObjectLinker.cpp ---------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/Object/ObjectLinker.h>
#include <mcld/LinkerConfig.h>
#include <mcld/LinkerScript.h>
#include <mcld/Module.h>
#include <mcld/InputTree.h>
#include <mcld/IRBuilder.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/Archive.h>
#include <mcld/LD/ArchiveReader.h>
#include <mcld/LD/ObjectReader.h>
#include <mcld/LD/DynObjReader.h>
#include <mcld/LD/GroupReader.h>
#include <mcld/LD/BinaryReader.h>
#include <mcld/LD/GarbageCollection.h>
#include <mcld/LD/IdenticalCodeFolding.h>
#include <mcld/LD/ObjectWriter.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/RelocData.h>
#include <mcld/LD/Relocator.h>
#include <mcld/LD/SectionData.h>
#include <mcld/LD/BranchIslandFactory.h>
#include <mcld/Script/ScriptFile.h>
#include <mcld/Script/ScriptReader.h>
#include <mcld/Script/Assignment.h>
#include <mcld/Script/Operand.h>
#include <mcld/Script/RpnEvaluator.h>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/FileOutputBuffer.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/Fragment/Relocation.h>
#include <mcld/Object/ObjectBuilder.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/Host.h>
#include <system_error>
using namespace llvm;
using namespace mcld;
//===----------------------------------------------------------------------===//
// ObjectLinker
//===----------------------------------------------------------------------===//
ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
TargetLDBackend& pLDBackend)
: m_Config(pConfig),
m_pModule(NULL),
m_pBuilder(NULL),
m_LDBackend(pLDBackend),
m_pObjectReader(NULL),
m_pDynObjReader(NULL),
m_pArchiveReader(NULL),
m_pGroupReader(NULL),
m_pBinaryReader(NULL),
m_pScriptReader(NULL),
m_pWriter(NULL) {
}
ObjectLinker::~ObjectLinker()
{
delete m_pObjectReader;
delete m_pDynObjReader;
delete m_pArchiveReader;
delete m_pGroupReader;
delete m_pBinaryReader;
delete m_pScriptReader;
delete m_pWriter;
}
bool ObjectLinker::initialize(Module& pModule, IRBuilder& pBuilder)
{
m_pModule = &pModule;
m_pBuilder = &pBuilder;
// initialize the readers and writers
m_pObjectReader = m_LDBackend.createObjectReader(*m_pBuilder);
m_pArchiveReader = m_LDBackend.createArchiveReader(*m_pModule);
m_pDynObjReader = m_LDBackend.createDynObjReader(*m_pBuilder);
m_pBinaryReader = m_LDBackend.createBinaryReader(*m_pBuilder);
m_pGroupReader = new GroupReader(*m_pModule, *m_pObjectReader,
*m_pDynObjReader, *m_pArchiveReader, *m_pBinaryReader);
m_pScriptReader = new ScriptReader(*m_pGroupReader);
m_pWriter = m_LDBackend.createWriter();
// initialize Relocator
m_LDBackend.initRelocator();
return true;
}
/// initStdSections - initialize standard sections
bool ObjectLinker::initStdSections()
{
ObjectBuilder builder(*m_pModule);
// initialize standard sections
if (!m_LDBackend.initStdSections(builder))
return false;
// initialize target-dependent sections
m_LDBackend.initTargetSections(*m_pModule, builder);
return true;
}
void ObjectLinker::addUndefinedSymbols()
{
// Add the symbol set by -u as an undefind global symbol into symbol pool
GeneralOptions::const_undef_sym_iterator usym;
GeneralOptions::const_undef_sym_iterator usymEnd =
m_Config.options().undef_sym_end();
for (usym = m_Config.options().undef_sym_begin(); usym != usymEnd; ++usym) {
Resolver::Result result;
m_pModule->getNamePool().insertSymbol(*usym, // name
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Undefined,
ResolveInfo::Global,
0x0, // size
0x0, // value
ResolveInfo::Default,
NULL,
result);
LDSymbol* output_sym = result.info->outSymbol();
bool has_output_sym = (NULL != output_sym);
// create the output symbol if it dose not have one
if (!result.existent || !has_output_sym) {
output_sym = LDSymbol::Create(*result.info);
result.info->setSymPtr(output_sym);
output_sym->setFragmentRef(FragmentRef::Null());
}
}
}
void ObjectLinker::normalize()
{
// ----- set up inputs ----- //
Module::input_iterator input, inEnd = m_pModule->input_end();
for (input = m_pModule->input_begin(); input!=inEnd; ++input) {
// is a group node
if (isGroup(input)) {
getGroupReader()->readGroup(input, inEnd, m_pBuilder->getInputBuilder(),
m_Config);
continue;
}
// already got type - for example, bitcode or external OIR (object
// intermediate representation)
if ((*input)->type() == Input::Script ||
(*input)->type() == Input::Archive ||
(*input)->type() == Input::External)
continue;
if (Input::Object == (*input)->type()) {
m_pModule->getObjectList().push_back(*input);
continue;
}
if (Input::DynObj == (*input)->type()) {
m_pModule->getLibraryList().push_back(*input);
continue;
}
bool doContinue = false;
// read input as a binary file
if (getBinaryReader()->isMyFormat(**input, doContinue)) {
(*input)->setType(Input::Object);
getBinaryReader()->readBinary(**input);
m_pModule->getObjectList().push_back(*input);
}
// is a relocatable object file
else if (doContinue && getObjectReader()->isMyFormat(**input, doContinue)) {
(*input)->setType(Input::Object);
getObjectReader()->readHeader(**input);
getObjectReader()->readSections(**input);
getObjectReader()->readSymbols(**input);
m_pModule->getObjectList().push_back(*input);
}
// is a shared object file
else if (doContinue && getDynObjReader()->isMyFormat(**input, doContinue)) {
(*input)->setType(Input::DynObj);
getDynObjReader()->readHeader(**input);
getDynObjReader()->readSymbols(**input);
m_pModule->getLibraryList().push_back(*input);
}
// is an archive
else if (doContinue && getArchiveReader()->isMyFormat(**input, doContinue)) {
(*input)->setType(Input::Archive);
if (m_Config.options().isInExcludeLIBS(**input)) {
(*input)->setNoExport();
}
Archive archive(**input, m_pBuilder->getInputBuilder());
getArchiveReader()->readArchive(m_Config, archive);
if(archive.numOfObjectMember() > 0) {
m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
archive.inputs());
}
}
// try to parse input as a linker script
else if (doContinue && getScriptReader()->isMyFormat(**input, doContinue)) {
ScriptFile script(ScriptFile::LDScript, **input,
m_pBuilder->getInputBuilder());
if (getScriptReader()->readScript(m_Config, script)) {
(*input)->setType(Input::Script);
script.activate(*m_pModule);
if (script.inputs().size() > 0) {
m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
script.inputs());
}
}
}
else {
if (m_Config.options().warnMismatch())
warning(diag::warn_unrecognized_input_file) << (*input)->path()
<< m_Config.targets().triple().str();
}
} // end of for
}
bool ObjectLinker::linkable() const
{
// check we have input and output files
if (m_pModule->getInputTree().empty()) {
error(diag::err_no_inputs);
return false;
}
// can not mix -static with shared objects
Module::const_lib_iterator lib, libEnd = m_pModule->lib_end();
for (lib = m_pModule->lib_begin(); lib != libEnd; ++lib) {
if((*lib)->attribute()->isStatic()) {
error(diag::err_mixed_shared_static_objects)
<< (*lib)->name() << (*lib)->path();
return false;
}
}
// --nmagic and --omagic options lead to static executable program.
// These options turn off page alignment of sections. Because the
// sections are not aligned to pages, these sections can not contain any
// exported functions. Also, because the two options disable linking
// against shared libraries, the output absolutely does not call outside
// functions.
if (m_Config.options().nmagic() && !m_Config.isCodeStatic()) {
error(diag::err_nmagic_not_static);
return false;
}
if (m_Config.options().omagic() && !m_Config.isCodeStatic()) {
error(diag::err_omagic_not_static);
return false;
}
return true;
}
void ObjectLinker::dataStrippingOpt()
{
// Garbege collection
if (m_Config.options().GCSections()) {
GarbageCollection GC(m_Config, m_LDBackend, *m_pModule);
GC.run();
}
// Identical code folding
if (m_Config.options().getICFMode() != GeneralOptions::ICF_None) {
IdenticalCodeFolding icf(m_Config, m_LDBackend, *m_pModule);
icf.foldIdenticalCode();
}
return;
}
/// readRelocations - read all relocation entries
///
/// All symbols should be read and resolved before this function.
bool ObjectLinker::readRelocations()
{
// Bitcode is read by the other path. This function reads relocation sections
// in object files.
mcld::InputTree::bfs_iterator input, inEnd = m_pModule->getInputTree().bfs_end();
for (input=m_pModule->getInputTree().bfs_begin(); input!=inEnd; ++input) {
if ((*input)->type() == Input::Object && (*input)->hasMemArea()) {
if (!getObjectReader()->readRelocations(**input))
return false;
}
// ignore the other kinds of files.
}
return true;
}
/// mergeSections - put allinput sections into output sections
bool ObjectLinker::mergeSections()
{
ObjectBuilder builder(*m_pModule);
Module::obj_iterator obj, objEnd = m_pModule->obj_end();
for (obj = m_pModule->obj_begin(); obj != objEnd; ++obj) {
LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
switch ((*sect)->kind()) {
// Some *INPUT sections should not be merged.
case LDFileFormat::Folded:
case LDFileFormat::Ignore:
case LDFileFormat::Null:
case LDFileFormat::NamePool:
case LDFileFormat::Group:
case LDFileFormat::StackNote:
// skip
continue;
case LDFileFormat::Relocation: {
if (!(*sect)->hasRelocData())
continue; // skip
if ((*sect)->getLink()->kind() == LDFileFormat::Ignore ||
(*sect)->getLink()->kind() == LDFileFormat::Folded)
(*sect)->setKind(LDFileFormat::Ignore);
break;
}
case LDFileFormat::Target:
if (!m_LDBackend.mergeSection(*m_pModule, **obj, **sect)) {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
}
break;
case LDFileFormat::EhFrame: {
if (!(*sect)->hasEhFrame())
continue; // skip
LDSection* out_sect = NULL;
if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
}
}
break;
}
default: {
if (!(*sect)->hasSectionData())
continue; // skip
LDSection* out_sect = NULL;
if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
}
}
break;
}
} // end of switch
} // for each section
} // for each obj
RpnEvaluator evaluator(*m_pModule, m_LDBackend);
SectionMap::iterator out, outBegin, outEnd;
outBegin = m_pModule->getScript().sectionMap().begin();
outEnd = m_pModule->getScript().sectionMap().end();
for (out = outBegin; out != outEnd; ++out) {
uint64_t out_align = 0x0, in_align = 0x0;
LDSection* out_sect = (*out)->getSection();
SectionMap::Output::iterator in, inBegin, inEnd;
inBegin = (*out)->begin();
inEnd = (*out)->end();
// force input alignment from ldscript if any
if ((*out)->prolog().hasSubAlign()) {
evaluator.eval((*out)->prolog().subAlign(), in_align);
}
for (in = inBegin; in != inEnd; ++in) {
LDSection* in_sect = (*in)->getSection();
if ((*out)->prolog().hasSubAlign())
in_sect->setAlign(in_align);
if (builder.MoveSectionData(*in_sect->getSectionData(),
*out_sect->getSectionData())) {
builder.UpdateSectionAlign(*out_sect, *in_sect);
m_LDBackend.updateSectionFlags(*out_sect, *in_sect);
}
} // for each input section description
// force output alignment from ldscript if any
if ((*out)->prolog().hasAlign()) {
evaluator.eval((*out)->prolog().align(), out_align);
out_sect->setAlign(out_align);
}
if ((*out)->hasContent()) {
LDSection* target = m_pModule->getSection((*out)->name());
assert(target != NULL && target->hasSectionData());
if (builder.MoveSectionData(*out_sect->getSectionData(),
*target->getSectionData())) {
builder.UpdateSectionAlign(*target, *out_sect);
m_LDBackend.updateSectionFlags(*target, *out_sect);
}
}
} // for each output section description
return true;
}
void ObjectLinker::addSymbolToOutput(ResolveInfo& pInfo, Module& pModule)
{
// section symbols will be defined by linker later, we should not add section
// symbols to output here
if (ResolveInfo::Section == pInfo.type() || NULL == pInfo.outSymbol())
return;
// if the symbols defined in the Ignore sections (e.g. discared by GC), then
// not to put them to output
if (pInfo.outSymbol()->hasFragRef() && LDFileFormat::Ignore ==
pInfo.outSymbol()->fragRef()->frag()->getParent()->getSection().kind())
return;
if (pInfo.shouldForceLocal(m_Config))
pModule.getSymbolTable().forceLocal(*pInfo.outSymbol());
else
pModule.getSymbolTable().add(*pInfo.outSymbol());
}
void ObjectLinker::addSymbolsToOutput(Module& pModule)
{
// Traverse all the free ResolveInfo and add the output symobols to output
NamePool::freeinfo_iterator free_it,
free_end = pModule.getNamePool().freeinfo_end();
for (free_it = pModule.getNamePool().freeinfo_begin(); free_it != free_end;
++free_it)
addSymbolToOutput(**free_it, pModule);
// Traverse all the resolveInfo and add the output symbol to output
NamePool::syminfo_iterator info_it,
info_end = pModule.getNamePool().syminfo_end();
for (info_it = pModule.getNamePool().syminfo_begin(); info_it != info_end;
++info_it)
addSymbolToOutput(*info_it.getEntry(), pModule);
}
/// addStandardSymbols - shared object and executable files need some
/// standard symbols
/// @return if there are some input symbols with the same name to the
/// standard symbols, return false
bool ObjectLinker::addStandardSymbols()
{
// create and add section symbols for each output section
Module::iterator iter, iterEnd = m_pModule->end();
for (iter = m_pModule->begin(); iter != iterEnd; ++iter) {
m_pModule->getSectionSymbolSet().add(**iter, m_pModule->getNamePool());
}
return m_LDBackend.initStandardSymbols(*m_pBuilder, *m_pModule);
}
/// addTargetSymbols - some targets, such as MIPS and ARM, need some
/// target-dependent symbols
/// @return if there are some input symbols with the same name to the
/// target symbols, return false
bool ObjectLinker::addTargetSymbols()
{
m_LDBackend.initTargetSymbols(*m_pBuilder, *m_pModule);
return true;
}
/// addScriptSymbols - define symbols from the command line option or linker
/// scripts.
bool ObjectLinker::addScriptSymbols()
{
LinkerScript& script = m_pModule->getScript();
LinkerScript::Assignments::iterator it, ie = script.assignments().end();
// go through the entire symbol assignments
for (it = script.assignments().begin(); it != ie; ++it) {
LDSymbol* symbol = NULL;
assert((*it).second.symbol().type() == Operand::SYMBOL);
const llvm::StringRef symName = (*it).second.symbol().name();
ResolveInfo::Type type = ResolveInfo::NoType;
ResolveInfo::Visibility vis = ResolveInfo::Default;
size_t size = 0;
ResolveInfo* old_info = m_pModule->getNamePool().findInfo(symName);
// if the symbol does not exist, we can set type to NOTYPE
// else we retain its type, same goes for size - 0 or retain old value
// and visibility - Default or retain
if (old_info != NULL) {
type = static_cast<ResolveInfo::Type>(old_info->type());
vis = old_info->visibility();
size = old_info->size();
}
// Add symbol and refine the visibility if needed
// FIXME: bfd linker would change the binding instead, but currently
// ABS is also a kind of Binding in ResolveInfo.
switch ((*it).second.type()) {
case Assignment::HIDDEN:
vis = ResolveInfo::Hidden;
// Fall through
case Assignment::DEFAULT:
symbol =
m_pBuilder->AddSymbol<IRBuilder::Force,
IRBuilder::Unresolve>(symName,
type,
ResolveInfo::Define,
ResolveInfo::Absolute,
size,
0x0,
FragmentRef::Null(),
vis);
break;
case Assignment::PROVIDE_HIDDEN:
vis = ResolveInfo::Hidden;
// Fall through
case Assignment::PROVIDE:
symbol =
m_pBuilder->AddSymbol<IRBuilder::AsReferred,
IRBuilder::Unresolve>(symName,
type,
ResolveInfo::Define,
ResolveInfo::Absolute,
size,
0x0,
FragmentRef::Null(),
vis);
break;
}
// Set symbol of this assignment.
(*it).first = symbol;
}
return true;
}
bool ObjectLinker::scanRelocations()
{
// apply all relocations of all inputs
Module::obj_iterator input, inEnd = m_pModule->obj_end();
for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
m_LDBackend.getRelocator()->initializeScan(**input);
LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
// bypass the reloc section if
// 1. its section kind is changed to Ignore. (The target section is a
// discarded group section.)
// 2. it has no reloc data. (All symbols in the input relocs are in the
// discarded group sections)
if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
continue;
RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
Relocation* relocation = llvm::cast<Relocation>(reloc);
// bypass the reloc if the symbol is in the discarded input section
ResolveInfo* info = relocation->symInfo();
if (!info->outSymbol()->hasFragRef() &&
ResolveInfo::Section == info->type() &&
ResolveInfo::Undefined == info->desc())
continue;
// scan relocation
if (LinkerConfig::Object != m_Config.codeGenType())
m_LDBackend.getRelocator()->scanRelocation(
*relocation, *m_pBuilder, *m_pModule, **rs, **input);
else
m_LDBackend.getRelocator()->partialScanRelocation(
*relocation, *m_pModule, **rs);
} // for all relocations
} // for all relocation section
m_LDBackend.getRelocator()->finalizeScan(**input);
} // for all inputs
return true;
}
/// initStubs - initialize stub-related stuff.
bool ObjectLinker::initStubs()
{
// initialize BranchIslandFactory
m_LDBackend.initBRIslandFactory();
// initialize StubFactory
m_LDBackend.initStubFactory();
// initialize target stubs
m_LDBackend.initTargetStubs();
return true;
}
/// allocateCommonSymobols - allocate fragments for common symbols to the
/// corresponding sections
bool ObjectLinker::allocateCommonSymbols()
{
if (LinkerConfig::Object != m_Config.codeGenType() ||
m_Config.options().isDefineCommon())
return m_LDBackend.allocateCommonSymbols(*m_pModule);
return true;
}
/// prelayout - help backend to do some modification before layout
bool ObjectLinker::prelayout()
{
// finalize the section symbols, set their fragment reference and push them
// into output symbol table
Module::iterator sect, sEnd = m_pModule->end();
for (sect = m_pModule->begin(); sect != sEnd; ++sect) {
m_pModule->getSectionSymbolSet().finalize(**sect,
m_pModule->getSymbolTable(),
m_Config.codeGenType() == LinkerConfig::Object);
}
m_LDBackend.preLayout(*m_pModule, *m_pBuilder);
/// check program interpreter - computer the name size of the runtime dyld
if (!m_Config.isCodeStatic() &&
(LinkerConfig::Exec == m_Config.codeGenType() ||
m_Config.options().isPIE() ||
m_Config.options().hasDyld()))
m_LDBackend.sizeInterp();
/// measure NamePools - compute the size of name pool sections
/// In ELF, will compute the size of.symtab, .strtab, .dynsym, .dynstr,
/// .hash and .shstrtab sections.
///
/// dump all symbols and strings from ObjectLinker and build the format-dependent
/// hash table.
/// @note sizeNamePools replies on LinkerConfig::CodePosition. Must determine
/// code position model before calling GNULDBackend::sizeNamePools()
m_LDBackend.sizeNamePools(*m_pModule);
// Do this after backend prelayout since it may add eh_frame entries.
LDSection* eh_frame_sect = m_pModule->getSection(".eh_frame");
if (eh_frame_sect && eh_frame_sect->hasEhFrame())
eh_frame_sect->getEhFrame()->computeOffsetSize();
m_LDBackend.createAndSizeEhFrameHdr(*m_pModule);
return true;
}
/// layout - linearly layout all output sections and reserve some space
/// for GOT/PLT
/// Because we do not support instruction relaxing in this early version,
/// if there is a branch can not jump to its target, we return false
/// directly
bool ObjectLinker::layout()
{
m_LDBackend.layout(*m_pModule);
return true;
}
/// prelayout - help backend to do some modification after layout
bool ObjectLinker::postlayout()
{
m_LDBackend.postLayout(*m_pModule, *m_pBuilder);
return true;
}
/// finalizeSymbolValue - finalize the resolved symbol value.
/// Before relocate(), after layout(), ObjectLinker should correct value of all
/// symbol.
bool ObjectLinker::finalizeSymbolValue()
{
Module::sym_iterator symbol, symEnd = m_pModule->sym_end();
for (symbol = m_pModule->sym_begin(); symbol != symEnd; ++symbol) {
if ((*symbol)->resolveInfo()->isAbsolute() ||
(*symbol)->resolveInfo()->type() == ResolveInfo::File) {
// absolute symbols should just use its value directly (i.e., the result
// of symbol resolution)
continue;
}
if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
m_LDBackend.finalizeTLSSymbol(**symbol);
continue;
}
if ((*symbol)->hasFragRef()) {
// set the virtual address of the symbol. If the output file is
// relocatable object file, the section's virtual address becomes zero.
// And the symbol's value become section relative offset.
uint64_t value = (*symbol)->fragRef()->getOutputOffset();
assert(NULL != (*symbol)->fragRef()->frag());
uint64_t addr =
(*symbol)->fragRef()->frag()->getParent()->getSection().addr();
(*symbol)->setValue(value + addr);
continue;
}
}
RpnEvaluator evaluator(*m_pModule, m_LDBackend);
bool finalized = m_LDBackend.finalizeSymbols();
bool scriptSymsFinalized = true;
LinkerScript& script = m_pModule->getScript();
LinkerScript::Assignments::iterator assign, assignEnd;
assignEnd = script.assignments().end();
for (assign = script.assignments().begin(); assign != assignEnd; ++assign) {
LDSymbol* symbol = (*assign).first;
Assignment& assignment = (*assign).second;
if (symbol == NULL)
continue;
scriptSymsFinalized &= assignment.assign(evaluator);
if (!scriptSymsFinalized)
break;
symbol->setValue(assignment.symbol().value());
} // for each script symbol assignment
bool assertionsPassed = true;
LinkerScript::Assertions::iterator assert, assertEnd;
assertEnd = script.assertions().end();
for (assert = script.assertions().begin(); assert != assertEnd; ++assert) {
uint64_t res = 0x0;
evaluator.eval((*assert).getRpnExpr(), res);
if (res == 0x0)
fatal(diag::err_assert_failed) << (*assert).message();
} // for each assertion in ldscript
return finalized && scriptSymsFinalized && assertionsPassed;
}
/// relocate - applying relocation entries and create relocation
/// section in the output files
/// Create relocation section, asking TargetLDBackend to
/// read the relocation information into RelocationEntry
/// and push_back into the relocation section
bool ObjectLinker::relocation()
{
// when producing relocatables, no need to apply relocation
if (LinkerConfig::Object == m_Config.codeGenType())
return true;
// apply all relocations of all inputs
Module::obj_iterator input, inEnd = m_pModule->obj_end();
for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
m_LDBackend.getRelocator()->initializeApply(**input);
LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
// bypass the reloc section if
// 1. its section kind is changed to Ignore. (The target section is a
// discarded group section.)
// 2. it has no reloc data. (All symbols in the input relocs are in the
// discarded group sections)
if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
continue;
RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
Relocation* relocation = llvm::cast<Relocation>(reloc);
// bypass the reloc if the symbol is in the discarded input section
ResolveInfo* info = relocation->symInfo();
if (!info->outSymbol()->hasFragRef() &&
ResolveInfo::Section == info->type() &&
ResolveInfo::Undefined == info->desc())
continue;
relocation->apply(*m_LDBackend.getRelocator());
} // for all relocations
} // for all relocation section
m_LDBackend.getRelocator()->finalizeApply(**input);
} // for all inputs
// apply relocations created by relaxation
BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
BranchIsland& island = *facIter;
BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
(*iter)->apply(*m_LDBackend.getRelocator());
}
return true;
}
/// emitOutput - emit the output file.
bool ObjectLinker::emitOutput(FileOutputBuffer& pOutput)
{
return std::error_code() == getWriter()->writeObject(*m_pModule, pOutput);
}
/// postProcessing - do modification after all processes
bool ObjectLinker::postProcessing(FileOutputBuffer& pOutput)
{
if (LinkerConfig::Object != m_Config.codeGenType())
normalSyncRelocationResult(pOutput);
else
partialSyncRelocationResult(pOutput);
// emit .eh_frame_hdr
// eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
// needs FDE PC value, which will be corrected at syncRelocation
m_LDBackend.postProcessing(pOutput);
return true;
}
void ObjectLinker::normalSyncRelocationResult(FileOutputBuffer& pOutput)
{
uint8_t* data = pOutput.getBufferStart();
// sync all relocations of all inputs
Module::obj_iterator input, inEnd = m_pModule->obj_end();
for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
// bypass the reloc section if
// 1. its section kind is changed to Ignore. (The target section is a
// discarded group section.)
// 2. it has no reloc data. (All symbols in the input relocs are in the
// discarded group sections)
if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
continue;
RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
Relocation* relocation = llvm::cast<Relocation>(reloc);
// bypass the reloc if the symbol is in the discarded input section
ResolveInfo* info = relocation->symInfo();
if (!info->outSymbol()->hasFragRef() &&
ResolveInfo::Section == info->type() &&
ResolveInfo::Undefined == info->desc())
continue;
// bypass the relocation with NONE type. This is to avoid overwrite the
// target result by NONE type relocation if there is a place which has
// two relocations to apply to, and one of it is NONE type. The result
// we want is the value of the other relocation result. For example,
// in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
// the same place
if (0x0 == relocation->type())
continue;
writeRelocationResult(*relocation, data);
} // for all relocations
} // for all relocation section
} // for all inputs
// sync relocations created by relaxation
BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
BranchIsland& island = *facIter;
BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
Relocation* reloc = *iter;
writeRelocationResult(*reloc, data);
}
}
}
void ObjectLinker::partialSyncRelocationResult(FileOutputBuffer& pOutput)
{
uint8_t* data = pOutput.getBufferStart();
// traverse outputs' LDSection to get RelocData
Module::iterator sectIter, sectEnd = m_pModule->end();
for (sectIter = m_pModule->begin(); sectIter != sectEnd; ++sectIter) {
if (LDFileFormat::Relocation != (*sectIter)->kind())
continue;
RelocData* reloc_data = (*sectIter)->getRelocData();
RelocData::iterator relocIter, relocEnd = reloc_data->end();
for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
Relocation* reloc = llvm::cast<Relocation>(relocIter);
// bypass the relocation with NONE type. This is to avoid overwrite the
// target result by NONE type relocation if there is a place which has
// two relocations to apply to, and one of it is NONE type. The result
// we want is the value of the other relocation result. For example,
// in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
// the same place
if (0x0 == reloc->type())
continue;
writeRelocationResult(*reloc, data);
}
}
}
void ObjectLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
{
// get output file offset
size_t out_offset =
pReloc.targetRef().frag()->getParent()->getSection().offset() +
pReloc.targetRef().getOutputOffset();
uint8_t* target_addr = pOutput + out_offset;
// byte swapping if target and host has different endian, and then write back
if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian()) {
uint64_t tmp_data = 0;
switch(pReloc.size(*m_LDBackend.getRelocator())) {
case 8u:
std::memcpy(target_addr, &pReloc.target(), 1);
break;
case 16u:
tmp_data = mcld::bswap16(pReloc.target());
std::memcpy(target_addr, &tmp_data, 2);
break;
case 32u:
tmp_data = mcld::bswap32(pReloc.target());
std::memcpy(target_addr, &tmp_data, 4);
break;
case 64u:
tmp_data = mcld::bswap64(pReloc.target());
std::memcpy(target_addr, &tmp_data, 8);
break;
default:
break;
}
}
else
std::memcpy(target_addr, &pReloc.target(),
pReloc.size(*m_LDBackend.getRelocator())/8);
}