195fb9b93SRafael Espindola //===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===// 295fb9b93SRafael Espindola // 395fb9b93SRafael Espindola // The LLVM Compiler Infrastructure 495fb9b93SRafael Espindola // 595fb9b93SRafael Espindola // This file is distributed under the University of Illinois Open Source 695fb9b93SRafael Espindola // License. See LICENSE.TXT for details. 795fb9b93SRafael Espindola // 895fb9b93SRafael Espindola //===----------------------------------------------------------------------===// 995fb9b93SRafael Espindola 1095fb9b93SRafael Espindola #include "llvm/MC/MCAssembler.h" 1195fb9b93SRafael Espindola #include "llvm/MC/MCSymbolELF.h" 1295fb9b93SRafael Espindola #include "llvm/MC/MCFixupKindInfo.h" 1395fb9b93SRafael Espindola #include "llvm/Support/ELF.h" 1495fb9b93SRafael Espindola 1595fb9b93SRafael Espindola namespace llvm { 1695fb9b93SRafael Espindola 17f8794ff2SRafael Espindola namespace { 18f8794ff2SRafael Espindola enum { 198c006ee3SRafael Espindola // Shift value for STT_* flags. 7 possible values. 3 bits. 208c006ee3SRafael Espindola ELF_STT_Shift = 0, 218c006ee3SRafael Espindola 228c006ee3SRafael Espindola // Shift value for STB_* flags. 4 possible values, 2 bits. 238c006ee3SRafael Espindola ELF_STB_Shift = 3, 248c006ee3SRafael Espindola 258c006ee3SRafael Espindola // Shift value for STV_* flags. 4 possible values, 2 bits. 268c006ee3SRafael Espindola ELF_STV_Shift = 5, 278c006ee3SRafael Espindola 288c006ee3SRafael Espindola // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and 298c006ee3SRafael Espindola // 0xe0, so we shift right by 5 before storing. 308c006ee3SRafael Espindola ELF_STO_Shift = 7, 318c006ee3SRafael Espindola 328c006ee3SRafael Espindola // One bit. 338c006ee3SRafael Espindola ELF_IsSignature_Shift = 10, 348c006ee3SRafael Espindola 358c006ee3SRafael Espindola // One bit. 368c006ee3SRafael Espindola ELF_WeakrefUsedInReloc_Shift = 11, 378c006ee3SRafael Espindola 388c006ee3SRafael Espindola // One bit. 39*dfe2d359SRafael Espindola ELF_BindingSet_Shift = 12 40f8794ff2SRafael Espindola }; 41f8794ff2SRafael Espindola } 42f8794ff2SRafael Espindola 4395fb9b93SRafael Espindola void MCSymbolELF::setBinding(unsigned Binding) const { 448c006ee3SRafael Espindola setIsBindingSet(); 458c006ee3SRafael Espindola unsigned Val; 468c006ee3SRafael Espindola switch (Binding) { 478c006ee3SRafael Espindola default: 488c006ee3SRafael Espindola llvm_unreachable("Unsupported Binding"); 498c006ee3SRafael Espindola case ELF::STB_LOCAL: 508c006ee3SRafael Espindola Val = 0; 518c006ee3SRafael Espindola break; 528c006ee3SRafael Espindola case ELF::STB_GLOBAL: 538c006ee3SRafael Espindola Val = 1; 548c006ee3SRafael Espindola break; 558c006ee3SRafael Espindola case ELF::STB_WEAK: 568c006ee3SRafael Espindola Val = 2; 578c006ee3SRafael Espindola break; 588c006ee3SRafael Espindola case ELF::STB_GNU_UNIQUE: 598c006ee3SRafael Espindola Val = 3; 608c006ee3SRafael Espindola break; 618c006ee3SRafael Espindola } 628c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift); 638c006ee3SRafael Espindola setFlags(OtherFlags | (Val << ELF_STB_Shift)); 6495fb9b93SRafael Espindola } 6595fb9b93SRafael Espindola 6695fb9b93SRafael Espindola unsigned MCSymbolELF::getBinding() const { 678c52a9b0SRafael Espindola if (isBindingSet()) { 688c006ee3SRafael Espindola uint32_t Val = (getFlags() & (0x3 << ELF_STB_Shift)) >> ELF_STB_Shift; 698c006ee3SRafael Espindola switch (Val) { 708c006ee3SRafael Espindola default: 718c006ee3SRafael Espindola llvm_unreachable("Invalid value"); 728c006ee3SRafael Espindola case 0: 738c006ee3SRafael Espindola return ELF::STB_LOCAL; 748c006ee3SRafael Espindola case 1: 758c006ee3SRafael Espindola return ELF::STB_GLOBAL; 768c006ee3SRafael Espindola case 2: 778c006ee3SRafael Espindola return ELF::STB_WEAK; 788c006ee3SRafael Espindola case 3: 798c006ee3SRafael Espindola return ELF::STB_GNU_UNIQUE; 808c006ee3SRafael Espindola } 8195fb9b93SRafael Espindola } 8295fb9b93SRafael Espindola 838c52a9b0SRafael Espindola if (isDefined()) 848c52a9b0SRafael Espindola return ELF::STB_LOCAL; 858c52a9b0SRafael Espindola if (isUsedInReloc()) 868c52a9b0SRafael Espindola return ELF::STB_GLOBAL; 87212fdde2SRafael Espindola if (isWeakrefUsedInReloc()) 88212fdde2SRafael Espindola return ELF::STB_WEAK; 898c52a9b0SRafael Espindola if (isSignature()) 908c52a9b0SRafael Espindola return ELF::STB_LOCAL; 918c52a9b0SRafael Espindola return ELF::STB_GLOBAL; 928c52a9b0SRafael Espindola } 938c52a9b0SRafael Espindola 9495fb9b93SRafael Espindola void MCSymbolELF::setType(unsigned Type) const { 958c006ee3SRafael Espindola unsigned Val; 968c006ee3SRafael Espindola switch (Type) { 978c006ee3SRafael Espindola default: 988c006ee3SRafael Espindola llvm_unreachable("Unsupported Binding"); 998c006ee3SRafael Espindola case ELF::STT_NOTYPE: 1008c006ee3SRafael Espindola Val = 0; 1018c006ee3SRafael Espindola break; 1028c006ee3SRafael Espindola case ELF::STT_OBJECT: 1038c006ee3SRafael Espindola Val = 1; 1048c006ee3SRafael Espindola break; 1058c006ee3SRafael Espindola case ELF::STT_FUNC: 1068c006ee3SRafael Espindola Val = 2; 1078c006ee3SRafael Espindola break; 1088c006ee3SRafael Espindola case ELF::STT_SECTION: 1098c006ee3SRafael Espindola Val = 3; 1108c006ee3SRafael Espindola break; 1118c006ee3SRafael Espindola case ELF::STT_COMMON: 1128c006ee3SRafael Espindola Val = 4; 1138c006ee3SRafael Espindola break; 1148c006ee3SRafael Espindola case ELF::STT_TLS: 1158c006ee3SRafael Espindola Val = 5; 1168c006ee3SRafael Espindola break; 1178c006ee3SRafael Espindola case ELF::STT_GNU_IFUNC: 1188c006ee3SRafael Espindola Val = 6; 1198c006ee3SRafael Espindola break; 1208c006ee3SRafael Espindola } 1218c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift); 1228c006ee3SRafael Espindola setFlags(OtherFlags | (Val << ELF_STT_Shift)); 12395fb9b93SRafael Espindola } 12495fb9b93SRafael Espindola 12595fb9b93SRafael Espindola unsigned MCSymbolELF::getType() const { 1268c006ee3SRafael Espindola uint32_t Val = (getFlags() & (0x7 << ELF_STT_Shift)) >> ELF_STT_Shift; 1278c006ee3SRafael Espindola switch (Val) { 1288c006ee3SRafael Espindola default: 1298c006ee3SRafael Espindola llvm_unreachable("Invalid value"); 1308c006ee3SRafael Espindola case 0: 1318c006ee3SRafael Espindola return ELF::STT_NOTYPE; 1328c006ee3SRafael Espindola case 1: 1338c006ee3SRafael Espindola return ELF::STT_OBJECT; 1348c006ee3SRafael Espindola case 2: 1358c006ee3SRafael Espindola return ELF::STT_FUNC; 1368c006ee3SRafael Espindola case 3: 1378c006ee3SRafael Espindola return ELF::STT_SECTION; 1388c006ee3SRafael Espindola case 4: 1398c006ee3SRafael Espindola return ELF::STT_COMMON; 1408c006ee3SRafael Espindola case 5: 1418c006ee3SRafael Espindola return ELF::STT_TLS; 1428c006ee3SRafael Espindola case 6: 1438c006ee3SRafael Espindola return ELF::STT_GNU_IFUNC; 1448c006ee3SRafael Espindola } 14595fb9b93SRafael Espindola } 14695fb9b93SRafael Espindola 14795fb9b93SRafael Espindola void MCSymbolELF::setVisibility(unsigned Visibility) { 14895fb9b93SRafael Espindola assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || 14995fb9b93SRafael Espindola Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); 15095fb9b93SRafael Espindola 15195fb9b93SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift); 15295fb9b93SRafael Espindola setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); 15395fb9b93SRafael Espindola } 15495fb9b93SRafael Espindola 15595fb9b93SRafael Espindola unsigned MCSymbolELF::getVisibility() const { 15695fb9b93SRafael Espindola unsigned Visibility = (getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift; 15795fb9b93SRafael Espindola assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || 15895fb9b93SRafael Espindola Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); 15995fb9b93SRafael Espindola return Visibility; 16095fb9b93SRafael Espindola } 16195fb9b93SRafael Espindola 16295fb9b93SRafael Espindola void MCSymbolELF::setOther(unsigned Other) { 1638c006ee3SRafael Espindola assert((Other & 0x1f) == 0); 1648c006ee3SRafael Espindola Other >>= 5; 1658c006ee3SRafael Espindola assert(Other <= 0x7); 1668c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift); 16795fb9b93SRafael Espindola setFlags(OtherFlags | (Other << ELF_STO_Shift)); 16895fb9b93SRafael Espindola } 16995fb9b93SRafael Espindola 17095fb9b93SRafael Espindola unsigned MCSymbolELF::getOther() const { 1718c006ee3SRafael Espindola unsigned Other = (getFlags() & (0x7 << ELF_STO_Shift)) >> ELF_STO_Shift; 1728c006ee3SRafael Espindola return Other << 5; 17395fb9b93SRafael Espindola } 174ada43f63SRafael Espindola 1758c006ee3SRafael Espindola void MCSymbolELF::setIsWeakrefUsedInReloc() const { 1768c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift); 1778c006ee3SRafael Espindola setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift)); 1788c006ee3SRafael Espindola } 179212fdde2SRafael Espindola 1808c006ee3SRafael Espindola bool MCSymbolELF::isWeakrefUsedInReloc() const { 1818c006ee3SRafael Espindola return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift); 1828c006ee3SRafael Espindola } 183212fdde2SRafael Espindola 1848c006ee3SRafael Espindola void MCSymbolELF::setIsSignature() const { 1858c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift); 1868c006ee3SRafael Espindola setFlags(OtherFlags | (1 << ELF_IsSignature_Shift)); 1878c006ee3SRafael Espindola } 1888c52a9b0SRafael Espindola 1898c006ee3SRafael Espindola bool MCSymbolELF::isSignature() const { 1908c006ee3SRafael Espindola return getFlags() & (0x1 << ELF_IsSignature_Shift); 1918c006ee3SRafael Espindola } 1928c006ee3SRafael Espindola 1938c006ee3SRafael Espindola void MCSymbolELF::setIsBindingSet() const { 1948c006ee3SRafael Espindola uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift); 1958c006ee3SRafael Espindola setFlags(OtherFlags | (1 << ELF_BindingSet_Shift)); 1968c006ee3SRafael Espindola } 1978c006ee3SRafael Espindola 1988c006ee3SRafael Espindola bool MCSymbolELF::isBindingSet() const { 1998c006ee3SRafael Espindola return getFlags() & (0x1 << ELF_BindingSet_Shift); 2008c006ee3SRafael Espindola } 20195fb9b93SRafael Espindola } 202