Windbg - <HRESULT 0x80004002>, неверное приведение, псевдоним как против aS - PullRequest
0 голосов
/ 27 марта 2019

Добрый день,

У меня есть скрипт Windbg, который перебирает кадры стека, используя цикл .do.Для каждого кадра он использует !for_each_local и $spat ("@#Local","foo"), чтобы соответствовать вещам, которые меня интересуют, чтобы получить начальный взгляд.Затем я использую dx @$t2 =, чтобы назначить и, наконец, распечатать то, что мне интересно, то есть dx @$t2 = ((foobase*) this)->m_current->m_name - в основном это работает нормально.

Время от времени будет this вкадр, который не может быть успешно отлит с помощью dx, так что он выглядит как barbase, а не foobase ... dx выглядит нормально, потому что я завернул его в .foreach (output { dx @$t2 = ((foobase*) this)->m_current->m_name }) {}, поэтомув конечном итоге содержит что-то , что приводит к завершению сценария (несмотря на попытку .catch).

Сначала я не совсем понял, что происходит, но делал .printf "%ma\n", @$t2 помог мне убедиться, что содержимое <HRESULT 0x80004002>, которое, как мне кажется, , подразумевает недопустимое приведение - что, если так, имеет смысл.Моя строка сценария использует foobase, когда потребуется barbase.

Если Я прав, то я ищу способ проверить это, прежде чем углубитьсядалее в сценарий и попытаемся получить доступ к деталям, которые, как я знаю, приведут к его завершению.

Я кажется придумал запутанный способ сделать это ... но я хотелспросите, было ли что-нибудь лучше ...

.frame 0a     $$ a frame with barbase, not foobase
dx @$t2 = ((foobase*) this)->m_name
.printf "%ma\n", @$t2     $$ prints <HRESULT 0x80004002>
as /c CastCheck .printf "%ma", @$t2
.if ($spat(@"${CastCheck}","<HRESULT 0x80004002>") = 1) { .printf "yes" } .else { .printf "no" }     $$ prints yes

Есть ли способ проверить, содержит ли $t2 индикатор неверного приведения без использования псевдонима?

Я спрашиваю это, потому что с помощьюпсевдоним вызвал у меня большую путаницу ... в моем скрипте (чтобы он работал, и он, кажется, работает довольно хорошо), мне пришлось использовать aS вместо as (я могу использовать as отличноиз окна командной строки, и я не совсем понимаю , почему мне нужно перейти на aS после прочтения документации), а также мне нужно завершить строку точкой с запятой (в отличие от любой другой строкив моем скрипте) и мне нужно использовать ad /q CastCheck; непосредственно перед aS, а затем быстро кормитьнаоборот, в противном случае псевдоним, кажется, теряется, так или иначе ... так что вы можете сказать, что использование этого псевдонима доставило мне немного хлопот.

Итак, есть ли a) anпростой способ предварительно проверить, является ли то, на что я смотрю, foobase или barbase, или b) после проверки после попытки приведения, содержит ли $t2 это <HRESULT 0x80004002>?Если я сделаю .printf "%d", @$t2, он покажет 5 ... 5 тоже что-то представляет?

Или, действительно, любые другие идеи (или вопросы).

РЕДАКТИРОВАТЬ:

