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