mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +00:00 
			
		
		
		
	LibDebug: Implement symbolication for x86_64
This commit is contained in:
		
							parent
							
								
									567fa4b2f0
								
							
						
					
					
						commit
						2c41e89d08
					
				
					 9 changed files with 33 additions and 43 deletions
				
			
		|  | @ -35,10 +35,6 @@ ELFObjectInfo const* Backtrace::object_info_for_region(ELF::Core::MemoryRegionIn | |||
|         return nullptr; | ||||
| 
 | ||||
|     auto image = make<ELF::Image>(file_or_error.value()->bytes()); | ||||
| #if !ARCH(I386) | ||||
|     // FIXME: Fix LibDebug
 | ||||
|     return nullptr; | ||||
| #endif | ||||
|     auto info = make<ELFObjectInfo>(file_or_error.release_value(), make<Debug::DebugInfo>(move(image))); | ||||
|     auto* info_ptr = info.ptr(); | ||||
|     m_debug_info_cache.set(path, move(info)); | ||||
|  | @ -81,11 +77,11 @@ Backtrace::~Backtrace() | |||
| { | ||||
| } | ||||
| 
 | ||||
| void Backtrace::add_entry(const Reader& coredump, FlatPtr eip) | ||||
| void Backtrace::add_entry(const Reader& coredump, FlatPtr ip) | ||||
| { | ||||
|     auto* region = coredump.region_containing((FlatPtr)eip); | ||||
|     auto* region = coredump.region_containing((FlatPtr)ip); | ||||
|     if (!region) { | ||||
|         m_entries.append({ eip, {}, {}, {} }); | ||||
|         m_entries.append({ ip, {}, {}, {} }); | ||||
|         return; | ||||
|     } | ||||
|     auto object_name = region->object_name(); | ||||
|  | @ -95,15 +91,9 @@ void Backtrace::add_entry(const Reader& coredump, FlatPtr eip) | |||
|     if (!object_info) | ||||
|         return; | ||||
| 
 | ||||
| #if ARCH(I386) | ||||
|     auto function_name = object_info->debug_info->elf().symbolicate(eip - region->region_start); | ||||
|     auto source_position = object_info->debug_info->get_source_position_with_inlines(eip - region->region_start); | ||||
| #else | ||||
|     // FIXME: Fix symbolication.
 | ||||
|     auto function_name = ""; | ||||
|     Debug::DebugInfo::SourcePositionWithInlines source_position; | ||||
| #endif | ||||
|     m_entries.append({ eip, object_name, function_name, source_position }); | ||||
|     auto function_name = object_info->debug_info->elf().symbolicate(ip - region->region_start); | ||||
|     auto source_position = object_info->debug_info->get_source_position_with_inlines(ip - region->region_start); | ||||
|     m_entries.append({ ip, object_name, function_name, source_position }); | ||||
| } | ||||
| 
 | ||||
| String Backtrace::Entry::to_string(bool color) const | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ public: | |||
|     const Vector<Entry> entries() const { return m_entries; } | ||||
| 
 | ||||
| private: | ||||
|     void add_entry(const Reader&, FlatPtr eip); | ||||
|     void add_entry(const Reader&, FlatPtr ip); | ||||
|     ELFObjectInfo const* object_info_for_region(ELF::Core::MemoryRegionInfo const&); | ||||
| 
 | ||||
|     ELF::Core::ThreadInfo m_thread_info; | ||||
|  |  | |||
|  | @ -60,9 +60,9 @@ void DebugInfo::parse_scopes_impl(Dwarf::DIE const& die) | |||
|             dbgln_if(SPAM_DEBUG, "DWARF: Couldn't find attribute LowPc for scope"); | ||||
|             return; | ||||
|         } | ||||
|         scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().data.as_u32; | ||||
|         scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().data.as_addr; | ||||
|         // The attribute name HighPc is confusing. In this context, it seems to actually be a positive offset from LowPc
 | ||||
|         scope.address_high = scope.address_low + child.get_attribute(Dwarf::Attribute::HighPc).value().data.as_u32; | ||||
|         scope.address_high = scope.address_low + child.get_attribute(Dwarf::Attribute::HighPc).value().data.as_addr; | ||||
| 
 | ||||
