Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Windbg, how can I list the values of an enumeration while debugging?

Usually, enum values are simple compiler-incremented values or are set directly to an integral literal, and so the values can be deduced easily or seen directly by looking at the source file.

However, sometimes enum values are used to set an in-class constant equal to a value defined elsewhere or to the result of a compile-time expression that isn't easily duplicated.

Is there a way to get Windbg to show me the actual value of each enum member for those trickier cases?

like image 756
Kurt Hutchinson Avatar asked Jun 05 '13 17:06

Kurt Hutchinson


1 Answers

Consider this small struct:

struct foo
{
    enum enum1
    {
        enum1_val1_ = 5,
        enum1_val2_,
    };

    enum enum2
    {
        enum2_val1_ = 0x0001,
        enum2_val2_ = 0x0010,
    };

    enum
    {
        // assume these come from complicated compile-time expressions
        some_class_constant_ = 86, 
        another_one_ = 99,
    };
};

The fastest way is to use the dt command, using switches -r (recurse, which you need to list the enum members) and -v (verbose, which you need to list enums at all):

0:000> dt -r -v foo
LangTestingD!foo
struct foo, 3 elements, 0x1 bytes
Enum enum1,  2 total enums
      enum1_val1_ = 0n5
      enum1_val2_ = 0n6
Enum enum2,  2 total enums
      enum2_val1_ = 0n1
      enum2_val2_ = 0n16
Enum <unnamed-tag>,  2 total enums
      some_class_constant_ = 0n86
      another_one_ = 0n99

You can see that it lists the values of each enum, even the unnamed one. Multiple unnamed enums will all be listed correctly.

The problem with dt -r -v foo is that it lists every single member of foo: all data members, all function members, all enums, and it tries to recurse into each one and lists its members. If foo is a complex class, which is rather easy to get with inheritance, the output will be huge, and it'll be difficult to find that one enum you're looking for.

So the next option is to tell dt which enum you want, specifically:

0:000> dt foo::enum1
LangTestingD!foo::enum1
   enum1_val1_ = 0n5
   enum1_val2_ = 0n6

Okay, great! But how about that unnamed enum? Well, you say, check out the output above, where it uses <unnamed-tag>. Maybe we can use that.

0:000> dt foo::<unnamed-tag>
Couldn't resolve error at 'foo::<unnamed-tag>'

It actually will work, but you need to use a couple extra switches. When you combine -n (following parameter is a name) and -y (match the next parameter as a name prefix) then it, sort of, works:

0:000> dt -n -y foo::<unnamed-tag>
LangTestingD!foo::<unnamed-tag>
   some_class_constant_ = 0n86

However, only the first value is listed. Even worse, if there are multiple unnamed enums, only the first value of the first one is listed. Often this will be enough, as multiple unnamed enums isn't too common, but if you absolutely need them, you'll have to use -r -v and just find them in the output.

like image 160
Kurt Hutchinson Avatar answered Sep 28 '22 02:09

Kurt Hutchinson