Home | History | Annotate | Line # | Download | only in MC
      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 #include "llvm/MC/MCFixupKindInfo.h"
     12 
     13 namespace llvm {
     14 
     15 namespace {
     16 enum {
     17   // Shift value for STT_* flags. 7 possible values. 3 bits.
     18   ELF_STT_Shift = 0,
     19 
     20   // Shift value for STB_* flags. 4 possible values, 2 bits.
     21   ELF_STB_Shift = 3,
     22 
     23   // Shift value for STV_* flags. 4 possible values, 2 bits.
     24   ELF_STV_Shift = 5,
     25 
     26   // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and
     27   // 0xe0, so we shift right by 5 before storing.
     28   ELF_STO_Shift = 7,
     29 
     30   // One bit.
     31   ELF_IsSignature_Shift = 10,
     32 
     33   // One bit.
     34   ELF_WeakrefUsedInReloc_Shift = 11,
     35 
     36   // One bit.
     37   ELF_BindingSet_Shift = 12
     38 };
     39 }
     40 
     41 void MCSymbolELF::setBinding(unsigned Binding) const {
     42   setIsBindingSet();
     43   unsigned Val;
     44   switch (Binding) {
     45   default:
     46     llvm_unreachable("Unsupported Binding");
     47   case ELF::STB_LOCAL:
     48     Val = 0;
     49     break;
     50   case ELF::STB_GLOBAL:
     51     Val = 1;
     52     break;
     53   case ELF::STB_WEAK:
     54     Val = 2;
     55     break;
     56   case ELF::STB_GNU_UNIQUE:
     57     Val = 3;
     58     break;
     59   }
     60   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
     61   setFlags(OtherFlags | (Val << ELF_STB_Shift));
     62 }
     63 
     64 unsigned MCSymbolELF::getBinding() const {
     65   if (isBindingSet()) {
     66     uint32_t Val = (Flags >> ELF_STB_Shift) & 3;
     67     switch (Val) {
     68     default:
     69       llvm_unreachable("Invalid value");
     70     case 0:
     71       return ELF::STB_LOCAL;
     72     case 1:
     73       return ELF::STB_GLOBAL;
     74     case 2:
     75       return ELF::STB_WEAK;
     76     case 3:
     77       return ELF::STB_GNU_UNIQUE;
     78     }
     79   }
     80 
     81   if (isDefined())
     82     return ELF::STB_LOCAL;
     83   if (isUsedInReloc())
     84     return ELF::STB_GLOBAL;
     85   if (isWeakrefUsedInReloc())
     86     return ELF::STB_WEAK;
     87   if (isSignature())
     88     return ELF::STB_LOCAL;
     89   return ELF::STB_GLOBAL;
     90 }
     91 
     92 void 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 
    123 unsigned 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 
    145 void 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 
    153 unsigned MCSymbolELF::getVisibility() const {
    154   unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;
    155   return Visibility;
    156 }
    157 
    158 void 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 
    166 unsigned MCSymbolELF::getOther() const {
    167   unsigned Other = (Flags >> ELF_STO_Shift) & 7;
    168   return Other << 5;
    169 }
    170 
    171 void MCSymbolELF::setIsWeakrefUsedInReloc() const {
    172   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
    173   setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
    174 }
    175 
    176 bool MCSymbolELF::isWeakrefUsedInReloc() const {
    177   return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
    178 }
    179 
    180 void MCSymbolELF::setIsSignature() const {
    181   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
    182   setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
    183 }
    184 
    185 bool MCSymbolELF::isSignature() const {
    186   return getFlags() & (0x1 << ELF_IsSignature_Shift);
    187 }
    188 
    189 void MCSymbolELF::setIsBindingSet() const {
    190   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
    191   setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
    192 }
    193 
    194 bool MCSymbolELF::isBindingSet() const {
    195   return getFlags() & (0x1 << ELF_BindingSet_Shift);
    196 }
    197 }
    198