xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCSymbolELF.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
100b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric namespace llvm {
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric namespace {
150b57cec5SDimitry Andric enum {
160b57cec5SDimitry Andric   // Shift value for STT_* flags. 7 possible values. 3 bits.
170b57cec5SDimitry Andric   ELF_STT_Shift = 0,
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric   // Shift value for STB_* flags. 4 possible values, 2 bits.
200b57cec5SDimitry Andric   ELF_STB_Shift = 3,
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric   // Shift value for STV_* flags. 4 possible values, 2 bits.
230b57cec5SDimitry Andric   ELF_STV_Shift = 5,
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric   // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and
260b57cec5SDimitry Andric   // 0xe0, so we shift right by 5 before storing.
270b57cec5SDimitry Andric   ELF_STO_Shift = 7,
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   // One bit.
300b57cec5SDimitry Andric   ELF_IsSignature_Shift = 10,
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   // One bit.
330b57cec5SDimitry Andric   ELF_WeakrefUsedInReloc_Shift = 11,
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   // One bit.
36*bdd1243dSDimitry Andric   ELF_BindingSet_Shift = 12,
37*bdd1243dSDimitry Andric 
38*bdd1243dSDimitry Andric   // One bit.
39*bdd1243dSDimitry Andric   ELF_IsMemoryTagged_Shift = 13,
400b57cec5SDimitry Andric };
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
setBinding(unsigned Binding) const430b57cec5SDimitry Andric void MCSymbolELF::setBinding(unsigned Binding) const {
440b57cec5SDimitry Andric   setIsBindingSet();
450b57cec5SDimitry Andric   unsigned Val;
460b57cec5SDimitry Andric   switch (Binding) {
470b57cec5SDimitry Andric   default:
480b57cec5SDimitry Andric     llvm_unreachable("Unsupported Binding");
490b57cec5SDimitry Andric   case ELF::STB_LOCAL:
500b57cec5SDimitry Andric     Val = 0;
510b57cec5SDimitry Andric     break;
520b57cec5SDimitry Andric   case ELF::STB_GLOBAL:
530b57cec5SDimitry Andric     Val = 1;
540b57cec5SDimitry Andric     break;
550b57cec5SDimitry Andric   case ELF::STB_WEAK:
560b57cec5SDimitry Andric     Val = 2;
570b57cec5SDimitry Andric     break;
580b57cec5SDimitry Andric   case ELF::STB_GNU_UNIQUE:
590b57cec5SDimitry Andric     Val = 3;
600b57cec5SDimitry Andric     break;
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
630b57cec5SDimitry Andric   setFlags(OtherFlags | (Val << ELF_STB_Shift));
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
getBinding() const660b57cec5SDimitry Andric unsigned MCSymbolELF::getBinding() const {
670b57cec5SDimitry Andric   if (isBindingSet()) {
680b57cec5SDimitry Andric     uint32_t Val = (Flags >> ELF_STB_Shift) & 3;
690b57cec5SDimitry Andric     switch (Val) {
700b57cec5SDimitry Andric     default:
710b57cec5SDimitry Andric       llvm_unreachable("Invalid value");
720b57cec5SDimitry Andric     case 0:
730b57cec5SDimitry Andric       return ELF::STB_LOCAL;
740b57cec5SDimitry Andric     case 1:
750b57cec5SDimitry Andric       return ELF::STB_GLOBAL;
760b57cec5SDimitry Andric     case 2:
770b57cec5SDimitry Andric       return ELF::STB_WEAK;
780b57cec5SDimitry Andric     case 3:
790b57cec5SDimitry Andric       return ELF::STB_GNU_UNIQUE;
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   if (isDefined())
840b57cec5SDimitry Andric     return ELF::STB_LOCAL;
850b57cec5SDimitry Andric   if (isUsedInReloc())
860b57cec5SDimitry Andric     return ELF::STB_GLOBAL;
870b57cec5SDimitry Andric   if (isWeakrefUsedInReloc())
880b57cec5SDimitry Andric     return ELF::STB_WEAK;
890b57cec5SDimitry Andric   if (isSignature())
900b57cec5SDimitry Andric     return ELF::STB_LOCAL;
910b57cec5SDimitry Andric   return ELF::STB_GLOBAL;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
setType(unsigned Type) const940b57cec5SDimitry Andric void MCSymbolELF::setType(unsigned Type) const {
950b57cec5SDimitry Andric   unsigned Val;
960b57cec5SDimitry Andric   switch (Type) {
970b57cec5SDimitry Andric   default:
980b57cec5SDimitry Andric     llvm_unreachable("Unsupported Binding");
990b57cec5SDimitry Andric   case ELF::STT_NOTYPE:
1000b57cec5SDimitry Andric     Val = 0;
1010b57cec5SDimitry Andric     break;
1020b57cec5SDimitry Andric   case ELF::STT_OBJECT:
1030b57cec5SDimitry Andric     Val = 1;
1040b57cec5SDimitry Andric     break;
1050b57cec5SDimitry Andric   case ELF::STT_FUNC:
1060b57cec5SDimitry Andric     Val = 2;
1070b57cec5SDimitry Andric     break;
1080b57cec5SDimitry Andric   case ELF::STT_SECTION:
1090b57cec5SDimitry Andric     Val = 3;
1100b57cec5SDimitry Andric     break;
1110b57cec5SDimitry Andric   case ELF::STT_COMMON:
1120b57cec5SDimitry Andric     Val = 4;
1130b57cec5SDimitry Andric     break;
1140b57cec5SDimitry Andric   case ELF::STT_TLS:
1150b57cec5SDimitry Andric     Val = 5;
1160b57cec5SDimitry Andric     break;
1170b57cec5SDimitry Andric   case ELF::STT_GNU_IFUNC:
1180b57cec5SDimitry Andric     Val = 6;
1190b57cec5SDimitry Andric     break;
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
1220b57cec5SDimitry Andric   setFlags(OtherFlags | (Val << ELF_STT_Shift));
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
getType() const1250b57cec5SDimitry Andric unsigned MCSymbolELF::getType() const {
1260b57cec5SDimitry Andric   uint32_t Val = (Flags >> ELF_STT_Shift) & 7;
1270b57cec5SDimitry Andric   switch (Val) {
1280b57cec5SDimitry Andric   default:
1290b57cec5SDimitry Andric     llvm_unreachable("Invalid value");
1300b57cec5SDimitry Andric   case 0:
1310b57cec5SDimitry Andric     return ELF::STT_NOTYPE;
1320b57cec5SDimitry Andric   case 1:
1330b57cec5SDimitry Andric     return ELF::STT_OBJECT;
1340b57cec5SDimitry Andric   case 2:
1350b57cec5SDimitry Andric     return ELF::STT_FUNC;
1360b57cec5SDimitry Andric   case 3:
1370b57cec5SDimitry Andric     return ELF::STT_SECTION;
1380b57cec5SDimitry Andric   case 4:
1390b57cec5SDimitry Andric     return ELF::STT_COMMON;
1400b57cec5SDimitry Andric   case 5:
1410b57cec5SDimitry Andric     return ELF::STT_TLS;
1420b57cec5SDimitry Andric   case 6:
1430b57cec5SDimitry Andric     return ELF::STT_GNU_IFUNC;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
setVisibility(unsigned Visibility)1470b57cec5SDimitry Andric void MCSymbolELF::setVisibility(unsigned Visibility) {
1480b57cec5SDimitry Andric   assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
1490b57cec5SDimitry Andric          Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
1520b57cec5SDimitry Andric   setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
getVisibility() const1550b57cec5SDimitry Andric unsigned MCSymbolELF::getVisibility() const {
1560b57cec5SDimitry Andric   unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;
1570b57cec5SDimitry Andric   return Visibility;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
setOther(unsigned Other)1600b57cec5SDimitry Andric void MCSymbolELF::setOther(unsigned Other) {
1610b57cec5SDimitry Andric   assert((Other & 0x1f) == 0);
1620b57cec5SDimitry Andric   Other >>= 5;
1630b57cec5SDimitry Andric   assert(Other <= 0x7);
1640b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift);
1650b57cec5SDimitry Andric   setFlags(OtherFlags | (Other << ELF_STO_Shift));
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
getOther() const1680b57cec5SDimitry Andric unsigned MCSymbolELF::getOther() const {
1690b57cec5SDimitry Andric   unsigned Other = (Flags >> ELF_STO_Shift) & 7;
1700b57cec5SDimitry Andric   return Other << 5;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
setIsWeakrefUsedInReloc() const1730b57cec5SDimitry Andric void MCSymbolELF::setIsWeakrefUsedInReloc() const {
1740b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
1750b57cec5SDimitry Andric   setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
isWeakrefUsedInReloc() const1780b57cec5SDimitry Andric bool MCSymbolELF::isWeakrefUsedInReloc() const {
1790b57cec5SDimitry Andric   return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
setIsSignature() const1820b57cec5SDimitry Andric void MCSymbolELF::setIsSignature() const {
1830b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
1840b57cec5SDimitry Andric   setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
isSignature() const1870b57cec5SDimitry Andric bool MCSymbolELF::isSignature() const {
1880b57cec5SDimitry Andric   return getFlags() & (0x1 << ELF_IsSignature_Shift);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
setIsBindingSet() const1910b57cec5SDimitry Andric void MCSymbolELF::setIsBindingSet() const {
1920b57cec5SDimitry Andric   uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
1930b57cec5SDimitry Andric   setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
isBindingSet() const1960b57cec5SDimitry Andric bool MCSymbolELF::isBindingSet() const {
1970b57cec5SDimitry Andric   return getFlags() & (0x1 << ELF_BindingSet_Shift);
1980b57cec5SDimitry Andric }
199*bdd1243dSDimitry Andric 
isMemtag() const200*bdd1243dSDimitry Andric bool MCSymbolELF::isMemtag() const {
201*bdd1243dSDimitry Andric   return getFlags() & (0x1 << ELF_IsMemoryTagged_Shift);
202*bdd1243dSDimitry Andric }
203*bdd1243dSDimitry Andric 
setMemtag(bool Tagged)204*bdd1243dSDimitry Andric void MCSymbolELF::setMemtag(bool Tagged) {
205*bdd1243dSDimitry Andric   uint32_t OtherFlags = getFlags() & ~(1 << ELF_IsMemoryTagged_Shift);
206*bdd1243dSDimitry Andric   if (Tagged)
207*bdd1243dSDimitry Andric     setFlags(OtherFlags | (1 << ELF_IsMemoryTagged_Shift));
208*bdd1243dSDimitry Andric   else
209*bdd1243dSDimitry Andric     setFlags(OtherFlags);
210*bdd1243dSDimitry Andric }
2110b57cec5SDimitry Andric }
212