首页 文章

无法访问.bss部分中的内存,但gdb 'info files'显示地址在范围内

提问于
浏览
1

我有一个生成 Bus error (core dumped) 消息的二进制文件 . 当我在调试器( gdb )下运行它时,它无法访问 .bss 部分中的内存位置 .

Program received signal SIGBUS, Bus error.
0x0000000000412275 in ?? ()

这个位置的代码是:

41226f:       0f 8f 33 ff ff ff       jg     4121a8 
  412275:       8b 35 51 b5 22 00       mov    0x22b551(%rip),%esi        # 63d7cc 
  41227b:       85 f6                   test   %esi,%esi

所以它试图访问 0x63d7cc 位置的内存,这显然位于 .bss 部分: 0x63c4e0 - 0x63d7e0 .

gdb (与/ proc / $ pid / maps一起)将此内存显示为已映射:

(gdb) info proc mappings
process 16533
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x43a000    0x3a000        0x0 /somepath/someapp
            0x639000           0x63e000     0x5000    0x39000 /somepath/someapp
            0x63e000           0x65f000    0x21000        0x0 [heap]
(gdb) info files
Symbols from "/somepath/someapp".
...
        0x0000000000639c80 - 0x000000000063c498 is .data
        0x000000000063c4e0 - 0x000000000063d7e0 is .bss

两个ELF部分的检查:

% readelf -S someapp
...
  [24] .data             PROGBITS         0000000000639c80  00039c80
       0000000000002818  0000000000000000  WA       0     0     32
  [25] .bss              NOBITS           000000000063c4e0  0003c498
       0000000000001300  0000000000000000  WA       0     0     32
  [26] .gnu_debuglink    PROGBITS         0000000000000000  0003c498
       000000000000000c  0000000000000000           0     0     1
...

和Segments将此内存显示为已映射:

% readelf -l someapp
...
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000003976c 0x000000000003976c  R E    200000
  LOAD           0x0000000000039770 0x0000000000639770 0x0000000000639770
                 0x0000000000004070 0x0000000000004070  RW     200000
...

gdb 无法访问它(因此应用程序失败的原因) . 有趣的是 gdb 能够访问 .bss 内存,直到 0x63d000

(gdb) x 0x63d7cc
0x63d7cc:       Cannot access memory at address 0x63d7cc
(gdb) x 0x63cff8
0x63cff8:       0x00000000
(gdb) x 0x63cffc
0x63cffc:       0x00000000
(gdb) x 0x63cffd
0x63cffd:       Cannot access memory at address 0x63d000

问题是:
有什么可能阻止这种访问?
还有哪些其他方法可用于检查运行时内存访问权限?
还有什么可以修改正在运行的进程的访问权限?

1 回答

  • 2

    此位置的代码是:

    .bss 通常不是可执行的,所以很可能这就是为什么在尝试跳转到它时会得到 SIGBUS .

    您的 readelf 输出显示 RW 标志(注意缺少 E xecutable标志) .

    您需要 mprotect 该部分首先添加执行权限 .

    请注意,某些环境(例如 SELinux )禁止使用 RWE 进行内存映射,并且将映射更改为 R-E 将导致程序无法写入其(通常可写)全局数据 . 这就是为什么将可执行代码放入 .bss 可能不是最好的想法 .

相关问题