Browse Source

LibDebug: Move Dwarf::LineProgram into Dwarf::CompilationUnit

Previously, the LineProgram objects were short-lived, and only created
inside DebugInfo::prepare_lines() to create a vector of sorted LineInfo
data.

However, Dwarf::LineProgram also contains other useful data, such as
index-to-string mapping of source directories and filenames.

This commit makes each Dwarf::CompilationUnit own its
Dwarf::LineProgram.
DebugInfo::prepare_lines() then iterates over the compilation units to
prepare its sorted vector of lines.
Itamar 4 years ago
parent
commit
0d89f70b66

+ 3 - 9
Userland/Libraries/LibDebug/DebugInfo.cpp

@@ -78,17 +78,11 @@ void DebugInfo::parse_scopes_impl(const Dwarf::DIE& die)
 
 void DebugInfo::prepare_lines()
 {
-    auto section = elf().lookup_section(".debug_line"sv);
-    if (!section.has_value())
-        return;
-
-    InputMemoryStream stream { section->bytes() };
 
     Vector<Dwarf::LineProgram::LineInfo> all_lines;
-    while (!stream.eof()) {
-        Dwarf::LineProgram program(m_dwarf_info, stream);
-        all_lines.extend(program.lines());
-    }
+    m_dwarf_info.for_each_compilation_unit([&all_lines](const Dwarf::CompilationUnit& unit) {
+        all_lines.extend(unit.line_program().lines());
+    });
 
     HashMap<FlyString, Optional<String>> memoized_full_paths;
     auto compute_full_path = [&](FlyString const& file_path) -> Optional<String> {

+ 2 - 1
Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp

@@ -9,11 +9,12 @@
 
 namespace Debug::Dwarf {
 
-CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader& header)
+CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader& header, NonnullOwnPtr<LineProgram>&& line_program)
     : m_dwarf_info(dwarf_info)
     , m_offset(offset)
     , m_header(header)
     , m_abbreviations(dwarf_info, header.abbrev_offset())
+    , m_line_program(move(line_program))
 {
     VERIFY(header.version() < 5 || header.unit_type() == CompilationUnitType::Full);
 }

+ 6 - 1
Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h

@@ -7,6 +7,8 @@
 #pragma once
 
 #include "AbbreviationsMap.h"
+#include "DIE.h"
+#include "LineProgram.h"
 #include <AK/Noncopyable.h>
 #include <AK/Types.h>
 
@@ -14,13 +16,14 @@ namespace Debug::Dwarf {
 
 class DwarfInfo;
 class DIE;
+class LineProgram;
 
 class CompilationUnit {
     AK_MAKE_NONCOPYABLE(CompilationUnit);
     AK_MAKE_NONMOVABLE(CompilationUnit);
 
 public:
-    CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader&);
+    CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader&, NonnullOwnPtr<LineProgram>&& line_program);
 
     u32 offset() const { return m_offset; }
     u32 size() const { return m_header.length() + sizeof(u32); }
@@ -30,12 +33,14 @@ public:
 
     const DwarfInfo& dwarf_info() const { return m_dwarf_info; }
     const AbbreviationsMap& abbreviations_map() const { return m_abbreviations; }
+    const LineProgram& line_program() const { return *m_line_program; }
 
 private:
     const DwarfInfo& m_dwarf_info;
     u32 m_offset { 0 };
     CompilationUnitHeader m_header;
     AbbreviationsMap m_abbreviations;
+    NonnullOwnPtr<LineProgram> m_line_program;
 };
 
 }

+ 14 - 6
Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp

@@ -16,6 +16,7 @@ DwarfInfo::DwarfInfo(const ELF::Image& elf)
     m_debug_info_data = section_data(".debug_info"sv);
     m_abbreviation_data = section_data(".debug_abbrev"sv);
     m_debug_strings_data = section_data(".debug_str"sv);
+    m_debug_line_data = section_data(".debug_line"sv);
     m_debug_line_strings_data = section_data(".debug_line_str"sv);
 
     populate_compilation_units();
@@ -34,19 +35,26 @@ void DwarfInfo::populate_compilation_units()
     if (!m_debug_info_data.data())
         return;
 
-    InputMemoryStream stream { m_debug_info_data };
-    while (!stream.eof()) {
-        auto unit_offset = stream.offset();
+    InputMemoryStream debug_info_stream { m_debug_info_data };
+    InputMemoryStream line_info_stream { m_debug_line_data };
+
+    while (!debug_info_stream.eof()) {
+        auto unit_offset = debug_info_stream.offset();
         CompilationUnitHeader compilation_unit_header {};
 
-        stream >> compilation_unit_header;
+        debug_info_stream >> compilation_unit_header;
         VERIFY(compilation_unit_header.common.version <= 5);
         VERIFY(compilation_unit_header.address_size() == sizeof(u32));
 
         u32 length_after_header = compilation_unit_header.length() - (compilation_unit_header.header_size() - offsetof(CompilationUnitHeader, common.version));
-        m_compilation_units.append(make<CompilationUnit>(*this, unit_offset, compilation_unit_header));
-        stream.discard_or_error(length_after_header);
+
+        auto line_program = make<LineProgram>(*this, line_info_stream);
+
+        m_compilation_units.append(make<CompilationUnit>(*this, unit_offset, compilation_unit_header, move(line_program)));
+        debug_info_stream.discard_or_error(length_after_header);
     }
+
+    VERIFY(line_info_stream.eof());
 }
 
 AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value,

+ 2 - 0
Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h

@@ -12,6 +12,7 @@
 #include <AK/ByteBuffer.h>
 #include <AK/NonnullOwnPtrVector.h>
 #include <AK/NonnullRefPtr.h>
+#include <AK/RedBlackTree.h>
 #include <AK/RefCounted.h>
 #include <AK/String.h>
 #include <LibELF/Image.h>
@@ -45,6 +46,7 @@ private:
     ReadonlyBytes m_debug_info_data;
     ReadonlyBytes m_abbreviation_data;
     ReadonlyBytes m_debug_strings_data;
+    ReadonlyBytes m_debug_line_data;
     ReadonlyBytes m_debug_line_strings_data;
 
     NonnullOwnPtrVector<Dwarf::CompilationUnit> m_compilation_units;

+ 3 - 0
Userland/Libraries/LibDebug/Dwarf/LineProgram.h

@@ -102,6 +102,9 @@ inline InputStream& operator>>(InputStream& stream, LineProgramUnitHeader32& hea
 }
 
 class LineProgram {
+    AK_MAKE_NONCOPYABLE(LineProgram);
+    AK_MAKE_NONMOVABLE(LineProgram);
+
 public:
     explicit LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream);