简体   繁体   中英

how to see step by step execution of each line of a macro expansion using gdb

i am having a macro whose definition runs into around 50 lines and has lot of 'if else' statements. This macro def'n appears in a .h file. I am running 'gdb in TUI mode', but when the execution reaches that macro, the code window goes blank and returns back only after the macro code gets executed. I want to see line by line execution of the full macro code. Please let me know how can that be done (one way is to replace the macro with its definition in the code and then recompile it. i don't want to use this option as there are several such macros in my code).

Any help will be greatly appreciated. looking forward to get the solution for this problem. Please let me know if there is some other way for this issue rather than the usage of preprocessed file ? i am having a code which runs into several hundred .c & .h files.

One option is to fully preprocess your C file, expanding all macros in it, and then compile the resulting preprocessed file.

For example, consider this simple C program:

// file: prep.c
#include <stdio.h>

#define MY_BIG_MACRO \
  int i; \
  printf("integers from 0 to 9:\n"); \
  for (i = 0; i < 10; i++) \
    printf("%d ", i); \
  printf("\n");

int main(void)
{
  MY_BIG_MACRO
  return 0;
}

Compile it, saving the temporary files (including the preprocessed source code):

gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps

This should give you a preprocessed version of prep.c , prep.i (shortened for brevity):

# 1 "prep.c"
# 1 "C:\\MinGW\\msys\\1.0\\home\\Alex//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "prep.c"

# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.6.2/../../../../include/stdio.h" 1 3

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
# 3 "prep.c" 2
# 11 "prep.c"
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

Now you want to get rid of the #-lines. One way or another, if they are left in, they will affect the debug info. Surprisingly, that means that the macro won't appear expanded in gdb .

Thankfully, grep can help (I'm not a grep pro, so check whether the params are correct, but they seem to work for me on Windows with MinGW x86):

grep ^[^\#].*$ prep.i > prepi.c

This will give you a stripped version of prep.i in prepi.c :

typedef unsigned int size_t;
typedef short unsigned int wchar_t;
typedef short unsigned int wint_t;

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

Now you can compile it:

gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe

And run it in gdb :

gdb prepi.exe

Issue the following commands:

b main
r
l

This will execute the app until main() and list the source code related to the reached breakpoint:

(gdb) b main
Breakpoint 1 at 0x40643f: file prepi.c, line 184.
(gdb) r
Starting program: C:\MinGW\msys\1.0\home\Alex\prepi.exe
[New Thread 7340.0x20c4]

Breakpoint 1, main () at prepi.c:184
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
(gdb) l
179              const wchar_t * __restrict__, __gnuc_va_list);
180     int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (c
onst wchar_t * __restrict__,
181              const wchar_t * __restrict__, __gnuc_va_list);
182     int main(void)
183     {
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
185       return 0;
186     }
(gdb)

As you can see, the macro body is now in the plain view.

One small problem here is that multi-line macros (those continued with \\ ) are expanded into a single line. I haven't found an option to expand them into multiple lines, but you can do that manually.

"One does not simply step into macros."

You still have a few options:

  1. Use the preprocessor, as @WhozCraig recommended.
  2. For a little less code bloat, convert your macros to functions and re-compile.
  3. If you absolutely don't want to recompile and you're comfortable with assembly code you can use stepi to execute your macro one machine instruction at a time.

If all the above does not work, really you should go back to using printf/fprintf within your large macro.

I had to deal with a 300 lines MACRO, burried deep into the library. This was easier than compiling by hand and dealing with post-processed files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM