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