You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
995 lines
37 KiB
995 lines
37 KiB
//===- 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/InputTree.h"
|
|
#include "mcld/IRBuilder.h"
|
|
#include "mcld/LinkerConfig.h"
|
|
#include "mcld/LinkerScript.h"
|
|
#include "mcld/Module.h"
|
|
#include "mcld/Fragment/Relocation.h"
|
|
#include "mcld/LD/Archive.h"
|
|
#include "mcld/LD/ArchiveReader.h"
|
|
#include "mcld/LD/BinaryReader.h"
|
|
#include "mcld/LD/BranchIslandFactory.h"
|
|
#include "mcld/LD/DebugString.h"
|
|
#include "mcld/LD/DynObjReader.h"
|
|
#include "mcld/LD/GarbageCollection.h"
|
|
#include "mcld/LD/GroupReader.h"
|
|
#include "mcld/LD/IdenticalCodeFolding.h"
|
|
#include "mcld/LD/LDContext.h"
|
|
#include "mcld/LD/LDSection.h"
|
|
#include "mcld/LD/ObjectReader.h"
|
|
#include "mcld/LD/ObjectWriter.h"
|
|
#include "mcld/LD/Relocator.h"
|
|
#include "mcld/LD/RelocData.h"
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
#include "mcld/LD/SectionData.h"
|
|
#include "mcld/Object/ObjectBuilder.h"
|
|
#include "mcld/Script/Assignment.h"
|
|
#include "mcld/Script/Operand.h"
|
|
#include "mcld/Script/RpnEvaluator.h"
|
|
#include "mcld/Script/ScriptFile.h"
|
|
#include "mcld/Script/ScriptReader.h"
|
|
#include "mcld/Support/FileOutputBuffer.h"
|
|
#include "mcld/Support/MsgHandling.h"
|
|
#include "mcld/Support/RealPath.h"
|
|
#include "mcld/Target/TargetLDBackend.h"
|
|
|
|
#include <llvm/Support/Casting.h>
|
|
#include <llvm/Support/Host.h>
|
|
|
|
#include <system_error>
|
|
|
|
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_pObjectReader, *m_pArchiveReader, *m_pDynObjReader, *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();
|
|
// create the output symbol if it dose not have one
|
|
if (!result.existent || (output_sym != NULL)) {
|
|
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);
|
|
} else if (doContinue &&
|
|
getObjectReader()->isMyFormat(**input, doContinue)) {
|
|
// is a relocatable object file
|
|
(*input)->setType(Input::Object);
|
|
getObjectReader()->readHeader(**input);
|
|
getObjectReader()->readSections(**input);
|
|
getObjectReader()->readSymbols(**input);
|
|
m_pModule->getObjectList().push_back(*input);
|
|
} else if (doContinue &&
|
|
getDynObjReader()->isMyFormat(**input, doContinue)) {
|
|
// is a shared object file
|
|
(*input)->setType(Input::DynObj);
|
|
getDynObjReader()->readHeader(**input);
|
|
getDynObjReader()->readSymbols(**input);
|
|
m_pModule->getLibraryList().push_back(*input);
|
|
} else if (doContinue &&
|
|
getArchiveReader()->isMyFormat(**input, doContinue)) {
|
|
// is an archive
|
|
(*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());
|
|
}
|
|
} else if (doContinue &&
|
|
getScriptReader()->isMyFormat(**input, doContinue)) {
|
|
// try to parse input as a linker script
|
|
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() {
|
|
if (m_Config.codeGenType() == LinkerConfig::Object) {
|
|
return;
|
|
}
|
|
|
|
// 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() {
|
|
// run the target-dependent hooks before merging sections
|
|
m_LDBackend.preMergeSections(*m_pModule);
|
|
|
|
// Set up input/output from ldscript requirement if any
|
|
{
|
|
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);
|
|
} // 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);
|
|
}
|
|
} // for each output section description
|
|
}
|
|
|
|
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 ((out_sect = builder.MergeSection(**obj, **sect)) != NULL) {
|
|
if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
|
|
error(diag::err_cannot_merge_section) << (*sect)->name()
|
|
<< (*obj)->name();
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case LDFileFormat::DebugString: {
|
|
// FIXME: disable debug string merge when doing partial link.
|
|
if (LinkerConfig::Object == m_Config.codeGenType())
|
|
(*sect)->setKind(LDFileFormat::Debug);
|
|
}
|
|
// Fall through
|
|
default: {
|
|
if (!(*sect)->hasSectionData())
|
|
continue; // skip
|
|
|
|
LDSection* out_sect = NULL;
|
|
if ((out_sect = builder.MergeSection(**obj, **sect)) != NULL) {
|
|
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
|
|
|
|
{
|
|
SectionMap::iterator out, outBegin, outEnd;
|
|
outBegin = m_pModule->getScript().sectionMap().begin();
|
|
outEnd = m_pModule->getScript().sectionMap().end();
|
|
for (out = outBegin; out != outEnd; ++out) {
|
|
LDSection* out_sect = (*out)->getSection();
|
|
SectionMap::Output::iterator in, inBegin, inEnd;
|
|
inBegin = (*out)->begin();
|
|
inEnd = (*out)->end();
|
|
|
|
for (in = inBegin; in != inEnd; ++in) {
|
|
LDSection* in_sect = (*in)->getSection();
|
|
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
|
|
|
|
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
|
|
}
|
|
|
|
// run the target-dependent hooks after merging sections
|
|
m_LDBackend.postMergeSections(*m_pModule);
|
|
|
|
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() || pInfo.outSymbol() == NULL)
|
|
return;
|
|
|
|
// if the symbols defined in the Ignore sections (e.g. discared by GC), then
|
|
// not to put them to output
|
|
// make sure that symbols defined in .debug_str won't add into output
|
|
// symbol table. Since these symbols has fragRef to input fragments, which
|
|
// will refer to input LDSection and has bad result when emitting their
|
|
// section index. However, .debug_str actually does not need symobl in
|
|
// shrad/executable objects, so it's fine to do so.
|
|
if (pInfo.outSymbol()->hasFragRef() &&
|
|
(LDFileFormat::Ignore ==
|
|
pInfo.outSymbol()
|
|
->fragRef()
|
|
->frag()
|
|
->getParent()
|
|
->getSection()
|
|
.kind() ||
|
|
LDFileFormat::DebugString ==
|
|
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);
|
|
}
|
|
} // 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);
|
|
|
|
// size debug string table and set up the debug string offset
|
|
// we set the .debug_str size here so that there won't be a section symbol for
|
|
// .debug_str. While actually it doesn't matter that .debug_str has section
|
|
// symbol or not.
|
|
// FIXME: disable debug string merge when doing partial link.
|
|
if (LinkerConfig::Object != m_Config.codeGenType()) {
|
|
LDSection* debug_str_sect = m_pModule->getSection(".debug_str");
|
|
if (debug_str_sect && debug_str_sect->hasDebugString())
|
|
debug_str_sect->getDebugString()->computeOffsetSize();
|
|
}
|
|
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((*symbol)->fragRef()->frag() != NULL);
|
|
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;
|
|
|
|
LDSection* debug_str_sect = m_pModule->getSection(".debug_str");
|
|
|
|
// 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;
|
|
|
|
// apply the relocation aginst symbol on DebugString
|
|
if (info->outSymbol()->hasFragRef() &&
|
|
info->outSymbol()->fragRef()->frag()->getKind()
|
|
== Fragment::Region &&
|
|
info->outSymbol()->fragRef()->frag()->getParent()->getSection()
|
|
.kind() == LDFileFormat::DebugString) {
|
|
assert(debug_str_sect != NULL);
|
|
assert(debug_str_sect->hasDebugString());
|
|
debug_str_sect->getDebugString()->applyOffset(*relocation,
|
|
m_LDBackend);
|
|
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());
|
|
}
|
|
|
|
// apply relocations created by LD backend
|
|
for (TargetLDBackend::extra_reloc_iterator
|
|
iter = m_LDBackend.extra_reloc_begin(),
|
|
end = m_LDBackend.extra_reloc_end(); iter != end; ++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 (relocation->type() == 0x0)
|
|
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);
|
|
}
|
|
}
|
|
|
|
// sync relocations created by LD backend
|
|
for (TargetLDBackend::extra_reloc_iterator
|
|
iter = m_LDBackend.extra_reloc_begin(),
|
|
end = m_LDBackend.extra_reloc_end(); iter != end; ++iter) {
|
|
writeRelocationResult(*iter, 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 (reloc->type() == 0x0)
|
|
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()) + 7) / 8);
|
|
}
|
|
}
|
|
|
|
} // namespace mcld
|