Giter Site home page Giter Site logo

concordextensibilitysamples's Introduction

ConcordExtensibilitySamples

Visual Studio Debug Engine Extensibility Samples

What are "Concord Extensibility Samples"?

Concord is the code name for Visual Studio's new debug engine that first shipped in Visual Studio 2012. Concord was designed to be extensible and this repo contains samples of these extensions.

The samples in this repo currently target Visual Studio 2022 (version 17.0). For older versions of these samples, please see the VS16 branch.

Getting started

For Concord documentation, take a look at the wiki:

If you want to dive right into some code for extending the debug engine, take a look at the samples:

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

concordextensibilitysamples's People

Contributors

calgagi avatar capfei avatar gregg-miskelly avatar microsoft-github-policy-service[bot] avatar mmitche avatar plnelson avatar wardengnaw avatar xisui-msft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

concordextensibilitysamples's Issues

Exception information "view details"

One thing that seems to be lost when using the concord api (and can also be seen in the iris sample by adding this to the entry point (just to trigger one):

movesMade := 0;
movesMade := movesMade / movesMade;

is the lack of "view details" when having an exception:
image

When using the C# debugger there's an extra "View Details"

(and I think the locals don't show the exception info either)

Missing contract name on launch settings

Hi,

I'm trying to replicate the Iris sample on my VS extension. After hitting the Start button for debug I'm getting this error:

2017-09-11_15-51-17

Any hints on what is this?
Thanks!

How can I add a new struct and use different Visualizer to show up it and FILETIME?

I have runned CppCustomVisualizer successfully and added a struct(named StructTest),I can add function in _EntryPoint.cpp to show up text I declared. But now I have some problems:
FILETIME also changed and I don’t know how to distinguish it from my struct.
image
Now I want to show date and time when the struct Is FILETIME and show text I declared when the struct is StructTest. How can I do this?

GetExpression

Is there an way we can use it like dte2.Debugger.GetExpression?

For example, I'd like to get the return string of "objA.FunctionReturnString(3)".
How to use Concord to do it instead of use dte2.Debugger.GetExpression("objA.FunctionReturnString(3)")?

Thanks!

Information on conditional breakpoints is missing

the concord sample is quite complete and works well, but lacks information on conditional breakpoints. In our language trying to set a conditional breakpoint shows:
"Elements does not support conditional breakpoints"

in the breakpoint dialog; there doesn't seem to be a callback before this happens.

Is is actually possible to perform function evaluation in IDkmRuntimeBreakpointNotification?

I am trying to evaluate a C++ expression with a function call when the runtime breakpoint hits, but the evaluation never completes.

In a debug monitor component, I capture the stack frame data and send it to an IDE component:

void IDkmRuntimeBreakpointNotification.OnRuntimeBreakpoint(DkmRuntimeBreakpoint runtimeBreakpoint, DkmThread thread, bool hasException, DkmEventDescriptorS eventDescriptor)
{
    var process = thread.Process;

    thread.GetCurrentFrameInfo(out ulong retAddr, out ulong frameBase, out ulong vframe);

    var data = new SupportBreakpointHitMessage
    {
        breakpointId = runtimeBreakpoint.UniqueId,
        threadId = thread.UniqueId,
        retAddr = retAddr,
        frameBase = frameBase,
        vframe = vframe
    };

    DkmCustomMessage.Create(process.Connection, process, MessageToLocal.guid, MessageToLocal.supportBreakpointHitNotification, data.Encode(), null).SendHigher();
}

in the IDE component (tested levels 1999000 and 9995000) IDkmCustomMessageCallbackReceiver.SendHigher I try to execute an expression:

const int CV_ALLREG_VFRAME = 0x00007536;
var vFrameRegister = DkmUnwoundRegister.Create(CV_ALLREG_VFRAME, new ReadOnlyCollection<byte>(BitConverter.GetBytes(data.vframe)));
var registers = thread.GetCurrentRegisters(new[] { vFrameRegister });
var instructionAddress = process.CreateNativeInstructionAddress(registers.GetInstructionPointer());
DkmStackWalkFrame frame = DkmStackWalkFrame.Create(thread, instructionAddress, data.frameBase, 0, DkmStackWalkFrameFlags.None, null, registers, null);

var inspectionSession = DkmInspectionSession.Create(process, null);

string expression = $"sethook(0x{stateAddress:x}, 0x{processData.helperHookFunctionAddress_5_1:x}, 7, 0)";

var compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp);
var language = DkmLanguage.Create("C++", compilerId);
var languageExpression = DkmLanguageExpression.Create(language, DkmEvaluationFlags.None, expression, null);
var inspectionContext = DkmInspectionContext.Create(inspectionSession, frame.RuntimeInstance, thread, 2000, DkmEvaluationFlags.None, DkmFuncEvalFlags.None, 10, language, null);
var workList = DkmWorkList.Create(null);

DkmSuccessEvaluationResult result = null;

inspectionContext.EvaluateExpression(workList, languageExpression, frame, res =>
{
    if (res.ErrorCode == 0)
    {
        result = res.ResultObject as DkmSuccessEvaluationResult;

        res.ResultObject.Close();
    }
});

workList.Execute();

workList.Execute(); call never returns.
If the same evaluation is performed in a IDkmCallStackFilter.FilterNextFrame there are no issues with it.
Expressions without function evaluations can also be successfully performed with this code in IDkmCustomMessageCallbackReceiver.SendHigher.

Documentation for IDkmRuntimeBreakpointNotification.OnRuntimeBreakpoint tells that:

When this
notification is called, the target process is stopped and implementers are
able to either inspect the process or cause it to execute in a controlled
manner (slip, func-eval).

Is this really true?

Performance problem, when a lot of local variables.

Hello, the debugger I am implementing must deal with up to 3 000 local variables, sometimes even more. Each variable is an object containing some information that will be displayed in the Visual Studio « Locals » window. So my Expression Compiler generate the PE, as described here https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/CLR-Expression-Evaluators, containing up to 3 000 methods (1 for each variable), where each of this methods returns a custom object. The problem is when the debugger enters IDkmClrResultProvider.GetResult method, all the 3000 methods from PE are already evaluated, which takes a lot of time for some reason. I noticed that the debugger spends about 12-15 seconds (on my Intel-i7 laptop) between the end of IDkmClrExpressionCompiler.GetClrLocalVariableQuery method and the start of IDkmClrResultProvider.GetResult method on every Debug Step Over. Is it possible to make this evaluation lazy? Because the list of the variables is so long, in the Visual Studio locals windows they are not all visible at once, the user has to Scroll Down/Up to see the rest of the variables. Similar lazy evaluation already exists when displaying arrays in the IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext, DkmWorkList workList, int startIndex, int count, DkmCompletionRoutine completionRoutine) method, where only the COUNT number of variables are displayed. Is there anything I can do, like implementing some additional interfaces in order to improve the performance of the debugger?

