c – Windbg型铸造

我想在命令窗口中输入一个子类的对象到WinDbg中的父类.

示例类

class parent
{
public:
    int a;
    int b;
    parent(){ a = 10; b = 10; }
    parent(int c) : a(a){}
};

class child : public parent
{
public:
    int a;
    int b;
    child(){ a = 20; b = 20; }
    child(int d) : b(d){}
};

我正在使用Windbg,我正在阅读帮助文件.它在C Numbers和Operators下显示我可以从WinDbg命令窗口执行以下类型转换:

dynamic_cast <type>(Value) 
static_cast <type>(Value) 
reinterpret_cast <type>(Value) 
const_cast <type>(Value)
(type) Value

所以我输入Windbg命令窗口:

?? (type) Value

有效的是

?? (char)a
?? static_cast<char>(a)

其中a是int.

什么不起作用

?? (parent)chld
?? static_cast<parent>(chld)
?? static_cast<mod!parent>(chld)

其中chld是类child的对象,child继承class parent.

对象示例:

child chld;

返回的错误是

Type conflict error at ‘<EOL>’

如果我做一个x mod!*我得到一个巨大的列表,在那个列表中

MOD!parent
MOD!child

如果我做了??然后将对象转移到屏幕上就好了.

我为什么要这样做?那么你可以做到

?? chld.childattr所以我想实际做? ((父)CHLD).parentattr

windbg帮助说:

Symbols in C++ Expressions

In a C++ expression, each symbol is interpreted according to its type. Depending on what the symbol refers to, it might be interpreted as an integer, a data structure, a function pointer, or any other data type. If you use a symbol that does not correspond to a C++ data type (such as an unmodified module name) within a C++ expression, a syntax error occurs.

所以我认为没有理由不能将对象强制转换为父数据类型.

我做了很多搜索,没有真正想到这个,如果有人可以指出我正确的方向,以便我可以阅读为什么这应该或不应该工作,或者我需要做什么才能取得成功,甚至为什么这不是我应该期待的WinDbg.

编辑:添加代码示例.

解决方法:

代码,片段或在其他机器中可以在某种程度上重现的任何东西可以提供更强大和清晰的答案,而不是干燥的理论问题

我将你的问题解释为类型可以将pe头转储为_eprocess结构

如果是这样你可以做这样的事情

lkd> ?? (char *)@$proc->ImageFileName
char * 0x866be194
 "windbg.exe"
lkd> lm m windbg
start    end        module name
01000000 01097000   windbg     (pdb symbols)          
lkd> db windbg l10
01000000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
lkd> da windbg+4e 
0100004e  "This program cannot be run in DO"
0100006e  "S mode....$"
lkd> ?? (char *)((nt!_EPROCESS *) @@masm(windbg - 174+4e) )->ImageFileName
char * 0x0100004e
 "This program cannot be run in DOS mode....$"

虽然仍然处于亏损状态,但此编辑是针对编辑过的问题

演练的完整来源
你的父类略微修改,以消除未引用的参数警告和输出歧义,并在函数main中使用

:\>type parchiltst.cpp
#include <stdio.h>
class parent
{
public:
    int a;
    int b;
    parent(){ a = 35; b = 28; }
    parent(int c) : a(c){}
};
class child : public parent
{
public:
    int a;
    int b;
    child(){ a = 20; b = 20; }
    child(int d) : b(d){}
};
int main (void) {
    parent par,papa,mama,gramp;
    child  chill,bigbro,lilsis,crybab;
    par.a=70;par.b=65;chill.a=4;chill.b=8;
    gramp=parent(par); papa=parent(); mama=parent(1234);
    bigbro=child(chill);lilsis=child();crybab=child(5678);
    printf("%d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\n",
        chill.a,chill.b,gramp.a,gramp.b,papa.a,papa.b,mama.a,mama.b,
        bigbro.a,bigbro.b,lilsis.a,lilsis.b,crybab.a,crybab.b);
    return 0;
}

编译,链接和执行以显示输出

:\>cl /Zi /nologo /W4 /analyze parchiltst.cpp /link /RELEASE
parchiltst.cpp

