How to understand an _asm command in Visual C++ - c++

I am picking up someone else's C++ code in MS Visual Studio and have encountered the line:
if (l > n) _asm{int 3};
I understand that is is meant to break to the debugger. I also understand that it's deprecated and has been replaced with:
__debugbreak()
My question is... how does this work? Why should such an inline assembler command result in the debugger?

It is the same thing as setting a breakpoint with the IDE, but the difference is that with the IDE or any other debugger, it sets a breakpoint overwriting the chosen opcode with int 3 and with __asm { int 3 }, it sets as a new opcode line.

To add to the comment, int 3 is an assembly instruction that triggers a hardware interrupt, which causes the running thread ( your code ) to halt while the operating system services that interrupt. Not sure of the specifics, but the debugger must be able to hook into the os to get a notification of that interrupt, and act appropriately.
Read more: https://blogs.msdn.microsoft.com/kangsu/2005/09/07/no-more-int-3/

Related

Inline Assembly with Borland/Embarcadero

A quick question here:
I'm trying to experiment with inline assembly using Embarcadero C++ Builder XE3 on 32-bit Windows 7, specifically to start re-teaching myself assembly with the possibility of future pragmatic application.
So far I've been able to write a set of instructions within a simple console project which compiles fine using all C++ Builder syntax at my disposal:
int _tmain(int argc, _TCHAR* argv[]) {
_asm{
mov dl, 0x24
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x25
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x26
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x27
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
int 0x20 // terminate COM
}
return 0;
}
This compiles ok, and these instructions work straight in NASM and the Windows native DEBUG environment. What I expect is a simple write to the console: $%&' followed by a successful termination.
However, when I try to run Project1.exe via the command line I immediately get a standard Win7 runtime error popup which disappears after a few seconds and terminates the program.
Running with debugging, I seem to be successfully reaching the first int 0x21 before it hangs, at which point Borland gives me the message:
Project Project1.exe raised exception class $C00000005 with message 'access violation at 0x00401213: read of address 0xffffffff'.
My theory is that I'm not properly initializing the segment with a 256-byte offset (NASM would use something like org 0x100 at the beginning of the instruction set). But I'm not entirely sure that's the issue.
Any ideas?
Those int 0x21 instructions are for MS-DOS and not Windows. They mean something else in a Windows program, with the result that you go up in flames.
I work primarily in C++ Builder, But I've also programmed assembly and nasm for production code (mainly on micros). My recommendation is not to go near C++ builder for anything you don't have to. Learning can be an art and the way you go about learning has a lot to do with the outcome. C++ Builder integration with assembly is a detour through South Compton. Even though it may not be the way you normally work, it will pay off big time to learn nasm in pure command line.

QTCreator: GDB debugs code once, then drops to assembly

