WinDbg: использование нескольких токенов из.foreach для ввода команды
Некоторая справочная информация
Недавно я задал вопрос и получил отличный ответ, используя.foreach. Теперь у меня есть дамп с большим количеством очень больших символов []. я сделал
.logopen c:\mychararrays.log
!dumpheap -type System.Char[]
.logclose
Я удалил все удобочитаемые материалы, такие как сводка и т. Д. Теперь в файле много строк с адресом объекта, таблицей методов и размером:
03d74c88 52b8b680 5570670
042c4cf8 52b8b680 5762890
...
21a1d6e0 52b8b680 6010030
Я уже использовал
.foreach /ps 2 /f (chararray "c:\mychararrays.log") { !do ${chararray} }
для выгрузки объектов.NET, но это не приведет к выводу полного текста char[], только первых 128 символов. И, к сожалению, начало этих символов [] всегда одинаково.
Вопрос
Я хочу сделать что-то вроде
.foreach /f (chararray "c:\mychararrays.log") { du <token 1 of line>+8 L? 0n<token 3 of line> }
для каждой строки, чтобы напечатать полный символ []. По умолчанию WinDbg разделяет токены в строке и обрабатывает их один за другим, поэтому для команды доступен только один токен.
Решение в Notepad++
Я уже решил это путем замены регулярного выражения в Notepad++. Я просто хочу знать, есть ли "родное" решение WinDbg для этого.
Find: ([^ ]*) [^ ]* ([^ ]*).*
Replace: du \1+8 L? 0n\2
И затем запустить результат в виде сценария:
$<c:\mychararrays.log
Примечание: это заняло ОЧЕНЬ много времени, поэтому я решил переключиться на
Find: ([^ ]*) [^ ]* ([^ ]*).*
Replace: .writemem c:\s\1.txt \1+8 L? 0n\2
2 ответа
Попробуйте расширение python для windbg http://pykd.codeplex.com/. С python вы получаете RE, гибкий язык сценариев и быстрое решение ваших проблем
Если вы знаете максимальный размер, вы можете указать этот размер du
и он остановит печать на первом нулевом терминаторе. Например, если я знаю, что максимальное значение равно 10 000 000, то следующие данные печатаются правильно, даже если длина составляет 320 символов:
0:000> du 00000000033495d8 +10 L?0n10000000
00000000`033495e8 "PermissionSetty.PermissionSeting"
00000000`03349628 "Permission, System.Drawing, Vers"
00000000`03349668 "ion=2.0.0.0, Culture=neutral, Pu"
00000000`033496a8 "blicKeyToken=b03f5f7f11d50a3a619"
00000000`033496e8 "34e0899AD9D5DCC1DD9AD23613210290"
00000000`03349728 "0B723CF980957FC4E177108FC607774F"
00000000`03349768 "29E8320E92EA05ECE4E821C0A5EFE8F1"
00000000`033497a8 "645C4C0C93C1AB99285D622CAA652C1D"
00000000`033497e8 "FAD63D745D6F2DE5F17E5EAF0FC4963D"
00000000`03349828 "261C8A12436518206DC093344D5AD293"
00000000`03349868 ""
И вот нулевой терминатор в 00000000`03349868:
0:000> db 00000000`03349868 l2
00000000`03349868 00 00
Так что, хотя я дал диапазон 10 миллионов du
, он знал, чтобы остановиться на первом нулевом терминаторе.
Кстати, это дамп 64-битного процесса, поэтому, возможно, мое смещение в буфер символов отличается от вашего.
Если вам абсолютно необходим фактический размер, то мы можем получить его как смещение от адреса объекта, чтобы вам не нужно было пытаться получить это значение в качестве другого токена. Но надеюсь, что Макс работает для вас.
Хотя это не зависит от каких-либо расширений и т. Д., Это может быть не "нативное" решение, которое вы искали (5+ лет назад, я знаю - я просто буду публиковать для справки), но я верю, что вы После этого можно добиться небольшого учета и тщательного управления псевдорегистрами.
Общая идея заключается в том, что основной блок foreach
Цикл получает каждый токен, запоминает их и использует их, когда все токены для основной обработки сохранены. Что-то вроде следующего скрипта, в котором перечислены загруженные модули, начинающиеся с "ora*" в текущей цели, и указаны их начальный адрес и размер (что недоступно в однострочном / модуле lm
выход):
ad /q startAddress;
ad /q endAddress;
r $t0=0;
.foreach /pS 8 (token {lmn m ora*}) {
r $t0=@$t0 + 1;
.if (@$t0 % 4 == 1) { as ${/v:startAddress} ${token}};
.if (@$t0 % 4 == 2) { as ${/v:endAddress} ${token}};
.if (@$t0 % 4 == 0) {.printf "${token}=%x,%x\n", ${startAddress}, ${endAddress} - ${startAddress}};
}
Как вы, наверное, догадались, главное требование - чтобы в каждой строке было определенно N токенов (4 в моем примере) (или если определенный токен можно идентифицировать как "маркер", это также можно использовать для сброса счетчика I). выполнил модуль арифметики с). То есть, если строки имеют разное количество токенов (из-за пробелов в именах файлов и т. Д.), Это не будет работать без обходного пути.
Копирование-вставка в одну строку:
ad /q startAddress; ad /q endAddress; r $t0=0; .foreach /pS 8 (token {lmn m ora*}) {r $t0=@$t0 + 1; .if (@$t0 % 4 == 1) { as ${/v:startAddress} ${token}}; .if (@$t0 % 4 == 2) { as ${/v:endAddress} ${token}}; .if (@$t0 % 4 == 0) {.printf "${token}=%x,%x\n", ${startAddress}, ${endAddress} - ${startAddress}}; }
Также обратите внимание, что если обрабатываемые токены являются числовыми, использование псевдорегистров вместо псевдонимов несколько упростит задачу, поскольку вы будете избегать идиосинкразий псевдонимов WinDbg! Несмотря на то, что мои токены действительно были числовыми, я использовал здесь псевдонимы, чтобы предоставить более общий пример / шаблон.