/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 |