AddressRanges.cpp 4.1 KB

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