summaryrefslogtreecommitdiff
path: root/lib/Object/ObjectLinker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Object/ObjectLinker.cpp')
-rw-r--r--lib/Object/ObjectLinker.cpp238
1 files changed, 124 insertions, 114 deletions
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
index 1e2ccb4..bbca437 100644
--- a/lib/Object/ObjectLinker.cpp
+++ b/lib/Object/ObjectLinker.cpp
@@ -21,9 +21,6 @@
#include <mcld/LD/GroupReader.h>
#include <mcld/LD/BinaryReader.h>
#include <mcld/LD/ObjectWriter.h>
-#include <mcld/LD/DynObjWriter.h>
-#include <mcld/LD/ExecWriter.h>
-#include <mcld/LD/BinaryWriter.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/RelocData.h>
#include <mcld/Support/RealPath.h>
@@ -35,32 +32,23 @@
#include <llvm/Support/Casting.h>
+
using namespace llvm;
using namespace mcld;
ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
- Module& pModule,
- IRBuilder& pBuilder,
TargetLDBackend& pLDBackend)
: m_Config(pConfig),
- m_Module(pModule),
- m_Builder(pBuilder),
m_pLinker(NULL),
+ 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_pObjectWriter(NULL),
- m_pDynObjWriter(NULL),
- m_pExecWriter(NULL),
- m_pBinaryWriter(NULL)
-{
- // set up soname
- if (!m_Config.options().soname().empty()) {
- m_Module.setName(m_Config.options().soname());
- }
+ m_pWriter(NULL) {
}
ObjectLinker::~ObjectLinker()
@@ -71,10 +59,17 @@ ObjectLinker::~ObjectLinker()
delete m_pArchiveReader;
delete m_pGroupReader;
delete m_pBinaryReader;
- delete m_pObjectWriter;
- delete m_pDynObjWriter;
- delete m_pExecWriter;
- delete m_pBinaryWriter;
+ delete m_pWriter;
+}
+
+void ObjectLinker::setup(Module& pModule, IRBuilder& pBuilder)
+{
+ m_pModule = &pModule;
+ m_pBuilder = &pBuilder;
+ // set up soname
+ if (!m_Config.options().soname().empty()) {
+ m_pModule->setName(m_Config.options().soname());
+ }
}
/// initFragmentLinker - initialize FragmentLinker
@@ -83,49 +78,37 @@ bool ObjectLinker::initFragmentLinker()
{
if (NULL == m_pLinker) {
m_pLinker = new FragmentLinker(m_Config,
- m_Module,
+ *m_pModule,
m_LDBackend);
}
// initialize the readers and writers
// Because constructor can not be failed, we initalize all readers and
// writers outside the FragmentLinker constructors.
- m_pObjectReader = m_LDBackend.createObjectReader(m_Builder);
- m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module);
- m_pDynObjReader = m_LDBackend.createDynObjReader(m_Builder);
- m_pGroupReader = new GroupReader(m_Module, *m_pObjectReader,
+ m_pObjectReader = m_LDBackend.createObjectReader(*m_pBuilder);
+ m_pArchiveReader = m_LDBackend.createArchiveReader(*m_pModule);
+ m_pDynObjReader = m_LDBackend.createDynObjReader(*m_pBuilder);
+ m_pGroupReader = new GroupReader(*m_pModule, *m_pObjectReader,
*m_pDynObjReader, *m_pArchiveReader);
- m_pBinaryReader = m_LDBackend.createBinaryReader(m_Builder);
- m_pObjectWriter = m_LDBackend.createObjectWriter();
- m_pDynObjWriter = m_LDBackend.createDynObjWriter();
- m_pExecWriter = m_LDBackend.createExecWriter();
- m_pBinaryWriter = m_LDBackend.createBinaryWriter();
+ m_pBinaryReader = m_LDBackend.createBinaryReader(*m_pBuilder);
+ m_pWriter = m_LDBackend.createWriter();
// initialize Relocator
- m_LDBackend.initRelocator(*m_pLinker);
-
- // initialize BranchIslandFactory
- m_LDBackend.initBRIslandFactory();
-
- // initialize StubFactory
- m_LDBackend.initStubFactory();
-
- // initialize target stubs
- m_LDBackend.initTargetStubs(*m_pLinker);
+ m_LDBackend.initRelocator();
return true;
}
/// initStdSections - initialize standard sections
bool ObjectLinker::initStdSections()
{
- ObjectBuilder builder(m_Config, m_Module);
+ ObjectBuilder builder(m_Config, *m_pModule);
// initialize standard sections
if (!m_LDBackend.initStdSections(builder))
return false;
// initialize target-dependent sections
- m_LDBackend.initTargetSections(m_Module, builder);
+ m_LDBackend.initTargetSections(*m_pModule, builder);
return true;
}
@@ -133,11 +116,11 @@ bool ObjectLinker::initStdSections()
void ObjectLinker::normalize()
{
// ----- set up inputs ----- //
- Module::input_iterator input, inEnd = m_Module.input_end();
- for (input = m_Module.input_begin(); input!=inEnd; ++input) {
+ 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, m_Builder.getInputBuilder(), m_Config);
+ getGroupReader()->readGroup(input, m_pBuilder->getInputBuilder(), m_Config);
continue;
}
@@ -149,12 +132,12 @@ void ObjectLinker::normalize()
continue;
if (Input::Object == (*input)->type()) {
- m_Module.getObjectList().push_back(*input);
+ m_pModule->getObjectList().push_back(*input);
continue;
}
if (Input::DynObj == (*input)->type()) {
- m_Module.getLibraryList().push_back(*input);
+ m_pModule->getLibraryList().push_back(*input);
continue;
}
@@ -162,7 +145,7 @@ void ObjectLinker::normalize()
if (m_Config.options().isBinaryInput()) {
(*input)->setType(Input::Object);
getBinaryReader()->readBinary(**input);
- m_Module.getObjectList().push_back(*input);
+ m_pModule->getObjectList().push_back(*input);
}
// is a relocatable object file
else if (getObjectReader()->isMyFormat(**input)) {
@@ -170,22 +153,22 @@ void ObjectLinker::normalize()
getObjectReader()->readHeader(**input);
getObjectReader()->readSections(**input);
getObjectReader()->readSymbols(**input);
- m_Module.getObjectList().push_back(*input);
+ m_pModule->getObjectList().push_back(*input);
}
// is a shared object file
else if (getDynObjReader()->isMyFormat(**input)) {
(*input)->setType(Input::DynObj);
getDynObjReader()->readHeader(**input);
getDynObjReader()->readSymbols(**input);
- m_Module.getLibraryList().push_back(*input);
+ m_pModule->getLibraryList().push_back(*input);
}
// is an archive
else if (getArchiveReader()->isMyFormat(**input)) {
(*input)->setType(Input::Archive);
- Archive archive(**input, m_Builder.getInputBuilder());
+ Archive archive(**input, m_pBuilder->getInputBuilder());
getArchiveReader()->readArchive(archive);
if(archive.numOfObjectMember() > 0) {
- m_Module.getInputTree().merge<InputTree::Inclusive>(input,
+ m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
archive.inputs());
}
}
@@ -199,14 +182,14 @@ void ObjectLinker::normalize()
bool ObjectLinker::linkable() const
{
// check we have input and output files
- if (m_Module.getInputTree().empty()) {
+ 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_Module.lib_end();
- for (lib = m_Module.lib_begin(); lib != libEnd; ++lib) {
+ 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();
@@ -214,7 +197,21 @@ bool ObjectLinker::linkable() const
}
}
- // can not mix -r with shared objects
+ // --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;
}
@@ -225,8 +222,8 @@ 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_Module.getInputTree().bfs_end();
- for (input=m_Module.getInputTree().bfs_begin(); input!=inEnd; ++input) {
+ 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;
@@ -239,9 +236,9 @@ bool ObjectLinker::readRelocations()
/// mergeSections - put allinput sections into output sections
bool ObjectLinker::mergeSections()
{
- ObjectBuilder builder(m_Config, m_Module);
- Module::obj_iterator obj, objEnd = m_Module.obj_end();
- for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+ ObjectBuilder builder(m_Config, *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()) {
@@ -255,7 +252,7 @@ bool ObjectLinker::mergeSections()
// skip
continue;
case LDFileFormat::Target:
- if (!m_LDBackend.mergeSection(m_Module, **sect)) {
+ if (!m_LDBackend.mergeSection(*m_pModule, **sect)) {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
@@ -265,7 +262,7 @@ bool ObjectLinker::mergeSections()
if (!(*sect)->hasEhFrame())
continue; // skip
- if (!builder.MergeSection(**sect)) {
+ if (NULL == builder.MergeSection(**sect)) {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
@@ -276,7 +273,15 @@ bool ObjectLinker::mergeSections()
if (!(*sect)->hasSectionData())
continue; // skip
- if (!builder.MergeSection(**sect)) {
+ LDSection* out_sect = builder.MergeSection(**sect);
+ if (NULL != out_sect) {
+ if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
+ error(diag::err_cannot_merge_section) << (*sect)->name()
+ << (*obj)->name();
+ return false;
+ }
+ }
+ else {
error(diag::err_cannot_merge_section) << (*sect)->name()
<< (*obj)->name();
return false;
@@ -296,12 +301,12 @@ bool ObjectLinker::mergeSections()
bool ObjectLinker::addStandardSymbols()
{
// create and add section symbols for each output section
- Module::iterator iter, iterEnd = m_Module.end();
- for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
- m_Module.getSectionSymbolSet().add(**iter, m_Module.getNamePool());
+ 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_pLinker, m_Module);
+ return m_LDBackend.initStandardSymbols(*m_pBuilder, *m_pModule);
}
/// addTargetSymbols - some targets, such as MIPS and ARM, need some
@@ -310,15 +315,24 @@ bool ObjectLinker::addStandardSymbols()
/// target symbols, return false
bool ObjectLinker::addTargetSymbols()
{
- m_LDBackend.initTargetSymbols(*m_pLinker);
+ m_LDBackend.initTargetSymbols(*m_pBuilder, *m_pModule);
+ return true;
+}
+
+/// addScriptSymbols - define symbols from the command line option or linker
+/// scripts.
+/// @return if there are some existing symbols with identical name to the
+/// script symbols, return false.
+bool ObjectLinker::addScriptSymbols()
+{
return true;
}
bool ObjectLinker::scanRelocations()
{
// apply all relocations of all inputs
- Module::obj_iterator input, inEnd = m_Module.obj_end();
- for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+ 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
@@ -332,42 +346,54 @@ bool ObjectLinker::scanRelocations()
for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
Relocation* relocation = llvm::cast<Relocation>(reloc);
// scan relocation
- if (LinkerConfig::Object != m_Config.codeGenType()) {
- m_LDBackend.scanRelocation(*relocation,
- *m_pLinker,
- m_Module,
- *(*rs)->getLink());
- }
- else {
- m_LDBackend.partialScanRelocation(*relocation,
- *m_pLinker,
- m_Module,
- *(*rs)->getLink());
- }
+ if (LinkerConfig::Object != m_Config.codeGenType())
+ m_LDBackend.scanRelocation(*relocation, *m_pBuilder, *m_pModule, **rs);
+ else
+ m_LDBackend.partialScanRelocation(*relocation, *m_pModule, **rs);
} // for all relocations
} // for all relocation section
} // 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_Module.end();
- for (sect = m_Module.begin(); sect != sEnd; ++sect) {
- m_Module.getSectionSymbolSet().finalize(**sect, m_Module.getSymbolTable());
+ Module::iterator sect, sEnd = m_pModule->end();
+ for (sect = m_pModule->begin(); sect != sEnd; ++sect) {
+ m_pModule->getSectionSymbolSet().finalize(**sect, m_pModule->getSymbolTable());
}
- m_LDBackend.preLayout(m_Module, *m_pLinker);
-
- if (LinkerConfig::Object != m_Config.codeGenType() ||
- m_Config.options().isDefineCommon())
- m_LDBackend.allocateCommonSymbols(m_Module);
+ m_LDBackend.preLayout(*m_pModule, *m_pBuilder);
/// check program interpreter - computer the name size of the runtime dyld
- if (!m_pLinker->isStaticLink() &&
+ if (!m_Config.isCodeStatic() &&
(LinkerConfig::Exec == m_Config.codeGenType() ||
m_Config.options().isPIE() ||
m_Config.options().hasDyld()))
@@ -379,7 +405,7 @@ bool ObjectLinker::prelayout()
///
/// dump all symbols and strings from FragmentLinker and build the format-dependent
/// hash table.
- m_LDBackend.sizeNamePools(m_Module, m_pLinker->isStaticLink());
+ m_LDBackend.sizeNamePools(*m_pModule, m_Config.isCodeStatic());
return true;
}
@@ -391,14 +417,14 @@ bool ObjectLinker::prelayout()
/// directly
bool ObjectLinker::layout()
{
- m_LDBackend.layout(m_Module, *m_pLinker);
+ m_LDBackend.layout(*m_pModule);
return true;
}
/// prelayout - help backend to do some modification after layout
bool ObjectLinker::postlayout()
{
- m_LDBackend.postLayout(m_Module, *m_pLinker);
+ m_LDBackend.postLayout(*m_pModule, *m_pBuilder);
return true;
}
@@ -407,7 +433,7 @@ bool ObjectLinker::postlayout()
/// symbol.
bool ObjectLinker::finalizeSymbolValue()
{
- return m_pLinker->finalizeSymbols();
+ return (m_pLinker->finalizeSymbols() && m_LDBackend.finalizeSymbols());
}
/// relocate - applying relocation entries and create relocation
@@ -423,23 +449,7 @@ bool ObjectLinker::relocation()
/// emitOutput - emit the output file.
bool ObjectLinker::emitOutput(MemoryArea& pOutput)
{
- switch(m_Config.codeGenType()) {
- case LinkerConfig::Object:
- getObjectWriter()->writeObject(m_Module, pOutput);
- return true;
- case LinkerConfig::DynObj:
- getDynObjWriter()->writeDynObj(m_Module, pOutput);
- return true;
- case LinkerConfig::Exec:
- getExecWriter()->writeExecutable(m_Module, pOutput);
- return true;
- case LinkerConfig::Binary:
- getBinaryWriter()->writeBinary(m_Module, pOutput);
- return true;
- default:
- fatal(diag::unrecognized_output_file) << m_Config.codeGenType();
- }
- return false;
+ return llvm::errc::success == getWriter()->writeObject(*m_pModule, pOutput);
}
/// postProcessing - do modification after all processes
@@ -450,7 +460,7 @@ bool ObjectLinker::postProcessing(MemoryArea& 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(*m_pLinker, pOutput);
+ m_LDBackend.postProcessing(pOutput);
return true;
}