none
Executing functions for native debugger visualizers autoexp.dat (stringview, preview)

    Question

  • I am trying to improve the visualization of some existing and custom data types while debugging native C++ code. I am using autoexp.dat and Visual Studio 2008.

    Is it possible to execute functions in the stringview and preview sections of the [Visualizer] types? Every time I try, I get "...", blank, or nothing (i.e, the expression reverts to the standard {} list of members). However, the children section appears to be able to execute functions at least some of the time. The first time the debugger stops, I get

    CXX0001: Error: error attempting to execute user function

    but after stepping at least once, I can reevaluate the function with the refresh button in the Watch window, and the function will execute.

    Examples:

    Assume there's a function, _print_int(), that looks like:

     

    unsigned int WINAPI _print_int()
    {
    	static unsigned int q = 42;
    	return q++;
    }
    
    
    Now we have a BSTR, which might have embedded NULLs, so it is useful to be able to see the full length:

     

     

    ATL::CComBSTR{
    	preview (
    [$e.m_str,su]
    )
    stringview (
    #([$e.m_str,sub], "

    len=", [(*(((unsigned long *)($e.m_str))-1))/2,u], "
    raw=", [$e.m_str,mu], "
    inttest1=", [_print_int], "
    inttest2=",
    [_print_int()]
    )
    )
    children (
    #(
    SysStringLen: [$e.Length()],
    len: [(*(((unsigned long *)($e.m_str))-1))/2,u],
    [inttest1]: [_print_int],
    [inttest2]: [_print_int()],
    [addin]: [$ADDIN(eeaddin.dll,AddIn_SystemTime)],
    #array (
    expr: $e.m_str[$i],
    size: (*(((unsigned long *)($e.m_str))-1))/2
    )
    )
    )
    }

     

    In the case of a BSTR with L"abc\0defghij" (including an embedded NULL), stringview shows:

     

    abc
    
    len=10
    raw=0x0044c8ac 0061 0062 0063 0000 0064 0065 0066 0067 abc.defg
    inttest1=0x00072070
    inttest2=...

    Notice that inttest1 is a raw memory address, and inttest2 is ..., which means that it can't be evaluated.

     

    In contrast, in the children section, we see:

     

    -		strWhatever	"abc"	ATL::CComBSTR
    SysStringLen CXX0001: Error: error attempting to execute user function
    (error) 0 int
    [inttest1] 0x00072070 _print_int(void) unsigned int (void)
    [inttest2] CXX0001: Error: error attempting to execute user function
    len 10 unsigned long
    [0] 97 L'a' wchar_t
    ...

     

    However, after stepping, the CXX0001 errors can be re-evaluated. Then we see:

     

    -		strWhatever	"abc"	ATL::CComBSTR
    		SysStringLen	10	unsigned int
    		(error)	0	int
    		[inttest1]	0x00072070 _print_int(void)	unsigned int (void)
    		[inttest2]	43	unsigned int
    		len	10	unsigned long
    		[0]	97 L'a'	wchar_t
    ...
    In other words, children call the appropriate function, but stringview does not. Is there another way to do it?

     

    Note that the (error) 0 appears to be due to the $ADDIN() syntax, which does not seem to work. If there is a way to call debugger add-ins in [Visualizer] as one can in [AutoExp], please let me know...

    Monday, September 6, 2010 9:19 PM

