1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/debug/dwarf_line_no.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/pointers/raw_ref.h"
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #ifdef USE_SYMBOLIZE
10*6777b538SAndroid Build Coastguard Worker #include <algorithm>
11*6777b538SAndroid Build Coastguard Worker #include <charconv>
12*6777b538SAndroid Build Coastguard Worker #include <cstdint>
13*6777b538SAndroid Build Coastguard Worker #include <limits>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
16*6777b538SAndroid Build Coastguard Worker #include <string.h>
17*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #include "base/debug/buffered_dwarf_reader.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/third_party/symbolize/symbolize.h"
21*6777b538SAndroid Build Coastguard Worker #include "partition_alloc/pointers/raw_ptr.h"
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace base {
24*6777b538SAndroid Build Coastguard Worker namespace debug {
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker namespace {
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kMaxOffset = std::numeric_limits<uint64_t>::max();
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker // These numbers are suitable for most compilation units for chrome and
31*6777b538SAndroid Build Coastguard Worker // content_shell. If a compilation unit has bigger number of directories or
32*6777b538SAndroid Build Coastguard Worker // filenames, the additional directories/filenames will be ignored, and the
33*6777b538SAndroid Build Coastguard Worker // stack frames pointing to these directories/filenames will not get line
34*6777b538SAndroid Build Coastguard Worker // numbers. We can't set these numbers too big because they affect the size of
35*6777b538SAndroid Build Coastguard Worker // ProgramInfo which is allocated in the stack.
36*6777b538SAndroid Build Coastguard Worker constexpr int kMaxDirectories = 128;
37*6777b538SAndroid Build Coastguard Worker constexpr size_t kMaxFilenames = 512;
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker // DWARF-4 line number program header, section 6.2.4
40*6777b538SAndroid Build Coastguard Worker struct ProgramInfo {
41*6777b538SAndroid Build Coastguard Worker uint64_t header_length;
42*6777b538SAndroid Build Coastguard Worker uint64_t start_offset;
43*6777b538SAndroid Build Coastguard Worker uint64_t end_offset;
44*6777b538SAndroid Build Coastguard Worker uint8_t minimum_instruction_length;
45*6777b538SAndroid Build Coastguard Worker uint8_t maximum_operations_per_instruction;
46*6777b538SAndroid Build Coastguard Worker uint8_t default_is_stmt;
47*6777b538SAndroid Build Coastguard Worker int8_t line_base;
48*6777b538SAndroid Build Coastguard Worker uint8_t line_range;
49*6777b538SAndroid Build Coastguard Worker uint8_t opcode_base;
50*6777b538SAndroid Build Coastguard Worker uint8_t standard_opcode_lengths[256];
51*6777b538SAndroid Build Coastguard Worker uint8_t include_directories_table_offset;
52*6777b538SAndroid Build Coastguard Worker uint8_t file_names_table_offset;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker // Store the directories as offsets.
55*6777b538SAndroid Build Coastguard Worker int num_directories = 1;
56*6777b538SAndroid Build Coastguard Worker uint64_t directory_offsets[kMaxDirectories];
57*6777b538SAndroid Build Coastguard Worker uint64_t directory_sizes[kMaxDirectories];
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker // Store the file number table offsets.
60*6777b538SAndroid Build Coastguard Worker mutable unsigned int num_filenames = 1;
61*6777b538SAndroid Build Coastguard Worker mutable uint64_t filename_offsets[kMaxFilenames];
62*6777b538SAndroid Build Coastguard Worker mutable uint8_t filename_dirs[kMaxFilenames];
63*6777b538SAndroid Build Coastguard Worker
OpcodeToAdvancebase::debug::__anon7dac112c0111::ProgramInfo64*6777b538SAndroid Build Coastguard Worker unsigned int OpcodeToAdvance(uint8_t adjusted_opcode) const {
65*6777b538SAndroid Build Coastguard Worker // Special opcodes advance line numbers by an amount based on line_range
66*6777b538SAndroid Build Coastguard Worker // and opcode_base. This calculation is taken from 6.2.5.1.
67*6777b538SAndroid Build Coastguard Worker return static_cast<unsigned int>(adjusted_opcode) / line_range;
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker };
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // DWARF-4 line number program registers, section 6.2.2
72*6777b538SAndroid Build Coastguard Worker struct LineNumberRegisters {
73*6777b538SAndroid Build Coastguard Worker // During the line number program evaluation, some instructions perform a
74*6777b538SAndroid Build Coastguard Worker // "commit" which is when the registers have finished calculating a new row in
75*6777b538SAndroid Build Coastguard Worker // the line-number table. This callback is executed and can be viewed as a
76*6777b538SAndroid Build Coastguard Worker // iterator over all rows in the line number table.
77*6777b538SAndroid Build Coastguard Worker class OnCommit {
78*6777b538SAndroid Build Coastguard Worker public:
79*6777b538SAndroid Build Coastguard Worker virtual void Do(LineNumberRegisters* registers) = 0;
80*6777b538SAndroid Build Coastguard Worker };
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker raw_ptr<OnCommit> on_commit;
LineNumberRegistersbase::debug::__anon7dac112c0111::LineNumberRegisters83*6777b538SAndroid Build Coastguard Worker LineNumberRegisters(ProgramInfo info, OnCommit* on_commit)
84*6777b538SAndroid Build Coastguard Worker : on_commit(on_commit), is_stmt(info.default_is_stmt) {}
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker // Current program counter.
87*6777b538SAndroid Build Coastguard Worker uintptr_t address = 0;
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker // For VLIW architectures, the index of the operation in the VLIW instruction.
90*6777b538SAndroid Build Coastguard Worker unsigned int op_index = 0;
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker // Identifies the source file relating to the address in the DWARF File name
93*6777b538SAndroid Build Coastguard Worker // table.
94*6777b538SAndroid Build Coastguard Worker uint64_t file = 0;
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker // Identifies the line number. Starts at 1. Can become 0 if instruction does
97*6777b538SAndroid Build Coastguard Worker // not match any line in the file.
98*6777b538SAndroid Build Coastguard Worker uint64_t line = 1;
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker // Identifies the column within the source line. Starts at 1 though "0"
101*6777b538SAndroid Build Coastguard Worker // also means "left edge" of the line.
102*6777b538SAndroid Build Coastguard Worker uint64_t column = 0;
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker // Boolean determining if this is a recommended spot for a breakpoint.
105*6777b538SAndroid Build Coastguard Worker // Should be initialized by the program header.
106*6777b538SAndroid Build Coastguard Worker bool is_stmt = false;
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker // Indicates start of a basic block.
109*6777b538SAndroid Build Coastguard Worker bool basic_block = false;
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker // Indicates first byte after a sequence of machine instructions.
112*6777b538SAndroid Build Coastguard Worker bool end_sequence = false;
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker // Indicates this may be where execution should stop if trying to break for
115*6777b538SAndroid Build Coastguard Worker // entering a function.
116*6777b538SAndroid Build Coastguard Worker bool prologue_end = false;
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker // Indicates this may be where execution should stop if trying to break for
119*6777b538SAndroid Build Coastguard Worker // exiting a function.
120*6777b538SAndroid Build Coastguard Worker bool epilogue_begin = false;
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker // Identifier for the instruction set of the current address.
123*6777b538SAndroid Build Coastguard Worker uint64_t isa = 0;
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker // Identifies which block the current instruction belongs to.
126*6777b538SAndroid Build Coastguard Worker uint64_t discriminator = 0;
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker // Values from the previously committed line. See OnCommit interface for more
129*6777b538SAndroid Build Coastguard Worker // details. This conceptually should be a copy of the whole
130*6777b538SAndroid Build Coastguard Worker // LineNumberRegisters but since only 4 pieces of data are needed, hacking
131*6777b538SAndroid Build Coastguard Worker // it inline was easier.
132*6777b538SAndroid Build Coastguard Worker uintptr_t last_address = 0;
133*6777b538SAndroid Build Coastguard Worker uint64_t last_file = 0;
134*6777b538SAndroid Build Coastguard Worker uint64_t last_line = 0;
135*6777b538SAndroid Build Coastguard Worker uint64_t last_column = 0;
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker // This is the magical calculation for decompressing the line-number
138*6777b538SAndroid Build Coastguard Worker // information. The `program_info` provides the parameters for the formula
139*6777b538SAndroid Build Coastguard Worker // and the `op_advance` is the input value. See DWARF-4 sections 6.2.5.1 for
140*6777b538SAndroid Build Coastguard Worker // the formula.
OpAdvancebase::debug::__anon7dac112c0111::LineNumberRegisters141*6777b538SAndroid Build Coastguard Worker void OpAdvance(const ProgramInfo* program_info, uint64_t op_advance) {
142*6777b538SAndroid Build Coastguard Worker address += program_info->minimum_instruction_length *
143*6777b538SAndroid Build Coastguard Worker ((op_index + op_advance) /
144*6777b538SAndroid Build Coastguard Worker program_info->maximum_operations_per_instruction);
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker op_index = (op_index + op_advance) %
147*6777b538SAndroid Build Coastguard Worker program_info->maximum_operations_per_instruction;
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker // Committing a line means the calculation has landed on a stable set of
151*6777b538SAndroid Build Coastguard Worker // values that represent an actual entry in the line number table.
CommitLinebase::debug::__anon7dac112c0111::LineNumberRegisters152*6777b538SAndroid Build Coastguard Worker void CommitLine() {
153*6777b538SAndroid Build Coastguard Worker on_commit->Do(this);
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker // Inlined or compiler generator code may have line number 0 which isn't
156*6777b538SAndroid Build Coastguard Worker // useful to the user. Better to go up one line number.
157*6777b538SAndroid Build Coastguard Worker if (line != 0) {
158*6777b538SAndroid Build Coastguard Worker last_address = address;
159*6777b538SAndroid Build Coastguard Worker last_file = file;
160*6777b538SAndroid Build Coastguard Worker last_column = column;
161*6777b538SAndroid Build Coastguard Worker last_line = line;
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker };
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker struct LineNumberInfo {
167*6777b538SAndroid Build Coastguard Worker uint64_t pc = 0;
168*6777b538SAndroid Build Coastguard Worker uint64_t line = 0;
169*6777b538SAndroid Build Coastguard Worker uint64_t column = 0;
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker // Offsets here are to the file table and directory table arrays inside the
172*6777b538SAndroid Build Coastguard Worker // ProgramInfo.
173*6777b538SAndroid Build Coastguard Worker uint64_t module_dir_offset = 0;
174*6777b538SAndroid Build Coastguard Worker uint64_t dir_size = 0;
175*6777b538SAndroid Build Coastguard Worker uint64_t module_filename_offset = 0;
176*6777b538SAndroid Build Coastguard Worker };
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker // Evaluates a Line Number Program as defined by the rules in section 6.2.5.
EvaluateLineNumberProgram(const int fd,LineNumberInfo * info,uint64_t base_address,uint64_t start,const ProgramInfo & program_info)179*6777b538SAndroid Build Coastguard Worker void EvaluateLineNumberProgram(const int fd,
180*6777b538SAndroid Build Coastguard Worker LineNumberInfo* info,
181*6777b538SAndroid Build Coastguard Worker uint64_t base_address,
182*6777b538SAndroid Build Coastguard Worker uint64_t start,
183*6777b538SAndroid Build Coastguard Worker const ProgramInfo& program_info) {
184*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader reader(fd, start);
185*6777b538SAndroid Build Coastguard Worker uint64_t module_relative_pc = info->pc - base_address;
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker // Helper that records the line-number table entry corresponding with the
188*6777b538SAndroid Build Coastguard Worker // `module_relative_pc`. This is the thing that actually finds the line
189*6777b538SAndroid Build Coastguard Worker // number for an address.
190*6777b538SAndroid Build Coastguard Worker struct OnCommitImpl : public LineNumberRegisters::OnCommit {
191*6777b538SAndroid Build Coastguard Worker private:
192*6777b538SAndroid Build Coastguard Worker raw_ptr<LineNumberInfo> info;
193*6777b538SAndroid Build Coastguard Worker uint64_t module_relative_pc;
194*6777b538SAndroid Build Coastguard Worker const raw_ref<const ProgramInfo> program_info;
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker public:
197*6777b538SAndroid Build Coastguard Worker OnCommitImpl(LineNumberInfo* info,
198*6777b538SAndroid Build Coastguard Worker uint64_t module_relative_pc,
199*6777b538SAndroid Build Coastguard Worker const ProgramInfo& program_info)
200*6777b538SAndroid Build Coastguard Worker : info(info),
201*6777b538SAndroid Build Coastguard Worker module_relative_pc(module_relative_pc),
202*6777b538SAndroid Build Coastguard Worker program_info(program_info) {}
203*6777b538SAndroid Build Coastguard Worker
204*6777b538SAndroid Build Coastguard Worker void Do(LineNumberRegisters* registers) override {
205*6777b538SAndroid Build Coastguard Worker // When a line is committed, the program counter needs to check if it is
206*6777b538SAndroid Build Coastguard Worker // in the [last_address, cur_addres) range. If yes, then the line pertains
207*6777b538SAndroid Build Coastguard Worker // to the program counter.
208*6777b538SAndroid Build Coastguard Worker if (registers->last_address == 0) {
209*6777b538SAndroid Build Coastguard Worker // This is the first table entry so by definition, nothing is in its
210*6777b538SAndroid Build Coastguard Worker // range.
211*6777b538SAndroid Build Coastguard Worker return;
212*6777b538SAndroid Build Coastguard Worker }
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Worker // If module_relative_pc is out of range, skip.
215*6777b538SAndroid Build Coastguard Worker if (module_relative_pc < registers->last_address ||
216*6777b538SAndroid Build Coastguard Worker module_relative_pc >= registers->address)
217*6777b538SAndroid Build Coastguard Worker return;
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker if (registers->last_file < program_info->num_filenames) {
220*6777b538SAndroid Build Coastguard Worker info->line = registers->last_line;
221*6777b538SAndroid Build Coastguard Worker info->column = registers->last_column;
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker // Since DW_AT_name in the compile_unit is optional, it may be empty. If
224*6777b538SAndroid Build Coastguard Worker // it is, guess that the file in entry 1 is the name. This does not
225*6777b538SAndroid Build Coastguard Worker // follow spec, but seems to be common behavior. See the following LLVM
226*6777b538SAndroid Build Coastguard Worker // bug for more info: https://reviews.llvm.org/D11003
227*6777b538SAndroid Build Coastguard Worker if (registers->last_file == 0 &&
228*6777b538SAndroid Build Coastguard Worker program_info->filename_offsets[0] == 0 &&
229*6777b538SAndroid Build Coastguard Worker 1 < program_info->num_filenames) {
230*6777b538SAndroid Build Coastguard Worker program_info->filename_offsets[0] = program_info->filename_offsets[1];
231*6777b538SAndroid Build Coastguard Worker program_info->filename_dirs[0] = program_info->filename_dirs[1];
232*6777b538SAndroid Build Coastguard Worker }
233*6777b538SAndroid Build Coastguard Worker
234*6777b538SAndroid Build Coastguard Worker if (registers->last_file < kMaxFilenames) {
235*6777b538SAndroid Build Coastguard Worker info->module_filename_offset =
236*6777b538SAndroid Build Coastguard Worker program_info->filename_offsets[registers->last_file];
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker uint8_t dir = program_info->filename_dirs[registers->last_file];
239*6777b538SAndroid Build Coastguard Worker info->module_dir_offset = program_info->directory_offsets[dir];
240*6777b538SAndroid Build Coastguard Worker info->dir_size = program_info->directory_sizes[dir];
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker }
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker } on_commit(info, module_relative_pc, program_info);
245*6777b538SAndroid Build Coastguard Worker
246*6777b538SAndroid Build Coastguard Worker LineNumberRegisters registers(program_info, &on_commit);
247*6777b538SAndroid Build Coastguard Worker
248*6777b538SAndroid Build Coastguard Worker // Special opcode range is [program_info.opcode_base, 255].
249*6777b538SAndroid Build Coastguard Worker // Lines can be max incremented by [line_base + line range - 1].
250*6777b538SAndroid Build Coastguard Worker // opcode = (desired line increment - line_base) + (line_range * operation
251*6777b538SAndroid Build Coastguard Worker // advance) + opcode_base.
252*6777b538SAndroid Build Coastguard Worker uint8_t opcode;
253*6777b538SAndroid Build Coastguard Worker while (reader.position() < program_info.end_offset && info->line == 0) {
254*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(opcode))
255*6777b538SAndroid Build Coastguard Worker return;
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker // It's SPECIAL OPCODE TIME!. They're so special that they make up the
258*6777b538SAndroid Build Coastguard Worker // vast majority of the opcodes and are the first thing described in the
259*6777b538SAndroid Build Coastguard Worker // documentation.
260*6777b538SAndroid Build Coastguard Worker //
261*6777b538SAndroid Build Coastguard Worker // See DWARF-4 spec 6.2.5.1.
262*6777b538SAndroid Build Coastguard Worker if (opcode >= program_info.opcode_base) {
263*6777b538SAndroid Build Coastguard Worker uint8_t adjusted_opcode = opcode - program_info.opcode_base;
264*6777b538SAndroid Build Coastguard Worker registers.OpAdvance(&program_info,
265*6777b538SAndroid Build Coastguard Worker program_info.OpcodeToAdvance(adjusted_opcode));
266*6777b538SAndroid Build Coastguard Worker const int line_adjust =
267*6777b538SAndroid Build Coastguard Worker program_info.line_base + (adjusted_opcode % program_info.line_range);
268*6777b538SAndroid Build Coastguard Worker if (line_adjust < 0) {
269*6777b538SAndroid Build Coastguard Worker if (static_cast<uint64_t>(-line_adjust) > registers.line)
270*6777b538SAndroid Build Coastguard Worker return;
271*6777b538SAndroid Build Coastguard Worker registers.line -= static_cast<uint64_t>(-line_adjust);
272*6777b538SAndroid Build Coastguard Worker } else {
273*6777b538SAndroid Build Coastguard Worker registers.line += static_cast<uint64_t>(line_adjust);
274*6777b538SAndroid Build Coastguard Worker }
275*6777b538SAndroid Build Coastguard Worker registers.basic_block = false;
276*6777b538SAndroid Build Coastguard Worker registers.prologue_end = false;
277*6777b538SAndroid Build Coastguard Worker registers.epilogue_begin = false;
278*6777b538SAndroid Build Coastguard Worker registers.discriminator = 0;
279*6777b538SAndroid Build Coastguard Worker registers.CommitLine();
280*6777b538SAndroid Build Coastguard Worker } else {
281*6777b538SAndroid Build Coastguard Worker // Standard opcodes
282*6777b538SAndroid Build Coastguard Worker switch (opcode) {
283*6777b538SAndroid Build Coastguard Worker case 0: {
284*6777b538SAndroid Build Coastguard Worker // Extended opcode.
285*6777b538SAndroid Build Coastguard Worker uint64_t extended_opcode;
286*6777b538SAndroid Build Coastguard Worker uint64_t extended_opcode_length;
287*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(extended_opcode_length))
288*6777b538SAndroid Build Coastguard Worker return;
289*6777b538SAndroid Build Coastguard Worker uint64_t next_opcode = reader.position() + extended_opcode_length;
290*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(extended_opcode))
291*6777b538SAndroid Build Coastguard Worker return;
292*6777b538SAndroid Build Coastguard Worker switch (extended_opcode) {
293*6777b538SAndroid Build Coastguard Worker case 1: {
294*6777b538SAndroid Build Coastguard Worker // DW_LNE_end_sequence
295*6777b538SAndroid Build Coastguard Worker registers.end_sequence = true;
296*6777b538SAndroid Build Coastguard Worker registers.CommitLine();
297*6777b538SAndroid Build Coastguard Worker registers = LineNumberRegisters(program_info, &on_commit);
298*6777b538SAndroid Build Coastguard Worker break;
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker
301*6777b538SAndroid Build Coastguard Worker case 2: {
302*6777b538SAndroid Build Coastguard Worker // DW_LNE_set_address
303*6777b538SAndroid Build Coastguard Worker uint32_t value;
304*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt32(value))
305*6777b538SAndroid Build Coastguard Worker return;
306*6777b538SAndroid Build Coastguard Worker registers.address = value;
307*6777b538SAndroid Build Coastguard Worker registers.op_index = 0;
308*6777b538SAndroid Build Coastguard Worker break;
309*6777b538SAndroid Build Coastguard Worker }
310*6777b538SAndroid Build Coastguard Worker
311*6777b538SAndroid Build Coastguard Worker case 3: {
312*6777b538SAndroid Build Coastguard Worker // DW_LNE_define_file
313*6777b538SAndroid Build Coastguard Worker //
314*6777b538SAndroid Build Coastguard Worker // This should only get used if the filename table itself is null.
315*6777b538SAndroid Build Coastguard Worker // Record the module offset for the string and then drop the data.
316*6777b538SAndroid Build Coastguard Worker uint64_t filename_offset = reader.position();
317*6777b538SAndroid Build Coastguard Worker reader.ReadCString(program_info.end_offset, nullptr, 0);
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker // dir index
320*6777b538SAndroid Build Coastguard Worker uint64_t value;
321*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
322*6777b538SAndroid Build Coastguard Worker return;
323*6777b538SAndroid Build Coastguard Worker size_t cur_filename = program_info.num_filenames;
324*6777b538SAndroid Build Coastguard Worker if (cur_filename < kMaxFilenames && value < kMaxDirectories) {
325*6777b538SAndroid Build Coastguard Worker ++program_info.num_filenames;
326*6777b538SAndroid Build Coastguard Worker // Store the offset from the start of file and skip the data to
327*6777b538SAndroid Build Coastguard Worker // save memory.
328*6777b538SAndroid Build Coastguard Worker program_info.filename_offsets[cur_filename] = filename_offset;
329*6777b538SAndroid Build Coastguard Worker program_info.filename_dirs[cur_filename] =
330*6777b538SAndroid Build Coastguard Worker static_cast<uint8_t>(value);
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker // modification time
334*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
335*6777b538SAndroid Build Coastguard Worker return;
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker // source file length
338*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
339*6777b538SAndroid Build Coastguard Worker return;
340*6777b538SAndroid Build Coastguard Worker break;
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker
343*6777b538SAndroid Build Coastguard Worker case 4: {
344*6777b538SAndroid Build Coastguard Worker // DW_LNE_set_discriminator
345*6777b538SAndroid Build Coastguard Worker uint64_t value;
346*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
347*6777b538SAndroid Build Coastguard Worker return;
348*6777b538SAndroid Build Coastguard Worker registers.discriminator = value;
349*6777b538SAndroid Build Coastguard Worker break;
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker
352*6777b538SAndroid Build Coastguard Worker default:
353*6777b538SAndroid Build Coastguard Worker abort();
354*6777b538SAndroid Build Coastguard Worker }
355*6777b538SAndroid Build Coastguard Worker
356*6777b538SAndroid Build Coastguard Worker // Skip any padding bytes in extended opcode.
357*6777b538SAndroid Build Coastguard Worker reader.set_position(next_opcode);
358*6777b538SAndroid Build Coastguard Worker break;
359*6777b538SAndroid Build Coastguard Worker }
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker case 1: {
362*6777b538SAndroid Build Coastguard Worker // DW_LNS_copy. This commits the registers to the line number table.
363*6777b538SAndroid Build Coastguard Worker registers.CommitLine();
364*6777b538SAndroid Build Coastguard Worker registers.discriminator = 0;
365*6777b538SAndroid Build Coastguard Worker registers.basic_block = false;
366*6777b538SAndroid Build Coastguard Worker registers.prologue_end = false;
367*6777b538SAndroid Build Coastguard Worker registers.epilogue_begin = false;
368*6777b538SAndroid Build Coastguard Worker break;
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker
371*6777b538SAndroid Build Coastguard Worker case 2: {
372*6777b538SAndroid Build Coastguard Worker // DW_LNS_advance_pc
373*6777b538SAndroid Build Coastguard Worker uint64_t op_advance;
374*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(op_advance))
375*6777b538SAndroid Build Coastguard Worker return;
376*6777b538SAndroid Build Coastguard Worker registers.OpAdvance(&program_info, op_advance);
377*6777b538SAndroid Build Coastguard Worker break;
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker
380*6777b538SAndroid Build Coastguard Worker case 3: {
381*6777b538SAndroid Build Coastguard Worker // DW_LNS_advance_line
382*6777b538SAndroid Build Coastguard Worker int64_t line_advance;
383*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(line_advance))
384*6777b538SAndroid Build Coastguard Worker return;
385*6777b538SAndroid Build Coastguard Worker if (line_advance < 0) {
386*6777b538SAndroid Build Coastguard Worker if (static_cast<uint64_t>(-line_advance) > registers.line)
387*6777b538SAndroid Build Coastguard Worker return;
388*6777b538SAndroid Build Coastguard Worker registers.line -= static_cast<uint64_t>(-line_advance);
389*6777b538SAndroid Build Coastguard Worker } else {
390*6777b538SAndroid Build Coastguard Worker registers.line += static_cast<uint64_t>(line_advance);
391*6777b538SAndroid Build Coastguard Worker }
392*6777b538SAndroid Build Coastguard Worker break;
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker
395*6777b538SAndroid Build Coastguard Worker case 4: {
396*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_file
397*6777b538SAndroid Build Coastguard Worker uint64_t value;
398*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
399*6777b538SAndroid Build Coastguard Worker return;
400*6777b538SAndroid Build Coastguard Worker registers.file = value;
401*6777b538SAndroid Build Coastguard Worker break;
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker case 5: {
405*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_column
406*6777b538SAndroid Build Coastguard Worker uint64_t value;
407*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
408*6777b538SAndroid Build Coastguard Worker return;
409*6777b538SAndroid Build Coastguard Worker registers.column = value;
410*6777b538SAndroid Build Coastguard Worker break;
411*6777b538SAndroid Build Coastguard Worker }
412*6777b538SAndroid Build Coastguard Worker
413*6777b538SAndroid Build Coastguard Worker case 6:
414*6777b538SAndroid Build Coastguard Worker // DW_LNS_negate_stmt
415*6777b538SAndroid Build Coastguard Worker registers.is_stmt = !registers.is_stmt;
416*6777b538SAndroid Build Coastguard Worker break;
417*6777b538SAndroid Build Coastguard Worker
418*6777b538SAndroid Build Coastguard Worker case 7:
419*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_basic_block
420*6777b538SAndroid Build Coastguard Worker registers.basic_block = true;
421*6777b538SAndroid Build Coastguard Worker break;
422*6777b538SAndroid Build Coastguard Worker
423*6777b538SAndroid Build Coastguard Worker case 8:
424*6777b538SAndroid Build Coastguard Worker // DW_LNS_const_add_pc
425*6777b538SAndroid Build Coastguard Worker registers.OpAdvance(
426*6777b538SAndroid Build Coastguard Worker &program_info,
427*6777b538SAndroid Build Coastguard Worker program_info.OpcodeToAdvance(255 - program_info.opcode_base));
428*6777b538SAndroid Build Coastguard Worker break;
429*6777b538SAndroid Build Coastguard Worker
430*6777b538SAndroid Build Coastguard Worker case 9: {
431*6777b538SAndroid Build Coastguard Worker // DW_LNS_fixed_advance_pc
432*6777b538SAndroid Build Coastguard Worker uint16_t value;
433*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt16(value))
434*6777b538SAndroid Build Coastguard Worker return;
435*6777b538SAndroid Build Coastguard Worker registers.address += value;
436*6777b538SAndroid Build Coastguard Worker registers.op_index = 0;
437*6777b538SAndroid Build Coastguard Worker break;
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker case 10:
441*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_prologue_end
442*6777b538SAndroid Build Coastguard Worker registers.prologue_end = true;
443*6777b538SAndroid Build Coastguard Worker break;
444*6777b538SAndroid Build Coastguard Worker
445*6777b538SAndroid Build Coastguard Worker case 11:
446*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_epilogue_begin
447*6777b538SAndroid Build Coastguard Worker registers.epilogue_begin = true;
448*6777b538SAndroid Build Coastguard Worker break;
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker case 12: {
451*6777b538SAndroid Build Coastguard Worker // DW_LNS_set_isa
452*6777b538SAndroid Build Coastguard Worker uint64_t value;
453*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value))
454*6777b538SAndroid Build Coastguard Worker return;
455*6777b538SAndroid Build Coastguard Worker registers.isa = value;
456*6777b538SAndroid Build Coastguard Worker break;
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker default:
460*6777b538SAndroid Build Coastguard Worker abort();
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker }
463*6777b538SAndroid Build Coastguard Worker }
464*6777b538SAndroid Build Coastguard Worker }
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker // Parses a 32-bit DWARF-4 line number program header per section 6.2.4.
467*6777b538SAndroid Build Coastguard Worker // `cu_name_offset` is the module offset for the 0th entry of the file table.
ParseDwarf4ProgramInfo(BufferedDwarfReader * reader,bool is_64bit,uint64_t cu_name_offset,ProgramInfo * program_info)468*6777b538SAndroid Build Coastguard Worker bool ParseDwarf4ProgramInfo(BufferedDwarfReader* reader,
469*6777b538SAndroid Build Coastguard Worker bool is_64bit,
470*6777b538SAndroid Build Coastguard Worker uint64_t cu_name_offset,
471*6777b538SAndroid Build Coastguard Worker ProgramInfo* program_info) {
472*6777b538SAndroid Build Coastguard Worker if (!reader->ReadOffset(is_64bit, program_info->header_length))
473*6777b538SAndroid Build Coastguard Worker return false;
474*6777b538SAndroid Build Coastguard Worker program_info->start_offset = reader->position() + program_info->header_length;
475*6777b538SAndroid Build Coastguard Worker
476*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(program_info->minimum_instruction_length) ||
477*6777b538SAndroid Build Coastguard Worker !reader->ReadInt8(program_info->maximum_operations_per_instruction) ||
478*6777b538SAndroid Build Coastguard Worker !reader->ReadInt8(program_info->default_is_stmt) ||
479*6777b538SAndroid Build Coastguard Worker !reader->ReadInt8(program_info->line_base) ||
480*6777b538SAndroid Build Coastguard Worker !reader->ReadInt8(program_info->line_range) ||
481*6777b538SAndroid Build Coastguard Worker !reader->ReadInt8(program_info->opcode_base)) {
482*6777b538SAndroid Build Coastguard Worker return false;
483*6777b538SAndroid Build Coastguard Worker }
484*6777b538SAndroid Build Coastguard Worker
485*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < (program_info->opcode_base - 1); i++) {
486*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(program_info->standard_opcode_lengths[i]))
487*6777b538SAndroid Build Coastguard Worker return false;
488*6777b538SAndroid Build Coastguard Worker }
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker // Table ends with a single null line. This basically means search for 2
491*6777b538SAndroid Build Coastguard Worker // contiguous empty bytes.
492*6777b538SAndroid Build Coastguard Worker uint8_t last = 0, cur = 0;
493*6777b538SAndroid Build Coastguard Worker for (;;) {
494*6777b538SAndroid Build Coastguard Worker // Read a byte.
495*6777b538SAndroid Build Coastguard Worker last = cur;
496*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(cur))
497*6777b538SAndroid Build Coastguard Worker return false;
498*6777b538SAndroid Build Coastguard Worker
499*6777b538SAndroid Build Coastguard Worker if (last == 0 && cur == 0) {
500*6777b538SAndroid Build Coastguard Worker // We're at the last entry where it's a double null.
501*6777b538SAndroid Build Coastguard Worker break;
502*6777b538SAndroid Build Coastguard Worker }
503*6777b538SAndroid Build Coastguard Worker
504*6777b538SAndroid Build Coastguard Worker // Read in all of the filename.
505*6777b538SAndroid Build Coastguard Worker int cur_dir = program_info->num_directories;
506*6777b538SAndroid Build Coastguard Worker if (cur_dir < kMaxDirectories) {
507*6777b538SAndroid Build Coastguard Worker ++program_info->num_directories;
508*6777b538SAndroid Build Coastguard Worker // "-1" is because we have already read the first byte above.
509*6777b538SAndroid Build Coastguard Worker program_info->directory_offsets[cur_dir] = reader->position() - 1;
510*6777b538SAndroid Build Coastguard Worker program_info->directory_sizes[cur_dir] = 1;
511*6777b538SAndroid Build Coastguard Worker }
512*6777b538SAndroid Build Coastguard Worker do {
513*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(cur))
514*6777b538SAndroid Build Coastguard Worker return false;
515*6777b538SAndroid Build Coastguard Worker if (cur_dir < kMaxDirectories)
516*6777b538SAndroid Build Coastguard Worker ++program_info->directory_sizes[cur_dir];
517*6777b538SAndroid Build Coastguard Worker } while (cur != '\0');
518*6777b538SAndroid Build Coastguard Worker }
519*6777b538SAndroid Build Coastguard Worker
520*6777b538SAndroid Build Coastguard Worker // Read filename table line-by-line.
521*6777b538SAndroid Build Coastguard Worker last = 0;
522*6777b538SAndroid Build Coastguard Worker cur = 0;
523*6777b538SAndroid Build Coastguard Worker for (;;) {
524*6777b538SAndroid Build Coastguard Worker // Read a byte.
525*6777b538SAndroid Build Coastguard Worker last = cur;
526*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(cur))
527*6777b538SAndroid Build Coastguard Worker return false;
528*6777b538SAndroid Build Coastguard Worker
529*6777b538SAndroid Build Coastguard Worker if (last == 0 && cur == 0) {
530*6777b538SAndroid Build Coastguard Worker // We're at the last entry where it's a double null.
531*6777b538SAndroid Build Coastguard Worker break;
532*6777b538SAndroid Build Coastguard Worker }
533*6777b538SAndroid Build Coastguard Worker
534*6777b538SAndroid Build Coastguard Worker // Read in all of the filename. "-1" is because we have already read the
535*6777b538SAndroid Build Coastguard Worker // first byte of the filename above.
536*6777b538SAndroid Build Coastguard Worker uint64_t filename_offset = reader->position() - 1;
537*6777b538SAndroid Build Coastguard Worker do {
538*6777b538SAndroid Build Coastguard Worker if (!reader->ReadInt8(cur))
539*6777b538SAndroid Build Coastguard Worker return false;
540*6777b538SAndroid Build Coastguard Worker } while (cur != '\0');
541*6777b538SAndroid Build Coastguard Worker
542*6777b538SAndroid Build Coastguard Worker uint64_t value;
543*6777b538SAndroid Build Coastguard Worker
544*6777b538SAndroid Build Coastguard Worker // Dir index
545*6777b538SAndroid Build Coastguard Worker if (!reader->ReadLeb128(value))
546*6777b538SAndroid Build Coastguard Worker return false;
547*6777b538SAndroid Build Coastguard Worker size_t cur_filename = program_info->num_filenames;
548*6777b538SAndroid Build Coastguard Worker if (cur_filename < kMaxFilenames && value < kMaxDirectories) {
549*6777b538SAndroid Build Coastguard Worker ++program_info->num_filenames;
550*6777b538SAndroid Build Coastguard Worker program_info->filename_offsets[cur_filename] = filename_offset;
551*6777b538SAndroid Build Coastguard Worker program_info->filename_dirs[cur_filename] = static_cast<uint8_t>(value);
552*6777b538SAndroid Build Coastguard Worker }
553*6777b538SAndroid Build Coastguard Worker
554*6777b538SAndroid Build Coastguard Worker // Modification time
555*6777b538SAndroid Build Coastguard Worker if (!reader->ReadLeb128(value))
556*6777b538SAndroid Build Coastguard Worker return false;
557*6777b538SAndroid Build Coastguard Worker
558*6777b538SAndroid Build Coastguard Worker // Bytes in file.
559*6777b538SAndroid Build Coastguard Worker if (!reader->ReadLeb128(value))
560*6777b538SAndroid Build Coastguard Worker return false;
561*6777b538SAndroid Build Coastguard Worker }
562*6777b538SAndroid Build Coastguard Worker
563*6777b538SAndroid Build Coastguard Worker // Set up the 0th filename.
564*6777b538SAndroid Build Coastguard Worker program_info->filename_offsets[0] = cu_name_offset;
565*6777b538SAndroid Build Coastguard Worker program_info->filename_dirs[0] = 0;
566*6777b538SAndroid Build Coastguard Worker program_info->directory_offsets[0] = 0;
567*6777b538SAndroid Build Coastguard Worker
568*6777b538SAndroid Build Coastguard Worker return true;
569*6777b538SAndroid Build Coastguard Worker }
570*6777b538SAndroid Build Coastguard Worker
571*6777b538SAndroid Build Coastguard Worker // Returns the offset of the next byte to read.
572*6777b538SAndroid Build Coastguard Worker // `program_info.program_end` is guaranteed to be initlialized to either
573*6777b538SAndroid Build Coastguard Worker // `kMaxOffset` if the program length could not be processed, or to
574*6777b538SAndroid Build Coastguard Worker // the byte after the end of this program.
ReadProgramInfo(const int fd,uint64_t start,uint64_t cu_name_offset,ProgramInfo * program_info)575*6777b538SAndroid Build Coastguard Worker bool ReadProgramInfo(const int fd,
576*6777b538SAndroid Build Coastguard Worker uint64_t start,
577*6777b538SAndroid Build Coastguard Worker uint64_t cu_name_offset,
578*6777b538SAndroid Build Coastguard Worker ProgramInfo* program_info) {
579*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader reader(fd, start);
580*6777b538SAndroid Build Coastguard Worker program_info->end_offset = kMaxOffset;
581*6777b538SAndroid Build Coastguard Worker
582*6777b538SAndroid Build Coastguard Worker // Note that 64-bit dwarf does NOT imply a 64-bit binary and vice-versa. In
583*6777b538SAndroid Build Coastguard Worker // fact many 64-bit binaries use 32-bit dwarf encoding.
584*6777b538SAndroid Build Coastguard Worker bool is_64bit = false;
585*6777b538SAndroid Build Coastguard Worker uint64_t data_length;
586*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInitialLength(is_64bit, data_length)) {
587*6777b538SAndroid Build Coastguard Worker return false;
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker
590*6777b538SAndroid Build Coastguard Worker // Set the program end. This allows the search to recover by skipping an
591*6777b538SAndroid Build Coastguard Worker // unparsable program.
592*6777b538SAndroid Build Coastguard Worker program_info->end_offset = reader.position() + data_length;
593*6777b538SAndroid Build Coastguard Worker
594*6777b538SAndroid Build Coastguard Worker uint16_t version;
595*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt16(version)) {
596*6777b538SAndroid Build Coastguard Worker return false;
597*6777b538SAndroid Build Coastguard Worker }
598*6777b538SAndroid Build Coastguard Worker
599*6777b538SAndroid Build Coastguard Worker if (version == 4) {
600*6777b538SAndroid Build Coastguard Worker return ParseDwarf4ProgramInfo(&reader, is_64bit, cu_name_offset,
601*6777b538SAndroid Build Coastguard Worker program_info);
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker
604*6777b538SAndroid Build Coastguard Worker // Currently does not support other DWARF versions.
605*6777b538SAndroid Build Coastguard Worker return false;
606*6777b538SAndroid Build Coastguard Worker }
607*6777b538SAndroid Build Coastguard Worker
608*6777b538SAndroid Build Coastguard Worker // Attempts to find line-number info for all of |info|. Returns the number of
609*6777b538SAndroid Build Coastguard Worker // entries that do not have info yet.
GetLineNumbersInProgram(const int fd,LineNumberInfo * info,uint64_t base_address,uint64_t start,uint64_t cu_name_offset)610*6777b538SAndroid Build Coastguard Worker uint64_t GetLineNumbersInProgram(const int fd,
611*6777b538SAndroid Build Coastguard Worker LineNumberInfo* info,
612*6777b538SAndroid Build Coastguard Worker uint64_t base_address,
613*6777b538SAndroid Build Coastguard Worker uint64_t start,
614*6777b538SAndroid Build Coastguard Worker uint64_t cu_name_offset) {
615*6777b538SAndroid Build Coastguard Worker // Open the program.
616*6777b538SAndroid Build Coastguard Worker ProgramInfo program_info;
617*6777b538SAndroid Build Coastguard Worker if (ReadProgramInfo(fd, start, cu_name_offset, &program_info)) {
618*6777b538SAndroid Build Coastguard Worker EvaluateLineNumberProgram(fd, info, base_address, program_info.start_offset,
619*6777b538SAndroid Build Coastguard Worker program_info);
620*6777b538SAndroid Build Coastguard Worker }
621*6777b538SAndroid Build Coastguard Worker
622*6777b538SAndroid Build Coastguard Worker return program_info.end_offset;
623*6777b538SAndroid Build Coastguard Worker }
624*6777b538SAndroid Build Coastguard Worker
625*6777b538SAndroid Build Coastguard Worker // Scans the .debug_abbrev entry until it finds the Attribute List matching the
626*6777b538SAndroid Build Coastguard Worker // `wanted_abbreviation_code`. This is called when parsing a DIE in .debug_info.
AdvancedReaderToAttributeList(BufferedDwarfReader & reader,uint64_t table_end,uint64_t wanted_abbreviation_code,uint64_t & tag,bool & has_children)627*6777b538SAndroid Build Coastguard Worker bool AdvancedReaderToAttributeList(BufferedDwarfReader& reader,
628*6777b538SAndroid Build Coastguard Worker uint64_t table_end,
629*6777b538SAndroid Build Coastguard Worker uint64_t wanted_abbreviation_code,
630*6777b538SAndroid Build Coastguard Worker uint64_t& tag,
631*6777b538SAndroid Build Coastguard Worker bool& has_children) {
632*6777b538SAndroid Build Coastguard Worker // Abbreviation Table entries are:
633*6777b538SAndroid Build Coastguard Worker // LEB128 - abbreviation code
634*6777b538SAndroid Build Coastguard Worker // LEB128 - the entry's tag
635*6777b538SAndroid Build Coastguard Worker // 1 byte - DW_CHILDREN_yes or DW_CHILDREN_no for if entry has children.
636*6777b538SAndroid Build Coastguard Worker // [LEB128, LEB128] -- repeated set of attribute + form values in LEB128
637*6777b538SAndroid Build Coastguard Worker // [0, 0] -- null entry terminating list is 2 LEB128 0s.
638*6777b538SAndroid Build Coastguard Worker while (reader.position() < table_end) {
639*6777b538SAndroid Build Coastguard Worker uint64_t abbreviation_code;
640*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(abbreviation_code)) {
641*6777b538SAndroid Build Coastguard Worker return false;
642*6777b538SAndroid Build Coastguard Worker }
643*6777b538SAndroid Build Coastguard Worker
644*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(tag)) {
645*6777b538SAndroid Build Coastguard Worker return false;
646*6777b538SAndroid Build Coastguard Worker }
647*6777b538SAndroid Build Coastguard Worker
648*6777b538SAndroid Build Coastguard Worker uint8_t raw_has_children;
649*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(raw_has_children)) {
650*6777b538SAndroid Build Coastguard Worker return false;
651*6777b538SAndroid Build Coastguard Worker }
652*6777b538SAndroid Build Coastguard Worker if (raw_has_children == 0) {
653*6777b538SAndroid Build Coastguard Worker has_children = false;
654*6777b538SAndroid Build Coastguard Worker } else if (raw_has_children == 1) {
655*6777b538SAndroid Build Coastguard Worker has_children = true;
656*6777b538SAndroid Build Coastguard Worker } else {
657*6777b538SAndroid Build Coastguard Worker return false;
658*6777b538SAndroid Build Coastguard Worker }
659*6777b538SAndroid Build Coastguard Worker
660*6777b538SAndroid Build Coastguard Worker if (abbreviation_code == wanted_abbreviation_code) {
661*6777b538SAndroid Build Coastguard Worker return true;
662*6777b538SAndroid Build Coastguard Worker }
663*6777b538SAndroid Build Coastguard Worker
664*6777b538SAndroid Build Coastguard Worker // Incorrect Abbreviation entry. Skip all of its attributes.
665*6777b538SAndroid Build Coastguard Worker uint64_t attr;
666*6777b538SAndroid Build Coastguard Worker uint64_t form;
667*6777b538SAndroid Build Coastguard Worker do {
668*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(attr) || !reader.ReadLeb128(form)) {
669*6777b538SAndroid Build Coastguard Worker return false;
670*6777b538SAndroid Build Coastguard Worker }
671*6777b538SAndroid Build Coastguard Worker } while (attr != 0 || form != 0);
672*6777b538SAndroid Build Coastguard Worker }
673*6777b538SAndroid Build Coastguard Worker
674*6777b538SAndroid Build Coastguard Worker return false;
675*6777b538SAndroid Build Coastguard Worker }
676*6777b538SAndroid Build Coastguard Worker
677*6777b538SAndroid Build Coastguard Worker // This reads through a .debug_info compile unit entry to try and extract
678*6777b538SAndroid Build Coastguard Worker // the `cu_name_offset` as well as the `debug_line_offset` (offset into the
679*6777b538SAndroid Build Coastguard Worker // .debug_lines table` corresponding to `pc`.
680*6777b538SAndroid Build Coastguard Worker //
681*6777b538SAndroid Build Coastguard Worker // The .debug_info sections are a packed set of bytes whose format is defined
682*6777b538SAndroid Build Coastguard Worker // by a corresponding .debug_abbrev entry. Basically .debug_abbrev describes
683*6777b538SAndroid Build Coastguard Worker // a struct and .debug_info has a header that tells which struct it is followed
684*6777b538SAndroid Build Coastguard Worker // by a bunch of bytes.
685*6777b538SAndroid Build Coastguard Worker //
686*6777b538SAndroid Build Coastguard Worker // The control flow is to find the .debug_abbrev entry for each .debug_info
687*6777b538SAndroid Build Coastguard Worker // entry, then walk through the .debug_abbrev entry to parse the bytes of the
688*6777b538SAndroid Build Coastguard Worker // .debug_info entry. A successful parse calculates the address range that the
689*6777b538SAndroid Build Coastguard Worker // .debug_info entry covers. When that is retrieved, `pc` can be compared to
690*6777b538SAndroid Build Coastguard Worker // the range and a corresponding .debug_info can be found.
691*6777b538SAndroid Build Coastguard Worker //
692*6777b538SAndroid Build Coastguard Worker // The `debug_info_start` be the start of the whole .debug_info section or an
693*6777b538SAndroid Build Coastguard Worker // offset into the section if it was known ahead of time (perhaps by consulting
694*6777b538SAndroid Build Coastguard Worker // .debug_aranges).
695*6777b538SAndroid Build Coastguard Worker //
696*6777b538SAndroid Build Coastguard Worker // To fully interpret this data, the .debug_ranges and .debug_str sections
697*6777b538SAndroid Build Coastguard Worker // also need to be interpreted.
GetCompileUnitName(int fd,uint64_t debug_info_start,uint64_t debug_info_end,uint64_t pc,uint64_t module_base_address,uint64_t * debug_line_offset,uint64_t * cu_name_offset)698*6777b538SAndroid Build Coastguard Worker bool GetCompileUnitName(int fd,
699*6777b538SAndroid Build Coastguard Worker uint64_t debug_info_start,
700*6777b538SAndroid Build Coastguard Worker uint64_t debug_info_end,
701*6777b538SAndroid Build Coastguard Worker uint64_t pc,
702*6777b538SAndroid Build Coastguard Worker uint64_t module_base_address,
703*6777b538SAndroid Build Coastguard Worker uint64_t* debug_line_offset,
704*6777b538SAndroid Build Coastguard Worker uint64_t* cu_name_offset) {
705*6777b538SAndroid Build Coastguard Worker // Ensure defined `cu_name_offset` in case DW_AT_name is missing.
706*6777b538SAndroid Build Coastguard Worker *cu_name_offset = 0;
707*6777b538SAndroid Build Coastguard Worker
708*6777b538SAndroid Build Coastguard Worker // Open .debug_info and .debug_abbrev as both are needed to find the
709*6777b538SAndroid Build Coastguard Worker // DW_AT_name for the DW_TAG_compile_unit or DW_TAG_partial_unit
710*6777b538SAndroid Build Coastguard Worker // corresponding to the given address.
711*6777b538SAndroid Build Coastguard Worker
712*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_abbrev;
713*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugAbbrevSectionName[] = ".debug_abbrev";
714*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(fd, kDebugAbbrevSectionName,
715*6777b538SAndroid Build Coastguard Worker sizeof(kDebugAbbrevSectionName),
716*6777b538SAndroid Build Coastguard Worker &debug_abbrev)) {
717*6777b538SAndroid Build Coastguard Worker return false;
718*6777b538SAndroid Build Coastguard Worker }
719*6777b538SAndroid Build Coastguard Worker uint64_t debug_abbrev_end = debug_abbrev.sh_offset + debug_abbrev.sh_size;
720*6777b538SAndroid Build Coastguard Worker
721*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_str;
722*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugStrSectionName[] = ".debug_str";
723*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(
724*6777b538SAndroid Build Coastguard Worker fd, kDebugStrSectionName, sizeof(kDebugStrSectionName), &debug_str)) {
725*6777b538SAndroid Build Coastguard Worker return false;
726*6777b538SAndroid Build Coastguard Worker }
727*6777b538SAndroid Build Coastguard Worker uint64_t debug_str_end = debug_str.sh_offset + debug_str.sh_size;
728*6777b538SAndroid Build Coastguard Worker
729*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_ranges;
730*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugRangesSectionName[] = ".debug_ranges";
731*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(fd, kDebugRangesSectionName,
732*6777b538SAndroid Build Coastguard Worker sizeof(kDebugRangesSectionName),
733*6777b538SAndroid Build Coastguard Worker &debug_ranges)) {
734*6777b538SAndroid Build Coastguard Worker return false;
735*6777b538SAndroid Build Coastguard Worker }
736*6777b538SAndroid Build Coastguard Worker uint64_t debug_ranges_end = debug_ranges.sh_offset + debug_ranges.sh_size;
737*6777b538SAndroid Build Coastguard Worker
738*6777b538SAndroid Build Coastguard Worker // Iterate Compile Units.
739*6777b538SAndroid Build Coastguard Worker uint64_t next_compilation_unit = kMaxOffset;
740*6777b538SAndroid Build Coastguard Worker for (BufferedDwarfReader reader(fd, debug_info_start);
741*6777b538SAndroid Build Coastguard Worker reader.position() < debug_info_end;
742*6777b538SAndroid Build Coastguard Worker reader.set_position(next_compilation_unit)) {
743*6777b538SAndroid Build Coastguard Worker bool is_64bit;
744*6777b538SAndroid Build Coastguard Worker uint64_t length;
745*6777b538SAndroid Build Coastguard Worker uint16_t dwarf_version;
746*6777b538SAndroid Build Coastguard Worker uint64_t abbrev_offset;
747*6777b538SAndroid Build Coastguard Worker uint8_t address_size;
748*6777b538SAndroid Build Coastguard Worker if (!reader.ReadCommonHeader(is_64bit, length, dwarf_version, abbrev_offset,
749*6777b538SAndroid Build Coastguard Worker address_size, next_compilation_unit)) {
750*6777b538SAndroid Build Coastguard Worker return false;
751*6777b538SAndroid Build Coastguard Worker }
752*6777b538SAndroid Build Coastguard Worker
753*6777b538SAndroid Build Coastguard Worker // Compilation Unit Header parsed. Now read the first tag which is either a
754*6777b538SAndroid Build Coastguard Worker // DW_TAG_compile_unit or DW_TAG_partial_unit. The entry type is designated
755*6777b538SAndroid Build Coastguard Worker // by a LEB128 number that needs to be cross-referenced in the abbreviations
756*6777b538SAndroid Build Coastguard Worker // table to understand the format of the rest of the entry.
757*6777b538SAndroid Build Coastguard Worker uint64_t abbreviation_code;
758*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(abbreviation_code)) {
759*6777b538SAndroid Build Coastguard Worker return false;
760*6777b538SAndroid Build Coastguard Worker }
761*6777b538SAndroid Build Coastguard Worker
762*6777b538SAndroid Build Coastguard Worker // Find entry in the abbreviation table.
763*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader abbrev_reader(fd,
764*6777b538SAndroid Build Coastguard Worker debug_abbrev.sh_offset + abbrev_offset);
765*6777b538SAndroid Build Coastguard Worker uint64_t tag;
766*6777b538SAndroid Build Coastguard Worker bool has_children;
767*6777b538SAndroid Build Coastguard Worker AdvancedReaderToAttributeList(abbrev_reader, debug_abbrev_end,
768*6777b538SAndroid Build Coastguard Worker abbreviation_code, tag, has_children);
769*6777b538SAndroid Build Coastguard Worker
770*6777b538SAndroid Build Coastguard Worker // Ignore if it has children.
771*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_TAG_compile_unit = 0x11;
772*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_TAG_partial_unit = 0x3c;
773*6777b538SAndroid Build Coastguard Worker if (tag != kDW_TAG_compile_unit && tag != kDW_TAG_partial_unit) {
774*6777b538SAndroid Build Coastguard Worker return false;
775*6777b538SAndroid Build Coastguard Worker }
776*6777b538SAndroid Build Coastguard Worker
777*6777b538SAndroid Build Coastguard Worker // Use table to parse the name, high, and low attributes.
778*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_AT_name = 0x3; // string
779*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_AT_stmt_list = 0x10; // lineptr
780*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_AT_low_pc = 0x11; // address
781*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_AT_high_pc = 0x12; // address, constant
782*6777b538SAndroid Build Coastguard Worker static constexpr int kDW_AT_ranges = 0x55; // rangelistptr
783*6777b538SAndroid Build Coastguard Worker uint64_t attr;
784*6777b538SAndroid Build Coastguard Worker uint64_t form;
785*6777b538SAndroid Build Coastguard Worker uint64_t low_pc = 0;
786*6777b538SAndroid Build Coastguard Worker uint64_t high_pc = 0;
787*6777b538SAndroid Build Coastguard Worker bool high_pc_is_offset = false;
788*6777b538SAndroid Build Coastguard Worker bool is_found_in_range = false;
789*6777b538SAndroid Build Coastguard Worker do {
790*6777b538SAndroid Build Coastguard Worker if (!abbrev_reader.ReadLeb128(attr)) {
791*6777b538SAndroid Build Coastguard Worker return false;
792*6777b538SAndroid Build Coastguard Worker }
793*6777b538SAndroid Build Coastguard Worker if (!abbrev_reader.ReadLeb128(form)) {
794*6777b538SAndroid Build Coastguard Worker return false;
795*6777b538SAndroid Build Coastguard Worker }
796*6777b538SAndroid Build Coastguard Worker // Table from 7.5.4, Figure 20.
797*6777b538SAndroid Build Coastguard Worker enum Form {
798*6777b538SAndroid Build Coastguard Worker kDW_FORM_addr = 0x01,
799*6777b538SAndroid Build Coastguard Worker kDW_FORM_block2 = 0x03,
800*6777b538SAndroid Build Coastguard Worker kDW_FORM_block4 = 0x04,
801*6777b538SAndroid Build Coastguard Worker kDW_FORM_data2 = 0x05,
802*6777b538SAndroid Build Coastguard Worker kDW_FORM_data4 = 0x06,
803*6777b538SAndroid Build Coastguard Worker kDW_FORM_data8 = 0x07,
804*6777b538SAndroid Build Coastguard Worker kDW_FORM_string = 0x08,
805*6777b538SAndroid Build Coastguard Worker kDW_FORM_block = 0x09,
806*6777b538SAndroid Build Coastguard Worker kDW_FORM_block1 = 0x0a,
807*6777b538SAndroid Build Coastguard Worker kDW_FORM_data1 = 0x0b,
808*6777b538SAndroid Build Coastguard Worker kDW_FORM_flag = 0x0c,
809*6777b538SAndroid Build Coastguard Worker kDW_FORM_sdata = 0x0d,
810*6777b538SAndroid Build Coastguard Worker kDW_FORM_strp = 0x0e,
811*6777b538SAndroid Build Coastguard Worker kDW_FORM_udata = 0x0f,
812*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref_addr = 0x10,
813*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref1 = 0x11,
814*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref2 = 0x12,
815*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref4 = 0x13,
816*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref8 = 0x14,
817*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref_udata = 0x15,
818*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref_indrect = 0x16,
819*6777b538SAndroid Build Coastguard Worker kDW_FORM_sec_offset = 0x17,
820*6777b538SAndroid Build Coastguard Worker kDW_FORM_exprloc = 0x18,
821*6777b538SAndroid Build Coastguard Worker kDW_FORM_flag_present = 0x19,
822*6777b538SAndroid Build Coastguard Worker kDW_FORM_ref_sig8 = 0x20,
823*6777b538SAndroid Build Coastguard Worker };
824*6777b538SAndroid Build Coastguard Worker
825*6777b538SAndroid Build Coastguard Worker switch (form) {
826*6777b538SAndroid Build Coastguard Worker case kDW_FORM_string: {
827*6777b538SAndroid Build Coastguard Worker // Read the value into if necessary `out`
828*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_name) {
829*6777b538SAndroid Build Coastguard Worker *cu_name_offset = reader.position();
830*6777b538SAndroid Build Coastguard Worker }
831*6777b538SAndroid Build Coastguard Worker if (!reader.ReadCString(debug_info_end, nullptr, 0)) {
832*6777b538SAndroid Build Coastguard Worker return false;
833*6777b538SAndroid Build Coastguard Worker }
834*6777b538SAndroid Build Coastguard Worker } break;
835*6777b538SAndroid Build Coastguard Worker
836*6777b538SAndroid Build Coastguard Worker case kDW_FORM_strp: {
837*6777b538SAndroid Build Coastguard Worker uint64_t strp_offset;
838*6777b538SAndroid Build Coastguard Worker if (!reader.ReadOffset(is_64bit, strp_offset)) {
839*6777b538SAndroid Build Coastguard Worker return false;
840*6777b538SAndroid Build Coastguard Worker }
841*6777b538SAndroid Build Coastguard Worker
842*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_name) {
843*6777b538SAndroid Build Coastguard Worker uint64_t pos = debug_str.sh_offset + strp_offset;
844*6777b538SAndroid Build Coastguard Worker if (pos >= debug_str_end) {
845*6777b538SAndroid Build Coastguard Worker return false;
846*6777b538SAndroid Build Coastguard Worker }
847*6777b538SAndroid Build Coastguard Worker *cu_name_offset = pos;
848*6777b538SAndroid Build Coastguard Worker }
849*6777b538SAndroid Build Coastguard Worker } break;
850*6777b538SAndroid Build Coastguard Worker
851*6777b538SAndroid Build Coastguard Worker case kDW_FORM_addr: {
852*6777b538SAndroid Build Coastguard Worker uint64_t address;
853*6777b538SAndroid Build Coastguard Worker if (!reader.ReadAddress(address_size, address)) {
854*6777b538SAndroid Build Coastguard Worker return false;
855*6777b538SAndroid Build Coastguard Worker }
856*6777b538SAndroid Build Coastguard Worker
857*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_low_pc) {
858*6777b538SAndroid Build Coastguard Worker low_pc = address;
859*6777b538SAndroid Build Coastguard Worker } else if (attr == kDW_AT_high_pc) {
860*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = false;
861*6777b538SAndroid Build Coastguard Worker high_pc = address;
862*6777b538SAndroid Build Coastguard Worker }
863*6777b538SAndroid Build Coastguard Worker } break;
864*6777b538SAndroid Build Coastguard Worker
865*6777b538SAndroid Build Coastguard Worker case kDW_FORM_data1: {
866*6777b538SAndroid Build Coastguard Worker uint8_t data;
867*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(data)) {
868*6777b538SAndroid Build Coastguard Worker return false;
869*6777b538SAndroid Build Coastguard Worker }
870*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
871*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
872*6777b538SAndroid Build Coastguard Worker high_pc = data;
873*6777b538SAndroid Build Coastguard Worker }
874*6777b538SAndroid Build Coastguard Worker } break;
875*6777b538SAndroid Build Coastguard Worker
876*6777b538SAndroid Build Coastguard Worker case kDW_FORM_data2: {
877*6777b538SAndroid Build Coastguard Worker uint16_t data;
878*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt16(data)) {
879*6777b538SAndroid Build Coastguard Worker return false;
880*6777b538SAndroid Build Coastguard Worker }
881*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
882*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
883*6777b538SAndroid Build Coastguard Worker high_pc = data;
884*6777b538SAndroid Build Coastguard Worker }
885*6777b538SAndroid Build Coastguard Worker } break;
886*6777b538SAndroid Build Coastguard Worker
887*6777b538SAndroid Build Coastguard Worker case kDW_FORM_data4: {
888*6777b538SAndroid Build Coastguard Worker uint32_t data;
889*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt32(data)) {
890*6777b538SAndroid Build Coastguard Worker return false;
891*6777b538SAndroid Build Coastguard Worker }
892*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
893*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
894*6777b538SAndroid Build Coastguard Worker high_pc = data;
895*6777b538SAndroid Build Coastguard Worker }
896*6777b538SAndroid Build Coastguard Worker } break;
897*6777b538SAndroid Build Coastguard Worker
898*6777b538SAndroid Build Coastguard Worker case kDW_FORM_data8: {
899*6777b538SAndroid Build Coastguard Worker uint64_t data;
900*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt64(data)) {
901*6777b538SAndroid Build Coastguard Worker return false;
902*6777b538SAndroid Build Coastguard Worker }
903*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
904*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
905*6777b538SAndroid Build Coastguard Worker high_pc = data;
906*6777b538SAndroid Build Coastguard Worker }
907*6777b538SAndroid Build Coastguard Worker } break;
908*6777b538SAndroid Build Coastguard Worker
909*6777b538SAndroid Build Coastguard Worker case kDW_FORM_sdata: {
910*6777b538SAndroid Build Coastguard Worker int64_t data;
911*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(data)) {
912*6777b538SAndroid Build Coastguard Worker return false;
913*6777b538SAndroid Build Coastguard Worker }
914*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
915*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
916*6777b538SAndroid Build Coastguard Worker high_pc = static_cast<uint64_t>(data);
917*6777b538SAndroid Build Coastguard Worker }
918*6777b538SAndroid Build Coastguard Worker } break;
919*6777b538SAndroid Build Coastguard Worker
920*6777b538SAndroid Build Coastguard Worker case kDW_FORM_udata: {
921*6777b538SAndroid Build Coastguard Worker uint64_t data;
922*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(data)) {
923*6777b538SAndroid Build Coastguard Worker return false;
924*6777b538SAndroid Build Coastguard Worker }
925*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_high_pc) {
926*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = true;
927*6777b538SAndroid Build Coastguard Worker high_pc = data;
928*6777b538SAndroid Build Coastguard Worker }
929*6777b538SAndroid Build Coastguard Worker } break;
930*6777b538SAndroid Build Coastguard Worker
931*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref_addr:
932*6777b538SAndroid Build Coastguard Worker case kDW_FORM_sec_offset: {
933*6777b538SAndroid Build Coastguard Worker uint64_t value;
934*6777b538SAndroid Build Coastguard Worker if (!reader.ReadOffset(is_64bit, value)) {
935*6777b538SAndroid Build Coastguard Worker return false;
936*6777b538SAndroid Build Coastguard Worker }
937*6777b538SAndroid Build Coastguard Worker
938*6777b538SAndroid Build Coastguard Worker if (attr == kDW_AT_ranges) {
939*6777b538SAndroid Build Coastguard Worker uint64_t current_base_address = module_base_address;
940*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader ranges_reader(fd,
941*6777b538SAndroid Build Coastguard Worker debug_ranges.sh_offset + value);
942*6777b538SAndroid Build Coastguard Worker
943*6777b538SAndroid Build Coastguard Worker while (ranges_reader.position() < debug_ranges_end) {
944*6777b538SAndroid Build Coastguard Worker // Ranges are 2 addresses in size.
945*6777b538SAndroid Build Coastguard Worker uint64_t range_start;
946*6777b538SAndroid Build Coastguard Worker uint64_t range_end;
947*6777b538SAndroid Build Coastguard Worker if (!ranges_reader.ReadAddress(address_size, range_start)) {
948*6777b538SAndroid Build Coastguard Worker return false;
949*6777b538SAndroid Build Coastguard Worker }
950*6777b538SAndroid Build Coastguard Worker if (!ranges_reader.ReadAddress(address_size, range_end)) {
951*6777b538SAndroid Build Coastguard Worker return false;
952*6777b538SAndroid Build Coastguard Worker }
953*6777b538SAndroid Build Coastguard Worker uint64_t relative_pc = pc - current_base_address;
954*6777b538SAndroid Build Coastguard Worker
955*6777b538SAndroid Build Coastguard Worker if (range_start == 0 && range_end == 0) {
956*6777b538SAndroid Build Coastguard Worker if (!is_found_in_range) {
957*6777b538SAndroid Build Coastguard Worker // Time to go to the next iteration.
958*6777b538SAndroid Build Coastguard Worker goto next_cu;
959*6777b538SAndroid Build Coastguard Worker }
960*6777b538SAndroid Build Coastguard Worker break;
961*6777b538SAndroid Build Coastguard Worker } else if (((address_size == 4) &&
962*6777b538SAndroid Build Coastguard Worker (range_start == 0xffffffffUL)) ||
963*6777b538SAndroid Build Coastguard Worker ((address_size == 8) &&
964*6777b538SAndroid Build Coastguard Worker (range_start == 0xffffffffffffffffULL))) {
965*6777b538SAndroid Build Coastguard Worker // Check if this is a new base add value. 2.17.3
966*6777b538SAndroid Build Coastguard Worker current_base_address = range_end;
967*6777b538SAndroid Build Coastguard Worker } else {
968*6777b538SAndroid Build Coastguard Worker if (relative_pc >= range_start && relative_pc < range_end) {
969*6777b538SAndroid Build Coastguard Worker is_found_in_range = true;
970*6777b538SAndroid Build Coastguard Worker break;
971*6777b538SAndroid Build Coastguard Worker }
972*6777b538SAndroid Build Coastguard Worker }
973*6777b538SAndroid Build Coastguard Worker }
974*6777b538SAndroid Build Coastguard Worker } else if (attr == kDW_AT_stmt_list) {
975*6777b538SAndroid Build Coastguard Worker *debug_line_offset = value;
976*6777b538SAndroid Build Coastguard Worker }
977*6777b538SAndroid Build Coastguard Worker } break;
978*6777b538SAndroid Build Coastguard Worker
979*6777b538SAndroid Build Coastguard Worker case kDW_FORM_flag:
980*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref1:
981*6777b538SAndroid Build Coastguard Worker case kDW_FORM_block1: {
982*6777b538SAndroid Build Coastguard Worker uint8_t dummy;
983*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(dummy)) {
984*6777b538SAndroid Build Coastguard Worker return false;
985*6777b538SAndroid Build Coastguard Worker }
986*6777b538SAndroid Build Coastguard Worker } break;
987*6777b538SAndroid Build Coastguard Worker
988*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref2:
989*6777b538SAndroid Build Coastguard Worker case kDW_FORM_block2: {
990*6777b538SAndroid Build Coastguard Worker uint16_t dummy;
991*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt16(dummy)) {
992*6777b538SAndroid Build Coastguard Worker return false;
993*6777b538SAndroid Build Coastguard Worker }
994*6777b538SAndroid Build Coastguard Worker } break;
995*6777b538SAndroid Build Coastguard Worker
996*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref4:
997*6777b538SAndroid Build Coastguard Worker case kDW_FORM_block4: {
998*6777b538SAndroid Build Coastguard Worker uint32_t dummy;
999*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt32(dummy)) {
1000*6777b538SAndroid Build Coastguard Worker return false;
1001*6777b538SAndroid Build Coastguard Worker }
1002*6777b538SAndroid Build Coastguard Worker } break;
1003*6777b538SAndroid Build Coastguard Worker
1004*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref8: {
1005*6777b538SAndroid Build Coastguard Worker uint64_t dummy;
1006*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt64(dummy)) {
1007*6777b538SAndroid Build Coastguard Worker return false;
1008*6777b538SAndroid Build Coastguard Worker }
1009*6777b538SAndroid Build Coastguard Worker } break;
1010*6777b538SAndroid Build Coastguard Worker
1011*6777b538SAndroid Build Coastguard Worker case kDW_FORM_ref_udata:
1012*6777b538SAndroid Build Coastguard Worker case kDW_FORM_block: {
1013*6777b538SAndroid Build Coastguard Worker uint64_t dummy;
1014*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(dummy)) {
1015*6777b538SAndroid Build Coastguard Worker return false;
1016*6777b538SAndroid Build Coastguard Worker }
1017*6777b538SAndroid Build Coastguard Worker } break;
1018*6777b538SAndroid Build Coastguard Worker
1019*6777b538SAndroid Build Coastguard Worker case kDW_FORM_exprloc: {
1020*6777b538SAndroid Build Coastguard Worker uint64_t value;
1021*6777b538SAndroid Build Coastguard Worker if (!reader.ReadLeb128(value)) {
1022*6777b538SAndroid Build Coastguard Worker return false;
1023*6777b538SAndroid Build Coastguard Worker }
1024*6777b538SAndroid Build Coastguard Worker reader.set_position(reader.position() + value);
1025*6777b538SAndroid Build Coastguard Worker } break;
1026*6777b538SAndroid Build Coastguard Worker }
1027*6777b538SAndroid Build Coastguard Worker } while (attr != 0 || form != 0);
1028*6777b538SAndroid Build Coastguard Worker
1029*6777b538SAndroid Build Coastguard Worker // Because attributes can be in any order, most of the computations (minus
1030*6777b538SAndroid Build Coastguard Worker // checking range list entries) cannot happen until everything is parsed for
1031*6777b538SAndroid Build Coastguard Worker // the one .debug_info entry. Do the analysis here.
1032*6777b538SAndroid Build Coastguard Worker if (is_found_in_range) {
1033*6777b538SAndroid Build Coastguard Worker // Well formed compile_unit and partial_unit tags either have a
1034*6777b538SAndroid Build Coastguard Worker // DT_AT_ranges entry or an DT_AT_low_pc entiry. If is_found_in_range
1035*6777b538SAndroid Build Coastguard Worker // matched as true, then this entry matches the given pc.
1036*6777b538SAndroid Build Coastguard Worker return true;
1037*6777b538SAndroid Build Coastguard Worker }
1038*6777b538SAndroid Build Coastguard Worker
1039*6777b538SAndroid Build Coastguard Worker // If high_pc_is_offset is 0, it was never found in the DIE. This indicates
1040*6777b538SAndroid Build Coastguard Worker // a single address entry. Only look at the low_pc.
1041*6777b538SAndroid Build Coastguard Worker {
1042*6777b538SAndroid Build Coastguard Worker uint64_t module_relative_pc = pc - module_base_address;
1043*6777b538SAndroid Build Coastguard Worker if (high_pc == 0 && module_relative_pc != low_pc) {
1044*6777b538SAndroid Build Coastguard Worker goto next_cu;
1045*6777b538SAndroid Build Coastguard Worker }
1046*6777b538SAndroid Build Coastguard Worker
1047*6777b538SAndroid Build Coastguard Worker // Otherwise this is a contiguous range DIE. Normalize the meaning of the
1048*6777b538SAndroid Build Coastguard Worker // high_pc field and check if it contains the pc.
1049*6777b538SAndroid Build Coastguard Worker if (high_pc_is_offset) {
1050*6777b538SAndroid Build Coastguard Worker high_pc = low_pc + high_pc;
1051*6777b538SAndroid Build Coastguard Worker high_pc_is_offset = false;
1052*6777b538SAndroid Build Coastguard Worker }
1053*6777b538SAndroid Build Coastguard Worker
1054*6777b538SAndroid Build Coastguard Worker if (module_relative_pc >= low_pc && module_relative_pc < high_pc) {
1055*6777b538SAndroid Build Coastguard Worker return true;
1056*6777b538SAndroid Build Coastguard Worker }
1057*6777b538SAndroid Build Coastguard Worker }
1058*6777b538SAndroid Build Coastguard Worker
1059*6777b538SAndroid Build Coastguard Worker // Not found.
1060*6777b538SAndroid Build Coastguard Worker next_cu:;
1061*6777b538SAndroid Build Coastguard Worker }
1062*6777b538SAndroid Build Coastguard Worker return false;
1063*6777b538SAndroid Build Coastguard Worker }
1064*6777b538SAndroid Build Coastguard Worker
1065*6777b538SAndroid Build Coastguard Worker // Thin wrapper over `GetCompileUnitName` that opens the .debug_info section.
ReadCompileUnit(int fd,uint64_t pc,uint64_t cu_offset,uint64_t base_address,uint64_t * debug_line_offset,uint64_t * cu_name_offset)1066*6777b538SAndroid Build Coastguard Worker bool ReadCompileUnit(int fd,
1067*6777b538SAndroid Build Coastguard Worker uint64_t pc,
1068*6777b538SAndroid Build Coastguard Worker uint64_t cu_offset,
1069*6777b538SAndroid Build Coastguard Worker uint64_t base_address,
1070*6777b538SAndroid Build Coastguard Worker uint64_t* debug_line_offset,
1071*6777b538SAndroid Build Coastguard Worker uint64_t* cu_name_offset) {
1072*6777b538SAndroid Build Coastguard Worker if (cu_offset == 0) {
1073*6777b538SAndroid Build Coastguard Worker return false;
1074*6777b538SAndroid Build Coastguard Worker }
1075*6777b538SAndroid Build Coastguard Worker
1076*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_info;
1077*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugInfoSectionName[] = ".debug_info";
1078*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(fd, kDebugInfoSectionName,
1079*6777b538SAndroid Build Coastguard Worker sizeof(kDebugInfoSectionName),
1080*6777b538SAndroid Build Coastguard Worker &debug_info)) {
1081*6777b538SAndroid Build Coastguard Worker return false;
1082*6777b538SAndroid Build Coastguard Worker }
1083*6777b538SAndroid Build Coastguard Worker uint64_t debug_info_end = debug_info.sh_offset + debug_info.sh_size;
1084*6777b538SAndroid Build Coastguard Worker
1085*6777b538SAndroid Build Coastguard Worker return GetCompileUnitName(fd, debug_info.sh_offset + cu_offset,
1086*6777b538SAndroid Build Coastguard Worker debug_info_end, pc, base_address, debug_line_offset,
1087*6777b538SAndroid Build Coastguard Worker cu_name_offset);
1088*6777b538SAndroid Build Coastguard Worker }
1089*6777b538SAndroid Build Coastguard Worker
1090*6777b538SAndroid Build Coastguard Worker // Takes the information from `info` and renders the data located in the
1091*6777b538SAndroid Build Coastguard Worker // object file `fd` into `out`. The format looks like:
1092*6777b538SAndroid Build Coastguard Worker //
1093*6777b538SAndroid Build Coastguard Worker // [../path/to/foo.cc:10:40]
1094*6777b538SAndroid Build Coastguard Worker //
1095*6777b538SAndroid Build Coastguard Worker // which would indicate line 10 column 40 in ../path/to/foo.cc
SerializeLineNumberInfoToString(int fd,const LineNumberInfo & info,char * out,size_t out_size)1096*6777b538SAndroid Build Coastguard Worker void SerializeLineNumberInfoToString(int fd,
1097*6777b538SAndroid Build Coastguard Worker const LineNumberInfo& info,
1098*6777b538SAndroid Build Coastguard Worker char* out,
1099*6777b538SAndroid Build Coastguard Worker size_t out_size) {
1100*6777b538SAndroid Build Coastguard Worker size_t out_pos = 0;
1101*6777b538SAndroid Build Coastguard Worker if (info.module_filename_offset) {
1102*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader reader(fd, info.module_dir_offset);
1103*6777b538SAndroid Build Coastguard Worker if (info.module_dir_offset != 0) {
1104*6777b538SAndroid Build Coastguard Worker out_pos +=
1105*6777b538SAndroid Build Coastguard Worker reader.ReadCString(kMaxOffset, out + out_pos, out_size - out_pos);
1106*6777b538SAndroid Build Coastguard Worker out[out_pos - 1] = '/';
1107*6777b538SAndroid Build Coastguard Worker }
1108*6777b538SAndroid Build Coastguard Worker
1109*6777b538SAndroid Build Coastguard Worker reader.set_position(info.module_filename_offset);
1110*6777b538SAndroid Build Coastguard Worker out_pos +=
1111*6777b538SAndroid Build Coastguard Worker reader.ReadCString(kMaxOffset, out + out_pos, out_size - out_pos);
1112*6777b538SAndroid Build Coastguard Worker } else {
1113*6777b538SAndroid Build Coastguard Worker out[out_pos++] = '\0';
1114*6777b538SAndroid Build Coastguard Worker }
1115*6777b538SAndroid Build Coastguard Worker
1116*6777b538SAndroid Build Coastguard Worker out[out_pos - 1] = ':';
1117*6777b538SAndroid Build Coastguard Worker auto result = std::to_chars(out + out_pos, out + out_size,
1118*6777b538SAndroid Build Coastguard Worker static_cast<intptr_t>(info.line));
1119*6777b538SAndroid Build Coastguard Worker if (result.ec != std::errc()) {
1120*6777b538SAndroid Build Coastguard Worker out[out_pos - 1] = '\0';
1121*6777b538SAndroid Build Coastguard Worker return;
1122*6777b538SAndroid Build Coastguard Worker }
1123*6777b538SAndroid Build Coastguard Worker out_pos = static_cast<size_t>(result.ptr - out);
1124*6777b538SAndroid Build Coastguard Worker
1125*6777b538SAndroid Build Coastguard Worker out[out_pos++] = ':';
1126*6777b538SAndroid Build Coastguard Worker result = std::to_chars(out + out_pos, out + out_size,
1127*6777b538SAndroid Build Coastguard Worker static_cast<intptr_t>(info.column));
1128*6777b538SAndroid Build Coastguard Worker if (result.ec != std::errc()) {
1129*6777b538SAndroid Build Coastguard Worker out[out_pos - 1] = '\0';
1130*6777b538SAndroid Build Coastguard Worker return;
1131*6777b538SAndroid Build Coastguard Worker }
1132*6777b538SAndroid Build Coastguard Worker out_pos = static_cast<size_t>(result.ptr - out);
1133*6777b538SAndroid Build Coastguard Worker
1134*6777b538SAndroid Build Coastguard Worker out[out_pos++] = '\0';
1135*6777b538SAndroid Build Coastguard Worker }
1136*6777b538SAndroid Build Coastguard Worker
1137*6777b538SAndroid Build Coastguard Worker // Reads the Line Number info for a compile unit.
GetLineNumberInfoFromObject(int fd,uint64_t pc,uint64_t cu_offset,uint64_t base_address,char * out,size_t out_size)1138*6777b538SAndroid Build Coastguard Worker bool GetLineNumberInfoFromObject(int fd,
1139*6777b538SAndroid Build Coastguard Worker uint64_t pc,
1140*6777b538SAndroid Build Coastguard Worker uint64_t cu_offset,
1141*6777b538SAndroid Build Coastguard Worker uint64_t base_address,
1142*6777b538SAndroid Build Coastguard Worker char* out,
1143*6777b538SAndroid Build Coastguard Worker size_t out_size) {
1144*6777b538SAndroid Build Coastguard Worker uint64_t cu_name_offset;
1145*6777b538SAndroid Build Coastguard Worker uint64_t debug_line_offset;
1146*6777b538SAndroid Build Coastguard Worker if (!ReadCompileUnit(fd, pc, cu_offset, base_address, &debug_line_offset,
1147*6777b538SAndroid Build Coastguard Worker &cu_name_offset)) {
1148*6777b538SAndroid Build Coastguard Worker return false;
1149*6777b538SAndroid Build Coastguard Worker }
1150*6777b538SAndroid Build Coastguard Worker
1151*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_line;
1152*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugLineSectionName[] = ".debug_line";
1153*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(fd, kDebugLineSectionName,
1154*6777b538SAndroid Build Coastguard Worker sizeof(kDebugLineSectionName),
1155*6777b538SAndroid Build Coastguard Worker &debug_line)) {
1156*6777b538SAndroid Build Coastguard Worker return false;
1157*6777b538SAndroid Build Coastguard Worker }
1158*6777b538SAndroid Build Coastguard Worker
1159*6777b538SAndroid Build Coastguard Worker LineNumberInfo info;
1160*6777b538SAndroid Build Coastguard Worker info.pc = pc;
1161*6777b538SAndroid Build Coastguard Worker uint64_t line_info_program_offset = debug_line.sh_offset + debug_line_offset;
1162*6777b538SAndroid Build Coastguard Worker GetLineNumbersInProgram(fd, &info, base_address, line_info_program_offset,
1163*6777b538SAndroid Build Coastguard Worker cu_name_offset);
1164*6777b538SAndroid Build Coastguard Worker
1165*6777b538SAndroid Build Coastguard Worker if (info.line == 0) {
1166*6777b538SAndroid Build Coastguard Worker // No matching line number or filename found.
1167*6777b538SAndroid Build Coastguard Worker return false;
1168*6777b538SAndroid Build Coastguard Worker }
1169*6777b538SAndroid Build Coastguard Worker
1170*6777b538SAndroid Build Coastguard Worker SerializeLineNumberInfoToString(fd, info, out, out_size);
1171*6777b538SAndroid Build Coastguard Worker
1172*6777b538SAndroid Build Coastguard Worker return true;
1173*6777b538SAndroid Build Coastguard Worker }
1174*6777b538SAndroid Build Coastguard Worker
1175*6777b538SAndroid Build Coastguard Worker struct FrameInfo {
1176*6777b538SAndroid Build Coastguard Worker raw_ptr<uint64_t> cu_offset;
1177*6777b538SAndroid Build Coastguard Worker uintptr_t pc;
1178*6777b538SAndroid Build Coastguard Worker };
1179*6777b538SAndroid Build Coastguard Worker
1180*6777b538SAndroid Build Coastguard Worker // Returns the number of frames still missing info.
1181*6777b538SAndroid Build Coastguard Worker //
1182*6777b538SAndroid Build Coastguard Worker // The aranges table is a mapping of ranges to compilation units. Given an array
1183*6777b538SAndroid Build Coastguard Worker // of `frame_info`, this finds the compile units for each of the frames doing
1184*6777b538SAndroid Build Coastguard Worker // only one pass over the table. It does not preserve the order of `frame_info`.
1185*6777b538SAndroid Build Coastguard Worker //
1186*6777b538SAndroid Build Coastguard Worker // The main benefit of this function is preserving the single pass through the
1187*6777b538SAndroid Build Coastguard Worker // table which is important for performance.
ProcessFlatArangeSet(BufferedDwarfReader * reader,uint64_t next_set,uint8_t address_size,uint64_t base_address,uint64_t cu_offset,FrameInfo * frame_info,size_t num_frames)1188*6777b538SAndroid Build Coastguard Worker size_t ProcessFlatArangeSet(BufferedDwarfReader* reader,
1189*6777b538SAndroid Build Coastguard Worker uint64_t next_set,
1190*6777b538SAndroid Build Coastguard Worker uint8_t address_size,
1191*6777b538SAndroid Build Coastguard Worker uint64_t base_address,
1192*6777b538SAndroid Build Coastguard Worker uint64_t cu_offset,
1193*6777b538SAndroid Build Coastguard Worker FrameInfo* frame_info,
1194*6777b538SAndroid Build Coastguard Worker size_t num_frames) {
1195*6777b538SAndroid Build Coastguard Worker size_t unsorted_start = 0;
1196*6777b538SAndroid Build Coastguard Worker while (unsorted_start < num_frames && reader->position() < next_set) {
1197*6777b538SAndroid Build Coastguard Worker uint64_t start;
1198*6777b538SAndroid Build Coastguard Worker uint64_t length;
1199*6777b538SAndroid Build Coastguard Worker if (!reader->ReadAddress(address_size, start)) {
1200*6777b538SAndroid Build Coastguard Worker break;
1201*6777b538SAndroid Build Coastguard Worker }
1202*6777b538SAndroid Build Coastguard Worker if (!reader->ReadAddress(address_size, length)) {
1203*6777b538SAndroid Build Coastguard Worker break;
1204*6777b538SAndroid Build Coastguard Worker }
1205*6777b538SAndroid Build Coastguard Worker uint64_t end = start + length;
1206*6777b538SAndroid Build Coastguard Worker for (size_t i = unsorted_start; i < num_frames; ++i) {
1207*6777b538SAndroid Build Coastguard Worker uint64_t module_relative_pc = frame_info[i].pc - base_address;
1208*6777b538SAndroid Build Coastguard Worker if (start <= module_relative_pc && module_relative_pc < end) {
1209*6777b538SAndroid Build Coastguard Worker *frame_info[i].cu_offset = cu_offset;
1210*6777b538SAndroid Build Coastguard Worker if (i != unsorted_start) {
1211*6777b538SAndroid Build Coastguard Worker // Move to sorted section.
1212*6777b538SAndroid Build Coastguard Worker std::swap(frame_info[i], frame_info[unsorted_start]);
1213*6777b538SAndroid Build Coastguard Worker }
1214*6777b538SAndroid Build Coastguard Worker unsorted_start++;
1215*6777b538SAndroid Build Coastguard Worker }
1216*6777b538SAndroid Build Coastguard Worker }
1217*6777b538SAndroid Build Coastguard Worker }
1218*6777b538SAndroid Build Coastguard Worker
1219*6777b538SAndroid Build Coastguard Worker return unsorted_start;
1220*6777b538SAndroid Build Coastguard Worker }
1221*6777b538SAndroid Build Coastguard Worker
1222*6777b538SAndroid Build Coastguard Worker // This is a pre-step that uses the .debug_aranges table to find all the compile
1223*6777b538SAndroid Build Coastguard Worker // units for a given set of frames. This allows code to avoid iterating over
1224*6777b538SAndroid Build Coastguard Worker // all compile units at a later step in the symbolization process.
PopulateCompileUnitOffsets(int fd,FrameInfo * frame_info,size_t num_frames,uint64_t base_address)1225*6777b538SAndroid Build Coastguard Worker void PopulateCompileUnitOffsets(int fd,
1226*6777b538SAndroid Build Coastguard Worker FrameInfo* frame_info,
1227*6777b538SAndroid Build Coastguard Worker size_t num_frames,
1228*6777b538SAndroid Build Coastguard Worker uint64_t base_address) {
1229*6777b538SAndroid Build Coastguard Worker ElfW(Shdr) debug_aranges;
1230*6777b538SAndroid Build Coastguard Worker constexpr static char kDebugArangesSectionName[] = ".debug_aranges";
1231*6777b538SAndroid Build Coastguard Worker if (!google::GetSectionHeaderByName(fd, kDebugArangesSectionName,
1232*6777b538SAndroid Build Coastguard Worker sizeof(kDebugArangesSectionName),
1233*6777b538SAndroid Build Coastguard Worker &debug_aranges)) {
1234*6777b538SAndroid Build Coastguard Worker return;
1235*6777b538SAndroid Build Coastguard Worker }
1236*6777b538SAndroid Build Coastguard Worker uint64_t debug_aranges_end = debug_aranges.sh_offset + debug_aranges.sh_size;
1237*6777b538SAndroid Build Coastguard Worker uint64_t next_arange_set = kMaxOffset;
1238*6777b538SAndroid Build Coastguard Worker size_t unsorted_start = 0;
1239*6777b538SAndroid Build Coastguard Worker for (BufferedDwarfReader reader(fd, debug_aranges.sh_offset);
1240*6777b538SAndroid Build Coastguard Worker unsorted_start < num_frames && reader.position() < debug_aranges_end;
1241*6777b538SAndroid Build Coastguard Worker reader.set_position(next_arange_set)) {
1242*6777b538SAndroid Build Coastguard Worker bool is_64bit;
1243*6777b538SAndroid Build Coastguard Worker uint64_t length;
1244*6777b538SAndroid Build Coastguard Worker uint16_t arange_version;
1245*6777b538SAndroid Build Coastguard Worker uint64_t debug_info_offset;
1246*6777b538SAndroid Build Coastguard Worker uint8_t address_size;
1247*6777b538SAndroid Build Coastguard Worker if (!reader.ReadCommonHeader(is_64bit, length, arange_version,
1248*6777b538SAndroid Build Coastguard Worker debug_info_offset, address_size,
1249*6777b538SAndroid Build Coastguard Worker next_arange_set)) {
1250*6777b538SAndroid Build Coastguard Worker return;
1251*6777b538SAndroid Build Coastguard Worker }
1252*6777b538SAndroid Build Coastguard Worker
1253*6777b538SAndroid Build Coastguard Worker uint8_t segment_size;
1254*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(segment_size)) {
1255*6777b538SAndroid Build Coastguard Worker return;
1256*6777b538SAndroid Build Coastguard Worker }
1257*6777b538SAndroid Build Coastguard Worker
1258*6777b538SAndroid Build Coastguard Worker if (segment_size != 0) {
1259*6777b538SAndroid Build Coastguard Worker // Only flat namespaces are supported.
1260*6777b538SAndroid Build Coastguard Worker return;
1261*6777b538SAndroid Build Coastguard Worker }
1262*6777b538SAndroid Build Coastguard Worker
1263*6777b538SAndroid Build Coastguard Worker // The tuple list is aligned, to a multiple of the tuple-size after the
1264*6777b538SAndroid Build Coastguard Worker // section sstart. Because this code only supports flat address spaces, this
1265*6777b538SAndroid Build Coastguard Worker // means 2*address_size.
1266*6777b538SAndroid Build Coastguard Worker while (((reader.position() - debug_aranges.sh_offset) %
1267*6777b538SAndroid Build Coastguard Worker (2 * address_size)) != 0) {
1268*6777b538SAndroid Build Coastguard Worker uint8_t dummy;
1269*6777b538SAndroid Build Coastguard Worker if (!reader.ReadInt8(dummy)) {
1270*6777b538SAndroid Build Coastguard Worker return;
1271*6777b538SAndroid Build Coastguard Worker }
1272*6777b538SAndroid Build Coastguard Worker }
1273*6777b538SAndroid Build Coastguard Worker unsorted_start += ProcessFlatArangeSet(
1274*6777b538SAndroid Build Coastguard Worker &reader, next_arange_set, address_size, base_address, debug_info_offset,
1275*6777b538SAndroid Build Coastguard Worker &frame_info[unsorted_start], num_frames - unsorted_start);
1276*6777b538SAndroid Build Coastguard Worker }
1277*6777b538SAndroid Build Coastguard Worker }
1278*6777b538SAndroid Build Coastguard Worker
1279*6777b538SAndroid Build Coastguard Worker } // namespace
1280*6777b538SAndroid Build Coastguard Worker
GetDwarfSourceLineNumber(const void * pc,uint64_t cu_offset,char * out,size_t out_size)1281*6777b538SAndroid Build Coastguard Worker bool GetDwarfSourceLineNumber(const void* pc,
1282*6777b538SAndroid Build Coastguard Worker uint64_t cu_offset,
1283*6777b538SAndroid Build Coastguard Worker char* out,
1284*6777b538SAndroid Build Coastguard Worker size_t out_size) {
1285*6777b538SAndroid Build Coastguard Worker uint64_t pc0 = reinterpret_cast<uint64_t>(pc);
1286*6777b538SAndroid Build Coastguard Worker uint64_t object_start_address = 0;
1287*6777b538SAndroid Build Coastguard Worker uint64_t object_base_address = 0;
1288*6777b538SAndroid Build Coastguard Worker
1289*6777b538SAndroid Build Coastguard Worker google::FileDescriptor object_fd(google::FileDescriptor(
1290*6777b538SAndroid Build Coastguard Worker google::OpenObjectFileContainingPcAndGetStartAddress(
1291*6777b538SAndroid Build Coastguard Worker pc0, object_start_address, object_base_address, nullptr, 0)));
1292*6777b538SAndroid Build Coastguard Worker
1293*6777b538SAndroid Build Coastguard Worker if (!object_fd.get()) {
1294*6777b538SAndroid Build Coastguard Worker return false;
1295*6777b538SAndroid Build Coastguard Worker }
1296*6777b538SAndroid Build Coastguard Worker
1297*6777b538SAndroid Build Coastguard Worker if (!GetLineNumberInfoFromObject(object_fd.get(), pc0, cu_offset,
1298*6777b538SAndroid Build Coastguard Worker object_base_address, out, out_size)) {
1299*6777b538SAndroid Build Coastguard Worker return false;
1300*6777b538SAndroid Build Coastguard Worker }
1301*6777b538SAndroid Build Coastguard Worker
1302*6777b538SAndroid Build Coastguard Worker return true;
1303*6777b538SAndroid Build Coastguard Worker }
1304*6777b538SAndroid Build Coastguard Worker
GetDwarfCompileUnitOffsets(const void * const * trace,uint64_t * cu_offsets,size_t num_frames)1305*6777b538SAndroid Build Coastguard Worker void GetDwarfCompileUnitOffsets(const void* const* trace,
1306*6777b538SAndroid Build Coastguard Worker uint64_t* cu_offsets,
1307*6777b538SAndroid Build Coastguard Worker size_t num_frames) {
1308*6777b538SAndroid Build Coastguard Worker // LINT.IfChange(max_stack_frames)
1309*6777b538SAndroid Build Coastguard Worker FrameInfo frame_info[250] = {};
1310*6777b538SAndroid Build Coastguard Worker // LINT.ThenChange(stack_trace.h:max_stack_frames)
1311*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < num_frames; i++) {
1312*6777b538SAndroid Build Coastguard Worker // The `cu_offset` also encodes the original sort order.
1313*6777b538SAndroid Build Coastguard Worker frame_info[i].cu_offset = &cu_offsets[i];
1314*6777b538SAndroid Build Coastguard Worker frame_info[i].pc = reinterpret_cast<uintptr_t>(trace[i]);
1315*6777b538SAndroid Build Coastguard Worker }
1316*6777b538SAndroid Build Coastguard Worker auto pc_comparator = [](const FrameInfo& lhs, const FrameInfo& rhs) {
1317*6777b538SAndroid Build Coastguard Worker return lhs.pc < rhs.pc;
1318*6777b538SAndroid Build Coastguard Worker };
1319*6777b538SAndroid Build Coastguard Worker
1320*6777b538SAndroid Build Coastguard Worker // Use heapsort to avoid recursion in a signal handler.
1321*6777b538SAndroid Build Coastguard Worker std::make_heap(&frame_info[0], &frame_info[num_frames - 1], pc_comparator);
1322*6777b538SAndroid Build Coastguard Worker std::sort_heap(&frame_info[0], &frame_info[num_frames - 1], pc_comparator);
1323*6777b538SAndroid Build Coastguard Worker
1324*6777b538SAndroid Build Coastguard Worker // Walk the frame_info one compilation unit at a time.
1325*6777b538SAndroid Build Coastguard Worker for (size_t cur_frame = 0; cur_frame < num_frames; ++cur_frame) {
1326*6777b538SAndroid Build Coastguard Worker uint64_t object_start_address = 0;
1327*6777b538SAndroid Build Coastguard Worker uint64_t object_base_address = 0;
1328*6777b538SAndroid Build Coastguard Worker google::FileDescriptor object_fd(google::FileDescriptor(
1329*6777b538SAndroid Build Coastguard Worker google::OpenObjectFileContainingPcAndGetStartAddress(
1330*6777b538SAndroid Build Coastguard Worker frame_info[cur_frame].pc, object_start_address, object_base_address,
1331*6777b538SAndroid Build Coastguard Worker nullptr, 0)));
1332*6777b538SAndroid Build Coastguard Worker
1333*6777b538SAndroid Build Coastguard Worker // Some stack frames may not have a corresponding object file, e.g. a call
1334*6777b538SAndroid Build Coastguard Worker // frame inside the Linux kernel's vdso. Just skip over these stack frames,
1335*6777b538SAndroid Build Coastguard Worker // as this is done on a best-effort basis.
1336*6777b538SAndroid Build Coastguard Worker if (object_fd.get() < 0) {
1337*6777b538SAndroid Build Coastguard Worker continue;
1338*6777b538SAndroid Build Coastguard Worker }
1339*6777b538SAndroid Build Coastguard Worker
1340*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1335630): Consider exposing the end address so a
1341*6777b538SAndroid Build Coastguard Worker // range of frames can be bulk-populated. This was originally implemented,
1342*6777b538SAndroid Build Coastguard Worker // but line number symbolization is currently broken by default (and also
1343*6777b538SAndroid Build Coastguard Worker // broken in sandboxed processes). The various issues will be addressed
1344*6777b538SAndroid Build Coastguard Worker // incrementally in follow-up patches, and the optimization here restored if
1345*6777b538SAndroid Build Coastguard Worker // needed.
1346*6777b538SAndroid Build Coastguard Worker
1347*6777b538SAndroid Build Coastguard Worker PopulateCompileUnitOffsets(object_fd.get(), &frame_info[cur_frame], 1,
1348*6777b538SAndroid Build Coastguard Worker object_base_address);
1349*6777b538SAndroid Build Coastguard Worker }
1350*6777b538SAndroid Build Coastguard Worker }
1351*6777b538SAndroid Build Coastguard Worker
1352*6777b538SAndroid Build Coastguard Worker } // namespace debug
1353*6777b538SAndroid Build Coastguard Worker } // namespace base
1354*6777b538SAndroid Build Coastguard Worker
1355*6777b538SAndroid Build Coastguard Worker #else // USE_SYMBOLIZE
1356*6777b538SAndroid Build Coastguard Worker
1357*6777b538SAndroid Build Coastguard Worker #include <cstring>
1358*6777b538SAndroid Build Coastguard Worker
1359*6777b538SAndroid Build Coastguard Worker namespace base {
1360*6777b538SAndroid Build Coastguard Worker namespace debug {
1361*6777b538SAndroid Build Coastguard Worker
GetDwarfSourceLineNumber(const void * pc,uint64_t cu_offset,char * out,size_t out_size)1362*6777b538SAndroid Build Coastguard Worker bool GetDwarfSourceLineNumber(const void* pc,
1363*6777b538SAndroid Build Coastguard Worker uint64_t cu_offset,
1364*6777b538SAndroid Build Coastguard Worker char* out,
1365*6777b538SAndroid Build Coastguard Worker size_t out_size) {
1366*6777b538SAndroid Build Coastguard Worker return false;
1367*6777b538SAndroid Build Coastguard Worker }
1368*6777b538SAndroid Build Coastguard Worker
GetDwarfCompileUnitOffsets(const void * const * trace,uint64_t * cu_offsets,size_t num_frames)1369*6777b538SAndroid Build Coastguard Worker void GetDwarfCompileUnitOffsets(const void* const* trace,
1370*6777b538SAndroid Build Coastguard Worker uint64_t* cu_offsets,
1371*6777b538SAndroid Build Coastguard Worker size_t num_frames) {
1372*6777b538SAndroid Build Coastguard Worker // Provide defined values even in the stub.
1373*6777b538SAndroid Build Coastguard Worker memset(cu_offsets, 0, sizeof(cu_offsets) * num_frames);
1374*6777b538SAndroid Build Coastguard Worker }
1375*6777b538SAndroid Build Coastguard Worker
1376*6777b538SAndroid Build Coastguard Worker } // namespace debug
1377*6777b538SAndroid Build Coastguard Worker } // namespace base
1378*6777b538SAndroid Build Coastguard Worker
1379*6777b538SAndroid Build Coastguard Worker #endif
1380