I would like to have a break on the SetTimer function in order to see which components register what timers with what values. Is this possible?
Yes, you can do this. First make sure you have public symbols setup for your debugger.
SetTimer lives in user32 but that is just what it is exported as. The easiest way to do this is with the command line debugger, NTSD. We need its real name, so look for symbols in user32 that match:
0:000> x user32!*timer*
759992b9 USER32!NtUserValidateTimerCallback = <no type information>
759977d5 USER32!NtUserSetTimer = <no type information>
759e4f13 USER32!NtUserSetSystemTimer = <no type information>
759993bf USER32!NtUserKillTimer = <no type information>
Ah-ha! Its debug symbol is NtUserSetTimer:
0:000> bp user32!NtUserSetTimer
In Visual Studio, you can figure out where SetTimer lives by writting a simple scratch program and then setting a breakpoint and right clicking and selecting "Go to Disassembly":
int _tmain(int argc, _TCHAR* argv[]) {
SetTimer(NULL, 0, 0, NULL);
004113BE mov esi,esp
004113C0 push 0
004113C2 push 0
004113C4 push 0
004113C6 push 0
004113C8 call dword ptr [__imp__SetTimer#16 (418338h)]
If we step into that call, then we land here:
_NtUserSetTimer#16:
759977D5 mov eax,123Dh
759977DA mov edx,7FFE0300h
759977DF call dword ptr [edx]
759977E1 ret 10h
So the to set a breakpoint there in Visual Studio, you have to use the context operator in the breakpoint. Select from the menus: Debug -> New Breakpoint -> Break at Function, then enter:
{,,user32.dll}_NtUserSetTimer#16
Here's a walkthrough, with screenshots, for VS2005. Note that for VS2008+ you don't need to input decorated function names (perhaps that's the reason the previous description didn't work out directly? What's your platform/IDE ?).
[Edit:] You definitely need public MS symbols to be able to locate Win32 API in binaries. The shortest route there is go to Tools/Options/Debugging/Symbols, then paste 'http://msdl.microsoft.com/download/symbols' into 'pdb locations'. It is highly recommended - but not necessary - to set a local cache for downloaded pdb's (first pdb loads can be a few minutes), and for your needs you should probably uncheck 'Search the above locations only when symbols are loaded manually'. There'd be some startup delay as all symbols are loaded, but you won't have to chase down user32.dll (or whatever dll holds the function you wish to break at) and load its pdb manually.
Related
I'm trying to debug physical memory allocation to understand what part of the Linux Kernel use memblock_alloc_range_nid on x86-64 and how.
I'm running the latest Linux Kernel 5.19-rc2 built from upstream with Ubuntu 20.04 inside QEMU. The problem is it's not possible to access memory address the function memblock_alloc_range_nid is located at. While other Kernel functions can be easily disassembled.
Here is what I have in my gdb connected to the QEMU VM:
(gdb) disas memblock_alloc_range_nid
Cannot access memory at address 0xffffffff831a05d1
(gdb) disas native_safe_halt
Dump of assembler code for function native_safe_halt:
#...
End of assembler dump.
What's wrong with the function memblock_alloc_range_nid? Why is it not possible to access its address? It seems all the function from memblock.c cannot be accessed.
As Margaret and Roi have noted in the above comments, memblock_alloc_range_nid() is annotated with __init. Functions annotated with __init, __head and similar macros are only needed during kernel initialization right after boot. After the kernel has finished initializing things, the special memory section containing all those functions is unmapped from memory since they are not needed anymore.
If you want to debug any such function, you will have to break very early, for example at start_kernel(), then you can inspect the function or set a breakpoint and continue execution to hit it.
Important: add -S (uppercase) to your QEMU command line options to make it stop and wait for the debugger before starting the kernel, and start the kernel with KASLR disabled using -append "nokaslr" (or adding nokaslr if you are already specifying -append).
The following GDB script should be what you need:
$ cat script.gdb
directory /path/to/kernel-source-dir
file /path/to/kernel-source-dir/vmlinux
target remote localhost:1234
break start_kernel
continue
Launch gdb -x script.gdb (after starting QEMU), and when you hit the start_kernel breakpoint, you can add another one for memblock_alloc_range_nid, then continue:
0x000000000000fff0 in exception_stacks ()
Breakpoint 1 at 0xffffffff82fbab4c
Breakpoint 1, 0xffffffff82fbab4c in start_kernel ()
(gdb) b memblock_alloc_range_nid
Breakpoint 2 at 0xffffffff82fe2879
(gdb) c
Continuing.
Breakpoint 2, 0xffffffff82fe2879 in memblock_alloc_range_nid ()
(gdb) disassemble
Dump of assembler code for function memblock_alloc_range_nid:
=> 0xffffffff82fe2879 <+0>: push r15
0xffffffff82fe287b <+2>: mov r15,rcx
0xffffffff82fe287e <+5>: push r14
0xffffffff82fe2880 <+7>: mov r14,rdx
0xffffffff82fe2883 <+10>: push r13
0xffffffff82fe2885 <+12>: mov r13d,r9
...
How do you get the signature of an exported function of a DLL? I know this is possible since a program analysis tool such as IDA (and ollydbg) manages to get the following for GetVersionExA:
push offset VersionInformation ; lpVersionInformation
mov edi, offset dword_4D3B94
mov esi, offset aSS ; "%s - %s"
call GetVersionExA
Using a hex editor to search through PDBs, I could not find the string lpVersionInformation. So where and how can I extract the signature?
Not totally sure that I've got this problem nailed down yet, but here's what I'm seeing and what I think is going on.
I have a Win32 program mostly written in C that loads a C++ DLL. That DLL passes data from the C program to another application via a COM object--one that's probably instantiated by the DLL itself. All of this has apparently worked fine through at least Windows XP and Windows 7 (possibly Win95 and Win98, I'd need to look back deeper into the code history to find out when this interface was introduced), but in Windows 10 the program crashes during the FreeLibrary() call for this DLL.
While checking this in the debugger, DLL_DETACH_PROCESS seems to be handled successfully (no code is executed when handling that message). The crash occurs after (or while) leaving the code from the Entry Point.
If I continue to Step In, I end up in a header file called utilcls.h, which seems to be one of the Borland C Builder 6 header files. I believe the template code therein is related to the COM object being torn down. An Unbind() call passes, and this is the last line of code I can step to before the crash.
If I use the debugger's CPU window and continue stepping, everything that remains appears to be related to freeing memory before the crash comes, but it's quite a lot of CPU-stepping to get there.
The crash raises APPCRASH with exception 0xc0000602, referring back to Combase.dll.
Simply not calling FreeLibrary for that DLL allows the application to close successfully, but my assumption is that the FreeLibrary call is important.
The COM object is released by the data-sharing application prior to the FreeLibrary() call, which allows that application to close. My assumption at the moment is that some of this unlinking is happening differently in the newer operating system and this is causing the crash, but I don't know how to be find out for sure.
My question(s):
if it's obvious to someone else who better knows what they're doing, what causes this crash?
what are the next steps in trying to debug this? I've exhausted my knowledge of the debugging environment I'm using and don't know COM or DLLs well enough to know what the next question to ask is.
Some of the debugger output RbMm requested:
0:000:x86> t
ntdll_77b40000!RtlIsCriticalSectionLockedByThread+0x1b:
77b7256b c20400 ret 4
0:000:x86> t
combase!DecrementMTAUsageHelper+0x5b:
7527a2d6 85c0 test eax,eax
0:000:x86> r eax
eax=00000001
0:000:x86> t
combase!DecrementMTAUsageHelper+0x5d:
7527a2d8 0f859a000000 jne combase!DecrementMTAUsageHelper+0xfd (7527a378) [br=1]
0:000:x86> t
combase!DecrementMTAUsageHelper+0xfd:
7527a378 e89e9e0f00 call combase!CrashProcessWithWERReport (7537421b)
At that point, the stack looks roughly like this:
ChildEBP RetAddr Args to Child
0019f9b8 7527a37c 063f4248 753d8448 00000000 combase!CrashProcessWithWERReport+0x35
0019f9e8 75292bfc 753d8448 7529257e 00000000 combase!DecrementMTAUsageHelper+0x101
(Inline) -------- -------- -------- -------- combase!DecrementMTAUsage+0x9
0019f9f0 7529257e 00000000 00000000 00000000 combase!CDllHost::MTAUninitializeApartmentOnly+0xe
0019fa08 7527543a 00000000 063f4248 00712410 combase!CDllHost::ClientCleanupFinish+0x4d
0019fa30 75276361 00000000 0019fa8c 00000000 combase!DllHostProcessUninitialize+0xa0
0019fa58 7527a452 000d06f6 00712410 00000000 combase!ApartmentUninitialize+0xe4
0019fa70 752c2a1e 000d06f6 00712e18 00712e80 combase!wCoUninitialize+0xd0
0019fa94 74ed3e58 00000003 74c17ff1 a6d0e607 combase!CoUninitialize+0x7e
0019fa9c 74c17ff1 a6d0e607 000b0792 74ed48f0 imm32!CtfImmCoUninitialize+0x48
0019fb7c 74809ea6 00050004 000d06f6 00000000 msctf!TF_Notify+0x581
0019fb98 748080dc 00050004 000d06f6 00000000 user32!CtfHookProcWorker+0x36
0019fbe0 74807fa6 0019fc34 0019fc24 00000000 user32!CallHookWithSEH+0x5c
0019fc08 77bb0006 0019fc24 00000018 0019fc80 user32!__fnHkINDWORD+0x26
0019fc38 710623fb 000b0792 04ff11aa 05480e70 ntdll!KiUserCallbackDispatcher+0x36
0019fc50 050364e4 000b0792 050376d8 05480e70 apphelp!DWM8AND16BitHook_DestroyWindow+0x2b
0019fc8c 05051007 00000000 05055034 00000001 myDLL!myCOMObject_tlbFinalize+0x408a4
0019fcb4 050511c6 0019fcd0 00000001 04ff1318 myDLL!myCOMObject_tlbFinalize+0x5b3c7
0019fcd8 04ff13d3 05055034 77badcce 04ff0000 myDLL!myCOMObject_tlbFinalize+0x5b586
0019fd00 77b807c6 04ff1318 04ff0000 00000000 myDLL+0x13d3
0019fd50 77b6aa5e 00000000 00000000 259704e5 ntdll!LdrpCallInitRoutine+0x43
0019fdb8 77b6e6c8 00000000 0071dd60 00000000 ntdll!LdrpProcessDetachNode+0xbb
0019fdd8 77b6e5af 25970745 0071e560 c000022d ntdll!LdrpUnloadNode+0x100
0019fe18 77b6e4f6 004afcc4 004ae3a4 04ff0000 ntdll!LdrpDecrementModuleLoadCountEx+0xa7
0019fe38 746e9d56 04ff0000 006e33c5 00000000 ntdll!LdrUnloadDll+0x86
0019fe4c 0049261c 04ff0000 00000000 00493034 KERNELBASE!FreeLibrary+0x16
0019fe64 00441895 004afc98 fffffffe 0019fee8 rpopdbg!_GetExceptDLLinfo+0x914bf
Working on the rest now, but my guess is I need to figure out how to do the cleanup properly on the COM object? Maybe in response to DLL_DETACH_PROCESS?
The crash raises APPCRASH with exception 0xc0000602, referring back to
Combase.dll
combase.dll used 0xc0000602 (STATUS_FAIL_FAST_EXCEPTION) code only from
void CrashProcessWithWERReport();
(which called RaiseFailFastException with this code)
CrashProcessWithWERReport called only from DecrementMTAUsageHelper on 2 conditions - CoDecrementMTAUsage called more times than CoIncrementMTAUsage or (and i almost sure in this reason) DecrementMTAUsageHelper called when calling thread hold Loader critical section - so while DLL loading or unloading process. from MSDN
Don't call CoDecrementMTAUsage during process shutdown or inside
dllmain. You can call CoDecrementMTAUsage before the call to start
the shutdown process.
so my guess - some code call CoDecrementMTAUsage in your DLL unloading process (when you call FreeLibrary)
your DLL can not direct call CoIncrementMTAUsage / CoDecrementMTAUsage because this new API, exist begin from win 8 (also check your code on win 8.1 - i think also will be crash), but this api can be indirect called from other system components.
i can assume that your DLL not direct free some used resources or you call FreeLibrary when DLL still holding some resources (so you call FreeLibrary without proper cleanup calls fro DLL) and as result this resources begin free (CoDecrementMTAUsage) in unloading process
what are the next steps in trying to debug this?
you need use debugging with symbols files (say with winDbg). set breakpoints at DecrementMTAUsageHelper, CoDecrementMTAUsage and may be CoIncrementMTAUsage - are i right that call toRtlIsCriticalSectionLockedByThread return TRUE (this api called from begin of DecrementMTAUsageHelper).
in any case post the thread call stack at DecrementMTAUsageHelper call point(just before crash) and possible on CoIncrementMTAUsage too
---------------------- EDIT -------------------------
by view stack trace visible that your DLL call DestroyWindow from DllMain.
apphelp!DWM8AND16BitHook_DestroyWindow
this is the bug just by 2 reasons - at first - read this article -
The thread that gets the DLL_PROCESS_DETACH notification is not
necessarily the one that got the DLL_PROCESS_ATTACH notification. You
can't do anything with thread affinity in your DLL_PROCESS_ATTACH or
DLL_PROCESS_DETACH handler since you have no guarantee about which
thread will be called upon to handle these process notifications. The
classic example of this, which I'm told the Developer Support team run
into with alarming frequency, is a DLL that creates a window in its
DLL_PROCESS_ATTACH handler and destroys it in its DLL_PROCESS_DETACH
handler.
but your crash here by another reason, not listed in article - DllMain have many restrictions, what can not be called inside it. despite DestroyWindow not direct listed here, but as show your case - this is illegal call (even if we called on same thread, on which this window was created) - while your window is destroyed imm32.CtfImmNotify(msctf!TF_Notify) is called
0019fa9c 74c17ff1 a6d0e607 000b0792 74ed48f0 imm32!CtfImmCoUninitialize+0x48
0019fb7c 74809ea6 00050004 000d06f6 00000000 msctf!TF_Notify+0x581
0019fb98 748080dc 00050004 000d06f6 00000000 user32!CtfHookProcWorker+0x36
0019fbe0 74807fa6 0019fc34 0019fc24 00000000 user32!CallHookWithSEH+0x5c
and as result CoUninitialize is called from DllMain !
from MSDN
do not call CoInitialize, CoInitializeEx, or CoUninitialize from the
DllMain function.
here inside FINAL CoUninitialize called DecrementMTAUsage which determinate that we inside loader lock by call RtlIsCriticalSectionLockedByThread and CrashProcessWithWERReport called.
Solution ?
of course the best is fix DLL, but if this is impossible - think next "hack" will be work
HRESULT hr = CoInitialize(0); // asume that we in STA
FreeLibrary(hDLL);
if (0 <= hr) CoUninitialize();
with this CoUninitialize of course anyway will be called from imm32!CtfImmCoUninitialize but this will be NOT FINAL Uninitialize and as result DecrementMTAUsage will be not called
I may not be able to come back to this question immediately, but I thought I'd jot it down now that I've encountered it:
First of, I'm not sure what the proper way to call this is; I've tried "descend" and "resolve" in the title, but I'd like to know if there is a more proper term. In essence, what I'd like is to obtain something like shown on this image I got from Kernel System Calls - ar.linux.it:
Here is a more concrete example - consider the following small and non-working (it will simply cause an "Assertion failed"), but compilable ALSA code:
// atest.c
#include <alsa/asoundlib.h>
static snd_pcm_t *playbck_pcm_handle;
static char wrsrcbuf[256] = {[0 ... 255] = 5}; // initialization gcc specific
static snd_pcm_uframes_t period_frames = 32;
static int ret;
int main() {
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames);
return 0;
}
I can build this with:
gcc -Wall -g atest.c -lasound -o atest
... and then, I can observe assembly with objdump:
$ objdump -d -M intel -S atest
...
int main() {
...
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames);
804842d: 8b 15 40 a1 04 08 mov edx,DWORD PTR ds:0x804a140
...
8048447: e8 0c ff ff ff call 8048358 <snd_pcm_writei#plt>
...
return 0;
8048451: b8 00 00 00 00 mov eax,0x0
}
...
... and this tells me only that a subroutine <snd_pcm_writei#plt> will be called - but it doesn't tell me in, say, which library object file (sidenote: given compilation passed, would that mean that gcc would know about the location of the library as an object file on the current system?)
Then, I can in principle run the program (though not this one), and by using the built-in Linux tracing (ftrace) functionality in /sys/kernel/debug/tracing/trace, obtain a run-time kernel log. Due to the preemptive nature and scheduling of the kernel, one cannot really count on any constancy in order of execution, but in principle, we could get something like this (not from the above example though, as it doesn't do any proper device initialization):
sys_ioctl() {
...
do_vfs_ioctl() {
snd_pcm_playback_ioctl() {
snd_pcm_playback_ioctl1() {
_cond_resched();
copy_from_user() {
...
}
snd_pcm_lib_write() {
snd_pcm_lib_write1() {
_raw_read_lock_irq();
_raw_spin_lock();
snd_pcm_update_hw_ptr() {
snd_pcm_update_hw_ptr0() {
azx_pcm_pointer() {
...
So, this tells me that in response to the snd_pcm_writei command - ultimately sys_ioctl -> snd_pcm_playback_ioctl -> snd_pcm_lib_write will be called, which would be ALSA functions built into the kernel; however, also functions like azx_pcm_pointer() will be called, which are part of a device driver (azx_pcm_pointer is part of the hda-intel driver).
So my question is - is there an application that could output the function "descent" tree of a program from userspace to kernel space - either at compile-time (which would be gcc itself, but with some special switches if they exist for that purpose), or post-compile (like when using objdump, which is however not "runtime", as the analyzed program itself is not running)? E.g. for this example, I'd hope for an output like:
int main() { # atest
...
ret = snd_pcm_writei(playbck_pcm_handle, wrsrcbuf, period_frames); # atest
...
<snd_pcm_writei#plt> # libasound.so ??
...
sys_ioctl() { # ???.(k)o?
...
snd_pcm_playback_ioctl() { # ???.(k)o?
...
azx_pcm_pointer() { # /lib/modules/.../sound/pci/hda/snd-hda-intel.ko
...
...
I understand that the code could take a number of code paths - so hopefully this tool would be able to resolve them all - or allow for setting of variables, to limit the number of code paths; but in general, the output would be a tree (which could then be visualized with, say, graphviz).
I also understand that resolving drivers may not be possible without going into runtime (since a device - and its driver - could be specified at runtime by, say, command line arguments of the user-space program); but I'd hope at least for a notification telling me something like "Here an unspecified driver function would be called".
sidenote: given compilation passed, would that mean that gcc would know about the location of the library as an object file on the current system?
Yes, this is exactly why you have to specify -lasound. This function was found by linker. If for some reasons libasound don't have it - you'll get linking error.
So my question is - is there an application that could output the function "descent" tree of a program from userspace to kernel space
None of i've heard of. It is surely possible, but transition between user and kernel spaces are far from mere function call. In fact, userspace library using syscall() function, which sets appropriate system call number and parameters to registers and issuing special CPU interrupt, which kernel catches and then executes - so neither gcc nor any object code parsing tools can trace this transition. My best guess is dumping both user and kernel spaces and connecting this logs afterwards, but it would be tricky.
Why do you want this, by the way?
I have an app running as a Windows Service. Today, I was notified that the service died. I found a event viewer entry whose basic info is: faulting module kernel32.dll, version 6.0.6002.18740, time stamp 0x50b58c3d, exception code 0xc0000005, fault offset 0x0003fc2e
I'm sure that there is a bug in my code. Can I determine the kernel32.dll function (where the exception came from) from the offset? I'm planning to backtrack to the call in my code.
I agree with what is said in the comments, but anyway I think the answer can be useful. Here is how you can find function name using Windows debugging tools from SDK provided that EventViewer reported offset of failing instruction in kernel32.dll.
First, install Windows debugging tools and configure path to Microsoft public symbol server. Instructions are available online, for example, this video: http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-Building-your-USB-thumbdrive
Start windows debugger attached to your process or just any process in the system. kernel32.dll is one of the first DLLs any process loads, it is very unlikely that it is rebased. So kernel32.dll’s base address is the same in all processes.
Get base address of kernel32.dll by running “list modules” command in debugger
0:006> lm m kernel32
start end module name
7c800000 7c8f6000 kernel32 (pdb symbols) c:\debuggers\symbols\kernel32.pdb\A22E3A9843CC45B4A2BFA31377127D422\kernel32.pdb
So the base address is 7c800000. Now run “disassemble single instruction” command using DLL base address and offset:
0:006> u 0x7c800000+0x0003fc2e l 1
kernel32!BasepCopyFileExW+0x859:
7c83fc2e 53 push ebx
So BasepCopyFileExW is the function name. (The result on your system may be different.)