All replies

  • Hi SeanTek,

    The ADDIN() syntax in your script needs to be adjusted. The syntax I know is of the below format:
        $ADDIN(DllName,FunctionDecoratedName)
    Below is a sample:
        $ADDIN(MyDbgEE.dll,?EE_MyClass@@YGJKPAUtagDEBUGHELPER@@HHPADIK@Z)

    You could get more about how to use this syntax from the document below:
    http://msdn.microsoft.com/en-us/library/aa730838(VS.80).aspx

    To get the function decorated name, you could use a listing or the DUMPBIN tool. You could get more about them from:
    http://msdn.microsoft.com/en-us/library/5x49w699(v=VS.71).aspx

    Let me know if this helps or not.
    Aland Li

    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    Tuesday, September 7, 2010 12:24 PM
    Moderator
  • Hi Aland,

    My syntax is correct. It looks like VS will use GetProcAddress() with whatever name you provide there. In my case, I specifically specified the export symbol with the following combination:

    module .def file:

    EXPORTS
        AddIn_SystemTime
        AddIn_FileTime
        AddIn_Whatever

     

    source:

    extern "C" ADDIN_API HRESULT WINAPI AddIn_SystemTime( ... )

    where ADDIN_API is __declspec(dllexport) and WINAPI is __stdcall.

    Note that the eeaddin sample on MSDN is wrong, and will cause a stack alignment exception. The calling convention should be declared __stdcall (aka WINAPI), not __cdecl. I found this out by trial and error.

    I think that the module .def file (without __declspec(dllexport)) is sufficient to specify whatever export symbol you want--in this case a basic string, "AddIn_SystemTime". If you leave it with __declspec(dllexport) but keep it extern "C", the default symbol looks more like _AddIn_SystemTime@28 or something (due to the stdcall convention). If it is not extern "C" then you will probably get the decorated name that you mention.

    Tuesday, September 7, 2010 11:38 PM
  • Hi SeanTek,

    You said: In other words, children call the appropriate function, but stringview does not. Is there another way to do it?
    Do you mean [_print_int()] or something else?

    You said: Note that the (error) 0 appears to be due to the $ADDIN() syntax
    The error is caused by the statement below:
     len: [(*(((unsigned long *)($e.m_str))-1))/2,u],
    I cannot see it is related to the add-in function. Could you please explain more?

    On the other hand, the statements where the CXX0001 error appears are below:
    SysStringLen: [$e.Length()],
    [inttest2]: [_print_int()],
    The parameters all end with '()', such as '_print_int()', I think this causes the error.

    By the way, you could type the add-in function in the watch window or the immediate window to run it. This testing can show if the function has errors.

    Regards,
    Aland Li

    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com

     




    Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
    Wednesday, September 8, 2010 12:53 PM
    Moderator
  • Thanks Aland for the response.

     

    Hi SeanTek,

    You said: In other words, children call the appropriate function, but stringview does not. Is there another way to do it?
    Do you mean [_print_int()] or something else?

    Yes, I mean [_print_int()]. Specifically, my intention is to be able to call a function during the rendering of stringview or preview, passing some argument to it so that I can see the computed output at a glance. The most useful application here is seeing the contents of a string, such as a BSTR, that contains embedded NULLs. The string visualizers automatically stop at NULLs but with a function I can pass a different string with the NULLs replaced, so that the visualizer will keep on going.

    The error is caused by the statement below: len: [(*(((unsigned long *)($e.m_str))-1))/2,u], I cannot see it is related to the add-in function. Could you please explain more?

    Yes. The expression that I provided above for len is supposed to calculate the length of a BSTR, which is stored in the 4 bytes (ULONG or UINT) prior to the start of the string. As you can see in the blob of autoexp.dat code, there is a line that says:
    len 10 unsigned long
    and that is the correct result.

    There is another line, however:
    (error) 0 int
    From my testing, I have only seen that line when you write an expression like:
    [addin]: [$ADDIN(eeaddin.dll,AddIn_SystemTime)],
    mainly due to the $ADDIN syntax, which does not appear to be recognized by the autoexp.dat processor. Note that in the output there is no "addin" element.

    By the way, you could type the add-in function in the watch window or the immediate window to run it. This testing can show if the function has errors.

    Do you mean the $ADDIN (which executes in devenv.exe), or the _print_int() (which executes in the debugged process)? I did not know that you could type $ADDIN(...) in the Watch window; I will give it a try and report back.

    Saturday, September 18, 2010 5:11 PM