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
。
在您的情况下,rcx
是 0x6a2900
(可能是数据部分中的变量,请尝试 info symbol 0x6a2900
),而 rdx
是 -13107
- 一个负数。带有负索引的数组索引在实际程序中很少发生,因此您需要查看函数的源代码并尝试了解它是如何发生的。
【讨论】:
感谢您的详细回复。执行“info symbol 0x6a2900”会产生以下输出:“Xw_prim_size_sa in section .data of ” @UnhandledException 所以请查看函数中如何访问该变量以及为什么索引可能为负数。也许添加一些检查/断言来捕捉错误的输入。以上是关于movsql 调用导致核心转储的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 中调用 Oracle 存储过程时如何避免核心转储