Set breakpoint in C or C++ code programmatically for gdb on Linux

95,188

Solution 1

One way is to signal an interrupt:

#include <csignal>

// Generate an interrupt
std::raise(SIGINT);

In C:

#include <signal.h>
raise(SIGINT);

UPDATE: Microsoft Docs says that Windows doesn't really support SIGINT, so if portability is a concern, you're probably better off using SIGABRT.

SIGINT is not supported for any Win32 application. When a CTRL+C interrupt occurs, Win32 operating systems generate a new thread to specifically handle that interrupt. This can cause a single-thread application, such as one in UNIX, to become multithreaded and cause unexpected behavior.

Solution 2

By looking here, I found the following way:

void main(int argc, char** argv)
{
    asm("int $3");
    int a = 3;
    a++;  //  In gdb> print a;  expect result to be 3
}

This seems a touch hackish to me. And I think this only works on x86 architecture.

Solution 3

In a project I work on, we do this:

raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */

(In our case we wanted to crash hard if this happened outside the debugger, generating a crash report if possible. That's one reason we used SIGABRT. Doing this portably across Windows, Mac, and Linux took several attempts. We ended up with a few #ifdefs, helpfully commented here: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)

Solution 4

Disappointing to see so many answers not using the dedicated signal for software breakpoints, SIGTRAP:

#include <signal.h>

raise(SIGTRAP); // At the location of the BP.

On MSVC/MinGW, you should use DebugBreak, or the __debugbreak intrinsic. A simple #ifdef can handle both cases (POSIX and Win32).

Solution 5

__asm__("int $3"); should work:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    __asm__("int $3");
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}
Share:
95,188
J. Polfer
Author by

J. Polfer

Updated on February 15, 2021

