ELFReaderIf.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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    return ResolveInfo::Global;
91  case llvm::ELF::STB_WEAK:
92    return ResolveInfo::Weak;
93  }
94
95  if (pShndx == llvm::ELF::SHN_ABS)
96    return ResolveInfo::Absolute;
97
98  return ResolveInfo::NoneBinding;
99}
100
101/// getSymFragmentRef
102FragmentRef*
103ELFReaderIF::getSymFragmentRef(Input& pInput,
104                               uint16_t pShndx,
105                               uint32_t pOffset) const
106{
107
108  if (Input::DynObj == pInput.type())
109    return FragmentRef::Null();
110
111  if (pShndx == llvm::ELF::SHN_UNDEF)
112    return FragmentRef::Null();
113
114  if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
115    return FragmentRef::Null();
116
117  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
118
119  if (NULL == sect_hdr)
120    unreachable(diag::unreachable_invalid_section_idx) << pShndx
121                                                       << pInput.path().native();
122
123  if (LDFileFormat::Ignore == sect_hdr->kind())
124    return FragmentRef::Null();
125
126  if (LDFileFormat::Group == sect_hdr->kind())
127    return FragmentRef::Null();
128
129  return FragmentRef::Create(*sect_hdr, pOffset);
130}
131
132/// getSymVisibility
133ResolveInfo::Visibility
134ELFReaderIF::getSymVisibility(uint8_t pVis) const
135{
136  return static_cast<ResolveInfo::Visibility>(pVis);
137}
138
139/// getSymValue - get the section offset of the symbol.
140uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
141                                  uint16_t pShndx,
142                                  const Input& pInput) const
143{
144  if (Input::Object == pInput.type()) {
145    // In relocatable files, st_value holds alignment constraints for a symbol
146    // whose section index is SHN_COMMON
147    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
148      return pValue;
149    }
150
151    // In relocatable files, st_value holds a section offset for a defined symbol.
152    // TODO:
153    // if --just-symbols option are enabled, convert the value from section offset
154    // to virtual address by adding input section's virtual address.
155    // The section's virtual address in relocatable files is normally zero, but
156    // people can use link script to change it.
157    return pValue;
158  }
159
160  // In executable and shared object files, st_value holds a virtual address.
161  // the virtual address is useless during linking.
162  return 0x0;
163}
164
165