Vladimir.

How to add a custom VisualizerId?

hi,i have runned CppCustomVisualizer successfully and i have read the wiki. But I am still confused about VisualizerId in CppCustomVisualizer.natvis and can not add a new customvisualizer myself. hope to get answers for these following questions.

  1. "FILETIME" is a class, but why there is a "_" before FILETIME.
    `

`

2.VisualizerId is generate by ourself, so can i regenerate it and replace it in CppCustomVisualizer.natvis and CppCustomVisualizer.vsdconfigxml? I replaced it and the project can not work correctlly.

3.If I want to add a new type "Struct A{ int a1; int b1;} and show a1 in debug window" ,How to modify the CppCustomVisualizer.natvis and CppCustomVisualizer.vsdconfigxml? if i add a Implements tag,the project will build failed ">CppCustomVisualizer.vsdconfigxml(44,8): error XAC1000:"

`


<Class Name="CCppCustomVisualizerService" ClassId="{9535F50E-1738-4AE2-8507-5207C44B8261}" WorkerProcessSupported="true">

  <Implements>
    <InterfaceGroup>
      <Filter>
        <!--NOTE: This VisualizerId is also used in the .natvis file.-->
        <VisualizerId RequiredValue="8E723FD7-611E-40E7-98C0-624D8873F559"/>
      </Filter>
      <Interface Name="IDkmCustomVisualizer"/>
    </InterfaceGroup>
  </Implements>

  <Implements>
    <InterfaceGroup>
      <NoFilter/>
      <Interface Name="IDkmCallStackFilter"/>
    </InterfaceGroup>
  </Implements>

</Class>
`

thanks

Problem handling exceptions with the C# HelloWorld sample

Hi,

I tried to run the HelloWorld C# sample. When I debug a program, everything works fine, I can see the [HelloWorld] frame, but whenever my program hits an exception, I get the exception assistant (if enabled, otherwise I get the standard exception system) twice (one with the exception as "thrown", one for the exception as "unhandled"), but when I press F5 on the second, the program does not terminate, it like stays there and go on, hit the exception again (thrown+unhandled), and again, and again indefinitely. I can stop debugging without problem, but the behavior is clearly not the same as usual.

Is this normal? Am i supposed to do something like terminate the process/instance/thread using the API?

Debugger UI integration