|         child.for_each_child([&](Dwarf::DIE const& variable_entry) { | ||||
|             if (!(variable_entry.tag() == Dwarf::EntryTag::Variable | ||||
|  | @ -78,7 +78,6 @@ void DebugInfo::parse_scopes_impl(Dwarf::DIE const& die) | |||
| 
 | ||||
| void DebugInfo::prepare_lines() | ||||
| { | ||||
| 
 | ||||
|     Vector<Dwarf::LineProgram::LineInfo> all_lines; | ||||
|     m_dwarf_info.for_each_compilation_unit([&all_lines](Dwarf::CompilationUnit const& unit) { | ||||
|         all_lines.extend(unit.line_program().lines()); | ||||
|  | @ -115,7 +114,7 @@ void DebugInfo::prepare_lines() | |||
|     }); | ||||
| } | ||||
| 
 | ||||
| Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(u32 target_address) const | ||||
| Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(FlatPtr target_address) const | ||||
| { | ||||
|     if (m_sorted_lines.is_empty()) | ||||
|         return {}; | ||||
|  | @ -219,7 +218,7 @@ static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::V | |||
|     switch (location_info.value().type) { | ||||
|     case Dwarf::AttributeValue::Type::UnsignedNumber: | ||||
|         variable_info.location_type = DebugInfo::VariableInfo::LocationType::Address; | ||||
|         variable_info.location_data.address = location_info.value().data.as_u32; | ||||
|         variable_info.location_data.address = location_info.value().data.as_addr; | ||||
|         break; | ||||
|     case Dwarf::AttributeValue::Type::DwarfExpression: { | ||||
|         auto expression_bytes = ReadonlyBytes { location_info.value().data.as_raw_bytes.bytes, location_info.value().data.as_raw_bytes.length }; | ||||
|  | @ -228,7 +227,7 @@ static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::V | |||
|         if (value.type != Dwarf::Expression::Type::None) { | ||||
|             VERIFY(value.type == Dwarf::Expression::Type::UnsignedInteger); | ||||
|             variable_info.location_type = DebugInfo::VariableInfo::LocationType::Address; | ||||
|             variable_info.location_data.address = value.data.as_u32; | ||||
|             variable_info.location_data.address = value.data.as_addr; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | @ -349,7 +348,7 @@ bool DebugInfo::is_variable_tag_supported(Dwarf::EntryTag const& tag) | |||
|         || tag == Dwarf::EntryTag::ArrayType; | ||||
| } | ||||
| 
 | ||||
| String DebugInfo::name_of_containing_function(u32 address) const | ||||
| String DebugInfo::name_of_containing_function(FlatPtr address) const | ||||
| { | ||||
|     auto function = get_containing_function(address); | ||||
|     if (!function.has_value()) | ||||
|  | @ -357,7 +356,7 @@ String DebugInfo::name_of_containing_function(u32 address) const | |||
|     return function.value().name; | ||||
| } | ||||
| 
 | ||||
| Optional<DebugInfo::VariablesScope> DebugInfo::get_containing_function(u32 address) const | ||||
| Optional<DebugInfo::VariablesScope> DebugInfo::get_containing_function(FlatPtr address) const | ||||
| { | ||||
|     for (const auto& scope : m_scopes) { | ||||
|         if (!scope.is_function || address < scope.address_low || address >= scope.address_high) | ||||
|  | @ -386,7 +385,7 @@ DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(Dwarf::LineP | |||
|     return { line.file, line.line, line.address }; | ||||
| } | ||||
| 
 | ||||
| DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(u32 address) const | ||||
| DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(FlatPtr address) const | ||||
| { | ||||
|     // If the address is in an "inline chain", this is the inner-most inlined position.
 | ||||
|     auto inner_source_position = get_source_position(address); | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ public: | |||
|     struct SourcePosition { | ||||
|         FlyString file_path; | ||||
|         size_t line_number { 0 }; | ||||
|         Optional<u32> address_of_first_statement; | ||||
|         Optional<FlatPtr> address_of_first_statement; | ||||
| 
 | ||||
|         SourcePosition() | ||||
|             : SourcePosition(String::empty(), 0) | ||||
|  | @ -42,7 +42,7 @@ public: | |||
|             , line_number(line_number) | ||||
|         { | ||||
|         } | ||||
|         SourcePosition(String file_path, size_t line_number, u32 address_of_first_statement) | ||||
|         SourcePosition(String file_path, size_t line_number, FlatPtr address_of_first_statement) | ||||
|             : file_path(file_path) | ||||
|             , line_number(line_number) | ||||
|             , address_of_first_statement(address_of_first_statement) | ||||
|  | @ -65,7 +65,7 @@ public: | |||
|         String type_name; | ||||
|         LocationType location_type { LocationType::None }; | ||||
|         union { | ||||
|             u32 address; | ||||
|             FlatPtr address; | ||||
|         } location_data { 0 }; | ||||
| 
 | ||||
|         union { | ||||
|  | @ -86,20 +86,20 @@ public: | |||
|     struct VariablesScope { | ||||
|         bool is_function { false }; | ||||
|         String name; | ||||
|         u32 address_low { 0 }; | ||||
|         u32 address_high { 0 }; // Non-inclusive - the lowest address after address_low that's not in this scope
 | ||||
|         FlatPtr address_low { 0 }; | ||||
|         FlatPtr address_high { 0 }; // Non-inclusive - the lowest address after address_low that's not in this scope
 | ||||
|         Vector<Dwarf::DIE> dies_of_variables; | ||||
|     }; | ||||
| 
 | ||||
|     NonnullOwnPtrVector<VariableInfo> get_variables_in_current_scope(PtraceRegisters const&) const; | ||||
| 
 | ||||
|     Optional<SourcePosition> get_source_position(u32 address) const; | ||||
|     Optional<SourcePosition> get_source_position(FlatPtr address) const; | ||||
| 
 | ||||
|     struct SourcePositionWithInlines { | ||||
|         Optional<SourcePosition> source_position; | ||||
|         Vector<SourcePosition> inline_chain; | ||||
|     }; | ||||
|     SourcePositionWithInlines get_source_position_with_inlines(u32 address) const; | ||||
|     SourcePositionWithInlines get_source_position_with_inlines(FlatPtr address) const; | ||||
| 
 | ||||
|     struct SourcePositionAndAddress { | ||||
|         String file; | ||||
|  | @ -109,9 +109,9 @@ public: | |||
| 
 | ||||
|     Optional<SourcePositionAndAddress> get_address_from_source_position(const String& file, size_t line) const; | ||||
| 
 | ||||
|     String name_of_containing_function(u32 address) const; | ||||
|     String name_of_containing_function(FlatPtr address) const; | ||||
|     Vector<SourcePosition> source_lines_in_scope(const VariablesScope&) const; | ||||
|     Optional<VariablesScope> get_containing_function(u32 address) const; | ||||
|     Optional<VariablesScope> get_containing_function(FlatPtr address) const; | ||||
| 
 | ||||
| private: | ||||
|     void prepare_variable_scopes(); | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ struct AttributeValue { | |||
|     } type; | ||||
| 
 | ||||
|     union { | ||||
|         FlatPtr as_addr; | ||||
|         u32 as_u32; | ||||
|         i32 as_i32; | ||||
|         u64 as_u64; | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ void DwarfInfo::populate_compilation_units() | |||
| 
 | ||||
|         debug_info_stream >> compilation_unit_header; | ||||
|         VERIFY(compilation_unit_header.common.version <= 5); | ||||
|         VERIFY(compilation_unit_header.address_size() == sizeof(u32)); | ||||
|         VERIFY(compilation_unit_header.address_size() == sizeof(FlatPtr)); | ||||
| 
 | ||||
|         u32 length_after_header = compilation_unit_header.length() - (compilation_unit_header.header_size() - offsetof(CompilationUnitHeader, common.version)); | ||||
| 
 | ||||
|  | @ -102,11 +102,11 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im | |||
|         break; | ||||
|     } | ||||
|     case AttributeDataForm::Addr: { | ||||
|         u32 address; | ||||
|         FlatPtr address; | ||||
|         debug_info_stream >> address; | ||||
|         VERIFY(!debug_info_stream.has_any_error()); | ||||
|         value.type = AttributeValue::Type::UnsignedNumber; | ||||
|         value.data.as_u32 = address; | ||||
|         value.data.as_addr = address; | ||||
|         break; | ||||
|     } | ||||
|     case AttributeDataForm::SData: { | ||||
|  | @ -250,7 +250,6 @@ void DwarfInfo::build_cached_dies() const | |||
|         if (!start.has_value() || !end.has_value()) | ||||
|             return {}; | ||||
| 
 | ||||
|         VERIFY(sizeof(FlatPtr) == sizeof(u32)); | ||||
|         VERIFY(start->type == Dwarf::AttributeValue::Type::UnsignedNumber); | ||||
| 
 | ||||
|         // DW_AT_high_pc attribute can have different meanings depending on the attribute form.
 | ||||
|  | @ -258,7 +257,7 @@ void DwarfInfo::build_cached_dies() const | |||
| 
 | ||||
|         uint32_t range_end = 0; | ||||
|         if (end->form == Dwarf::AttributeDataForm::Addr) | ||||
|             range_end = end->data.as_u32; | ||||
|             range_end = end->data.as_addr; | ||||
|         else | ||||
|             range_end = start->data.as_u32 + end->data.as_u32; | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ enum class Type { | |||
| struct Value { | ||||
|     Type type; | ||||
|     union { | ||||
|         FlatPtr as_addr; | ||||
|         u32 as_u32; | ||||
|     } data { 0 }; | ||||
| }; | ||||
|  |  | |||
|  | @ -174,7 +174,7 @@ void LineProgram::handle_extended_opcode() | |||
|         break; | ||||
|     } | ||||
|     default: | ||||
|         dbgln_if(DWARF_DEBUG, "offset: {:p}", m_stream.offset()); | ||||
|         dbgln("Encountered unknown sub opcode {} at stream offset {:p}", sub_opcode, m_stream.offset()); | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -109,7 +109,7 @@ public: | |||
|     explicit LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream); | ||||
| 
 | ||||
|     struct LineInfo { | ||||
|         u32 address { 0 }; | ||||
|         FlatPtr address { 0 }; | ||||
|         FlyString file; | ||||
|         size_t line { 0 }; | ||||
|     }; | ||||
|  | @ -176,7 +176,7 @@ private: | |||
|     Vector<FileEntry> m_source_files; | ||||
| 
 | ||||
|     // The registers of the "line program" virtual machine
 | ||||
|     u32 m_address { 0 }; | ||||
|     FlatPtr m_address { 0 }; | ||||
|     size_t m_line { 0 }; | ||||
|     size_t m_file_index { 0 }; | ||||
|     bool m_is_statement { false }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gunnar Beutner
						Gunnar Beutner