diff options
5 files changed, 163 insertions, 45 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b8575d13d45..fc8fe30101c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -198,15 +198,23 @@ GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,    return std::move(rel_path);  } -static FileSpecList ParseSupportFilesFromPrologue( -    const lldb::ModuleSP &module, -    const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, -    llvm::StringRef compile_dir = {}, FileSpec first_file = {}) { +static FileSpecList +ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, +                              const llvm::DWARFDebugLine::Prologue &prologue, +                              FileSpec::Style style, +                              llvm::StringRef compile_dir = {}) {    FileSpecList support_files; -  support_files.Append(first_file); +  size_t first_file = 0; +  if (prologue.getVersion() <= 4) { +    // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure +    // support file list indices match those we get from the debug info and line +    // tables. +    support_files.Append(FileSpec()); +    first_file = 1; +  }    const size_t number_of_files = prologue.FileNames.size(); -  for (size_t idx = 1; idx <= number_of_files; ++idx) { +  for (size_t idx = first_file; idx <= number_of_files; ++idx) {      std::string remapped_file;      if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))        if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file)) @@ -1046,8 +1054,7 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {    comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(        comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(), -      dwarf_cu->GetCompilationDirectory().GetCString(), -      comp_unit.GetPrimaryFile())); +      dwarf_cu->GetCompilationDirectory().GetCString()));    return true;  } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index f0308e23c9d..22d1b08ea9e 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1110,9 +1110,7 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {        // LLDB wants the index of the file in the list of support files.        auto fn_iter = llvm::find(cci->m_file_list, *efn);        lldbassert(fn_iter != cci->m_file_list.end()); -      // LLDB support file indices are 1-based. -      uint32_t file_index = -          1 + std::distance(cci->m_file_list.begin(), fn_iter); +      uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter);        std::unique_ptr<LineSequence> sequence(            line_table->CreateLineSequenceContainer()); @@ -1155,14 +1153,6 @@ bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,      FileSpec spec(f, style);      support_files.Append(spec);    } - -  llvm::SmallString<64> main_source_file = -      m_index->compilands().GetMainSourceFile(*cci); -  FileSpec::Style style = main_source_file.startswith("/") -                              ? FileSpec::Style::posix -                              : FileSpec::Style::windows; -  FileSpec spec(main_source_file, style); -  support_files.Insert(0, spec);    return true;  } diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index dcbefdcbb6f..b3e06fdd1a5 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -371,10 +371,6 @@ bool SymbolFilePDB::ParseSupportFiles(      support_files.AppendIfUnique(spec);    } -  // LLDB uses the DWARF-like file numeration (one based), -  // the zeroth file is the compile unit itself -  support_files.Insert(0, comp_unit.GetPrimaryFile()); -    return true;  } @@ -1881,9 +1877,7 @@ void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(    if (!source_files)      return; -  // LLDB uses the DWARF-like file numeration (one based) -  int index = 1; - +  int index = 0;    while (auto file = source_files->getNext()) {      uint32_t source_id = file->getUniqueId();      index_map[source_id] = index++; diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index 98cf675fb37..b05036e27fc 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -207,30 +207,28 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) {    return m_variables;  } +std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, const FileSpec &file) { +  std::vector<uint32_t> result; +  uint32_t idx = -1; +  while ((idx = files.FindFileIndex(idx + 1, file, /*full=*/true)) != +         UINT32_MAX) +    result.push_back(idx); +  return result; +} +  uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,                                      const FileSpec *file_spec_ptr, bool exact,                                      LineEntry *line_entry_ptr) { -  uint32_t file_idx = 0; +  if (!file_spec_ptr) +    file_spec_ptr = &GetPrimaryFile(); +  std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), *file_spec_ptr); +  if (file_indexes.empty()) +    return UINT32_MAX; -  if (file_spec_ptr) { -    file_idx = GetSupportFiles().FindFileIndex(1, *file_spec_ptr, true); -    if (file_idx == UINT32_MAX) -      return UINT32_MAX; -  } else { -    // All the line table entries actually point to the version of the Compile -    // Unit that is in the support files (the one at 0 was artificially added.) -    // So prefer the one further on in the support files if it exists... -    const FileSpecList &support_files = GetSupportFiles(); -    const bool full = true; -    file_idx = support_files.FindFileIndex( -        1, support_files.GetFileSpecAtIndex(0), full); -    if (file_idx == UINT32_MAX) -      file_idx = 0; -  }    LineTable *line_table = GetLineTable();    if (line_table) -    return line_table->FindLineEntryIndexByFileIndex(start_idx, file_idx, line, -                                                     exact, line_entry_ptr); +    return line_table->FindLineEntryIndexByFileIndex( +        start_idx, file_indexes, line, exact, line_entry_ptr);    return UINT32_MAX;  } @@ -252,7 +250,7 @@ void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,      return;    uint32_t file_idx = -      GetSupportFiles().FindFileIndex(1, file_spec, true); +      GetSupportFiles().FindFileIndex(0, file_spec, true);    while (file_idx != UINT32_MAX) {      file_indexes.push_back(file_idx);      file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true); diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwarf5-debug_line.s b/lldb/test/Shell/SymbolFile/DWARF/dwarf5-debug_line.s new file mode 100644 index 00000000000..d15f31039bb --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwarf5-debug_line.s @@ -0,0 +1,129 @@ +# Test handling of DWARF5 line tables. In particular, test that we handle files +# which are present in the line table more than once. + +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -o %t -triple x86_64-pc-linux %s +# RUN: %lldb %t -o "source info -f file0.c" -o "source info -f file1.c" \ +# RUN:   -o "breakpoint set -f file0.c -l 42" \ +# RUN:   -o "breakpoint set -f file0.c -l 47" \ +# RUN:   -o exit | FileCheck %s + +# CHECK-LABEL: source info -f file0.c +# CHECK: [0x0000000000000000-0x0000000000000001): /file0.c:42 +# CHECK-LABEL: source info -f file1.c +# CHECK: [0x0000000000000001-0x0000000000000002): /file1.c:47 +# CHECK-LABEL: breakpoint set -f file0.c -l 42 +# CHECK: Breakpoint 1: {{.*}}`foo, +# CHECK-LABEL: breakpoint set -f file0.c -l 47 +# CHECK: Breakpoint 2: {{.*}}`foo + 2, + +        .text +        .globl  foo +foo: +        nop +        nop +        nop +.Lfoo_end: + +        .section        .debug_abbrev,"",@progbits +        .byte   1                       # Abbreviation Code +        .byte   17                      # DW_TAG_compile_unit +        .byte   0                       # DW_CHILDREN_no +        .byte   37                      # DW_AT_producer +        .byte   8                       # DW_FORM_string +        .byte   19                      # DW_AT_language +        .byte   5                       # DW_FORM_data2 +        .byte   3                       # DW_AT_name +        .byte   8                       # DW_FORM_string +        .byte   16                      # DW_AT_stmt_list +        .byte   23                      # DW_FORM_sec_offset +        .byte   27                      # DW_AT_comp_dir +        .byte   8                       # DW_FORM_string +        .byte   17                      # DW_AT_low_pc +        .byte   1                       # DW_FORM_addr +        .byte   18                      # DW_AT_high_pc +        .byte   6                       # DW_FORM_data4 +        .byte   0                       # EOM(1) +        .byte   0                       # EOM(2) +        .byte   0                       # EOM(3) + +        .section        .debug_info,"",@progbits +.Lcu_begin0: +        .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: +        .short  5                       # DWARF version number +        .byte   1                       # DWARF Unit Type +        .byte   8                       # Address Size (in bytes) +        .long   .debug_abbrev           # Offset Into Abbrev. Section +        .byte   1                       # Abbrev [1] 0xc:0x23 DW_TAG_compile_unit +        .asciz  "Hand-written DWARF"    # DW_AT_producer +        .short  12                      # DW_AT_language +        .asciz  "file0.c"               # DW_AT_name +        .long   .Lline_table_begin      # DW_AT_stmt_list +        .asciz  "/"                     # DW_AT_comp_dir +        .quad   foo                     # DW_AT_low_pc +        .long   .Lfoo_end-foo           # DW_AT_high_pc +.Ldebug_info_end0: + +        .section        .debug_line,"",@progbits +.Lline_table_begin: +        .long .Lline_end-.Lline_start +.Lline_start: +        .short  5                       # DWARF version number +        .byte   8                       # Address Size (in bytes) +        .byte   0                       # Segment Selector Size +        .long   .Lheader_end-.Lheader_start +.Lheader_start: +        .byte   1                       # Minimum Instruction Length +        .byte   1                       # Maximum Operations per Instruction +        .byte   1                       # Default is_stmt +        .byte   0                       # Line Base +        .byte   0                       # Line Range +        .byte   5                       # Opcode Base +        .byte   0, 1, 1, 1              # Standard Opcode Lengths + +        # Directory table format +        .byte   1                       # One element per directory entry +        .byte   1                       # DW_LNCT_path +        .byte   0x08                    # DW_FORM_string + +        # Directory table entries +        .byte   1                       # 1 directory +        .asciz  "/" + +        # File table format +        .byte   2                       # 2 elements per file entry +        .byte   1                       # DW_LNCT_path +        .byte   0x08                    # DW_FORM_string +        .byte   2                       # DW_LNCT_directory_index +        .byte   0x0b                    # DW_FORM_data1 + +        # File table entries +        .byte   3                       # 3 files +        .asciz  "file0.c" +        .byte   0 +        .asciz  "file1.c" +        .byte   0 +        .asciz  "file0.c" +        .byte   0 +.Lheader_end: + +        .byte   4, 0                    # DW_LNS_set_file 0 +        .byte   0, 9, 2                 # DW_LNE_set_address +        .quad   foo +        .byte   3, 41                   # DW_LNS_advance_line 41 +        .byte   1                       # DW_LNS_copy + +        .byte   4, 1                    # DW_LNS_set_file 1 +        .byte   2, 1                    # DW_LNS_advance_pc 1 +        .byte   3, 5                    # DW_LNS_advance_line 5 +        .byte   1                       # DW_LNS_copy + +        .byte   4, 2                    # DW_LNS_set_file 2 +        .byte   2, 1                    # DW_LNS_advance_pc 1 +        .byte   1                       # DW_LNS_copy + +        .byte   2, 1                    # DW_LNS_advance_pc 1 +        .byte   0, 1, 1                 # DW_LNE_end_sequence +.Lline_end:  | 

