gdb 是否支持选择性的 `auto-solib-add`?
Does gdb support selective `auto-solib-add`?
我正在调试一个大型命令行程序,它会在启动时加载许多 *.so 库。
如果 auto-solib-add
是 on
,加载的符号太多,gdb
就会挂起。因此,我们的最佳做法是在 .gdbinit
中关闭 auto-solib-add
并通过 sharedlibrary
.
手动加载所选库的符号
有些*.so库我们不能在程序启动后运行 sharedlibrary
,因为这些库还没有加载。我们需要在程序中执行一个命令,比如 dosomething
来触发这些库的加载。之后,这些库将在 gdb
中可见 sharedlibrary
。
这适用于大多数调试场景,但有一种情况我遇到了麻烦。通过 dosomething
加载的库之一称为 libfoo.so
,其 API foo()
在 dosomething
期间执行。如何在 dosomething
期间进入 foo()
?换句话说,根据程序阶段的以下心理图像,我如何在 stage j
之后和 stage k
之前暂停 gdb
以便我可以在执行 foo()
之前加载符号?
* ...
* Stage i: In the main program interface, the command `dosomething` is issued. This will trigger the loading of some dynamic linked libraries, including `libfoo.so`.
* ...
* Stage j: `libfoo.so` is loaded.
* ...
* Stage k: `foo()` is executed.
* ...
* Stage l: The command `dosomething` finishes and returns the control to the user in the main program.
* ...
注意:由于某些技术原因,我也无法在主程序启动后和运行 dosomething
触发加载那些库之前打开auto-solib-add
。否则,我知道这可能是一种解决方法,而不是尝试在 stage j
和 stage k
之间的最佳位置手动暂停。
My mental image is that the following happens in order:
您的心智模型不正确:如果您可以调用 foo()
,那么 定义 foo()
的库一定已经加载。没有 .so
文件的“按需”加载——它们 仅 加载,因为可执行文件直接链接到 .so
(在这种情况下 .so
在可执行文件的单个指令运行之前加载), 或 作为 dlopen()
调用的结果。
您可以通过在 foo()
的 caller 上设置断点并使用 GDB info shared
命令检查所有加载的 .so
来验证这一点]s.
假设 libfoo.so
实际上已经加载,你可以要求 GDB 使用 shared libfoo.so
命令为这个库添加符号。之后,您将能够在 foo()
.
上设置断点
如果libfoo.so
在info shared
输出中不是,那么你没有准确描述你的程序,你的问题无法回答。
我通过阅读这篇文章开始思考:https://developer.ibm.com/technologies/linux/tutorials/l-dynamic-libraries/
如果我们将三个库的使用场景编号为:
- 静态库。
- 共享库动态链接。
- 共享库动态加载。
libfoo.so
的加载属于 3),其中 dlopen
库用于触发从应用程序加载(但仍然通过处理 2 的系统动态链接器)。
运行 程序启动后 gdb
中的以下内容将允许我们停止每次动态加载。
sharedlibrary libdl.so
b dlopen
我在 stage j
和 stage k
之间寻找的点可能就在 dlopen
returns 之后到它的调用者 libfoo.so
.
我正在调试一个大型命令行程序,它会在启动时加载许多 *.so 库。
如果 auto-solib-add
是 on
,加载的符号太多,gdb
就会挂起。因此,我们的最佳做法是在 .gdbinit
中关闭 auto-solib-add
并通过 sharedlibrary
.
有些*.so库我们不能在程序启动后运行 sharedlibrary
,因为这些库还没有加载。我们需要在程序中执行一个命令,比如 dosomething
来触发这些库的加载。之后,这些库将在 gdb
中可见 sharedlibrary
。
这适用于大多数调试场景,但有一种情况我遇到了麻烦。通过 dosomething
加载的库之一称为 libfoo.so
,其 API foo()
在 dosomething
期间执行。如何在 dosomething
期间进入 foo()
?换句话说,根据程序阶段的以下心理图像,我如何在 stage j
之后和 stage k
之前暂停 gdb
以便我可以在执行 foo()
之前加载符号?
* ...
* Stage i: In the main program interface, the command `dosomething` is issued. This will trigger the loading of some dynamic linked libraries, including `libfoo.so`.
* ...
* Stage j: `libfoo.so` is loaded.
* ...
* Stage k: `foo()` is executed.
* ...
* Stage l: The command `dosomething` finishes and returns the control to the user in the main program.
* ...
注意:由于某些技术原因,我也无法在主程序启动后和运行 dosomething
触发加载那些库之前打开auto-solib-add
。否则,我知道这可能是一种解决方法,而不是尝试在 stage j
和 stage k
之间的最佳位置手动暂停。
My mental image is that the following happens in order:
您的心智模型不正确:如果您可以调用 foo()
,那么 定义 foo()
的库一定已经加载。没有 .so
文件的“按需”加载——它们 仅 加载,因为可执行文件直接链接到 .so
(在这种情况下 .so
在可执行文件的单个指令运行之前加载), 或 作为 dlopen()
调用的结果。
您可以通过在 foo()
的 caller 上设置断点并使用 GDB info shared
命令检查所有加载的 .so
来验证这一点]s.
假设 libfoo.so
实际上已经加载,你可以要求 GDB 使用 shared libfoo.so
命令为这个库添加符号。之后,您将能够在 foo()
.
如果libfoo.so
在info shared
输出中不是,那么你没有准确描述你的程序,你的问题无法回答。
我通过阅读这篇文章开始思考:https://developer.ibm.com/technologies/linux/tutorials/l-dynamic-libraries/
如果我们将三个库的使用场景编号为:
- 静态库。
- 共享库动态链接。
- 共享库动态加载。
libfoo.so
的加载属于 3),其中 dlopen
库用于触发从应用程序加载(但仍然通过处理 2 的系统动态链接器)。
运行 程序启动后 gdb
中的以下内容将允许我们停止每次动态加载。
sharedlibrary libdl.so
b dlopen
我在 stage j
和 stage k
之间寻找的点可能就在 dlopen
returns 之后到它的调用者 libfoo.so
.