【问题标题】:Why does my strdup in asm intel 64 segfault when I try to test it [duplicate]当我尝试测试它时,为什么我的 asm intel 64 中的 strdup 会出现段错误[重复]
【发布时间】:2021-07-11 12:36:07
【问题描述】:

我是使用 intel asm 64 位编码的新手,我正在尝试从 libc 重新编码 strdup,当我尝试在我的 c 主程序中对其进行测试时出现段错误,但我不明白为什么会出现此错误

这是我的 main.c:

#include "libasm.h"

int main(void)
{

    printf("  _____________\n");
    printf("//             \\\\\n");
    printf("||  ft_strdup  ||\n");
    printf("||_____________||\n");
    char *str;
    char *dup;

    str = "test";
    printf("segfault1\n");
    dup = ft_strdup(str);
    printf("segfault2\n");
    printf("str: %s\n", dup);
    free(dup);
    return 0;
}

当我使用标志 -g -fsanitize 启动我的程序时,我在调用 ft_strdup 的行上遇到了这个段错误:

ASAN:DEADLYSIGNAL

=================================================================
==21414==ERROR: AddressSanitizer: SEGV on unknown address 0x55789815fa80 (pc 0x55789815fa80 bp 0x7ffe98c5e8a0 sp 0x7ffe98c5e3d8 T0)
==21414==The signal is caused by a READ memory access.
ASAN:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.

gdb 回溯:

Program received signal SIGSEGV, Segmentation fault.
0x00005554f7a79140 in ?? ()
(gdb) backtrace
#0  0x00005554f7a79140 in ?? ()
#1  0x0000555555554fb2 in ft_strdup ()
#2  0x000055555555508a in ?? ()
#3  0x0000555555554e69 in main () at main.c:90

这里是指令0x0000555555554fb2:

(gdb) x/10i 0x0000555555554fb2
   0x555555554fb2 <ft_strdup+18>:       pop    %rsi
   0x555555554fb3 <ft_strdup+19>:       mov    %rax,%rdi
   0x555555554fb6 <ft_strdup+22>:       jmpq   0x555555554ef0 <ft_strcpy>
   0x555555554fbb <ft_strdup+27>:       nopl   0x0(%rax,%rax,1)
   0x555555554fc0 <__libc_csu_init>:    push   %r15
   0x555555554fc2 <__libc_csu_init+2>:  push   %r14
   0x555555554fc4 <__libc_csu_init+4>:  mov    %rdx,%r15
   0x555555554fc7 <__libc_csu_init+7>:  push   %r13
   0x555555554fc9 <__libc_csu_init+9>:  push   %r12
   0x555555554fcb <__libc_csu_init+11>: lea    0x200d9e(%rip),%r12        # 0x555555755d70

这是我的 ft_strdup 代码:

global    ft_strdup
extern    malloc
extern    ft_strlen
extern    ft_strcpy

ft_strdup:
    push rdi
    call ft_strlen
    add rax, 1
    mov rdi, rax
    call malloc
    pop rsi
    mov rdi, rax
    jmp ft_strcpy

这是我的 ft_strcpy 代码:


global ft_strcpy

ft_strcpy:
    xor     rax, rax            

loop:
    cmp     byte [rsi + rax], 0
    jz      return
    mov     dl, [rsi + rax]
    mov     [rdi + rax], dl
    inc     rax
    jmp     loop

return:
    mov     byte [rdi + rax], 0
    mov     rax, rdi
    ret

还有我的 ft_strlen 代码:

global ft_strlen

ft_strlen:
    xor rcx, rcx

count:
    cmp byte [rdi], 0
    je ret;
    inc rdi
    inc rcx
    jmp count

ret :
    mov rax, rcx
    ret

如果有人可以就可能导致此段错误的原因给我一些指示,那真的会对我有所帮助!

【问题讨论】:

  • 您是否使用调试器查看异常发生的位置?
  • 另外,虽然我不知道这是否会导致问题,但您似乎没有在函数调用时保持 16 字节堆栈对齐。
  • 你所有的ft函数都是用汇编写的吗?其他人是否按预期工作?
  • 提供minimal reproducible example 以及使用的命令。如果错误确实与调用有关,则意味着您以某种方式将ft_strdup的地址弄错了。
  • @AmmarFaizi:555555554fb2处的代码是call malloc的返回地址。这不是很有帮助;看到 call 指令本身的机器代码会使诊断段错误更有可能(即 rel32 由于重定位溢出而得到垃圾),所以 dis ft_strdup 会更有用。当然,将Symbol 'malloc' causes overflow in R_X86_64_PC32 relocation 错误消息作为minimal reproducible example 的一部分包含在问题中会为大家节省很多时间。

标签: c assembly segmentation-fault x86-64


【解决方案1】:

我发现了这个帖子:Nasm - Symbol `printf' causes overflow in R_X86_64_PC32 relocation

这解释了如何使用以下方法修复导致我的段错误的错误:

./a.out: Symbol `malloc' causes overflow in R_X86_64_PC32 relocation

通过使用标志 gcc -no-pie main.c mylibrary.a:

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
  • 2019-09-23
相关资源
最近更新 更多