Using Qt 5.1.1 for Windows 32-bit (with MinGW 4.8), when debugging GDB wants to drop into dissassembly while debugging code after the first time.
I make a "Plain C++" project, insert some simple code:
int x = 5;
cout << x << endl;
return 0;
Build, and debug it with a breakpoint on first line. First time through it debugs just fine stepping through the code with "Step Over". Any debug session after that, it will drop into dissamebly view of ntdll when it hits cout (or anything else library related).
Operate By Instruction is not checked and there is debug information for my code. It works as expected once, then refuses to.
I can delete the build folder and the .pro.user file and the project still exhibits the same behavior after a new build. Even tried wiping my QTProject settings folder. There seems to be no way to debug just my code more than once without it wanting to drop into assembly instead of stepping over statements. If I make a new project, I can debug it normally once, then it starts behaving the same way.
Looking for a fix or suggestions of things to try.
Had a chance to go back...diffed the debugger log on the good initial vs sequential runs. Everything looks similar until I get to this in good run:
=thread-exited,id="2",group-id="i1"
sThread 2 in group i1 exited
~"[Switching to Thread 5588.0x239c]\n"
=thread-selected,id="1"
sThread 1 selected
Bad runs never have that. Later, this is unique to bad run:
>1272^done,threads=[{id="2",target-id="Thread 7148.0x242c",frame=
{level="0",addr="0x7792fd91",func="ntdll!RtlFindSetBits",args=
[],from="C:\\Windows\\system32\\ntdll.dll"},state="stopped"},
//LINES BELOW COMMON TO GOOD+BAD
{id="1",target-id="Thread 7148.0x1bbc",frame=
{level="0",addr="0x00401606",func="main",args=
[],file="..\\untitled8\\main.cpp",fullname=
"C:\\Users\\Andrew\\Desktop\\untitled8\\main.cpp",line="7"},
state="stopped"}],current-thread-id="1"*
Then once it hits the breakpoint, good run shows this:
*stopped,reason="end-stepping-range",frame={addr="0x00401620",func="fu0__ZSt4cout",args[],
file="..\untitled8\main.cpp",
fullname="C:\Users\Andrew\Desktop\untitled8\main.cpp",line="9"},
thread-id="1",stopped-threads="all"
Bad run shows this:
>*stopped,reason="signal-received",signal-name="SIGTRAP",signal-meaning="Trace/breakpoint trap",
frame={addr="0x7792000d",func="ntdll!LdrFindResource_U",args=[],
from="C:\\Windows\\system32\\ntdll.dll"},thread-id="2",stopped-threads="all"
dNOTE: INFERIOR SPONTANEOUS STOP sStopped.
dState changed from InferiorRunOk(11) to InferiorStopOk(14) [master]
dSIGTRAP CONSIDERED HARMLESS. CONTINUING.
sStopped: "signal-received"
>=thread-selected,id="2"
sThread 2 selected
<1283-thread-info
>1283^done,threads=[{id="2",target-id="Thread 7148.0x242c",frame=
{level="0",addr="0x7792000d",func="ntdll!LdrFindResource_U",args=[],
from="C:\\Windows\\system32\\ntdll.dll"},state="stopped"},
{id="1",target-id="Thread 7148.0x1bbc",
frame={level="0",addr="0x756a133d",func="KERNEL32!GetPrivateProfileStructA",
args=[],from="C:\\Windows\\syswow64\\kernel32.dll"},state="stopped"}],current-thread-id="2"
<1284-stack-list-frames 0 20
>1284^done,stack=[frame={level="0",addr="0x7792000d",func="ntdll!LdrFindResource_U",
from="C:\\Windows\\system32\\ntdll.dll"},
frame={level="1",addr="0x779af926",
func="ntdll!RtlQueryTimeZoneInformation",
from="C:\\Windows\\system32\\ntdll.dll"},frame={level="2",addr="0x75f45dd1",func="??"},
frame={level="3",addr="0x00000000",func="??"}]
<1285-stack-select-frame 0
<1286disassemble 0x7791fff9,0x77920071
<1287bb options:fancy,autoderef,dyntype vars: expanded:return,local,watch,inspect typeformats: formats: watchers:
>1285^done
>&"disassemble 0x7791fff9,0x77920071\n"
>~"Dump of assembler code from 0x7791fff9 to 0x77920071:\n"
>~" 0x7791fff9 <ntdll!LdrFindResource_U+60953>:\t"
>&"Cannot access memory at address 0x7791fff9\n"
>1286^error,msg="Cannot access memory at address 0x7791fff9"
sDisassembler failed: Cannot access memory at address 0x7791fff9
Looks like for some reason that extra thread is not exiting when expected and qtcreator/gdb convince themselves there are breakpoints in ntdll that I want to stop at.

STATUS_SINGLE_STEP in Visual Studio

I am trying to add a VEH handler in my code, and in it, upon first STATUS_ACCESS_VIOLATION, I set the Trace bit to 1 by setting the exc->ContextRecord->EFlags |= 0x100 so as to single step the violation. I see that the handler is getting called for ACCESS_VIOLATION but never getting called with exc->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP after stepping over the offending code.
I am suspecting that the debugger is removing the 0x100 from the EFlags when it runs its handler. If I run in a command prompt, I see that it is getting hit. Is there anyway I can make the debugger not alter the trace flag and allow my handler to get called with ExceptionCode = STATUS_SINGLE_STEP?
thanks

Program crashes with 0xC000000D and no exceptions - how do I debug it?

