LLVM: lib/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

14

18

19#define DEBUG_TYPE "orc"

20

21using namespace llvm;

24

25namespace {

26

27

28

29

32 bool absolute) {

34 uint8_t EhFramePtrEnc = 0;

35 if (absolute) {

37 } else {

39 }

42

43 uint32_t EHFrameRelocation = 0;

44

45

46

47

48

49

50

51 size_t HeaderSize =

52 (sizeof(Version) + sizeof(EhFramePtrEnc) + sizeof(FDECountEnc) +

53 sizeof(TableEnc) +

54 (absolute ? sizeof(uint64_t) : sizeof(EHFrameRelocation)));

55 std::string HeaderContent(HeaderSize, '\0');

58 reinterpret_cast<uint8_t *>(HeaderContent.data()), HeaderSize),

61 return std::move(Err);

62 if (auto Err = Writer.writeInteger(EhFramePtrEnc))

63 return std::move(Err);

64 if (auto Err = Writer.writeInteger(FDECountEnc))

65 return std::move(Err);

67 return std::move(Err);

68 if (absolute) {

70 if (auto Err = Writer.writeInteger(EHFrameAddr))

71 return std::move(Err);

72 } else {

73 if (auto Err = Writer.writeInteger(EHFrameRelocation))

74 return std::move(Err);

75 }

76 return HeaderContent;

77}

78

79constexpr StringRef RegisterPerfStartSymbolName =

80 "llvm_orc_registerJITLoaderPerfStart";

81constexpr StringRef RegisterPerfEndSymbolName =

82 "llvm_orc_registerJITLoaderPerfEnd";

83constexpr StringRef RegisterPerfImplSymbolName =

84 "llvm_orc_registerJITLoaderPerfImpl";

85

87getCodeLoadRecord(const Symbol &Sym, std::atomic<uint64_t> &CodeIndex) {

89 auto Name = *Sym.getName();

93

95

100 Record.CodeIndex = CodeIndex++;

101 Record.Name = Name.str();

102

103 Record.Prefix.TotalSize =

104 (2 * sizeof(uint32_t)

105 + sizeof(uint64_t)

106 + 2 * sizeof(uint32_t)

107 + 4 * sizeof(uint64_t)

108 + Name.size() + 1

109 + Record.CodeSize

110 );

112}

113

114static std::optional

121 << " at address " << Addr.getValue() << " with size "

122 << Size << "\n"

126 if (LInfo.empty()) {

127

129 return std::nullopt;

130 }

134 for (const auto &Entry : LInfo) {

135 auto Addr = Entry.first;

136

137

138

139 Addr += 0x40;

140 Record.Entries.push_back({Addr, Entry.second.Line,

141 Entry.second.Discriminator,

142 Entry.second.FileName});

143 }

144 size_t EntriesBytes = (2

145 + 2

146 ) *

148 for (const auto &Entry : Record.Entries) {

149 EntriesBytes +=

150 sizeof(uint64_t) + 2 * sizeof(uint32_t);

151 EntriesBytes += Entry.Name.size() + 1;

152 }

153 Record.Prefix.TotalSize = EntriesBytes;

155 << "Total size: " << Record.Prefix.TotalSize << "\n"

156 << "Nr entries: " << Record.Entries.size() << "\n");

158}

159

164 Record.Prefix.TotalSize = 0;

165 auto Eh_frame = G.findSectionByName(".eh_frame");

166 if (!Eh_frame) {

167 LLVM_DEBUG(dbgs() << "No .eh_frame section found\n");

169 }

170 if (G.getTargetTriple().isOSBinFormatELF()) {

171 LLVM_DEBUG(dbgs() << "Not an ELF file, will not emit unwinding info\n");

173 }

175 auto EHFrameSize = SR.getSize();

176 auto Eh_frame_hdr = G.findSectionByName(".eh_frame_hdr");

177 if (!Eh_frame_hdr) {

179 auto Hdr = createX64EHFrameHeader(*Eh_frame, G.getEndianness(), true);

180 if (!Hdr)

181 return Hdr.takeError();

182 Record.EHFrameHdr = std::move(*Hdr);

183 } else {

184 LLVM_DEBUG(dbgs() << "No .eh_frame_hdr section found\n");

186 }

187 Record.EHFrameHdrAddr = 0;

188 Record.EHFrameHdrSize = Record.EHFrameHdr.size();

189 Record.UnwindDataSize = EHFrameSize + Record.EHFrameHdrSize;

190 Record.MappedSize = 0;

191 } else {

194 Record.EHFrameHdrSize = SR.getSize();

195 Record.UnwindDataSize = EHFrameSize + Record.EHFrameHdrSize;

197 }

199 Record.Prefix.TotalSize =

200 (2 * sizeof(uint32_t)

201 + sizeof(uint64_t)

202 +

203 3 * sizeof(uint64_t)

204 + Record.UnwindDataSize

205 );

207 << "Total size: " << Record.Prefix.TotalSize << "\n"

208 << "Unwind size: " << Record.UnwindDataSize << "\n"

209 << "EHFrame size: " << EHFrameSize << "\n"

210 << "EHFrameHdr size: " << Record.EHFrameHdrSize << "\n");

212}

213

215 std::atomic<uint64_t> &CodeIndex,

