Ответ 1
Один из вариантов - полностью препроцитировать ваш файл C, развернуть все макросы и затем скомпилировать полученный предварительно обработанный файл.
Например, рассмотрим эту простую программу на 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;
}
Скомпилируйте его, сохранив временные файлы (включая предварительно обработанный исходный код):
gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps
Это должно дать вам предварительно обработанную версию prep.c
, prep.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;
}
Теперь вы хотите избавиться от # -lines. Так или иначе, если они останутся, они будут влиять на информацию об отладке. Удивительно, но это означает, что макрос не будет расширяться в gdb
.
К счастью, grep
может помочь (я не grep pro, поэтому проверьте правильность параметров, но они, похоже, работают для меня в Windows с MinGW x86):
grep ^[^\#].*$ prep.i > 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;
}
Теперь вы можете скомпилировать его:
gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe
И запустите его в gdb
:
gdb prepi.exe
Выполните следующие команды:
b main
r
l
Это выполнит приложение до 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)
Как вы можете видеть, тело макроса теперь находится в простом виде.
Одна небольшая проблема заключается в том, что многострочные макросы (те, которые продолжаются с \
) расширяются в одну строку. Я не нашел возможности развернуть их на несколько строк, но вы можете сделать это вручную.