I have a Visual C++ 9 Win32 application that uses a third-party library. When a function from that library is called with a certain set of parameters the program crashes with "exception code 0xC000000D".
I tried to attach Visual Studio debugger - no exceptions are thrown (neither C++ nor structured like access violations) and terminate() is not called either. Still the program just ends silently.
How does it happen that the program just ends abnormally but without stopping in the debugger? How can I localize the problem?
That's STATUS_INVALID_PARAMETER, use WinDbg to track down who threw it (i.e. attach WinDbg, sxe eh then g.
Other answers and comments to the question helped a lot. Here's what I did.
I notices that if I run the program under Visual Studio debugger it just ends silently, but if I run it without debugger it crashes with a message box (usual Windows message box saying that I lost my unsaved data and everyone is sooo sorry).
So I started the program wihtout debugger, let it crash and then - while the message box was still there - attached the debugger and hit "Break". Here's the call stack:
ntdll.dll!_KiFastSystemCallRet#0()
ntdll.dll!_ZwWaitForMultipleObjects#20() + 0xc bytes
kernel32.dll!_WaitForMultipleObjectsEx#20() - 0x48 bytes
kernel32.dll!_WaitForMultipleObjects#16() + 0x18 bytes
faultrep.dll!StartDWException() + 0x5df bytes
faultrep.dll!ReportFault() + 0x533 bytes
kernel32.dll!_UnhandledExceptionFilter#4() + 0x55c bytes
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//SomeThirdPartyLibraryFunctionAddress
//OurCodeInvokingThirdPartyLibraryCode
so obviously that's some problem inside the trird-party library. According to MSDN, UnhandledExceptionFilter() is called in fatal situations and clearly the call is done because of some problem in the library code. So we'll try to work the problem out with the library vendor first.
If you don't have source and debugging information for your 3rd party library, you will not be able to step into it with the debugger. As I see it, your choices are;
Put together a simple test case illustrating the crash and send it onto the library developer
Wrap that library function in your own code that checks for illegal parameters and throw an exception / return an error code when they are passed by your own application
Rewrite the parts of the library that do not work or use an alternative
Very difficult to fix code that is provided as object only
Edit You might also be able to exit more gracefully using __try __finally around your main message loop, something like
int CMyApp::Run()
{
__try
{
int i = CWinApp::Run();
m_Exitok = MAGIC_EXIT_NO;
return i;
}
__finally
{
if (m_Exitok != MAGIC_EXIT_NO)
FaultHandler();
}
}

process termination C++

I have the following problem: I have an application (server that never ends) written in C++ running as a service containing inside the main thread also 3 threads (mainly doing IO).
In the main loop I CATCH all possible exceptions.
The process terminated and nothing was printed either by the main loop or by the threads themselves. I saw in the event log that the process stopped with code 1000.
Does Windows creates Core files like in unix ?
If from the event log I get a memory address, is there any way of knowing in which part in the application it occurred?
Maybe this is a clue: at the same time that it happened I started another application (not the same type).
try to set windbg as the postmortem debugger.
install windbg
from commandline execute "windbg -I"
start you application, then you when your application get an unhandled exception,
the windbg will be activated .
from windbg use "kb" or "!uniqstack" to see the stacktrace.
look here for more commands.
and look here for how to analysis.
and try use SEH:
#include "windows.h"
#include "stdio.h"
DWORD FilterFunction()
{
printf("you will see this message first.\n");
return EXCEPTION_EXECUTE_HANDLER;
}
int main(char** argv, int c)
{
__try
{
int this_will_be_zero = (c == 9999);
int blowup = 1 / this_will_be_zero;
}
__except ( FilterFunction())
{
printf("you will see this message\n");
}
return 0;
}
Bear in mind that catch(...) does not intercept everything that can go wrong in your code, unless you are using Structured Exception Handling. Eg
#include "stdio.h"
int main(char** argv, int c)
{
try {
int this_will_be_zero = (c == 9999);
int blowup = 1 / this_will_be_zero;
} catch (...) {
printf("you won't see this message\n");
}
}
You need to use the /EHa compiler switch when building your application in order to catch windows structured exceptions (such as access violation) with the C++ try/catch constructs.
In Visual Studio this is in project properties Configuration Properties -> C/C++ -> Code Generation -> Enable C++ Exceptions. You want "Yes With SEH Exceptions (/EHa)". I remember reading setting this has some significant drawbacks, although I cannot recall what they were exactly.
Link: MSDN on C++ exception handling model
Edit: As whunmr suggests, directly using structured exceptions is probably better idea than /EHa
Does Windows creates Core files like in unix ?
it does not, automatically. however you can enable such a files by
either implementing it in your code or by using external application
as windbg, or Dr. Watson
If from the event log I get a memory address, is there any way of knowing in which part in the application it occurred?
There is no way if in general, if you don't keep debug information files (pdb)
Maybe this is a clue: at the same time that it happened I started another application (not the same type).
this is not helpful information, unless both of the applications are interacted each other
Windows will whatever program you are using as a debugger depending on the setting in:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="0"
"Debugger"="My_Debugger" -p %ld -e %ld"
"UserDebuggerHotKey"=dword:00000000
You can change My_Debugger to the full path of whatever program/IDE you are using for debugging.
This is often set to Dr Watson which will create a log entry of the crash which is not what you want.