gpt4 book ai didi

c++ - Windbg类型类型转换

转载 作者:太空狗 更新时间:2023-10-29 20:39:40 26 4
gpt4 key购买 nike

我想在命令窗口的 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++ 数字和运算符下显示我可以从 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 是一个整数。

没用的是

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

chld 是子类的对象,子类继承父类。

对象示例:

child chld;

返回的错误是

Type conflict error at '<EOL>'

如果我执行 x mod!* 我会得到一个巨大的列表,该列表中有

MOD!parent
MOD!child

如果我做一个 ?? chld 然后对象就会被转储到屏幕上。

我为什么要这样做?好吧,你可以做到

?? chld.childattr++ 所以我真的想做 ?? ((parent)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 的期望。

已编辑:添加代码示例。

最佳答案

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

我将你的问题解释为 can pe header be dumped as _eprocess structure

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

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)

注意 @@ only 足以指示 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> ?? ((nt!_EPROCESS) @$proc)->ImageFileName

Type conflict error at ')->ImageFileName'

lkd> ?? ((nt!_EPROCESS *) @$proc)->ImageFileName

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

lkd> ?? (char *)((nt!_EPROCESS *) @$proc)->ImageFileName

char * 0x86305f14
"kd.exe"

lkd> ?? (char *)((nt!_EPROCESS *) nt)->ImageFileName

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

lkd> ?? (char *)((nt!_EPROCESS *) @@(nt))->ImageFileName

char * 0x804d7174
""

<强>?? #FIELD_OFFSET(nt!_EPROCESS, ImageFileName)

long 0n372

会怎样>? 0n372

Evaluate expression: 372 = 00000174

会怎样>? @@c++(#FIELD_OFFSET(nt!_EPROCESS, ImageFileName)) + nt

Evaluate expression: -2142408332 = 804d7174

lkd> ?? @@c++(#FIELD_OFFSET(nt!_EPROCESS, ImageFileName)) + nt

Couldn't resolve error at 'nt'

lkd> ?? @@c++(#FIELD_OFFSET(nt!_EPROCESS, ImageFileName)) + @@(nt)

unsigned int64 0xffffffff`804d7174
lkd>

关于c++ - Windbg类型类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27050080/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com