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