简体   繁体   English

如何使用gdb逐步执行宏扩展的每一行

[英]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. 我有一个宏,其定义大约有50行,并且有很多'if else'语句。 This macro def'n appears in a .h file. 此宏def'n出现在.h文件中。 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. 我在TUI模式下运行'gdb',但是当执行到达该宏时,代码窗口变为空白并仅在宏代码执行后返回。 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. 我有一个代码,它可以运行几百个.c和.h文件。

One option is to fully preprocess your C file, expanding all macros in it, and then compile the resulting preprocessed file. 一种选择是完全预处理C文件,扩展其中的所有宏,然后编译生成的预处理文件。

For example, consider this simple C program: 例如,考虑这个简单的C程序:

// 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): 这应该给你一个preprocessed版本的prep.cprep.i (为简洁起见缩短):

# 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. 现在你想摆脱#-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 . 令人惊讶的是,这意味着宏不会在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可以提供帮助(我不是grep专业人员,所以请检查params是否正确,但它们似乎适用于使用MinGW x86的Windows):

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

This will give you a stripped version of prep.i in prepi.c : 这将为您提供prep.i中的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运行它:

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: 这将执行app直到main()并列出与到达的断点相关的源代码:

(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." “人们不只是step成宏。”

You still have a few options: 你还有几个选择:

  1. Use the preprocessor, as @WhozCraig recommended. 使用预处理器,如@WhozCraig推荐的那样。
  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. 如果您绝对不想重新编译并且您对汇编代码感到满意,则可以使用stepi执行宏一台机器指令。

If all the above does not work, really you should go back to using printf/fprintf within your large macro. 如果以上所有方法都不起作用,那么你应该回到在大宏中使用printf/fprintf

I had to deal with a 300 lines MACRO, burried deep into the library. 我不得不处理300线MACRO,深入图书馆。 This was easier than compiling by hand and dealing with post-processed files. 这比手工编译和处理后处理文件更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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