10b57cec5SDimitry Andric //===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// 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/MCSectionELF.h" 100b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 110b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 120b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 130b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 140b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 1506c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 160b57cec5SDimitry Andric #include <cassert> 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric // Decides whether a '.section' directive 210b57cec5SDimitry Andric // should be printed before the section name. 2281ad6265SDimitry Andric bool MCSectionELF::shouldOmitSectionDirective(StringRef Name, 230b57cec5SDimitry Andric const MCAsmInfo &MAI) const { 240b57cec5SDimitry Andric if (isUnique()) 250b57cec5SDimitry Andric return false; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric return MAI.shouldOmitSectionDirective(Name); 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric static void printName(raw_ostream &OS, StringRef Name) { 310b57cec5SDimitry Andric if (Name.find_first_not_of("0123456789_." 320b57cec5SDimitry Andric "abcdefghijklmnopqrstuvwxyz" 330b57cec5SDimitry Andric "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) { 340b57cec5SDimitry Andric OS << Name; 350b57cec5SDimitry Andric return; 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric OS << '"'; 380b57cec5SDimitry Andric for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) { 390b57cec5SDimitry Andric if (*B == '"') // Unquoted " 400b57cec5SDimitry Andric OS << "\\\""; 410b57cec5SDimitry Andric else if (*B != '\\') // Neither " or backslash 420b57cec5SDimitry Andric OS << *B; 430b57cec5SDimitry Andric else if (B + 1 == E) // Trailing backslash 440b57cec5SDimitry Andric OS << "\\\\"; 450b57cec5SDimitry Andric else { 460b57cec5SDimitry Andric OS << B[0] << B[1]; // Quoted character 470b57cec5SDimitry Andric ++B; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric OS << '"'; 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 5381ad6265SDimitry Andric void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, 540b57cec5SDimitry Andric raw_ostream &OS, 55*0fca6ea1SDimitry Andric uint32_t Subsection) const { 5681ad6265SDimitry Andric if (shouldOmitSectionDirective(getName(), MAI)) { 575ffd83dbSDimitry Andric OS << '\t' << getName(); 58*0fca6ea1SDimitry Andric if (Subsection) 59*0fca6ea1SDimitry Andric OS << '\t' << Subsection; 600b57cec5SDimitry Andric OS << '\n'; 610b57cec5SDimitry Andric return; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric OS << "\t.section\t"; 655ffd83dbSDimitry Andric printName(OS, getName()); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Handle the weird solaris syntax if desired. 680b57cec5SDimitry Andric if (MAI.usesSunStyleELFSectionSwitchSyntax() && 690b57cec5SDimitry Andric !(Flags & ELF::SHF_MERGE)) { 700b57cec5SDimitry Andric if (Flags & ELF::SHF_ALLOC) 710b57cec5SDimitry Andric OS << ",#alloc"; 720b57cec5SDimitry Andric if (Flags & ELF::SHF_EXECINSTR) 730b57cec5SDimitry Andric OS << ",#execinstr"; 740b57cec5SDimitry Andric if (Flags & ELF::SHF_WRITE) 750b57cec5SDimitry Andric OS << ",#write"; 760b57cec5SDimitry Andric if (Flags & ELF::SHF_EXCLUDE) 770b57cec5SDimitry Andric OS << ",#exclude"; 780b57cec5SDimitry Andric if (Flags & ELF::SHF_TLS) 790b57cec5SDimitry Andric OS << ",#tls"; 800b57cec5SDimitry Andric OS << '\n'; 810b57cec5SDimitry Andric return; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric OS << ",\""; 850b57cec5SDimitry Andric if (Flags & ELF::SHF_ALLOC) 860b57cec5SDimitry Andric OS << 'a'; 870b57cec5SDimitry Andric if (Flags & ELF::SHF_EXCLUDE) 880b57cec5SDimitry Andric OS << 'e'; 890b57cec5SDimitry Andric if (Flags & ELF::SHF_EXECINSTR) 900b57cec5SDimitry Andric OS << 'x'; 910b57cec5SDimitry Andric if (Flags & ELF::SHF_WRITE) 920b57cec5SDimitry Andric OS << 'w'; 930b57cec5SDimitry Andric if (Flags & ELF::SHF_MERGE) 940b57cec5SDimitry Andric OS << 'M'; 950b57cec5SDimitry Andric if (Flags & ELF::SHF_STRINGS) 960b57cec5SDimitry Andric OS << 'S'; 970b57cec5SDimitry Andric if (Flags & ELF::SHF_TLS) 980b57cec5SDimitry Andric OS << 'T'; 990b57cec5SDimitry Andric if (Flags & ELF::SHF_LINK_ORDER) 1000b57cec5SDimitry Andric OS << 'o'; 101297eecfbSDimitry Andric if (Flags & ELF::SHF_GROUP) 102297eecfbSDimitry Andric OS << 'G'; 103fe6060f1SDimitry Andric if (Flags & ELF::SHF_GNU_RETAIN) 104fe6060f1SDimitry Andric OS << 'R'; 1050b57cec5SDimitry Andric 10681ad6265SDimitry Andric // If there are os-specific flags, print them. 10781ad6265SDimitry Andric if (T.isOSSolaris()) 10881ad6265SDimitry Andric if (Flags & ELF::SHF_SUNW_NODISCARD) 10981ad6265SDimitry Andric OS << 'R'; 11081ad6265SDimitry Andric 1110b57cec5SDimitry Andric // If there are target-specific flags, print them. 1120b57cec5SDimitry Andric Triple::ArchType Arch = T.getArch(); 1130b57cec5SDimitry Andric if (Arch == Triple::xcore) { 1140b57cec5SDimitry Andric if (Flags & ELF::XCORE_SHF_CP_SECTION) 1150b57cec5SDimitry Andric OS << 'c'; 1160b57cec5SDimitry Andric if (Flags & ELF::XCORE_SHF_DP_SECTION) 1170b57cec5SDimitry Andric OS << 'd'; 1180b57cec5SDimitry Andric } else if (T.isARM() || T.isThumb()) { 1190b57cec5SDimitry Andric if (Flags & ELF::SHF_ARM_PURECODE) 1200b57cec5SDimitry Andric OS << 'y'; 1210b57cec5SDimitry Andric } else if (Arch == Triple::hexagon) { 1220b57cec5SDimitry Andric if (Flags & ELF::SHF_HEX_GPREL) 1230b57cec5SDimitry Andric OS << 's'; 1245f757f3fSDimitry Andric } else if (Arch == Triple::x86_64) { 1255f757f3fSDimitry Andric if (Flags & ELF::SHF_X86_64_LARGE) 1265f757f3fSDimitry Andric OS << 'l'; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric OS << '"'; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric OS << ','; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // If comment string is '@', e.g. as on ARM - use '%' instead 1340b57cec5SDimitry Andric if (MAI.getCommentString()[0] == '@') 1350b57cec5SDimitry Andric OS << '%'; 1360b57cec5SDimitry Andric else 1370b57cec5SDimitry Andric OS << '@'; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (Type == ELF::SHT_INIT_ARRAY) 1400b57cec5SDimitry Andric OS << "init_array"; 1410b57cec5SDimitry Andric else if (Type == ELF::SHT_FINI_ARRAY) 1420b57cec5SDimitry Andric OS << "fini_array"; 1430b57cec5SDimitry Andric else if (Type == ELF::SHT_PREINIT_ARRAY) 1440b57cec5SDimitry Andric OS << "preinit_array"; 1450b57cec5SDimitry Andric else if (Type == ELF::SHT_NOBITS) 1460b57cec5SDimitry Andric OS << "nobits"; 1470b57cec5SDimitry Andric else if (Type == ELF::SHT_NOTE) 1480b57cec5SDimitry Andric OS << "note"; 1490b57cec5SDimitry Andric else if (Type == ELF::SHT_PROGBITS) 1500b57cec5SDimitry Andric OS << "progbits"; 1510b57cec5SDimitry Andric else if (Type == ELF::SHT_X86_64_UNWIND) 1520b57cec5SDimitry Andric OS << "unwind"; 1530b57cec5SDimitry Andric else if (Type == ELF::SHT_MIPS_DWARF) 1540b57cec5SDimitry Andric // Print hex value of the flag while we do not have 1550b57cec5SDimitry Andric // any standard symbolic representation of the flag. 1560b57cec5SDimitry Andric OS << "0x7000001e"; 1570b57cec5SDimitry Andric else if (Type == ELF::SHT_LLVM_ODRTAB) 1580b57cec5SDimitry Andric OS << "llvm_odrtab"; 1590b57cec5SDimitry Andric else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS) 1600b57cec5SDimitry Andric OS << "llvm_linker_options"; 1610b57cec5SDimitry Andric else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) 1620b57cec5SDimitry Andric OS << "llvm_call_graph_profile"; 1630b57cec5SDimitry Andric else if (Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES) 1640b57cec5SDimitry Andric OS << "llvm_dependent_libraries"; 1650b57cec5SDimitry Andric else if (Type == ELF::SHT_LLVM_SYMPART) 1660b57cec5SDimitry Andric OS << "llvm_sympart"; 167e8d8bef9SDimitry Andric else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP) 168e8d8bef9SDimitry Andric OS << "llvm_bb_addr_map"; 16981ad6265SDimitry Andric else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP_V0) 17081ad6265SDimitry Andric OS << "llvm_bb_addr_map_v0"; 171753f127fSDimitry Andric else if (Type == ELF::SHT_LLVM_OFFLOADING) 172753f127fSDimitry Andric OS << "llvm_offloading"; 17306c3fb27SDimitry Andric else if (Type == ELF::SHT_LLVM_LTO) 17406c3fb27SDimitry Andric OS << "llvm_lto"; 1750b57cec5SDimitry Andric else 176*0fca6ea1SDimitry Andric OS << "0x" << Twine::utohexstr(Type); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric if (EntrySize) { 1790b57cec5SDimitry Andric assert(Flags & ELF::SHF_MERGE); 1800b57cec5SDimitry Andric OS << "," << EntrySize; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric if (Flags & ELF::SHF_LINK_ORDER) { 1840b57cec5SDimitry Andric OS << ","; 185e8d8bef9SDimitry Andric if (LinkedToSym) 1865ffd83dbSDimitry Andric printName(OS, LinkedToSym->getName()); 187e8d8bef9SDimitry Andric else 188e8d8bef9SDimitry Andric OS << '0'; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 191297eecfbSDimitry Andric if (Flags & ELF::SHF_GROUP) { 192297eecfbSDimitry Andric OS << ","; 193297eecfbSDimitry Andric printName(OS, Group.getPointer()->getName()); 194297eecfbSDimitry Andric if (isComdat()) 195297eecfbSDimitry Andric OS << ",comdat"; 196297eecfbSDimitry Andric } 197297eecfbSDimitry Andric 1980b57cec5SDimitry Andric if (isUnique()) 1990b57cec5SDimitry Andric OS << ",unique," << UniqueID; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric OS << '\n'; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric if (Subsection) { 204*0fca6ea1SDimitry Andric OS << "\t.subsection\t" << Subsection; 2050b57cec5SDimitry Andric OS << '\n'; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 20981ad6265SDimitry Andric bool MCSectionELF::useCodeAlign() const { 2100b57cec5SDimitry Andric return getFlags() & ELF::SHF_EXECINSTR; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2135ffd83dbSDimitry Andric StringRef MCSectionELF::getVirtualSectionKind() const { return "SHT_NOBITS"; } 214