Line data Source code
1 : //===- FaultMaps.cpp ------------------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/CodeGen/FaultMaps.h"
11 : #include "llvm/ADT/Twine.h"
12 : #include "llvm/CodeGen/AsmPrinter.h"
13 : #include "llvm/MC/MCContext.h"
14 : #include "llvm/MC/MCExpr.h"
15 : #include "llvm/MC/MCObjectFileInfo.h"
16 : #include "llvm/MC/MCStreamer.h"
17 : #include "llvm/Support/Debug.h"
18 : #include "llvm/Support/ErrorHandling.h"
19 : #include "llvm/Support/Format.h"
20 : #include "llvm/Support/raw_ostream.h"
21 :
22 : using namespace llvm;
23 :
24 : #define DEBUG_TYPE "faultmaps"
25 :
26 : static const int FaultMapVersion = 1;
27 : const char *FaultMaps::WFMP = "Fault Maps: ";
28 :
29 29740 : FaultMaps::FaultMaps(AsmPrinter &AP) : AP(AP) {}
30 :
31 26 : void FaultMaps::recordFaultingOp(FaultKind FaultTy,
32 : const MCSymbol *HandlerLabel) {
33 26 : MCContext &OutContext = AP.OutStreamer->getContext();
34 26 : MCSymbol *FaultingLabel = OutContext.createTempSymbol();
35 :
36 52 : AP.OutStreamer->EmitLabel(FaultingLabel);
37 :
38 : const MCExpr *FaultingOffset = MCBinaryExpr::createSub(
39 : MCSymbolRefExpr::create(FaultingLabel, OutContext),
40 26 : MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
41 :
42 : const MCExpr *HandlerOffset = MCBinaryExpr::createSub(
43 : MCSymbolRefExpr::create(HandlerLabel, OutContext),
44 26 : MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
45 :
46 26 : FunctionInfos[AP.CurrentFnSym].emplace_back(FaultTy, FaultingOffset,
47 : HandlerOffset);
48 26 : }
49 :
50 14006 : void FaultMaps::serializeToFaultMapSection() {
51 14006 : if (FunctionInfos.empty())
52 : return;
53 :
54 4 : MCContext &OutContext = AP.OutStreamer->getContext();
55 : MCStreamer &OS = *AP.OutStreamer;
56 :
57 : // Create the section.
58 : MCSection *FaultMapSection =
59 4 : OutContext.getObjectFileInfo()->getFaultMapSection();
60 4 : OS.SwitchSection(FaultMapSection);
61 :
62 : // Emit a dummy symbol to force section inclusion.
63 8 : OS.EmitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
64 :
65 : LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");
66 :
67 : // Header
68 4 : OS.EmitIntValue(FaultMapVersion, 1); // Version.
69 4 : OS.EmitIntValue(0, 1); // Reserved.
70 4 : OS.EmitIntValue(0, 2); // Reserved.
71 :
72 : LLVM_DEBUG(dbgs() << WFMP << "#functions = " << FunctionInfos.size() << "\n");
73 8 : OS.EmitIntValue(FunctionInfos.size(), 4);
74 :
75 : LLVM_DEBUG(dbgs() << WFMP << "functions:\n");
76 :
77 29 : for (const auto &FFI : FunctionInfos)
78 25 : emitFunctionInfo(FFI.first, FFI.second);
79 : }
80 :
81 25 : void FaultMaps::emitFunctionInfo(const MCSymbol *FnLabel,
82 : const FunctionFaultInfos &FFI) {
83 25 : MCStreamer &OS = *AP.OutStreamer;
84 :
85 : LLVM_DEBUG(dbgs() << WFMP << " function addr: " << *FnLabel << "\n");
86 25 : OS.EmitSymbolValue(FnLabel, 8);
87 :
88 : LLVM_DEBUG(dbgs() << WFMP << " #faulting PCs: " << FFI.size() << "\n");
89 50 : OS.EmitIntValue(FFI.size(), 4);
90 :
91 25 : OS.EmitIntValue(0, 4); // Reserved
92 :
93 51 : for (auto &Fault : FFI) {
94 : LLVM_DEBUG(dbgs() << WFMP << " fault type: "
95 : << faultTypeToString(Fault.Kind) << "\n");
96 26 : OS.EmitIntValue(Fault.Kind, 4);
97 :
98 : LLVM_DEBUG(dbgs() << WFMP << " faulting PC offset: "
99 : << *Fault.FaultingOffsetExpr << "\n");
100 26 : OS.EmitValue(Fault.FaultingOffsetExpr, 4);
101 :
102 : LLVM_DEBUG(dbgs() << WFMP << " fault handler PC offset: "
103 : << *Fault.HandlerOffsetExpr << "\n");
104 26 : OS.EmitValue(Fault.HandlerOffsetExpr, 4);
105 : }
106 25 : }
107 :
108 18 : const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT) {
109 18 : switch (FT) {
110 0 : default:
111 0 : llvm_unreachable("unhandled fault type!");
112 : case FaultMaps::FaultingLoad:
113 : return "FaultingLoad";
114 0 : case FaultMaps::FaultingLoadStore:
115 0 : return "FaultingLoadStore";
116 2 : case FaultMaps::FaultingStore:
117 2 : return "FaultingStore";
118 : }
119 : }
120 :
121 18 : raw_ostream &llvm::
122 : operator<<(raw_ostream &OS,
123 : const FaultMapParser::FunctionFaultInfoAccessor &FFI) {
124 18 : OS << "Fault kind: "
125 36 : << FaultMaps::faultTypeToString((FaultMaps::FaultKind)FFI.getFaultKind())
126 18 : << ", faulting PC offset: " << FFI.getFaultingPCOffset()
127 18 : << ", handling PC offset: " << FFI.getHandlerPCOffset();
128 18 : return OS;
129 : }
130 :
131 18 : raw_ostream &llvm::
132 : operator<<(raw_ostream &OS, const FaultMapParser::FunctionInfoAccessor &FI) {
133 18 : OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8)
134 18 : << ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n";
135 36 : for (unsigned i = 0, e = FI.getNumFaultingPCs(); i != e; ++i)
136 36 : OS << FI.getFunctionFaultInfoAt(i) << "\n";
137 18 : return OS;
138 : }
139 :
140 3 : raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) {
141 3 : OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n";
142 3 : OS << "NumFunctions: " << FMP.getNumFunctions() << "\n";
143 :
144 6 : if (FMP.getNumFunctions() == 0)
145 : return OS;
146 :
147 3 : FaultMapParser::FunctionInfoAccessor FI;
148 :
149 21 : for (unsigned i = 0, e = FMP.getNumFunctions(); i != e; ++i) {
150 18 : FI = (i == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo();
151 18 : OS << FI;
152 : }
153 :
154 : return OS;
155 : }
|