210 lines · cpp
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-exception6//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 STO_* flags. 3 bits. All the values are between 0x20 and26 // 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 43void 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 66unsigned 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 92void 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 123unsigned 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 145void 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 153unsigned MCSymbolELF::getVisibility() const {154 unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;155 return Visibility;156}157 158void 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 166unsigned MCSymbolELF::getOther() const {167 unsigned Other = (Flags >> ELF_STO_Shift) & 7;168 return Other << 5;169}170 171void MCSymbolELF::setIsWeakref() const {172 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_Weakref_Shift);173 setFlags(OtherFlags | (1 << ELF_Weakref_Shift));174}175 176bool MCSymbolELF::isWeakref() const {177 return getFlags() & (0x1 << ELF_Weakref_Shift);178}179 180void MCSymbolELF::setIsSignature() const {181 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);182 setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));183}184 185bool MCSymbolELF::isSignature() const {186 return getFlags() & (0x1 << ELF_IsSignature_Shift);187}188 189void MCSymbolELF::setIsBindingSet() const {190 uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);191 setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));192}193 194bool MCSymbolELF::isBindingSet() const {195 return getFlags() & (0x1 << ELF_BindingSet_Shift);196}197 198bool MCSymbolELF::isMemtag() const {199 return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift);200}201 202void MCSymbolELF::setMemtag(bool Tagged) {203 uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift);204 if (Tagged)205 setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift));206 else207 setFlags(OtherFlags);208}209}210