Я собираюсь попробовать и проиллюстрировать, что я имею в виду с 2 короткими прогонами кода, выполненного в командном окне ... где кадр 00 содержит thisчто можно привести к foobase, а затем. printf работает хорошо, и где кадр 0a содержит this, то есть barbase (но мой сценарий все еще не ожидает этого, и яхочу быть в состоянии обслужить это) ... dx все еще помещает что-то в $t10 ... Я хочу быть в состоянии обнаружить, что это мусор (или предварительно обнаружить, я не должен 'даже попробуйте dx, если this равно barbase, так как это бессмысленно, и я все равно не заинтересован в этом).

0:038> .frame 00
00 00000006`3e2bc930 00007ffe`926293a8 BlahBlahBlah 
0:038> dx @$t10 = ((foobase *) this)->m_name
@$t10 = ((foobase *) this)->m_name                 : 0x869c7b8 : "nice string" [Type: char *]
0:038> .printf "%ma\n", @$t10
nice string

Здесь this является barbase, и даже не имеет m_name:

0:038> .frame 0a
0a 00000006`3e2bd220 00007ffe`91ec7780 BlahBlahBlah 
0:038> dx @$t10 = ((foobase *) this)->m_name
@$t10 = ((foobase *) this)->m_name                 : 0x2265646f00000005 : "--- memory read error at address 0x2265646f`00000005 ---" [Type: char *]
0:038> .printf "%ma\n", @$t10
<HRESULT 0x80004002>

При помещении в цикл я обнаружил, что сценарий завершится с Memory access error в кадре 0a, когда я попытаюсь проверитьдлина струны I believe должна быть возвращена dx.

По существу, во втором блоке я хочу либо проверить $t10 на то, что не хорошая строка (вероятно, это <HRESULT 0x80004002>?) или, что еще лучше, вообще не делал dx и .printf, потому что я мог до этого проверить, что this был barbase, а не foobase.

Это имеет больше смысла, или я должен начать снова?

Ответы [ 2 ]

1 голос
/ 28 марта 2019

хорошо, что вы пытались, но это все еще расплывчато

Вы можете объяснить, что необходимо сделать .frame
и затем dx this ??

вы можете привести любой адрес к любому типу

, например, при первом запуске я приведу это к правильному типу и перечислю все кадры

при следующем запуске.Я преобразую в фиктивный тип и перечисляем

в обоих этих только один кадр имеет указатель this

, когда это правильный тип, он возвращает правильный член

, когда он является фиктивнымхорошо, он возвращает фиктивные вещи

0:000> !for_each_frame dx ((Student *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20] 
((Student *) this)->Name                 : 0x7ff7282153e0 : "dave" [Type: char *]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33] 
Error: Unable to bind name 'this'

он нашел это, но он не может найти имя члена

0:000> !for_each_frame dx ((ntdll!_EPROCESS *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20] 
Error: Unable to bind name 'Name' <<<<<<
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33] 
Error: Unable to bind name 'this' 

кстати вы знаете, какой тип это указатель, так почему вы его приводите???

Вы можете найти тип этого ptr с помощью различных команд, некоторые из которых показаны ниже

0:000> dx this
this                 : 0xc5d6f6f910 [Type: Student *] <<<
    [+0x000] Roll             : 1 [Type: int]
    [+0x008] Name             : 0x7ff7282153e0 : "dave" [Type: char *]
    [+0x010] Marks            : 72.300000 [Type: double]


0:000> ?? this 
class Student * 0x000000c5`d6f6f910  <<<
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 


0:000> x /t this
000000c5`d6f6f8f0 class Student * this = 0x000000c5`d6f6f910  <<<


0:000> x /v /t this
prv local  000000c5`d6f6f8f0    8 class Student * this = 0x000000c5`d6f6f910

0:000> dt this 
Local var @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 


0:000> dt /v this 
Local var [AddrFlags 90  AddrOff 0000000000000030  Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 
   <function> Student     void (
    int, 
    char*, 
    double)+000000c5`d6f6f910
   <function> PrintStudent     void ( void )+000000c5`d6f6f910

0:000> dt /v /t this 
Local var [AddrFlags 90  AddrOff 0000000000000030  Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 
   <function> Student     void (
    int, 
    char*, 
    double)+000000c5`d6f6f910
   <function> PrintStudent     void ( void )+000000c5`d6f6f910
0 голосов
/ 28 марта 2019

добавление другого ответа, чтобы подчеркнуть использование javascript вместо синтаксического анализа текста

Поддержка сценариев javascript была добавлена ​​в windbg quiet давно, и она значительно улучшается

(чтобы попробоватьпоследние добавления javascript используют предварительный просмотр windbg в последней версии windows 10)

x / v / t или dv / t предоставляет тип указателя this

javascript предоставляет свойство targetType для этих объектов

вот как его использовать

создать файл .js foo.js с содержанием ниже

function typethis ( somevar ) 
{
    host.diagnostics.debugLog( somevar.targetType ,  "\t" , JSON.stringify(somevar) , "\n"  )
}

в windbg do

.load jsprovider
.scriptload x:\..\\..\foo.js
dx @$scriptcontents.functionname(argument) to run the script

и результаты будут

0:000> .load jsprovider
0:000> .scriptload f:\wdscr\typthis.js
JavaScript script successfully loaded from 'f:\wdscr\typthis.js'
0:000> dx @$scriptContents.typethis( this )
Student *   {"Roll":1,"Name":{},"Marks":72.3}
@$scriptContents.typethis( this )
...