2009-08-13 13:07:35 +08:00
|
|
|
//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-08-13 13:07:35 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/MC/MCSectionELF.h"
|
2017-02-14 08:33:36 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2017-06-07 11:48:56 +08:00
|
|
|
#include "llvm/BinaryFormat/ELF.h"
|
2010-01-14 05:21:29 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2013-04-18 05:18:16 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2017-03-10 16:22:13 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-08-13 13:07:35 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-14 08:33:36 +08:00
|
|
|
#include <cassert>
|
2011-01-23 12:28:49 +08:00
|
|
|
|
2009-08-13 13:07:35 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-10-10 05:23:39 +08:00
|
|
|
// Decides whether a '.section' directive
|
|
|
|
// should be printed before the section name.
|
2010-01-23 02:21:23 +08:00
|
|
|
bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
|
2010-01-14 05:21:29 +08:00
|
|
|
const MCAsmInfo &MAI) const {
|
2015-04-05 02:02:01 +08:00
|
|
|
if (isUnique())
|
2015-02-18 04:48:01 +08:00
|
|
|
return false;
|
|
|
|
|
MCAsmInfo: Allow targets to specify when the .section directive should be omitted
Summary:
The default behavior is to omit the .section directive for .text, .data,
and sometimes .bss, but some targets may want to omit this directive for
other sections too.
The AMDGPU backend will uses this to emit a simplified syntax for section
switches. For example if the section directive is not omitted (current
behavior), section switches to .hsatext will be printed like this:
.section .hsatext,#alloc,#execinstr,#write
This is actually wrong, because .hsatext has some custom STT_* flags,
which MC doesn't know how to print or parse.
If the section directive is omitted (made possible by this commit),
section switches will be printed like this:
.hsatext
The motivation for this patch is to make it possible to emit sections
with custom STT_* flags without having to teach MC about all the target
specific STT_* flags.
Reviewers: rafael, grosbach
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D12423
llvm-svn: 248618
2015-09-26 05:41:14 +08:00
|
|
|
return MAI.shouldOmitSectionDirective(Name);
|
2009-08-13 13:07:35 +08:00
|
|
|
}
|
|
|
|
|
2013-11-13 22:01:59 +08:00
|
|
|
static void printName(raw_ostream &OS, StringRef Name) {
|
|
|
|
if (Name.find_first_not_of("0123456789_."
|
|
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
|
|
|
|
OS << Name;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
OS << '"';
|
|
|
|
for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
|
|
|
|
if (*B == '"') // Unquoted "
|
|
|
|
OS << "\\\"";
|
|
|
|
else if (*B != '\\') // Neither " or backslash
|
|
|
|
OS << *B;
|
|
|
|
else if (B + 1 == E) // Trailing backslash
|
|
|
|
OS << "\\\\";
|
|
|
|
else {
|
|
|
|
OS << B[0] << B[1]; // Quoted character
|
|
|
|
++B;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OS << '"';
|
|
|
|
}
|
|
|
|
|
2017-01-30 23:38:43 +08:00
|
|
|
void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
2013-04-18 05:18:16 +08:00
|
|
|
raw_ostream &OS,
|
|
|
|
const MCExpr *Subsection) const {
|
2010-01-23 02:21:23 +08:00
|
|
|
if (ShouldOmitSectionDirective(SectionName, MAI)) {
|
2013-04-18 05:18:16 +08:00
|
|
|
OS << '\t' << getSectionName();
|
2015-06-09 08:31:39 +08:00
|
|
|
if (Subsection) {
|
|
|
|
OS << '\t';
|
|
|
|
Subsection->print(OS, &MAI);
|
|
|
|
}
|
2013-04-18 05:18:16 +08:00
|
|
|
OS << '\n';
|
2009-08-13 13:07:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-13 22:01:59 +08:00
|
|
|
OS << "\t.section\t";
|
|
|
|
printName(OS, getSectionName());
|
2011-03-04 06:31:08 +08:00
|
|
|
|
2009-08-13 13:07:35 +08:00
|
|
|
// Handle the weird solaris syntax if desired.
|
2012-05-11 09:41:30 +08:00
|
|
|
if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
|
2011-01-23 12:43:11 +08:00
|
|
|
!(Flags & ELF::SHF_MERGE)) {
|
|
|
|
if (Flags & ELF::SHF_ALLOC)
|
2009-08-13 13:07:35 +08:00
|
|
|
OS << ",#alloc";
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_EXECINSTR)
|
2009-08-13 13:07:35 +08:00
|
|
|
OS << ",#execinstr";
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_WRITE)
|
2009-08-13 13:07:35 +08:00
|
|
|
OS << ",#write";
|
2013-09-16 03:53:20 +08:00
|
|
|
if (Flags & ELF::SHF_EXCLUDE)
|
|
|
|
OS << ",#exclude";
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_TLS)
|
2009-08-13 13:07:35 +08:00
|
|
|
OS << ",#tls";
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << '\n';
|
|
|
|
return;
|
|
|
|
}
|
2012-05-11 09:41:30 +08:00
|
|
|
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << ",\"";
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_ALLOC)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'a';
|
2013-09-16 03:53:20 +08:00
|
|
|
if (Flags & ELF::SHF_EXCLUDE)
|
|
|
|
OS << 'e';
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_EXECINSTR)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'x';
|
2011-02-15 06:23:49 +08:00
|
|
|
if (Flags & ELF::SHF_GROUP)
|
|
|
|
OS << 'G';
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_WRITE)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'w';
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_MERGE)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'M';
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_STRINGS)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'S';
|
2011-01-23 12:43:11 +08:00
|
|
|
if (Flags & ELF::SHF_TLS)
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << 'T';
|
2017-03-15 03:28:51 +08:00
|
|
|
if (Flags & ELF::SHF_LINK_ORDER)
|
2017-04-05 06:35:08 +08:00
|
|
|
OS << 'o';
|
2012-05-11 09:41:30 +08:00
|
|
|
|
2010-04-09 05:26:26 +08:00
|
|
|
// If there are target-specific flags, print them.
|
2017-01-30 23:38:43 +08:00
|
|
|
Triple::ArchType Arch = T.getArch();
|
|
|
|
if (Arch == Triple::xcore) {
|
|
|
|
if (Flags & ELF::XCORE_SHF_CP_SECTION)
|
|
|
|
OS << 'c';
|
|
|
|
if (Flags & ELF::XCORE_SHF_DP_SECTION)
|
|
|
|
OS << 'd';
|
2017-08-13 01:40:18 +08:00
|
|
|
} else if (T.isARM() || T.isThumb()) {
|
2017-01-30 23:38:43 +08:00
|
|
|
if (Flags & ELF::SHF_ARM_PURECODE)
|
|
|
|
OS << 'y';
|
2018-11-09 22:17:27 +08:00
|
|
|
} else if (Arch == Triple::hexagon) {
|
|
|
|
if (Flags & ELF::SHF_HEX_GPREL)
|
|
|
|
OS << 's';
|
2017-01-30 23:38:43 +08:00
|
|
|
}
|
2012-05-11 09:41:30 +08:00
|
|
|
|
2010-04-09 05:26:26 +08:00
|
|
|
OS << '"';
|
2009-08-13 13:07:35 +08:00
|
|
|
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << ',';
|
|
|
|
|
|
|
|
// If comment string is '@', e.g. as on ARM - use '%' instead
|
|
|
|
if (MAI.getCommentString()[0] == '@')
|
|
|
|
OS << '%';
|
|
|
|
else
|
|
|
|
OS << '@';
|
|
|
|
|
2011-01-23 12:28:49 +08:00
|
|
|
if (Type == ELF::SHT_INIT_ARRAY)
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "init_array";
|
2011-01-23 12:28:49 +08:00
|
|
|
else if (Type == ELF::SHT_FINI_ARRAY)
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "fini_array";
|
2011-01-23 12:28:49 +08:00
|
|
|
else if (Type == ELF::SHT_PREINIT_ARRAY)
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "preinit_array";
|
2011-01-23 12:28:49 +08:00
|
|
|
else if (Type == ELF::SHT_NOBITS)
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "nobits";
|
2011-01-23 12:28:49 +08:00
|
|
|
else if (Type == ELF::SHT_NOTE)
|
2010-12-27 05:30:59 +08:00
|
|
|
OS << "note";
|
2011-01-23 12:28:49 +08:00
|
|
|
else if (Type == ELF::SHT_PROGBITS)
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "progbits";
|
2015-11-06 23:30:45 +08:00
|
|
|
else if (Type == ELF::SHT_X86_64_UNWIND)
|
|
|
|
OS << "unwind";
|
2017-03-10 16:22:20 +08:00
|
|
|
else if (Type == ELF::SHT_MIPS_DWARF)
|
|
|
|
// Print hex value of the flag while we do not have
|
|
|
|
// any standard symbolic representation of the flag.
|
|
|
|
OS << "0x7000001e";
|
2017-06-15 02:52:12 +08:00
|
|
|
else if (Type == ELF::SHT_LLVM_ODRTAB)
|
|
|
|
OS << "llvm_odrtab";
|
2018-01-31 00:29:29 +08:00
|
|
|
else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS)
|
|
|
|
OS << "llvm_linker_options";
|
[MC] Add assembler support for .cg_profile.
Object FIle Representation
At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like:
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight).
Differential Revision: https://reviews.llvm.org/D44965
llvm-svn: 333823
2018-06-03 00:33:01 +08:00
|
|
|
else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
|
|
|
|
OS << "llvm_call_graph_profile";
|
2017-03-10 16:22:13 +08:00
|
|
|
else
|
|
|
|
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
|
|
|
|
" for section " + getSectionName());
|
2010-11-10 07:42:07 +08:00
|
|
|
|
|
|
|
if (EntrySize) {
|
2011-01-23 12:43:11 +08:00
|
|
|
assert(Flags & ELF::SHF_MERGE);
|
2010-11-10 07:42:07 +08:00
|
|
|
OS << "," << EntrySize;
|
2009-08-13 13:07:35 +08:00
|
|
|
}
|
2010-11-10 07:42:07 +08:00
|
|
|
|
2013-11-13 22:01:59 +08:00
|
|
|
if (Flags & ELF::SHF_GROUP) {
|
|
|
|
OS << ",";
|
|
|
|
printName(OS, Group->getName());
|
|
|
|
OS << ",comdat";
|
|
|
|
}
|
2015-02-18 04:48:01 +08:00
|
|
|
|
2017-03-15 03:28:51 +08:00
|
|
|
if (Flags & ELF::SHF_LINK_ORDER) {
|
|
|
|
assert(AssociatedSymbol);
|
|
|
|
OS << ",";
|
|
|
|
printName(OS, AssociatedSymbol->getName());
|
|
|
|
}
|
|
|
|
|
2015-04-05 02:02:01 +08:00
|
|
|
if (isUnique())
|
2015-04-07 00:34:41 +08:00
|
|
|
OS << ",unique," << UniqueID;
|
2015-02-18 04:48:01 +08:00
|
|
|
|
2009-08-13 13:07:35 +08:00
|
|
|
OS << '\n';
|
2013-04-18 05:18:16 +08:00
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
if (Subsection) {
|
|
|
|
OS << "\t.subsection\t";
|
|
|
|
Subsection->print(OS, &MAI);
|
|
|
|
OS << '\n';
|
|
|
|
}
|
2009-08-13 13:07:35 +08:00
|
|
|
}
|
|
|
|
|
2010-10-05 01:32:41 +08:00
|
|
|
bool MCSectionELF::UseCodeAlign() const {
|
2011-01-23 12:43:11 +08:00
|
|
|
return getFlags() & ELF::SHF_EXECINSTR;
|
2010-10-05 01:32:41 +08:00
|
|
|
}
|
|
|
|
|
2010-11-18 04:03:54 +08:00
|
|
|
bool MCSectionELF::isVirtualSection() const {
|
2011-01-23 12:28:49 +08:00
|
|
|
return getType() == ELF::SHT_NOBITS;
|
2010-11-18 04:03:54 +08:00
|
|
|
}
|