這是個工具半殘時,debug會很慘烈的故事Orz
既上次想要搬遷到host來用qemu-user加快測試節奏後,發現Alpine內的toolchain與host的,因為bintuils版本不一,導致DWARF2的資訊無法被host端解讀,而沒辦法正常判讀行號與位置。
幾經嘗試,最後決定重新在 host 端使用riscv-gnu-toolchain,在configure時,多加上 --enable-gdb
來開啟gdb的support。在有了可用的gdb後,繼續進行debug,
從debug 訊息中判讀,得知程式是在清零 bss section時,memset()遇上存取系統認為不可存取的區域:
│ 780 if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
│ 781 size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
│ 782 size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
│ >783 memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
│ 784 if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)
│ 785 goto error;
│ 786 }
│ 787 }
│ 788 for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
└───────────────────────────────────────────────────────────────────────────────────────────────
remote Thread 1.243523 In: map_library
(gdb) down
#1 0x3f7b1b94 in map_library (fd=5, dso=0x3fffe458) at ldso/dynlink.c:783
(gdb) p base
$1 = (unsigned char *) 0x3f423000 "\177ELF\001\001\001"
(gdb) p/x ph->p_vaddr
$2 = 0x279a50
(gdb) p/x brk
$3 = 0x3f6c7708
其中這時可以開始懷疑是不是mmap的部份有出狀況,於是一路step進去看,此時發現我們呼叫到了mmap:
│ 28 #ifdef SYS_mmap2
│ 29 ret = __syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT);
│ 30 #else
│ >31 ret = __syscall(SYS_mmap, start, len, prot, flags, fd, off);
│ 32 #endif
│ 33 /* Fixup incorrect EPERM from kernel. */
│ 34 if (ret == -EPERM && !start && (flags&MAP_ANON) && !(flags&MAP_FIXED))
│ 35 ret = -ENOMEM;
│ 36 return (void *)__syscall_ret(ret);
│ 37 }
└─────────────────────────────────────────────────────────────────────────────────────────────
remote Thread 1.244285 In: __mmap
(gdb) ni
這時,我們回去對一下QEMU的linux-user/riscv/syscall32_nr.h
:
208 #define TARGET_NR_mmap2 222
這下,就有趣了。
這時我們來看一下mmap2的manual page:
The mmap2() system call provides the same interface as mmap(2), except that the final argument specifies the offset into the file in 4096-byte units
(instead of bytes, as is done by mmap(2)). This enables applications that use a 32-bit off_t to map large files (up to 2^44 bytes).
而目前我的musl source中,SYS_mmap
被指向了mmap2
,變成錯的syscall symbol,被對上mmap2。
這點改正後,我們可以再繼續作驗證看看。