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
28 using namespace mcld;
29
30 //===----------------------------------------------------------------------===//
31 // ELFReaderIF
32 //===----------------------------------------------------------------------===//
33 /// getSymType
getSymType(uint8_t pInfo,uint16_t pShndx) const34 ResolveInfo::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
getSymDesc(uint16_t pShndx,const Input & pInput) const49 ResolveInfo::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
79 ResolveInfo::Binding
getSymBinding(uint8_t pBinding,uint16_t pShndx,uint8_t pVis) const80 ELFReaderIF::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
101 FragmentRef*
getSymFragmentRef(Input & pInput,uint16_t pShndx,uint32_t pOffset) const102 ELFReaderIF::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
132 ResolveInfo::Visibility
getSymVisibility(uint8_t pVis) const133 ELFReaderIF::getSymVisibility(uint8_t pVis) const
134 {
135 return static_cast<ResolveInfo::Visibility>(pVis);
136 }
137
138 /// getSymValue - get the section offset of the symbol.
getSymValue(uint64_t pValue,uint16_t pShndx,const Input & pInput) const139 uint64_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