风型铸件
Windbg Type Casting
我想在命令窗口中将子类的对象强制转换为 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 的对象,而 Child 继承类父级。
对象示例:
child chld;
返回的错误是
在"
"处键入冲突错误
如果我做一个x mod!*
我会得到一个巨大的列表,在该列表中是
MOD!parent
MOD!child
如果我做一个?? chld
那么对象就会被转储到屏幕上。
我为什么要这样做?好吧,你可以做到
?? chld.childattr++
,所以我想实际做?? ((parent)chld).parentattr++
风帮忙 说:
C++表达式中的符号
在C++表达式中,每个符号都根据其类型进行解释。根据符号所指的内容,它可能被解释为整数、数据结构、函数指针或任何其他数据类型。如果在C++表达式中使用与C++数据类型(如未修改的模块名称)不对应的符号,则会发生语法错误。
所以我认为没有理由我不应该能够将对象类型转换为父数据类型。
我做了很多搜索,但没有任何真正的结果,如果有人能指出我正确的方向,以便我可以阅读为什么这应该或不应该工作,或者我需要做什么才能成功,甚至为什么这不是我应该期望从 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 %dn",
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 ++计算器中解释的表达式
所以为了避免歧义we need to explicitly state that lilsis etc needs to be evaluated as masm expression not as c++ expression because ?? tries to interpret lilsis , somefoo as c++ expression
所以完整的表达将是?? (somefoo *) @@(someotherfoo)
注意 @@ only
足以指示 MASM 表达式,但为了进一步避免歧义,最好指定表达式计算器explicitly like @@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>
这不仅适用于阶级,也适用于types displayed with dt
下面对不同的场景操作 nt!_eprocess 作为示例
LKD> ??((nt!_EPROCESS) @$proc)->图像文件名
Type conflict error at ')->ImageFileName'
LKD> ??((nt!_EPROCESS *) @$proc)->图像文件名
unsigned char [16] 0x86305f14
0x6b 'k'
LKD> ??(字符 *)((nt!_EPROCESS *) @$proc)->图像文件名
char * 0x86305f14
"kd.exe"
LKD> ??(字符 *)((nt!_EPROCESS *) nt)->图像文件名
Couldn't resolve error at 'nt)->ImageFileName'
LKD> ??(字符 *)((nt!_EPROCESS *) @@(nt))->ImageFileName
char * 0x804d7174
""
#FIELD_OFFSET(nt!_EPROCESS , 图像文件名)
long 0n372
lkd> ? 0n372
Evaluate expression: 372 = 00000174
lkd> ? @@c++(#FIELD_OFFSET(nt!_EPROCESS , 图像文件名)) + nt
Evaluate expression: -2142408332 = 804d7174
LKD> ?? @@c++(#FIELD_OFFSET(nt!_EPROCESS , 图像文件名)) + nt
Couldn't resolve error at 'nt'
LKD> ?? @@c++(#FIELD_OFFSET(nt!_EPROCESS , ImageFileName)) + @@(nt)
unsigned int64 0xffffffff`804d7174
lkd>
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 错误处理.将系统错误代码映射到泛型
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 链表的泛型函数remove()与成员函数remove)
- 如何为 C 型字符串数组编写 getter 和 setter?
- C 字符串返回字符串的整数/双精度/长整型值
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 无法在 Arduino 中uint8_t数组转换为无符号长整型数组
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 如何编写将要继承的泛型代码?
- C++17 如何保存泛型可调用对象以供以后使用
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 从.txt文件中读取浮点型数字并在公式中使用它们
- C++泛型类错误,问题出在哪里?
- C++泛型类,单独实现?
- 序列化多晶型接口
- 将参数传递给泛型 lambda 时复制构造函数不正确
- JNI 日期值转换问题,在C++中获取不同的长整型值
- 风型铸件