Forráskód Böngészése

LibDebug: Handle DWARF 4 address ranges

The format of the address range section is different between DWARF
version 4 and version 5. This meant that we parsed programs compiled
with `-gdwarf-4` incorrectly.
Daniel Bertalan 3 éve
szülő
commit
815f15f82c

+ 30 - 2
Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp

@@ -9,14 +9,14 @@
 
 
 namespace Debug::Dwarf {
 namespace Debug::Dwarf {
 
 
-AddressRanges::AddressRanges(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit)
+AddressRangesV5::AddressRangesV5(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit)
     : m_range_lists_stream(range_lists_data)
     : m_range_lists_stream(range_lists_data)
     , m_compilation_unit(compilation_unit)
     , m_compilation_unit(compilation_unit)
 {
 {
     m_range_lists_stream.seek(offset);
     m_range_lists_stream.seek(offset);
 }
 }
 
 
-void AddressRanges::for_each_range(Function<void(Range)> callback)
+void AddressRangesV5::for_each_range(Function<void(Range)> callback)
 {
 {
     // Dwarf version 5, section 2.17.3 "Non-Contiguous Address Ranges"
     // Dwarf version 5, section 2.17.3 "Non-Contiguous Address Ranges"
 
 
@@ -86,4 +86,32 @@ void AddressRanges::for_each_range(Function<void(Range)> callback)
     }
     }
 }
 }
 
 
+AddressRangesV4::AddressRangesV4(ReadonlyBytes ranges_data, size_t offset, CompilationUnit const& compilation_unit)
+    : m_ranges_stream(ranges_data)
+    , m_compilation_unit(compilation_unit)
+{
+    m_ranges_stream.seek(offset);
+}
+
+void AddressRangesV4::for_each_range(Function<void(Range)> callback)
+{
+    // Dwarf version 4, section 2.17.3 "Non-Contiguous Address Ranges"
+
+    Optional<FlatPtr> current_base_address;
+    while (!m_ranges_stream.eof() && !m_ranges_stream.has_any_error()) {
+        FlatPtr begin, end;
+        m_ranges_stream >> begin >> end;
+
+        if (begin == 0 && end == 0) {
+            // end of list entry
+            return;
+        } else if (begin == explode_byte(0xff)) {
+            current_base_address = end;
+        } else {
+            FlatPtr base = current_base_address.value_or(m_compilation_unit.base_address().value_or(0));
+            callback({ base + begin, base + end });
+        }
+    }
+}
+
 }
 }

+ 23 - 8
Userland/Libraries/LibDebug/Dwarf/AddressRanges.h

@@ -14,17 +14,18 @@
 
 
 namespace Debug::Dwarf {
 namespace Debug::Dwarf {
 
 
-class AddressRanges {
-    AK_MAKE_NONCOPYABLE(AddressRanges);
-    AK_MAKE_NONMOVABLE(AddressRanges);
+struct Range {
+    FlatPtr start { 0 };
+    FlatPtr end { 0 };
+};
+
+class AddressRangesV5 {
+    AK_MAKE_NONCOPYABLE(AddressRangesV5);
+    AK_MAKE_NONMOVABLE(AddressRangesV5);
 
 
 public:
 public:
-    AddressRanges(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit);
+    AddressRangesV5(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit);
 
 
-    struct Range {
-        FlatPtr start { 0 };
-        FlatPtr end { 0 };
-    };
     void for_each_range(Function<void(Range)>);
     void for_each_range(Function<void(Range)>);
 
 
 private:
 private:
@@ -32,4 +33,18 @@ private:
     CompilationUnit const& m_compilation_unit;
     CompilationUnit const& m_compilation_unit;
 };
 };
 
 
+class AddressRangesV4 {
+    AK_MAKE_NONCOPYABLE(AddressRangesV4);
+    AK_MAKE_NONMOVABLE(AddressRangesV4);
+
+public:
+    AddressRangesV4(ReadonlyBytes ranges_data, size_t offset, CompilationUnit const&);
+
+    void for_each_range(Function<void(Range)>);
+
+private:
+    InputMemoryStream m_ranges_stream;
+    CompilationUnit const& m_compilation_unit;
+};
+
 }
 }

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

