系统调用后 Gnu 汇编器 .data 节值损坏

2023-12-15

我有以下代码

.data
result: .byte 1
.lcomm input 1
.lcomm cha 2

.text
(some other code, syscalls)

起初一切都很好。当调用系统调用(例如读取)时,标签“结果”处的值更改为某个随机垃圾值。

有谁知道出了什么问题吗?

附:环境 Debian x86_64 最新 在虚拟机中运行 使用 as -g ld emacs makelatest

- - -编辑 - - -

(continue)
.global _start
_start:
mov $3,%rax
mov $0,%rbx
mov $input,%rcx
mov $1,%rdx
int $0x80
(sys_exit)

“输入”的值已正确更改,但“结果”的值也更改为随机值

int $0x80 

您正在查看从以下位置开始的 4 个字节result, 包括input作为第二个或第三个字节。 (这就是为什么该值会增加 256 或 65536 的倍数,如果您将低字节保留为 1print (char)result)。如果你使用的话,这会更明显p /x以十六进制打印。

GDB 的默认行为print result当没有调试信息时假设int。现在,由于这样的用户错误,gdbArch Linux 上的 8.1,print result says 'result' has unknown type; cast it to its declared type

GAS + ld意外地(无论如何对我来说)将 BSS 和数据段合并到一页中,因此即使您将变量放在不同的部分中(您希望得到不同的处理),它们也是相邻的。 (BSS 由匿名归零页支持,数据由文件的私有读写映射支持)。

构建后gcc -nostdlib -no-pie test.S, I get:

(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>

与使用不同.section .bss并手动预留空间,.lcomm如果需要可以随意垫。大概是为了对齐,也许在这里 BSS 从 8 字节边界开始。当我用clang, I got input在之后的字节中result(在不同的地址)。


我通过添加一个大数组进行调查.lcomm arr, 888332。一旦我意识到它没有在可执行文件中存储 BSS 的文字零,我就使用了readelf -a a.out进一步检查:

(有关的:ELF文件格式中的节和段有什么区别)

...
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000126 0x0000000000000126  R E    0x200000
  LOAD           0x0000000000000126 0x0000000000600126 0x0000000000600126
                 0x0000000000000001 0x00000000000d8e1a  RW     0x200000
  NOTE           0x00000000000000e8 0x00000000004000e8 0x00000000004000e8
                 0x0000000000000024 0x0000000000000024  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .text 
   01     .data .bss 
   02     .note.gnu.build-id 

...

所以是的,.data and .bss部分最终位于相同的 ELF 段中。

我认为这里发生的事情是 ELF 元数据说要映射 MemSize0xd8e1a从 virt addr 开始的字节(归零页)0x600126. and 从偏移量加载 1 个字节0x126在文件中到虚拟地址0x600126.

因此,ELF 程序加载器必须将文件中的数据复制到支持 BSS 的清零页中,而不仅仅是 mmap.data部分。

这可能是一个更大的.data链接器决定使用单独的段所需的部分。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

系统调用后 Gnu 汇编器 .data 节值损坏 的相关文章

随机推荐