capture_memory.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2016 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "snapshot/capture_memory.h"
  15. #include <stdint.h>
  16. #include <windows.h>
  17. // dbghelp must be after windows.h.
  18. #include <dbghelp.h>
  19. #include <iterator>
  20. #include <limits>
  21. #include <memory>
  22. #include "base/logging.h"
  23. #include "snapshot/memory_snapshot.h"
  24. namespace crashpad {
  25. namespace internal {
  26. namespace {
  27. void MaybeCaptureMemoryAround(CaptureMemory::Delegate* delegate,
  28. uint64_t address) {
  29. constexpr uint64_t non_address_offset = 0x10000;
  30. if (address < non_address_offset)
  31. return;
  32. const uint64_t max_address = delegate->Is64Bit() ?
  33. std::numeric_limits<uint64_t>::max() :
  34. std::numeric_limits<uint32_t>::max();
  35. if (address > max_address - non_address_offset)
  36. return;
  37. constexpr uint64_t kRegisterByteOffset = 128;
  38. const uint64_t target = address - kRegisterByteOffset;
  39. constexpr uint64_t size = 512;
  40. static_assert(kRegisterByteOffset <= size / 2,
  41. "negative offset too large");
  42. auto ranges =
  43. delegate->GetReadableRanges(CheckedRange<uint64_t>(target, size));
  44. for (const auto& range : ranges) {
  45. delegate->AddNewMemorySnapshot(range);
  46. }
  47. }
  48. template <class T>
  49. void CaptureAtPointersInRange(uint8_t* buffer,
  50. uint64_t buffer_size,
  51. CaptureMemory::Delegate* delegate) {
  52. for (uint64_t address_offset = 0; address_offset < buffer_size;
  53. address_offset += sizeof(T)) {
  54. uint64_t target_address = *reinterpret_cast<T*>(&buffer[address_offset]);
  55. MaybeCaptureMemoryAround(delegate, target_address);
  56. }
  57. }
  58. } // namespace
  59. // static
  60. void CaptureMemory::PointedToByContext(const CPUContext& context,
  61. Delegate* delegate) {
  62. #if defined(ARCH_CPU_X86_FAMILY)
  63. if (context.architecture == kCPUArchitectureX86_64) {
  64. MaybeCaptureMemoryAround(delegate, context.x86_64->rip);
  65. MaybeCaptureMemoryAround(delegate, context.x86_64->rax);
  66. MaybeCaptureMemoryAround(delegate, context.x86_64->rbx);
  67. MaybeCaptureMemoryAround(delegate, context.x86_64->rcx);
  68. MaybeCaptureMemoryAround(delegate, context.x86_64->rdx);
  69. MaybeCaptureMemoryAround(delegate, context.x86_64->rdi);
  70. MaybeCaptureMemoryAround(delegate, context.x86_64->rsi);
  71. MaybeCaptureMemoryAround(delegate, context.x86_64->rbp);
  72. MaybeCaptureMemoryAround(delegate, context.x86_64->r8);
  73. MaybeCaptureMemoryAround(delegate, context.x86_64->r9);
  74. MaybeCaptureMemoryAround(delegate, context.x86_64->r10);
  75. MaybeCaptureMemoryAround(delegate, context.x86_64->r11);
  76. MaybeCaptureMemoryAround(delegate, context.x86_64->r12);
  77. MaybeCaptureMemoryAround(delegate, context.x86_64->r13);
  78. MaybeCaptureMemoryAround(delegate, context.x86_64->r14);
  79. MaybeCaptureMemoryAround(delegate, context.x86_64->r15);
  80. // Note: Shadow stack region is directly captured.
  81. } else {
  82. MaybeCaptureMemoryAround(delegate, context.x86->eip);
  83. MaybeCaptureMemoryAround(delegate, context.x86->eax);
  84. MaybeCaptureMemoryAround(delegate, context.x86->ebx);
  85. MaybeCaptureMemoryAround(delegate, context.x86->ecx);
  86. MaybeCaptureMemoryAround(delegate, context.x86->edx);
  87. MaybeCaptureMemoryAround(delegate, context.x86->edi);
  88. MaybeCaptureMemoryAround(delegate, context.x86->esi);
  89. MaybeCaptureMemoryAround(delegate, context.x86->ebp);
  90. }
  91. #elif defined(ARCH_CPU_ARM_FAMILY)
  92. if (context.architecture == kCPUArchitectureARM64) {
  93. MaybeCaptureMemoryAround(delegate, context.arm64->pc);
  94. for (size_t i = 0; i < std::size(context.arm64->regs); ++i) {
  95. MaybeCaptureMemoryAround(delegate, context.arm64->regs[i]);
  96. }
  97. } else {
  98. MaybeCaptureMemoryAround(delegate, context.arm->pc);
  99. for (size_t i = 0; i < std::size(context.arm->regs); ++i) {
  100. MaybeCaptureMemoryAround(delegate, context.arm->regs[i]);
  101. }
  102. }
  103. #elif defined(ARCH_CPU_MIPS_FAMILY)
  104. for (size_t i = 0; i < std::size(context.mipsel->regs); ++i) {
  105. MaybeCaptureMemoryAround(delegate, context.mipsel->regs[i]);
  106. }
  107. #elif defined(ARCH_CPU_RISCV_FAMILY)
  108. if (context.architecture == kCPUArchitectureRISCV) {
  109. for (size_t i = 0; i < std::size(context.riscv->regs); ++i) {
  110. MaybeCaptureMemoryAround(delegate, context.riscv->regs[i]);
  111. }
  112. } else {
  113. for (size_t i = 0; i < std::size(context.riscv64->regs); ++i) {
  114. MaybeCaptureMemoryAround(delegate, context.riscv64->regs[i]);
  115. }
  116. }
  117. #else
  118. #error Port.
  119. #endif
  120. }
  121. // static
  122. void CaptureMemory::PointedToByMemoryRange(const MemorySnapshot& memory,
  123. Delegate* delegate) {
  124. if (memory.Size() == 0)
  125. return;
  126. const size_t alignment =
  127. delegate->Is64Bit() ? sizeof(uint64_t) : sizeof(uint32_t);
  128. if (memory.Address() % alignment != 0 || memory.Size() % alignment != 0) {
  129. LOG(ERROR) << "unaligned range";
  130. return;
  131. }
  132. std::unique_ptr<uint8_t[]> buffer(new uint8_t[memory.Size()]);
  133. if (!delegate->ReadMemory(memory.Address(), memory.Size(), buffer.get())) {
  134. LOG(ERROR) << "ReadMemory";
  135. return;
  136. }
  137. if (delegate->Is64Bit())
  138. CaptureAtPointersInRange<uint64_t>(buffer.get(), memory.Size(), delegate);
  139. else
  140. CaptureAtPointersInRange<uint32_t>(buffer.get(), memory.Size(), delegate);
  141. }
  142. } // namespace internal
  143. } // namespace crashpad