mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:07:46 +00:00
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.
This commit is contained in:
parent
aa941a31ed
commit
7413a7c509
3 changed files with 42 additions and 2 deletions
|
@ -24,6 +24,8 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
#include <LibCoreDump/Backtrace.h>
|
#include <LibCoreDump/Backtrace.h>
|
||||||
#include <LibCoreDump/Reader.h>
|
#include <LibCoreDump/Reader.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -69,6 +71,7 @@ ELF::Core::NotesEntryHeader::Type Reader::NotesEntryIterator::type() const
|
||||||
ASSERT(m_current->header.type == ELF::Core::NotesEntryHeader::Type::ProcessInfo
|
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::MemoryRegionInfo
|
||||||
|| m_current->header.type == ELF::Core::NotesEntryHeader::Type::ThreadInfo
|
|| 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);
|
|| m_current->header.type == ELF::Core::NotesEntryHeader::Type::Null);
|
||||||
return m_current->header.type;
|
return m_current->header.type;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +100,11 @@ void Reader::NotesEntryIterator::next()
|
||||||
m_current = reinterpret_cast<const ELF::Core::NotesEntry*>(current->region_name + strlen(current->region_name) + 1);
|
m_current = reinterpret_cast<const ELF::Core::NotesEntry*>(current->region_name + strlen(current->region_name) + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ELF::Core::NotesEntryHeader::Type::Metadata: {
|
||||||
|
const auto* current = reinterpret_cast<const ELF::Core::Metadata*>(m_current);
|
||||||
|
m_current = reinterpret_cast<const ELF::Core::NotesEntry*>(current->json_data + strlen(current->json_data) + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -141,9 +149,32 @@ const ELF::Core::MemoryRegionInfo* Reader::region_containing(FlatPtr address) co
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace Reader::backtrace() const
|
const Backtrace Reader::backtrace() const
|
||||||
{
|
{
|
||||||
return Backtrace(*this);
|
return Backtrace(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HashMap<String, String> 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<const ELF::Core::Metadata*>(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<String, String> metadata;
|
||||||
|
metadata_json_value.value().as_object().for_each_member([&](auto& key, auto& value) {
|
||||||
|
metadata.set(key, value.as_string_or({}));
|
||||||
|
});
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
#include <AK/MappedFile.h>
|
#include <AK/MappedFile.h>
|
||||||
#include <AK/Noncopyable.h>
|
#include <AK/Noncopyable.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
|
@ -57,7 +58,8 @@ public:
|
||||||
Optional<uint32_t> peek_memory(FlatPtr address) const;
|
Optional<uint32_t> peek_memory(FlatPtr address) const;
|
||||||
const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const;
|
const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const;
|
||||||
|
|
||||||
Backtrace backtrace() const;
|
const Backtrace backtrace() const;
|
||||||
|
const HashMap<String, String> metadata() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class NotesEntryIterator {
|
class NotesEntryIterator {
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct [[gnu::packed]] NotesEntryHeader
|
||||||
ProcessInfo,
|
ProcessInfo,
|
||||||
ThreadInfo,
|
ThreadInfo,
|
||||||
MemoryRegionInfo,
|
MemoryRegionInfo,
|
||||||
|
Metadata,
|
||||||
};
|
};
|
||||||
Type type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
@ -82,4 +83,10 @@ struct [[gnu::packed]] MemoryRegionInfo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct [[gnu::packed]] Metadata
|
||||||
|
{
|
||||||
|
NotesEntryHeader header;
|
||||||
|
char json_data[]; // Null terminated
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue