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 | |
12 | namespace llvm { |
13 | |
14 | namespace { |
15 | enum { |
16 | // Shift value for STT_* flags. 7 possible values. 3 bits. |
17 | ELF_STT_Shift = 0, |
18 | |
19 | // Shift value for STB_* flags. 4 possible values, 2 bits. |
20 | ELF_STB_Shift = 3, |
21 | |
22 | // Shift value for STV_* flags. 4 possible values, 2 bits. |
23 | ELF_STV_Shift = 5, |
24 | |
25 | // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and |
26 | // 0xe0, so we shift right by 5 before storing. |
27 | ELF_STO_Shift = 7, |
28 | |
29 | // One bit. |
30 | ELF_IsSignature_Shift = 10, |
31 | |
32 | // One bit. |
33 | ELF_WeakrefUsedInReloc_Shift = 11, |
34 | |
35 | // One bit. |
36 | ELF_BindingSet_Shift = 12, |
37 | |
38 | // One bit. |
39 | ELF_IsMemoryTagged_Shift = 13, |
40 | }; |
41 | } |
42 | |
43 | void MCSymbolELF::setBinding(unsigned Binding) const { |
44 | setIsBindingSet(); |
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 | switch (Type) { |
97 | default: |
98 | llvm_unreachable("Unsupported Binding" ); |
99 | case ELF::STT_NOTYPE: |
100 | Val = 0; |
101 | break; |
102 | case ELF::STT_OBJECT: |
103 | Val = 1; |
104 | break; |
105 | case ELF::STT_FUNC: |
106 | Val = 2; |
107 | break; |
108 | case ELF::STT_SECTION: |
109 | Val = 3; |
110 | break; |
111 | case ELF::STT_COMMON: |
112 | Val = 4; |
113 | break; |
114 | case ELF::STT_TLS: |
115 | Val = 5; |
116 | break; |
117 | case ELF::STT_GNU_IFUNC: |
118 | Val = 6; |
119 | break; |
120 | } |
121 | uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift); |
122 | setFlags(OtherFlags | (Val << ELF_STT_Shift)); |
123 | } |
124 | |
125 | unsigned MCSymbolELF::getType() const { |
126 | uint32_t Val = (Flags >> ELF_STT_Shift) & 7; |
127 | switch (Val) { |
128 | default: |
129 | llvm_unreachable("Invalid value" ); |
130 | case 0: |
131 | return ELF::STT_NOTYPE; |
132 | case 1: |
133 | return ELF::STT_OBJECT; |
134 | case 2: |
135 | return ELF::STT_FUNC; |
136 | case 3: |
137 | return ELF::STT_SECTION; |
138 | case 4: |
139 | return ELF::STT_COMMON; |
140 | case 5: |
141 | return ELF::STT_TLS; |
142 | case 6: |
143 | return ELF::STT_GNU_IFUNC; |
144 | } |
145 | } |
146 | |
147 | void MCSymbolELF::setVisibility(unsigned Visibility) { |
148 | assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || |
149 | Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); |
150 | |
151 | uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift); |
152 | setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); |
153 | } |
154 | |
155 | unsigned MCSymbolELF::getVisibility() const { |
156 | unsigned Visibility = (Flags >> ELF_STV_Shift) & 3; |
157 | return Visibility; |
158 | } |
159 | |
160 | void MCSymbolELF::setOther(unsigned Other) { |
161 | assert((Other & 0x1f) == 0); |
162 | Other >>= 5; |
163 | assert(Other <= 0x7); |
164 | uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift); |
165 | setFlags(OtherFlags | (Other << ELF_STO_Shift)); |
166 | } |
167 | |
168 | unsigned MCSymbolELF::getOther() const { |
169 | unsigned Other = (Flags >> ELF_STO_Shift) & 7; |
170 | return Other << 5; |
171 | } |
172 | |
173 | void MCSymbolELF::setIsWeakrefUsedInReloc() const { |
174 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift); |
175 | setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift)); |
176 | } |
177 | |
178 | bool MCSymbolELF::isWeakrefUsedInReloc() const { |
179 | return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift); |
180 | } |
181 | |
182 | void MCSymbolELF::setIsSignature() const { |
183 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift); |
184 | setFlags(OtherFlags | (1 << ELF_IsSignature_Shift)); |
185 | } |
186 | |
187 | bool MCSymbolELF::isSignature() const { |
188 | return getFlags() & (0x1 << ELF_IsSignature_Shift); |
189 | } |
190 | |
191 | void MCSymbolELF::setIsBindingSet() const { |
192 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift); |
193 | setFlags(OtherFlags | (1 << ELF_BindingSet_Shift)); |
194 | } |
195 | |
196 | bool MCSymbolELF::isBindingSet() const { |
197 | return getFlags() & (0x1 << ELF_BindingSet_Shift); |
198 | } |
199 | |
200 | bool MCSymbolELF::isMemtag() const { |
201 | return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift); |
202 | } |
203 | |
204 | void MCSymbolELF::setMemtag(bool Tagged) { |
205 | uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift); |
206 | if (Tagged) |
207 | setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift)); |
208 | else |
209 | setFlags(OtherFlags); |
210 | } |
211 | } |
212 | |