From 7413a7c50959575388ca3dcc1a3341ef8e89e555 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 30 Dec 2020 15:06:33 +0100 Subject: [PATCH] LibELF+LibCoreDump: Add a Metadata notes entry This is a new NotesEntry type which will allow applications to embed arbitrary metadata in crashdumps (stored as a JSON string). It will be used to store an assertion message, for example. --- Libraries/LibCoreDump/Reader.cpp | 33 +++++++++++++++++++++++++++++++- Libraries/LibCoreDump/Reader.h | 4 +++- Libraries/LibELF/CoreDump.h | 7 +++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Libraries/LibCoreDump/Reader.cpp b/Libraries/LibCoreDump/Reader.cpp index e1bdbeed37..130c0bab9b 100644 --- a/Libraries/LibCoreDump/Reader.cpp +++ b/Libraries/LibCoreDump/Reader.cpp @@ -24,6 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include @@ -69,6 +71,7 @@ ELF::Core::NotesEntryHeader::Type Reader::NotesEntryIterator::type() const ASSERT(m_current->header.type == ELF::Core::NotesEntryHeader::Type::ProcessInfo || m_current->header.type == ELF::Core::NotesEntryHeader::Type::MemoryRegionInfo || m_current->header.type == ELF::Core::NotesEntryHeader::Type::ThreadInfo + || m_current->header.type == ELF::Core::NotesEntryHeader::Type::Metadata || m_current->header.type == ELF::Core::NotesEntryHeader::Type::Null); return m_current->header.type; } @@ -97,6 +100,11 @@ void Reader::NotesEntryIterator::next() m_current = reinterpret_cast(current->region_name + strlen(current->region_name) + 1); break; } + case ELF::Core::NotesEntryHeader::Type::Metadata: { + const auto* current = reinterpret_cast(m_current); + m_current = reinterpret_cast(current->json_data + strlen(current->json_data) + 1); + break; + } default: ASSERT_NOT_REACHED(); } @@ -141,9 +149,32 @@ const ELF::Core::MemoryRegionInfo* Reader::region_containing(FlatPtr address) co return ret; } -Backtrace Reader::backtrace() const +const Backtrace Reader::backtrace() const { return Backtrace(*this); } +const HashMap Reader::metadata() const +{ + const ELF::Core::Metadata* metadata_notes_entry = nullptr; + for (NotesEntryIterator it((const u8*)m_coredump_image.program_header(m_notes_segment_index).raw_data()); !it.at_end(); it.next()) { + if (it.type() != ELF::Core::NotesEntryHeader::Type::Metadata) + continue; + metadata_notes_entry = reinterpret_cast(it.current()); + break; + } + if (!metadata_notes_entry) + return {}; + auto metadata_json_value = JsonValue::from_string(metadata_notes_entry->json_data); + if (!metadata_json_value.has_value()) + return {}; + if (!metadata_json_value.value().is_object()) + return {}; + HashMap metadata; + metadata_json_value.value().as_object().for_each_member([&](auto& key, auto& value) { + metadata.set(key, value.as_string_or({})); + }); + return metadata; +} + } diff --git a/Libraries/LibCoreDump/Reader.h b/Libraries/LibCoreDump/Reader.h index ee7dd82ed2..a05200ed44 100644 --- a/Libraries/LibCoreDump/Reader.h +++ b/Libraries/LibCoreDump/Reader.h @@ -26,6 +26,7 @@ #pragma once +#include #include #include #include @@ -57,7 +58,8 @@ public: Optional peek_memory(FlatPtr address) const; const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const; - Backtrace backtrace() const; + const Backtrace backtrace() const; + const HashMap metadata() const; private: class NotesEntryIterator { diff --git a/Libraries/LibELF/CoreDump.h b/Libraries/LibELF/CoreDump.h index 3ff21d38bb..fa3fb45e5a 100644 --- a/Libraries/LibELF/CoreDump.h +++ b/Libraries/LibELF/CoreDump.h @@ -39,6 +39,7 @@ struct [[gnu::packed]] NotesEntryHeader ProcessInfo, ThreadInfo, MemoryRegionInfo, + Metadata, }; Type type; }; @@ -82,4 +83,10 @@ struct [[gnu::packed]] MemoryRegionInfo } }; +struct [[gnu::packed]] Metadata +{ + NotesEntryHeader header; + char json_data[]; // Null terminated +}; + }