AddressRanges.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2020-2021, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "AddressRanges.h"
  7. #include "DwarfTypes.h"
  8. #include <AK/LEB128.h>
  9. #include <LibCore/Stream.h>
  10. namespace Debug::Dwarf {
  11. AddressRangesV5::AddressRangesV5(NonnullOwnPtr<AK::Stream> range_lists_stream, CompilationUnit const& compilation_unit)
  12. : m_range_lists_stream(move(range_lists_stream))
  13. , m_compilation_unit(compilation_unit)
  14. {
  15. }
  16. ErrorOr<void> AddressRangesV5::for_each_range(Function<void(Range)> callback)
  17. {
  18. // Dwarf version 5, section 2.17.3 "Non-Contiguous Address Ranges"
  19. Optional<FlatPtr> current_base_address;
  20. while (!m_range_lists_stream->is_eof()) {
  21. auto entry_type = TRY(m_range_lists_stream->read_value<u8>());
  22. switch (static_cast<RangeListEntryType>(entry_type)) {
  23. case RangeListEntryType::BaseAddress: {
  24. current_base_address = TRY(m_range_lists_stream->read_value<FlatPtr>());
  25. break;
  26. }
  27. case RangeListEntryType::BaseAddressX: {
  28. FlatPtr index;
  29. TRY(LEB128::read_unsigned(*m_range_lists_stream, index));
  30. current_base_address = TRY(m_compilation_unit.get_address(index));
  31. break;
  32. }
  33. case RangeListEntryType::OffsetPair: {
  34. Optional<FlatPtr> base_address = current_base_address;
  35. if (!base_address.has_value()) {
  36. base_address = TRY(m_compilation_unit.base_address());
  37. }
  38. if (!base_address.has_value())
  39. return Error::from_string_literal("Expected base_address for rangelist");
  40. size_t start_offset, end_offset;
  41. TRY(LEB128::read_unsigned(*m_range_lists_stream, start_offset));
  42. TRY(LEB128::read_unsigned(*m_range_lists_stream, end_offset));
  43. callback(Range { start_offset + *base_address, end_offset + *base_address });
  44. break;
  45. }
  46. case RangeListEntryType::StartLength: {
  47. auto start = TRY(m_range_lists_stream->read_value<FlatPtr>());
  48. size_t length;
  49. TRY(LEB128::read_unsigned(*m_range_lists_stream, length));
  50. callback(Range { start, start + length });
  51. break;
  52. }
  53. case RangeListEntryType::StartXEndX: {
  54. size_t start, end;
  55. TRY(LEB128::read_unsigned(*m_range_lists_stream, start));
  56. TRY(LEB128::read_unsigned(*m_range_lists_stream, end));
  57. callback(Range { TRY(m_compilation_unit.get_address(start)), TRY(m_compilation_unit.get_address(end)) });
  58. break;
  59. }
  60. case RangeListEntryType::StartXLength: {
  61. size_t start, length;
  62. TRY(LEB128::read_unsigned(*m_range_lists_stream, start));
  63. TRY(LEB128::read_unsigned(*m_range_lists_stream, length));
  64. auto start_addr = TRY(m_compilation_unit.get_address(start));
  65. callback(Range { start_addr, start_addr + length });
  66. break;
  67. }
  68. case RangeListEntryType::EndOfList:
  69. return {};
  70. default:
  71. dbgln("unsupported range list entry type: 0x{:x}", entry_type);
  72. return Error::from_string_literal("Unsupported range list entry type");
  73. }
  74. }
  75. return {};
  76. }
  77. AddressRangesV4::AddressRangesV4(NonnullOwnPtr<AK::Stream> ranges_stream, CompilationUnit const& compilation_unit)
  78. : m_ranges_stream(move(ranges_stream))
  79. , m_compilation_unit(compilation_unit)
  80. {
  81. }
  82. ErrorOr<void> AddressRangesV4::for_each_range(Function<void(Range)> callback)
  83. {
  84. // Dwarf version 4, section 2.17.3 "Non-Contiguous Address Ranges"
  85. Optional<FlatPtr> current_base_address;
  86. while (!m_ranges_stream->is_eof()) {
  87. auto begin = TRY(m_ranges_stream->read_value<FlatPtr>());
  88. auto end = TRY(m_ranges_stream->read_value<FlatPtr>());
  89. if (begin == 0 && end == 0) {
  90. // end of list entry
  91. return {};
  92. } else if (begin == explode_byte(0xff)) {
  93. current_base_address = end;
  94. } else {
  95. FlatPtr base = current_base_address.value_or(TRY(m_compilation_unit.base_address()).value_or(0));
  96. callback({ base + begin, base + end });
  97. }
  98. }
  99. return {};
  100. }
  101. }