diff --git a/Kernel/Tasks/Coredump.cpp b/Kernel/Tasks/Coredump.cpp index 380dfa0644b..c529ec0d3dd 100644 --- a/Kernel/Tasks/Coredump.cpp +++ b/Kernel/Tasks/Coredump.cpp @@ -377,10 +377,33 @@ ErrorOr Coredump::create_notes_metadata_data(auto& builder) const return {}; } +static ErrorOr add_elf_note_header(KBufferBuilder& builder) +{ + // https://gabi.xinuos.com/elf/07-pheader.html#note-sections + + static constexpr StringView name = "SerenityOS\0"sv; + Elf_Note note; + note.namesz = name.length(); + note.type = 0; // Arbitrary chosen, we already have our own `type` field in NotesEntryHeader. + + static_assert(sizeof(Elf_Note) == 12); + TRY(builder.append_bytes(ReadonlyBytes { ¬e, sizeof(note) })); + + // names and desc are 4-bytes aligned. + Array zero_padding {}; + TRY(builder.append(name)); + TRY(builder.append_bytes(zero_padding.span().trim(mod(-name.length(), 4)))); + + return {}; +} + ErrorOr> Coredump::create_notes_segment_data() const { auto builder = TRY(KBufferBuilder::try_create()); + TRY(add_elf_note_header(builder)); + auto header_offset = builder.length(); + TRY(create_notes_process_data(builder)); TRY(create_notes_threads_data(builder)); TRY(create_notes_regions_data(builder)); @@ -390,6 +413,13 @@ ErrorOr> Coredump::create_notes_segment_data() const null_entry.type = ELF::Core::NotesEntryHeader::Type::Null; TRY(builder.append(ReadonlyBytes { &null_entry, sizeof(null_entry) })); + auto desc_size = builder.length() - header_offset; + auto note_header = reinterpret_cast(builder.bytes().data()); + note_header->descsz = desc_size; + + Array padding_bytes {}; + TRY(builder.append_bytes(padding_bytes.span().trim(mod(-desc_size, 4)))); + return builder.build(); } diff --git a/Userland/Libraries/LibCoredump/Reader.cpp b/Userland/Libraries/LibCoredump/Reader.cpp index f823f8de9d8..ae5d872ce0d 100644 --- a/Userland/Libraries/LibCoredump/Reader.cpp +++ b/Userland/Libraries/LibCoredump/Reader.cpp @@ -18,6 +18,11 @@ #include #include +template<> +struct AK::Traits : public AK::DefaultTraits { + static constexpr bool is_trivially_serializable() { return true; } +}; + namespace Coredump { OwnPtr Reader::create(StringView path) @@ -133,6 +138,23 @@ bool Reader::NotesEntryIterator::at_end() const return type() == ELF::Core::NotesEntryHeader::Type::Null; } +ReadonlyBytes Reader::get_serenity_note_section() const +{ + auto const& program_header = m_coredump_image.program_header(m_notes_segment_index); + auto note_section_bytes = ReadonlyBytes { program_header.raw_data(), program_header.size_in_memory() }; + FixedMemoryStream section_stream { note_section_bytes }; + + auto note = section_stream.read_value().release_value_but_fixme_should_propagate_errors(); + auto name = section_stream.read_in_place(note.namesz); + + VERIFY(note.type == 0); + VERIFY(name.release_value_but_fixme_should_propagate_errors() == "SerenityOS\0"sv.bytes()); + + section_stream.discard(mod(-note.namesz, 4)).release_value_but_fixme_should_propagate_errors(); + + return section_stream.read_in_place(note.descsz).release_value_but_fixme_should_propagate_errors(); +} + Optional Reader::peek_memory(FlatPtr address) const { auto region = region_containing(address); @@ -149,7 +171,7 @@ Optional Reader::peek_memory(FlatPtr address) const JsonObject const Reader::process_info() const { const ELF::Core::ProcessInfo* process_info_notes_entry = nullptr; - NotesEntryIterator it(bit_cast(m_coredump_image.program_header(m_notes_segment_index).raw_data())); + NotesEntryIterator it(get_serenity_note_section().data()); for (; !it.at_end(); it.next()) { if (it.type() != ELF::Core::NotesEntryHeader::Type::ProcessInfo) continue; @@ -248,7 +270,7 @@ Vector Reader::process_environment() const HashMap Reader::metadata() const { const ELF::Core::Metadata* metadata_notes_entry = nullptr; - NotesEntryIterator it(bit_cast(m_coredump_image.program_header(m_notes_segment_index).raw_data())); + NotesEntryIterator it(get_serenity_note_section().data()); for (; !it.at_end(); it.next()) { if (it.type() != ELF::Core::NotesEntryHeader::Type::Metadata) continue; diff --git a/Userland/Libraries/LibCoredump/Reader.h b/Userland/Libraries/LibCoredump/Reader.h index 5a8813f5334..16b8fd26208 100644 --- a/Userland/Libraries/LibCoredump/Reader.h +++ b/Userland/Libraries/LibCoredump/Reader.h @@ -102,6 +102,8 @@ private: u8 const* start { nullptr }; }; + ReadonlyBytes get_serenity_note_section() const; + // Private as we don't need anyone poking around in this JsonObject // manually - we know very well what should be included and expose that // as getters with the appropriate (non-JsonValue) types. @@ -122,7 +124,7 @@ private: template void Reader::for_each_memory_region_info(Func func) const { - NotesEntryIterator it(bit_cast(m_coredump_image.program_header(m_notes_segment_index).raw_data())); + NotesEntryIterator it(get_serenity_note_section().data()); for (; !it.at_end(); it.next()) { if (it.type() != ELF::Core::NotesEntryHeader::Type::MemoryRegionInfo) continue; @@ -150,7 +152,7 @@ void Reader::for_each_memory_region_info(Func func) const template void Reader::for_each_thread_info(Func func) const { - NotesEntryIterator it(bit_cast(m_coredump_image.program_header(m_notes_segment_index).raw_data())); + NotesEntryIterator it(get_serenity_note_section().data()); for (; !it.at_end(); it.next()) { if (it.type() != ELF::Core::NotesEntryHeader::Type::ThreadInfo) continue;