@@ -34,6 +34,8 @@ public:
     FlatPtr get_address(size_t index) const;
     FlatPtr get_address(size_t index) const;
     char const* get_string(size_t index) const;
     char const* get_string(size_t index) const;
 
 
+    u8 dwarf_version() const { return m_header.version(); }
+
     DwarfInfo const& dwarf_info() const { return m_dwarf_info; }
     DwarfInfo const& dwarf_info() const { return m_dwarf_info; }
     AbbreviationsMap const& abbreviations_map() const { return m_abbreviations; }
     AbbreviationsMap const& abbreviations_map() const { return m_abbreviations; }
     LineProgram const& line_program() const { return *m_line_program; }
     LineProgram const& line_program() const { return *m_line_program; }

+ 13 - 4
Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp

@@ -25,6 +25,7 @@ DwarfInfo::DwarfInfo(ELF::Image const& elf)
     m_debug_range_lists_data = section_data(".debug_rnglists"sv);
     m_debug_range_lists_data = section_data(".debug_rnglists"sv);
     m_debug_str_offsets_data = section_data(".debug_str_offsets"sv);
     m_debug_str_offsets_data = section_data(".debug_str_offsets"sv);
     m_debug_addr_data = section_data(".debug_addr"sv);
     m_debug_addr_data = section_data(".debug_addr"sv);
+    m_debug_ranges_data = section_data(".debug_ranges"sv);
 
 
     populate_compilation_units();
     populate_compilation_units();
 }
 }
@@ -346,11 +347,19 @@ void DwarfInfo::build_cached_dies() const
                 auto offsets = reinterpret_cast<u32 const*>(debug_range_lists_data().offset(base));
                 auto offsets = reinterpret_cast<u32 const*>(debug_range_lists_data().offset(base));
                 offset = offsets[index] + base;
                 offset = offsets[index] + base;
             }
             }
-            AddressRanges address_ranges(debug_range_lists_data(), offset, die.compilation_unit());
+
             Vector<DIERange> entries;
             Vector<DIERange> entries;
-            address_ranges.for_each_range([&entries](auto range) {
-                entries.empend(range.start, range.end);
-            });
+            if (die.compilation_unit().dwarf_version() == 5) {
+                AddressRangesV5 address_ranges(debug_range_lists_data(), offset, die.compilation_unit());
+                address_ranges.for_each_range([&entries](auto range) {
+                    entries.empend(range.start, range.end);
+                });
+            } else {
+                AddressRangesV4 address_ranges(debug_ranges_data(), offset, die.compilation_unit());
+                address_ranges.for_each_range([&entries](auto range) {
+                    entries.empend(range.start, range.end);
+                });
+            }
             return entries;
             return entries;
         }
         }
 
 

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

@@ -33,6 +33,7 @@ public:
     ReadonlyBytes debug_range_lists_data() const { return m_debug_range_lists_data; }
     ReadonlyBytes debug_range_lists_data() const { return m_debug_range_lists_data; }
     ReadonlyBytes debug_str_offsets_data() const { return m_debug_str_offsets_data; }
     ReadonlyBytes debug_str_offsets_data() const { return m_debug_str_offsets_data; }
     ReadonlyBytes debug_addr_data() const { return m_debug_addr_data; }
     ReadonlyBytes debug_addr_data() const { return m_debug_addr_data; }
+    ReadonlyBytes debug_ranges_data() const { return m_debug_ranges_data; }
 
 
     template<typename Callback>
     template<typename Callback>
     void for_each_compilation_unit(Callback) const;
     void for_each_compilation_unit(Callback) const;
@@ -64,6 +65,7 @@ private:
     ReadonlyBytes m_debug_range_lists_data;
     ReadonlyBytes m_debug_range_lists_data;
     ReadonlyBytes m_debug_str_offsets_data;
     ReadonlyBytes m_debug_str_offsets_data;
     ReadonlyBytes m_debug_addr_data;
     ReadonlyBytes m_debug_addr_data;
+    ReadonlyBytes m_debug_ranges_data;
 
 
     NonnullOwnPtrVector<Dwarf::CompilationUnit> m_compilation_units;
     NonnullOwnPtrVector<Dwarf::CompilationUnit> m_compilation_units;