]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/MC/MCSymbolELF.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / MC / MCSymbolELF.cpp
1 //===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/MC/MCSymbolELF.h"
10 #include "llvm/BinaryFormat/ELF.h"
11 #include "llvm/MC/MCFixupKindInfo.h"
12
13 namespace llvm {
14
15 namespace {
16 enum {
17   // Shift value for STT_* flags. 7 possible values. 3 bits.
18   ELF_STT_Shift = 0,
19
20   // Shift value for STB_* flags. 4 possible values, 2 bits.
21   ELF_STB_Shift = 3,
22
23   // Shift value for STV_* flags. 4 possible values, 2 bits.
24   ELF_STV_Shift = 5,
25
26   // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and
27   // 0xe0, so we shift right by 5 before storing.
28   ELF_STO_Shift = 7,
29
30   // One bit.
31   ELF_IsSignature_Shift = 10,
32
33   // One bit.
34   ELF_WeakrefUsedInReloc_Shift = 11,
35
36   // One bit.
37   ELF_BindingSet_Shift = 12
38 };
39 }
40
41 void MCSymbolELF::setBinding(unsigned Binding) const {
42   setIsBindingSet();
43   if (getType() == ELF::STT_SECTION && Binding != ELF::STB_LOCAL)
44     setType(ELF::STT_NOTYPE);
45   unsigned Val;
46   switch (Binding) {
47   default:
48     llvm_unreachable("Unsupported Binding");
49   case ELF::STB_LOCAL:
50     Val = 0;
51     break;
52   case ELF::STB_GLOBAL:
53     Val = 1;
54     break;
55   case ELF::STB_WEAK:
56     Val = 2;
57     break;
58   case ELF::STB_GNU_UNIQUE:
59     Val = 3;
60     break;
61   }
62   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
63   setFlags(OtherFlags | (Val << ELF_STB_Shift));
64 }
65
66 unsigned MCSymbolELF::getBinding() const {
67   if (isBindingSet()) {
68     uint32_t Val = (Flags >> ELF_STB_Shift) & 3;
69     switch (Val) {
70     default:
71       llvm_unreachable("Invalid value");
72     case 0:
73       return ELF::STB_LOCAL;
74     case 1:
75       return ELF::STB_GLOBAL;
76     case 2:
77       return ELF::STB_WEAK;
78     case 3:
79       return ELF::STB_GNU_UNIQUE;
80     }
81   }
82
83   if (isDefined())
84     return ELF::STB_LOCAL;
85   if (isUsedInReloc())
86     return ELF::STB_GLOBAL;
87   if (isWeakrefUsedInReloc())
88     return ELF::STB_WEAK;
89   if (isSignature())
90     return ELF::STB_LOCAL;
91   return ELF::STB_GLOBAL;
92 }
93
94 void MCSymbolELF::setType(unsigned Type) const {
95   unsigned Val;
96   if (Type == ELF::STT_SECTION && getBinding() != ELF::STB_LOCAL)
97     return;
98   switch (Type) {
99   default:
100     llvm_unreachable("Unsupported Binding");
101   case ELF::STT_NOTYPE:
102     Val = 0;
103     break;
104   case ELF::STT_OBJECT:
105     Val = 1;
106     break;
107   case ELF::STT_FUNC:
108     Val = 2;
109     break;
110   case ELF::STT_SECTION:
111     Val = 3;
112     break;
113   case ELF::STT_COMMON:
114     Val = 4;
115     break;
116   case ELF::STT_TLS:
117     Val = 5;
118     break;
119   case ELF::STT_GNU_IFUNC:
120     Val = 6;
121     break;
122   }
123   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
124   setFlags(OtherFlags | (Val << ELF_STT_Shift));
125 }
126
127 unsigned MCSymbolELF::getType() const {
128   uint32_t Val = (Flags >> ELF_STT_Shift) & 7;
129   switch (Val) {
130   default:
131     llvm_unreachable("Invalid value");
132   case 0:
133     return ELF::STT_NOTYPE;
134   case 1:
135     return ELF::STT_OBJECT;
136   case 2:
137     return ELF::STT_FUNC;
138   case 3:
139     return ELF::STT_SECTION;
140   case 4:
141     return ELF::STT_COMMON;
142   case 5:
143     return ELF::STT_TLS;
144   case 6:
145     return ELF::STT_GNU_IFUNC;
146   }
147 }
148
149 void MCSymbolELF::setVisibility(unsigned Visibility) {
150   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
151          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
152
153   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
154   setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
155 }
156
157 unsigned MCSymbolELF::getVisibility() const {
158   unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;
159   return Visibility;
160 }
161
162 void MCSymbolELF::setOther(unsigned Other) {
163   assert((Other & 0x1f) == 0);
164   Other >>= 5;
165   assert(Other <= 0x7);
166   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift);
167   setFlags(OtherFlags | (Other << ELF_STO_Shift));
168 }
169
170 unsigned MCSymbolELF::getOther() const {
171   unsigned Other = (Flags >> ELF_STO_Shift) & 7;
172   return Other << 5;
173 }
174
175 void MCSymbolELF::setIsWeakrefUsedInReloc() const {
176   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
177   setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
178 }
179
180 bool MCSymbolELF::isWeakrefUsedInReloc() const {
181   return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
182 }
183
184 void MCSymbolELF::setIsSignature() const {
185   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
186   setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
187 }
188
189 bool MCSymbolELF::isSignature() const {
190   return getFlags() & (0x1 << ELF_IsSignature_Shift);
191 }
192
193 void MCSymbolELF::setIsBindingSet() const {
194   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
195   setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
196 }
197
198 bool MCSymbolELF::isBindingSet() const {
199   return getFlags() & (0x1 << ELF_BindingSet_Shift);
200 }
201 }