Дамповый массив строк с использованием команд отладчика Windbg - PullRequest
1 голос
/ 20 мая 2019

Я хотел бы вывести массив управляемых строк в файл, где каждая строка в файле соответствует отдельной строке в массиве.

У меня есть адрес массива, поэтому я начал с:

.foreach (ptr { !da <address> } ) {

}

Как мне .printf строка, если вывод !da выглядит следующим образом:

[0] 000002104816bf00
[1] 000002104816c220
[2] 000002104816c528

1 Ответ

1 голос
/ 20 мая 2019

Да, конечно, это возможно - если вам нравится синтаксис WinDbg ...

Учитывая простую программу, такую ​​как

using System;

namespace DumpStringArray
{
    class Program
    {
        static void Main()
        {
            string[] a = new string[1000];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = "Line "+i;
            }

            Console.WriteLine("Debug now");
            Console.ReadLine();
            Console.WriteLine(a[0]);
        }
    }
}

Сначала мы получим значение локальной переменной a с использованием !clrstack:

0:000> !clrstack -a
[...]
0137ecf8 019e0516 *** WARNING: Unable to verify checksum for DumpStringArray.exe
DumpStringArray.Program.Main() [...\DumpStringArray\DumpStringArray\Program.cs @ 16]
    LOCALS:
        0x0137ed14 = 0x033c241c
        0x0137ed20 = 0x000003e8
        0x0137ed1c = 0x00000000

0137ee98 5cdaebe6 [GCFrame: 0137ee98] 

0:000> !DumpObj /d 033c241c
Name:        System.String[]
MethodTable: 5beb08b8
EEClass:     5ba84fc0
Size:        4012(0xfac) bytes
Array:       Rank 1, Number of elements 1000, Type CLASS (Print Array)
Fields:
None
0:000>

Если вы распечатаете этот массив, вы увидите, что в нем содержится куча текста перед фактическим списком элементов:

0:000> !DumpArray /d 033c241c
Name:        System.String[]
MethodTable: 5beb08b8
EEClass:     5ba84fc0
Size:        4012(0xfac) bytes
Array:       Rank 1, Number of elements 1000, Type CLASS
Element Methodtable: 5beafd60
[0] 033c4a98
[1] 033c4ad0
[2] 033c4b08
[...]

Давайтеподсчитать количество токенов до начала списка:

  1. Name:
  2. System.String[]
  3. MethodTable:
  4. 5beb08b8
  5. EEClass:
  6. 5ba84fc0
  7. Size:
  8. 4012(0xfac)
  9. bytes
  10. Array:
  11. Rank
  12. 1,
  13. Number
  14. of
  15. elements
  16. 1000,
  17. Type
  18. CLASS
  19. Element
  20. Methodtable:
  21. 5beafd60
  22. [0]

Следовательно, вам нужно /pS 0n22 в цикле .foreach, чтобы пропустить их.

Далее вам нужно /ps 0n1 чтобы пропустить все остальные индексы массива.

Команда пока чтобудет .foreach /pS 0n22 /ps 0n1 (str {!da <address>}) { }.

Теперь строка .NET имеет заголовок, поэтому фактическое содержимое строки начинается не с адреса, а несколько позже:

0:000> !do 033d42a4
Name:        System.String
MethodTable: 5beafd60
EEClass:     5ba84e90
Size:        30(0x1e) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Line 999
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
5beb1bc0  400027b        4         System.Int32  1 instance        8 m_stringLength
5beb07a8  400027c        8          System.Char  1 instance       4c m_firstChar
5beafd60  4000280       60        System.String  0   shared   static Empty
    >> Domain:Value  01408b18:NotInit  <<

Как вы можетевидите, смещение первого символа 8.

Мы можем использовать du для отображения строк Unicode с заданным смещением, поэтому команда теперь:

.foreach /pS 0n22 /ps 0n1 (str {!da <address>}) { du ${str}+8 }

К сожалению, это выведет адрес и текст:

0:000> .foreach /pS 0n22 /ps 1 (str {!da 033c241c}){du ${str}+8}
033c4aa0  "Line 0"
033c4ad8  "Line 1"
033c4b10  "Line 2"
[...]

Так что да, вам нужно .printf, чтобы исправить это:

.foreach /pS 0n22 /ps 1 (str {!da 033c241c}){.printf "%mu\n", (${str}+8)}

Теперь, это работает на 32 бит.Я оставляю для вас 64-битную миграцию.

Используйте .logopen перед тем, чтобы открыть текстовый файл, и .logclose после этого.

...