1//===- ELFObjectReader.cpp ------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <string>
11#include <cassert>
12
13#include <llvm/Support/ELF.h>
14#include <llvm/ADT/Twine.h>
15
16#include <mcld/MC/MCLDInput.h>
17#include <mcld/MC/MCLinker.h>
18#include <mcld/LD/RegionFragment.h>
19#include <mcld/LD/ELFReader.h>
20#include <mcld/LD/ELFObjectReader.h>
21#include <mcld/Target/GNULDBackend.h>
22#include <mcld/Support/MsgHandling.h>
23
24using namespace mcld;
25
26//==========================
27// ELFObjectReader
28/// constructor
29ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, MCLinker& pLinker)
30  : ObjectReader(),
31    m_pELFReader(0),
32    m_Linker(pLinker)
33{
34  if (32 == pBackend.bitclass() && pBackend.isLittleEndian()) {
35    m_pELFReader = new ELFReader<32, true>(pBackend);
36  }
37}
38
39/// destructor
40ELFObjectReader::~ELFObjectReader()
41{
42  delete m_pELFReader;
43}
44
45/// isMyFormat
46bool ELFObjectReader::isMyFormat(Input &pInput) const
47{
48  assert(pInput.hasMemArea());
49
50  // Don't warning about the frequently requests.
51  // MemoryArea has a list of cache to handle this.
52  size_t hdr_size = m_pELFReader->getELFHeaderSize();
53  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
54                                                     hdr_size);
55
56  uint8_t* ELF_hdr = region->start();
57  bool result = true;
58  if (!m_pELFReader->isELF(ELF_hdr))
59    result = false;
60  else if (!m_pELFReader->isMyEndian(ELF_hdr))
61    result = false;
62  else if (!m_pELFReader->isMyMachine(ELF_hdr))
63    result = false;
64  else if (MCLDFile::Object != m_pELFReader->fileType(ELF_hdr))
65    result = false;
66  pInput.memArea()->release(region);
67  return result;
68}
69
70/// readObject - read section header and create LDSections.
71bool ELFObjectReader::readObject(Input& pInput)
72{
73  assert(pInput.hasMemArea());
74
75  size_t hdr_size = m_pELFReader->getELFHeaderSize();
76  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
77                                                     hdr_size);
78  uint8_t* ELF_hdr = region->start();
79  bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
80  pInput.memArea()->release(region);
81  return result;
82}
83
84/// readSections - read all regular sections.
85bool ELFObjectReader::readSections(Input& pInput)
86{
87  // handle sections
88  LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
89  for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
90    // ignore the section if the LDSection* in input context is NULL
91    if (NULL == *section)
92        continue;
93
94    switch((*section)->kind()) {
95      /** group sections **/
96      case LDFileFormat::Group: {
97        assert(NULL != (*section)->getLink());
98        ResolveInfo* signature =
99              m_pELFReader->readSymbol(pInput,
100                                       *(*section)->getLink(),
101                                       m_Linker.getLDInfo(),
102                                       (*section)->getInfo());
103
104        bool exist = false;
105        if (0 == std::strlen(signature->name()) &&
106            ResolveInfo::Section == signature->type()) {
107          // if the signature is a section symbol in input object, we use the
108          // section name as group signature.
109          signatures().insert((*section)->name(), exist);
110        } else {
111          signatures().insert(signature->name(), exist);
112        }
113
114        if (exist) {
115          // if this is not the first time we see this group signature, then
116          // ignore all the members in this group (set NULL)
117          MemoryRegion* region = pInput.memArea()->request(
118               pInput.fileOffset() + (*section)->offset(), (*section)->size());
119          llvm::ELF::Elf32_Word* value =
120                     reinterpret_cast<llvm::ELF::Elf32_Word*>(region->start());
121
122          size_t size = region->size() / sizeof(llvm::ELF::Elf32_Word);
123          if (llvm::ELF::GRP_COMDAT == *value) {
124            for (size_t index = 1; index < size; ++index)
125              pInput.context()->getSectionTable()[value[index]] = NULL;
126          }
127          pInput.memArea()->release(region);
128        }
129        break;
130      }
131      /** relocation sections **/
132      case LDFileFormat::Relocation: {
133        assert(NULL != (*section)->getLink());
134        size_t link_index = (*section)->getLink()->index();
135        if (NULL == pInput.context()->getSectionTable()[link_index]) {
136          // Relocation sections of group members should also be part of the
137          // group. Thus, if the associated member sections are ignored, the
138          // related relocations should be also ignored.
139          *section = NULL;
140        }
141        break;
142      }
143      /** normal sections **/
144      // FIXME: support Version Kinds
145      case LDFileFormat::Version:
146      /** Fall through **/
147      case LDFileFormat::Regular:
148      case LDFileFormat::Note:
149      case LDFileFormat::Debug:
150      case LDFileFormat::MetaData: {
151        if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
152          fatal(diag::err_cannot_read_section) << (*section)->name();
153        break;
154      }
155      case LDFileFormat::EhFrame: {
156        if (!m_pELFReader->readEhFrame(pInput, m_Linker, **section))
157          fatal(diag::err_cannot_read_section) <<(*section)->name();
158        break;
159      }
160      case LDFileFormat::GCCExceptTable: {
161        //if (!m_pELFReader->readExceptionSection(pInput, m_Linker, **section))
162        if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
163          fatal(diag::err_cannot_read_section) << (*section)->name();
164        break;
165      }
166      /** target dependent sections **/
167      case LDFileFormat::Target: {
168        if (!m_pELFReader->readTargetSection(pInput, m_Linker, **section))
169          fatal(diag::err_cannot_read_target_section) << (*section)->name();
170        break;
171      }
172      /** BSS sections **/
173      case LDFileFormat::BSS: {
174        LDSection& output_bss = m_Linker.getOrCreateOutputSectHdr(
175                                               (*section)->name(),
176                                               LDFileFormat::BSS,
177                                               llvm::ELF::SHT_NOBITS,
178                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE);
179
180        SectionData& sect_data = m_Linker.getOrCreateSectData(**section);
181                                            /*  value, valsize, size*/
182        FillFragment* frag = new FillFragment(0x0,   1,       (*section)->size());
183
184        uint64_t size = m_Linker.getLayout().appendFragment(*frag,
185                                                            sect_data,
186                                                            (*section)->align());
187        output_bss.setSize(output_bss.size() + size);
188        break;
189      }
190      // ignore
191      case LDFileFormat::Null:
192      case LDFileFormat::NamePool:
193        continue;
194      // warning
195      case LDFileFormat::EhFrameHdr:
196      default: {
197        warning(diag::warn_illegal_input_section) << (*section)->name()
198                                                  << pInput.name()
199                                                  << pInput.path();
200        break;
201      }
202    }
203  } // end of for all sections
204
205  return true;
206}
207
208/// readSymbols - read symbols into MCLinker from the input relocatable object.
209bool ELFObjectReader::readSymbols(Input& pInput)
210{
211  assert(pInput.hasMemArea());
212
213  LDSection* symtab_shdr = pInput.context()->getSection(".symtab");
214  if (NULL == symtab_shdr) {
215    note(diag::note_has_no_symtab) << pInput.name()
216                                   << pInput.path()
217                                   << ".symtab";
218    return true;
219  }
220
221  LDSection* strtab_shdr = symtab_shdr->getLink();
222  if (NULL == strtab_shdr) {
223    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
224                                          << pInput.path()
225                                          << ".symtab";
226    return false;
227  }
228
229  MemoryRegion* symtab_region = pInput.memArea()->request(
230             pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
231  MemoryRegion* strtab_region = pInput.memArea()->request(
232             pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
233  char* strtab = reinterpret_cast<char*>(strtab_region->start());
234  bool result = m_pELFReader->readSymbols(pInput,
235                                          m_Linker,
236                                          *symtab_region,
237                                          strtab);
238  pInput.memArea()->release(symtab_region);
239  pInput.memArea()->release(strtab_region);
240  return result;
241}
242
243bool ELFObjectReader::readRelocations(Input& pInput)
244{
245  assert(pInput.hasMemArea());
246
247  MemoryArea* mem = pInput.memArea();
248  LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
249  for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
250    // ignore the section if the LDSection* in input context is NULL
251    if (NULL == *section)
252        continue;
253
254    if ((*section)->type() == llvm::ELF::SHT_RELA &&
255        (*section)->kind() == LDFileFormat::Relocation) {
256      MemoryRegion* region = mem->request(
257               pInput.fileOffset() + (*section)->offset(), (*section)->size());
258      bool result = m_pELFReader->readRela(pInput, m_Linker, **section,
259                                           *region);
260      mem->release(region);
261      if (!result)
262        return false;
263    }
264    else if ((*section)->type() == llvm::ELF::SHT_REL &&
265             (*section)->kind() == LDFileFormat::Relocation) {
266      MemoryRegion* region = mem->request(
267               pInput.fileOffset() + (*section)->offset(), (*section)->size());
268      bool result = m_pELFReader->readRel(pInput, m_Linker, **section, *region);
269      mem->release(region);
270      if (!result)
271        return false;
272    }
273  }
274  return true;
275}
276
277