Linux Gnu汇编程序。数据节值在系统调用后损坏
我有以下代码Linux Gnu汇编程序。数据节值在系统调用后损坏,linux,assembly,x86,gnu-assembler,Linux,Assembly,X86,Gnu Assembler,我有以下代码 .data result: .byte 1 .lcomm input 1 .lcomm cha 2 .text (some other code, syscalls) 起初一切都很好。当调用系统调用(如read)时,标签“result”处的值更改为某个随机垃圾值 有人知道怎么了吗 p.S.环境 Debian x86_64最新版本 在virtualbox中运行 使用as-gld-emacs制作最新版本 -----编辑----- “输入”的值已正确更改,但“结果”的值在更改后也更改
.data
result: .byte 1
.lcomm input 1
.lcomm cha 2
.text
(some other code, syscalls)
起初一切都很好。当调用系统调用(如read)时,标签“result”处的值更改为某个随机垃圾值
有人知道怎么了吗
p.S.环境
Debian x86_64最新版本
在virtualbox中运行
使用as-gld-emacs制作最新版本
-----编辑-----
“输入”的值已正确更改,但“结果”的值在更改后也更改为随机值
int $0x80
您看到的是从
结果
开始的4个字节,其中包括输入
作为第2或第3个字节。(这就是为什么该值会增加256或65536的倍数,如果print(char)result
,则保留低位字节=1)。如果您使用p/x
以十六进制打印,这将更加明显
当没有调试信息时,print result
的GDB默认行为是假定int
。现在,由于这样的用户错误,在Arch Linux上使用gdb
8.1时,print result
表示'result'的类型未知;将其强制转换为声明的类型
GAS+ld
出人意料地(对我来说)将BSS和数据段合并到一个页面中,因此即使您将变量放在不同的部分中,您也会期望得到不同的处理,但它们是相邻的。(BSS由匿名零页支持,数据由文件的私有读写映射支持)
使用gcc-nostlib-no pie test.S构建之后,我得到:
(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>
因此,是的,.data
和.bss
部分最终位于同一个ELF段中
我认为这里发生的事情是ELF元数据表示从virt addr0x600126
开始映射0xd8e1a
字节(零页)的MemSize。并将文件中偏移量0x126
中的1个字节加载到虚拟地址0x600126
因此,ELF程序加载器必须将数据从文件复制到支持BSS和.data
部分的另一个归零页面,而不仅仅是一个mmap
它可能是一个较大的.data
部分,链接器需要它来决定使用单独的段。您能做一个比较吗?您没有显示实际的代码,因此很难真正了解问题所在sys\u read
只会将字节从buf
修改为buf+length
。或者更好的方法是,在被修改的内存上设置一个断点,以找出修改的位置。顺便问一下,为什么要显示BSS静态数据(.lcomm
)?是否也在修改?int$0x80
不是执行64位系统调用的正确方法。有关详细信息,请参阅。这可能是您的问题的根源,但很难说没有一个代码段不是。也就是说,您的代码片段缺少“完整”和“可验证”的部分,这对其他人重现和诊断您的问题很重要。打印结果
是否将结果
视为int
类型,即显示4个字节而不是1个字节?(尝试以十六进制输出,并检查低8位(最后两个十六进制数字)=这些应该是结果字节值)(以十六进制打印:p/x result
@Ped7g:这里不涉及编译器本身,只涉及汇编程序+链接器,它们通常只遵循简单规则,不寻求优化(除分支位移外,尽可能使用jmp rel8
短编码,以及最小尺寸立即和位移。)@空格:我错了,它没有在文件中存储文字零。使用readelf
输出进一步更新了包含.data
和.bss
部分的段的工作方式。我认为变量最终会出现在.data
部分,因为在声明t之前OP没有更改为.bss
部分哼哼。GNU汇编程序不会将变量放入.bss
中,除非您明确告诉它。@fuz:.lcomm
在bss中保留空间,并且不关心当前部分。我在.text
和mov%al,cha(%rip)之后使用它进行了双重检查
不会分离故障,但.text
中的.byte
存储区会分离故障。使用nm-n a.out
检查符号地址,其中包括\u bss\u start
和\u edata
,这样您就可以知道哪个静态存储在哪里。
(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>
...
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
...