如何在 NASM x64 中测试我自己的 GLIBC 实现?

问题描述 投票:0回答:1

我目前正在开发 NASM x64 版本的 GLIBC,但在测试它时遇到问题。 ASM 代码首先在 .so 中编译,接下来我的测试代码(C 语言)通过 GCC 编译,然后我通过

LD_PRELOAD
加载我的共享库并执行我的二进制文件。

这是我的 ASM 实现

putchar()
:

bits 64

STDOUT equ 1

section .text
    global putchar
    putchar:
        push rdi
        mov rax, 1
        mov rdi, STDOUT
        mov rsi, rsp
        mov rdx, 1
        syscall
        pop rdi
        ret

这是测试主要内容:

#include <stddef.h>

extern size_t putchar(const char str);

int main(void)
{
    putchar('z');
    return (0);
}

这是 Makefile :

CC      =   nasm
CFLAGS  =   -f elf64
SRC     =   $(wildcard src/*.asm)
OBJ     =   $(SRC:.asm=.o)
NAME    =   minilibc.so

all: $(NAME)

$(NAME): $(OBJ)
    ld -fPIC -shared -o $(NAME) $(OBJ) -nostdlib

%.o: %.asm
    $(CC) $(CFLAGS) $< -o $@

clean:
    rm -f $(OBJ)

fclean: clean
    rm -f $(NAME)

re: fclean all

test: re
    gcc -o test/test test/main.c -g3
    LD_PRELOAD=./minilibc.so ./test/test

.PHONY: all clean fclean re

问题是当我尝试设置断点时,GDB 继续使用 glibc 函数:

(gdb) b putchar
Breakpoint 1 at 0x1030
...
Breakpoint 1, 0x00007ffff7c7bb20 in putchar () from /usr/lib/libc.so.6

我也尝试过使用

-nostlib
进行编译(在 make test 中),但它不起作用:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000001020
...
/home/mimahk/Documents/Workspace C/minilibc/test/main.c:7:(.text+0xa): undefined reference to `putchar'

我知道实际上二进制文件需要一个

_start
标签才能运行,但尽管进行了多次搜索,我仍无法对其进行编码。

我测试了这个,但它不起作用:

asm(".global _start; _start: call main; movq %rax, %rdi; movq $60, %rax;");

我明白:

main.c:9:(.text+0x19): undefined reference to putchar

你能告诉我如何测试我的共享库吗?

c assembly x86-64 nasm libc
1个回答
0
投票

感谢@PeterCordes 和@Jester 的评论,我能够纠正这个问题。

首先,我必须修改代码,在

main()
之前加上名为
_start
的 ASM 标签。

然后我修改了 Makefile 中的一些选项以在运行时直接链接 .so(并添加了基本的调试选项):

-g3
:启用 GDB 深度调试。

-fno-builtin
:删除 GCC 的自动代码替换(例如
printf(%s\n, str)
替换为
puts(str)

-fnostdlib
:不包括 GLIBC。

-fno-plt
:直接使用GOT,无需PLT。

-L./ -lminilibc
:指示链接器将我的可执行文件链接到
minilibc
库(因此应该称为
libminilibc.so
)。

-Wl,-rpath=./
:告诉链接器我的库在运行时的位置(因为它不在
/usr/lib/
中),省去了我使用
LD_PRELOAD
的麻烦。

完整代码如下:

main.c

#include <stddef.h>

extern int putchar(const char str);

asm(".global _start; _start: call main; movq %rax, %rdi; movq $60, %rax; syscall"); // Call the main() function and exit with the code corresponding to the return of main().

int main(void)
{
    putchar('H');
    return (0);
}

生成文件

CC      =   nasm
CFLAGS  =   -f elf64
SRC     =   $(wildcard src/*.asm)
OBJ     =   $(SRC:.asm=.o)
NAME    =   libminilibc.so

all: $(NAME)

$(NAME): $(OBJ)
    ld -fPIC -shared -o $(NAME) $(OBJ) -nostdlib

%.o: %.asm
    $(CC) $(CFLAGS) $< -o $@

clean:
    rm -f $(OBJ)

fclean: clean
    rm -f $(NAME)

re: fclean all

test: re
    gcc -o test/test test/main.c -g3 -fno-builtin -nostdlib -fno-plt -L./ -lminilibc -Wl,-rpath=./

.PHONY: all clean fclean re

© www.soinside.com 2019 - 2024. All rights reserved.