@@ -317,6 +317,14 @@ void line_header::read(freader& s, bool needs_byteswap) {
317
317
_include_directories.push_back (cur_directory);
318
318
}
319
319
320
+ // REVIST (fosterbrereton): The reading here isn't entirely accurate. The current code stops the
321
+ // first time an empty name is found, and interprets that as the end of the file names (and thus
322
+ // the `line_header`). However, the spec (as the end of section 6.2.4) states "A compiler may
323
+ // generate a single null byte for the file names field and define file names using the
324
+ // extended opcode DW_LNE_define_file." This loop, then, should iterate through the end of the
325
+ // defined size of `_header_length` instead of using an empty name as a sentry. Any additional
326
+ // null bytes should be interpreted as a placeholder file name description. (Admittedly, I
327
+ // haven't seen one of these in the wild yet.)
320
328
while (true ) {
321
329
file_name cur_file_name;
322
330
cur_file_name._name = s.read_c_string_view ();
@@ -420,7 +428,7 @@ struct dwarf::implementation {
420
428
std::int32_t read_sleb ();
421
429
422
430
void read_abbreviations ();
423
- void read_lines ();
431
+ void read_lines (std:: size_t header_offset );
424
432
const abbrev& find_abbreviation (std::uint32_t code) const ;
425
433
426
434
pool_string read_debug_str (std::size_t offset);
@@ -519,10 +527,10 @@ void dwarf::implementation::read_abbreviations() {
519
527
520
528
/* *************************************************************************************************/
521
529
522
- void dwarf::implementation::read_lines () {
530
+ void dwarf::implementation::read_lines (std:: size_t header_offset ) {
523
531
ZoneScoped;
524
532
525
- temp_seek (_s, _debug_line._offset , [&] {
533
+ temp_seek (_s, _debug_line._offset + header_offset , [&] {
526
534
line_header header;
527
535
header.read (_s, _details._needs_byteswap );
528
536
@@ -538,7 +546,8 @@ void dwarf::implementation::read_lines() {
538
546
}
539
547
}
540
548
541
- // We don't need to process the rest of __debug__line. We're only here for the file table.
549
+ // We don't need to process the rest of this __debug__line subsection.
550
+ // We're only here for the file table.
542
551
});
543
552
}
544
553
@@ -1296,8 +1305,6 @@ bool dwarf::implementation::register_sections_done() {
1296
1305
1297
1306
read_abbreviations ();
1298
1307
1299
- read_lines ();
1300
-
1301
1308
_ready = true ;
1302
1309
1303
1310
return true ;
@@ -1433,6 +1440,21 @@ void dwarf::implementation::process_all_dies() {
1433
1440
1434
1441
continue ;
1435
1442
} else if (die._tag == dw::tag::compile_unit || die._tag == dw::tag::partial_unit) {
1443
+ // Spec (section 3.1.1) says that compilation and partial units may specify which
1444
+ // __debug_line subsection they want to draw their decl_files list from. This also
1445
+ // means we need to clear our current decl_files list (from index 1 to the end)
1446
+ // whenever we do hit either of these two dies. (What's the right action to take
1447
+ // when a unit doesn't have a stmt_list attribute? Where do we get our file names
1448
+ // from? Or is the expectation that the DWARF information won't specify any in that
1449
+ // case?)
1450
+
1451
+ assert (!_decl_files.empty ());
1452
+ _decl_files.erase (std::next (_decl_files.begin ()), _decl_files.end ());
1453
+
1454
+ if (attributes.has_uint (dw::at::stmt_list)) {
1455
+ read_lines (attributes.uint (dw::at::stmt_list));
1456
+ }
1457
+
1436
1458
// REVISIT (fosterbrereton): If the name is a relative path, there may be a
1437
1459
// DW_AT_comp_dir attribute that specifies the path it is relative from.
1438
1460
// Is it worth making this path absolute?
0 commit comments