debug_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/debug_info.h"
16 #include "dwarf_constants.h"
17 #include "dwarf/dwarf_util.h"
18 
19 using namespace dwarf2reader;
20 
21 using absl::string_view;
22 
23 namespace bloaty {
24 namespace dwarf {
25 
26 void AbbrevTable::ReadAbbrevs(string_view data) {
27  const char* start = data.data();
28  while (true) {
29  uint32_t code = ReadLEB128<uint32_t>(&data);
30 
31  if (code == 0) {
32  abbrev_data_ = string_view(start, data.data() - start);
33  return;
34  }
35 
36  Abbrev& abbrev = abbrev_[code];
37 
38  if (abbrev.code) {
39  THROW("DWARF data contained duplicate abbrev code");
40  }
41 
42  uint8_t has_child;
43 
44  abbrev.code = code;
45  abbrev.tag = ReadLEB128<uint16_t>(&data);
46  has_child = ReadFixed<uint8_t>(&data);
47 
48  switch (has_child) {
49  case DW_children_yes:
50  abbrev.has_child = true;
51  break;
52  case DW_children_no:
53  abbrev.has_child = false;
54  break;
55  default:
56  THROWF("DWARF has_child is neither true nor false: $0, code=$1, tag=$2",
57  has_child, abbrev.code, abbrev.tag);
58  }
59 
60  while (true) {
62  attr.name = ReadLEB128<uint16_t>(&data);
63  attr.form = ReadLEB128<uint8_t>(&data);
64 
65  if (attr.name == 0 && attr.form == 0) {
66  break; // End of this abbrev
67  }
68 
69  abbrev.attr.push_back(attr);
70  }
71  }
72 }
73 
74 absl::string_view CompilationUnitSizes::ReadInitialLength(
75  absl::string_view* remaining) {
76  uint64_t len = ReadFixed<uint32_t>(remaining);
77 
78  if (len == 0xffffffff) {
79  dwarf64_ = true;
80  len = ReadFixed<uint64_t>(remaining);
81  } else {
82  dwarf64_ = false;
83  }
84 
85  if (remaining->size() < len) {
86  THROW("short DWARF compilation unit");
87  }
88 
89  absl::string_view unit = *remaining;
90  unit.remove_suffix(remaining->size() - len);
91  *remaining = remaining->substr(len);
92  return unit;
93 }
94 
95 CUIter InfoReader::GetCUIter(Section section, uint64_t offset) {
97 
98  if (section == Section::kDebugInfo) {
99  data = dwarf_.debug_info;
100  } else {
101  data = dwarf_.debug_types;
102  }
103 
104  SkipBytes(offset, &data);
105  return CUIter(section, data);
106 }
107 
108 bool CUIter::NextCU(InfoReader& reader, CU* cu) {
109  if (next_unit_.empty()) return false;
110 
111  // Read initial length and calculate entire_unit/data.
112  string_view entire_unit = next_unit_;
113  string_view data = cu->unit_sizes_.ReadInitialLength(&next_unit_);
114  size_t initial_length_len = data.data() - entire_unit.data();
115  entire_unit = entire_unit.substr(0, data.size() + initial_length_len);
116 
117  // Delegate to CU to read the unit header.
118  cu->ReadHeader(entire_unit, data, section_, reader);
119  return true;
120 }
121 
122 // Reads the header of this CU from |data|, updating our member variables
123 // according to what was parsed.
124 void CU::ReadHeader(string_view entire_unit, string_view data,
126  entire_unit_ = entire_unit;
127  dwarf_ = &reader.dwarf_;
128  unit_sizes_.ReadDWARFVersion(&data);
129 
130  if (unit_sizes_.dwarf_version() > 5) {
131  THROWF("Data is in DWARF $0 format which we don't understand",
132  unit_sizes_.dwarf_version());
133  }
134 
135  uint64_t debug_abbrev_offset;
136 
137  if (unit_sizes_.dwarf_version() == 5) {
138  unit_type_ = ReadFixed<uint8_t>(&data);
139  unit_sizes_.SetAddressSize(ReadFixed<uint8_t>(&data));
140  debug_abbrev_offset = unit_sizes_.ReadDWARFOffset(&data);
141 
142  switch (unit_type_) {
143  case DW_UT_skeleton:
144  case DW_UT_split_compile:
145  case DW_UT_split_type:
146  dwo_id_ = ReadFixed<uint64_t>(&data);
147  break;
148  case DW_UT_type:
149  unit_type_signature_ = ReadFixed<uint64_t>(&data);
150  unit_type_offset_ = unit_sizes_.ReadDWARFOffset(&data);
151  break;
152  case DW_UT_compile:
153  case DW_UT_partial:
154  break;
155  default:
156  fprintf(stderr, "warning: Unknown DWARF Unit Type in user defined range\n");
157  break;
158  }
159 
160  } else {
161  debug_abbrev_offset = unit_sizes_.ReadDWARFOffset(&data);
162  unit_sizes_.SetAddressSize(ReadFixed<uint8_t>(&data));
163 
164  if (section == InfoReader::Section::kDebugTypes) {
165  unit_type_signature_ = ReadFixed<uint64_t>(&data);
166  unit_type_offset_ = unit_sizes_.ReadDWARFOffset(&data);
167  }
168  }
169 
170  unit_abbrev_ = &reader.abbrev_tables_[debug_abbrev_offset];
171 
172  // If we haven't already read abbreviations for this debug_abbrev_offset_, we
173  // need to do so now.
174  if (unit_abbrev_->IsEmpty()) {
175  string_view abbrev_data = dwarf_->debug_abbrev;
176  SkipBytes(debug_abbrev_offset, &abbrev_data);
177  unit_abbrev_->ReadAbbrevs(abbrev_data);
178  }
179 
180  data_ = data;
181  ReadTopLevelDIE(reader);
182 }
183 
184 // Read the root-level DIE in order to populate some member variables on which
185 // other attributes depend. In particular, we may re-parse this DIE later and
186 // read attributes that are relative to these base addresses.
187 void CU::ReadTopLevelDIE(InfoReader& reader) {
188  DIEReader die_reader = GetDIEReader();
189  const auto* abbrev = die_reader.ReadCode(*this);
190  absl::optional<uint64_t> stmt_list;
191  unit_name_.clear();
192  die_reader.ReadAttributes(
193  *this, abbrev, [this, &stmt_list](uint16_t tag, dwarf::AttrValue value) {
194  switch (tag) {
195  case DW_AT_name:
196  if (value.IsString()) {
197  unit_name_ = std::string(value.GetString(*this));
198  }
199  break;
200  case DW_AT_stmt_list:
201  if (value.form() == DW_FORM_sec_offset) {
202  stmt_list = value.GetUint(*this);
203  }
204  break;
205  case DW_AT_addr_base:
206  if (value.form() == DW_FORM_sec_offset) {
207  addr_base_ = value.GetUint(*this);
208  }
209  break;
211  if (value.form() == DW_FORM_sec_offset) {
212  str_offsets_base_ = value.GetUint(*this);
213  }
214  break;
215  case DW_AT_rnglists_base:
216  if (value.form() == DW_FORM_sec_offset) {
217  range_lists_base_ = value.GetUint(*this);
218  }
219  break;
220  }
221  });
222 
223  if (stmt_list) {
224  if (unit_name_.empty()) {
225  auto iter = reader.stmt_list_map_.find(*stmt_list);
226  if (iter != reader.stmt_list_map_.end()) {
227  unit_name_ = iter->second;
228  }
229  } else {
230  (reader.stmt_list_map_)[*stmt_list] = unit_name_;
231  }
232  }
233 }
234 
235 void DIEReader::SkipNullEntries() {
236  while (!remaining_.empty() && remaining_[0] == 0) {
237  // null entry terminates a chain of sibling entries.
239  depth_--;
240  }
241 }
242 
243 const AbbrevTable::Abbrev* DIEReader::ReadCode(const CU& cu) {
244  SkipNullEntries();
245  if (remaining_.empty()) {
246  return nullptr;
247  }
248  uint32_t code = ReadLEB128<uint32_t>(&remaining_);
249  const AbbrevTable::Abbrev* ret;
250  if (!cu.unit_abbrev_->GetAbbrev(code, &ret)) {
251  THROW("couldn't find abbreviation for code");
252  }
253  if (ret->has_child) {
254  depth_++;
255  }
256  return ret;
257 }
258 
259 void DIEReader::SkipChildren(const CU& cu, const AbbrevTable::Abbrev* abbrev) {
260  if (!abbrev->has_child) {
261  return;
262  }
263 
264  int target_depth = depth_ - 1;
265  SkipNullEntries();
266  while (depth_ > target_depth) {
267  // TODO(haberman): use DW_AT_sibling to optimize skipping when it is
268  // available.
269  abbrev = ReadCode(cu);
270  if (!abbrev) {
271  return;
272  }
273  ReadAttributes(cu, abbrev, [](uint16_t, dwarf::AttrValue) {});
274  SkipNullEntries();
275  }
276 }
277 
278 } // namespace dwarf
279 } // namespace bloaty
bloaty::dwarf::DIEReader::ReadCode
const AbbrevTable::Abbrev * ReadCode(const CU &cu)
Definition: debug_info.cc:243
dwarf2reader::DW_AT_addr_base
@ DW_AT_addr_base
Definition: dwarf_constants.h:287
bloaty
Definition: bloaty.cc:69
dwarf2reader::DW_UT_partial
@ DW_UT_partial
Definition: dwarf_constants.h:710
absl::string_view::remove_suffix
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_suffix(size_type n)
Definition: abseil-cpp/absl/strings/string_view.h:354
bloaty::dwarf::AbbrevTable::Attribute
Definition: debug_info.h:157
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
bloaty::dwarf::DIEReader
Definition: debug_info.h:304
bloaty::dwarf::DIEReader::ReadAttributes
void ReadAttributes(const CU &cu, const AbbrevTable::Abbrev *code, T &&func)
Definition: debug_info.h:342
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
dwarf2reader::DW_AT_rnglists_base
@ DW_AT_rnglists_base
Definition: dwarf_constants.h:288
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
grpc_status._async.code
code
Definition: grpcio_status/grpc_status/_async.py:34
remaining_
string_view remaining_
Definition: elf.cc:155
dwarf2reader::DW_UT_type
@ DW_UT_type
Definition: dwarf_constants.h:709
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
bloaty::dwarf::AbbrevTable::Abbrev::code
uint32_t code
Definition: debug_info.h:164
dwarf2reader::DW_children_no
@ DW_children_no
Definition: dwarf_constants.h:123
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
dwarf2reader::DW_AT_str_offsets_base
@ DW_AT_str_offsets_base
Definition: dwarf_constants.h:286
start
static uint64_t start
Definition: benchmark-pound.c:74
bloaty::SkipBytes
void SkipBytes(size_t bytes, absl::string_view *data)
Definition: bloaty/src/util.h:174
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
THROW
#define THROW(msg)
Definition: bloaty/src/util.h:45
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
bloaty::dwarf::CU
Definition: debug_info.h:241
bloaty::dwarf::AbbrevTable::Abbrev::attr
std::vector< Attribute > attr
Definition: debug_info.h:167
dwarf_util.h
bloaty::dwarf::AbbrevTable::GetAbbrev
bool GetAbbrev(uint32_t code, const Abbrev **abbrev) const
Definition: debug_info.h:175
dwarf_constants.h
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::optional< uint64_t >
dwarf2reader::DW_AT_name
@ DW_AT_name
Definition: dwarf_constants.h:185
depth_
int depth_
Definition: json_writer.cc:73
bloaty::dwarf::AbbrevTable::Abbrev::has_child
bool has_child
Definition: debug_info.h:166
dwarf2reader::DW_AT_stmt_list
@ DW_AT_stmt_list
Definition: dwarf_constants.h:192
dwarf2reader
Definition: dwarf_constants.h:20
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
dwarf2reader::DW_UT_split_compile
@ DW_UT_split_compile
Definition: dwarf_constants.h:712
section
Definition: loader.h:337
value
const char * value
Definition: hpack_parser_table.cc:165
bloaty::dwarf::CU::ReadHeader
void ReadHeader(absl::string_view entire_unit, absl::string_view data, InfoReader::Section section, InfoReader &reader)
Definition: debug_info.cc:124
bloaty::dwarf::InfoReader
Definition: debug_info.h:198
attr
OPENSSL_EXPORT X509_ATTRIBUTE * attr
Definition: x509.h:1666
bloaty::dwarf::CompilationUnitSizes::ReadInitialLength
absl::string_view ReadInitialLength(absl::string_view *remaining)
Definition: debug_info.cc:74
absl::string_view::remove_prefix
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n)
Definition: abseil-cpp/absl/strings/string_view.h:344
bloaty::dwarf::InfoReader::Section
Section
Definition: debug_info.h:207
bloaty::dwarf::CU::unit_abbrev_
AbbrevTable * unit_abbrev_
Definition: debug_info.h:283
dwarf2reader::DW_UT_split_type
@ DW_UT_split_type
Definition: dwarf_constants.h:713
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
debug_info.h
string_view
absl::string_view string_view
Definition: attr.cc:22
bloaty::dwarf::CU::unit_sizes_
CompilationUnitSizes unit_sizes_
Definition: debug_info.h:282
THROWF
#define THROWF(...)
Definition: bloaty/src/util.h:46
data_
std::string data_
Definition: cord_rep_btree_navigator_test.cc:84
dwarf2reader::DW_UT_skeleton
@ DW_UT_skeleton
Definition: dwarf_constants.h:711
dwarf2reader::DW_children_yes
@ DW_children_yes
Definition: dwarf_constants.h:124
dwarf2reader::DW_FORM_sec_offset
@ DW_FORM_sec_offset
Definition: dwarf_constants.h:151
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
iter
Definition: test_winkernel.cpp:47
bloaty::dwarf::CUIter
Definition: debug_info.h:225
code
Definition: bloaty/third_party/zlib/contrib/infback9/inftree9.h:24
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
bloaty::dwarf::AbbrevTable::Abbrev::tag
uint16_t tag
Definition: debug_info.h:165
absl::string_view::substr
constexpr string_view substr(size_type pos=0, size_type n=npos) const
Definition: abseil-cpp/absl/strings/string_view.h:399
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
reader
void reader(void *n)
Definition: libuv/docs/code/locks/main.c:8
dwarf2reader::DW_UT_compile
@ DW_UT_compile
Definition: dwarf_constants.h:708
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
bloaty::dwarf::AbbrevTable::Abbrev
Definition: debug_info.h:163
bloaty::dwarf::AttrValue
Definition: attr.h:28


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:59:02