1//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines target asm properties related what form asm statements
10// should take in general on ELF-based targets
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/MC/MCAsmInfoELF.h"
15#include "llvm/ADT/Twine.h"
16#include "llvm/BinaryFormat/ELF.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCSectionELF.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "llvm/Support/raw_ostream.h"
23#include "llvm/TargetParser/Triple.h"
24#include <cassert>
25
26using namespace llvm;
27
28void MCAsmInfoELF::anchor() {}
29
30MCSection *MCAsmInfoELF::getStackSection(MCContext &Ctx, bool Exec) const {
31 // Solaris doesn't know/doesn't care about .note.GNU-stack sections, so
32 // don't emit them.
33 if (Ctx.getTargetTriple().isOSSolaris())
34 return nullptr;
35 return Ctx.getELFSection(Section: ".note.GNU-stack", Type: ELF::SHT_PROGBITS,
36 Flags: Exec ? ELF::SHF_EXECINSTR : 0U);
37}
38
39bool MCAsmInfoELF::useCodeAlign(const MCSection &Sec) const {
40 return static_cast<const MCSectionELF &>(Sec).getFlags() & ELF::SHF_EXECINSTR;
41}
42
43MCAsmInfoELF::MCAsmInfoELF() {
44 HasIdentDirective = true;
45 HasPreferredAlignment = true;
46 WeakRefDirective = "\t.weak\t";
47 PrivateGlobalPrefix = ".L";
48 PrivateLabelPrefix = ".L";
49}
50
51static void printName(raw_ostream &OS, StringRef Name) {
52 if (Name.find_first_not_of(Chars: "0123456789_."
53 "abcdefghijklmnopqrstuvwxyz"
54 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
55 OS << Name;
56 return;
57 }
58 OS << '"';
59 for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
60 if (*B == '"') // Unquoted "
61 OS << "\\\"";
62 else if (*B != '\\') // Neither " or backslash
63 OS << *B;
64 else if (B + 1 == E) // Trailing backslash
65 OS << "\\\\";
66 else {
67 OS << B[0] << B[1]; // Quoted character
68 ++B;
69 }
70 }
71 OS << '"';
72}
73
74void MCAsmInfoELF::printSwitchToSection(const MCSection &Section,
75 uint32_t Subsection, const Triple &T,
76 raw_ostream &OS) const {
77 auto &Sec = static_cast<const MCSectionELF &>(Section);
78 if (!Sec.isUnique() && shouldOmitSectionDirective(SectionName: Sec.getName())) {
79 OS << '\t' << Sec.getName();
80 if (Subsection)
81 OS << '\t' << Subsection;
82 OS << '\n';
83 return;
84 }
85
86 OS << "\t.section\t";
87 printName(OS, Name: Sec.getName());
88
89 // Handle the weird solaris syntax if desired.
90 if (usesSunStyleELFSectionSwitchSyntax() && !(Sec.Flags & ELF::SHF_MERGE)) {
91 if (Sec.Flags & ELF::SHF_ALLOC)
92 OS << ",#alloc";
93 if (Sec.Flags & ELF::SHF_EXECINSTR)
94 OS << ",#execinstr";
95 if (Sec.Flags & ELF::SHF_WRITE)
96 OS << ",#write";
97 if (Sec.Flags & ELF::SHF_EXCLUDE)
98 OS << ",#exclude";
99 if (Sec.Flags & ELF::SHF_TLS)
100 OS << ",#tls";
101 OS << '\n';
102 return;
103 }
104
105 OS << ",\"";
106 if (Sec.Flags & ELF::SHF_ALLOC)
107 OS << 'a';
108 if (Sec.Flags & ELF::SHF_EXCLUDE)
109 OS << 'e';
110 if (Sec.Flags & ELF::SHF_EXECINSTR)
111 OS << 'x';
112 if (Sec.Flags & ELF::SHF_WRITE)
113 OS << 'w';
114 if (Sec.Flags & ELF::SHF_MERGE)
115 OS << 'M';
116 if (Sec.Flags & ELF::SHF_STRINGS)
117 OS << 'S';
118 if (Sec.Flags & ELF::SHF_TLS)
119 OS << 'T';
120 if (Sec.Flags & ELF::SHF_LINK_ORDER)
121 OS << 'o';
122 if (Sec.Flags & ELF::SHF_GROUP)
123 OS << 'G';
124 if (Sec.Flags & ELF::SHF_GNU_RETAIN)
125 OS << 'R';
126
127 // If there are os-specific flags, print them.
128 if (T.isOSSolaris())
129 if (Sec.Flags & ELF::SHF_SUNW_NODISCARD)
130 OS << 'R';
131
132 // If there are tarSec.get-specific flags, print them.
133 Triple::ArchType Arch = T.getArch();
134 if (Arch == Triple::xcore) {
135 if (Sec.Flags & ELF::XCORE_SHF_CP_SECTION)
136 OS << 'c';
137 if (Sec.Flags & ELF::XCORE_SHF_DP_SECTION)
138 OS << 'd';
139 } else if (T.isARM() || T.isThumb()) {
140 if (Sec.Flags & ELF::SHF_ARM_PURECODE)
141 OS << 'y';
142 } else if (T.isAArch64()) {
143 if (Sec.Flags & ELF::SHF_AARCH64_PURECODE)
144 OS << 'y';
145 } else if (Arch == Triple::hexagon) {
146 if (Sec.Flags & ELF::SHF_HEX_GPREL)
147 OS << 's';
148 } else if (Arch == Triple::x86_64) {
149 if (Sec.Flags & ELF::SHF_X86_64_LARGE)
150 OS << 'l';
151 }
152
153 OS << '"';
154
155 OS << ',';
156
157 // If comment string is '@', e.g. as on ARM - use '%' instead
158 if (getCommentString()[0] == '@')
159 OS << '%';
160 else
161 OS << '@';
162
163 if (Sec.Type == ELF::SHT_INIT_ARRAY)
164 OS << "init_array";
165 else if (Sec.Type == ELF::SHT_FINI_ARRAY)
166 OS << "fini_array";
167 else if (Sec.Type == ELF::SHT_PREINIT_ARRAY)
168 OS << "preinit_array";
169 else if (Sec.Type == ELF::SHT_NOBITS)
170 OS << "nobits";
171 else if (Sec.Type == ELF::SHT_NOTE)
172 OS << "note";
173 else if (Sec.Type == ELF::SHT_PROGBITS)
174 OS << "progbits";
175 else if (Sec.Type == ELF::SHT_X86_64_UNWIND)
176 OS << "unwind";
177 else if (Sec.Type == ELF::SHT_MIPS_DWARF)
178 // Print hex value of the flag while we do not have
179 // any standard symbolic representation of the flag.
180 OS << "0x7000001e";
181 else if (Sec.Type == ELF::SHT_LLVM_ODRTAB)
182 OS << "llvm_odrtab";
183 else if (Sec.Type == ELF::SHT_LLVM_LINKER_OPTIONS)
184 OS << "llvm_linker_options";
185 else if (Sec.Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
186 OS << "llvm_call_graph_profile";
187 else if (Sec.Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
188 OS << "llvm_dependent_libraries";
189 else if (Sec.Type == ELF::SHT_LLVM_SYMPART)
190 OS << "llvm_sympart";
191 else if (Sec.Type == ELF::SHT_LLVM_BB_ADDR_MAP)
192 OS << "llvm_bb_addr_map";
193 else if (Sec.Type == ELF::SHT_LLVM_OFFLOADING)
194 OS << "llvm_offloading";
195 else if (Sec.Type == ELF::SHT_LLVM_LTO)
196 OS << "llvm_lto";
197 else if (Sec.Type == ELF::SHT_LLVM_JT_SIZES)
198 OS << "llvm_jt_sizes";
199 else if (Sec.Type == ELF::SHT_LLVM_CFI_JUMP_TABLE)
200 OS << "llvm_cfi_jump_table";
201 else if (Sec.Type == ELF::SHT_LLVM_CALL_GRAPH)
202 OS << "llvm_call_graph";
203 else
204 OS << "0x" << Twine::utohexstr(Val: Sec.Type);
205
206 if (Sec.EntrySize) {
207 assert((Sec.Flags & ELF::SHF_MERGE) ||
208 Sec.Type == ELF::SHT_LLVM_CFI_JUMP_TABLE);
209 OS << "," << Sec.EntrySize;
210 }
211
212 if (Sec.Flags & ELF::SHF_LINK_ORDER) {
213 OS << ",";
214 if (Sec.LinkedToSym)
215 printName(OS, Name: Sec.LinkedToSym->getName());
216 else
217 OS << '0';
218 }
219
220 if (Sec.Flags & ELF::SHF_GROUP) {
221 OS << ",";
222 printName(OS, Name: Sec.Group.getPointer()->getName());
223 if (Sec.isComdat())
224 OS << ",comdat";
225 }
226
227 if (Sec.isUnique())
228 OS << ",unique," << Sec.UniqueID;
229
230 OS << '\n';
231
232 if (Subsection) {
233 OS << "\t.subsection\t" << Subsection;
234 OS << '\n';
235 }
236}
237