-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Address not in trace #4059
Comments
@astrelsky getting on a plane right now, but will take a look at this after I get back, either this aft or tomorrow. |
Ok, no rush. |
This might be another case of a stale or incomplete memory map. My guess is the memory map does not include the library loaded via |
I mentioned it in the comment in the discussion just now but will make it here as well. I get the same behavior if I link directly to the dll's lib file instead of using Just saw the second half, trying now. |
@astrelsky WOW, OK, so I wasn't able to repeat your experiment - not because I didn't encounter your problem, but because I hit so many other problems on the way to your problem that I never got to your problem. Guess I know what I'll be doing for the next week or three. Will try to keep you posted as I go, but, either the existing unit tests are not keeping the dbgeng version in a sane state or something about your example is causing it to got seriously haywire. Among the issues I'm seeing:
sigh more tomorrow |
Wait, this is the normal behavior? 🤣 In order to get the breakpoints in the dll to fire you have to map the module to the dll. Please excuse the horrid screenshot below. @nsadeveloper789 with respect to the second half with enabling the full view. Once enabled while I am tracking the instructions for my function in the static listing they dynamic view is grayed out and all zeroes. This may be seen in the screenshot above as well. This might end up being a bit of a challenge but I, as well as many others I'm sure, would need to be able to break and step through |
iWell, leaving aside the issue of "normal", none of those things are supposed to happen. And, I'm pretty sure, you shouldn't have to map dll.dll to DLL.DLL. That function should only be necessary if the program name is not a match to the name of the executable as seen by the loader. After LoadLibraryA is called, there should be a load module event and the memory should be updated to reflect the load. You might need to pre-map the memory if you wanted to set up the breakpoint before the LoadLibraryA call, but not after. |
Just out of curiosity, at what point was the screenshot above taken? i.e. before or after the break post-LoadLibraryA? Looks like it was taken at the first, i.e. windows-inserted default, breakpoint, well before the dll load. |
The current instruction is 1000b95c. I was stepping through the dll function seen in the listing. |
@d-millar you may be working from the master branch. Even so, if that's the case, sounds like quite a few problems have cropped up. @astrelsky Following up on the second "Force-full-view" method, I suspect it's not a feature used very often, and some of the bits of automation are still heeding the incomplete map. You might be able to work around by selecting a portion of the grey 0s and clicking the little "memory chip" looking button in the dynamic listing. That should cause it to refresh pages containing the selected addresses. Whether or not that works, sounds like you've found another bug :) . |
@nsadeveloper789 - yeah, a lot. more than I have listed above. we should discuss at some point, but fixing what I can right now. |
OK, bit of an update: still a lot of things I need to work on, but I have at least some understanding of what's going on. The main issue is a concurrency bug in how I update the memory regions. The addRegion logic was ok, but the removeRegion logic was, well, not so good. Why is that relevant, you might ask? To answer that, let me backtrack a bit and walk through your experiment to make sure I'm on the same page. So, your steps with some edits: Steps to reproduce the behavior:
Haven't really gotten to 13-18 (although I pretty much am always doing 18). Guessing I am not at the end of the difficulties yet, but am trying to fix as I go. @astrelsky Big thanks for this example - it highlights a bunch of bugs I probably wouldn't have seen through the unit tests. The concurrency bug is bad, but the thread/process mismatch could be causing some fairly insidious behavior. I also discovered our cleanup logic was failing, so re-running the same process causes progressively worse performance. |
This was to point out the error popup that occurs when right clicking in the decompiler window when there is no debugger connection. What section of the debugger api were the concurrency issues in? Was it just the windows debugger portions or would it affect gdb too? For a while I was working on a gdb stub for yuzu to use with Ghidra but after getting the stub nearly complete I gave up. I was having problems getting breakpoints to be consistent among other things and couldn't figure out why. I assumed it to be due to the lack of debugging functionality built into yuzu and dynarmic and put the project aside. |
@astrelsky The concurrency issues (and, in fact, most of the issues I've mentioned) have been in the Windows-specific code, so probably not relevant for the gdbstub. If you get back to the stub work at some point, feel free to give me a shout. Have written stubs before, albeit not in the last decade - not sure if I can be helpful but willing to try. On the decompiler error, that seems a little surprising - the decompiler is more or less completely decoupled from the debugger. What was the actual error? |
stacktrace
As for the gdbstub then I'm almost certain it is due to lack of debugging support in yuzu/dynarmic. |
Gotcha - well, I can fix the NPE for sure. :) |
I'd hope so 😅. That's why it was "for laughs". |
AH! (missed that) On the progress front, almost "everything" fixed. Not sure if the fixes will make the next minor release, but certainly 10.2. |
One thing probably not in "everything" is how to walk through DllMain. I think the answer is to break before LoadLibraryA, then select up Debugger->Sessions[0]->Processes[x]->Debug->Events->Load module->Execute, and hit T a couple of times to toggle the option to "Break". When you continue, the process should break on the load and the address space for DllMain should be valid. You could then set a breakpoint there and single-step through the code. You'll want to wait until the LoadLibraryA call to avoid having to resume a gabillion times for every module load and probably will want to toggle Break->Output after for the same reason. |
To follow up on [https://github.com//discussions/3151], another approach to this which I just verified is to run "/c:/windows/system32/rundll32.exe DLL.dll,debuggerProblems". On the initial break, in the Interpreter window, enter "bp DLL!debuggerProblems". The breakpoint will be deferred and will trigger on entry to debuggerProblems. I should figure out how to make a non-command line version of the same, but that will have to be a problem for Monday. |
Excellent thank you. |
FWIW, the stack trace from right-clicking in the decompiler is already fixed in an internal branch. It's awaiting review. Also, regarding setting a deferred breakpoint, there is an "Add breakpoint" button in the "Objects" window. AFAIK for Windows, that should be a shortcut for the "bp" command. You'd enter |
@nsadeveloper789 yep, gotcha - new adds move "DLL!debuggerProblems" automatically into the dialog if you "Add" off that node in Objects' Process->Module->Symbols. |
Is this supposed to be fixed yet in the master branch? I just want to be sure we are on the same page as I tried yesterday and was still unable to see anything on the heap. |
@astrelsky Some, but not all, of the fixes mentioned above have been incorporated into master. With regard to the heap, I think we need to nail down the specifics on this one. If this is still an issue of using "*:4 EAX" with GoTo, I think the problem is the comment on the GoTo, which is frankly confusing and which has been modified. Specifically, if you want to go to the address in RAX, you should just enter RAX. If you want to go to the contents of the address at RAX, you should enter *:8 RAX. In other words, *:8 RAX assumes something like RAX == DEADBEEF, DEADBEEF is a pointer, say, containing FEEDFACE, and you want to go to FEEDFACE. If FEEDFACE is not in the trace, *:8 RAX will throw the "Not in trace" error. If this is NOT the situation, then, as @nsadeveloper789 mentioned, the problem is probably incomplete information provided by the API. For WIndows, the API is IDebugDataSpaces::QueryVirtual. Possible, we're misusing this, I guess, but, if so, I'm not sure of the fix. I believe this provides the same info as "!address" in Windbg. Is you address in the list if you issue "!address" from the Interpreter window? Also, you should still have the option to force all of memory in as described. Does your address not appear in the Dynamic Listing if you've forced memory in? |
If I force all memory I can go to it but it is grayed out and all 0's. However when dereferenced by an instruction I can see it is not 0. |
when you force it in, you probably have to refresh/flush caches (yes, anticipating a scowl, that should be fixed) |
How would I do that? If you meant to just refresh the objects in the tree that didn't help. I should mention that I don't actually know how to use the debugger outside of Ghidra so I'm not familiar with any of it's commands. |
that was the right thing - well, there are two options. "Refresh" in the Objects view with the root selected, and "flush caches" in the Targets view from either the pull-down or a right-click. So, I think you did the right thing. Which means I clearly do not have a grasp of the problem yet. (Side note: the #4059 change set has now been pushed to our local master - shouldn't be too long before it's in the public master.) |
So, am trying to get this down to the minimal experiment to make sure you and I are doing the same thing. My latest runs have been along the lines of: connect to IN-VM dbgeng, launch "Test.exe TestDll.dll" (my local names), resume once to get the conhost process to launch, enable the bpt after the load, resume until the bpt gets hit, enable the bpt in TestDll.dll, resume, bpt hits. Haven't done anything past that. Are you doing more or less the same? And just because someone else here had a similar issue, is the pull-down in the Dynamic listing set to track PC? And is the trace associated with Test (vs conhost) in Threads selected? |
It is similar. It could be because I still have to do the map modules to xyz. 100% of the time the filename I have will not be what is expected.
yes
yes I didn't flush the caches, only the refresh. Should I try flushing them? |
Can't hurt (he says). I will try renaming my program and testing that way |
GP-1812: another revert GP-1812: moving changes to alt branches GP-1812: comment in goto no longer applies to registers GP-1812: new providers not retrieving configState GP-1812: NPE mentioned in #4059 GP-1812: MISSING+ENABLED -> ENABLED, not DISABLED_ENABLED GP-1812: name inconsistency in breakpoints GP-1812: String->Address to assist navigation GP-1812: force memory refresh on module load GP-1812: concurrency error processing memory GP-1812: thread/process fix for dbgmodel; restricting changeElements to matching container matching process GP-1812: make currentThread/Process consistent GP-1812: fix for failed DebugClient cleanup; callback error msg issue
I'm going to re-open this - am still trying to understand the missing memory issue. |
OK, I have a fix - took me a while to understand what was really happening. Hopefully, will hit master in the near future. In the meantime, I can describe the problem and a workaround. The issue: we try not to update memory on every event because it's super-expensive. We were updating it before on process start-up, module loads, and resync. Would have thought "Flush Caches" would trigger a resync, but it doesn't. Would have thought "Refresh" on the Object tree root or the Memory node would trigger a resync, but they don't. The resync only happens if the Memory node is open. While this probably seems dumb, it's actually a good design decision for a couple of reasons. Namely, it restricts updates to those items the user is presumably interested in, and it prevents potentially recursive transits through the tree, which contains linked nodes. So, the workaround is to (1) open the Memory node, and (2) select/refresh it if you suspect memory is stale. The full fix should allow "Refresh" from anywhere in the tree above or on Memory and increase the number of events that auto-refresh memory. |
Ok great. I will give it a shot tomorrow morning. Thank you. |
I was just thinking about this and am wondering if it would be sufficient to set a "dirty" flag on events which update memory and then the actual update would occur on a user triggered event such as reaching a breakpoint or stepping. |
Would work if you had events for updated memory, but that’s a pretty rare case unfortunately. |
That's unfortunate. How about a different approach then. Why is there a lot of overhead in updating the memory? It's still a bit early so I can be mistaken but I think I recall a lot of things happening in the ui while the target is running in the debugger. This may not be necessary and could be made to occur once execution pauses. I have no idea if this is actually a cause of overhead or not but I do recall comments elsewhere about some analysis performing better if you minimize the ui since the events won't fire or something. |
Well, this is just my opinion - take it with a grain of salt - but my impression is that most users can stand a considerably larger hit to the running process than they can when interacting with it. For example, full-on tracing via single-step incurs about a 100x penalty, but for debugging a serious problem on a single process many users are willing to take that hit. Tracing via step-by-branch or using dedicated hardware is considerably less, in the 10x-100x range, and most users don't mind this at all unless they're batch processing hundreds (or thousands) of executables. However, a 2x-10x slowdown in single-stepping is unacceptable to almost everyone. Users want to be able to bang in single-step as hard and fast as they can and have the GUI respond. Single-step normally involves a minimum of commands, typically ask for the step (often by setting a register), resuming, and returning the new register values. That's typically of the order of a hundred bytes for a large register set. Asking for all the modules and/or all the memory regions and potentially pages that might have changed and are visible is more like a thousand+ bytes. For users with very fast machines maybe not a problem, but for most at least an annoyance. I think updating on non-single-step events is a good compromise, and generally that means process/thread create/destroy, module load/unload, and breakpoints hit. |
Oh yea, this good stuff. <- Me after refreshing the memory node. |
So initially I was under the impression that I had to refresh the memory node all the time including after a single byte had been written to memory. Now that I know it is only when sections of memory are added/removed I no longer see it as such a big deal. 😅 |
Wow, that’s an interesting point. I suppose, if you’re watching the stack, you really might want it to update on every step. I think we might need to make this an option. |
Actually, I think it does that much. Will verify, but I think visible memory is refreshed for all events, and non-visible memory is refreshed when viewed. |
I think you misunderstood my above comment. I initially thought the behavior was like that. After getting everything mostly working I realized I had misunderstood the reason for having to refresh the memory node. It seems to be functioning as would be expected at the moment. |
Describe the bug
Attempting to go to a virtual address to see the values in memory results in "Address not in trace" error.
To Reproduce
Steps to reproduce the behavior:
LoadLibraryA
.*:4 EAX
(assumming it is inEAX
).19.
Attachments
main.cpp
dllmain.cpp
Environment (please complete the following information):
Additional context
#3151
The text was updated successfully, but these errors were encountered: