1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- Linker.cpp ---------------------------------------------------------===//
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//                     The MCLinker Project
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details.
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "alone/Linker.h"
11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "alone/Support/LinkerConfig.h"
1267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao#include "alone/Support/Log.h"
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/ELF.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Module.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/IRBuilder.h>
18d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/MC/MCLDInput.h>
19d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/Linker.h>
20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/LDSection.h>
21affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/LDContext.h>
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/Path.h>
23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
24affc150dc44fab1911775a49636d0ce85333b634Zonr Changusing namespace alone;
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
27affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  static const char* ErrorString[] = {
28affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kSuccess */
29affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Successfully compiled.",
30affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kDoubleConfig */
31affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Configure Linker twice.",
32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kDelegateLDInfo */
33affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot get linker information",
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    /* kFindNameSpec */
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    "Cannot find -lnamespec",
36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kOpenObjectFile */
37affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot open object file",
38affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kNotConfig */
39affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Linker::config() is not called",
40affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kNotSetUpOutput */
41affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Linker::setOutput() is not called before add input files",
42affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kOpenOutput */
43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot open output file",
44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kReadSections */
45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot read sections",
46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kReadSymbols */
47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot read symbols",
48affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kAddAdditionalSymbols */
49affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "Cannot add standard and target symbols",
50affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    /* kMaxErrorCode */
51affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    "(Unknown error code)"
52affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  };
53affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
54affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pErrCode > kMaxErrorCode) {
55affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pErrCode = kMaxErrorCode;
56affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
57affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
58affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ErrorString[ static_cast<size_t>(pErrCode) ];
59affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
60affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
62affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Linker
63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
64affc150dc44fab1911775a49636d0ce85333b634Zonr ChangLinker::Linker()
65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
66d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    mOutputHandler(-1) {
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
68affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
69affc150dc44fab1911775a49636d0ce85333b634Zonr ChangLinker::Linker(const LinkerConfig& pConfig)
70d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
71d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    mOutputHandler(-1) {
72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
73affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const std::string &triple = pConfig.getTriple();
74affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  enum ErrorCode err = config(pConfig);
76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (kSuccess != err) {
77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
78affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return;
79affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
80affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return;
82affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
83affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
8467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoLinker::~Linker() {
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete mModule;
86d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  delete mLinker;
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete mBuilder;
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
9067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  mLDConfig = pConfig.getLDConfig();
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (mLDConfig == NULL) {
93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return kDelegateLDInfo;
9467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  }
95affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return kSuccess;
96affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
9867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (mLDConfig != NULL) {
100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return kDoubleConfig;
10167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  }
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
103affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  extractFiles(pConfig);
104affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  mModule = new mcld::Module(mLDConfig->options().soname(),
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()));
107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
108d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
110d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mLinker = new mcld::Linker();
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  mLinker->emulate(const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()),
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   const_cast<mcld::LinkerConfig&>(*mLDConfig));
114affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return kSuccess;
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
11867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
119d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::Input* input = mBuilder->ReadInput(pNameSpec);
120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (NULL == input)
12167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return kFindNameSpec;
122d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return kSuccess;
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// addObject - Add a object file by the filename.
12667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
127d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (NULL == input)
129d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return kOpenObjectFile;
130d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return kSuccess;
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// addObject - Add a piece of memory. The memory is of ELF format.
13467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
135d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
136d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (NULL == input)
137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return kOpenMemory;
138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return kSuccess;
139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
14167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
143d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                llvm::ELF::SHT_PROGBITS,
145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                0x1);
147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
148d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
149d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mBuilder->AppendFragment(*frag, *data);
150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return kSuccess;
151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mOutputPath = pPath;
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return kSuccess;
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
159d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mOutputHandler = pFileHandler;
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return kSuccess;
16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
162affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoenum Linker::ErrorCode Linker::link() {
164d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  mLinker->link(*mModule, *mBuilder);
165d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (!mOutputPath.empty()) {
166d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    mLinker->emit(mOutputPath);
167d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return kSuccess;
16867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  }
16967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
170d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (-1 != mOutputHandler) {
171d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    mLinker->emit(mOutputHandler);
172d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return kSuccess;
17367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  }
174d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return kNotSetUpOutput;
175affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
177