Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bloaty/src/dwarf/attr.cc
Line
Count
Source
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/attr.h"
16
17
#include "dwarf/debug_info.h"
18
#include "dwarf/dwarf_util.h"
19
#include "dwarf_constants.h"
20
#include "util.h"
21
22
using string_view = std::string_view;
23
using namespace dwarf2reader;
24
25
namespace bloaty {
26
namespace dwarf {
27
28
10.4k
absl::optional<uint64_t> AttrValue::ToUint(const CU& cu) const {
29
10.4k
  if (form_ == DW_FORM_implicit_const) {
30
    // DW_FORM_implicit_const value is stored in AbbrevTable, but
31
    // we don't keep it in AttrValue (discarded in AbbrevTable::ReadAbbrevs()).
32
    // return absl::nullopt to make sure the value is not available.
33
153
    return absl::nullopt;
34
153
  }
35
10.2k
  if (IsUint()) return GetUint(cu);
36
4.56k
  string_view str = GetString(cu);
37
4.56k
  switch (str.size()) {
38
193
    case 1:
39
193
      return ReadFixed<uint8_t>(&str);
40
36
    case 2:
41
36
      return ReadFixed<uint16_t>(&str);
42
3.72k
    case 4:
43
3.72k
      return ReadFixed<uint32_t>(&str);
44
356
    case 8:
45
356
      return ReadFixed<uint64_t>(&str);
46
4.56k
  }
47
245
  return absl::nullopt;
48
4.56k
}
49
50
10.4k
uint64_t AttrValue::GetUint(const CU& cu) const {
51
10.4k
  if (type_ == Type::kUnresolvedUint) {
52
74
    return ResolveIndirectAddress(cu);
53
10.4k
  } else {
54
10.4k
    assert(type_ == Type::kUint);
55
    // DW_FORM_implicit_const value is stored in AbbrevTable, but
56
    // we don't keep it in AttrValue (discarded in AbbrevTable::ReadAbbrevs()).
57
10.4k
    if (form_ == DW_FORM_implicit_const) {
58
0
      THROW("DW_FORM_implicit_const is not supported");
59
0
    }
60
10.4k
    return uint_;
61
10.4k
  }
62
10.4k
}
63
64
41.1k
string_view AttrValue::GetString(const CU& cu) const {
65
41.1k
  if (type_ == Type::kUnresolvedString) {
66
351
    return ResolveDoubleIndirectString(cu);
67
40.7k
  } else {
68
40.7k
    assert(type_ == Type::kString);
69
40.7k
    return string_;
70
40.7k
  }
71
41.1k
}
72
73
template <class D>
74
4.60k
string_view AttrValue::ReadBlock(string_view* data) {
75
4.60k
  D len = ReadFixed<D>(data);
76
4.60k
  return ReadBytes(len, data);
77
4.60k
}
std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadBlock<unsigned char>(std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Line
Count
Source
74
4.39k
string_view AttrValue::ReadBlock(string_view* data) {
75
4.39k
  D len = ReadFixed<D>(data);
76
4.39k
  return ReadBytes(len, data);
77
4.39k
}
std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadBlock<unsigned short>(std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Line
Count
Source
74
86
string_view AttrValue::ReadBlock(string_view* data) {
75
86
  D len = ReadFixed<D>(data);
76
86
  return ReadBytes(len, data);
77
86
}
std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadBlock<unsigned int>(std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Line
Count
Source
74
123
string_view AttrValue::ReadBlock(string_view* data) {
75
123
  D len = ReadFixed<D>(data);
76
123
  return ReadBytes(len, data);
77
123
}
78
79
1.74k
string_view AttrValue::ReadVariableBlock(string_view* data) {
80
1.74k
  uint64_t len = ReadLEB128<uint64_t>(data);
81
1.74k
  return ReadBytes(len, data);
82
1.74k
}
83
84
44.9k
string_view AttrValue::ResolveIndirectString(const CU& cu, uint64_t ofs) {
85
  // offset into a string table contained in the .debug_str of the object file.
86
44.9k
  string_view ret = ReadDebugStrEntry(cu.dwarf().debug_str, ofs);
87
44.9k
  cu.AddIndirectString(ret);
88
44.9k
  return ret;
89
44.9k
}
90
91
1
string_view AttrValue::ResolveIndirectLineString(const CU& cu, uint64_t ofs) {
92
  // offset into a string table contained in the .debug_line_str of the object file.
93
1
  string_view ret = ReadDebugStrEntry(cu.dwarf().debug_line_str, ofs);
94
1
  cu.AddIndirectString(ret);
95
1
  return ret;
96
1
}
97
98
template <class D>
99
44.9k
string_view AttrValue::ReadIndirectString(const CU& cu, string_view* data) {
100
44.9k
  return ResolveIndirectString(cu, ReadFixed<D>(data));
101
44.9k
}
Unexecuted instantiation: std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadIndirectString<unsigned long>(bloaty::dwarf::CU const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadIndirectString<unsigned int>(bloaty::dwarf::CU const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Line
Count
Source
99
44.9k
string_view AttrValue::ReadIndirectString(const CU& cu, string_view* data) {
100
44.9k
  return ResolveIndirectString(cu, ReadFixed<D>(data));
101
44.9k
}
102
103
template <class D>
104
4
string_view AttrValue::ReadIndirectLineString(const CU& cu, string_view* data) {
105
4
  return ResolveIndirectLineString(cu, ReadFixed<D>(data));
106
4
}
Unexecuted instantiation: std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadIndirectLineString<unsigned long>(bloaty::dwarf::CU const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
std::__1::basic_string_view<char, std::__1::char_traits<char> > bloaty::dwarf::AttrValue::ReadIndirectLineString<unsigned int>(bloaty::dwarf::CU const&, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Line
Count
Source
104
4
string_view AttrValue::ReadIndirectLineString(const CU& cu, string_view* data) {
105
4
  return ResolveIndirectLineString(cu, ReadFixed<D>(data));
106
4
}
107
108
string_view
109
351
AttrValue::ResolveDoubleIndirectString(const CU &cu) const {
110
351
  uint64_t ofs = uint_;
111
351
  string_view offsets = cu.dwarf().debug_str_offsets;
112
351
  uint64_t ofs2;
113
351
  if (cu.unit_sizes().dwarf64()) {
114
0
    SkipBytes((ofs * 8) + cu.str_offsets_base(), &offsets);
115
0
    ofs2 = ReadFixed<uint64_t>(&offsets);
116
351
  } else {
117
351
    SkipBytes((ofs * 4) + cu.str_offsets_base(), &offsets);
118
351
    ofs2 = ReadFixed<uint32_t>(&offsets);
119
351
  }
120
351
  string_view ret = ReadDebugStrEntry(cu.dwarf().debug_str, ofs2);
121
351
  cu.AddIndirectString(ret);
122
351
  return ret;
123
351
}
124
125
74
uint64_t AttrValue::ResolveIndirectAddress(const CU& cu) const {
126
74
  return ReadIndirectAddress(cu, uint_);
127
74
}
128
129
217k
AttrValue AttrValue::ParseAttr(const CU& cu, uint16_t form, string_view* data) {
130
217k
  switch (form) {
131
294
    case DW_FORM_indirect: {
132
294
      uint16_t indirect_form = ReadLEB128<uint16_t>(data);
133
294
      if (indirect_form == DW_FORM_indirect) {
134
1
        THROW("indirect attribute has indirect form type");
135
1
      }
136
293
      return ParseAttr(cu, indirect_form, data);
137
294
    }
138
309
    case DW_FORM_ref1:
139
309
      return AttrValue(form, ReadFixed<uint8_t>(data));
140
92
    case DW_FORM_ref2:
141
92
      return AttrValue(form, ReadFixed<uint16_t>(data));
142
26.4k
    case DW_FORM_ref4:
143
26.4k
      return AttrValue(form, ReadFixed<uint32_t>(data));
144
769
    case DW_FORM_ref_sig8:
145
1.06k
    case DW_FORM_ref8:
146
1.06k
      return AttrValue(form, ReadFixed<uint64_t>(data));
147
115
    case DW_FORM_ref_udata:
148
115
      return AttrValue(form, ReadLEB128<uint64_t>(data));
149
1.16k
    case DW_FORM_strx1:
150
1.16k
      return AttrValue::UnresolvedString(form, ReadFixed<uint8_t>(data));
151
608
    case DW_FORM_strx2:
152
608
      return AttrValue::UnresolvedString(form, ReadFixed<uint16_t>(data));
153
201
    case DW_FORM_strx3:
154
201
      return AttrValue::UnresolvedString(form, ReadFixed<uint32_t, 3>(data));
155
74
    case DW_FORM_strx4:
156
74
      return AttrValue::UnresolvedString(form, ReadFixed<uint32_t>(data));
157
83
    case DW_FORM_strx:
158
83
    case DW_FORM_GNU_str_index:
159
83
      return AttrValue::UnresolvedString(form, ReadLEB128<uint64_t>(data));
160
128
    case DW_FORM_addrx1:
161
128
      return AttrValue::UnresolvedUint(form, ReadFixed<uint8_t>(data));
162
178
    case DW_FORM_addrx2:
163
178
      return AttrValue::UnresolvedUint(form, ReadFixed<uint16_t>(data));
164
367
    case DW_FORM_addrx3:
165
367
      return AttrValue::UnresolvedUint(form, ReadFixed<uint32_t, 3>(data));
166
133
    case DW_FORM_addrx4:
167
133
      return AttrValue::UnresolvedUint(form, ReadFixed<uint32_t>(data));
168
762
    case DW_FORM_addrx:
169
762
    case DW_FORM_GNU_addr_index:
170
762
      return AttrValue::UnresolvedUint(form, ReadLEB128<uint64_t>(data));
171
22.5k
    case DW_FORM_addr:
172
22.8k
    address_size:
173
22.8k
      switch (cu.unit_sizes().address_size()) {
174
16.8k
        case 4:
175
16.8k
          return AttrValue(form, ReadFixed<uint32_t>(data));
176
5.94k
        case 8:
177
5.94k
          return AttrValue(form, ReadFixed<uint64_t>(data));
178
0
        default:
179
0
          BLOATY_UNREACHABLE();
180
22.8k
      }
181
696
    case DW_FORM_ref_addr:
182
696
      if (cu.unit_sizes().dwarf_version() <= 2) {
183
268
        goto address_size;
184
268
      }
185
428
      ABSL_FALLTHROUGH_INTENDED;
186
7.86k
    case DW_FORM_sec_offset:
187
7.86k
      if (cu.unit_sizes().dwarf64()) {
188
0
        return AttrValue(form, ReadFixed<uint64_t>(data));
189
7.86k
      } else {
190
7.86k
        return AttrValue(form, ReadFixed<uint32_t>(data));
191
7.86k
      }
192
203
    case DW_FORM_udata:
193
203
      return AttrValue(form, ReadLEB128<uint64_t>(data));
194
4.39k
    case DW_FORM_block1:
195
4.39k
      return AttrValue(form, ReadBlock<uint8_t>(data));
196
86
    case DW_FORM_block2:
197
86
      return AttrValue(form, ReadBlock<uint16_t>(data));
198
123
    case DW_FORM_block4:
199
123
      return AttrValue(form, ReadBlock<uint32_t>(data));
200
82
    case DW_FORM_block:
201
1.74k
    case DW_FORM_exprloc:
202
1.74k
      return AttrValue(form, ReadVariableBlock(data));
203
12.7k
    case DW_FORM_string:
204
12.7k
      return AttrValue(form, ReadNullTerminated(data));
205
44.9k
    case DW_FORM_strp:
206
44.9k
      if (cu.unit_sizes().dwarf64()) {
207
0
        return AttrValue(form, ReadIndirectString<uint64_t>(cu, data));
208
44.9k
      } else {
209
44.9k
        return AttrValue(form, ReadIndirectString<uint32_t>(cu, data));
210
44.9k
      }
211
4
    case DW_FORM_line_strp:
212
4
      if (cu.unit_sizes().dwarf64()) {
213
0
        return AttrValue(form, ReadIndirectLineString<uint64_t>(cu, data));
214
4
      } else {
215
4
        return AttrValue(form, ReadIndirectLineString<uint32_t>(cu, data));
216
4
      }
217
52.4k
    case DW_FORM_data1:
218
52.4k
      return AttrValue(form, ReadBytes(1, data));
219
11.3k
    case DW_FORM_data2:
220
11.3k
      return AttrValue(form, ReadBytes(2, data));
221
17.6k
    case DW_FORM_data4:
222
17.6k
      return AttrValue(form, ReadBytes(4, data));
223
1.77k
    case DW_FORM_data8:
224
1.77k
      return AttrValue(form, ReadBytes(8, data));
225
49
    case DW_FORM_data16:
226
49
      return AttrValue(form, ReadBytes(16, data));
227
170
    case DW_FORM_loclistx:
228
299
    case DW_FORM_rnglistx:
229
299
      return AttrValue(form, ReadLEB128<uint64_t>(data));
230
231
    // Bloaty doesn't currently care about any bool or signed data.
232
    // So we fudge it a bit and just stuff these in a uint64.
233
2.86k
    case DW_FORM_flag_present:
234
2.86k
      return AttrValue(form, 1);
235
2.58k
    case DW_FORM_flag:
236
2.58k
      return AttrValue(form, ReadFixed<uint8_t>(data));
237
1.21k
    case DW_FORM_sdata:
238
1.21k
      return AttrValue(form, ReadLEB128<uint64_t>(data));
239
500
    case DW_FORM_implicit_const:
240
500
      return AttrValue(form, 1);
241
62
    default:
242
62
      THROWF("Don't know how to parse DWARF form: $0", form);
243
217k
  }
244
217k
}
245
246
}  // namepsace dwarf
247
}  // namespace bloaty