首页 > 解决方案 > 如何让 GDB 自动停止解析共享库中的符号

问题描述

我创建了一个简单的程序,在共享库中调用 foo 函数。它会这样调用:

0000000000001169 <main>:
    1169:   f3 0f 1e fa             endbr64 
    116d:   55                      push   %rbp
    116e:   48 89 e5                mov    %rsp,%rbp
    1171:   e8 ea fe ff ff          callq  1060 <_Z3foov@plt>

当我查看 foo@plt 时,它看起来像

0000000000001060 <_Z3foov@plt>:
    1060:   f3 0f 1e fa             endbr64 
    1064:   f2 ff 25 5d 2f 00 00    bnd jmpq *0x2f5d(%rip)        # 3fc8 <_Z3foov>
    106b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

奇怪的是,当我运行该程序的 gdb 时,*0x2f5d(%rip) 已经包含 foo 函数的地址。我想知道它是如何自动绑定的。

nopl 0x0(%rax,%rax,1)另外,指令的目的是什么?


更新

我意识到我的程序是使用完整的 RELRO 选项编译的。于是我又用norelro选项编译了一遍(-Wl,-z,norelro,用checksec确认不是RELRO),这样就可以通过gdb观察惰性绑定了。但是,似乎 gdb 在 main 启动之前会自动解析所有动态符号。如何让 gdb 不这样做?


更新 2

// foo.h
int foo();
// foo.cc
#include "bar.h"

int foo() {
  bar();
  return 1;
}
// bar.h
void bar();
// bar.cc
void bar() {}
// main.cc
#include "bar.h"
#include "foo.h"

int main() {
  bar();

  foo();
}

我按如下方式创建了共享库。

$ g++ -c -fpic -g foo.cc
$ g++ -c -fpic -g bar.cc
$ g++ -shared foo.o bar.o -o -g libfoobar.so

并将其链接到main。

g++ -g -Wl,-z,norelro main.cc libfoobar.so -o main

checksec 告诉我No RELRO是指定的。

$ checksec --file=main
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH  Symbols     FORTIFY Fortified   Fortifiable  FILE
No RELRO        No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   71 Symbols     No   0       0   main

标签: c++cdynamiclinkershared-libraries

解决方案


推荐阅读