1//===- ELFReader.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#include <mcld/LD/ELFReaderIf.h>
10
11#include <mcld/IRBuilder.h>
12#include <mcld/Fragment/FillFragment.h>
13#include <mcld/LD/EhFrame.h>
14#include <mcld/LD/SectionData.h>
15#include <mcld/Target/GNULDBackend.h>
16//#include <mcld/Support/MemoryArea.h>
17//#include <mcld/Support/MemoryRegion.h>
18//#include <mcld/Support/MsgHandling.h>
19//#include <mcld/Object/ObjectBuilder.h>
20
21#include <cstring>
22
23#include <llvm/ADT/StringRef.h>
24#include <llvm/ADT/Twine.h>
25#include <llvm/Support/ELF.h>
26#include <llvm/Support/Host.h>
27
28using namespace mcld;
29
30//===----------------------------------------------------------------------===//
31// ELFReaderIF
32//===----------------------------------------------------------------------===//
33/// getSymType
34ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
35{
36  ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
37  if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
38    // In Mips, __gp_disp is a special section symbol. Its name comes from
39    // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
40    // symbol. So here is a tricky to identify __gp_disp and convert it to
41    // Object symbol.
42    return ResolveInfo::Object;
43  }
44
45  return result;
46}
47
48/// getSymDesc
49ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
50{
51  if (pShndx == llvm::ELF::SHN_UNDEF)
52    return ResolveInfo::Undefined;
53
54  if (pShndx < llvm::ELF::SHN_LORESERVE) {
55    // an ELF symbol defined in a section which we are not including
56    // must be treated as an Undefined.
57    // @ref Google gold linker: symtab.cc: 1086
58    if (NULL == pInput.context()->getSection(pShndx) ||
59        LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
60      return ResolveInfo::Undefined;
61    return ResolveInfo::Define;
62  }
63
64  if (pShndx == llvm::ELF::SHN_ABS)
65    return ResolveInfo::Define;
66
67  if (pShndx == llvm::ELF::SHN_COMMON)
68    return ResolveInfo::Common;
69
70  if (pShndx >= llvm::ELF::SHN_LOPROC &&
71      pShndx <= llvm::ELF::SHN_HIPROC)
72    return target().getSymDesc(pShndx);
73
74  // FIXME: ELF weak alias should be ResolveInfo::Indirect
75  return ResolveInfo::NoneDesc;
76}
77
78/// getSymBinding
79ResolveInfo::Binding
80ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
81{
82
83  // TODO:
84  // if --just-symbols option is enabled, the symbol must covert to Absolute
85
86  switch(pBinding) {
87  case llvm::ELF::STB_LOCAL:
88    return ResolveInfo::Local;
89  case llvm::ELF::STB_GLOBAL:
90    if (pShndx == llvm::ELF::SHN_ABS)
91      return ResolveInfo::Absolute;
92    return ResolveInfo::Global;
93  case llvm::ELF::STB_WEAK:
94    return ResolveInfo::Weak;
95  }
96
97  return ResolveInfo::NoneBinding;
98}
99
100/// getSymFragmentRef
101FragmentRef*
102ELFReaderIF::getSymFragmentRef(Input& pInput,
103                               uint16_t pShndx,
104                               uint32_t pOffset) const
105{
106
107  if (Input::DynObj == pInput.type())
108    return FragmentRef::Null();
109
110  if (pShndx == llvm::ELF::SHN_UNDEF)
111    return FragmentRef::Null();
112
113  if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
114    return FragmentRef::Null();
115
116  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
117
118  if (NULL == sect_hdr)
119    unreachable(diag::unreachable_invalid_section_idx) << pShndx
120                                                       << pInput.path().native();
121
122  if (LDFileFormat::Ignore == sect_hdr->kind())
123    return FragmentRef::Null();
124
125  if (LDFileFormat::Group == sect_hdr->kind())
126    return FragmentRef::Null();
127
128  return FragmentRef::Create(*sect_hdr, pOffset);
129}
130
131/// getSymVisibility
132ResolveInfo::Visibility
133ELFReaderIF::getSymVisibility(uint8_t pVis) const
134{
135  return static_cast<ResolveInfo::Visibility>(pVis);
136}
137
138/// getSymValue - get the section offset of the symbol.
139uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
140                                  uint16_t pShndx,
141                                  const Input& pInput) const
142{
143  if (Input::Object == pInput.type()) {
144    // In relocatable files, st_value holds alignment constraints for a symbol
145    // whose section index is SHN_COMMON
146    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
147      return pValue;
148    }
149
150    // In relocatable files, st_value holds a section offset for a defined symbol.
151    // TODO:
152    // if --just-symbols option are enabled, convert the value from section offset
153    // to virtual address by adding input section's virtual address.
154    // The section's virtual address in relocatable files is normally zero, but
155    // people can use link script to change it.
156    return pValue;
157  }
158
159  // In executable and shared object files, st_value holds a virtual address.
160  // the virtual address is needed for alias identification.
161  return pValue;
162}
163
164