1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2017 Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker *
8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker *
10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker */
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker #include <map>
18*387f9dfdSAndroid Build Coastguard Worker #include <string>
19*387f9dfdSAndroid Build Coastguard Worker #include <tuple>
20*387f9dfdSAndroid Build Coastguard Worker #include <vector>
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 15
23*387f9dfdSAndroid Build Coastguard Worker #include <llvm/DebugInfo/DWARF/DWARFCompileUnit.h>
24*387f9dfdSAndroid Build Coastguard Worker #endif
25*387f9dfdSAndroid Build Coastguard Worker #include <llvm/DebugInfo/DWARF/DWARFContext.h>
26*387f9dfdSAndroid Build Coastguard Worker #include <llvm/DebugInfo/DWARF/DWARFDebugLine.h>
27*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/Module.h>
28*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCAsmInfo.h>
29*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCContext.h>
30*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCDisassembler/MCDisassembler.h>
31*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCInstPrinter.h>
32*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCInstrInfo.h>
33*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCObjectFileInfo.h>
34*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCRegisterInfo.h>
35*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 15
36*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/MCSubtargetInfo.h>
37*387f9dfdSAndroid Build Coastguard Worker #endif
38*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 14
39*387f9dfdSAndroid Build Coastguard Worker #include <llvm/MC/TargetRegistry.h>
40*387f9dfdSAndroid Build Coastguard Worker #else
41*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Support/TargetRegistry.h>
42*387f9dfdSAndroid Build Coastguard Worker #endif
43*387f9dfdSAndroid Build Coastguard Worker
44*387f9dfdSAndroid Build Coastguard Worker #include "bcc_debug.h"
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Worker namespace ebpf {
47*387f9dfdSAndroid Build Coastguard Worker
48*387f9dfdSAndroid Build Coastguard Worker // ld_pseudo can only be disassembled properly
49*387f9dfdSAndroid Build Coastguard Worker // in llvm 6.0, so having this workaround now
50*387f9dfdSAndroid Build Coastguard Worker // until disto llvm versions catch up
51*387f9dfdSAndroid Build Coastguard Worker #define WORKAROUND_FOR_LD_PSEUDO
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Worker using std::get;
54*387f9dfdSAndroid Build Coastguard Worker using std::map;
55*387f9dfdSAndroid Build Coastguard Worker using std::string;
56*387f9dfdSAndroid Build Coastguard Worker using std::tuple;
57*387f9dfdSAndroid Build Coastguard Worker using std::vector;
58*387f9dfdSAndroid Build Coastguard Worker using namespace llvm;
59*387f9dfdSAndroid Build Coastguard Worker using DWARFLineTable = DWARFDebugLine::LineTable;
60*387f9dfdSAndroid Build Coastguard Worker
adjustInstSize(uint64_t & Size,uint8_t byte0,uint8_t byte1)61*387f9dfdSAndroid Build Coastguard Worker void SourceDebugger::adjustInstSize(uint64_t &Size, uint8_t byte0,
62*387f9dfdSAndroid Build Coastguard Worker uint8_t byte1) {
63*387f9dfdSAndroid Build Coastguard Worker #ifdef WORKAROUND_FOR_LD_PSEUDO
64*387f9dfdSAndroid Build Coastguard Worker bool isLittleEndian = mod_->getDataLayout().isLittleEndian();
65*387f9dfdSAndroid Build Coastguard Worker if (byte0 == 0x18 && ((isLittleEndian && (byte1 & 0xf) == 0x1) ||
66*387f9dfdSAndroid Build Coastguard Worker (!isLittleEndian && (byte1 & 0xf0) == 0x10)))
67*387f9dfdSAndroid Build Coastguard Worker Size = 16;
68*387f9dfdSAndroid Build Coastguard Worker #endif
69*387f9dfdSAndroid Build Coastguard Worker }
70*387f9dfdSAndroid Build Coastguard Worker
buildLineCache()71*387f9dfdSAndroid Build Coastguard Worker vector<string> SourceDebugger::buildLineCache() {
72*387f9dfdSAndroid Build Coastguard Worker vector<string> LineCache;
73*387f9dfdSAndroid Build Coastguard Worker size_t FileBufSize = mod_src_.size();
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker for (uint32_t start = 0, end = start; end < FileBufSize; end++)
76*387f9dfdSAndroid Build Coastguard Worker if (mod_src_[end] == '\n' || end == FileBufSize - 1 ||
77*387f9dfdSAndroid Build Coastguard Worker (mod_src_[end] == '\r' && mod_src_[end + 1] == '\n')) {
78*387f9dfdSAndroid Build Coastguard Worker // Not including the endline
79*387f9dfdSAndroid Build Coastguard Worker LineCache.push_back(string(mod_src_.substr(start, end - start)));
80*387f9dfdSAndroid Build Coastguard Worker if (mod_src_[end] == '\r')
81*387f9dfdSAndroid Build Coastguard Worker end++;
82*387f9dfdSAndroid Build Coastguard Worker start = end + 1;
83*387f9dfdSAndroid Build Coastguard Worker }
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker return LineCache;
86*387f9dfdSAndroid Build Coastguard Worker }
87*387f9dfdSAndroid Build Coastguard Worker
dumpSrcLine(const vector<string> & LineCache,const string & FileName,uint32_t Line,uint32_t & CurrentSrcLine,llvm::raw_ostream & os)88*387f9dfdSAndroid Build Coastguard Worker void SourceDebugger::dumpSrcLine(const vector<string> &LineCache,
89*387f9dfdSAndroid Build Coastguard Worker const string &FileName, uint32_t Line,
90*387f9dfdSAndroid Build Coastguard Worker uint32_t &CurrentSrcLine,
91*387f9dfdSAndroid Build Coastguard Worker llvm::raw_ostream &os) {
92*387f9dfdSAndroid Build Coastguard Worker if (Line != 0 && Line != CurrentSrcLine && Line < LineCache.size() &&
93*387f9dfdSAndroid Build Coastguard Worker FileName == mod_->getSourceFileName()) {
94*387f9dfdSAndroid Build Coastguard Worker os << "; " << StringRef(LineCache[Line - 1]).ltrim()
95*387f9dfdSAndroid Build Coastguard Worker << format(
96*387f9dfdSAndroid Build Coastguard Worker " // Line"
97*387f9dfdSAndroid Build Coastguard Worker "%4" PRIu64 "\n",
98*387f9dfdSAndroid Build Coastguard Worker Line);
99*387f9dfdSAndroid Build Coastguard Worker CurrentSrcLine = Line;
100*387f9dfdSAndroid Build Coastguard Worker }
101*387f9dfdSAndroid Build Coastguard Worker }
102*387f9dfdSAndroid Build Coastguard Worker
getDebugSections(StringMap<std::unique_ptr<MemoryBuffer>> & DebugSections)103*387f9dfdSAndroid Build Coastguard Worker void SourceDebugger::getDebugSections(
104*387f9dfdSAndroid Build Coastguard Worker StringMap<std::unique_ptr<MemoryBuffer>> &DebugSections) {
105*387f9dfdSAndroid Build Coastguard Worker for (auto section : sections_) {
106*387f9dfdSAndroid Build Coastguard Worker if (strncmp(section.first.c_str(), ".debug", 6) == 0) {
107*387f9dfdSAndroid Build Coastguard Worker StringRef SecData(reinterpret_cast<const char *>(get<0>(section.second)),
108*387f9dfdSAndroid Build Coastguard Worker get<1>(section.second));
109*387f9dfdSAndroid Build Coastguard Worker DebugSections[section.first.substr(1)] =
110*387f9dfdSAndroid Build Coastguard Worker MemoryBuffer::getMemBufferCopy(SecData);
111*387f9dfdSAndroid Build Coastguard Worker }
112*387f9dfdSAndroid Build Coastguard Worker }
113*387f9dfdSAndroid Build Coastguard Worker }
114*387f9dfdSAndroid Build Coastguard Worker
dump()115*387f9dfdSAndroid Build Coastguard Worker void SourceDebugger::dump() {
116*387f9dfdSAndroid Build Coastguard Worker string Error;
117*387f9dfdSAndroid Build Coastguard Worker string TripleStr(mod_->getTargetTriple());
118*387f9dfdSAndroid Build Coastguard Worker Triple TheTriple(TripleStr);
119*387f9dfdSAndroid Build Coastguard Worker const Target *T = TargetRegistry::lookupTarget(TripleStr, Error);
120*387f9dfdSAndroid Build Coastguard Worker if (!T) {
121*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: cannot get target\n";
122*387f9dfdSAndroid Build Coastguard Worker return;
123*387f9dfdSAndroid Build Coastguard Worker }
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TripleStr));
126*387f9dfdSAndroid Build Coastguard Worker if (!MRI) {
127*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: cannot get register info\n";
128*387f9dfdSAndroid Build Coastguard Worker return;
129*387f9dfdSAndroid Build Coastguard Worker }
130*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 10
131*387f9dfdSAndroid Build Coastguard Worker MCTargetOptions MCOptions;
132*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr, MCOptions));
133*387f9dfdSAndroid Build Coastguard Worker #else
134*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr));
135*387f9dfdSAndroid Build Coastguard Worker #endif
136*387f9dfdSAndroid Build Coastguard Worker if (!MAI) {
137*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: cannot get assembly info\n";
138*387f9dfdSAndroid Build Coastguard Worker return;
139*387f9dfdSAndroid Build Coastguard Worker }
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<MCSubtargetInfo> STI(
142*387f9dfdSAndroid Build Coastguard Worker T->createMCSubtargetInfo(TripleStr, "", ""));
143*387f9dfdSAndroid Build Coastguard Worker MCObjectFileInfo MOFI;
144*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 13
145*387f9dfdSAndroid Build Coastguard Worker MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), nullptr);
146*387f9dfdSAndroid Build Coastguard Worker Ctx.setObjectFileInfo(&MOFI);
147*387f9dfdSAndroid Build Coastguard Worker MOFI.initMCObjectFileInfo(Ctx, false, false);
148*387f9dfdSAndroid Build Coastguard Worker #else
149*387f9dfdSAndroid Build Coastguard Worker MCContext Ctx(MAI.get(), MRI.get(), &MOFI, nullptr);
150*387f9dfdSAndroid Build Coastguard Worker MOFI.InitMCObjectFileInfo(TheTriple, false, Ctx, false);
151*387f9dfdSAndroid Build Coastguard Worker #endif
152*387f9dfdSAndroid Build Coastguard Worker
153*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
154*387f9dfdSAndroid Build Coastguard Worker MCInstPrinter *IP = T->createMCInstPrinter(TheTriple, 0, *MAI, *MCII, *MRI);
155*387f9dfdSAndroid Build Coastguard Worker if (!IP) {
156*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: unable to create instruction printer\n";
157*387f9dfdSAndroid Build Coastguard Worker return;
158*387f9dfdSAndroid Build Coastguard Worker }
159*387f9dfdSAndroid Build Coastguard Worker
160*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<const MCDisassembler> DisAsm(
161*387f9dfdSAndroid Build Coastguard Worker T->createMCDisassembler(*STI, Ctx));
162*387f9dfdSAndroid Build Coastguard Worker if (!DisAsm) {
163*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: no disassembler\n";
164*387f9dfdSAndroid Build Coastguard Worker return;
165*387f9dfdSAndroid Build Coastguard Worker }
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Worker // Set up the dwarf debug context
168*387f9dfdSAndroid Build Coastguard Worker StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
169*387f9dfdSAndroid Build Coastguard Worker getDebugSections(DebugSections);
170*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<DWARFContext> DwarfCtx =
171*387f9dfdSAndroid Build Coastguard Worker DWARFContext::create(DebugSections, 8);
172*387f9dfdSAndroid Build Coastguard Worker if (!DwarfCtx) {
173*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: dwarf context creation failed\n";
174*387f9dfdSAndroid Build Coastguard Worker return;
175*387f9dfdSAndroid Build Coastguard Worker }
176*387f9dfdSAndroid Build Coastguard Worker
177*387f9dfdSAndroid Build Coastguard Worker // bcc has only one compilation unit
178*387f9dfdSAndroid Build Coastguard Worker // getCompileUnitAtIndex() was gone in llvm 8.0 (https://reviews.llvm.org/D49741)
179*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 8
180*387f9dfdSAndroid Build Coastguard Worker DWARFCompileUnit *CU = cast<DWARFCompileUnit>(DwarfCtx->getUnitAtIndex(0));
181*387f9dfdSAndroid Build Coastguard Worker #else
182*387f9dfdSAndroid Build Coastguard Worker DWARFCompileUnit *CU = DwarfCtx->getCompileUnitAtIndex(0);
183*387f9dfdSAndroid Build Coastguard Worker #endif
184*387f9dfdSAndroid Build Coastguard Worker if (!CU) {
185*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: dwarf context failed to get compile unit\n";
186*387f9dfdSAndroid Build Coastguard Worker return;
187*387f9dfdSAndroid Build Coastguard Worker }
188*387f9dfdSAndroid Build Coastguard Worker
189*387f9dfdSAndroid Build Coastguard Worker const DWARFLineTable *LineTable = DwarfCtx->getLineTableForUnit(CU);
190*387f9dfdSAndroid Build Coastguard Worker if (!LineTable) {
191*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: dwarf context failed to get line table\n";
192*387f9dfdSAndroid Build Coastguard Worker return;
193*387f9dfdSAndroid Build Coastguard Worker }
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker // Build LineCache for later source code printing
196*387f9dfdSAndroid Build Coastguard Worker vector<string> LineCache = buildLineCache();
197*387f9dfdSAndroid Build Coastguard Worker
198*387f9dfdSAndroid Build Coastguard Worker // Start to disassemble with source code annotation section by section
199*387f9dfdSAndroid Build Coastguard Worker prog_func_info_.for_each_func([&](std::string func_name, FuncInfo &info) {
200*387f9dfdSAndroid Build Coastguard Worker MCDisassembler::DecodeStatus S;
201*387f9dfdSAndroid Build Coastguard Worker MCInst Inst;
202*387f9dfdSAndroid Build Coastguard Worker uint64_t Size;
203*387f9dfdSAndroid Build Coastguard Worker uint8_t *FuncStart = info.start_;
204*387f9dfdSAndroid Build Coastguard Worker uint64_t FuncSize = info.size_;
205*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 9
206*387f9dfdSAndroid Build Coastguard Worker auto section = sections_.find(info.section_);
207*387f9dfdSAndroid Build Coastguard Worker if (section == sections_.end()) {
208*387f9dfdSAndroid Build Coastguard Worker errs() << "Debug Error: no section entry for section " << info.section_
209*387f9dfdSAndroid Build Coastguard Worker << '\n';
210*387f9dfdSAndroid Build Coastguard Worker return;
211*387f9dfdSAndroid Build Coastguard Worker }
212*387f9dfdSAndroid Build Coastguard Worker unsigned SectionID = get<2>(section->second);
213*387f9dfdSAndroid Build Coastguard Worker #endif
214*387f9dfdSAndroid Build Coastguard Worker ArrayRef<uint8_t> Data(FuncStart, FuncSize);
215*387f9dfdSAndroid Build Coastguard Worker uint32_t CurrentSrcLine = 0;
216*387f9dfdSAndroid Build Coastguard Worker
217*387f9dfdSAndroid Build Coastguard Worker errs() << "Disassembly of function " << func_name << "\n";
218*387f9dfdSAndroid Build Coastguard Worker
219*387f9dfdSAndroid Build Coastguard Worker string src_dbg_str;
220*387f9dfdSAndroid Build Coastguard Worker llvm::raw_string_ostream os(src_dbg_str);
221*387f9dfdSAndroid Build Coastguard Worker for (uint64_t Index = 0; Index < FuncSize; Index += Size) {
222*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 10
223*387f9dfdSAndroid Build Coastguard Worker S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index, nulls());
224*387f9dfdSAndroid Build Coastguard Worker #else
225*387f9dfdSAndroid Build Coastguard Worker S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index, nulls(),
226*387f9dfdSAndroid Build Coastguard Worker nulls());
227*387f9dfdSAndroid Build Coastguard Worker #endif
228*387f9dfdSAndroid Build Coastguard Worker if (S != MCDisassembler::Success) {
229*387f9dfdSAndroid Build Coastguard Worker os << "Debug Error: disassembler failed: " << std::to_string(S) << '\n';
230*387f9dfdSAndroid Build Coastguard Worker break;
231*387f9dfdSAndroid Build Coastguard Worker } else {
232*387f9dfdSAndroid Build Coastguard Worker DILineInfo LineInfo;
233*387f9dfdSAndroid Build Coastguard Worker
234*387f9dfdSAndroid Build Coastguard Worker LineTable->getFileLineInfoForAddress(
235*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 9
236*387f9dfdSAndroid Build Coastguard Worker {(uint64_t)FuncStart + Index, SectionID},
237*387f9dfdSAndroid Build Coastguard Worker #else
238*387f9dfdSAndroid Build Coastguard Worker (uint64_t)FuncStart + Index,
239*387f9dfdSAndroid Build Coastguard Worker #endif
240*387f9dfdSAndroid Build Coastguard Worker CU->getCompilationDir(),
241*387f9dfdSAndroid Build Coastguard Worker DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, LineInfo);
242*387f9dfdSAndroid Build Coastguard Worker
243*387f9dfdSAndroid Build Coastguard Worker adjustInstSize(Size, Data[Index], Data[Index + 1]);
244*387f9dfdSAndroid Build Coastguard Worker dumpSrcLine(LineCache, LineInfo.FileName, LineInfo.Line, CurrentSrcLine,
245*387f9dfdSAndroid Build Coastguard Worker os);
246*387f9dfdSAndroid Build Coastguard Worker os << format("%4" PRIu64 ":", Index >> 3) << '\t';
247*387f9dfdSAndroid Build Coastguard Worker dumpBytes(Data.slice(Index, Size), os);
248*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 10
249*387f9dfdSAndroid Build Coastguard Worker IP->printInst(&Inst, 0, "", *STI, os);
250*387f9dfdSAndroid Build Coastguard Worker #else
251*387f9dfdSAndroid Build Coastguard Worker IP->printInst(&Inst, os, "", *STI);
252*387f9dfdSAndroid Build Coastguard Worker #endif
253*387f9dfdSAndroid Build Coastguard Worker os << '\n';
254*387f9dfdSAndroid Build Coastguard Worker }
255*387f9dfdSAndroid Build Coastguard Worker }
256*387f9dfdSAndroid Build Coastguard Worker os.flush();
257*387f9dfdSAndroid Build Coastguard Worker errs() << src_dbg_str << '\n';
258*387f9dfdSAndroid Build Coastguard Worker src_dbg_fmap_[func_name] = src_dbg_str;
259*387f9dfdSAndroid Build Coastguard Worker });
260*387f9dfdSAndroid Build Coastguard Worker }
261*387f9dfdSAndroid Build Coastguard Worker
262*387f9dfdSAndroid Build Coastguard Worker } // namespace ebpf
263