microsoft/DbgShell

EnumerateLIST_ENTRY doesn't work

Zhentar opened this issue · 5 comments

EnumerateLIST_ENTRY has two main troubles:

  1. It yields PSObjects, not DbgValues.
  2. It throws a NotImplementedException

The NotImplementedException can be resolved easily enough by skipping the dynamic entirely:

        var val = Debugger.GetValueForAddressAndType( curItemAddr, entryType, itemNamePrefix + idx.ToString(), false, false );
        yield return val;

        curListEntry = val.Properties[listEntryMemberPath].Value;
        curListEntry = curListEntry.Flink;

Additionally, the head = head.WrappingPSObject; at the start is a bit inconvenient, since it means one has to pass in the PSObject.BaseObject instead of the PSObject directly, and the is DbgPointerValue & is DbgValueError checks don't work, since the values are always PSObject.

Thank you for the feedback! The LIST_ENTRY code is definitely only half baked. I think I might've started on it when chipping away at kernel mode support, and just committed what I had done. Unfortunately I don't think I will get to fixing this one up in the very near future, but as always, feedback such as this helps me know what to prioritize when I get time.

Out of curiosity, are you dealing with a LIST_ENTRY in user mode, or are you coaxing DbgShell to work for kernel mode? (I personally haven't often needed to deal with LIST_ENTRY lists in user mode.)

Kernel structures, user mode - specifically, _HEAP with its list of _HEAP_SEGMENT (and probably others in short order)

Can EnumerateLIST_ENTRY be implemented as a wrapper around EnumerateLIST_ENTRY_raw? I don't know how StreamFromDbgEngThread runs under the hood so I'm wondering if there are any thread safety/deadlock concerns.

I should probably just delete EnumerateLIST_ENTRY... I think maybe I had a script implementation of it, and was trying to write it in C# instead... oh, yep; found it: Expand-LIST_ENTRY in OtherUtils.ps1. I don't remember why I wanted to write it in C#... oh, probably so that it would be available to other C# code. I'll need to find some time to page in what I was trying to do there, but I suspect that I will need to largely scrap it and implement in terms of the other "raw" one.

StreamFromDbgEngThread is conceptually very simple. There is a dbgeng thread, and a pipeline execution thread, and cmdlets run on the latter, but actually interacting with dbgeng must happen on the former. StreamFromDbgEngThread just lets you pass in a Func to run on the dbgeng thread, and as the func produces results, StreamFromDbgEngThread handles shuttling them back over to the pipeline execution thread, where they pop out of the returned IEnumerable<T>. It handles all the thread safety stuff, to make it easy to use from the pipeline execution thread.

My implementation: Zhentar@11fa946