Home | History | Annotate | Download | only in MC
      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/MCAssembler.h"
     11 #include "llvm/MC/MCSymbolELF.h"
     12 #include "llvm/MC/MCFixupKindInfo.h"
     13 #include "llvm/Support/ELF.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   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 
     66 unsigned MCSymbolELF::getBinding() const {
     67   if (isBindingSet()) {
     68     uint32_t Val = (getFlags() & (0x3 << ELF_STB_Shift)) >> ELF_STB_Shift;
     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 (isWeakrefUsedInReloc())
     88     return ELF::STB_WEAK;
     89   if (isSignature())
     90     return ELF::STB_LOCAL;
     91   return ELF::STB_GLOBAL;
     92 }
     93 
     94 void MCSymbolELF::setType(unsigned Type) const {
     95   unsigned Val;
     96   switch (Type) {
     97   default:
     98     llvm_unreachable("Unsupported Binding");
     99   case ELF::STT_NOTYPE:
    100     Val = 0;
    101     break;
    102   case ELF::STT_OBJECT:
    103     Val = 1;
    104     break;
    105   case ELF::STT_FUNC:
    106     Val = 2;
    107     break;
    108   case ELF::STT_SECTION:
    109     Val = 3;
    110     break;
    111   case ELF::STT_COMMON:
    112     Val = 4;
    113     break;
    114   case ELF::STT_TLS:
    115     Val = 5;
    116     break;
    117   case ELF::STT_GNU_IFUNC:
    118     Val = 6;
    119     break;
    120   }
    121   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
    122   setFlags(OtherFlags | (Val << ELF_STT_Shift));
    123 }
    124 
    125 unsigned MCSymbolELF::getType() const {
    126   uint32_t Val = (getFlags() & (0x7 << ELF_STT_Shift)) >> ELF_STT_Shift;
    127   switch (Val) {
    128   default:
    129     llvm_unreachable("Invalid value");
    130   case 0:
    131     return ELF::STT_NOTYPE;
    132   case 1:
    133     return ELF::STT_OBJECT;
    134   case 2:
    135     return ELF::STT_FUNC;
    136   case 3:
    137     return ELF::STT_SECTION;
    138   case 4:
    139     return ELF::STT_COMMON;
    140   case 5:
    141     return ELF::STT_TLS;
    142   case 6:
    143     return ELF::STT_GNU_IFUNC;
    144   }
    145 }
    146 
    147 void MCSymbolELF::setVisibility(unsigned Visibility) {
    148   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
    149          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
    150 
    151   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
    152   setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
    153 }
    154 
    155 unsigned MCSymbolELF::getVisibility() const {
    156   unsigned Visibility = (getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift;
    157   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
    158          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
    159   return Visibility;
    160 }
    161 
    162 void MCSymbolELF::setOther(unsigned Other) {
    163   assert((Other & 0x1f) == 0);
    164   Other >>= 5;
    165   assert(Other <= 0x7);
    166   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift);
    167   setFlags(OtherFlags | (Other << ELF_STO_Shift));
    168 }
    169 
    170 unsigned MCSymbolELF::getOther() const {
    171   unsigned Other = (getFlags() & (0x7 << ELF_STO_Shift)) >> ELF_STO_Shift;
    172   return Other << 5;
    173 }
    174 
    175 void MCSymbolELF::setIsWeakrefUsedInReloc() const {
    176   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
    177   setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
    178 }
    179 
    180 bool MCSymbolELF::isWeakrefUsedInReloc() const {
    181   return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
    182 }
    183 
    184 void MCSymbolELF::setIsSignature() const {
    185   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
    186   setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
    187 }
    188 
    189 bool MCSymbolELF::isSignature() const {
    190   return getFlags() & (0x1 << ELF_IsSignature_Shift);
    191 }
    192 
    193 void MCSymbolELF::setIsBindingSet() const {
    194   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
    195   setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
    196 }
    197 
    198 bool MCSymbolELF::isBindingSet() const {
    199   return getFlags() & (0x1 << ELF_BindingSet_Shift);
    200 }
    201 }
    202