• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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