1 //===- FaultMaps.cpp ------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/CodeGen/FaultMaps.h"
10 #include "llvm/ADT/Twine.h"
11 #include "llvm/CodeGen/AsmPrinter.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCObjectFileInfo.h"
15 #include "llvm/MC/MCStreamer.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/raw_ostream.h"
23 #define DEBUG_TYPE "faultmaps"
25 static const int FaultMapVersion
= 1;
26 const char *FaultMaps::WFMP
= "Fault Maps: ";
28 FaultMaps::FaultMaps(AsmPrinter
&AP
) : AP(AP
) {}
30 void FaultMaps::recordFaultingOp(FaultKind FaultTy
,
31 const MCSymbol
*HandlerLabel
) {
32 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
33 MCSymbol
*FaultingLabel
= OutContext
.createTempSymbol();
35 AP
.OutStreamer
->EmitLabel(FaultingLabel
);
37 const MCExpr
*FaultingOffset
= MCBinaryExpr::createSub(
38 MCSymbolRefExpr::create(FaultingLabel
, OutContext
),
39 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
41 const MCExpr
*HandlerOffset
= MCBinaryExpr::createSub(
42 MCSymbolRefExpr::create(HandlerLabel
, OutContext
),
43 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
45 FunctionInfos
[AP
.CurrentFnSym
].emplace_back(FaultTy
, FaultingOffset
,
49 void FaultMaps::serializeToFaultMapSection() {
50 if (FunctionInfos
.empty())
53 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
54 MCStreamer
&OS
= *AP
.OutStreamer
;
56 // Create the section.
57 MCSection
*FaultMapSection
=
58 OutContext
.getObjectFileInfo()->getFaultMapSection();
59 OS
.SwitchSection(FaultMapSection
);
61 // Emit a dummy symbol to force section inclusion.
62 OS
.EmitLabel(OutContext
.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
64 LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");
67 OS
.EmitIntValue(FaultMapVersion
, 1); // Version.
68 OS
.EmitIntValue(0, 1); // Reserved.
69 OS
.EmitIntValue(0, 2); // Reserved.
71 LLVM_DEBUG(dbgs() << WFMP
<< "#functions = " << FunctionInfos
.size() << "\n");
72 OS
.EmitIntValue(FunctionInfos
.size(), 4);
74 LLVM_DEBUG(dbgs() << WFMP
<< "functions:\n");
76 for (const auto &FFI
: FunctionInfos
)
77 emitFunctionInfo(FFI
.first
, FFI
.second
);
80 void FaultMaps::emitFunctionInfo(const MCSymbol
*FnLabel
,
81 const FunctionFaultInfos
&FFI
) {
82 MCStreamer
&OS
= *AP
.OutStreamer
;
84 LLVM_DEBUG(dbgs() << WFMP
<< " function addr: " << *FnLabel
<< "\n");
85 OS
.EmitSymbolValue(FnLabel
, 8);
87 LLVM_DEBUG(dbgs() << WFMP
<< " #faulting PCs: " << FFI
.size() << "\n");
88 OS
.EmitIntValue(FFI
.size(), 4);
90 OS
.EmitIntValue(0, 4); // Reserved
92 for (auto &Fault
: FFI
) {
93 LLVM_DEBUG(dbgs() << WFMP
<< " fault type: "
94 << faultTypeToString(Fault
.Kind
) << "\n");
95 OS
.EmitIntValue(Fault
.Kind
, 4);
97 LLVM_DEBUG(dbgs() << WFMP
<< " faulting PC offset: "
98 << *Fault
.FaultingOffsetExpr
<< "\n");
99 OS
.EmitValue(Fault
.FaultingOffsetExpr
, 4);
101 LLVM_DEBUG(dbgs() << WFMP
<< " fault handler PC offset: "
102 << *Fault
.HandlerOffsetExpr
<< "\n");
103 OS
.EmitValue(Fault
.HandlerOffsetExpr
, 4);
107 const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT
) {
110 llvm_unreachable("unhandled fault type!");
111 case FaultMaps::FaultingLoad
:
112 return "FaultingLoad";
113 case FaultMaps::FaultingLoadStore
:
114 return "FaultingLoadStore";
115 case FaultMaps::FaultingStore
:
116 return "FaultingStore";
121 operator<<(raw_ostream
&OS
,
122 const FaultMapParser::FunctionFaultInfoAccessor
&FFI
) {
124 << FaultMaps::faultTypeToString((FaultMaps::FaultKind
)FFI
.getFaultKind())
125 << ", faulting PC offset: " << FFI
.getFaultingPCOffset()
126 << ", handling PC offset: " << FFI
.getHandlerPCOffset();
131 operator<<(raw_ostream
&OS
, const FaultMapParser::FunctionInfoAccessor
&FI
) {
132 OS
<< "FunctionAddress: " << format_hex(FI
.getFunctionAddr(), 8)
133 << ", NumFaultingPCs: " << FI
.getNumFaultingPCs() << "\n";
134 for (unsigned i
= 0, e
= FI
.getNumFaultingPCs(); i
!= e
; ++i
)
135 OS
<< FI
.getFunctionFaultInfoAt(i
) << "\n";
139 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const FaultMapParser
&FMP
) {
140 OS
<< "Version: " << format_hex(FMP
.getFaultMapVersion(), 2) << "\n";
141 OS
<< "NumFunctions: " << FMP
.getNumFunctions() << "\n";
143 if (FMP
.getNumFunctions() == 0)
146 FaultMapParser::FunctionInfoAccessor FI
;
148 for (unsigned i
= 0, e
= FMP
.getNumFunctions(); i
!= e
; ++i
) {
149 FI
= (i
== 0) ? FMP
.getFirstFunctionInfo() : FI
.getNextFunctionInfo();