Comments

  • J. Polfer
    J. Polfer over 3 years

    How can I set a breakpoint in C or C++ code programatically that will work for gdb on Linux?

    I.e.:

    int main(int argc, char** argv)
    {
        /* set breakpoint here! */
        int a = 3;
        a++;  /*  In gdb> print a;  expect result to be 3 */
        return 0;
    }
    
    • Stuart Golodetz
      Stuart Golodetz over 13 years
      Very much a side note (sorry to nitpick), but if you're worried about portability then you're probably also worried about correctness - hence int main rather than void main.
    • J. Polfer
      J. Polfer over 13 years
      @Stuart - Fixed. Should have done that a while ago.
    • Lightness Races in Orbit
      Lightness Races in Orbit about 9 years
      @J.Polfer: The return 0 is not necessary, though, and is just noise!
    • Jimmio92
      Jimmio92 over 2 years
      @LightnessRacesinOrbit the return 0; is 100% necessary. Besides the warning your compiler should throw at you, this can corrupt the stack on older/embedded systems, and as such should ALWAYS be done out of habit and correctness. Forget a return in other places in your code and you're guaranteed to pay for it on modern desktop systems, too.
    • handle
      handle over 2 years
    • Jonathan Wakely
      Jonathan Wakely over 2 years
      @Jimmio92 No, main is special in all versions of C++ and also in C since C99. Reaching the final } of main without returning is equivalent to return 0; so the compiler should not warn, and it cannot corrupt anything. In C89 it's undefined, but that's the exception to the rule, not the general case as you imply by "100% necessary". C++98 and C99 are not new, time to update your knowledge ;-)
    • Jimmio92
      Jimmio92 over 2 years
      @JonathanWakely Maybe you meant that comment as helpful, but I took it the polar opposite. So let me address as calmly as I can muster. One, I mentioned your own code must return if you tell the compiler to expect it. Two, it should warn you. Just because the standard automatically fixes your mistakes because of a wrapper around main doesn't mean you should make them. Three, I use C++17 in clang. Four, I have literally encountered this as a bug in low level code. C/C++ can be used without the standard library and without an operating system. Take your "learn it again" attitude elsewhere.
    • Jonathan Wakely
      Jonathan Wakely over 2 years
      It's not a mistake though. The standard guarantees the behaviour, relying on that is not a mistake. You said "100% necessary" and that's just wrong.
  • Håvard S
    Håvard S over 13 years
    Yes, this should work across operating systems/compilers/debuggers.
  • Cascabel
    Cascabel over 13 years
    I don't know other debuggers, but gdb is pretty flexible about signal handling.
  • Håvard S
    Håvard S over 13 years
    @Jefromi Most decent debuggers have knobs and switches that allow you to control how they handle various signals.
  • Håvard S
    Håvard S over 13 years
    And only with compilers supporting the AT&T assembly syntax. In particular, Microsoft's compiler (cl.exe) does not support this syntax, but uses a different syntax.
  • js.
    js. over 13 years
    the question was about linux, so i guess we can assume that the gcc syntax will work for x86.
  • J. Polfer
    J. Polfer over 13 years
    BTW - I did try the above on my x86 machine and it did work. I was curious if there was a better way of doing it. Looks like there is.
  • mathk
    mathk about 13 years
    As usual windows does not look like the others :)
  • JBRWilkinson
    JBRWilkinson almost 12 years
    We found SIGTRAP better on some Unices
  • Machta
    Machta about 10 years
    I am using mingw on windows so the other suggestions can't help me. Raising SIGINT signal just terminates the application, SIGTRAP is not defined in mingw headers... Using int instruction actually sends SIGTRAP and gdb breaks nicely on the appropriate line.
  • Fernando Gonzalez Sanchez
    Fernando Gonzalez Sanchez over 9 years
    in Windows, MSVC you can use __debug_break, DebugBreak or _asm {int 3}.
  • Morix Dev
    Morix Dev almost 9 years
    @FernandoGonzalezSanchez: actually the function name is __debugbreak() and NOT __debug_break(), as you can see here
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 8 years
    In Linux, int 3 raises a SIGTRAP.
  • Mawg says reinstate Monica
    Mawg says reinstate Monica almost 8 years
    I like to #define this, so that I don't have toi remember the syntax. I have it sprinkled throughout my code, sometimes in place of assert(), since stopping the debiugger let's me examine all variables & the stack. And, of course, like assert, I don't have to remove it for production code
  • Jason Doucette
    Jason Doucette over 7 years
    Is it possible to issue "signal 0" to continue program the program in a paused state? It would be nice to be able to use 'n' or 's' from this point, without a 'c' being issued.
  • Jason Orendorff
    Jason Orendorff over 7 years
    @JasonDoucette If you really just want the program to pause, you might want to add a breakpoint() function in your program (it can be empty or just contain a print statement) and add break breakpoint to your ~/.gdbinit.
  • Alex
    Alex almost 7 years
    Which library ?
  • Dellowar
    Dellowar over 6 years
    Nice and spooky. I like it.
  • Benjamin Crawford Ctrl-Alt-Tut
    Benjamin Crawford Ctrl-Alt-Tut over 4 years
    This is part of the standard C++ library and is cross-platform where C++11-compliant compilers exist. This however, raises SIGABRT, which is not really an appropriate signal to raise in this instance.
  • Benjamin Crawford Ctrl-Alt-Tut
    Benjamin Crawford Ctrl-Alt-Tut over 4 years
    Interesting that this has 10 upvotes when the question constraints of "Linux" and "GDB" give plenty of options outside of resorting to assembly, which should always be a last resort for portability's sake if nothing else. Please see some of the other answers.
  • ergohack
    ergohack over 3 years
    Some platforms (e.g. Msys2), do not have SIGTRAP defined.
  • Ralph
    Ralph almost 3 years
    @BenjaminCrawfordCtrl-Alt-Tut In this specific case conceptually raising a SIGTRAP signal is a good idea. Of course the answer could be improved by specifying to do raise() instead, but it is valuable to see what goes behind it.
  • Benjamin Crawford Ctrl-Alt-Tut
    Benjamin Crawford Ctrl-Alt-Tut over 2 years
    @Ralph int $3 is only "what goes behind it" on x86 systems, which the question doesn't specify...