- 论坛徽章:
- 0
|
没人帮忙,只好自己解决了!
分析:
借用jjh编译的cc1编译程序,就可以展开宏。于是想到是gcc的原因。
使用readelf命令把编译后的程序进行对比,得到的主要差别如下:
161,166c195,201
< 1 0 0 0 test.c
< 2 1 0 0 stdlib.h
< 3 2 0 0 cdefs.h
< 4 2 0 0 _null.h
< 5 2 0 0 _types.h
< 6 3 0 0 _types.h
---
> 1 1 0 0 stdlib.h
> 2 2 0 0 cdefs.h
> 3 2 0 0 _null.h
> 4 2 0 0 _types.h
> 5 3 0 0 _types.h
> 6 0 0 0 test.c
> 7 0 0 0 <internal>
226,300c244,314
< DW_MACINFO_start_file - lineno: 0 filenum: 1
< DW_MACINFO_define - lineno : 0 macro : __STDC__ 1
...
---
> DW_MACINFO_define - lineno : 1 macro : __STDC_HOSTED__ 1
> DW_MACINFO_define - lineno : 2 macro : __GNUC__ 3
前者可以展开宏,后者不能展开宏。主要区别在于test.c的位置以及是否含有DW_MACINFO_start_file
解决:
有两种方法:
1 使用官方的gcc。但是发现编译内核的时候有些编译选项不能识别。影响太大。
2 修改gdb。费些事,但可以使影响降到最小。
我们采用第二种方法。主要修改文件为dwarf2read.c中的函数dwarf_decode_macros和file_full_name.
# diff dwarf2read.c.bak dwarf2read.c
9038a9039,9041
>
> if (!strcmp("<internal>", fe->name))
> fe = &lh->file_names[file - 2];
9333,9346c9336,9344
< if (! current_file)
< complaint (&symfile_complaints,
< _("debug info gives macro %s outside of any file: %s"),
< macinfo_type ==
< DW_MACINFO_define ? "definition" : macinfo_type ==
< DW_MACINFO_undef ? "undefinition" :
< "something-or-other", body);
< else
< {
< if (macinfo_type == DW_MACINFO_define)
< parse_macro_definition (current_file, line, body);
< else if (macinfo_type == DW_MACINFO_undef)
< macro_undef (current_file, line, body);
< }
---
> if (! current_file) {
> current_file = macro_start_file (lh->num_file_names, line,
> current_file, comp_dir, lh, cu->objfile);
> }
>
> if (macinfo_type == DW_MACINFO_define)
> parse_macro_definition (current_file, line, body);
> else if (macinfo_type == DW_MACINFO_undef)
> macro_undef (current_file, line, body);
调试内核展开宏注意事项:
1 在config生成的Makefile中如下行
.include "$S/conf/kern.pre.mk"
后加入:
CFLAGS+=-gdwarf-2 -g3
2 make cleandepend; make depend; make kernel
3 启动虚拟机完成连接
4 (gdb) macro expand LINKER_GET_NEXT_FILE_ID(lf->id)
expands to: do { linker_file_t lftmp; retry: do { uintptr_t _tid = (uintptr_t)((__curthread())); if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, 0x00000004, (_tid))) _mtx_lock_sleep((((&kld_mtx))), _tid, ((0)), (((void *)0)), (0)); } while (0); for ((lftmp) = (((&linker_files))->tqh_first); (lftmp); (lftmp) = (((lftmp))->link.tqe_next)) { if (next_file_id == lftmp->id) { next_file_id++; do { uintptr_t _tid = (uintptr_t)((__curthread())); if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, (_tid), 0x00000004)) _mtx_unlock_sleep((((&kld_mtx))), ((0)), (((void *)0)), (0)); } while (0); goto retry; } } (lf->id) = next_file_id; do { uintptr_t _tid = (uintptr_t)((__curthread())); if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, (_tid), 0x00000004)) _mtx_unlock_sleep((((&kld_mtx))), ((0)), (((void *)0)), (0)); } while (0); } while(0)
嗯,太难看了,可惜set print pretty对它也没用。没关系,我们可以把它拷贝到一个临时文件tmp里,然后执行:
# indent tmp
再看看:
do {
linker_file_t lftmp;
retry: do {
uintptr_t _tid = (uintptr_t) ((__curthread()));
if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, 0x00000004, (_tid)))
_mtx_lock_sleep((((&kld_mtx))), _tid, ((0)), (((void *)0)), (0));
} while (0);
for ((lftmp) = (((&linker_files))->tqh_first); (lftmp); (lftmp) = (((lftmp))->link.tqe_next)) {
if (next_file_id == lftmp->id) {
next_file_id++;
do {
uintptr_t _tid = (uintptr_t) ((__curthread()));
if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, (_tid), 0x00000004))
_mtx_unlock_sleep((((&kld_mtx))), ((0)), (((void *)0)), (0));
} while (0);
goto retry;
}
} (lf->id) = next_file_id;
do {
uintptr_t _tid = (uintptr_t) ((__curthread()));
if (!atomic_cmpset_int(&((((&kld_mtx))))->mtx_lock, (_tid), 0x00000004))
_mtx_unlock_sleep((((&kld_mtx))), ((0)), (((void *)0)), (0));
} while (0);
} while (0)
Enjoy! |
|