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