buffered_dwarf_reader.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright (c) 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/debug/buffered_dwarf_reader.h"
  5. #ifdef USE_SYMBOLIZE
  6. #include <algorithm>
  7. #include <cstring>
  8. #include "base/numerics/safe_conversions.h"
  9. #include "base/third_party/symbolize/symbolize.h"
  10. namespace base::debug {
  11. BufferedDwarfReader::BufferedDwarfReader(int fd, uint64_t position)
  12. : fd_(fd), next_chunk_start_(position), last_chunk_start_(position) {}
  13. size_t BufferedDwarfReader::ReadCString(uint64_t max_position,
  14. char* out,
  15. size_t out_size) {
  16. char character;
  17. size_t bytes_written = 0;
  18. do {
  19. if (!ReadChar(character)) {
  20. return 0;
  21. }
  22. if (out && bytes_written < out_size) {
  23. out[bytes_written++] = character;
  24. }
  25. } while (character != '\0' && position() < max_position);
  26. if (out) {
  27. out[std::min(bytes_written, out_size - 1)] = '\0';
  28. }
  29. return bytes_written;
  30. }
  31. bool BufferedDwarfReader::ReadLeb128(uint64_t& value) {
  32. value = 0;
  33. uint8_t byte;
  34. int shift = 0;
  35. do {
  36. if (!ReadInt8(byte))
  37. return false;
  38. value |= static_cast<uint64_t>(byte & 0x7F) << shift;
  39. shift += 7;
  40. } while (byte & 0x80);
  41. return true;
  42. }
  43. bool BufferedDwarfReader::ReadLeb128(int64_t& value) {
  44. value = 0;
  45. uint8_t byte;
  46. int shift = 0;
  47. bool sign_bit = false;
  48. do {
  49. if (!ReadInt8(byte))
  50. return false;
  51. value |= static_cast<uint64_t>(byte & 0x7F) << shift;
  52. shift += 7;
  53. sign_bit = byte & 0x40;
  54. } while (byte & 0x80);
  55. constexpr int bits_in_output = sizeof(value) * 8;
  56. if ((shift < bits_in_output) && sign_bit) {
  57. value |= -(1 << shift);
  58. }
  59. return true;
  60. }
  61. bool BufferedDwarfReader::ReadInitialLength(bool& is_64bit, uint64_t& length) {
  62. uint32_t token_32bit;
  63. if (!ReadInt32(token_32bit)) {
  64. return false;
  65. }
  66. // Dwarf 3 introduced an extended length field that both indicates this is
  67. // DWARF-64 and changes how the size is encoded. 0xfffffff0 and higher are
  68. // reserved with 0xffffffff meaning it's the extended field with the
  69. // following 64-bits being the full length.
  70. if (token_32bit < 0xfffffff0) {
  71. length = token_32bit;
  72. is_64bit = false;
  73. return true;
  74. }
  75. if (token_32bit != 0xffffffff) {
  76. return false;
  77. }
  78. if (!ReadInt64(length)) {
  79. return false;
  80. }
  81. is_64bit = true;
  82. return true;
  83. }
  84. bool BufferedDwarfReader::ReadOffset(bool is_64bit, uint64_t& offset) {
  85. if (is_64bit) {
  86. if (!ReadInt64(offset)) {
  87. return false;
  88. }
  89. } else {
  90. uint32_t tmp;
  91. if (!ReadInt32(tmp)) {
  92. return false;
  93. }
  94. offset = tmp;
  95. }
  96. return true;
  97. }
  98. bool BufferedDwarfReader::ReadAddress(uint8_t address_size, uint64_t& address) {
  99. // Note `address_size` indicates the numbrer of bytes in the address.
  100. switch (address_size) {
  101. case 2: {
  102. uint16_t tmp;
  103. if (!ReadInt16(tmp))
  104. return false;
  105. address = tmp;
  106. } break;
  107. case 4: {
  108. uint32_t tmp;
  109. if (!ReadInt32(tmp))
  110. return false;
  111. address = tmp;
  112. } break;
  113. case 8: {
  114. uint64_t tmp;
  115. if (!ReadInt64(tmp))
  116. return false;
  117. address = tmp;
  118. } break;
  119. default:
  120. return false;
  121. }
  122. return true;
  123. }
  124. bool BufferedDwarfReader::ReadCommonHeader(bool& is_64bit,
  125. uint64_t& length,
  126. uint16_t& version,
  127. uint64_t& offset,
  128. uint8_t& address_size,
  129. uint64_t& end_position) {
  130. if (!ReadInitialLength(is_64bit, length)) {
  131. return false;
  132. }
  133. end_position = position() + length;
  134. if (!ReadInt16(version)) {
  135. return false;
  136. }
  137. if (!ReadOffset(is_64bit, offset)) {
  138. return false;
  139. }
  140. if (!ReadInt8(address_size)) {
  141. return false;
  142. }
  143. return true;
  144. }
  145. bool BufferedDwarfReader::BufferedRead(void* out, const size_t bytes) {
  146. size_t bytes_left = bytes;
  147. while (bytes_left > 0) {
  148. // Refresh the buffer.
  149. if (unconsumed_amount_ == 0) {
  150. if (!base::IsValueInRangeForNumericType<off_t>(next_chunk_start_))
  151. return false;
  152. const ssize_t unconsumed_amount = google::ReadFromOffset(
  153. fd_, buf_, sizeof(buf_), static_cast<off_t>(next_chunk_start_));
  154. if (unconsumed_amount_ <= 0) {
  155. // Read error.
  156. return false;
  157. }
  158. unconsumed_amount_ = static_cast<size_t>(unconsumed_amount);
  159. last_chunk_start_ = next_chunk_start_;
  160. next_chunk_start_ += unconsumed_amount_;
  161. cursor_in_buffer_ = 0;
  162. }
  163. size_t to_copy = std::min(bytes_left, unconsumed_amount_);
  164. memcpy(out, &buf_[cursor_in_buffer_], to_copy);
  165. unconsumed_amount_ -= to_copy;
  166. cursor_in_buffer_ += to_copy;
  167. bytes_left -= to_copy;
  168. }
  169. return true;
  170. }
  171. } // namespace base::debug
  172. #endif