Coverage Report

Created: 2026-01-28 20:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/common/dwarf.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
// This file is copied from
18
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/Dwarf.cpp
19
// and modified by Doris
20
21
#if defined(__ELF__) && !defined(__FreeBSD__)
22
23
/*
24
 * Copyright 2012-present Facebook, Inc.
25
 *
26
 * Licensed under the Apache License, Version 2.0 (the "License");
27
 * you may not use this file except in compliance with the License.
28
 * You may obtain a copy of the License at
29
 *
30
 *   http://www.apache.org/licenses/LICENSE-2.0
31
 *
32
 * Unless required by applicable law or agreed to in writing, software
33
 * distributed under the License is distributed on an "AS IS" BASIS,
34
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35
 * See the License for the specific language governing permissions and
36
 * limitations under the License.
37
 */
38
39
/** This file was edited for ClickHouse.
40
  */
41
42
#include "common/dwarf.h"
43
44
#include <cstring>
45
46
#include "common/elf.h"
47
#include "common/logging.h"
48
49
522
#define DW_CHILDREN_no 0
50
51
522
#define DW_FORM_addr 1
52
0
#define DW_FORM_block1 0x0a
53
0
#define DW_FORM_block2 3
54
0
#define DW_FORM_block4 4
55
0
#define DW_FORM_block 9
56
0
#define DW_FORM_exprloc 0x18
57
0
#define DW_FORM_data1 0x0b
58
0
#define DW_FORM_ref1 0x11
59
522
#define DW_FORM_data2 0x05
60
522
#define DW_FORM_ref2 0x12
61
0
#define DW_FORM_data4 0x06
62
0
#define DW_FORM_ref4 0x13
63
0
#define DW_FORM_data8 0x07
64
0
#define DW_FORM_ref8 0x14
65
0
#define DW_FORM_ref_sig8 0x20
66
0
#define DW_FORM_sdata 0x0d
67
113k
#define DW_FORM_udata 0x0f
68
0
#define DW_FORM_ref_udata 0x15
69
0
#define DW_FORM_flag 0x0c
70
0
#define DW_FORM_flag_present 0x19
71
2.41k
#define DW_FORM_sec_offset 0x17
72
2.41k
#define DW_FORM_ref_addr 0x10
73
0
#define DW_FORM_string 0x08
74
0
#define DW_FORM_strp 0x0e
75
0
#define DW_FORM_indirect 0x16
76
0
#define DW_FORM_strx 0x1a
77
0
#define DW_FORM_addrx 0x1b
78
0
#define DW_FORM_ref_sup4 0x1c
79
0
#define DW_FORM_strp_sup 0x1d
80
0
#define DW_FORM_data16 0x1e
81
127k
#define DW_FORM_line_strp 0x1f
82
12.1k
#define DW_FORM_implicit_const 0x21
83
522
#define DW_FORM_rnglistx 0x23
84
0
#define DW_FORM_loclistx 0x22
85
0
#define DW_FORM_ref_sup8 0x24
86
1.56k
#define DW_FORM_strx1 0x25
87
0
#define DW_FORM_strx2 0x26
88
0
#define DW_FORM_strx3 0x27
89
0
#define DW_FORM_strx4 0x28
90
0
#define DW_FORM_addrx1 0x29
91
0
#define DW_FORM_addrx2 0x2a
92
0
#define DW_FORM_addrx3 0x2b
93
0
#define DW_FORM_addrx4 0x2c
94
95
261
#define DW_TAG_compile_unit 0x11
96
0
#define DW_TAG_subprogram 0x2e
97
0
#define DW_TAG_try_block 0x32
98
0
#define DW_TAG_catch_block 0x25
99
0
#define DW_TAG_entry_point 0x03
100
0
#define DW_TAG_common_block 0x1a
101
0
#define DW_TAG_lexical_block 0x0b
102
103
261
#define DW_AT_stmt_list 0x10
104
261
#define DW_AT_comp_dir 0x1b
105
261
#define DW_AT_name 0x03
106
0
#define DW_AT_high_pc 0x12
107
261
#define DW_AT_low_pc 0x11
108
261
#define DW_AT_entry_pc 0x52
109
0
#define DW_AT_ranges 0x55
110
0
#define DW_AT_abstract_origin 0x31
111
0
#define DW_AT_call_line 0x59
112
0
#define DW_AT_call_file 0x58
113
0
#define DW_AT_linkage_name 0x6e
114
0
#define DW_AT_specification 0x47
115
261
#define DW_AT_str_offsets_base 0x72
116
261
#define DW_AT_addr_base 0x73
117
261
#define DW_AT_rnglists_base 0x74
118
165
#define DW_AT_loclists_base 0x8c
119
261
#define DW_AT_GNU_ranges_base 0x2132
120
261
#define DW_AT_GNU_addr_base 0x2133
121
122
0
#define DW_LNE_define_file 0x03
123
324k
#define DW_LNS_copy 0x01
124
416k
#define DW_LNS_advance_pc 0x02
125
1.84M
#define DW_LNS_advance_line 0x03
126
143k
#define DW_LNS_set_file 0x04
127
1.01M
#define DW_LNS_set_column 0x05
128
837k
#define DW_LNS_negate_stmt 0x06
129
0
#define DW_LNS_set_basic_block 0x07
130
411k
#define DW_LNS_const_add_pc 0x08
131
0
#define DW_LNS_fixed_advance_pc 0x09
132
95.4k
#define DW_LNS_set_prologue_end 0x0a
133
94.0k
#define DW_LNS_set_epilogue_begin 0x0b
134
0
#define DW_LNS_set_isa 0x0c
135
91.3k
#define DW_LNE_end_sequence 0x01
136
91.5k
#define DW_LNE_set_address 0x02
137
0
#define DW_LNE_set_discriminator 0x04
138
139
127k
#define DW_LNCT_path 0x1
140
113k
#define DW_LNCT_directory_index 0x2
141
0
#define DW_LNCT_timestamp 0x3
142
0
#define DW_LNCT_size 0x4
143
0
#define DW_LNCT_MD5 0x5
144
145
0
#define DW_RLE_end_of_list 0x0
146
0
#define DW_RLE_base_addressx 0x1
147
0
#define DW_RLE_startx_endx 0x2
148
0
#define DW_RLE_startx_length 0x3
149
0
#define DW_RLE_offset_pair 0x4
150
0
#define DW_RLE_base_address 0x5
151
0
#define DW_RLE_start_end 0x6
152
0
#define DW_RLE_start_length 0x7
153
154
namespace doris {
155
#include "common/compile_check_avoid_begin.h"
156
157
Dwarf::Dwarf(const std::shared_ptr<Elf>& elf)
158
515
        : elf_(elf),
159
515
          abbrev_(getSection(".debug_abbrev")),
160
515
          addr_(getSection(".debug_addr")),
161
515
          aranges_(getSection(".debug_aranges")),
162
515
          info_(getSection(".debug_info")),
163
515
          line_(getSection(".debug_line")),
164
515
          line_str_(getSection(".debug_line_str")),
165
515
          loclists_(getSection(".debug_loclists")),
166
515
          ranges_(getSection(".debug_ranges")),
167
515
          rnglists_(getSection(".debug_rnglists")),
168
515
          str_(getSection(".debug_str")),
169
515
          str_offsets_(getSection(".debug_str_offsets")) {
170
    // Optional sections:
171
    //  - debugAranges_: for fast address range lookup.
172
    //     If missing .debug_info can be used - but it's much slower (linear
173
    //     scan).
174
    //  - debugRanges_ (DWARF 4) / debugRnglists_ (DWARF 5): non-contiguous
175
    //    address ranges of debugging information entries.
176
    //    Used for inline function address lookup.
177
515
    if (info_.empty() || abbrev_.empty() || line_.empty() || str_.empty()) {
178
258
        elf_ = nullptr;
179
258
    }
180
515
}
181
182
794
Dwarf::Section::Section(std::string_view d) : is64_bit(false), data(d) {}
183
184
#define SAFE_CHECK(cond, ...)                                \
185
3.46G
    do {                                                     \
186
3.46G
        if (!(cond)) LOG(FATAL) << fmt::format(__VA_ARGS__); \
187
3.46G
    } while (false)
188
189
namespace {
190
// Maximum number of DIEAbbreviation to cache in a compilation unit. Used to
191
// speed up inline function lookup.
192
const uint32_t kMaxAbbreviationEntries = 1000;
193
194
// All following read* functions read from a std::string_view, advancing the
195
// std::string_view, and aborting if there's not enough room.
196
197
// Read (bitwise) one object of type T
198
template <typename T>
199
    requires std::is_trivial_v<T> && std::is_standard_layout_v<T>
200
3.45G
T read(std::string_view& sp) {
201
3.45G
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
3.45G
               sp.size());
203
3.45G
    T x;
204
3.45G
    memcpy(&x, sp.data(), sizeof(T));
205
3.45G
    sp.remove_prefix(sizeof(T));
206
3.45G
    return x;
207
3.45G
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_14readIhQaasr3stdE12is_trivial_vIT_Esr3stdE20is_standard_layout_vIS2_EEES2_RSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
200
18.8M
T read(std::string_view& sp) {
201
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
18.8M
               sp.size());
203
18.8M
    T x;
204
18.8M
    memcpy(&x, sp.data(), sizeof(T));
205
18.8M
    sp.remove_prefix(sizeof(T));
206
18.8M
    return x;
207
18.8M
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_14readImQaasr3stdE12is_trivial_vIT_Esr3stdE20is_standard_layout_vIS2_EEES2_RSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
200
3.42G
T read(std::string_view& sp) {
201
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
3.42G
               sp.size());
203
3.42G
    T x;
204
3.42G
    memcpy(&x, sp.data(), sizeof(T));
205
3.42G
    sp.remove_prefix(sizeof(T));
206
3.42G
    return x;
207
3.42G
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_14readIjQaasr3stdE12is_trivial_vIT_Esr3stdE20is_standard_layout_vIS2_EEES2_RSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
200
5.17M
T read(std::string_view& sp) {
201
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
5.17M
               sp.size());
203
5.17M
    T x;
204
5.17M
    memcpy(&x, sp.data(), sizeof(T));
205
5.17M
    sp.remove_prefix(sizeof(T));
206
5.17M
    return x;
207
5.17M
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_14readItQaasr3stdE12is_trivial_vIT_Esr3stdE20is_standard_layout_vIS2_EEES2_RSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
200
2.52M
T read(std::string_view& sp) {
201
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
2.52M
               sp.size());
203
2.52M
    T x;
204
2.52M
    memcpy(&x, sp.data(), sizeof(T));
205
2.52M
    sp.remove_prefix(sizeof(T));
206
2.52M
    return x;
207
2.52M
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_14readIaQaasr3stdE12is_trivial_vIT_Esr3stdE20is_standard_layout_vIS2_EEES2_RSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
200
261
T read(std::string_view& sp) {
201
    SAFE_CHECK(sp.size() >= sizeof(T), "underflow: expected bytes {}, got bytes {}", sizeof(T),
202
261
               sp.size());
203
261
    T x;
204
261
    memcpy(&x, sp.data(), sizeof(T));
205
261
    sp.remove_prefix(sizeof(T));
206
261
    return x;
207
261
}
208
209
// Read (bitwise) an unsigned number of N bytes (N in 1, 2, 3, 4).
210
template <size_t N>
211
1.56k
uint64_t readU64(std::string_view& sp) {
212
1.56k
    SAFE_CHECK(sp.size() >= N, "underflow");
213
1.56k
    uint64_t x = 0;
214
1.56k
    memcpy(&x, sp.data(), N);
215
1.56k
    sp.remove_prefix(N);
216
1.56k
    return x;
217
1.56k
}
dwarf.cpp:_ZN5doris12_GLOBAL__N_17readU64ILm1EEEmRSt17basic_string_viewIcSt11char_traitsIcEE
Line
Count
Source
211
1.56k
uint64_t readU64(std::string_view& sp) {
212
    SAFE_CHECK(sp.size() >= N, "underflow");
213
1.56k
    uint64_t x = 0;
214
1.56k
    memcpy(&x, sp.data(), N);
215
1.56k
    sp.remove_prefix(N);
216
1.56k
    return x;
217
1.56k
}
Unexecuted instantiation: dwarf.cpp:_ZN5doris12_GLOBAL__N_17readU64ILm2EEEmRSt17basic_string_viewIcSt11char_traitsIcEE
Unexecuted instantiation: dwarf.cpp:_ZN5doris12_GLOBAL__N_17readU64ILm3EEEmRSt17basic_string_viewIcSt11char_traitsIcEE
Unexecuted instantiation: dwarf.cpp:_ZN5doris12_GLOBAL__N_17readU64ILm4EEEmRSt17basic_string_viewIcSt11char_traitsIcEE
218
219
// Read ULEB (unsigned) varint value; algorithm from the DWARF spec
220
4.22M
uint64_t readULEB(std::string_view& sp, uint8_t& shift, uint8_t& val) {
221
4.22M
    uint64_t r = 0;
222
4.22M
    shift = 0;
223
5.96M
    do {
224
5.96M
        val = read<uint8_t>(sp);
225
5.96M
        r |= (uint64_t(val & 0x7f) << shift);
226
5.96M
        shift += 7;
227
5.96M
    } while (val & 0x80);
228
4.22M
    return r;
229
4.22M
}
230
231
2.37M
uint64_t readULEB(std::string_view& sp) {
232
2.37M
    uint8_t shift;
233
2.37M
    uint8_t val;
234
2.37M
    return readULEB(sp, shift, val);
235
2.37M
}
236
237
// Read SLEB (signed) varint value; algorithm from the DWARF spec
238
1.84M
int64_t readSLEB(std::string_view& sp) {
239
1.84M
    uint8_t shift;
240
1.84M
    uint8_t val;
241
1.84M
    uint64_t r = readULEB(sp, shift, val);
242
243
1.84M
    if (shift < 64 && (val & 0x40)) {
244
878k
        r |= -(1ULL << shift); // sign extend
245
878k
    }
246
247
1.84M
    return r;
248
1.84M
}
249
250
// Read a value of "section offset" type, which may be 4 or 8 bytes
251
2.65M
uint64_t readOffset(std::string_view& sp, bool is64_bit) {
252
2.65M
    return is64_bit ? read<uint64_t>(sp) : read<uint32_t>(sp);
253
2.65M
}
254
255
// Read "len" bytes
256
0
std::string_view readBytes(std::string_view& sp, uint64_t len) {
257
0
    SAFE_CHECK(len <= sp.size(), "invalid string length: {} vs. {}", len, sp.size());
258
0
    std::string_view ret(sp.data(), len);
259
0
    sp.remove_prefix(len);
260
0
    return ret;
261
0
}
262
263
// Read a null-terminated string
264
128k
std::string_view readNullTerminated(std::string_view& sp) {
265
128k
    const char* p = static_cast<const char*>(memchr(sp.data(), 0, sp.size()));
266
128k
    SAFE_CHECK(p, "invalid null-terminated string");
267
128k
    std::string_view ret(sp.data(), p - sp.data());
268
128k
    sp = std::string_view(p + 1, sp.size());
269
128k
    return ret;
270
128k
}
271
272
// Get a string from the section
273
128k
std::string_view getStringFromStringSection(std::string_view section, uint64_t offset) {
274
128k
    SAFE_CHECK(offset < section.size(), "invalid section offset");
275
128k
    std::string_view sp(section);
276
128k
    sp.remove_prefix(offset);
277
128k
    return readNullTerminated(sp);
278
128k
}
279
280
// Skip over padding until sp.data() - start is a multiple of alignment
281
2.52M
void skipPadding(std::string_view& sp, const char* start, size_t alignment) {
282
2.52M
    size_t remainder = (sp.data() - start) % alignment;
283
2.52M
    if (remainder) {
284
2.52M
        SAFE_CHECK(alignment - remainder <= sp.size(), "invalid padding");
285
2.52M
        sp.remove_prefix(alignment - remainder);
286
2.52M
    }
287
2.52M
}
288
289
} // namespace
290
291
Dwarf::Path::Path(std::string_view baseDir, std::string_view subDir, std::string_view file)
292
522
        : baseDir_(baseDir), subDir_(subDir), file_(file) {
293
    // Normalize
294
522
    if (file_.empty()) {
295
0
        baseDir_ = {};
296
0
        subDir_ = {};
297
0
        return;
298
0
    }
299
300
522
    if (file_[0] == '/') {
301
        // file_ is absolute
302
261
        baseDir_ = {};
303
261
        subDir_ = {};
304
261
    }
305
306
522
    if (!subDir_.empty() && subDir_[0] == '/') {
307
261
        baseDir_ = {}; // subDir_ is absolute
308
261
    }
309
310
    // Make sure it's never the case that baseDir_ is empty, but subDir_ isn't.
311
522
    if (baseDir_.empty()) {
312
522
        swap(baseDir_, subDir_);
313
522
    }
314
522
}
315
316
522
size_t Dwarf::Path::size() const {
317
522
    size_t size = 0;
318
522
    bool needs_slash = false;
319
320
522
    if (!baseDir_.empty()) {
321
522
        size += baseDir_.size();
322
522
        needs_slash = baseDir_.back() != '/';
323
522
    }
324
325
522
    if (!subDir_.empty()) {
326
0
        size += needs_slash;
327
0
        size += subDir_.size();
328
0
        needs_slash = subDir_.back() != '/';
329
0
    }
330
331
522
    if (!file_.empty()) {
332
522
        size += needs_slash;
333
522
        size += file_.size();
334
522
    }
335
336
522
    return size;
337
522
}
338
339
0
size_t Dwarf::Path::toBuffer(char* buf, size_t bufSize) const {
340
0
    size_t total_size = 0;
341
0
    bool needs_slash = false;
342
343
0
    auto append = [&](std::string_view sp) {
344
0
        if (bufSize >= 2) {
345
0
            size_t to_copy = std::min(sp.size(), bufSize - 1);
346
0
            memcpy(buf, sp.data(), to_copy);
347
0
            buf += to_copy;
348
0
            bufSize -= to_copy;
349
0
        }
350
0
        total_size += sp.size();
351
0
    };
352
353
0
    if (!baseDir_.empty()) {
354
0
        append(baseDir_);
355
0
        needs_slash = baseDir_.back() != '/';
356
0
    }
357
0
    if (!subDir_.empty()) {
358
0
        if (needs_slash) {
359
0
            append("/");
360
0
        }
361
0
        append(subDir_);
362
0
        needs_slash = subDir_.back() != '/';
363
0
    }
364
0
    if (!file_.empty()) {
365
0
        if (needs_slash) {
366
0
            append("/");
367
0
        }
368
0
        append(file_);
369
0
    }
370
0
    if (bufSize) {
371
0
        *buf = '\0';
372
0
    }
373
374
0
    SAFE_CHECK(total_size == size(), "Size mismatch");
375
0
    return total_size;
376
0
}
377
378
261
void Dwarf::Path::toString(std::string& dest) const {
379
261
    size_t initial_size = dest.size();
380
261
    dest.reserve(initial_size + size());
381
261
    if (!baseDir_.empty()) {
382
261
        dest.append(baseDir_.begin(), baseDir_.end());
383
261
    }
384
261
    if (!subDir_.empty()) {
385
0
        if (!dest.empty() && dest.back() != '/') {
386
0
            dest.push_back('/');
387
0
        }
388
0
        dest.append(subDir_.begin(), subDir_.end());
389
0
    }
390
261
    if (!file_.empty()) {
391
261
        if (!dest.empty() && dest.back() != '/') {
392
261
            dest.push_back('/');
393
261
        }
394
261
        dest.append(file_.begin(), file_.end());
395
261
    }
396
261
    SAFE_CHECK(dest.size() == initial_size + size(), "Size mismatch");
397
261
}
398
399
// Next chunk in section
400
2.52M
bool Dwarf::Section::next(std::string_view& chunk) {
401
2.52M
    chunk = data;
402
2.52M
    if (chunk.empty()) {
403
272
        return false;
404
272
    }
405
406
    // Initial length is a uint32_t value for a 32-bit section, and
407
    // a 96-bit value (0xffffffff followed by the 64-bit length) for a 64-bit
408
    // section.
409
2.52M
    auto initial_length = read<uint32_t>(chunk);
410
2.52M
    is64_bit = (initial_length == uint32_t(-1));
411
2.52M
    auto length = is64_bit ? read<uint64_t>(chunk) : initial_length;
412
2.52M
    SAFE_CHECK(length <= chunk.size(), "invalid DWARF section");
413
2.52M
    chunk = std::string_view(chunk.data(), length);
414
2.52M
    data = std::string_view(chunk.end(), data.end() - chunk.end());
415
2.52M
    return true;
416
2.52M
}
417
418
5.66k
std::string_view Dwarf::getSection(const char* name) const {
419
5.66k
    std::optional<Elf::Section> elf_section = elf_->findSectionByName(name);
420
5.66k
    if (!elf_section) {
421
2.83k
        return {};
422
2.83k
    }
423
424
2.82k
#ifdef SHF_COMPRESSED
425
2.82k
    if (elf_section->header.sh_flags & SHF_COMPRESSED) {
426
0
        return {};
427
0
    }
428
2.82k
#endif
429
430
2.82k
    return {elf_section->begin(), elf_section->size()};
431
2.82k
}
432
433
// static
434
522
bool Dwarf::readAbbreviation(std::string_view& section, DIEAbbreviation& abbr) {
435
    // abbreviation code
436
522
    abbr.code = readULEB(section);
437
522
    if (abbr.code == 0) {
438
0
        return false;
439
0
    }
440
441
    // abbreviation tag
442
522
    abbr.tag = readULEB(section);
443
444
    // does this entry have children?
445
522
    abbr.has_children = (read<uint8_t>(section) != DW_CHILDREN_no);
446
447
    // attributes
448
522
    const char* attribute_begin = section.data();
449
6.07k
    for (;;) {
450
6.07k
        SAFE_CHECK(!section.empty(), "invalid attribute section");
451
6.07k
        auto attr = readAttributeSpec(section);
452
6.07k
        if (attr.name == 0 && attr.form == 0) {
453
522
            break;
454
522
        }
455
6.07k
    }
456
457
522
    abbr.attributes = std::string_view(attribute_begin, section.data() - attribute_begin);
458
522
    return true;
459
522
}
460
461
// static
462
0
void Dwarf::readCompilationUnitAbbrs(std::string_view abbrev, CompilationUnit& cu) {
463
0
    abbrev.remove_prefix(cu.abbrev_offset);
464
465
0
    DIEAbbreviation abbr;
466
0
    while (readAbbreviation(abbrev, abbr)) {
467
        // Abbreviation code 0 is reserved for null debugging information entries.
468
0
        if (abbr.code != 0 && abbr.code <= kMaxAbbreviationEntries) {
469
0
            cu.abbr_cache[abbr.code - 1] = abbr;
470
0
        }
471
0
    }
472
0
}
473
474
size_t Dwarf::forEachChild(const CompilationUnit& cu, const Die& die,
475
0
                           std::function<bool(const Die& die)> f) const {
476
0
    size_t next_die_offset = forEachAttribute(cu, die, [&](const Attribute&) { return true; });
477
0
    if (!die.abbr.has_children) {
478
0
        return next_die_offset;
479
0
    }
480
481
0
    auto child_die = getDieAtOffset(cu, next_die_offset);
482
0
    while (child_die.code != 0) {
483
0
        if (!f(child_die)) {
484
0
            return child_die.offset;
485
0
        }
486
487
        // NOTE: Don't run `f` over grandchildren, just skip over them.
488
0
        size_t sibling_offset = forEachChild(cu, child_die, [](const Die&) { return true; });
489
0
        child_die = getDieAtOffset(cu, sibling_offset);
490
0
    }
491
492
    // childDie is now a dummy die whose offset is to the code 0 marking the
493
    // end of the children. Need to add one to get the offset of the next die.
494
0
    return child_die.offset + 1;
495
0
}
496
497
/*
498
 * Iterate over all attributes of the given DIE, calling the given callable
499
 * for each. Iteration is stopped early if any of the calls return false.
500
 */
501
size_t Dwarf::forEachAttribute(const CompilationUnit& cu, const Die& die,
502
522
                               std::function<bool(const Attribute& die)> f) const {
503
522
    auto attrs = die.abbr.attributes;
504
522
    auto values = std::string_view {info_.data() + die.offset + die.attr_offset,
505
522
                                    cu.offset + cu.size - die.offset - die.attr_offset};
506
6.07k
    while (auto spec = readAttributeSpec(attrs)) {
507
5.55k
        auto attr = readAttribute(cu, die, spec, values);
508
5.55k
        if (!f(attr)) {
509
0
            return static_cast<size_t>(-1);
510
0
        }
511
5.55k
    }
512
522
    return values.data() - info_.data();
513
522
}
514
515
Dwarf::Attribute Dwarf::readAttribute(const CompilationUnit& cu, const Die& die, AttributeSpec spec,
516
5.55k
                                      std::string_view& info) const {
517
    // DWARF 5 introduces new FORMs whose values are relative to some base attrs:
518
    // DW_AT_str_offsets_base, DW_AT_rnglists_base, DW_AT_addr_base.
519
    // Debug Fission DWARF 4 uses GNU DW_AT_GNU_ranges_base & DW_AT_GNU_addr_base.
520
    //
521
    // The order in which attributes appear in a CU is not defined.
522
    // The DW_AT_*_base attrs may appear after attributes that need them.
523
    // The DW_AT_*_base attrs are CU specific; so we read them just after
524
    // reading the CU header. During this first pass return empty values
525
    // when encountering a FORM that depends on DW_AT_*_base.
526
5.55k
    auto get_string_using_offset_table = [&](uint64_t index) {
527
1.56k
        if (!cu.str_offsets_base.has_value()) {
528
522
            return std::string_view();
529
522
        }
530
        // DWARF 5: 7.26 String Offsets Table
531
        // The DW_AT_str_offsets_base attribute points to the first entry following
532
        // the header. The entries are indexed sequentially from this base entry,
533
        // starting from 0.
534
1.04k
        auto sp = str_offsets_.substr(*cu.str_offsets_base +
535
1.04k
                                      index * (cu.is64Bit ? sizeof(uint64_t) : sizeof(uint32_t)));
536
1.04k
        uint64_t str_offset = readOffset(sp, cu.is64Bit);
537
1.04k
        return getStringFromStringSection(str_, str_offset);
538
1.56k
    };
539
540
5.55k
    auto read_debug_addr = [&](uint64_t index) {
541
0
        if (!cu.addr_base.has_value()) {
542
0
            return uint64_t(0);
543
0
        }
544
        // DWARF 5: 7.27 Address Table
545
        // The DW_AT_addr_base attribute points to the first entry following the
546
        // header. The entries are indexed sequentially from this base entry,
547
        // starting from 0.
548
0
        auto sp = addr_.substr(*cu.addr_base + index * sizeof(uint64_t));
549
0
        return read<uint64_t>(sp);
550
0
    };
551
552
5.55k
    switch (spec.form) {
553
522
    case DW_FORM_addr:
554
522
        return {spec, die, read<uintptr_t>(info)};
555
0
    case DW_FORM_block1:
556
0
        return {spec, die, readBytes(info, read<uint8_t>(info))};
557
0
    case DW_FORM_block2:
558
0
        return {spec, die, readBytes(info, read<uint16_t>(info))};
559
0
    case DW_FORM_block4:
560
0
        return {spec, die, readBytes(info, read<uint32_t>(info))};
561
0
    case DW_FORM_block:
562
0
        [[fallthrough]];
563
0
    case DW_FORM_exprloc:
564
0
        return {spec, die, readBytes(info, readULEB(info))};
565
0
    case DW_FORM_data1:
566
0
        [[fallthrough]];
567
0
    case DW_FORM_ref1:
568
0
        return {spec, die, read<uint8_t>(info)};
569
522
    case DW_FORM_data2:
570
522
        [[fallthrough]];
571
522
    case DW_FORM_ref2:
572
522
        return {spec, die, read<uint16_t>(info)};
573
0
    case DW_FORM_data4:
574
0
        [[fallthrough]];
575
0
    case DW_FORM_ref4:
576
0
        return {spec, die, read<uint32_t>(info)};
577
0
    case DW_FORM_data8:
578
0
        [[fallthrough]];
579
0
    case DW_FORM_ref8:
580
0
        [[fallthrough]];
581
0
    case DW_FORM_ref_sig8:
582
0
        return {spec, die, read<uint64_t>(info)};
583
0
    case DW_FORM_sdata:
584
0
        return {spec, die, static_cast<uint64_t>(readSLEB(info))};
585
0
    case DW_FORM_udata:
586
0
        [[fallthrough]];
587
0
    case DW_FORM_ref_udata:
588
0
        return {spec, die, readULEB(info)};
589
0
    case DW_FORM_flag:
590
0
        return {spec, die, read<uint8_t>(info)};
591
0
    case DW_FORM_flag_present:
592
0
        return {spec, die, 1ULL};
593
2.41k
    case DW_FORM_sec_offset:
594
2.41k
        [[fallthrough]];
595
2.41k
    case DW_FORM_ref_addr:
596
2.41k
        return {spec, die, readOffset(info, die.is64Bit)};
597
0
    case DW_FORM_string:
598
0
        return {spec, die, readNullTerminated(info)};
599
0
    case DW_FORM_strp:
600
0
        return {spec, die, getStringFromStringSection(str_, readOffset(info, die.is64Bit))};
601
0
    case DW_FORM_indirect: // form is explicitly specified
602
        // Update spec with the actual FORM.
603
0
        spec.form = readULEB(info);
604
0
        return readAttribute(cu, die, spec, info);
605
606
    // DWARF 5:
607
0
    case DW_FORM_implicit_const: // form is explicitly specified
608
        // For attributes with this form, the attribute specification contains a
609
        // third part, which is a signed LEB128 number. The value of this number
610
        // is used as the value of the attribute, and no value is stored in the
611
        // .debug_info section.
612
0
        return {spec, die, static_cast<uint64_t>(spec.implicitConst)};
613
614
0
    case DW_FORM_addrx:
615
0
        return {spec, die, read_debug_addr(readULEB(info))};
616
0
    case DW_FORM_addrx1:
617
0
        return {spec, die, read_debug_addr(readU64<1>(info))};
618
0
    case DW_FORM_addrx2:
619
0
        return {spec, die, read_debug_addr(readU64<2>(info))};
620
0
    case DW_FORM_addrx3:
621
0
        return {spec, die, read_debug_addr(readU64<3>(info))};
622
0
    case DW_FORM_addrx4:
623
0
        return {spec, die, read_debug_addr(readU64<4>(info))};
624
625
0
    case DW_FORM_line_strp:
626
0
        return {spec, die, getStringFromStringSection(line_str_, readOffset(info, die.is64Bit))};
627
628
0
    case DW_FORM_strx:
629
0
        return {spec, die, get_string_using_offset_table(readULEB(info))};
630
1.56k
    case DW_FORM_strx1:
631
1.56k
        return {spec, die, get_string_using_offset_table(readU64<1>(info))};
632
0
    case DW_FORM_strx2:
633
0
        return {spec, die, get_string_using_offset_table(readU64<2>(info))};
634
0
    case DW_FORM_strx3:
635
0
        return {spec, die, get_string_using_offset_table(readU64<3>(info))};
636
0
    case DW_FORM_strx4:
637
0
        return {spec, die, get_string_using_offset_table(readU64<4>(info))};
638
639
522
    case DW_FORM_rnglistx: {
640
522
        auto index = readULEB(info);
641
522
        if (!cu.rnglists_base.has_value()) {
642
261
            return {spec, die, 0ULL};
643
261
        }
644
261
        const uint64_t offset_size = cu.is64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
645
261
        auto sp = rnglists_.substr(*cu.rnglists_base + index * offset_size);
646
261
        auto offset = readOffset(sp, cu.is64Bit);
647
261
        return {spec, die, *cu.rnglists_base + offset};
648
522
    }
649
650
0
    case DW_FORM_loclistx: {
651
0
        auto index = readULEB(info);
652
0
        if (!cu.loclists_base.has_value()) {
653
0
            return {spec, die, 0ULL};
654
0
        }
655
0
        const uint64_t offset_size = cu.is64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
656
0
        auto sp = loclists_.substr(*cu.loclists_base + index * offset_size);
657
0
        auto offset = readOffset(sp, cu.is64Bit);
658
0
        return {spec, die, *cu.loclists_base + offset};
659
0
    }
660
661
0
    case DW_FORM_data16:
662
0
        return {spec, die, readBytes(info, 16)};
663
664
0
    case DW_FORM_ref_sup4:
665
0
    case DW_FORM_ref_sup8:
666
0
    case DW_FORM_strp_sup:
667
0
        SAFE_CHECK(false, "Unexpected DWARF5 supplimentary object files");
668
669
0
    default:
670
0
        SAFE_CHECK(false, "invalid attribute form");
671
5.55k
    }
672
0
    return {spec, die, 0ULL};
673
5.55k
}
674
675
// static
676
12.1k
Dwarf::AttributeSpec Dwarf::readAttributeSpec(std::string_view& sp) {
677
12.1k
    Dwarf::AttributeSpec spec;
678
12.1k
    spec.name = readULEB(sp);
679
12.1k
    spec.form = readULEB(sp);
680
12.1k
    if (spec.form == DW_FORM_implicit_const) {
681
0
        spec.implicitConst = readSLEB(sp);
682
0
    }
683
12.1k
    return spec;
684
12.1k
}
685
686
261
Dwarf::CompilationUnit Dwarf::getCompilationUnit(uint64_t offset) const {
687
    // SAFE_CHECK(offset < info_.size(), "unexpected offset");
688
261
    CompilationUnit cu;
689
261
    std::string_view chunk(info_);
690
261
    cu.offset = offset;
691
261
    chunk.remove_prefix(offset);
692
693
    // 1) unit_length
694
261
    auto initial_length = read<uint32_t>(chunk);
695
261
    cu.is64Bit = (initial_length == uint32_t(-1));
696
261
    cu.size = cu.is64Bit ? read<uint64_t>(chunk) : initial_length;
697
261
    SAFE_CHECK(cu.size <= chunk.size(), "invalid chunk size");
698
261
    cu.size += cu.is64Bit ? 12 : 4;
699
700
    // 2) version
701
261
    cu.version = read<uint16_t>(chunk);
702
261
    SAFE_CHECK(cu.version >= 2 && cu.version <= 5, "invalid info version");
703
704
261
    if (cu.version == 5) {
705
        // DWARF5: 7.5.1.1 Full and Partial Compilation Unit Headers
706
        // 3) unit_type (new DWARF 5)
707
261
        cu.unit_type = read<uint8_t>(chunk);
708
261
        if (cu.unit_type != DW_UT_compile && cu.unit_type != DW_UT_skeleton) {
709
0
            return cu;
710
0
        }
711
        // 4) address_size
712
261
        cu.addr_size = read<uint8_t>(chunk);
713
261
        SAFE_CHECK(cu.addr_size == sizeof(uintptr_t), "invalid address size");
714
715
        // 5) debug_abbrev_offset
716
261
        cu.abbrev_offset = readOffset(chunk, cu.is64Bit);
717
718
261
        if (cu.unit_type == DW_UT_skeleton) {
719
            // 6) dwo_id
720
0
            read<uint64_t>(chunk);
721
0
        }
722
261
    } else {
723
        // DWARF4 has a single type of unit in .debug_info
724
0
        cu.unit_type = DW_UT_compile;
725
        // 3) debug_abbrev_offset
726
0
        cu.abbrev_offset = readOffset(chunk, cu.is64Bit);
727
        // 4) address_size
728
0
        cu.addr_size = read<uint8_t>(chunk);
729
0
        SAFE_CHECK(cu.addr_size == sizeof(uintptr_t), "invalid address size");
730
0
    }
731
261
    cu.first_die = chunk.data() - info_.data();
732
261
    if (cu.version < 5) {
733
0
        return cu;
734
0
    }
735
736
261
    Die die = getDieAtOffset(cu, cu.first_die);
737
261
    if (die.abbr.tag != DW_TAG_compile_unit) {
738
0
        return cu;
739
0
    }
740
741
    // Read the DW_AT_*_base attributes.
742
    // Attributes which use FORMs relative to these base attrs
743
    // will not have valid values during this first pass!
744
2.77k
    forEachAttribute(cu, die, [&](const Attribute& attr) {
745
2.77k
        switch (attr.spec.name) {
746
261
        case DW_AT_addr_base:
747
261
        case DW_AT_GNU_addr_base:
748
261
            cu.addr_base = std::get<uint64_t>(attr.attr_value);
749
261
            break;
750
165
        case DW_AT_loclists_base:
751
165
            cu.loclists_base = std::get<uint64_t>(attr.attr_value);
752
165
            break;
753
261
        case DW_AT_rnglists_base:
754
261
        case DW_AT_GNU_ranges_base:
755
261
            cu.rnglists_base = std::get<uint64_t>(attr.attr_value);
756
261
            break;
757
261
        case DW_AT_str_offsets_base:
758
261
            cu.str_offsets_base = std::get<uint64_t>(attr.attr_value);
759
261
            break;
760
2.77k
        }
761
2.77k
        return true; // continue forEachAttribute
762
2.77k
    });
763
261
    return cu;
764
261
}
765
766
// Finds the Compilation Unit starting at offset.
767
0
Dwarf::CompilationUnit Dwarf::findCompilationUnit(uint64_t targetOffset) const {
768
    // SAFE_CHECK(targetOffset < info_.size(), "unexpected target address");
769
0
    uint64_t offset = 0;
770
0
    while (offset < info_.size()) {
771
0
        std::string_view chunk(info_);
772
0
        chunk.remove_prefix(offset);
773
774
0
        auto initial_length = read<uint32_t>(chunk);
775
0
        auto is64_bit = (initial_length == static_cast<uint32_t>(-1));
776
0
        auto size = is64_bit ? read<uint64_t>(chunk) : initial_length;
777
0
        SAFE_CHECK(size <= chunk.size(), "invalid chunk size");
778
0
        size += is64_bit ? 12 : 4;
779
780
0
        if (offset + size > targetOffset) {
781
0
            break;
782
0
        }
783
0
        offset += size;
784
0
    }
785
0
    return getCompilationUnit(offset);
786
0
}
787
788
522
Dwarf::DIEAbbreviation Dwarf::getAbbreviation(uint64_t code, uint64_t offset) const {
789
    // Linear search in the .debug_abbrev section, starting at offset
790
522
    std::string_view section = abbrev_;
791
522
    section.remove_prefix(offset);
792
793
522
    Dwarf::DIEAbbreviation abbr;
794
522
    while (readAbbreviation(section, abbr)) {
795
522
        if (abbr.code == code) {
796
522
            return abbr;
797
522
        }
798
522
    }
799
800
0
    SAFE_CHECK(false, "could not find abbreviation code");
801
0
}
802
803
Dwarf::AttributeValue Dwarf::readAttributeValue(std::string_view& sp, uint64_t form,
804
0
                                                bool is64_bit) const {
805
0
    switch (form) {
806
0
    case DW_FORM_addr:
807
0
        return uint64_t(read<uintptr_t>(sp));
808
0
    case DW_FORM_block1:
809
0
        return readBytes(sp, read<uint8_t>(sp));
810
0
    case DW_FORM_block2:
811
0
        return readBytes(sp, read<uint16_t>(sp));
812
0
    case DW_FORM_block4:
813
0
        return readBytes(sp, read<uint32_t>(sp));
814
0
    case DW_FORM_block:
815
0
        [[fallthrough]];
816
0
    case DW_FORM_exprloc:
817
0
        return readBytes(sp, readULEB(sp));
818
0
    case DW_FORM_data1:
819
0
        [[fallthrough]];
820
0
    case DW_FORM_ref1:
821
0
        return uint64_t(read<uint8_t>(sp));
822
0
    case DW_FORM_data2:
823
0
        [[fallthrough]];
824
0
    case DW_FORM_ref2:
825
0
        return uint64_t(read<uint16_t>(sp));
826
0
    case DW_FORM_data4:
827
0
        [[fallthrough]];
828
0
    case DW_FORM_ref4:
829
0
        return uint64_t(read<uint32_t>(sp));
830
0
    case DW_FORM_data8:
831
0
        [[fallthrough]];
832
0
    case DW_FORM_ref8:
833
0
        return read<uint64_t>(sp);
834
0
    case DW_FORM_sdata:
835
0
        return uint64_t(readSLEB(sp));
836
0
    case DW_FORM_udata:
837
0
        [[fallthrough]];
838
0
    case DW_FORM_ref_udata:
839
0
        return readULEB(sp);
840
0
    case DW_FORM_flag:
841
0
        return uint64_t(read<uint8_t>(sp));
842
0
    case DW_FORM_flag_present:
843
0
        return uint64_t(1);
844
0
    case DW_FORM_sec_offset:
845
0
        [[fallthrough]];
846
0
    case DW_FORM_ref_addr:
847
0
        return readOffset(sp, is64_bit);
848
0
    case DW_FORM_string:
849
0
        return readNullTerminated(sp);
850
0
    case DW_FORM_strp:
851
0
        return getStringFromStringSection(str_, readOffset(sp, is64_bit));
852
0
    case DW_FORM_indirect: // form is explicitly specified
853
0
        return readAttributeValue(sp, readULEB(sp), is64_bit);
854
0
    default:
855
0
        SAFE_CHECK(false, "invalid attribute form");
856
0
        return uint64_t(1);
857
0
        ;
858
0
    }
859
0
}
860
861
/**
862
 * Find @address in .debug_aranges and return the offset in
863
 * .debug_info for compilation unit to which this address belongs.
864
 */
865
533
bool Dwarf::findDebugInfoOffset(uintptr_t address, std::string_view aranges, uint64_t& offset) {
866
533
    Section aranges_section(aranges);
867
533
    std::string_view chunk;
868
2.52M
    while (aranges_section.next(chunk)) {
869
2.52M
        auto version = read<uint16_t>(chunk);
870
2.52M
        SAFE_CHECK(version == 2, "invalid aranges version");
871
872
2.52M
        offset = readOffset(chunk, aranges_section.is64Bit());
873
2.52M
        auto address_size = read<uint8_t>(chunk);
874
2.52M
        SAFE_CHECK(address_size == sizeof(uintptr_t), "invalid address size");
875
2.52M
        auto segment_size = read<uint8_t>(chunk);
876
2.52M
        SAFE_CHECK(segment_size == 0, "segmented architecture not supported");
877
878
        // Padded to a multiple of 2 addresses.
879
        // Strangely enough, this is the only place in the DWARF spec that requires
880
        // padding.
881
2.52M
        skipPadding(chunk, aranges.data(), 2 * sizeof(uintptr_t));
882
1.71G
        for (;;) {
883
1.71G
            auto start = read<uintptr_t>(chunk);
884
1.71G
            auto length = read<uintptr_t>(chunk);
885
886
1.71G
            if (start == 0 && length == 0) {
887
2.52M
                break;
888
2.52M
            }
889
890
            // Is our address in this range?
891
1.71G
            if (address >= start && address < start + length) {
892
261
                return true;
893
261
            }
894
1.71G
        }
895
2.52M
    }
896
272
    return false;
897
533
}
898
899
522
Dwarf::Die Dwarf::getDieAtOffset(const CompilationUnit& cu, uint64_t offset) const {
900
522
    SAFE_CHECK(offset < info_.size(), "unexpected offset {}, info size {}", offset, info_.size());
901
522
    Die die;
902
522
    std::string_view sp {info_.data() + offset, cu.offset + cu.size - offset};
903
522
    die.offset = offset;
904
522
    die.is64Bit = cu.is64Bit;
905
522
    auto code = readULEB(sp);
906
522
    die.code = code;
907
522
    if (code == 0) {
908
0
        return die;
909
0
    }
910
522
    die.attr_offset = sp.data() - info_.data() - offset;
911
522
    die.abbr = !cu.abbr_cache.empty() && die.code < kMaxAbbreviationEntries
912
522
                       ? cu.abbr_cache[die.code - 1]
913
522
                       : getAbbreviation(die.code, cu.abbrev_offset);
914
915
522
    return die;
916
522
}
917
918
/**
919
 * Find the @locationInfo for @address in the compilation unit represented
920
 * by the @sp .debug_info entry.
921
 * Returns whether the address was found.
922
 * Advances @sp to the next entry in .debug_info.
923
 */
924
bool Dwarf::findLocation(uintptr_t address, const LocationInfoMode mode, CompilationUnit& cu,
925
261
                         LocationInfo& info, std::vector<SymbolizedFrame>& inline_frames) const {
926
261
    Die die = getDieAtOffset(cu, cu.first_die);
927
    // Partial compilation unit (DW_TAG_partial_unit) is not supported.
928
261
    SAFE_CHECK(die.abbr.tag == DW_TAG_compile_unit, "expecting compile unit entry");
929
930
    // Offset in .debug_line for the line number VM program for this CU
931
261
    std::optional<uint64_t> line_offset = 0;
932
261
    std::string_view compilation_directory;
933
261
    std::optional<std::string_view> main_file_name;
934
261
    std::optional<uint64_t> base_addr_cu;
935
936
2.77k
    forEachAttribute(cu, die, [&](const Attribute& attr) {
937
2.77k
        switch (attr.spec.name) {
938
261
        case DW_AT_stmt_list:
939
            // Offset in .debug_line for the line number VM program for this
940
            // compilation unit
941
261
            line_offset = std::get<uint64_t>(attr.attr_value);
942
261
            break;
943
261
        case DW_AT_comp_dir:
944
            // Compilation directory
945
261
            compilation_directory = std::get<std::string_view>(attr.attr_value);
946
261
            break;
947
261
        case DW_AT_name:
948
            // File name of main file being compiled
949
261
            main_file_name = std::get<std::string_view>(attr.attr_value);
950
261
            break;
951
261
        case DW_AT_low_pc:
952
261
        case DW_AT_entry_pc:
953
            // 2.17.1: historically DW_AT_low_pc was used. DW_AT_entry_pc was
954
            // introduced in DWARF3. Support either to determine the base address of
955
            // the CU.
956
261
            base_addr_cu = std::get<uint64_t>(attr.attr_value);
957
261
            break;
958
2.77k
        }
959
        // Iterate through all attributes until find all above.
960
2.77k
        return true;
961
2.77k
    });
962
963
261
    if (main_file_name) {
964
261
        info.has_main_file = true;
965
261
        info.main_file = Path(compilation_directory, "", *main_file_name);
966
261
    }
967
968
261
    if (!line_offset) {
969
0
        return false;
970
0
    }
971
972
261
    std::string_view line_section(line_);
973
261
    line_section.remove_prefix(*line_offset);
974
261
    LineNumberVM line_vm(line_section, compilation_directory, str_, line_str_);
975
976
    // Execute line number VM program to find file and line
977
261
    info.has_file_and_line = line_vm.findAddress(address, info.file, info.line);
978
979
261
    bool check_inline = (mode == LocationInfoMode::FULL_WITH_INLINE);
980
981
261
    if (info.has_file_and_line && check_inline) {
982
        // Re-get the compilation unit with abbreviation cached.
983
0
        cu.abbr_cache.clear();
984
0
        cu.abbr_cache.resize(kMaxAbbreviationEntries);
985
0
        readCompilationUnitAbbrs(abbrev_, cu);
986
987
        // Find the subprogram that matches the given address.
988
0
        Die subprogram;
989
0
        findSubProgramDieForAddress(cu, die, address, base_addr_cu, subprogram);
990
991
        // Subprogram is the DIE of caller function.
992
0
        if (/*check_inline &&*/ subprogram.abbr.has_children) {
993
            // Use an extra location and get its call file and call line, so that
994
            // they can be used for the second last location when we don't have
995
            // enough inline frames for all inline functions call stack.
996
0
            const size_t max_size = Dwarf::kMaxInlineLocationInfoPerFrame + 1;
997
0
            std::vector<CallLocation> call_locations;
998
0
            call_locations.reserve(Dwarf::kMaxInlineLocationInfoPerFrame + 1);
999
1000
0
            findInlinedSubroutineDieForAddress(cu, subprogram, line_vm, address, base_addr_cu,
1001
0
                                               call_locations, max_size);
1002
0
            size_t num_found = call_locations.size();
1003
1004
0
            if (num_found > 0) {
1005
0
                const auto inner_most_file = info.file;
1006
0
                const auto inner_most_line = info.line;
1007
1008
                // Earlier we filled in locationInfo:
1009
                // - mainFile: the path to the CU -- the file where the non-inlined
1010
                //   call is made from.
1011
                // - file + line: the location of the inner-most inlined call.
1012
                // Here we already find inlined info so mainFile would be redundant.
1013
0
                info.has_main_file = false;
1014
0
                info.main_file = Path {};
1015
                // @findInlinedSubroutineDieForAddress fills inlineLocations[0] with the
1016
                // file+line of the non-inlined outer function making the call.
1017
                // locationInfo.name is already set by the caller by looking up the
1018
                // non-inlined function @address belongs to.
1019
0
                info.has_file_and_line = true;
1020
0
                info.file = call_locations[0].file;
1021
0
                info.line = call_locations[0].line;
1022
1023
                // The next inlined subroutine's call file and call line is the current
1024
                // caller's location.
1025
0
                for (size_t i = 0; i < num_found - 1; ++i) {
1026
0
                    call_locations[i].file = call_locations[i + 1].file;
1027
0
                    call_locations[i].line = call_locations[i + 1].line;
1028
0
                }
1029
                // CallLocation for the inner-most inlined function:
1030
                // - will be computed if enough space was available in the passed
1031
                //   buffer.
1032
                // - will have a .name, but no !.file && !.line
1033
                // - its corresponding file+line is the one returned by LineVM based
1034
                //   on @address.
1035
                // Use the inner-most inlined file+line info we got from the LineVM.
1036
0
                call_locations[num_found - 1].file = inner_most_file;
1037
0
                call_locations[num_found - 1].line = inner_most_line;
1038
1039
                // Fill in inline frames in reverse order (as expected by the caller).
1040
0
                std::reverse(call_locations.begin(), call_locations.end());
1041
0
                for (const auto& call_location : call_locations) {
1042
0
                    SymbolizedFrame inline_frame;
1043
0
                    inline_frame.found = true;
1044
0
                    inline_frame.addr = address;
1045
0
                    if (!call_location.name.empty()) {
1046
0
                        inline_frame.name = call_location.name.data();
1047
0
                    } else {
1048
0
                        inline_frame.name = nullptr;
1049
0
                    }
1050
0
                    inline_frame.location.has_file_and_line = true;
1051
0
                    inline_frame.location.file = call_location.file;
1052
0
                    inline_frame.location.line = call_location.line;
1053
0
                    inline_frames.push_back(inline_frame);
1054
0
                }
1055
0
            }
1056
0
        }
1057
0
    }
1058
1059
261
    return info.has_file_and_line;
1060
261
}
1061
1062
void Dwarf::findSubProgramDieForAddress(const CompilationUnit& cu, const Die& die, uint64_t address,
1063
                                        std::optional<uint64_t> base_addr_cu,
1064
0
                                        Die& subprogram) const {
1065
0
    forEachChild(cu, die, [&](const Die& child_die) {
1066
0
        if (child_die.abbr.tag == DW_TAG_subprogram) {
1067
0
            std::optional<uint64_t> low_pc;
1068
0
            std::optional<uint64_t> high_pc;
1069
0
            std::optional<bool> is_high_pc_addr;
1070
0
            std::optional<uint64_t> range_offset;
1071
0
            forEachAttribute(cu, child_die, [&](const Attribute& attr) {
1072
0
                switch (attr.spec.name) {
1073
0
                case DW_AT_ranges:
1074
0
                    range_offset = std::get<uint64_t>(attr.attr_value);
1075
0
                    break;
1076
0
                case DW_AT_low_pc:
1077
0
                    low_pc = std::get<uint64_t>(attr.attr_value);
1078
0
                    break;
1079
0
                case DW_AT_high_pc:
1080
                    // The value of the DW_AT_high_pc attribute can be
1081
                    // an address (DW_FORM_addr*) or an offset (DW_FORM_data*).
1082
0
                    is_high_pc_addr = attr.spec.form == DW_FORM_addr ||   //
1083
0
                                      attr.spec.form == DW_FORM_addrx ||  //
1084
0
                                      attr.spec.form == DW_FORM_addrx1 || //
1085
0
                                      attr.spec.form == DW_FORM_addrx2 || //
1086
0
                                      attr.spec.form == DW_FORM_addrx3 || //
1087
0
                                      attr.spec.form == DW_FORM_addrx4;
1088
0
                    high_pc = std::get<uint64_t>(attr.attr_value);
1089
0
                    break;
1090
0
                }
1091
                // Iterate through all attributes until find all above.
1092
0
                return true;
1093
0
            });
1094
0
            bool pc_match = low_pc && high_pc && is_high_pc_addr && address >= *low_pc &&
1095
0
                            (address < (*is_high_pc_addr ? *high_pc : *low_pc + *high_pc));
1096
0
            bool range_match =
1097
0
                    range_offset && isAddrInRangeList(cu, address, base_addr_cu,
1098
0
                                                      range_offset.value(), cu.addr_size);
1099
0
            if (pc_match || range_match) {
1100
0
                subprogram = child_die;
1101
0
                return false;
1102
0
            }
1103
0
        }
1104
1105
0
        findSubProgramDieForAddress(cu, child_die, address, base_addr_cu, subprogram);
1106
1107
        // Iterates through children until find the inline subprogram.
1108
0
        return true;
1109
0
    });
1110
0
}
1111
1112
/**
1113
 * Find DW_TAG_inlined_subroutine child DIEs that contain @address and
1114
 * then extract:
1115
 * - Where was it called from (DW_AT_call_file & DW_AT_call_line):
1116
 *   the statement or expression that caused the inline expansion.
1117
 * - The inlined function's name. As a function may be inlined multiple
1118
 *   times, common attributes like DW_AT_linkage_name or DW_AT_name
1119
 *   are only stored in its "concrete out-of-line instance" (a
1120
 *   DW_TAG_subprogram) which we find using DW_AT_abstract_origin.
1121
 */
1122
void Dwarf::findInlinedSubroutineDieForAddress(const CompilationUnit& cu, const Die& die,
1123
                                               const LineNumberVM& line_vm, uint64_t address,
1124
                                               std::optional<uint64_t> base_addr_cu,
1125
                                               std::vector<CallLocation>& locations,
1126
0
                                               const size_t max_size) const {
1127
0
    if (locations.size() >= max_size) {
1128
0
        return;
1129
0
    }
1130
1131
0
    forEachChild(cu, die, [&](const Die& child_die) {
1132
        // Between a DW_TAG_subprogram and and DW_TAG_inlined_subroutine we might
1133
        // have arbitrary intermediary "nodes", including DW_TAG_common_block,
1134
        // DW_TAG_lexical_block, DW_TAG_try_block, DW_TAG_catch_block and
1135
        // DW_TAG_with_stmt, etc.
1136
        // We can't filter with locationhere since its range may be not specified.
1137
        // See section 2.6.2: A location list containing only an end of list entry
1138
        // describes an object that exists in the source code but not in the
1139
        // executable program.
1140
0
        if (child_die.abbr.tag == DW_TAG_try_block || child_die.abbr.tag == DW_TAG_catch_block ||
1141
0
            child_die.abbr.tag == DW_TAG_entry_point || child_die.abbr.tag == DW_TAG_common_block ||
1142
0
            child_die.abbr.tag == DW_TAG_lexical_block) {
1143
0
            findInlinedSubroutineDieForAddress(cu, child_die, line_vm, address, base_addr_cu,
1144
0
                                               locations, max_size);
1145
0
            return true;
1146
0
        }
1147
1148
0
        std::optional<uint64_t> low_pc;
1149
0
        std::optional<uint64_t> high_pc;
1150
0
        std::optional<bool> is_high_pc_addr;
1151
0
        std::optional<uint64_t> abstract_origin;
1152
0
        std::optional<uint64_t> abstract_origin_ref_type;
1153
0
        std::optional<uint64_t> call_file;
1154
0
        std::optional<uint64_t> call_line;
1155
0
        std::optional<uint64_t> range_offset;
1156
0
        forEachAttribute(cu, child_die, [&](const Attribute& attr) {
1157
0
            switch (attr.spec.name) {
1158
0
            case DW_AT_ranges:
1159
0
                range_offset = std::get<uint64_t>(attr.attr_value);
1160
0
                break;
1161
0
            case DW_AT_low_pc:
1162
0
                low_pc = std::get<uint64_t>(attr.attr_value);
1163
0
                break;
1164
0
            case DW_AT_high_pc:
1165
                // The value of the DW_AT_high_pc attribute can be
1166
                // an address (DW_FORM_addr*) or an offset (DW_FORM_data*).
1167
0
                is_high_pc_addr = attr.spec.form == DW_FORM_addr ||   //
1168
0
                                  attr.spec.form == DW_FORM_addrx ||  //
1169
0
                                  attr.spec.form == DW_FORM_addrx1 || //
1170
0
                                  attr.spec.form == DW_FORM_addrx2 || //
1171
0
                                  attr.spec.form == DW_FORM_addrx3 || //
1172
0
                                  attr.spec.form == DW_FORM_addrx4;
1173
0
                high_pc = std::get<uint64_t>(attr.attr_value);
1174
0
                break;
1175
0
            case DW_AT_abstract_origin:
1176
0
                abstract_origin_ref_type = attr.spec.form;
1177
0
                abstract_origin = std::get<uint64_t>(attr.attr_value);
1178
0
                break;
1179
0
            case DW_AT_call_line:
1180
0
                call_line = std::get<uint64_t>(attr.attr_value);
1181
0
                break;
1182
0
            case DW_AT_call_file:
1183
0
                call_file = std::get<uint64_t>(attr.attr_value);
1184
0
                break;
1185
0
            }
1186
            // Iterate through all until find all above attributes.
1187
0
            return true;
1188
0
        });
1189
1190
        // 2.17 Code Addresses and Ranges
1191
        // Any debugging information entry describing an entity that has a
1192
        // machine code address or range of machine code addresses,
1193
        // which includes compilation units, module initialization, subroutines,
1194
        // ordinary blocks, try/catch blocks, labels and the like, may have
1195
        //  - A DW_AT_low_pc attribute for a single address,
1196
        //  - A DW_AT_low_pc and DW_AT_high_pc pair of attributes for a
1197
        //    single contiguous range of addresses, or
1198
        //  - A DW_AT_ranges attribute for a non-contiguous range of addresses.
1199
        // TODO: Support DW_TAG_entry_point and DW_TAG_common_block that don't
1200
        // have DW_AT_low_pc/DW_AT_high_pc pairs and DW_AT_ranges.
1201
        // TODO: Support relocated address which requires lookup in relocation map.
1202
0
        bool pc_match = low_pc && high_pc && is_high_pc_addr && address >= *low_pc &&
1203
0
                        (address < (*is_high_pc_addr ? *high_pc : *low_pc + *high_pc));
1204
0
        bool range_match = range_offset && isAddrInRangeList(cu, address, base_addr_cu,
1205
0
                                                             range_offset.value(), cu.addr_size);
1206
0
        if (!pc_match && !range_match) {
1207
            // Address doesn't match. Keep searching other children.
1208
0
            return true;
1209
0
        }
1210
1211
0
        if (!abstract_origin || !abstract_origin_ref_type || !call_line || !call_file) {
1212
            // We expect a single sibling DIE to match on addr, but it's missing
1213
            // required fields. Stop searching for other DIEs.
1214
0
            return false;
1215
0
        }
1216
1217
0
        CallLocation location;
1218
0
        location.file = line_vm.getFullFileName(*call_file);
1219
0
        location.line = *call_line;
1220
1221
        /// Something wrong with receiving debug info about inline.
1222
        /// If set to true we stop parsing DWARF.
1223
0
        bool die_for_inline_broken = false;
1224
1225
        // DW_AT_abstract_origin is a reference. There a 3 types of references:
1226
        // - the reference can identify any debugging information entry within the
1227
        //   compilation unit (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4,
1228
        //   DW_FORM_ref8, DW_FORM_ref_udata). This type of reference is an offset
1229
        //   from the first byte of the compilation header for the compilation unit
1230
        //   containing the reference.
1231
        // - the reference can identify any debugging information entry within a
1232
        //   .debug_info section; in particular, it may refer to an entry in a
1233
        //   different compilation unit (DW_FORM_ref_addr)
1234
        // - the reference can identify any debugging information type entry that
1235
        //   has been placed in its own type unit.
1236
        //   Not applicable for DW_AT_abstract_origin.
1237
0
        location.name = (*abstract_origin_ref_type != DW_FORM_ref_addr)
1238
0
                                ? getFunctionNameFromDie(cu, cu.offset + *abstract_origin,
1239
0
                                                         die_for_inline_broken)
1240
0
                                : getFunctionNameFromDie(findCompilationUnit(*abstract_origin),
1241
0
                                                         *abstract_origin, die_for_inline_broken);
1242
        /// FIXME: see comment above
1243
0
        if (die_for_inline_broken) {
1244
0
            return false;
1245
0
        }
1246
1247
0
        locations.push_back(location);
1248
1249
0
        findInlinedSubroutineDieForAddress(cu, child_die, line_vm, address, base_addr_cu, locations,
1250
0
                                           max_size);
1251
1252
0
        return false;
1253
0
    });
1254
0
}
1255
1256
std::string_view Dwarf::getFunctionNameFromDie(const CompilationUnit& srcu, uint64_t die_offset,
1257
0
                                               bool& die_for_inline_broken) const {
1258
0
    Die decl_die = getDieAtOffset(srcu, die_offset);
1259
0
    auto& die_to_look_for_name = decl_die;
1260
1261
0
    Die def_die;
1262
    // Jump to the actual function definition instead of declaration for name
1263
    // and line info.
1264
    // DW_AT_specification: Incomplete, non-defining, or separate declaration
1265
    // corresponding to a declaration
1266
0
    auto offset = getAttribute<uint64_t>(srcu, decl_die, DW_AT_specification);
1267
0
    if (offset) {
1268
        /// FIXME: actually it's a bug in our DWARF parser.
1269
        ///
1270
        /// Most of the times compilation unit offset (srcu.offset) is some big number inside .debug_info (like 434782255).
1271
        /// Offset of DIE definition is some small relative number to srcu.offset (like 3518).
1272
        /// However in some unknown cases offset looks like global, non relative number (like 434672579) and in this
1273
        /// case we obviously doing something wrong parsing DWARF.
1274
        ///
1275
        /// What is important -- this bug? reproduces only with -flto=thin in release mode.
1276
        /// Also llvm-dwarfdump --verify ./clickhouse says that our DWARF is ok, so it's another prove
1277
        /// that we just doing something wrong.
1278
        ///
1279
        /// FIXME: Currently we just give up parsing DWARF for inlines when we got into this situation.
1280
0
        if (srcu.offset + offset.value() >= info_.size()) {
1281
0
            die_for_inline_broken = true;
1282
0
        } else {
1283
0
            def_die = getDieAtOffset(srcu, srcu.offset + offset.value());
1284
0
            die_to_look_for_name = def_die;
1285
0
        }
1286
0
    }
1287
1288
0
    std::string_view name;
1289
1290
0
    if (die_for_inline_broken) {
1291
0
        return name;
1292
0
    }
1293
1294
    // The file and line will be set in the next inline subroutine based on
1295
    // its DW_AT_call_file and DW_AT_call_line.
1296
0
    forEachAttribute(srcu, die_to_look_for_name, [&](const Attribute& attr) {
1297
0
        switch (attr.spec.name) {
1298
0
        case DW_AT_linkage_name:
1299
0
            name = std::get<std::string_view>(attr.attr_value);
1300
0
            break;
1301
0
        case DW_AT_name:
1302
            // NOTE: when DW_AT_linkage_name and DW_AT_name match, dwarf
1303
            // emitters omit DW_AT_linkage_name (to save space). If present
1304
            // DW_AT_linkage_name should always be preferred (mangled C++ name
1305
            // vs just the function name).
1306
0
            if (name.empty()) {
1307
0
                name = std::get<std::string_view>(attr.attr_value);
1308
0
            }
1309
0
            break;
1310
0
        }
1311
0
        return true;
1312
0
    });
1313
0
    return name;
1314
0
}
1315
1316
bool Dwarf::findAddress(uintptr_t address, LocationInfo& locationInfo, LocationInfoMode mode,
1317
5.12k
                        std::vector<SymbolizedFrame>& inline_frames) const {
1318
5.12k
    locationInfo = LocationInfo();
1319
1320
5.12k
    if (mode == LocationInfoMode::DISABLED) {
1321
4.56k
        return false;
1322
4.56k
    }
1323
1324
562
    if (!elf_) { // No file.
1325
29
        return false;
1326
29
    }
1327
1328
533
    if (!aranges_.empty()) {
1329
        // Fast path: find the right .debug_info entry by looking up the
1330
        // address in .debug_aranges.
1331
533
        uint64_t offset = 0;
1332
533
        if (findDebugInfoOffset(address, aranges_, offset)) {
1333
            // Read compilation unit header from .debug_info
1334
261
            auto unit = getCompilationUnit(offset);
1335
261
            if (unit.unit_type != DW_UT_compile && unit.unit_type != DW_UT_skeleton) {
1336
0
                return false;
1337
0
            }
1338
261
            findLocation(address, mode, unit, locationInfo, inline_frames);
1339
261
            return locationInfo.has_file_and_line;
1340
272
        } else if (mode == LocationInfoMode::FAST) {
1341
            // NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries
1342
            // in .debug_aranges for some functions, but always generates
1343
            // .debug_info entries.  Scanning .debug_info is slow, so fall back to
1344
            // it only if such behavior is requested via LocationInfoMode.
1345
272
            return false;
1346
272
        } else {
1347
0
            SAFE_CHECK(mode == LocationInfoMode::FULL || mode == LocationInfoMode::FULL_WITH_INLINE,
1348
0
                       "unexpected mode");
1349
            // Fall back to the linear scan.
1350
0
        }
1351
533
    }
1352
1353
    // Slow path (linear scan): Iterate over all .debug_info entries
1354
    // and look for the address in each compilation unit.
1355
0
    uint64_t offset = 0;
1356
0
    while (offset < info_.size() && !locationInfo.has_file_and_line) {
1357
0
        auto unit = getCompilationUnit(offset);
1358
0
        offset += unit.size;
1359
0
        if (unit.unit_type != DW_UT_compile && unit.unit_type != DW_UT_skeleton) {
1360
0
            continue;
1361
0
        }
1362
0
        findLocation(address, mode, unit, locationInfo, inline_frames);
1363
0
    }
1364
1365
0
    return locationInfo.has_file_and_line;
1366
533
}
1367
1368
bool Dwarf::isAddrInRangeList(const CompilationUnit& cu, uint64_t address,
1369
                              std::optional<uint64_t> base_addr, size_t offset,
1370
0
                              uint8_t addr_size) const {
1371
0
    SAFE_CHECK(addr_size == 4 || addr_size == 8, "wrong address size");
1372
0
    if (cu.version <= 4 && !ranges_.empty()) {
1373
0
        const bool is64_bit_addr = addr_size == 8;
1374
0
        std::string_view sp = ranges_;
1375
0
        sp.remove_prefix(offset);
1376
0
        const uint64_t max_addr = is64_bit_addr ? std::numeric_limits<uint64_t>::max()
1377
0
                                                : std::numeric_limits<uint32_t>::max();
1378
0
        while (!sp.empty()) {
1379
0
            uint64_t begin = readOffset(sp, is64_bit_addr);
1380
0
            uint64_t end = readOffset(sp, is64_bit_addr);
1381
            // The range list entry is a base address selection entry.
1382
0
            if (begin == max_addr) {
1383
0
                base_addr = end;
1384
0
                continue;
1385
0
            }
1386
            // The range list entry is an end of list entry.
1387
0
            if (begin == 0 && end == 0) {
1388
0
                break;
1389
0
            }
1390
1391
            // Check if the given address falls in the range list entry.
1392
            // 2.17.3 Non-Contiguous Address Ranges
1393
            // The applicable base address of a range list entry is determined by the
1394
            // closest preceding base address selection entry (see below) in the same
1395
            // range list. If there is no such selection entry, then the applicable
1396
            // base address defaults to the base address of the compilation unit.
1397
0
            if (base_addr && address >= begin + *base_addr && address < end + *base_addr) {
1398
0
                return true;
1399
0
            }
1400
0
        }
1401
0
    }
1402
1403
0
    if (cu.version == 5 && !rnglists_.empty() && cu.addr_base.has_value()) {
1404
0
        auto rnglists = rnglists_;
1405
0
        rnglists.remove_prefix(offset);
1406
1407
0
        while (!rnglists.empty()) {
1408
0
            auto kind = read<uint8_t>(rnglists);
1409
0
            switch (kind) {
1410
0
            case DW_RLE_end_of_list:
1411
0
                return false;
1412
0
            case DW_RLE_base_addressx: {
1413
0
                auto index = readULEB(rnglists);
1414
0
                auto sp = addr_.substr(*cu.addr_base + index * sizeof(uint64_t));
1415
0
                base_addr = read<uint64_t>(sp);
1416
0
            } break;
1417
1418
0
            case DW_RLE_startx_endx: {
1419
0
                auto index_start = readULEB(rnglists);
1420
0
                auto index_end = readULEB(rnglists);
1421
0
                auto sp_start = addr_.substr(*cu.addr_base + index_start * sizeof(uint64_t));
1422
0
                auto start = read<uint64_t>(sp_start);
1423
1424
0
                auto sp_end = addr_.substr(*cu.addr_base + index_end * sizeof(uint64_t));
1425
0
                auto end = read<uint64_t>(sp_end);
1426
0
                if (address >= start && address < end) {
1427
0
                    return true;
1428
0
                }
1429
0
            } break;
1430
1431
0
            case DW_RLE_startx_length: {
1432
0
                auto index_start = readULEB(rnglists);
1433
0
                auto length = readULEB(rnglists);
1434
0
                auto sp_start = addr_.substr(*cu.addr_base + index_start * sizeof(uint64_t));
1435
0
                auto start = read<uint64_t>(sp_start);
1436
1437
0
                auto sp_end = addr_.substr(*cu.addr_base + index_start * sizeof(uint64_t) + length);
1438
0
                auto end = read<uint64_t>(sp_end);
1439
0
                if (start != end && address >= start && address < end) {
1440
0
                    return true;
1441
0
                }
1442
0
            } break;
1443
1444
0
            case DW_RLE_offset_pair: {
1445
0
                auto offset_start = readULEB(rnglists);
1446
0
                auto offset_end = readULEB(rnglists);
1447
0
                if (base_addr && address >= (*base_addr + offset_start) &&
1448
0
                    address < (*base_addr + offset_end)) {
1449
0
                    return true;
1450
0
                }
1451
0
            } break;
1452
1453
0
            case DW_RLE_base_address:
1454
0
                base_addr = read<uint64_t>(rnglists);
1455
0
                break;
1456
1457
0
            case DW_RLE_start_end: {
1458
0
                uint64_t start = read<uint64_t>(rnglists);
1459
0
                uint64_t end = read<uint64_t>(rnglists);
1460
0
                if (address >= start && address < end) {
1461
0
                    return true;
1462
0
                }
1463
0
            } break;
1464
1465
0
            case DW_RLE_start_length: {
1466
0
                uint64_t start = read<uint64_t>(rnglists);
1467
0
                uint64_t end = start + readULEB(rnglists);
1468
0
                if (address >= start && address < end) {
1469
0
                    return true;
1470
0
                }
1471
0
            } break;
1472
1473
0
            default:
1474
0
                SAFE_CHECK(false, "Unexpected debug_rnglists entry kind");
1475
0
            }
1476
0
        }
1477
0
    }
1478
0
    return false;
1479
0
}
1480
1481
Dwarf::LineNumberVM::LineNumberVM(std::string_view data, std::string_view compilationDirectory,
1482
                                  std::string_view debugStr, std::string_view debugLineStr)
1483
261
        : compilationDirectory_(compilationDirectory),
1484
261
          debugStr_(debugStr),
1485
261
          debugLineStr_(debugLineStr) {
1486
261
    Section section(data);
1487
261
    SAFE_CHECK(section.next(data_), "invalid line number VM");
1488
261
    is64Bit_ = section.is64Bit();
1489
261
    init();
1490
261
    reset();
1491
261
}
1492
1493
91.8k
void Dwarf::LineNumberVM::reset() {
1494
91.8k
    address_ = 0;
1495
91.8k
    file_ = 1;
1496
91.8k
    line_ = 1;
1497
91.8k
    column_ = 0;
1498
91.8k
    isStmt_ = defaultIsStmt_;
1499
91.8k
    basicBlock_ = false;
1500
91.8k
    endSequence_ = false;
1501
91.8k
    prologueEnd_ = false;
1502
91.8k
    epilogueBegin_ = false;
1503
91.8k
    isa_ = 0;
1504
91.8k
    discriminator_ = 0;
1505
91.8k
}
1506
1507
struct LineNumberAttribute {
1508
    uint64_t content_type_code;
1509
    uint64_t form_code;
1510
    std::variant<uint64_t, std::string_view> attr_value;
1511
};
1512
1513
LineNumberAttribute readLineNumberAttribute(bool is64_bit, std::string_view& format,
1514
                                            std::string_view& entries, std::string_view debugStr,
1515
240k
                                            std::string_view debugLineStr) {
1516
240k
    uint64_t content_type_code = readULEB(format);
1517
240k
    uint64_t form_code = readULEB(format);
1518
240k
    std::variant<uint64_t, std::string_view> attr_value;
1519
1520
240k
    switch (content_type_code) {
1521
127k
    case DW_LNCT_path: {
1522
127k
        switch (form_code) {
1523
0
        case DW_FORM_string:
1524
0
            attr_value = readNullTerminated(entries);
1525
0
            break;
1526
127k
        case DW_FORM_line_strp: {
1527
127k
            auto off = readOffset(entries, is64_bit);
1528
127k
            attr_value = getStringFromStringSection(debugLineStr, off);
1529
127k
        } break;
1530
0
        case DW_FORM_strp:
1531
0
            attr_value = getStringFromStringSection(debugStr, readOffset(entries, is64_bit));
1532
0
            break;
1533
0
        case DW_FORM_strp_sup:
1534
0
            SAFE_CHECK(false, "Unexpected DW_FORM_strp_sup");
1535
0
            break;
1536
0
        default:
1537
0
            SAFE_CHECK(false, "Unexpected form for DW_LNCT_path");
1538
0
            break;
1539
127k
        }
1540
127k
    } break;
1541
1542
127k
    case DW_LNCT_directory_index: {
1543
113k
        switch (form_code) {
1544
0
        case DW_FORM_data1:
1545
0
            attr_value = read<uint8_t>(entries);
1546
0
            break;
1547
0
        case DW_FORM_data2:
1548
0
            attr_value = read<uint16_t>(entries);
1549
0
            break;
1550
113k
        case DW_FORM_udata:
1551
113k
            attr_value = readULEB(entries);
1552
113k
            break;
1553
0
        default:
1554
0
            SAFE_CHECK(false, "Unexpected form for DW_LNCT_directory_index");
1555
0
            break;
1556
113k
        }
1557
113k
    } break;
1558
1559
113k
    case DW_LNCT_timestamp: {
1560
0
        switch (form_code) {
1561
0
        case DW_FORM_udata:
1562
0
            attr_value = readULEB(entries);
1563
0
            break;
1564
0
        case DW_FORM_data4:
1565
0
            attr_value = read<uint32_t>(entries);
1566
0
            break;
1567
0
        case DW_FORM_data8:
1568
0
            attr_value = read<uint64_t>(entries);
1569
0
            break;
1570
0
        case DW_FORM_block:
1571
0
            attr_value = readBytes(entries, readULEB(entries));
1572
0
            break;
1573
0
        default:
1574
0
            SAFE_CHECK(false, "Unexpected form for DW_LNCT_timestamp");
1575
0
        }
1576
0
    } break;
1577
1578
0
    case DW_LNCT_size: {
1579
0
        switch (form_code) {
1580
0
        case DW_FORM_udata:
1581
0
            attr_value = readULEB(entries);
1582
0
            break;
1583
0
        case DW_FORM_data1:
1584
0
            attr_value = read<uint8_t>(entries);
1585
0
            break;
1586
0
        case DW_FORM_data2:
1587
0
            attr_value = read<uint16_t>(entries);
1588
0
            break;
1589
0
        case DW_FORM_data4:
1590
0
            attr_value = read<uint32_t>(entries);
1591
0
            break;
1592
0
        case DW_FORM_data8:
1593
0
            attr_value = read<uint64_t>(entries);
1594
0
            break;
1595
0
        default:
1596
0
            SAFE_CHECK(false, "Unexpected form for DW_LNCT_size");
1597
0
            break;
1598
0
        }
1599
0
    } break;
1600
1601
0
    case DW_LNCT_MD5: {
1602
0
        switch (form_code) {
1603
0
        case DW_FORM_data16:
1604
0
            attr_value = readBytes(entries, 16);
1605
0
            break;
1606
0
        default:
1607
0
            SAFE_CHECK(false, "Unexpected form for DW_LNCT_MD5");
1608
0
            break;
1609
0
        }
1610
0
    } break;
1611
1612
0
    default:
1613
        // TODO: skip over vendor data as specified by the form instead.
1614
0
        SAFE_CHECK(false, "Unexpected vendor content type code");
1615
0
        break;
1616
240k
    }
1617
240k
    return {
1618
240k
            .content_type_code = content_type_code,
1619
240k
            .form_code = form_code,
1620
240k
            .attr_value = attr_value,
1621
240k
    };
1622
240k
}
1623
1624
261
void Dwarf::LineNumberVM::init() {
1625
261
    version_ = read<uint16_t>(data_);
1626
261
    SAFE_CHECK(version_ >= 2 && version_ <= 5, "invalid version in line number VM: {}", version_);
1627
261
    if (version_ == 5) {
1628
261
        auto address_size = read<uint8_t>(data_);
1629
261
        SAFE_CHECK(address_size == sizeof(uintptr_t), "Unexpected Line Number Table address_size");
1630
261
        auto segment_selector_size = read<uint8_t>(data_);
1631
261
        SAFE_CHECK(segment_selector_size == 0, "Segments not supported");
1632
261
    }
1633
261
    uint64_t header_length = readOffset(data_, is64Bit_);
1634
261
    SAFE_CHECK(header_length <= data_.size(), "invalid line number VM header length");
1635
261
    std::string_view header(data_.data(), header_length);
1636
261
    data_ = std::string_view(header.end(), data_.end() - header.end());
1637
1638
261
    minLength_ = read<uint8_t>(header);
1639
261
    if (version_ >= 4) { // Version 2 and 3 records don't have this
1640
261
        uint8_t max_ops_per_instruction = read<uint8_t>(header);
1641
261
        SAFE_CHECK(max_ops_per_instruction == 1, "VLIW not supported");
1642
261
    }
1643
261
    defaultIsStmt_ = read<uint8_t>(header);
1644
261
    lineBase_ = read<int8_t>(header); // yes, signed
1645
261
    lineRange_ = read<uint8_t>(header);
1646
261
    opcodeBase_ = read<uint8_t>(header);
1647
261
    SAFE_CHECK(opcodeBase_ != 0, "invalid opcode base");
1648
261
    standardOpcodeLengths_ = reinterpret_cast<const uint8_t*>(header.data());
1649
261
    header.remove_prefix(opcodeBase_ - 1);
1650
1651
261
    if (version_ <= 4) {
1652
        // We don't want to use heap, so we don't keep an unbounded amount of state.
1653
        // We'll just skip over include directories and file names here, and
1654
        // we'll loop again when we actually need to retrieve one.
1655
0
        std::string_view sp;
1656
0
        const char* tmp = header.data();
1657
0
        v4_.includeDirectoryCount = 0;
1658
0
        while (!(sp = readNullTerminated(header)).empty()) {
1659
0
            ++v4_.includeDirectoryCount;
1660
0
        }
1661
0
        v4_.includeDirectories = {tmp, header.data()};
1662
1663
0
        tmp = header.data();
1664
0
        FileName fn;
1665
0
        v4_.fileNameCount = 0;
1666
0
        while (readFileName(header, fn)) {
1667
0
            ++v4_.fileNameCount;
1668
0
        }
1669
0
        v4_.fileNames = {tmp, header.data()};
1670
261
    } else if (version_ == 5) {
1671
261
        v5_.directoryEntryFormatCount = read<uint8_t>(header);
1672
261
        const char* tmp = header.data();
1673
522
        for (uint8_t i = 0; i < v5_.directoryEntryFormatCount; i++) {
1674
            // A sequence of directory entry format descriptions. Each description
1675
            // consists of a pair of ULEB128 values:
1676
261
            readULEB(header); // A content type code
1677
261
            readULEB(header); // A form code using the attribute form codes
1678
261
        }
1679
261
        v5_.directoryEntryFormat = {tmp, header.data()};
1680
261
        v5_.directoriesCount = readULEB(header);
1681
261
        tmp = header.data();
1682
12.6k
        for (uint64_t i = 0; i < v5_.directoriesCount; i++) {
1683
12.3k
            std::string_view format = v5_.directoryEntryFormat;
1684
24.7k
            for (uint8_t f = 0; f < v5_.directoryEntryFormatCount; f++) {
1685
12.3k
                readLineNumberAttribute(is64Bit_, format, header, debugStr_, debugLineStr_);
1686
12.3k
            }
1687
12.3k
        }
1688
261
        v5_.directories = {tmp, header.data()};
1689
1690
261
        v5_.fileNameEntryFormatCount = read<uint8_t>(header);
1691
261
        tmp = header.data();
1692
783
        for (uint8_t i = 0; i < v5_.fileNameEntryFormatCount; i++) {
1693
            // A sequence of file entry format descriptions. Each description
1694
            // consists of a pair of ULEB128 values:
1695
522
            readULEB(header); // A content type code
1696
522
            readULEB(header); // A form code using the attribute form codes
1697
522
        }
1698
261
        v5_.fileNameEntryFormat = {tmp, header.data()};
1699
261
        v5_.fileNamesCount = readULEB(header);
1700
261
        tmp = header.data();
1701
57.1k
        for (uint64_t i = 0; i < v5_.fileNamesCount; i++) {
1702
56.8k
            std::string_view format = v5_.fileNameEntryFormat;
1703
170k
            for (uint8_t f = 0; f < v5_.fileNameEntryFormatCount; f++) {
1704
113k
                readLineNumberAttribute(is64Bit_, format, header, debugStr_, debugLineStr_);
1705
113k
            }
1706
56.8k
        }
1707
261
        v5_.fileNames = {tmp, header.data()};
1708
261
    }
1709
261
}
1710
1711
2.72M
bool Dwarf::LineNumberVM::next(std::string_view& program) {
1712
2.72M
    Dwarf::LineNumberVM::StepResult ret;
1713
7.67M
    do {
1714
7.67M
        ret = step(program);
1715
7.67M
    } while (ret == CONTINUE);
1716
1717
2.72M
    return (ret == COMMIT);
1718
2.72M
}
1719
1720
261
Dwarf::LineNumberVM::FileName Dwarf::LineNumberVM::getFileName(uint64_t index) const {
1721
261
    if (version_ <= 4) {
1722
0
        SAFE_CHECK(index != 0, "invalid file index 0");
1723
0
        FileName fn;
1724
0
        if (index <= v4_.fileNameCount) {
1725
0
            std::string_view file_names = v4_.fileNames;
1726
0
            for (; index; --index) {
1727
0
                if (!readFileName(file_names, fn)) {
1728
0
                    abort();
1729
0
                }
1730
0
            }
1731
0
            return fn;
1732
0
        }
1733
1734
0
        index -= v4_.fileNameCount;
1735
1736
0
        std::string_view program = data_;
1737
0
        for (; index; --index) {
1738
0
            SAFE_CHECK(nextDefineFile(program, fn), "invalid file index");
1739
0
        }
1740
1741
0
        return fn;
1742
261
    } else {
1743
261
        FileName fn;
1744
261
        SAFE_CHECK(index < v5_.fileNamesCount, "invalid file index");
1745
261
        std::string_view file_names = v5_.fileNames;
1746
57.1k
        for (uint64_t i = 0; i < v5_.fileNamesCount; i++) {
1747
56.8k
            std::string_view format = v5_.fileNameEntryFormat;
1748
170k
            for (uint8_t f = 0; f < v5_.fileNameEntryFormatCount; f++) {
1749
113k
                auto attr = readLineNumberAttribute(is64Bit_, format, file_names, debugStr_,
1750
113k
                                                    debugLineStr_);
1751
113k
                if (i == index) {
1752
522
                    switch (attr.content_type_code) {
1753
261
                    case DW_LNCT_path:
1754
261
                        fn.relativeName = std::get<std::string_view>(attr.attr_value);
1755
261
                        break;
1756
261
                    case DW_LNCT_directory_index:
1757
261
                        fn.directoryIndex = std::get<uint64_t>(attr.attr_value);
1758
261
                        break;
1759
522
                    }
1760
522
                }
1761
113k
            }
1762
56.8k
        }
1763
261
        return fn;
1764
261
    }
1765
261
}
1766
1767
261
std::string_view Dwarf::LineNumberVM::getIncludeDirectory(uint64_t index) const {
1768
261
    if (version_ <= 4) {
1769
0
        if (index == 0) {
1770
            // In DWARF <= 4 the current directory is not represented in the
1771
            // directories field and a directory index of 0 implicitly referred to
1772
            // that directory as found in the DW_AT_comp_dir attribute of the
1773
            // compilation unit debugging information entry.
1774
0
            return {};
1775
0
        }
1776
1777
0
        SAFE_CHECK(index <= v4_.includeDirectoryCount, "invalid include directory");
1778
1779
0
        std::string_view include_directories = v4_.includeDirectories;
1780
0
        std::string_view dir;
1781
0
        for (; index; --index) {
1782
0
            dir = readNullTerminated(include_directories);
1783
0
            if (dir.empty()) {
1784
0
                abort(); // BUG
1785
0
            }
1786
0
        }
1787
1788
0
        return dir;
1789
261
    } else {
1790
261
        SAFE_CHECK(index < v5_.directoriesCount, "invalid file index");
1791
261
        std::string_view directories = v5_.directories;
1792
1.12k
        for (uint64_t i = 0; i < v5_.directoriesCount; i++) {
1793
1.12k
            std::string_view format = v5_.directoryEntryFormat;
1794
1.99k
            for (uint8_t f = 0; f < v5_.directoryEntryFormatCount; f++) {
1795
1.12k
                auto attr = readLineNumberAttribute(is64Bit_, format, directories, debugStr_,
1796
1.12k
                                                    debugLineStr_);
1797
1.12k
                if (i == index && attr.content_type_code == DW_LNCT_path) {
1798
261
                    return std::get<std::string_view>(attr.attr_value);
1799
261
                }
1800
1.12k
            }
1801
1.12k
        }
1802
        // This could only happen if DWARF5's directory_entry_format doesn't contain
1803
        // a DW_LNCT_path. Highly unlikely, but we shouldn't crash.
1804
0
        return std::string_view("<directory not found>");
1805
261
    }
1806
261
}
1807
1808
0
bool Dwarf::LineNumberVM::readFileName(std::string_view& program, FileName& fn) {
1809
0
    fn.relativeName = readNullTerminated(program);
1810
0
    if (fn.relativeName.empty()) {
1811
0
        return false;
1812
0
    }
1813
0
    fn.directoryIndex = readULEB(program);
1814
    // Skip over file size and last modified time
1815
0
    readULEB(program);
1816
0
    readULEB(program);
1817
0
    return true;
1818
0
}
1819
1820
0
bool Dwarf::LineNumberVM::nextDefineFile(std::string_view& program, FileName& fn) const {
1821
0
    while (!program.empty()) {
1822
0
        auto opcode = read<uint8_t>(program);
1823
1824
0
        if (opcode >= opcodeBase_) { // special opcode
1825
0
            continue;
1826
0
        }
1827
1828
0
        if (opcode != 0) { // standard opcode
1829
            // Skip, slurp the appropriate number of LEB arguments
1830
0
            uint8_t arg_count = standardOpcodeLengths_[opcode - 1];
1831
0
            while (arg_count--) {
1832
0
                readULEB(program);
1833
0
            }
1834
0
            continue;
1835
0
        }
1836
1837
        // Extended opcode
1838
0
        auto length = readULEB(program);
1839
        // the opcode itself should be included in the length, so length >= 1
1840
0
        SAFE_CHECK(length != 0, "invalid extended opcode length");
1841
0
        read<uint8_t>(program); // extended opcode
1842
0
        --length;
1843
1844
0
        if (opcode == DW_LNE_define_file) {
1845
0
            SAFE_CHECK(version_ < 5, "DW_LNE_define_file deprecated in DWARF5");
1846
0
            SAFE_CHECK(readFileName(program, fn), "invalid empty file in DW_LNE_define_file");
1847
0
            return true;
1848
0
        }
1849
1850
0
        program.remove_prefix(length);
1851
0
    }
1852
1853
0
    return false;
1854
0
}
1855
1856
7.67M
Dwarf::LineNumberVM::StepResult Dwarf::LineNumberVM::step(std::string_view& program) {
1857
7.67M
    auto opcode = read<uint8_t>(program);
1858
1859
7.67M
    if (opcode >= opcodeBase_) { // special opcode
1860
2.31M
        uint8_t adjusted_opcode = opcode - opcodeBase_;
1861
2.31M
        uint8_t op_advance = adjusted_opcode / lineRange_;
1862
1863
2.31M
        address_ += minLength_ * op_advance;
1864
2.31M
        line_ += lineBase_ + adjusted_opcode % lineRange_;
1865
1866
2.31M
        basicBlock_ = false;
1867
2.31M
        prologueEnd_ = false;
1868
2.31M
        epilogueBegin_ = false;
1869
2.31M
        discriminator_ = 0;
1870
2.31M
        return COMMIT;
1871
2.31M
    }
1872
1873
5.36M
    if (opcode != 0) { // standard opcode
1874
        // Only interpret opcodes that are recognized by the version we're parsing;
1875
        // the others are vendor extensions and we should ignore them.
1876
5.17M
        switch (opcode) {
1877
324k
        case DW_LNS_copy:
1878
324k
            basicBlock_ = false;
1879
324k
            prologueEnd_ = false;
1880
324k
            epilogueBegin_ = false;
1881
324k
            discriminator_ = 0;
1882
324k
            return COMMIT;
1883
416k
        case DW_LNS_advance_pc:
1884
416k
            address_ += minLength_ * readULEB(program);
1885
416k
            return CONTINUE;
1886
1.84M
        case DW_LNS_advance_line:
1887
1.84M
            line_ += readSLEB(program);
1888
1.84M
            return CONTINUE;
1889
143k
        case DW_LNS_set_file:
1890
143k
            file_ = readULEB(program);
1891
143k
            return CONTINUE;
1892
1.01M
        case DW_LNS_set_column:
1893
1.01M
            column_ = readULEB(program);
1894
1.01M
            return CONTINUE;
1895
837k
        case DW_LNS_negate_stmt:
1896
837k
            isStmt_ = !isStmt_;
1897
837k
            return CONTINUE;
1898
0
        case DW_LNS_set_basic_block:
1899
0
            basicBlock_ = true;
1900
0
            return CONTINUE;
1901
411k
        case DW_LNS_const_add_pc:
1902
411k
            address_ += minLength_ * ((255 - opcodeBase_) / lineRange_);
1903
411k
            return CONTINUE;
1904
0
        case DW_LNS_fixed_advance_pc:
1905
0
            address_ += read<uint16_t>(program);
1906
0
            return CONTINUE;
1907
95.4k
        case DW_LNS_set_prologue_end:
1908
95.4k
            if (version_ == 2) {
1909
0
                break; // not supported in version 2
1910
0
            }
1911
95.4k
            prologueEnd_ = true;
1912
95.4k
            return CONTINUE;
1913
94.0k
        case DW_LNS_set_epilogue_begin:
1914
94.0k
            if (version_ == 2) {
1915
0
                break; // not supported in version 2
1916
0
            }
1917
94.0k
            epilogueBegin_ = true;
1918
94.0k
            return CONTINUE;
1919
0
        case DW_LNS_set_isa:
1920
0
            if (version_ == 2) {
1921
0
                break; // not supported in version 2
1922
0
            }
1923
0
            isa_ = readULEB(program);
1924
0
            return CONTINUE;
1925
5.17M
        }
1926
1927
        // Unrecognized standard opcode, slurp the appropriate number of LEB
1928
        // arguments.
1929
0
        uint8_t arg_count = standardOpcodeLengths_[opcode - 1];
1930
0
        while (arg_count--) {
1931
0
            readULEB(program);
1932
0
        }
1933
0
        return CONTINUE;
1934
5.17M
    }
1935
1936
    // Extended opcode
1937
182k
    auto length = readULEB(program);
1938
    // the opcode itself should be included in the length, so length >= 1
1939
182k
    SAFE_CHECK(length != 0, "invalid extended opcode length");
1940
182k
    auto extended_opcode = read<uint8_t>(program);
1941
182k
    --length;
1942
1943
182k
    switch (extended_opcode) {
1944
91.3k
    case DW_LNE_end_sequence:
1945
91.3k
        return END;
1946
91.5k
    case DW_LNE_set_address:
1947
91.5k
        address_ = read<uintptr_t>(program);
1948
91.5k
        return CONTINUE;
1949
0
    case DW_LNE_define_file:
1950
0
        SAFE_CHECK(version_ < 5, "DW_LNE_define_file deprecated in DWARF5");
1951
        // We can't process DW_LNE_define_file here, as it would require us to
1952
        // use unbounded amounts of state (ie. use the heap).  We'll do a second
1953
        // pass (using nextDefineFile()) if necessary.
1954
0
        break;
1955
0
    case DW_LNE_set_discriminator:
1956
0
        discriminator_ = readULEB(program);
1957
0
        return CONTINUE;
1958
182k
    }
1959
1960
    // Unrecognized extended opcode
1961
0
    program.remove_prefix(length);
1962
0
    return CONTINUE;
1963
182k
}
1964
1965
261
Dwarf::Path Dwarf::LineNumberVM::getFullFileName(uint64_t index) const {
1966
261
    auto fn = getFileName(index);
1967
    // DWARF <= 4: the current dir is not represented in the CU's Line Number
1968
    // Program Header and relies on the CU's DW_AT_comp_dir.
1969
    // DWARF 5: the current directory is explicitly present.
1970
261
    const std::string_view base_dir = version_ == 5 ? "" : compilationDirectory_;
1971
261
    return Path(base_dir, getIncludeDirectory(fn.directoryIndex), fn.relativeName);
1972
261
}
1973
1974
261
bool Dwarf::LineNumberVM::findAddress(uintptr_t target, Path& file, uint64_t& line) {
1975
261
    std::string_view program = data_;
1976
1977
    // Within each sequence of instructions, the address may only increase.
1978
    // Unfortunately, within the same compilation unit, sequences may appear
1979
    // in any order.  So any sequence is a candidate if it starts at an address
1980
    // <= the target address, and we know we've found the target address if
1981
    // a candidate crosses the target address.
1982
261
    enum State {
1983
261
        START,
1984
261
        LOW_SEQ, // candidate
1985
261
        HIGH_SEQ
1986
261
    };
1987
261
    State state = START;
1988
261
    reset();
1989
1990
261
    uint64_t prev_file = 0;
1991
261
    uint64_t prev_line = 0;
1992
2.72M
    while (!program.empty()) {
1993
2.72M
        bool seq_end = !next(program);
1994
1995
2.72M
        if (state == START) {
1996
91.5k
            if (!seq_end) {
1997
91.5k
                state = address_ <= target ? LOW_SEQ : HIGH_SEQ;
1998
91.5k
            }
1999
91.5k
        }
2000
2001
2.72M
        if (state == LOW_SEQ) {
2002
2.57M
            if (address_ > target) {
2003
                // Found it!  Note that ">" is indeed correct (not ">="), as each
2004
                // sequence is guaranteed to have one entry past-the-end (emitted by
2005
                // DW_LNE_end_sequence)
2006
                //
2007
                // NOTE: In DWARF <= 4 the file register is non-zero.
2008
                //   See DWARF 4: 6.2.4 The Line Number Program Header
2009
                //   "The line number program assigns numbers to each of the file
2010
                //   entries in order, beginning with 1, and uses those numbers instead
2011
                //   of file names in the file register."
2012
                // DWARF 5 has a different include directory/file header and 0 is valid.
2013
261
                if (version_ <= 4 && prev_file == 0) {
2014
0
                    return false;
2015
0
                }
2016
261
                file = getFullFileName(prev_file);
2017
261
                line = prev_line;
2018
261
                return true;
2019
261
            }
2020
2.57M
            prev_file = file_;
2021
2.57M
            prev_line = line_;
2022
2.57M
        }
2023
2024
2.72M
        if (seq_end) {
2025
91.2k
            state = START;
2026
91.2k
            reset();
2027
91.2k
        }
2028
2.72M
    }
2029
2030
0
    return false;
2031
261
}
2032
2033
#include "common/compile_check_avoid_end.h"
2034
} // namespace doris
2035
2036
#endif