提问人:Virgil G. 提问时间:9/25/2023 最后编辑:Virgil G. 更新时间:9/25/2023 访问量:75
如何在 NASM x64 中测试自己的 GLIBC 实现?
How can I test my own implementation of GLIBC in NASM x64?
问:
我目前正在开发我的 NASM x64 版本的 GLIBC,但我在测试它时遇到了问题。ASM 代码首先以 .so 格式编译,然后通过 GCC 编译我的测试代码(C 语言),然后我通过加载我的共享库并执行我的二进制文件。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
我也尝试过编译(在make test中),但它不起作用:-nostlib
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
你能告诉我如何测试我的共享库吗?
答:
多亏了@PeterCordes和@Jester的评论,我才能够纠正这个问题。
首先,我必须修改代码,使其前面有一个名为 的 ASM 标签。main()
_start
然后,我修改了 Makefile 中的几个选项,以在运行时直接链接 .so(并添加了基本的调试选项):
-g3
:启用使用 GDB 进行深入调试。
-fno-builtin
:删除 GCC 的自动代码替换(例如 由。printf("%s\n", str)
puts(str)
-nostdlib
:不包括 GLIBC。
-fno-plt
:直接使用GOT而不使用PLT。
-L./ -lminilibc
:指示链接器将我的可执行文件链接到库(因此应称为 libminilibc.so
)。minilibc
-Wl,-rpath=./
:告诉链接器我的库在运行时的位置(因为它不在 中),并省去了使用 ./usr/lib/
LD_PRELOAD
完整代码如下:
main.c
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 -shared -o $(NAME) $(OBJ)
%.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
评论
-fnostdlib
不是 GCC 选项。你是说。-nostdlib
ld
-nostdlib
-fPIC
ld
-fPIC
ld
ld -nostdlib
-l
ld
ld -n -o stdlib
--nmagic
ld
-fPIC
--auxiliary=PIC
)
评论
_start
main
write
LD_PRELOAD
Breakpoint 1, 0x00007ffff7bd81f0 in putchar () from ./minilibc.so
-nostdlib
exit