movsql 调用导致核心转储

Posted

技术标签:

【中文标题】movsql 调用导致核心转储【英文标题】:movsql call results in a core dump 【发布时间】:2020-01-22 20:47:26 【问题描述】:

基于核心文件,先使用where 命令,然后使用disassemble 命令。

(gdb) disassemble
Dump of assembler code for function prm_get_sta:
   0x0000000000414b80 <+0>:     push   %rbp
   0x0000000000414b81 <+1>:     mov    %rsi,%rbp
   0x0000000000414b84 <+4>:     push   %rbx
   0x0000000000414b85 <+5>:     mov    %rdi,%rbx
   0x0000000000414b88 <+8>:     sub    $0x18,%rsp
   0x0000000000414b8c <+12>:    movabs 0x6a53e8,%rax
   0x0000000000414b96 <+22>:    test   %rax,%rax
   0x0000000000414b99 <+25>:    je     0x414c90 <prm_get_sta+272>
   0x0000000000414b9f <+31>:    mov    0x80(%rax),%edx
   0x0000000000414ba5 <+37>:    test   %edx,%edx
   0x0000000000414ba7 <+39>:    jne    0x414c90 <prm_get_sta+272>
   0x0000000000414bad <+45>:    mov    0x8(%rbx),%edx
   0x0000000000414bb0 <+48>:    mov    0x18(%rbx),%rax
   0x0000000000414bb4 <+52>:    add    (%rbx),%rdx
   0x0000000000414bb7 <+55>:    cmp    %rdx,%rax
   0x0000000000414bba <+58>:    je     0x414ce6 <prm_get_sta+358>
   0x0000000000414bc0 <+64>:    mov    %rax,0x0(%rbp)
   0x0000000000414bc4 <+68>:    movswq (%rax),%rdx
   0x0000000000414bc8 <+72>:    movabs $0x6a2900,%rcx
=> 0x0000000000414bd2 <+82>:    movslq (%rcx,%rdx,8),%rdx
   0x0000000000414bd6 <+86>:    add    0x18(%rbx),%rdx
   0x0000000000414bda <+90>:    mov    %rdx,0x8(%rbp)

接下来,执行信息寄存器。

(gdb) info registers
rax            0x1672fa0        23539616
rbx            0x7fff6ec02f40   140735051476800
rcx            0x6a2900         6957312                 <----------------Hex to Decimal value
rdx            0xffffffffffffcccd       -13107          <----------------Hex to Decimal value 
rsi            0x7fff6ec01060   140735051468896
rdi            0x7fff6ec02f40   140735051476800
rbp            0x7fff6ec01060   0x7fff6ec01060
rsp            0x7fff6ec01000   0x7fff6ec01000
r8             0x7fff6ec02588   140735051474312
r9             0x111    273
r10            0x0      0
r11            0x2abd31653c50   46992065903696
r12            0x414b80 4279168
r13            0x7fff6ec02b00   140735051475712
r14            0x414440 4277312
r15            0x0      0
rip            0x414bd2 0x414bd2 <prm_get_sta+82>
eflags         0x10297  [ CF PF AF SF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0

研究: movslq 命令应该进行 32->64 位 2 的补码扩展,通过将源的符号位复制到所有新的高位来扩展

找到了有关括号中数据的独特用法的文档:(%rcx,%rdx,8),它是这样解释的:

(%rcx, %rdx, 8) 存储在地址 %rcx + 8%rdx*

处的内存内容

如果正确遵循逻辑,我使用上述注册表数据将其解释为以下意思...

(6957312 + 8*-13107)

使用操作顺序,这将首先执行 (8*-13107),结果为:-104,856 然后添加 6957312,即 6,852,456 和足够小的数字。

-104,856 值导致完整的 8 个字节,想知道那里是否可能存在问题。

问题:

1 - 这个假设是否正确 (6957312 + (8*-13107)) ?

2 - 乘以 8 的目的是什么?

3 - 有什么明显的东西会导致核心吗?

【问题讨论】:

问题可能是地址6,852,456(0x00688F68)没有映射内存,如果数量太大,只会溢出而没有不良影响。 那么结果值实际上是内存地址而不是整数值? 是的!为什么你认为它说“存储在地址...的内存内容?” 【参考方案1】:

指令正在访问无效的内存地址,原因似乎是负数组索引

正如您提到的,(%rcx, %rdx, 8) 访问存储在地址%rcx + 8*%rdx 的内存。

换句话说,我们从一个 8 字节元素 数组中加载一个项目,该数组从 rcx 开始,索引为 rdx

在您的情况下,rcx0x6a2900(可能是数据部分中的变量,请尝试 info symbol 0x6a2900),而 rdx-13107 - 一个负数。带有负索引的数组索引在实际程序中很少发生,因此您需要查看函数的源代码并尝试了解它是如何发生的。

【讨论】:

感谢您的详细回复。执行“info symbol 0x6a2900”会产生以下输出:“Xw_prim_size_sa in section .data of ” @UnhandledException 所以请查看函数中如何访问该变量以及为什么索引可能为负数。也许添加一些检查/断言来捕捉错误的输入。

以上是关于movsql 调用导致核心转储的主要内容,如果未能解决你的问题,请参考以下文章

来自垂死的多线程进程的核心转储

在 Java 中调用 Oracle 存储过程时如何避免核心转储

释放从核心中排除的内存后核心转储大小增加

使用pthread_create时的“分段错误(核心转储)”

创建核心转储时设置退出状态

[c的JNI调用java导致分段错误(内核已转储)