1//===----------------------------------------------------------------------===//
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/// \file
10/// LFI-specific MC implementation.
11///
12//===----------------------------------------------------------------------===//
13
14#include "llvm/MC/MCLFI.h"
15#include "MCCLOptions.h"
16#include "llvm/BinaryFormat/ELF.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCInstrInfo.h"
19#include "llvm/MC/MCLFIRewriter.h"
20#include "llvm/MC/MCRegisterInfo.h"
21#include "llvm/MC/MCSectionELF.h"
22#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/TargetRegistry.h"
24#include "llvm/Support/Alignment.h"
25#include "llvm/TargetParser/Triple.h"
26
27using namespace llvm;
28
29const char NoteNamespace[] = "LFI";
30
31constexpr unsigned X86BundleSize = 32;
32
33void llvm::initializeLFIMCStreamer(MCStreamer &Streamer, MCContext &Ctx,
34 const Triple &TheTriple) {
35 assert(TheTriple.isLFI());
36
37 std::string Error;
38 const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, Error);
39
40 // Create the target-specific MCLFIRewriter.
41 assert(TheTarget != nullptr);
42 if (MCCLOptions::Global.lfi_enable_rewriter) {
43 auto MRI =
44 std::unique_ptr<MCRegisterInfo>(TheTarget->createMCRegInfo(TT: TheTriple));
45 auto MII = std::unique_ptr<MCInstrInfo>(TheTarget->createMCInstrInfo());
46 Streamer.setLFIRewriter(std::unique_ptr<MCLFIRewriter>(
47 TheTarget->createMCLFIRewriter(Ctx, RegInfo: std::move(MRI), InstInfo: std::move(MII))));
48 }
49}
50
51void llvm::emitLFIBundleAlign(MCStreamer &Streamer, MCContext &Ctx) {
52 const Triple &TheTriple = Ctx.getTargetTriple();
53 assert(TheTriple.isLFI());
54 if (TheTriple.getArch() == Triple::x86_64)
55 Streamer.emitBundleAlignMode(Alignment: Align(X86BundleSize));
56}
57
58void llvm::emitLFINoteSection(MCStreamer &Streamer, MCContext &Ctx) {
59 const Triple &TheTriple = Ctx.getTargetTriple();
60 assert(TheTriple.isLFI());
61
62 const char *NoteName;
63 const char *NoteArch;
64 switch (TheTriple.getArch()) {
65 case Triple::aarch64:
66 NoteName = ".note.LFI.ABI.aarch64";
67 NoteArch = "aarch64";
68 break;
69 case Triple::x86_64:
70 NoteName = ".note.LFI.ABI.x86_64";
71 NoteArch = "x86_64";
72 break;
73 default:
74 reportFatalUsageError(reason: "Unsupported architecture for LFI");
75 }
76
77 // Emit an ELF Note section in its own COMDAT group which identifies LFI
78 // object files.
79 MCSectionELF *Note = Ctx.getELFSection(Section: NoteName, Type: ELF::SHT_NOTE,
80 Flags: ELF::SHF_ALLOC | ELF::SHF_GROUP, EntrySize: 0,
81 Group: NoteName, /*IsComdat=*/true);
82
83 Streamer.switchSection(Section: Note);
84 Streamer.emitIntValue(Value: strlen(s: NoteNamespace) + 1, Size: 4);
85 Streamer.emitIntValue(Value: strlen(s: NoteArch) + 1, Size: 4);
86 Streamer.emitIntValue(Value: ELF::NT_VERSION, Size: 4);
87 Streamer.emitBytes(Data: NoteNamespace);
88 Streamer.emitIntValue(Value: 0, Size: 1); // NUL terminator
89 Streamer.emitValueToAlignment(Alignment: Align(4));
90 Streamer.emitBytes(Data: NoteArch);
91 Streamer.emitIntValue(Value: 0, Size: 1); // NUL terminator
92 Streamer.emitValueToAlignment(Alignment: Align(4));
93}
94