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
10#include <llvm/Support/ELF.h>
11#include <llvm/ADT/StringRef.h>
12#include <llvm/ADT/Twine.h>
13#include <llvm/Support/Host.h>
14#include <mcld/MC/MCLinker.h>
15#include <mcld/Support/MemoryArea.h>
16#include <mcld/Support/MemoryRegion.h>
17#include <mcld/LD/ELFReader.h>
18#include <mcld/Target/GNULDBackend.h>
19#include <cstring>
20
21using namespace mcld;
22
23//===----------------------------------------------------------------------===//
24// ELFReaderIF
25/// getLDSectionKind
26LDFileFormat::Kind
27ELFReaderIF::getLDSectionKind(uint32_t pType, const char* pName) const
28{
29  // name rules
30  llvm::StringRef name(pName);
31  if (llvm::StringRef::npos != name.find(".debug"))
32    return LDFileFormat::Debug;
33  if (name.startswith(".comment"))
34    return LDFileFormat::MetaData;
35  if (name.startswith(".interp") || name.startswith(".dynamic"))
36    return LDFileFormat::Note;
37  if (name.startswith(".eh_frame") ||
38      name.startswith(".eh_frame_hdr") ||
39      name.startswith(".gcc_except_table"))
40    return LDFileFormat::Exception;
41
42  // type rules
43  switch(pType) {
44  case llvm::ELF::SHT_NULL:
45    return LDFileFormat::Null;
46  case llvm::ELF::SHT_INIT_ARRAY:
47  case llvm::ELF::SHT_FINI_ARRAY:
48  case llvm::ELF::SHT_PREINIT_ARRAY:
49  case llvm::ELF::SHT_PROGBITS:
50    return LDFileFormat::Regular;
51  case llvm::ELF::SHT_SYMTAB:
52  case llvm::ELF::SHT_DYNSYM:
53  case llvm::ELF::SHT_STRTAB:
54    return LDFileFormat::NamePool;
55  case llvm::ELF::SHT_RELA:
56  case llvm::ELF::SHT_REL:
57    return LDFileFormat::Relocation;
58  case llvm::ELF::SHT_NOBITS:
59    return LDFileFormat::BSS;
60  case llvm::ELF::SHT_DYNAMIC:
61  case llvm::ELF::SHT_NOTE:
62    return LDFileFormat::Note;
63  case llvm::ELF::SHT_HASH:
64  case llvm::ELF::SHT_SHLIB:
65    return LDFileFormat::MetaData;
66  case llvm::ELF::SHT_GROUP:
67    return LDFileFormat::Group;
68  case llvm::ELF::SHT_GNU_versym:
69  case llvm::ELF::SHT_GNU_verdef:
70  case llvm::ELF::SHT_GNU_verneed:
71    return LDFileFormat::Version;
72  default:
73    if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
74        (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
75        (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
76      return LDFileFormat::Target;
77    llvm::report_fatal_error(llvm::Twine("unsupported ELF section type: ") +
78                             llvm::Twine(pType) + llvm::Twine(".\n"));
79  }
80  return LDFileFormat::MetaData;
81}
82
83/// getSymDesc
84ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
85{
86  if (pShndx == llvm::ELF::SHN_UNDEF)
87    return ResolveInfo::Undefined;
88
89  if (pShndx < llvm::ELF::SHN_LORESERVE) {
90    // an ELF symbol defined in a section which we are not including
91    // must be treated as an Undefined.
92    // @ref Google gold linker: symtab.cc: 1086
93    if (NULL == pInput.context()->getSection(pShndx))
94      return ResolveInfo::Undefined;
95    return ResolveInfo::Define;
96  }
97
98  if (pShndx == llvm::ELF::SHN_ABS)
99    return ResolveInfo::Define;
100
101  if (pShndx == llvm::ELF::SHN_COMMON)
102    return ResolveInfo::Common;
103
104  // FIXME: ELF weak alias should be ResolveInfo::Indirect
105  return ResolveInfo::NoneDesc;
106}
107
108/// getSymBinding
109ResolveInfo::Binding
110ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
111{
112
113  // TODO:
114  // if --just-symbols option is enabled, the symbol must covert to Absolute
115
116  switch(pBinding) {
117  case llvm::ELF::STB_LOCAL:
118    return ResolveInfo::Local;
119  case llvm::ELF::STB_GLOBAL:
120    return ResolveInfo::Global;
121  case llvm::ELF::STB_WEAK:
122    return ResolveInfo::Weak;
123  }
124
125  if (pShndx == llvm::ELF::SHN_ABS)
126    return ResolveInfo::Absolute;
127
128  return ResolveInfo::NoneBinding;
129}
130
131/// getSymFragmentRef
132MCFragmentRef*
133ELFReaderIF::getSymFragmentRef(Input& pInput,
134                               MCLinker& pLinker,
135                               uint16_t pShndx,
136                               uint32_t pOffset) const
137{
138
139  if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE)
140    return NULL;
141
142  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
143
144  if (NULL == sect_hdr) {
145    llvm::report_fatal_error(llvm::Twine("section[") +
146                             llvm::Twine(pShndx) +
147                             llvm::Twine("] is invalid in file `") +
148                             pInput.path().native() +
149                             llvm::Twine("'.\n"));
150  }
151
152  MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
153  return result;
154}
155
156/// getSymVisibility
157ResolveInfo::Visibility
158ELFReaderIF::getSymVisibility(uint8_t pVis) const
159{
160  return static_cast<ResolveInfo::Visibility>(pVis);
161}
162
163/// getSymValue - get the section offset of the symbol.
164uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
165                                  uint16_t pShndx,
166                                  const Input& pInput) const
167{
168  if (Input::Object == pInput.type()) {
169    // In relocatable files, st_value holds alignment constraints for a symbol
170    // whose section index is SHN_COMMON
171    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
172      return pValue;
173    }
174
175    // In relocatable files, st_value holds a section offset for a defined symbol.
176    // TODO:
177    // if --just-symbols option are enabled, convert the value from section offset
178    // to virtual address by adding input section's virtual address.
179    // The section's virtual address in relocatable files is normally zero, but
180    // people can use link script to change it.
181    return pValue;
182  }
183
184  // In executable and shared object files, st_value holds a virtual address.
185  // the virtual address is useless during linking.
186  return 0x0;
187}
188
189