:\>parchiltst.exe
4  8  70  65  35  28  1234  0  4  8  20  20  196608  5678 `

在windbg下加载它并踩到printf以便所有当地人
正确初始化

:\>cdb parchiltst.exe

0:000> g main
parchiltst!main:
00401000 55              push    ebp
0:000> dv -V -t -i
prv local  0013ff18 @ebp-0x60 class child lilsis = class child
prv local  0013ff28 @ebp-0x50 class parent par = class parent
prv local  0013ff30 @ebp-0x48 class parent gramp = class parent
prv local  0013ff38 @ebp-0x40 class parent papa = class parent
prv local  0013ff40 @ebp-0x38 class parent mama = class parent
prv local  0013ff48 @ebp-0x30 class child chill = class child
prv local  0013ff58 @ebp-0x20 class child bigbro = class child
prv local  0013ff68 @ebp-0x10 class child crybab = class child
0:000> .lines
Line number information will be loaded
0:000> l+*
0:000> p
>   19:     parent par,papa,mama,gramp;
0:000>
>   20:     child  chill,bigbro,lilsis,crybab;
0:000>
>   21:     par.a=70;par.b=65;chill.a=4;chill.b=8;
0:000>
>   22:     gramp=parent(par); papa=parent(); mama=parent(1234);
0:000>
>   23:     bigbro=child(chill);lilsis=child();crybab=child(5678);
0:000>
>   26:         bigbro.a,bigbro.b,lilsis.a,lilsis.b,crybab.a,crybab.b);

使用c exp评估程序评估所有本地人员

0:000> !for_each_local "?? @#Local"
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n4
   +0x00c b                : 0n8
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n4
   +0x00c b                : 0n8
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n2090270496
   +0x00c b                : 0n5678
class parent
   +0x000 a                : 0n70
   +0x004 b                : 0n65
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n20
   +0x00c b                : 0n20
class parent
   +0x000 a                : 0n1234
   +0x004 b                : 0n0
class parent
   +0x000 a                : 0n35
   +0x004 b                : 0n28
class parent
   +0x000 a                : 0n70
   +0x004 b                : 0n65

单独检查

0:000> ?? ((child *) @@masm(mama))->a
int 0n35
0:000> ?? ((parent *) @@masm(mama))->a
int 0n1234
0:000> ?? ((parent *) @@masm(papa))->a
int 0n35
0:000> ?? ((child *) @@masm(papa))->a
int 0n1234
0:000> ?? ((child *) @@masm(lilsis))->a
int 0n20
0:000> ?? ((parent *) @@masm(lilsis))->a
int 0n35
0:000> ?? ((parent *) @@masm(lilsis))
class parent * 0x0013ff18
   +0x000 a                : 0n35
   +0x004 b                : 0n28
0:000> ?? ((child *) @@masm(lilsis))
class child * 0x0013ff18
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n20
   +0x00c b                : 0n20
0:000> ?? ((child *) @@masm(mama))
class child * 0x0013ff40
   +0x000 a                : 0n1234
   +0x004 b                : 0n0
   +0x008 a                : 0n35
   +0x00c b                : 0n28
0:000> ?? ((parent *) @@masm(mama))
class parent * 0x0013ff40
   +0x000 a                : 0n1234
   +0x004 b                : 0n0
0:000>

一系列可能导致解决方案的问题和答案

我们想要展示什么?

a pointer to a class

什么是班级

somefoo

所以在c表达式求值程序中显示指向somefoo的指针

?? (somefoo *) should be used

指针需要一个地址或一个求值为地址的表达式

lilsis,papa,somefoo等是可以在masm和c评估器中解释的表达式

所以为了避免歧义,我们需要明确说明lilsis等需要被评估为masm表达式而不是c表达式,因为??试图解释lilsis,somefoo作为c表达式
所以完整的表达将是?? (somefoo *)@@(someotherfoo)

通知@@仅足以表示masm表达式,但为了进一步避免歧义,明确指定表达式评估器是一个好习惯,如@@ masm(,@@ c(等等)

看下面一个?类指针返回一个地址和??返回类型

0:000> ? mama
Evaluate expression: 1310528 = 0013ff40
0:000> ?? mama
class parent
   +0x000 a                : 0n1234
   +0x004 b                : 0n0
0:000> ?? lilsis
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n20
   +0x00c b                : 0n20
0:000> ? lilsis
Evaluate expression: 1310488 = 0013ff18
0:000> ?? @@(mama)
unsigned int64 0x13ff40
0:000> ?? @@masm(mama)
unsigned int64 0x13ff40
0:000> ?? @@c++(mama)
class parent
   +0x000 a                : 0n1234
   +0x004 b                : 0n0
0:000> ?? @@c++(crybab)
class child
   +0x000 a                : 0n35
   +0x004 b                : 0n28
   +0x008 a                : 0n2090270496
   +0x00c b                : 0n5678
0:000>

这不仅适用于类,也适用于使用dt显示的类型

作为示例,nt!_eprocess在下面针对不同的场景进行操作

LKD&GT ?? ((nt!_EPROCESS)@ $proc) – > ImageFileName

Type conflict error at ')->ImageFileName'

LKD&GT ?? ((nt!_EPROCESS *)@ $proc) – > ImageFileName

unsigned char [16] 0x86305f14
0x6b 'k'

LKD&GT ?? (char *)((nt!_EPROCESS *)@ $proc) – > ImageFileName

char * 0x86305f14
 "kd.exe"

LKD&GT ?? (char *)((nt!_EPROCESS *)nt) – > ImageFileName

Couldn't resolve error at 'nt)->ImageFileName'

LKD&GT ?? (char *)((nt!_EPROCESS *)@@(nt)) – > ImageFileName

char * 0x804d7174
 ""

?? #FIELD_OFFSET(nt!_EPROCESS,ImageFileName)

long 0n372

LKD&GT ? 0n372

Evaluate expression: 372 = 00000174

LKD&GT ? @@ c(#FIELD_OFFSET(nt!_EPROCESS,ImageFileName))nt

Evaluate expression: -2142408332 = 804d7174

LKD&GT ?? @@ c(#FIELD_OFFSET(nt!_EPROCESS,ImageFileName))nt

Couldn't resolve error at 'nt'

LKD&GT ?? @@ c(#FIELD_OFFSET(nt!_EPROCESS,ImageFileName))@@(nt)

unsigned int64 0xffffffff`804d7174
lkd> 
上一篇:c – 如何从启用了优化的二进制文件(发布模式)中分析崩溃转储?


下一篇:c – .pdb中的函数地址与.exe不同,为什么?