步入共享库的条件应该在gdb中运行?

The*_*eer 13 c linux debugging gdb

有很多与特定错误相关的问题,为什么单独使用gdb进入共享库是行不通的.他们都没有就如何确定原因在哪里提供系统的答案.这个问题是关于诊断设置的方法.

设置示例

main.c中

#include <stdio.h>
#include "myshared.h"

int main(void)
{
    int a = 3;
    print_from_lib();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

myshared.h

void print_from_lib();
Run Code Online (Sandbox Code Playgroud)

myshared.c

#include <stdio.h>

void print_from_lib()
{
    printf("Printed from shared library\n");
}
Run Code Online (Sandbox Code Playgroud)

将所有文件放在同一目录中.

export LIBRARY_PATH=$PWD:$LIBRARY_PATH
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb
Run Code Online (Sandbox Code Playgroud)

得到错误

$ gdb ./app-ggdb 
GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1) 7.12.50.20170314-git
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
Printed from shared library
8       return 0;
Run Code Online (Sandbox Code Playgroud)

gdb没有踩到函数内部

必要但不充分的检查

调试二进制文件中的符号

$ objdump --syms libmyshared-ggdb.so | grep debug
0000000000000000 l    d  .debug_aranges 0000000000000000              .debug_aranges
0000000000000000 l    d  .debug_info    0000000000000000              .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000              .debug_abbrev
0000000000000000 l    d  .debug_line    0000000000000000              .debug_line
0000000000000000 l    d  .debug_str     0000000000000000              .debug_str
Run Code Online (Sandbox Code Playgroud)

gdb识别的符号

$ gdb ./app-ggdb
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb)(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
0x00007ffff7dd7aa0  0x00007ffff7df55c0  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7bd5580  0x00007ffff7bd5693  Yes         /home/user/share-lib-example/libmyshared-ggdb.so
0x00007ffff782d9c0  0x00007ffff797ed43  Yes         /lib/x86_64-linux-gnu/libc.so.6
Run Code Online (Sandbox Code Playgroud)

确认.gdbinit不是原因

~/.gdbinit包含启动gdb时自动执行的命令.REF.

使用-nx标志运行gdb 可以排除.gdbinit作为问题的根源.

我正在寻找建议来完成清单Necessary but not sufficient checks.

当前期刊[Mark Plotnick更新]

这个步骤错误可以在Ubuntu 17.04 amd64上重现,同时具有64位和32位可执行文件和库.

该错误在Ubuntu 17.04 i386上无法重现.(gcc 6.3.0-12ubuntu2,gdb 7.12.50和8.0,没有.gdbinit.).

可能相关:默认情况下,17.04 amd64上的gcc(由Canonical构建)生成饼可执行文件.

构建gcc的标志是否会干扰调试?你怎么能确定你的gcc是否是原因?

Emp*_*ian 6

你的问题是自我强加的:不要这样做:set step-mode on,并且step会像你期望的那样工作.

从GDB 手册:

set step-mode
set step-mode on
The set step-mode on command causes the step command to stop at the first
instruction of a function which contains no debug line information
rather than stepping over it.

This is useful in cases where you may be interested in inspecting the machine
instructions of a function which has no symbolic info and do not want
GDB to automatically skip over this function.
Run Code Online (Sandbox Code Playgroud)

你感兴趣的对面上面的-你想一步进入print_from_lib功能,避免了PLT跳存根和动态加载程序的符号解析函数中停止.


hao*_*lee 5

GDB 7.11无法重现此问题.这是我的步骤.我希望这能帮到您:

1.gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
2.gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
3.gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb -L.
4.gdb ./app-ggdb
Run Code Online (Sandbox Code Playgroud)

在GDB中

(gdb) set env LD_LIBRARY_PATH=.
(gdb) b main.c:7
Breakpoint 1 at 0x4006a5: file main.c, line 7.
(gdb) r
Starting program: /home/haolee/tmp/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
print_from_lib () at myshared.c:5
5       printf("Printed from shared library\n");
(gdb) 
Run Code Online (Sandbox Code Playgroud)

print_from_lib成功地进入了这个功能.