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 } 39 40 void MCSymbolELF::setBinding(unsigned Binding) const { 41 setIsBindingSet(); 42 unsigned Val; 43 switch (Binding) { 44 default: 45 llvm_unreachable("Unsupported Binding"); 46 case ELF::STB_LOCAL: 47 Val = 0; 48 break; 49 case ELF::STB_GLOBAL: 50 Val = 1; 51 break; 52 case ELF::STB_WEAK: 53 Val = 2; 54 break; 55 case ELF::STB_GNU_UNIQUE: 56 Val = 3; 57 break; 58 } 59 uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift); 60 setFlags(OtherFlags | (Val << ELF_STB_Shift)); 61 } 62 63 unsigned MCSymbolELF::getBinding() const { 64 if (isBindingSet()) { 65 uint32_t Val = (Flags >> ELF_STB_Shift) & 3; 66 switch (Val) { 67 default: 68 llvm_unreachable("Invalid value"); 69 case 0: 70 return ELF::STB_LOCAL; 71 case 1: 72 return ELF::STB_GLOBAL; 73 case 2: 74 return ELF::STB_WEAK; 75 case 3: 76 return ELF::STB_GNU_UNIQUE; 77 } 78 } 79 80 if (isDefined()) 81 return ELF::STB_LOCAL; 82 if (isUsedInReloc()) 83 return ELF::STB_GLOBAL; 84 if (isWeakrefUsedInReloc()) 85 return ELF::STB_WEAK; 86 if (isSignature()) 87 return ELF::STB_LOCAL; 88 return ELF::STB_GLOBAL; 89 } 90 91 void 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 122 unsigned 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 144 void 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 152 unsigned MCSymbolELF::getVisibility() const { 153 unsigned Visibility = (Flags >> ELF_STV_Shift) & 3; 154 return Visibility; 155 } 156 157 void MCSymbolELF::setOther(unsigned Other) { 158 assert((Other & 0x1f) == 0); 159 Other >>= 5; 160 assert(Other <= 0x7); 161 uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift); 162 setFlags(OtherFlags | (Other << ELF_STO_Shift)); 163 } 164 165 unsigned MCSymbolELF::getOther() const { 166 unsigned Other = (Flags >> ELF_STO_Shift) & 7; 167 return Other << 5; 168 } 169 170 void MCSymbolELF::setIsWeakrefUsedInReloc() const { 171 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift); 172 setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift)); 173 } 174 175 bool MCSymbolELF::isWeakrefUsedInReloc() const { 176 return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift); 177 } 178 179 void MCSymbolELF::setIsSignature() const { 180 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift); 181 setFlags(OtherFlags | (1 << ELF_IsSignature_Shift)); 182 } 183 184 bool MCSymbolELF::isSignature() const { 185 return getFlags() & (0x1 << ELF_IsSignature_Shift); 186 } 187 188 void MCSymbolELF::setIsBindingSet() const { 189 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift); 190 setFlags(OtherFlags | (1 << ELF_BindingSet_Shift)); 191 } 192 193 bool MCSymbolELF::isBindingSet() const { 194 return getFlags() & (0x1 << ELF_BindingSet_Shift); 195 } 196 } 197