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_Weakref_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 (isSignature()) |
88 | return ELF::STB_LOCAL; |
89 | return ELF::STB_GLOBAL; |
90 | } |
91 | |
92 | void MCSymbolELF::setType(unsigned Type) const { |
93 | unsigned Val; |
94 | switch (Type) { |
95 | default: |
96 | llvm_unreachable("Unsupported Binding" ); |
97 | case ELF::STT_NOTYPE: |
98 | Val = 0; |
99 | break; |
100 | case ELF::STT_OBJECT: |
101 | Val = 1; |
102 | break; |
103 | case ELF::STT_FUNC: |
104 | Val = 2; |
105 | break; |
106 | case ELF::STT_SECTION: |
107 | Val = 3; |
108 | break; |
109 | case ELF::STT_COMMON: |
110 | Val = 4; |
111 | break; |
112 | case ELF::STT_TLS: |
113 | Val = 5; |
114 | break; |
115 | case ELF::STT_GNU_IFUNC: |
116 | Val = 6; |
117 | break; |
118 | } |
119 | uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift); |
120 | setFlags(OtherFlags | (Val << ELF_STT_Shift)); |
121 | } |
122 | |
123 | unsigned MCSymbolELF::getType() const { |
124 | uint32_t Val = (Flags >> ELF_STT_Shift) & 7; |
125 | switch (Val) { |
126 | default: |
127 | llvm_unreachable("Invalid value" ); |
128 | case 0: |
129 | return ELF::STT_NOTYPE; |
130 | case 1: |
131 | return ELF::STT_OBJECT; |
132 | case 2: |
133 | return ELF::STT_FUNC; |
134 | case 3: |
135 | return ELF::STT_SECTION; |
136 | case 4: |
137 | return ELF::STT_COMMON; |
138 | case 5: |
139 | return ELF::STT_TLS; |
140 | case 6: |
141 | return ELF::STT_GNU_IFUNC; |
142 | } |
143 | } |
144 | |
145 | void MCSymbolELF::setVisibility(unsigned Visibility) { |
146 | assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || |
147 | Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); |
148 | |
149 | uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift); |
150 | setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); |
151 | } |
152 | |
153 | unsigned MCSymbolELF::getVisibility() const { |
154 | unsigned Visibility = (Flags >> ELF_STV_Shift) & 3; |
155 | return Visibility; |
156 | } |
157 | |
158 | void MCSymbolELF::setOther(unsigned Other) { |
159 | assert((Other & 0x1f) == 0); |
160 | Other >>= 5; |
161 | assert(Other <= 0x7); |
162 | uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift); |
163 | setFlags(OtherFlags | (Other << ELF_STO_Shift)); |
164 | } |
165 | |
166 | unsigned MCSymbolELF::getOther() const { |
167 | unsigned Other = (Flags >> ELF_STO_Shift) & 7; |
168 | return Other << 5; |
169 | } |
170 | |
171 | void MCSymbolELF::setIsWeakref() const { |
172 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_Weakref_Shift); |
173 | setFlags(OtherFlags | (1 << ELF_Weakref_Shift)); |
174 | } |
175 | |
176 | bool MCSymbolELF::isWeakref() const { |
177 | return getFlags() & (0x1 << ELF_Weakref_Shift); |
178 | } |
179 | |
180 | void MCSymbolELF::setIsSignature() const { |
181 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift); |
182 | setFlags(OtherFlags | (1 << ELF_IsSignature_Shift)); |
183 | } |
184 | |
185 | bool MCSymbolELF::isSignature() const { |
186 | return getFlags() & (0x1 << ELF_IsSignature_Shift); |
187 | } |
188 | |
189 | void MCSymbolELF::setIsBindingSet() const { |
190 | uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift); |
191 | setFlags(OtherFlags | (1 << ELF_BindingSet_Shift)); |
192 | } |
193 | |
194 | bool MCSymbolELF::isBindingSet() const { |
195 | return getFlags() & (0x1 << ELF_BindingSet_Shift); |
196 | } |
197 | |
198 | bool MCSymbolELF::isMemtag() const { |
199 | return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift); |
200 | } |
201 | |
202 | void MCSymbolELF::setMemtag(bool Tagged) { |
203 | uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift); |
204 | if (Tagged) |
205 | setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift)); |
206 | else |
207 | setFlags(OtherFlags); |
208 | } |
209 | } |
210 | |