xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCSectionELF.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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