这是个工具半残时,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。
这点改正後,我们可以再继续作验证看看。
什麽是软分岔、硬分岔? 在链上,常见有两种分岔,一种最容易理解,就是网路时差带来「最长链」不同的情...
你好,我是 ALPHA Camp 的 Bernard。感谢你来阅读我的文章。这次铁人赛我会针对「成为...
GCD(Grand Central Dispatch)是由苹果开发用来操作Thread的API 而在...
前情提要 上回提到魔法学姊艾草(鸟)在练习英文。 艾草:「This, These, That, Th...
怪物实作 怪物是由多个子物件组合而成的,其阶层看起来可能会是如下所示 利用子物件达成其功能的分类,目...