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