• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/MC/MCSymbolELF.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/MC/MCFixupKindInfo.h"
13 
14 namespace llvm {
15 
16 namespace {
17 enum {
18   // Shift value for STT_* flags. 7 possible values. 3 bits.
19   ELF_STT_Shift = 0,
20 
21   // Shift value for STB_* flags. 4 possible values, 2 bits.
22   ELF_STB_Shift = 3,
23 
24   // Shift value for STV_* flags. 4 possible values, 2 bits.
25   ELF_STV_Shift = 5,
26 
27   // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and
28   // 0xe0, so we shift right by 5 before storing.
29   ELF_STO_Shift = 7,
30 
31   // One bit.
32   ELF_IsSignature_Shift = 10,
33 
34   // One bit.
35   ELF_WeakrefUsedInReloc_Shift = 11,
36 
37   // One bit.
38   ELF_BindingSet_Shift = 12
39 };
40 }
41 
setBinding(unsigned Binding) const42 void MCSymbolELF::setBinding(unsigned Binding) const {
43   setIsBindingSet();
44   if (getType() == ELF::STT_SECTION && Binding != ELF::STB_LOCAL)
45     setType(ELF::STT_NOTYPE);
46   unsigned Val;
47   switch (Binding) {
48   default:
49     llvm_unreachable("Unsupported Binding");
50   case ELF::STB_LOCAL:
51     Val = 0;
52     break;
53   case ELF::STB_GLOBAL:
54     Val = 1;
55     break;
56   case ELF::STB_WEAK:
57     Val = 2;
58     break;
59   case ELF::STB_GNU_UNIQUE:
60     Val = 3;
61     break;
62   }
63   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
64   setFlags(OtherFlags | (Val << ELF_STB_Shift));
65 }
66 
getBinding() const67 unsigned MCSymbolELF::getBinding() const {
68   if (isBindingSet()) {
69     uint32_t Val = (getFlags() & (0x3 << ELF_STB_Shift)) >> ELF_STB_Shift;
70     switch (Val) {
71     default:
72       llvm_unreachable("Invalid value");
73     case 0:
74       return ELF::STB_LOCAL;
75     case 1:
76       return ELF::STB_GLOBAL;
77     case 2:
78       return ELF::STB_WEAK;
79     case 3:
80       return ELF::STB_GNU_UNIQUE;
81     }
82   }
83 
84   if (isDefined())
85     return ELF::STB_LOCAL;
86   if (isUsedInReloc())
87     return ELF::STB_GLOBAL;
88   if (isWeakrefUsedInReloc())
89     return ELF::STB_WEAK;
90   if (isSignature())
91     return ELF::STB_LOCAL;
92   return ELF::STB_GLOBAL;
93 }
94 
setType(unsigned Type) const95 void MCSymbolELF::setType(unsigned Type) const {
96   unsigned Val;
97   if (Type == ELF::STT_SECTION && getBinding() != ELF::STB_LOCAL)
98     return;
99   switch (Type) {
100   default:
101     llvm_unreachable("Unsupported Binding");
102   case ELF::STT_NOTYPE:
103     Val = 0;
104     break;
105   case ELF::STT_OBJECT:
106     Val = 1;
107     break;
108   case ELF::STT_FUNC:
109     Val = 2;
110     break;
111   case ELF::STT_SECTION:
112     Val = 3;
113     break;
114   case ELF::STT_COMMON:
115     Val = 4;
116     break;
117   case ELF::STT_TLS:
118     Val = 5;
119     break;
120   case ELF::STT_GNU_IFUNC:
121     Val = 6;
122     break;
123   }
124   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
125   setFlags(OtherFlags | (Val << ELF_STT_Shift));
126 }
127 
getType() const128 unsigned MCSymbolELF::getType() const {
129   uint32_t Val = (getFlags() & (0x7 << ELF_STT_Shift)) >> ELF_STT_Shift;
130   switch (Val) {
131   default:
132     llvm_unreachable("Invalid value");
133   case 0:
134     return ELF::STT_NOTYPE;
135   case 1:
136     return ELF::STT_OBJECT;
137   case 2:
138     return ELF::STT_FUNC;
139   case 3:
140     return ELF::STT_SECTION;
141   case 4:
142     return ELF::STT_COMMON;
143   case 5:
144     return ELF::STT_TLS;
145   case 6:
146     return ELF::STT_GNU_IFUNC;
147   }
148 }
149 
setVisibility(unsigned Visibility)150 void MCSymbolELF::setVisibility(unsigned Visibility) {
151   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
152          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
153 
154   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
155   setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
156 }
157 
getVisibility() const158 unsigned MCSymbolELF::getVisibility() const {
159   unsigned Visibility = (getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift;
160   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
161          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
162   return Visibility;
163 }
164 
setOther(unsigned Other)165 void MCSymbolELF::setOther(unsigned Other) {
166   assert((Other & 0x1f) == 0);
167   Other >>= 5;
168   assert(Other <= 0x7);
169   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift);
170   setFlags(OtherFlags | (Other << ELF_STO_Shift));
171 }
172 
getOther() const173 unsigned MCSymbolELF::getOther() const {
174   unsigned Other = (getFlags() & (0x7 << ELF_STO_Shift)) >> ELF_STO_Shift;
175   return Other << 5;
176 }
177 
setIsWeakrefUsedInReloc() const178 void MCSymbolELF::setIsWeakrefUsedInReloc() const {
179   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
180   setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
181 }
182 
isWeakrefUsedInReloc() const183 bool MCSymbolELF::isWeakrefUsedInReloc() const {
184   return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
185 }
186 
setIsSignature() const187 void MCSymbolELF::setIsSignature() const {
188   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
189   setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
190 }
191 
isSignature() const192 bool MCSymbolELF::isSignature() const {
193   return getFlags() & (0x1 << ELF_IsSignature_Shift);
194 }
195 
setIsBindingSet() const196 void MCSymbolELF::setIsBindingSet() const {
197   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
198   setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
199 }
200 
isBindingSet() const201 bool MCSymbolELF::isBindingSet() const {
202   return getFlags() & (0x1 << ELF_BindingSet_Shift);
203 }
204 }
205