Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.2 KiB

  1. /*++
  2. Copyright (c) 1990-2001 Microsoft Corporation
  3. Module Name:
  4. kdmove.c
  5. Abstract:
  6. This module contains code to implement the portable kernel debugger
  7. memory mover.
  8. Author:
  9. Mark Lucovsky (markl) 31-Aug-1990
  10. Revision History:
  11. --*/
  12. #include "kdp.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGEKD, KdpQuickMoveMemory)
  15. #pragma alloc_text(PAGEKD, KdpCopyMemoryChunks)
  16. #endif
  17. VOID
  18. KdpQuickMoveMemory (
  19. IN PCHAR Destination,
  20. IN PCHAR Source,
  21. IN ULONG Length
  22. )
  23. /*++
  24. Routine Description:
  25. This routine does the exact same thing as RtlCopyMemory, BUT it is
  26. private to the debugger. This allows folks to set breakpoints and
  27. watch points in RtlCopyMemory without risk of recursive debugger
  28. entry and the accompanying hang.
  29. N.B. UNLIKE KdpCopyMemoryChunks, this routine does NOT check for
  30. accessibility and may fault! Use it ONLY in the debugger and ONLY
  31. where you could use RtlCopyMemory.
  32. Arguments:
  33. Destination - Supplies a pointer to destination of the move operation.
  34. Source - Supplies a pointer to the source of the move operation.
  35. Length - Supplies the length of the move operation.
  36. Return Value:
  37. None.
  38. --*/
  39. {
  40. while (Length > 0) {
  41. *Destination = *Source;
  42. Destination++;
  43. Source++;
  44. Length--;
  45. }
  46. }
  47. NTSTATUS
  48. KdpCopyMemoryChunks(
  49. ULONG64 Address,
  50. PVOID Buffer,
  51. ULONG TotalSize,
  52. ULONG ChunkSize,
  53. ULONG Flags,
  54. PULONG ActualSize OPTIONAL
  55. )
  56. /*++
  57. Routine Description:
  58. Copies memory to/from a buffer to/from a system address.
  59. The address can be physical or virtual.
  60. The buffer is assumed to be valid for the duration of this call.
  61. Arguments:
  62. Address - System address.
  63. Buffer - Buffer to read from or write to.
  64. TotalSize - Number of bytes to read/write.
  65. ChunkSize - Maximum single item transfer size, must
  66. be 1, 2, 4 or 8.
  67. 0 means choose a default.
  68. Flags - MMDBG_COPY flags for MmDbgCopyMemory.
  69. ActualSize - Number of bytes actually read/written.
  70. Return Value:
  71. NTSTATUS
  72. --*/
  73. {
  74. ULONG Length;
  75. ULONG CopyChunk;
  76. NTSTATUS Status;
  77. ULONG64 AddressStart = Address;
  78. if (ChunkSize > MMDBG_COPY_MAX_SIZE) {
  79. ChunkSize = MMDBG_COPY_MAX_SIZE;
  80. } else if (ChunkSize == 0) {
  81. // Default to 4 byte chunks as that's
  82. // what the previous code did.
  83. ChunkSize = 4;
  84. }
  85. //
  86. // MmDbgCopyMemory only copies a single aligned chunk at a
  87. // time. It is Kd's responsibility to chunk up a larger
  88. // request for individual copy requests. This gives Kd
  89. // the flexibility to pick a chunk size and also frees
  90. // Mm from having to worry about more than a page at a time.
  91. // Additionally, it is important that we access memory with the
  92. // largest size possible because we could be accessing
  93. // memory-mapped I/O space.
  94. //
  95. Length = TotalSize;
  96. CopyChunk = 1;
  97. while (Length > 0) {
  98. // Expand the chunk size as long as:
  99. // We haven't hit the chunk limit.
  100. // We have enough data left.
  101. // The address is properly aligned.
  102. while (CopyChunk < ChunkSize &&
  103. (CopyChunk << 1) <= Length &&
  104. (Address & ((CopyChunk << 1) - 1)) == 0) {
  105. CopyChunk <<= 1;
  106. }
  107. // Shrink the chunk size to fit the available data.
  108. while (CopyChunk > Length) {
  109. CopyChunk >>= 1;
  110. }
  111. Status = MmDbgCopyMemory(Address, Buffer, CopyChunk, Flags);
  112. if (!NT_SUCCESS(Status)) {
  113. break;
  114. }
  115. Address += CopyChunk;
  116. Buffer = (PVOID)((PUCHAR)Buffer + CopyChunk);
  117. Length -= CopyChunk;
  118. }
  119. if (ActualSize)
  120. {
  121. *ActualSize = TotalSize - Length;
  122. }
  123. //
  124. // Flush the instruction cache in case the write was into the instruction
  125. // stream. Only do this when writing into the kernel address space,
  126. // and if any bytes were actually written
  127. //
  128. if ((Flags & MMDBG_COPY_WRITE) &&
  129. Length < TotalSize) {
  130. #if defined(_IA64_)
  131. KeSweepCurrentIcacheRange((PVOID)AddressStart, TotalSize - Length);
  132. #else
  133. KeSweepCurrentIcache();
  134. #endif
  135. }
  136. return Length != 0 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
  137. }