【问题标题】:Windbg Type CastingWindbg型铸造
【发布时间】:2014-11-20 21:40:11
【问题描述】:

我想在 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 是一个 int。

没用的是

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

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

对象示例:

child chld;

返回的错误是

”处的类型冲突错误

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

MOD!parent
MOD!child

如果我执行?? chld,那么对象就会很好地转储到屏幕上。

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

?? chld.childattr++ 所以我想实际做?? ((parent)chld).parentattr++

windbg 帮助说:

C++ 表达式中的符号

在 C++ 表达式中,每个符号都根据其类型进行解释。根据符号所指的内容,它可能被解释为整数、数据结构、函数指针、或任何其他数据类型。如果在 C++ 表达式中使用与 C++ 数据类型不对应的符号(例如未修改的模块名称),则会出现语法错误。

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

我做了很多搜索,但没有真正找到任何东西,如果有人能指出我正确的方向,以便我可以了解为什么这应该或不应该工作,或者我需要做什么才能成功甚至为什么这不是我对 WinDbg 的期望。

已编辑:添加代码示例。

【问题讨论】:

    标签: c++ windbg


    【解决方案1】:

    code、sn-p 或任何在其他机器上在某种程度上可重现的东西都可以提供更可靠、更清晰的答案,而不是枯燥的理论问题

    我将您的问题解释为可以将 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++ 求值器中解释的表达式

    为了避免歧义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)

    notice @@ only 足以指示 masm 表达式,但为了进一步避免歧义,指定表达式评估器 explicitly like @@masm( , @@c++( 等是一个好习惯

    见下单? on 类指针返回一个地址和一个 ??返回类型

    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)->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
    

    lkd> ? 0n372

    Evaluate expression: 372 = 00000174
    

    lkd> ? @@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++ 自定义类。
    • 是的,Thomas W. 在我所问的问题上是正确的。我将编辑问题并添加示例。感谢您对 Blabb 的回复。
    • 在我的原始答案中添加了一些可重现的编辑,看看是否有帮助
    • 感谢 blabb,?? (parent *)@@masm(chld) 正是我想要的。
    • 感谢 blabb 跟进并发布带有源代码的酷示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多