Reputation: 33
I would like to type cast an object of a child class to a parent class in WinDbg at the command window.
Example classes
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){}
};
I am using Windbg and I was reading through the help file. It shows under C++ Numbers and Operators that I can do the following typecastings from the WinDbg command window:
dynamic_cast <type>(Value)
static_cast <type>(Value)
reinterpret_cast <type>(Value)
const_cast <type>(Value)
(type) Value
So I would type in the Windbg command window:
?? (type) Value
What works is
?? (char)a
?? static_cast<char>(a)
where a is an int.
What doesn't work is
?? (parent)chld
?? static_cast<parent>(chld)
?? static_cast<mod!parent>(chld)
where chld is an object of class child and child inherits class parent.
object example:
child chld;
The error returned is
Type conflict error at '<EOL>'
If I do a x mod!*
I get a giant list, in that list are
MOD!parent
MOD!child
If I do a ?? chld
then the object gets dumped to the screen just fine.
Why I would want to do this? Well you can do
?? chld.childattr++
and so I would like to actually do ?? ((parent)chld).parentattr++
The windbg help says:
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.
So I see no reason I shouldn't be able to type cast an object to a parent data type.
I did a lot of searching and nothing really came up for this, if someone could point me in the right direction so that I could read about why this should or shouldn't work or maybe what I need to do to be successful or even why this is not something I should expect from WinDbg.
Edited: To add code example.
Upvotes: 3
Views: 4694
Reputation: 9007
code , snippet or anything that is reproducible to some extent in other machines can provide a more robust and clear answers instead of dry theoretical question
i interpret your question to be of the type can pe header be dumped as _eprocess structure
if so you can do some thing like this
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....$"
though still at loss this edit is in response to edited question
full source for walkthrough your parent class slightly modified to eliminate unreferenced parameter warning and output ambiguity and used inside function 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;
}
compiled ,linked and executed to show output
:\>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 `
loading it under windbg and stepping upto printf so that all locals are properly initialised
:\>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);
evaluating all locals with c++ exp evaluator
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
checking individually
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 trail of questions and answers that may lead to solutions
what do we want to display ?
a pointer to a class
what is the type of class
somefoo
so to display a pointer to somefoo in c++ expression evaluator
?? (somefoo *) should be used
a pointer needs an address or an expression that evaluates to an address
lilsis, papa , somefoo etc are expressions that can be interpreted in both masm and c++ evaluators
so to avoid ambiguity 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
so the full expression will be ?? (somefoo *) @@(someotherfoo)
notice @@ only
is sufficient to indicate a masm expression but to further avoid ambiguity it is a good habit to specify expression evaluators explicitly like @@masm( , @@c++(
and so forth
see below a single ? on class pointer returns an address and a ?? return the type
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>
this applies not just to class but also to types displayed with dt
nt!_eprocess is manipulated below for different scenerios as an example
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>
Upvotes: 5