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 "llvm/BinaryFormat/ELF.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCInstrInfo.h"
18#include "llvm/MC/MCRegisterInfo.h"
19#include "llvm/MC/MCSectionELF.h"
20#include "llvm/MC/MCStreamer.h"
21#include "llvm/MC/TargetRegistry.h"
22#include "llvm/Support/Alignment.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/TargetParser/Triple.h"
25
26static const char NoteNamespace[] = "LFI";
27
28namespace llvm {
29
30cl::opt<bool> FlagEnableRewriting("lfi-enable-rewriter",
31 cl::desc("Enable rewriting for LFI."),
32 cl::init(Val: true));
33
34void initializeLFIMCStreamer(MCStreamer &Streamer, MCContext &Ctx,
35 const Triple &TheTriple) {
36 assert(TheTriple.isLFI());
37 const char *NoteName;
38 const char *NoteArch;
39 switch (TheTriple.getArch()) {
40 case Triple::aarch64:
41 NoteName = ".note.LFI.ABI.aarch64";
42 NoteArch = "aarch64";
43 break;
44 default:
45 reportFatalUsageError(reason: "Unsupported architecture for LFI");
46 }
47
48 std::string Error; // empty
49 const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, Error);
50
51 // Create the Target specific MCLFIRewriter.
52 assert(TheTarget != nullptr);
53 if (FlagEnableRewriting) {
54 TheTarget->createMCLFIRewriter(
55 S&: Streamer,
56 RegInfo: std::unique_ptr<MCRegisterInfo>(TheTarget->createMCRegInfo(TT: TheTriple)),
57 InstInfo: std::unique_ptr<MCInstrInfo>(TheTarget->createMCInstrInfo()));
58 }
59
60 // Emit an ELF Note section in its own COMDAT group which identifies LFI
61 // object files.
62 MCSectionELF *Note = Ctx.getELFSection(Section: NoteName, Type: ELF::SHT_NOTE,
63 Flags: ELF::SHF_ALLOC | ELF::SHF_GROUP, EntrySize: 0,
64 Group: NoteName, /*IsComdat=*/true);
65
66 Streamer.pushSection();
67 Streamer.switchSection(Section: Note);
68 Streamer.emitIntValue(Value: strlen(s: NoteNamespace) + 1, Size: 4);
69 Streamer.emitIntValue(Value: strlen(s: NoteArch) + 1, Size: 4);
70 Streamer.emitIntValue(Value: ELF::NT_VERSION, Size: 4);
71 Streamer.emitBytes(Data: NoteNamespace);
72 Streamer.emitIntValue(Value: 0, Size: 1); // NUL terminator
73 Streamer.emitValueToAlignment(Alignment: Align(4));
74 Streamer.emitBytes(Data: NoteArch);
75 Streamer.emitIntValue(Value: 0, Size: 1); // NUL terminator
76 Streamer.emitValueToAlignment(Alignment: Align(4));
77 Streamer.popSection();
78}
79
80} // namespace llvm
81