We have created support for the ExpressionCompile, Formatter and FrameDecoder for our custom .Net langage (X#) based on the examples in this repo. That was very helpfull.
We have now also added some new toolwindows in the Debugger, that are correctly only shown when the debugger runs.
The UI component uses a ToolWindow with a ToolWindowPane and a control that is a XAML userControl.
On that control we have a ListView with several columns (like in the Watch, Locals and Breakpoints windows). We noticed a problem that when we apply the VS Theme then the headers of the Listview are not shown. When we remove the theming then the headers are shown but not in the expected color of course.
I have two questions:

  • Are the other windows also created this way. If so, what have they done to make the headers visible?
  • If they are not implemented like this, how can I then use the same underlying controls for the lists on the built-in debugger windows?

I hope someone here can answer this or if someone can tell me in which VS component these windows are implemented (so I can inspect them to see how these are created)

Bug in CCppCustomVisualizerService::FiletimeToText() function

When trying out the CppCustomVisualizer project in Visual Studio 2019 in order to try to make my own visualizer for CTime I found that the debugger always showed "Invalid Value" for a FILETIME value. After debugging the code it turned out that the function CCppCustomVisualizerService::FileTimeToText() does not perform as it should if the if the length for the date format (from GetDateFormatW()) is longer than the length for the time format (from GetTimeFormatW()) as it is for me. I am in Sweden and my locale length for the date is 10 characters (2019-12-25) and 8 characters for the time (13:26:49).

This is because the cch variable is used to get the length needed for both the date and time string and then also used to tell GetDateFormatW() how much space to use, which is the value for the previous call to GetTimeFormatW(), which is then to short for the date.

Change the function like this and it will work when the length for the time string is shorter than the date string also:

`HRESULT CCppCustomVisualizerService::FileTimeToText(const FILETIME& fileTime, CString& text)
{
text.Empty();

SYSTEMTIME systemTime;
if (!FileTimeToSystemTime(&fileTime, &systemTime))
{
    return WIN32_LAST_ERROR();
}

// Deterime how much to allocate for the date
int cchDate; // Length needed for the date
cchDate = GetDateFormatW(
    GetThreadLocale(),
    DATE_SHORTDATE,
    &systemTime,
    nullptr,
    nullptr,
    0
    );
if (cchDate == 0)
{
    return WIN32_LAST_ERROR();
}

int allocLength = cchDate
    - 1 // To convert from a character count (including null terminator) to a length
    + 1; // For the space (' ') character between the date and time

// Deterime how much to allocate for the time
int cchTime; // Length needed for the time
cchTime = GetTimeFormatW(
    GetThreadLocale(),
    /*flags*/0,
    &systemTime,
    nullptr,
    nullptr,
    0
    );
if (cchTime == 0)
{
    return WIN32_LAST_ERROR();
}

allocLength += (cchTime - 1); // '-1' is to convert from a character count (including null terminator) to a length
CString result;
LPWSTR pBuffer = result.GetBuffer(allocLength);

// Add the date
int cch;
cch = GetDateFormatW(
    GetThreadLocale(),
    DATE_SHORTDATE,
    &systemTime,
    nullptr,
    pBuffer,
    cchDate   // Use length for date here instead of the returnvalue from
                    // the previous GetTimeFormatW() call.
    );
if (cch == 0)
{
    return WIN32_LAST_ERROR();
}

pBuffer += (cch-1); // '-1' is to convert from a character count (including null terminator) to a length
int remainaingLength = allocLength - (cch-1);

// Add a space between the date and the time
if (remainaingLength <= 1)
{
    return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
*pBuffer = ' ';
pBuffer++;
remainaingLength--;

// Add the time
cch = GetTimeFormatW(
    GetThreadLocale(),
    /*flags*/0,
    &systemTime,
    nullptr,
    pBuffer,
    remainaingLength + 1 // '+1' is for null terminator
    );
if (cch == 0)
{
    return WIN32_LAST_ERROR();
}

result.ReleaseBuffer();
text = result;

return S_OK;

}`

/Ruben

Adding code showing how to add Child items

It would be really useful to add some more functionnality to CppCustomVisualizer, to bootstrap adding custom child views. Maybe two of them.

Very simply, the two custom child items could be "Date" and "Time". Both are combined into the root item visualisation, but could be made available as custom children for the purpose of demoing the right way to do it.

That would add great value to this excellent sample.

Recent VsDbg versions missing System.Threading.Tasks.dll assembly

We're hitting a problem with our VsDbg EE extension where we see a load fail on this assembly. It looks like at some point in the VsDbg releases this assembly from the shared framework was removed from the VsDbg releases. It's quite hard to track VsDbg changes so it's tricky to know for sure when this change occurred.

A workaround is to copy from say /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.14/System.Threading.Tasks.dll to the vsdbg folder.
I think the issue is likely that .NET Standard 2.0 doesn't generate a reference to this assembly but earlier versions of .NET Standard 1.x do. Equally targeting .NET 6 seems to require this reference.
We can resolve this ourselves by retargeting to .NET Standard 2.0 but is there any possibility of putting this shared framework assembly back into VsDbg releases? And is there somewhere that lists significant changes for VsDbg? I know GetVsDbg.sh can pick versions but it would be useful to have more information on what has changed in them for example.

Method Chaining in Practice?

Hey,

first of all thank you for these descriptions and examples, in the last few days I was repeatedly amazed by the remarkable extensibility of VS throughout its many iterations. However, skimming through the vsdebugeng.h header, I cannot find any lead on how to attempt the "method chaining" part in the actual interface specifications (referring to https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Component-discovery-and-configuration#method-chaining).

Could you clarify how exactly one would have to go about in order to partly extend existing debugging functionalty, say for example, an expression compiler/evaluator that translates custom expression syntax to native C++ expressions that can be compiled by the built-in evaluators?

Since an additional input parameter of the next evaluator in the chain seems to be forbidden by the interface specifications, are you supposed to retrieve the other implementations from the context in some way?

Thanks!

Dataset Visualizer not showing

When writing a custom debugger the DataSet visualizer doesn't load and says:

  • Could not load this custom viewer.

There are no exceptions or errors in the debug output. Is there anything special needed to get that going?

Wiki missing info - Obtaining the Concord API headers

This page mentions 2 ways to get the headers and libs: the Visual Studio Extensibility workload and nuget.
https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Obtaining-the-Concord-API-headers,-libraries,-etc

I'm using the first method and that page doesn't describe how to actually reference the headers and libs from a C++ project. I can find the files in paths below, but they are not part of the set of resolved paths in a default C++ project.

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Inc
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Lib\x64
etc

Nor do I see any new macros that include VSSDK or VisualStudioIntegration paths. It's not clear to me what the intended way to get at those files is. I can use $(VsInstallDir) and manually add the header and lib dirs I need. Is that the intended way?

Additional Include Directories: $(VSInstallDir)VSSDK\VisualStudioIntegration\Common\Inc
Additional Library Directories: $(VSInstallDir)VSSDK\VisualStudioIntegration\Common\Lib\$(PlatformTarget)

C# implemented IDkmCustomVisualizer broken in worker processes in VS 2019

We are using a C++ visualizer which visualized the class content to DataTip using IDkmCustomVisualizer. The extension is written in C# and worked beautiful in VS 2017. Since we switched to VS 2019 it stopped working due to new mechanism introduced in VS 2019 (external process).

I was studying the C++ extension example. Unfortunately I was not able to get it work. Apparently change my vsdconfigxml WorkerProcessSupported="true" is not enough. If I disable the Load debug symbols in external process (native only) option my extension starts to work. However our project is huge and we like the new external process.

Unfortunately without a guidance/example/tutorial I don't know how to update my extension. Could you point me to some project from which I can decipher how to get this work?

Thanks for any help,
Csaba

HelloWorld Cs sample doesn't build in VS 2019 Community

HelloWorld project doesn't have any Visual Studio SDK references, so it fails to find them:

1>Build started 24-Apr-20 9:50:28.
1>GenerateTargetFrameworkMonikerAttribute:
1>Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
1>CoreCompile:
1>  L:\dev\VS2019\MSBuild\Current\Bin\Roslyn\csc.exe /noconfig /nowarn:1701,1702,2008 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva+ /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.dll" /debug+ /debug:full /filealign:512 /optimize- /out:obj\Debug\HelloWorld.dll /ruleset:"L:\dev\VS2019\Team Tools\Static Analysis Tools\\Rule Sets\AllRules.ruleset" /subsystemversion:6.00 /target:library /utf8output /langversion:7.3 HelloWorldDataItem.cs _HelloWorldService.cs Properties\AssemblyInfo.cs "C:\Users\User\AppData\Local\Temp\.NETFramework,Version=v4.5.AssemblyAttributes.cs"
1>  Using shared compilation with compiler from directory: L:\dev\VS2019\MSBuild\Current\Bin\Roslyn
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\HelloWorldDataItem.cs(4,17,4,29): error CS0234: The type or namespace name 'VisualStudio' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\HelloWorldDataItem.cs(5,17,5,29): error CS0234: The type or namespace name 'VisualStudio' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(4,17,4,29): error CS0234: The type or namespace name 'VisualStudio' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(5,17,5,29): error CS0234: The type or namespace name 'VisualStudio' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\HelloWorldDataItem.cs(31,40,31,51): error CS0246: The type or namespace name 'DkmDataItem' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(16,38,16,57): error CS0246: The type or namespace name 'IDkmCallStackFilter' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(20,29,20,48): error CS0246: The type or namespace name 'IDkmCallStackFilter' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(20,65,20,80): error CS0246: The type or namespace name 'DkmStackContext' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(20,95,20,112): error CS0246: The type or namespace name 'DkmStackWalkFrame' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(20,9,20,26): error CS0246: The type or namespace name 'DkmStackWalkFrame' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\_HelloWorldService.cs(20,29,20,48): error CS0538: 'IDkmCallStackFilter' in explicit interface declaration is not an interface
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\HelloWorldDataItem.cs(51,53,51,68): error CS0246: The type or namespace name 'DkmStackContext' could not be found (are you missing a using directive or an assembly reference?)
1>L:\dev\vs_extensions\ConcordExtensibilitySamples\HelloWorld\Cs\dll\HelloWorldDataItem.cs(69,61,69,76): error CS0246: The type or namespace name 'DkmStackContext' could not be found (are you missing a using directive or an assembly reference?)
1>
1>Build FAILED.

You have to add a reference to
<Reference Include="Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />

Registering and loading Concord extensions on Linux .NET Core vsdbg

I'm trying to get my language extension to load alongside other Concord extensions under vsdbg on .NET Core for Linux. The remote process debugging works great, but without the language-specific functionality there are locals that would be nonsensical to external users. Is there a straightforward path to implementation or perhaps documentation?

It looks like there is a JSON file to map language names, language GUIDs, and vendor GUIDs in the vs2022 directory on Linux. I tried updating that and supplying my assemblies + vsdconfig, but there is not much output or error feedback that I have discovered to help guide what is working or not working.

CppCustomVisualizer doesn't work when building x64 config (following instructions)

Step 3 here says to build Debug x64. However, this does not appear to work. Building Debug x86 does work as expected. Might just be a typo in the instructions since the Build-x64.targets file implies the solution is expected to build in x86.

When I build and launch Debug x64 it appears to work, but there's no custom visualization and I can't put breakpoints in CppCustomVisualizer code.
image

Presumably this is because the vsix is not set to build in this configuration. If I attempt to build the vsix project explicitly I get an error because it's trying to copy x86 output that doesn't exist.

Error VSSDK1025 Could not add the file 'D:\Dev\ConcordExtensibilitySamples\CppCustomVisualizer\Debug\x86\CppCustomVisualizer.vsdconfig' to the zip package 'D:\Dev\ConcordExtensibilitySamples\CppCustomVisualizer\Debug\CppCustomVisualizer.vsix'. Could not find a part of the path 'D:\Dev\ConcordExtensibilitySamples\CppCustomVisualizer\Debug\x86\CppCustomVisualizer.vsdconfig'. vsix D:\Dev\ConcordExtensibilitySamples\CppCustomVisualizer\vsix\VSSDK 1

image

Commit 1e5dec7 (since I'm using 2019 and not 2022)
Windows 21H2 19044.1415
Microsoft Visual Studio Community 2019 Version 16.11.8
Visual Studio extension development workload is installed
Microsoft Child Process Debugging Power Tool is installed

Query expressions and use of temporary locals in real func-eval

It's difficult to provide a repro for this, but I'm hoping a debugger expert may have some insight into this problem.

Say, I have a generated query expression that requires the use of a temporary local. In my case this is a byte[]. I pass this into two methods that exist in the debuggee process. The first method will update the individual bytes in the byte[]. However, it seems that the second method does not get the data updated by the first. This only appears to happen if using a temporary local - my experiments show that if I use a real local the func eval succeeds. Interesting if I force execution by the VIL interpreter (applying , emulator format specifier) the evaluation also returns the correct IL. The func eval will also succeed if the query expression and methods used return the byte[] rather than just pass it by value. Does anyone know whether this is a bug or just something that won't work?

Here's some example IL which I hope illustrates this:

class public '<>x'
{
.method public hidebysig static string '<>m0'()
{
.locals init (uint8[] _REAL_LOCAL_0) // Real data in user program
.locals init (object _REAL_LOCAL_1) // Real data in user program
ldc.i4.6
newarr uint8 // Constructed for use by the Query Expression
.locals init (uint8[] _TEMP_LOCAL_2) // Added as a temp for use by query expression
stloc.2
ldarg.0
ldfld int16 'num_00000225'
ldloc.2 // If instead of this I use REAL_LOCAL_0, the query works correctly
ldc.i4.0
ldc.i4.5
call void 'StoreInByteArray'(int32, uint8[], int32, int32) // When doing a real func-eval, the byte[] is modified by this method, but the updated data never returned in this temp byte[]
ldloc.2
ldc.i4.0
ldc.i4.6
call string 'FormatAsString'(uint8[], int32, int32) // This just has a sequence of null bytes
ret
.maxstack 4
}

Unable to load custom VsDbg extensions in linux/WSL using VS 17.7 Preview

Using VS 17.7 Preview 1, WSL/Ubuntu linux 22.04. .NET Runtime 6.0.16. VsDbg version.txt 17.6.10401.3 commit:2b6b7003009fd737853b727ff5723629d01c281d

Start WSL debugging from VS gives an immediate fail about launching the debug adapter.

Running ./vsdbg/vsdbg from the linux box gives:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.SpanHelpers.IndexOf(Char ByRef, Char, Int32)
at System.String.Ctor(Char*)
at VsDbg.EntryPoint.GetAssemblyDirectories(IntPtr)
at VsDbg.EntryPoint.Initialize(IntPtr)
Aborted

It seems that any directory specified in a .link file for VsDbg extensions (e.g. ~/.dotnet/vsdbg-extensions/any.link) will cause this fail as long as the .link file contains a valid absolute directory (the directory itself can be totally empty) so I'm not sure this issue is anything to do with the VsDbg extension itself.

Any help with diagnosing the issue appreciated!

How to use IDkmCustomMessageForwardReceiver?

it is stated in documentation that IDkmCustomMessageForwardReceiver can be "Implemented by components that want to receive custom messages from the IDE". Can you provide and example hot send message from Visual Studio?
Or at least which function should be used for this?

IDkmClrExpressionCompiler bug/limitation of the generated MSIL

When generating the MSIL file to get the locals variables, based on the doc from here https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/CLR-Expression-Evaluators, I found a bug/limitation.
The documentation says and I quote:

“locals of the query method match the arguments and locals of the method we are evaluating in”

But what if the MSIL needed to compute a variable is very complex and requires additional local variables? A natural solution to bypass this limitation is to use a call an intermediate function that does all necessary work. So the code would look something like that:

.class public QueryClass 
{
  .method public hidebysig static int32 M1(int32 arg1, int32 arg2) cil managed
   {
      .locals init ([0]int32 local1, [1]string local2)
      ldarg.0
      call int32 QueryClass::MyMethod(int32 arg)
      ret
   }
   .method public hidebysig static int32 MyMethod(int32 arg)
   {
       ldarg.0
       ret
   }
}

The code above works fine (If I didn’t make a typo when writing it). But when I try to do something more complex in my MyMethod sometimes it fails and I can’t understand why. Now let’s look at 2 cases where it fails for the reasons I don’t understand:

  1. To somehow debug I created a logger that uses a TextWriter class to write to some file. The call to the logger looks something like
     ldstr "my Log message"
     call void [LoggerLib] TmpLogger::Log(class [mscorlib]System.String)

When I place the call to the logger in the "M1" method everything works fine, but if I put the same call in the "MyMethod" method, I get an exception:

“method calls into native method Microsoft.Win32.Win32Native.WriteFile(). Evaluation of native methods in this context is not supported.”

Why the same call works in “M1” and not in “MyMethod”??? It looks like for some reasons I am more limited in the library usage in “MyMethod”.
2) The second example and the main reason why I created this topic is that I want “MyMethod” to return System.Array. Let’s take the example from above and replace int32 by System.Array:

.class public QueryClass
{
    .method public hidebysig static static class [mscorlib]System.Array M1(int32 arg1, int32 arg2) cil  managed
    {
       .locals init ([0]int32 local1, [1]string local2)
        call class [mscorlib]System.Array QueryClass::MyMethod()
        ret
    }

   .method public hidebysig static class [mscorlib]System.Array MyMethod()
   {
   	ldtoken [mscorlib]System.String
        call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
	ldc.i4.s 10
	call class [mscorlib]System.Array [mscorlib]System.Array::CreateInstance(class [mscorlib]System.Type, int32)
	ret
   }
}

As you can see this code is very similar to the first example but in this case we create a System.Array of size 10. For some unknown reasons it does not work: the value, the name and the type for the specified local is blank in the debugger local window. If we inline the “MyMethod” call, everything works fine. Again, it looks like making call to an intermediate functions creates a bug. Here is the inline version that works correctly:

.class public QueryClass
{
   .method public hidebysig static static class [mscorlib]System.Array M1(int32 arg1, int32 arg2) cil managed
   {
      .locals init ([0]int32 local1, [1]string local2)
       ldtoken [mscorlib]System.String
        call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
	ldc.i4.s 10
	call class [mscorlib]System.Array [mscorlib]System.Array::CreateInstance(class [mscorlib]System.Type, int32)
       ret
   }
}

Difficulties calling function on Complex struct types such as lua_State

Hi, I want to get more informations from debug value such as lua_State in Lua5.3.lib.

Following this demo, It is possibe to get the lua_State* address and following fixed size memory(BY DkmProcess::ReadMemory). But lua_State is very complicated, and is not easy to copy.

More seriously I can not call any functions from lua_State with the address because it is from another Process. As I Known,there is an old way in natvis called "LegacyAddin" which can make my debug dll and the target project run in the same peocess. But this way isn`t valid after vs 2019.


//complicated struct, there are a lot of pointers
struct lua_State {
  CommonHeader;
  lu_byte status;
  lu_byte allowhook;
  unsigned short nci;  /* number of items in 'ci' list */
  StkId top;  /* first free slot in the stack */
  global_State *l_G;
  CallInfo *ci;  /* call info for current function */
  const Instruction *oldpc;  /* last pc traced */
  StkId stack_last;  /* last free slot in the stack */
  StkId stack;  /* stack base */
  UpVal *openupval;  /* list of open upvalues in this stack */
  GCObject *gclist;
  struct lua_State *twups;  /* list of threads with open upvalues */
  struct lua_longjmp *errorJmp;  /* current error recover point */
  CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
  volatile lua_Hook hook;
  ptrdiff_t errfunc;  /* current error handling function (stack index) */
  l_uint32 nCcalls;  /* number of allowed nested C calls - 'nci' */
  int stacksize;
  int basehookcount;
  int hookcount;
  volatile l_signalT hookmask;
};

 HRESULT STDMETHODCALLTYPE CLuaStateVisualizerService::EvaluateVisualizedExpression(
    _In_ Evaluation::DkmVisualizedExpression* pVisualizedExpression,
    _Deref_out_opt_ Evaluation::DkmEvaluationResult** ppResultObject
)
{
    HRESULT hr;
    Evaluation::DkmPointerValueHome* pPointerValueHome = Evaluation::DkmPointerValueHome::TryCast(pVisualizedExpression->ValueHome());
    if (pPointerValueHome == nullptr)
    {
        return E_NOTIMPL;
    }

    DkmRootVisualizedExpression* pRootVisualizedExpression = DkmRootVisualizedExpression::TryCast(pVisualizedExpression);
    if (pRootVisualizedExpression == nullptr)
    {
        return E_NOTIMPL;
    }
    // I can get the lua_State address, but 
    DkmProcess* pTargetProcess = pVisualizedExpression->RuntimeInstance()->Process();
    lua_State* value = (lua_State*)pPointerValueHome->Address();
    int n = lua_gettop(L);//Crashed , read access violation. beacuse read address from another process 

Could give me any suggestions? Thanks

Is it possible to skip IDkmSymbolDocumentCollectionQuery.FindDocuments?

To write a custom symbol provider, as part of the implementation, I have registered for IDkmSymbolDocumentCollectionQuery, but VS asks me to find documents for all modules and source files that are not part of my module.

Documentation tells that

        /// Returns document objects from search parameters contained in the document query.
        /// If the symbol file does not contain a reference to this document the returned
        /// document object will be NULL (S_FALSE return code in native). The returned
        /// document objects must be explicitly closed by the caller when the caller is done
        /// with the document.

I've tried different return values and they all break the VS debugger:

return null; - Exception in DkmDebugger, debugger stops working.
return return new DkmResolvedDocument[0]; - C++ breakpoints stop working (my extension is not even for C++)
return new DkmResolvedDocument[1] { null }; - Visual Studio crashes completely

I've looked at PythonTools, they use
throw new NotSupportedException();
That also leads to C++ breakpoints not working with a message "The breakpoint will not currently be hit. Unexpected symbol reader error while processing console.exe"

So is there a way to tell the debugger to 'look elsewhere' if my symbol provider doesn't handle specific modules?

Difficulties changing names on DkmEvaluationResults

This is not really an issue per se, more of a question of how to use the API.

I have a modified CCppCustomVisualizer class I'm working on, for a complex object(the object is actually a collection of structs residing in different memory locations, so the object can have 0-N "members"). So far so good, I've gotten it to work and when resolving the complex object, it has a dynamic amount of children.

The problem I'm encountering is when I try to rename the children by recreating a DkmSuccessEvaluationResult, is that the little "+" next to the object stops working in Visual Studios 'Watch' window, i.e. we cannot expand the child components. However, dragging the child member so it creates a new entry in the 'Watch' window, allows expansion. Also, not renaming/recreating DkmSuccessEvaluationResult also works.

HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::GetItems(
   _In_ Evaluation::DkmVisualizedExpression *pVisualizedExpression,
   _In_ Evaluation::DkmEvaluationResultEnumContext *pEnumContext,
   _In_ UINT32 StartIndex, _In_ UINT32 Count,
   _Out_ DkmArray<Evaluation::DkmChildVisualizedExpression *> *pItems) {
 HRESULT hr;
 hr = DkmAllocArray(Count, pItems);
 if (FAILED(hr)) {
   return hr;
 }

 Evaluation::DkmPointerValueHome *pPointerValueHome =
     Evaluation::DkmPointerValueHome::TryCast(
         pVisualizedExpression->ValueHome());

 vector<name_and_expr> comps;
 hr = evaluate_entity(pVisualizedExpression, pPointerValueHome, comps);
 if (FAILED(hr)) {
   return hr;
 }

 for (UINT32 i = StartIndex; i < StartIndex + Count; ++i) {
   const name_and_expr &expr = comps[i];
   DkmChildVisualizedExpression **children = pItems->Members;
   DkmChildVisualizedExpression **pChild = &children[i];

   CComPtr<DkmEvaluationResult> pEEEvaluationResultOther;
   hr =
       EvaluateOtherExpression(pVisualizedExpression, DkmEvaluationFlags::None,
                               expr._expr.c_str(), &pEEEvaluationResultOther);
   CComPtr<DkmString> pName;
   hr = DkmString::Create(DkmSourceString(expr._name.c_str()), &pName);
   if (FAILED(hr)) {
     return hr;
   }

   if (pEEEvaluationResultOther->TagValue() ==
           DkmEvaluationResult::Tag::SuccessResult &&
       !expr._name.empty()) {
     DkmSuccessEvaluationResult *success =
         DkmSuccessEvaluationResult::TryCast(pEEEvaluationResultOther);

     CComPtr<DkmSuccessEvaluationResult> pNamedEEEvaluationResultOther;

     // NOTE: HERE IS THE PROBLEM CODE
     // Createa success result, but with a custom name
     // Either using 'success->Name()' or 'pName' here leads to a child member which cannot be expanded
     hr = DkmSuccessEvaluationResult::Create(
         success->InspectionContext(), success->StackFrame(), success->Name(),
         success->FullName(), success->Flags(), success->Value(),
         success->EditableValue(), success->Type(), success->Category(),
         success->Access(), success->StorageType(),
         success->TypeModifierFlags(), success->Address(),
         success->CustomUIVisualizers(), success->ExternalModules(),
         DkmDataItem::Null(), &pNamedEEEvaluationResultOther);

     pEEEvaluationResultOther = pNamedEEEvaluationResultOther.Detach();
     // NOTE: PROBLEM CODE END
   }

   DkmChildVisualizedExpression::Create(
       pVisualizedExpression->InspectionContext(),
       pVisualizedExpression->VisualizerId(),
       pVisualizedExpression->SourceId(), pVisualizedExpression->StackFrame(),
       pPointerValueHome, pEEEvaluationResultOther.Detach(),
       pVisualizedExpression, i, DkmDataItem::Null(), pChild);
 }

 return S_OK;
}

Image of the result, where the selected row cannot be expanded, but as you can see, the row at the end containing the same expression can be.
image

Do you have any idea what could cause such a behavior? Is it possible to change the 'Name' of a DkmEvaluationResult in some other way? Or clone it somehow? I have used the same approach in another part of the code, and there it works. You can check the fork with modified CppCustomVisualizer/dll and CppCustomVisualizer/TargetApp here: https://github.com/fredrikz/ConcordExtensibilitySamples

How to filter for my custom project?

I am developing extension for a C++ Native project, but my extensions are only useful if user is debugging my special framework. Is it possible to use vsdconfigxml Filters somehow to filter out non my special framework projects? For example I can set up some variables in my special VSIX or Solution variable?

How can evaluate expression in Immediate window

Example Code:
class VisualizerComponent : IDkmCustomVisualizer{
IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression visualizedExpression){
using (var LanguageExpression = DkmLanguageExpression.Create(
ParentInspectionContext.Language,
DkmEvaluationFlags.DesignTime | DkmEvaluationFlags.TreatAsExpression,
$"sizeof({rootExpr.FullName})",
null
))
{
//Evaluate it
}
}
}
but evaluate this failed.
but evaluate "sizeof" work in immediate window,what should i do

Changes to the NuGet distribution of System.Reflection.Metadata

I might be missing something completely obvious here but it seem that the version of System.Reflection.Metadata referenced by the Iris Example is unavailable in the listed source.
When reverting to NuGet.org it isn't available either which makes restoration difficult.

After removing it and installing it again it seem that in the current distribution available in that way the whole System.Reflection.Metadata.Decoding is Internal, the latest working version I could find was 1.1.0-alpha-00015

Component with WorkerProcessSupported="true" is not being loaded into remote msvsmon process

I have decided to split some work with C++ IDiaSession into a worker component and I have created a new vsdconfigxml file with a separate C# class:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="http://schemas.microsoft.com/vstudio/vsdconfig/2008">
	<DefineGuid Name="guidLuaLocalWorkerDebuggerComponent" Value="7EA4B490-BDF9-42AD-8A5B-BCA60741E5D6"/>
	<DefineGuid Name="guidLuaMessageToLocalWorker" Value="CD3A296C-3C54-4B5E-AF46-8B72F528E4B5"/>

	<ManagedComponent ComponentId="guidLuaLocalWorkerDebuggerComponent" ComponentLevel="1999100" AssemblyName="LuaDkmDebuggerComponent">
		<Class Name="LuaDkmDebuggerComponent.LocalWorkerComponent" WorkerProcessSupported="true">
			<Implements>
				<InterfaceGroup>
					<Filter>
						<SourceId RequiredValue="guidLuaMessageToLocalWorker"/>
					</Filter>
					<Interface Name="IDkmCustomMessageForwardReceiver"/>
				</InterfaceGroup>
			</Implements>
		</Class>
	</ManagedComponent>
</Configuration>

But when I send a message from an IDE component to this component, it is not executed in a worker process.
DkmCustomMessage.Create(process.Connection, process, MessageToLocalWorker.guid, MessageToLocalWorker.checkSymbol, nativeModuleInstance.UniqueId.ToByteArray(), null).SendLower();

image

Error building CPPCustomVisualizer example in VS 2019 16.3.8

When I download the CPPCustomVisualizer example source code and, in VS 2019 16.3.8, right-click on the 'vsix' project and build in release, there is an error at the end of the build process and the build fails with the following error:

2>VSSDK : error VSSDK1025: Could not add the file 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x86\CppCustomVisualizer.vsdconfig' to the zip package 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\CppCustomVisualizer.vsix'. Could not find a part of the path 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x86\CppCustomVisualizer.vsdconfig'.

Here's the build output:

1>------ Build started: Project: CppCustomVisualizer, Configuration: Release x64 ------
1>stdafx.cpp
1>dllmain.cpp
1>_EntryPoint.cpp
1>Generating Code...
1>   Creating library C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x64\CppCustomVisualizer.lib and object C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x64\CppCustomVisualizer.exp
1>CppCustomVisualizer.vcxproj -> C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x64\CppCustomVisualizer.dll
2>------ Build started: Project: vsix, Configuration: Release Win32 ------
2>Build started 11/7/2019 9:55:23 AM.
2>     1>Project "C:\Users\ckline\dev\c\CppCustomVisualizer\CppCustomVisualizer.sln" on node 1 (Build target(s)).
2>     1>ValidateSolutionConfiguration:
2>         Building solution configuration "Release|x64".
2>       ValidateProjects:
2>         The project "vsix" is not selected for building in solution configuration "Release|x64".
2>     1>Project "C:\Users\ckline\dev\c\CppCustomVisualizer\CppCustomVisualizer.sln" (1) is building "C:\Users\ckline\dev\c\CppCustomVisualizer\dll\CppCustomVisualizer.vcxproj" (2) on node 1 (default targets).
2>     2>InitializeBuildStatus:
2>         Creating "Release\x64\CppCusto.F7062FB7.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
2>       CreateVsdbgConfigContract:
2>       Skipping target "CreateVsdbgConfigContract" because all output files are up-to-date with respect to the input files.
2>       ClCompile:
2>         All outputs are up-to-date.
2>         All outputs are up-to-date.
2>       ResourceCompile:
2>         All outputs are up-to-date.
2>       Link:
2>         All outputs are up-to-date.
2>         CppCustomVisualizer.vcxproj -> C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x64\CppCustomVisualizer.dll
2>       CreateVsdbgConfigFile:
2>       Skipping target "CreateVsdbgConfigFile" because all output files are up-to-date with respect to the input files.
2>       FinalizeBuildStatus:
2>         Deleting file "Release\x64\CppCusto.F7062FB7.tlog\unsuccessfulbuild".
2>         Touching "Release\x64\CppCusto.F7062FB7.tlog\CppCustomVisualizer.lastbuildstate".
2>     2>Done Building Project "C:\Users\ckline\dev\c\CppCustomVisualizer\dll\CppCustomVisualizer.vcxproj" (default targets).
2>     1>Done Building Project "C:\Users\ckline\dev\c\CppCustomVisualizer\CppCustomVisualizer.sln" (Build target(s)).
2>
2>Build succeeded.
2>    0 Warning(s)
2>    0 Error(s)
2>
2>Time Elapsed 00:00:00.48

2>VSSDK : error VSSDK1025: Could not add the file 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x86\CppCustomVisualizer.vsdconfig' to the zip package 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\CppCustomVisualizer.vsix'. Could not find a part of the path 'C:\Users\ckline\dev\c\CppCustomVisualizer\Release\x86\CppCustomVisualizer.vsdconfig'.

2>Done building project "vsix.vcxproj" -- FAILED.

========== Build: 1 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

vsdconfig.xsd gets added to projects when adding Microsoft.VSSDK.Debugger.VSDConfigTool package

Repro steps:

  1. Create a new C++ project
  2. Right click on the solution and open nuget package manager
  3. Add a reference to Microsoft.VSSDK.Debugger.VSDConfigTool

Result:

vsdconfig.xsd gets copied from the nuget package and added to the solution. For C++ projects this can cause the build to fail as it invokes legacy code that doesn't work.

Expected:

vsdconfig.xsd should NOT be copied from the nuget package, and should NOT be added to the solution

Work around:

Delete the copied vsdconfig.xsd and remove the reference from the project. Optionally one can replace it with something like this.

Visual Studio 2017 Support problem

Hello, my LanguageService and Debugger are in Visual Studio 2015, and I am trying to add the possibility of my plugin to be used under both VS 2015 and VS 2017.
Similarly to the Iris sample, I rely on the old version of System.Reflection.Metadata (System.Reflection.Metadata.1.3.0-rc3-23923) in order to be able to decode method signatures. The newer versions of this DLL do not support this feature. Under VS 2015 everything works fine. With VS 2017 the Debugger uses a new version of System.Reflection.Metadata (1.4.1) that came with the installation of VS 2017 instead of using the System.Reflection.Metadata 1.3.0 that came with my VSIX see screenshot below:

metadataerror

Any idea on how to solve/bypass it. And why this decoding feature was removed from the newer version of System.Reflection.Metadata and is there any alternatives to it?
Thanks in advance,
Vladimir.

Register source language enumerator value

Hi,

I'm not sure this is the right place to ask, but is it possible to "register" a source language identifier to get listed in CV_CFL_LANG here https://github.com/Microsoft/microsoft-pdb/blob/master/include/cvconst.h#L300 ?

I have extracted the D language expression evaluator of the mago debug engine (https://github.com/rainers/mago/tree/master/EED/MagoNatCC) as a Concord extension and used 'D' (0x44) as the source language identifier for the S_COMPILE CodeView record emitted by the compiler. The installer adds appropriate "CodeView Compiler" registry entries for the VS debugger to map this identifier to the D Concord extension. Long term, this might cause conflicts with other languages using the same enumerator value, though.

LLVM got support for the S_COMPILE3 record recently, and I'd like the 'D' identifier to be added there, too. It might be easier to get addition of the appropriate translation with some "official blessing" of the actual value.

Thanks.

Calling back into the default expression evaluator doesn't work with arrays

This may be an issue with my implementation, but I've noticed that when I try to create a visualizer that just kicks the work back to the default expression evaluator I get different results than when I have no visualizer at all. In particular, I start to see ??? in the display string for array elements in the Watch window.

In this screenshot the NoVis type has no custom visualizer at all. Notice that it shows the value of the single array element in the display string. The DefaultVis type has a custom visualizer but all it does is callback into EvaluateExpressionCallback from EvaluateVisualizedExpression and set pUseDefaultEvaluationBehavior to true in UseDefaultEvaluationBehavior.

I'm using VS2022 (17.0.4) here.
image

In VS2019 (16.11.8) I get slightly different results. I can run the same solution (after downgrading the Microsoft.VSSDK.BuildTools package and build tools version) and it works correctly. However, it will exhibit the same issue if I set pUseDefaultEvaluationBehavior to false and then use the callbacks to do default visualization in the rest of the IDkmCustomVisualizer functions.
image

vs-native-debug-visualizer-github.zip

E_XAPI_COMPONENT_DLL_NOT_FOUND when using load symbols in external process

I have a small debugger extension that is written using IDkmCustomVisualizer API to extend some native (C++) watch variable. The extension works as expected when load symbols in external process is not check but fails when it is.

Extension is installed by copying the .dll and .vsdconfig in the diectory desribed by the documentation https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Installing-Concord-Extensions. So everything is copied to that folder C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Packages\Debugger and the .natvis here C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Packages\Debugger\Visualizers.

Is there a way to find out what is going on ?

Thanks.

Method chaining in IDkmLanguageExpressionEvaluator not working

Hello,

I am not sure if this is a bug or me doing something wrong, but I am having troubles getting a basic IDkmLanguageExpressionEvaluator to work. I adapted the HelloWorld sample (not the C# and the c++ flavor) to implement the interface, and my functions are getting called. Since they don't do anything yet, I just hand them off to the next dispatch objects with the method chaining method. However, the dispatch objects down the chain don't seem to do anything anymore as soon as my dispatch object is installed. I get empty watch windows and when I force a watch, it hangs until I stop debugging.

Oddly enough, the watches are broken, regardless of whether my plugin has a high component level and actually gets called, or a low enough level so that it doesn't get called. Hence my suspicion that it might be a bug.

I also tried without method chaining by returning E_NOTIMPL, like the CppCustomVisualizer (which I got to work btw), with no change.

Here is an example of an interface function with chaining:

HRESULT STDMETHODCALLTYPE CHelloWorldService::GetFrameLocals(
    DkmInspectionContext* inspectionContext,
    DkmWorkList* workList,
    DkmStackWalkFrame* frame,
    IDkmCompletionRoutine<DkmGetFrameLocalsAsyncResult>* completionRoutine
)
{
    Log("CHelloWorldService::GetFrameLocals");
    inspectionContext->GetFrameLocals(workList, frame, completionRoutine);
    return S_OK;
}

And here is the .vsdconfigxml with the high component level:

<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="http://schemas.microsoft.com/vstudio/vsdconfig/2008">
  <NativeComponent
    ComponentId="EB539DB5-EB09-42C8-8217-AEB14EA4C30B"
    ComponentLevel="10000000"
    ModuleName="HelloWorld.dll">
    <Class Name="CHelloWorldService" ClassId="C797BD7C-E993-440D-BAC3-DCB6858052B4">
      <Implements>
        <InterfaceGroup>
          <NoFilter/>
          <Interface Name="IDkmLanguageExpressionEvaluator"/>
        </InterfaceGroup>
      </Implements>
    </Class>
  </NativeComponent>
</Configuration>

Debugging CppCustomVisualizer doesn't work in VS2019

If I try to debug (F5) CppCustomVisualizer project new VS2019 instance starts but doesn't load TargetApp.sln. Even if I load it manually from started VS2019 instance, FILETIME in debugger doesn't doesn't get displayed as intended by CppCustomVisualizer.
This is how debugging page of Debug configuration of vsix project looks like:
image

Note, that Release config is identical to the screenshot in Greg's comment.
I use pretty much barebones latest VS2019 with little no none extensions installed. If I build CppCustomVisualizer and manually install the resulting extension, then yes, FILETIME visualizer works in TargetApp. I do not have any local changes in the ConcordExtensibilitySamples clone and the path doesn't have any spaces.

Originally requested by @gregg-miskelly in #52 (comment)

IDmkClrExpressionCompiler.CompileExpression: wrong value in "Text" property of DkmLanguageExpression

Hello, when implementing IDkmClrExpressionCompiler interface I found a strange behaviour in the CompileExpression method. The property “Text” of the DkmLanguageExpression (=first parameter of this method) sometimes doesn’t contain the desired information. For example, consider a string “R14” in a custom language. When I point the mouse between 1 and 4 in the debugging session, the "Text" property will only contain “R1”! Is there an Interface that I can implement to change what will be stored in the “Text” property or get access to the source code from CompileExpression method so I can parse it manually?
Thank you.

Support for Tree like variables in IDkmClrExpressionCompiler.GetClrLocalVariableQuery

Hello, the language I am trying to implement has a tree like structure variables, where only leaves has actual values, any other node value is the concatenation of his children (=sub nodes) and each leave may contain a different type of data. When composing the list of locals variables (type DkmClrLocalVariableInfo) in the IDkmClrExpressionCompiler.GetClrLocalVariableQuery, I got a dilemma with 2 possible choices:

  1. Each tree structure variable will be contained in 1 DkmClrLocalVariableInfo. In this case the tree like variables can be nicely displayed (by constructing a MSIL class for each tree like variable) but I didn’t find any way to obtain the Type information for each leaf in my IDkmClrFormatter.GetTypeName implementation. When displaying simple variable, the type information can be stored in DkmClrCustomTypeInfo class when building the DkmClrLocalVariableInfo and then retrieved from the parameters of the IDkmClrFormatter.GetTypeName function. With the tree structure variables, for each node we will pass by IDkmClrFormatter.GetTypeName function and only for the root node I can retrieve the DkmClrCustomTypeInfo, for all the sub nodes of this tree the value will be null. Well, even if it was not null it would not help because the order in which nodes are visited is unpredictable, so no way to store the information for all the nodes in one instance of the DkmClrCustomTypeInfo.
    vars
  2. The second possibility: for each leave or node of the tree like variable create a different DkmClrLocalVariableInfo, so we have 1 to 1 relation between DkmClrLocalVariableInfo and IDkmClrFormatter. But in the case I lose the tree structure representation.

Also, due to the complexity of data types there is no way create 1 to 1 relation between my custom language and MSIL, which of course would have solved the problem.

Any suggestions? Maybe instead of IDkmClrFormatter there is a different interface that I can implement that offers more flexibility?

Thank you in advance, Vladimir

How can I get resolved DkmInstructionAddress on Target computer component?

Hello,
I would like to get DkmCustomInstructionAddress from the interface function "OnEmbeddedBreakpoint" which is implemented in the component "A" of target computer (Levels Values < 99,999).

"A" component inserts "TRAP" in the instruction stream. As a result, It received "OnEmbeddedBreakpointHit" with a DkmUnknownInstructionAddress. Is there any simple ways to get the resolved DkmCustomInstructionAddress on the target computer component? IDkmInstructionAddressResolver is implemented by an IDE component.

What I have tried are as follows.

  1. Implement "IDkmInstructionAddressProvider" interface in a IDE component. - Not Working.
  2. Call DkmProcess.GetInstructionAddress. - NotImplementedException is thrown.
  3. Implement "IDkmEmbeddedBreakpointHitNotifier" interface in a IDE component "B" and call thread.OnEmbeddedBreakpointHit. However the notification was received by only the components whose level is higher than the level of "B" component.

I hope to find a simple way so that makes easy to implement stepper.

Thanks.

visx project fails to load

image
I've made sure that:

  1. Build is set to x86. BTW, why is this necessary, it's not explained.
  2. 'Allow NuGet to download missing packages during build.' from Tools -> Options -> NuGet Package Manager, is checked.
  3. There is no file named ConcordExtensibilitySamples\CppCustomVisualizer\vsix\vsix.vcxproj.user.
  4. I've also attempted to do what you say in your If Debug Launch doesn't start Visual Studio correctly Troubleshooting step manually to the visx.vcxproj to no avail.

I'm using VS Pro 2019 v16.3.7 with .NET framework 4.8.03752.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.