217 std::unique_ptr DC;

219 if (EmitDebugInfo) {

221 if (!EDC) {

223 EmitDebugInfo = false;

224 } else {

225 DC = std::move(EDC->first);

226 DCBacking = std::move(EDC->second);

227 }

228 }

230 for (auto Sym : G.defined_symbols()) {

232 continue;

233 if (EmitDebugInfo) {

234 auto DebugInfo = getDebugInfoRecord(*Sym, *DC);

237 }

238 Batch.CodeLoadRecords.push_back(getCodeLoadRecord(*Sym, CodeIndex));

239 }

241 auto UWR = getUnwindingRecord(G);

242 if (!UWR) {

244 } else {

246 }

247 } else {

249 }

250 return Batch;

251}

252}

253

258 bool EmitDebugInfo, bool EmitUnwindInfo)

259 : EPC(EPC), RegisterPerfStartAddr(RegisterPerfStartAddr),

260 RegisterPerfEndAddr(RegisterPerfEndAddr),

261 RegisterPerfImplAddr(RegisterPerfImplAddr), CodeIndex(0),

262 EmitDebugInfo(EmitDebugInfo), EmitUnwindInfo(EmitUnwindInfo) {

263 cantFail(EPC.callSPSWrapper<void()>(RegisterPerfStartAddr));

264}

266 cantFail(EPC.callSPSWrapper<void()>(RegisterPerfEndAddr));

267}

268

273 auto Batch = getRecords(EPC.getExecutionSession(), G, CodeIndex,

274 EmitDebugInfo, EmitUnwindInfo);

275 G.allocActions().push_back(

278 RegisterPerfImplAddr, Batch)),

279 {}});

281 });

282}

283

286 bool EmitDebugInfo, bool EmitUnwindInfo) {

287 if (!EPC.getTargetTriple().isOSBinFormatELF()) {

289 "Perf support only available for ELF LinkGraphs!",

291 }

292 auto &ES = EPC.getExecutionSession();

296 {{ES.intern(RegisterPerfStartSymbolName), &StartAddr},

297 {ES.intern(RegisterPerfEndSymbolName), &EndAddr},

298 {ES.intern(RegisterPerfImplSymbolName), &ImplAddr}}))

299 return std::move(Err);

300 return std::make_unique(EPC, StartAddr, EndAddr, ImplAddr,

301 EmitDebugInfo, EmitUnwindInfo);

302}

static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)

Provides write only access to a subclass of WritableBinaryStream.

Error writeInteger(T Value)

Write the integer Value to the underlying stream in the specified endianness.

DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...

DILineInfoTable getLineInfoForAddressRange(object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

const RecordVal * getValue(const Init *Name) const

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

StringRef - Represent a constant reference to a string, i.e.

Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...

orc::ExecutorAddr getStart() const

Represents an object file section.

SectionOrdinal getOrdinal() const

Returns the ordinal for this section.

bool isCallable() const

Returns true is this symbol is callable.

const orc::SymbolStringPtr & getName() const

Returns the name of this symbol (empty if the symbol is anonymous).

orc::ExecutorAddr getAddress() const

Returns the address of this symbol.

Section & getSection() const

Return the Section for this Symbol (Symbol must be defined).

orc::ExecutorAddrDiff getSize() const

Returns the size of this symbol.

bool hasName() const

Returns true if this symbol has a name.

An ExecutionSession represents a running JIT program.

void reportError(Error Err)

Report a error for this execution session.

Represents an address in the executor process.

uint64_t getValue() const

ExecutorProcessControl supports interaction with a JIT target process.

Represents a JIT'd dynamic library.

Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...

void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &Config) override

Definition PerfSupportPlugin.cpp:269

~PerfSupportPlugin() override

Definition PerfSupportPlugin.cpp:265

static Expected< std::unique_ptr< PerfSupportPlugin > > Create(ExecutorProcessControl &EPC, JITDylib &JD, bool EmitDebugInfo, bool EmitUnwindInfo)

Definition PerfSupportPlugin.cpp:285

PerfSupportPlugin(ExecutorProcessControl &EPC, ExecutorAddr RegisterPerfStartAddr, ExecutorAddr RegisterPerfEndAddr, ExecutorAddr RegisterPerfImplAddr, bool EmitDebugInfo, bool EmitUnwindInfo)

Definition PerfSupportPlugin.cpp:254

JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)

Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...

@ JIT_CODE_UNWINDING_INFO

LLVM_ABI void lookupAndRecordAddrs(unique_function< void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder, std::vector< std::pair< SymbolStringPtr, ExecutorAddr * > > Pairs, SymbolLookupFlags LookupFlags=SymbolLookupFlags::RequiredSymbol)

Record addresses of the given symbols in the given ExecutorAddrs.

LLVM_ABI Expected< std::pair< std::unique_ptr< DWARFContext >, StringMap< std::unique_ptr< MemoryBuffer > > > > createDWARFContext(jitlink::LinkGraph &G)

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...

LinkGraphPassList PostFixupPasses

Post-fixup passes.

PerfJITRecordPrefix Prefix

std::vector< PerfJITDebugInfoRecord > DebugInfoRecords

PerfJITCodeUnwindingInfoRecord UnwindingRecord

std::vector< PerfJITCodeLoadRecord > CodeLoadRecords