line_info.cc
Go to the documentation of this file.
1 // Copyright 2016 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dwarf/line_info.h"
16 
17 #include "dwarf/dwarf_util.h"
18 #include "dwarf_constants.h"
19 
20 using namespace dwarf2reader;
21 using absl::string_view;
22 
23 namespace bloaty {
24 
25 extern int verbose_level;
26 
27 namespace dwarf {
28 
29 const std::string& LineInfoReader::GetExpandedFilename(size_t index) {
30  if (index >= filenames_.size()) {
31  THROW("filename index out of range");
32  }
33 
34  // Generate these lazily.
35  if (expanded_filenames_.size() <= index) {
36  expanded_filenames_.resize(filenames_.size());
37  }
38 
39  std::string& ret = expanded_filenames_[index];
40  if (ret.empty()) {
41  const FileName& filename = filenames_[index];
42  absl::string_view directory = include_directories_[filename.directory_index];
44  if (!ret.empty()) {
45  ret += "/";
46  }
47  ret += std::string(filename.name);
48  }
49  return ret;
50 }
51 
52 void LineInfoReader::Advance(uint64_t amount) {
53  if (params_.maximum_operations_per_instruction == 1) {
54  // This is by far the common case (only false on VLIW architectuers),
55  // and this inlining/specialization avoids a costly division.
56  DoAdvance(amount, 1);
57  } else {
58  DoAdvance(amount, params_.maximum_operations_per_instruction);
59  }
60 }
61 
62 void LineInfoReader::DoAdvance(uint64_t advance, uint8_t max_per_instr) {
63  info_.address += params_.minimum_instruction_length *
64  ((info_.op_index + advance) / max_per_instr);
65  info_.op_index = (info_.op_index + advance) % max_per_instr;
66 }
67 
68 void LineInfoReader::SpecialOpcodeAdvance(uint8_t op) {
69  Advance(AdjustedOpcode(op) / params_.line_range);
70 }
71 
72 uint8_t LineInfoReader::AdjustedOpcode(uint8_t op) {
73  return op - params_.opcode_base;
74 }
75 
76 void LineInfoReader::SeekToOffset(uint64_t offset, uint8_t address_size) {
77  string_view data = file_.debug_line;
79 
80  sizes_.SetAddressSize(address_size);
81  data = sizes_.ReadInitialLength(&data);
82  sizes_.ReadDWARFVersion(&data);
83  uint64_t header_length = sizes_.ReadDWARFOffset(&data);
84  string_view program = data;
85  SkipBytes(header_length, &program);
86 
87  params_.minimum_instruction_length = ReadFixed<uint8_t>(&data);
88  if (sizes_.dwarf_version() == 4) {
89  params_.maximum_operations_per_instruction = ReadFixed<uint8_t>(&data);
90 
91  if (params_.maximum_operations_per_instruction == 0) {
92  THROW("DWARF line info had maximum_operations_per_instruction=0");
93  }
94  } else {
95  params_.maximum_operations_per_instruction = 1;
96  }
97  params_.default_is_stmt = ReadFixed<uint8_t>(&data);
98  params_.line_base = ReadFixed<int8_t>(&data);
99  params_.line_range = ReadFixed<uint8_t>(&data);
100  params_.opcode_base = ReadFixed<uint8_t>(&data);
101  if (params_.line_range == 0) {
102  THROW("line_range of zero will cause divide by zero");
103  }
104 
105  standard_opcode_lengths_.resize(params_.opcode_base);
106  for (size_t i = 1; i < params_.opcode_base; i++) {
107  standard_opcode_lengths_[i] = ReadFixed<uint8_t>(&data);
108  }
109 
110  // Read include_directories.
111  include_directories_.clear();
112 
113  // Implicit current directory entry.
114  include_directories_.push_back(string_view());
115 
116  while (true) {
118  if (dir.empty()) {
119  break;
120  }
121  include_directories_.push_back(dir);
122  }
123 
124  // Read file_names.
125  filenames_.clear();
126  expanded_filenames_.clear();
127 
128  // Filename 0 is unused.
129  filenames_.push_back(FileName());
130  while (true) {
131  FileName file_name;
132  file_name.name = ReadNullTerminated(&data);
133  if (file_name.name.empty()) {
134  break;
135  }
136  file_name.directory_index = ReadLEB128<uint32_t>(&data);
137  file_name.modified_time = ReadLEB128<uint64_t>(&data);
138  file_name.file_size = ReadLEB128<uint64_t>(&data);
139  if (file_name.directory_index >= include_directories_.size()) {
140  THROW("directory index out of range");
141  }
142  filenames_.push_back(file_name);
143  }
144 
145  info_ = LineInfo(params_.default_is_stmt);
146  remaining_ = program;
147  shadow_ = false;
148 }
149 
150 bool LineInfoReader::ReadLineInfo() {
151  // Final step of last DW_LNS_copy / special opcode.
152  info_.discriminator = 0;
153  info_.basic_block = false;
154  info_.prologue_end = false;
155  info_.epilogue_begin = false;
156 
157  // Final step of DW_LNE_end_sequence.
158  info_.end_sequence = false;
159 
161 
162  while (true) {
163  if (data.empty()) {
164  remaining_ = data;
165  return false;
166  }
167 
168  uint8_t op = ReadFixed<uint8_t>(&data);
169 
170  if (op >= params_.opcode_base) {
171  SpecialOpcodeAdvance(op);
172  info_.line +=
173  params_.line_base + (AdjustedOpcode(op) % params_.line_range);
174  if (!shadow_) {
175  remaining_ = data;
176  return true;
177  }
178  } else {
179  switch (op) {
180  case DW_LNS_extended_op: {
181  uint16_t len = ReadLEB128<uint16_t>(&data);
182  uint8_t extended_op = ReadFixed<uint8_t>(&data);
183  switch (extended_op) {
184  case DW_LNE_end_sequence: {
185  // Preserve address and set end_sequence, but reset everything
186  // else.
187  uint64_t addr = info_.address;
188  info_ = LineInfo(params_.default_is_stmt);
189  info_.address = addr;
190  info_.end_sequence = true;
191  if (!shadow_) {
192  remaining_ = data;
193  return true;
194  }
195  break;
196  }
197  case DW_LNE_set_address:
198  info_.address = sizes_.ReadAddress(&data);
199  info_.op_index = 0;
200  shadow_ = (info_.address == 0);
201  break;
202  case DW_LNE_define_file: {
203  FileName file_name;
204  file_name.name = ReadNullTerminated(&data);
205  file_name.directory_index = ReadLEB128<uint32_t>(&data);
206  file_name.modified_time = ReadLEB128<uint64_t>(&data);
207  file_name.file_size = ReadLEB128<uint64_t>(&data);
208  if (file_name.directory_index >= include_directories_.size()) {
209  THROW("directory index out of range");
210  }
211  filenames_.push_back(file_name);
212  break;
213  }
215  info_.discriminator = ReadLEB128<uint32_t>(&data);
216  break;
217  default:
218  // We don't understand this opcode, skip it.
219  SkipBytes(len, &data);
220  if (verbose_level > 0) {
221  fprintf(stderr,
222  "bloaty: warning: unknown DWARF line table extended "
223  "opcode: %d\n",
224  extended_op);
225  }
226  break;
227  }
228  break;
229  }
230  case DW_LNS_copy:
231  if (!shadow_) {
232  remaining_ = data;
233  return true;
234  }
235  break;
236  case DW_LNS_advance_pc:
237  Advance(ReadLEB128<uint64_t>(&data));
238  break;
239  case DW_LNS_advance_line:
240  info_.line += ReadLEB128<int32_t>(&data);
241  break;
242  case DW_LNS_set_file:
243  info_.file = ReadLEB128<uint32_t>(&data);
244  if (info_.file >= filenames_.size()) {
245  THROW("filename index too big");
246  }
247  break;
248  case DW_LNS_set_column:
249  info_.column = ReadLEB128<uint32_t>(&data);
250  break;
251  case DW_LNS_negate_stmt:
252  info_.is_stmt = !info_.is_stmt;
253  break;
255  info_.basic_block = true;
256  break;
257  case DW_LNS_const_add_pc:
258  SpecialOpcodeAdvance(255);
259  break;
261  info_.address += ReadFixed<uint16_t>(&data);
262  info_.op_index = 0;
263  break;
265  info_.prologue_end = true;
266  break;
268  info_.epilogue_begin = true;
269  break;
270  case DW_LNS_set_isa:
271  info_.isa = ReadLEB128<uint8_t>(&data);
272  break;
273  default:
274  // Unknown opcode, but we know its length so can skip it.
275  SkipBytes(standard_opcode_lengths_[op], &data);
276  if (verbose_level > 0) {
277  fprintf(stderr,
278  "bloaty: warning: unknown DWARF line table opcode: %d\n",
279  op);
280  }
281  break;
282  }
283  }
284  }
285 }
286 
287 } // namespace dwarf
288 } // namespace bloaty
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
bloaty
Definition: bloaty.cc:69
dwarf2reader::DW_LNS_const_add_pc
@ DW_LNS_const_add_pc
Definition: dwarf_constants.h:412
bloaty::dwarf::LineInfoReader::FileName::directory_index
uint32_t directory_index
Definition: line_info.h:61
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
file_
FileDescriptorProto * file_
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/annotation_test_util.cc:68
bloaty::verbose_level
int verbose_level
Definition: bloaty.cc:74
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
dwarf2reader::DW_LNE_set_address
@ DW_LNE_set_address
Definition: dwarf_constants.h:429
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
remaining_
string_view remaining_
Definition: elf.cc:155
bloaty::dwarf::LineInfoReader::FileName
Definition: line_info.h:59
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
line_info.h
info_
experimental::ClientRpcInfo * info_
Definition: client_interceptors_end2end_test.cc:169
dwarf2reader::DW_LNS_set_file
@ DW_LNS_set_file
Definition: dwarf_constants.h:408
bloaty::SkipBytes
void SkipBytes(size_t bytes, absl::string_view *data)
Definition: bloaty/src/util.h:174
THROW
#define THROW(msg)
Definition: bloaty/src/util.h:45
dwarf_util.h
dwarf_constants.h
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
dwarf2reader::DW_LNS_set_basic_block
@ DW_LNS_set_basic_block
Definition: dwarf_constants.h:411
dwarf2reader::DW_LNE_define_file
@ DW_LNE_define_file
Definition: dwarf_constants.h:430
dwarf2reader::DW_LNS_set_column
@ DW_LNS_set_column
Definition: dwarf_constants.h:409
advance
static void advance(upb_pbdecoder *d, size_t len)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:6553
dwarf2reader::DW_LNS_advance_line
@ DW_LNS_advance_line
Definition: dwarf_constants.h:407
dwarf2reader
Definition: dwarf_constants.h:20
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
bloaty::dwarf::LineInfoReader::FileName::file_size
uint64_t file_size
Definition: line_info.h:63
dwarf2reader::DW_LNS_set_prologue_end
@ DW_LNS_set_prologue_end
Definition: dwarf_constants.h:415
bloaty::dwarf::LineInfoReader::FileName::modified_time
uint64_t modified_time
Definition: line_info.h:62
dwarf2reader::DW_LNS_advance_pc
@ DW_LNS_advance_pc
Definition: dwarf_constants.h:406
regress.directory
directory
Definition: regress/regress.py:17
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
string_view
absl::string_view string_view
Definition: attr.cc:22
bloaty::ReadNullTerminated
absl::string_view ReadNullTerminated(absl::string_view *data)
Definition: third_party/bloaty/src/util.cc:26
dwarf2reader::DW_LNS_extended_op
@ DW_LNS_extended_op
Definition: dwarf_constants.h:404
dwarf2reader::DW_LNE_set_discriminator
@ DW_LNE_set_discriminator
Definition: dwarf_constants.h:431
bloaty::dwarf::LineInfoReader::LineInfo
Definition: line_info.h:43
dwarf2reader::DW_LNE_end_sequence
@ DW_LNE_end_sequence
Definition: dwarf_constants.h:428
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
bloaty::dwarf::LineInfoReader::FileName::name
absl::string_view name
Definition: line_info.h:60
op
static grpc_op * op
Definition: test/core/fling/client.cc:47
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
dwarf2reader::DW_LNS_set_epilogue_begin
@ DW_LNS_set_epilogue_begin
Definition: dwarf_constants.h:416
dwarf2reader::DW_LNS_fixed_advance_pc
@ DW_LNS_fixed_advance_pc
Definition: dwarf_constants.h:413
dwarf2reader::DW_LNS_copy
@ DW_LNS_copy
Definition: dwarf_constants.h:405
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
dwarf2reader::DW_LNS_negate_stmt
@ DW_LNS_negate_stmt
Definition: dwarf_constants.h:410
dwarf2reader::DW_LNS_set_isa
@ DW_LNS_set_isa
Definition: dwarf_constants.h:417


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:15