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
12namespace llvm {
13
14namespace {
15enum {
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 the target-specific high four bits of st_other.
26 ELF_STO_Shift = 7,
27
28 // One bit.
29 ELF_IsSignature_Shift = 11,
30
31 // One bit.
32 ELF_Weakref_Shift = 12,
33
34 // One bit.
35 ELF_BindingSet_Shift = 13,
36
37 // One bit.
38 ELF_IsMemoryTagged_Shift = 14,
39};
40}
41
42void MCSymbolELF::setBinding(unsigned Binding) const {
43 setIsBindingSet();
44 unsigned Val;
45 switch (Binding) {
46 default:
47 llvm_unreachable("Unsupported Binding");
48 case ELF::STB_LOCAL:
49 Val = 0;
50 break;
51 case ELF::STB_GLOBAL:
52 Val = 1;
53 break;
54 case ELF::STB_WEAK:
55 Val = 2;
56 break;
57 case ELF::STB_GNU_UNIQUE:
58 Val = 3;
59 break;
60 }
61 uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
62 setFlags(OtherFlags | (Val << ELF_STB_Shift));
63}
64
65unsigned MCSymbolELF::getBinding() const {
66 if (isBindingSet()) {
67 uint32_t Val = (Flags >> ELF_STB_Shift) & 3;
68 switch (Val) {
69 default:
70 llvm_unreachable("Invalid value");
71 case 0:
72 return ELF::STB_LOCAL;
73 case 1:
74 return ELF::STB_GLOBAL;
75 case 2:
76 return ELF::STB_WEAK;
77 case 3:
78 return ELF::STB_GNU_UNIQUE;
79 }
80 }
81
82 if (isDefined())
83 return ELF::STB_LOCAL;
84 if (isUsedInReloc())
85 return ELF::STB_GLOBAL;
86 if (isSignature())
87 return ELF::STB_LOCAL;
88 return ELF::STB_GLOBAL;
89}
90
91void MCSymbolELF::setType(unsigned Type) const {
92 unsigned Val;
93 switch (Type) {
94 default:
95 llvm_unreachable("Unsupported Binding");
96 case ELF::STT_NOTYPE:
97 Val = 0;
98 break;
99 case ELF::STT_OBJECT:
100 Val = 1;
101 break;
102 case ELF::STT_FUNC:
103 Val = 2;
104 break;
105 case ELF::STT_SECTION:
106 Val = 3;
107 break;
108 case ELF::STT_COMMON:
109 Val = 4;
110 break;
111 case ELF::STT_TLS:
112 Val = 5;
113 break;
114 case ELF::STT_GNU_IFUNC:
115 Val = 6;
116 break;
117 }
118 uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
119 setFlags(OtherFlags | (Val << ELF_STT_Shift));
120}
121
122unsigned MCSymbolELF::getType() const {
123 uint32_t Val = (Flags >> ELF_STT_Shift) & 7;
124 switch (Val) {
125 default:
126 llvm_unreachable("Invalid value");
127 case 0:
128 return ELF::STT_NOTYPE;
129 case 1:
130 return ELF::STT_OBJECT;
131 case 2:
132 return ELF::STT_FUNC;
133 case 3:
134 return ELF::STT_SECTION;
135 case 4:
136 return ELF::STT_COMMON;
137 case 5:
138 return ELF::STT_TLS;
139 case 6:
140 return ELF::STT_GNU_IFUNC;
141 }
142}
143
144void MCSymbolELF::setVisibility(unsigned Visibility) {
145 assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
146 Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
147
148 uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
149 setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
150}
151
152unsigned MCSymbolELF::getVisibility() const {
153 unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;
154 return Visibility;
155}
156
157void MCSymbolELF::setOther(unsigned Other) {
158 assert((Other & 0xf) == 0);
159 Other >>= 4;
160 assert(Other <= 0xf);
161 uint32_t OtherFlags = getFlags() & ~(0xf << ELF_STO_Shift);
162 setFlags(OtherFlags | (Other << ELF_STO_Shift));
163}
164
165unsigned MCSymbolELF::getOther() const {
166 unsigned Other = (Flags >> ELF_STO_Shift) & 0xf;
167 return Other << 4;
168}
169
170void MCSymbolELF::setIsWeakref() const {
171 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_Weakref_Shift);
172 setFlags(OtherFlags | (1 << ELF_Weakref_Shift));
173}
174
175bool MCSymbolELF::isWeakref() const {
176 return getFlags() & (0x1 << ELF_Weakref_Shift);
177}
178
179void MCSymbolELF::setIsSignature() const {
180 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
181 setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
182}
183
184bool MCSymbolELF::isSignature() const {
185 return getFlags() & (0x1 << ELF_IsSignature_Shift);
186}
187
188void MCSymbolELF::setIsBindingSet() const {
189 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
190 setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
191}
192
193bool MCSymbolELF::isBindingSet() const {
194 return getFlags() & (0x1 << ELF_BindingSet_Shift);
195}
196
197bool MCSymbolELF::isMemtag() const {
198 return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift);
199}
200
201void MCSymbolELF::setMemtag(bool Tagged) {
202 uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift);
203 if (Tagged)
204 setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift));
205 else
206 setFlags(OtherFlags);
207}
208}
209