Reader.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/ByteReader.h>
  9. #include <AK/HashMap.h>
  10. #include <AK/Noncopyable.h>
  11. #include <AK/OwnPtr.h>
  12. #include <LibCore/MappedFile.h>
  13. #include <LibELF/Core.h>
  14. #include <LibELF/Image.h>
  15. namespace Coredump {
  16. struct MemoryRegionInfo {
  17. ELF::Core::NotesEntryHeader header;
  18. uint64_t region_start;
  19. uint64_t region_end;
  20. uint16_t program_header_index;
  21. StringView region_name;
  22. StringView object_name() const
  23. {
  24. if (region_name.contains("Loader.so"sv))
  25. return "Loader.so"sv;
  26. auto maybe_colon_index = region_name.find(':');
  27. if (!maybe_colon_index.has_value())
  28. return {};
  29. return region_name.substring_view(0, *maybe_colon_index);
  30. }
  31. };
  32. class Reader {
  33. AK_MAKE_NONCOPYABLE(Reader);
  34. AK_MAKE_NONMOVABLE(Reader);
  35. public:
  36. static OwnPtr<Reader> create(StringView);
  37. ~Reader() = default;
  38. template<typename Func>
  39. void for_each_memory_region_info(Func func) const;
  40. struct LibraryInfo {
  41. ByteString name;
  42. ByteString path;
  43. FlatPtr base_address { 0 };
  44. };
  45. void for_each_library(Function<void(LibraryInfo)> func) const;
  46. template<typename Func>
  47. void for_each_thread_info(Func func) const;
  48. const ELF::Image& image() const { return m_coredump_image; }
  49. Optional<FlatPtr> peek_memory(FlatPtr address) const;
  50. Optional<MemoryRegionInfo> first_region_for_object(StringView object_name) const;
  51. Optional<MemoryRegionInfo> region_containing(FlatPtr address) const;
  52. struct LibraryData {
  53. ByteString name;
  54. FlatPtr base_address { 0 };
  55. NonnullOwnPtr<Core::MappedFile> file;
  56. ELF::Image lib_elf;
  57. };
  58. LibraryData const* library_containing(FlatPtr address) const;
  59. ByteString resolve_object_path(StringView object_name) const;
  60. int process_pid() const;
  61. u8 process_termination_signal() const;
  62. ByteString process_executable_path() const;
  63. Vector<ByteString> process_arguments() const;
  64. Vector<ByteString> process_environment() const;
  65. HashMap<ByteString, ByteString> metadata() const;
  66. private:
  67. explicit Reader(ReadonlyBytes);
  68. explicit Reader(ByteBuffer);
  69. explicit Reader(NonnullOwnPtr<Core::MappedFile>);
  70. static Optional<ByteBuffer> decompress_coredump(ReadonlyBytes);
  71. class NotesEntryIterator {
  72. public:
  73. NotesEntryIterator(u8 const* notes_data);
  74. ELF::Core::NotesEntryHeader::Type type() const;
  75. const ELF::Core::NotesEntry* current() const;
  76. void next();
  77. bool at_end() const;
  78. private:
  79. const ELF::Core::NotesEntry* m_current { nullptr };
  80. u8 const* start { nullptr };
  81. };
  82. // Private as we don't need anyone poking around in this JsonObject
  83. // manually - we know very well what should be included and expose that
  84. // as getters with the appropriate (non-JsonValue) types.
  85. const JsonObject process_info() const;
  86. // For uncompressed coredumps, we keep the MappedFile
  87. OwnPtr<Core::MappedFile> m_mapped_file;
  88. // For compressed coredumps, we decompress them into a ByteBuffer
  89. ByteBuffer m_coredump_buffer;
  90. ReadonlyBytes m_coredump_bytes;
  91. ELF::Image m_coredump_image;
  92. ssize_t m_notes_segment_index { -1 };
  93. };
  94. template<typename Func>
  95. void Reader::for_each_memory_region_info(Func func) const
  96. {
  97. NotesEntryIterator it(bit_cast<u8 const*>(m_coredump_image.program_header(m_notes_segment_index).raw_data()));
  98. for (; !it.at_end(); it.next()) {
  99. if (it.type() != ELF::Core::NotesEntryHeader::Type::MemoryRegionInfo)
  100. continue;
  101. ELF::Core::MemoryRegionInfo raw_memory_region_info;
  102. ReadonlyBytes raw_data {
  103. it.current(),
  104. sizeof(raw_memory_region_info),
  105. };
  106. ByteReader::load(raw_data.data(), raw_memory_region_info);
  107. auto const* region_name_ptr = bit_cast<char const*>(raw_data.offset_pointer(raw_data.size()));
  108. MemoryRegionInfo memory_region_info {
  109. raw_memory_region_info.header,
  110. raw_memory_region_info.region_start,
  111. raw_memory_region_info.region_end,
  112. raw_memory_region_info.program_header_index,
  113. { region_name_ptr, strlen(region_name_ptr) },
  114. };
  115. IterationDecision decision = func(memory_region_info);
  116. if (decision == IterationDecision::Break)
  117. return;
  118. }
  119. }
  120. template<typename Func>
  121. void Reader::for_each_thread_info(Func func) const
  122. {
  123. NotesEntryIterator it(bit_cast<u8 const*>(m_coredump_image.program_header(m_notes_segment_index).raw_data()));
  124. for (; !it.at_end(); it.next()) {
  125. if (it.type() != ELF::Core::NotesEntryHeader::Type::ThreadInfo)
  126. continue;
  127. ELF::Core::ThreadInfo thread_info;
  128. ByteReader::load(bit_cast<u8 const*>(it.current()), thread_info);
  129. IterationDecision decision = func(thread_info);
  130. if (decision == IterationDecision::Break)
  131. return;
  132. }
  133. }
  134. }