[TOC]

0. 这个文件的必要性和阅读的注意事项

因为自己在实现musl兼容库——mocklibc的时候,往往要进行一些分析,也要写一些东西。这些东西往往不成体系,也没有什么总结的价值,基本是随写随丢的状态。但是这个随写随丢有时候反而会造成一些困扰,特别是在回顾之前思路的时候。同时,写下这个博客也算是记录自己的工作内容

所以,我开了这个文件,用来记录自己的笔记。作为阅听者的你,除非有特别的需求,否则建议退出,因为这里的内容可能是错误的,有偏差的,毫无格式的,语言不通顺的,可能会给你带来误导,特别当你对相关问题不熟悉的情况下!!!

阅读方式:基本没有什么固定的格式,一个建议的格式如下:

  • 发生一个事件、实现、修复或思考的时候,将其记录在三级标题中
  • 在每一个三级标题下有一个四级标题,用于记录创建时间与最后修改时间

1. mocklibc开发手记

[ADD] sleep函数

创建:2025_1_18_21:53;修改:2025_1_18_22:09

需要实现的:sleep(),依赖于:nanosleep()nanosleep依赖于syscall_ret__clock_nanosleep()

syscall_ret本身不难实现,注意的是要写入一个叫做errno的全局变量中

__clock_nanosleep或许可以作为替换的选择

__clock_nanosleep函数依赖__syscall_cp函数,以及IS32BIT宏(定义在好多地方)

src/thread/__syscall_cp.c 在中,通过 week_alias 告诉我们当 single thread 的时候 syscall_cp 可以退化为普通的 syscall 的。

不行的话,我就替换__clock_nanosleep

有一说一可以直接用sleep,ArceOS底层有这个函数[X],就用这个

完成支持。

[FIXED] BUG 实现pthread

创建19号上午 最后更新:2025-1-24 12:02

很奇怪,在不同情况下会跑飞之类的,但是也就这样了吧,先放下,解决另一个

在杨金全同学的帮助下完成了修正,具体请看[这个内容](#[FIXED] 在关于ArceOS mocklibc_libloader中线程创建的BUG修复[见专题文章])

[XXX] BUG Math库中,所有带l(long)类型的操作都会被导向到一些奇怪的符号,例如__getf2

创建19号中午

可能的相关文章:https://github.com/ziglang/zig/issues/5320

-fno-compiler-rt是什么?

有关运行时库的内容:https://compiler-rt.llvm.org/

这个是CSDN上的运行时库的介绍:https://blog.csdn.net/ssdlearnerused/article/details/107426495

这个是一个类似问题,有解决的:https://rustcc.cn/article?id=50ac4eec-17eb-4fc7-be08-a23d7794fefc

最接近和具有参考价值的:https://github.com/termux/termux-packages/issues/8029

image-20250119162526756

image-20250119162546755

image-20250119162657635

Yeah, that’s the problem: libtool supplying all the link flags to the compiler and overriding the runtime library the compiler chooses with -nostdlib. Maybe it needs to be patched to add compiler-rt instead of libgcc, but in the meantime, perhaps we could override it by passing in the -rtlib=compiler-rt flag for those packages, as I did with the Swift CMake config.
是的,这就是问题所在: libtool 向编译器提供所有链接标志,并使用 -nostdlib 覆盖编译器选择的运行时库。也许需要修补以添加 compiler-rt 而不是 libgcc,但与此同时,也许我们可以通过为这些包传递 -rtlib=compiler-rt 标志来覆盖它,就像我对 Swift CMake 配置所做的那样

gcc关于这个问题的通信邮件:

https://gcc.gnu.org/legacy-ml/gcc/2001-09/msg00262.html

https://gcc.gnu.org/legacy-ml/gcc/2001-09/msg00327.html

第一次修改方式

添加链接:$($CC -print-libgcc-file-name)

第一次修改前报错:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
make -C hello dynamic
make[1]: 进入目录“/home/marinatoo/Dev/arceos/mockc_apps/hello”
riscv64-linux-musl-gcc -nostdlib -nodefaultlibs -ffreestanding -O0 -mcmodel=medany -nostartfiles -I../../ulib/mocklibc_lib/include -c hello.c -o hello.o
riscv64-linux-musl-ld hello.o -L../../ulib/mocklibc_lib/lib -lmock -o hello
riscv64-linux-musl-ld: warning: cannot find entry symbol _start; defaulting to 0000000000010500
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__getf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__eqtf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__addtf3'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__floatsitf'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__divtf3'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__letf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__fixtfdi'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__fixtfsi'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__lttf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__netf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__extenddftf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__extendsftf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__multf3'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__gttf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__subtf3'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__trunctfsf2'
riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to `__trunctfdf2'
make[1]: *** [Makefile:37:dynamic] 错误 1
make[1]: 离开目录“/home/marinatoo/Dev/arceos/mockc_apps/hello”
make: *** [Makefile:8:subdir] 错误 2
第一次修改后报错:
1
2
3
4
5
6
7
8
9
10
make -C hello dynamic
make[1]: 进入目录“/home/marinatoo/Dev/arceos/mockc_apps/hello”
riscv64-linux-musl-gcc -nostdlib -nodefaultlibs -ffreestanding -O0 -mcmodel=medany -nostartfiles -I../../ulib/mocklibc_lib/include -c hello.c -o hello.o
riscv64-linux-musl-ld hello.o -L../../ulib/mocklibc_lib/lib -lmock /home/marinatoo/App/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/libgcc.a -o hello
riscv64-linux-musl-ld: warning: cannot find entry symbol _start; defaulting to 0000000000010500
riscv64-linux-musl-ld: hello: hidden symbol `__getf2' in /home/marinatoo/App/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/libgcc.a(getf2.o) is referenced by DSO
riscv64-linux-musl-ld: final link failed: bad value
make[1]: *** [Makefile:37:dynamic] 错误 1
make[1]: 离开目录“/home/marinatoo/Dev/arceos/mockc_apps/hello”
make: *** [Makefile:8:subdir] 错误 2

可能原因:https://stackoverflow.com/questions/23696585/what-does-exactly-the-warning-mean-about-hidden-symbol-being-referenced-by-dso

问题并未得到解决,这里我想应该是将上述符号切换为DEFAULT(HIDDEN),而不是让他们保持NOTYPE.

这是另一个相关的:https://gcc.gnu.org/bugzilla/show_bug.cgi?format=multiple&id=36669

该问题的完整描述:

我的问题是这样的:我使用的是musl的编译器(版本不重要),其在面临float_128类型变量的时候,出于某些我目前不能肯定的原因(我有看到说musl不支持这个长度),会尝试链接外部的函数,例如:__getf2这样的。
但是相关函数musl库本身并没有实现,那么我使用musl编译库的时候就会出现,由于我是要开发自己的库,使用了-nostdlib,所以屏蔽了标准库,然后我想说要不就先链接已有的这些外部函数。路径如下:/home/marinatoo/App/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/libgcc.a(getf2.o),然后链接后出现的问题是:
musl提供的gcc库里相关的符号是hidden的。然后我尝试链接会报错:riscv64-linux-musl-ld: hello: hidden symbol __getf2' in /home/marinatoo/App/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/libgcc.a(getf2.o) is referenced by DSO。不链接的话就是riscv64-linux-musl-ld: ../../ulib/mocklibc_lib/lib/libmock.so: undefined reference to __getf2'

不过这个在遇到float 128类型的时候调用llvm的compile_rt的行为是编译器进行的,所以其实有一个解决方案,就是将它需要的函数自己实现出来,不过考虑到其工作之多,我选择去部分使用llvm的那个实现,不过llvm最终就是用的我上面的那个gcc的实现,我也不确定是不是musl编译器自己的行为。
但是我出问题的函数是个纯数学库,然后编译后的目标文件中引用了符号”__getf2”,然后在这里是没有调用这个函数的,就是,这个是一个0函数调用库,它使用了一些宏定义(如 RPOLY 和 VPOLY)来计算多项式,但这些宏只是用来计算值,并不涉及对其他函数的调用。

然后我的编译选项如下:CFLAGS = -nostartfiles -ffreestanding -nostdlib -O0 -mcmodel=medany $(INTERNAL_INCLUDE) -fPIC

$(SHARED_LIB): $(LIBOBJS) $(CRTOBJS) $(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC -o $@ $^

LINK_FLAGS += /home/marinatoo/App/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/libgcc.a # 尝试修正compile-rt被-nolib屏蔽的问题,也就是__getf2符号没有的问题。

这个LINK_FLAGS就是在尝试手动链接这些缺失的库的,不过可以不加

==最终我还是选择自己去实现这些函数,然后直接链接了,然后在这里函数中跳转到一个“未实现”的系统调用,然后直接退出==

思考:是否可以找到足够底层且开放的输出接口,去完成musl中的输出底层接口的替换

创建:1_20_9:06

可能是axhal::console::write_bytes(s.as_bytes());,不带fmt,能直接输出,似乎可以作为musl中print_core函数的输出接口。往下再探索,发现其实就已经是跟具体的架构相关的代码了,感觉不是很适合继续挖掘。

现在的问题是,我打算直接使用printf_core来验证思路,但是printf_core在使用errno,而errno是需要通过__errno_location()的返回值来获取的,__errno_location()依赖__pthread_self()来获得,同时也依赖其返回的结构体指针,然后我要定位这个函数的位置。

#define __pthread_self() ((pthread_t)__get_tp()),依赖__get_tip()。这个与架构相关,RV64的:nvim arch/riscv64/pthread_arch.h

1
2
3
4
5
6
7
8
9
10
11
12
13
static inline uintptr_t __get_tp()
{
uintptr_t tp;
__asm__ __volatile__("mv %0, tp" : "=r"(tp));
return tp;
}

#define TLS_ABOVE_TP
#define GAP_ABOVE_TP 0

#define DTP_OFFSET 0x800

#define MC_PC __gregs[0]

我在想,这样的汇编其实什么都没做,不会影响执行流(对于RV64),那么是否可以直接用?

==我发现printf函数在面对FILE的问题的时候,需要大幅修改原来函数,会使得思路二的优势丧失,不建议使用了==

==在没有系统解决FILE的兼容之前,不能盲目替换。因此暂时放弃相关想法==

开发errno以及__errno_location()函数

创建:2025_1_20 13:16

直接复制的,用的就是上面的思路,直接使用,经过测试是报错了。

在理论上而言,tp应当指向一个结构体,映射关系就在这个结构体中,说明当前的硬件线程编号,以及已经分配的地址空间。但是我发现报错了,报的LoadFault。但是tp看不太出来问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Unhandled trap Exception(LoadFault) @ 0xffffffc080110670:
TrapFrame {
regs: GeneralRegisters {
ra: 0xffffffc08011066e,
sp: 0xffffffc080266620,
gp: 0xffffffc08026aff0,
tp: 0xffffffc080266520,
t0: 0xffffffc08021b8c8,
t1: 0xffffffc0801104ec,
t2: 0xf0,
s0: 0xffffffc080266670,
s1: 0x1,
a0: 0x80047f5c,
a1: 0x4,
a2: 0x0,
a3: 0x4,
a4: 0x4000000000,
a5: 0x80047f5c,
a6: 0x0,
a7: 0x4442434e,
s2: 0x2,
s3: 0xffffffc0802668b8,
s4: 0xffffffc080266958,
s5: 0xffffffc0802668f8,
s6: 0xffffffc08032f766,
s7: 0x11300000001,
s8: 0xffffffc08026aff0,
s9: 0x18,
s10: 0x9,
s11: 0x4,
t3: 0xffffffc08032f746,
t4: 0xffffffffffffffbf,
t5: 0x1,
t6: 0xffffffffffffff8f,
},
sepc: 0xffffffc080110670,
sstatus: 0x8000000200006100,
}

image-20250120140704716

总体而言是这样的,所以是出现了一些问题,本来应该去访问高地址的

image-20250120152822543

所以是tp寄存器本身的问题,这里会出现问题,也就是tp寄存器存在问题。tp寄存器存放的数值很奇怪,或者说,是否意味着,这个值本来就是在低地址呢?

==保留BUG==

我觉得得做文件系统的迁移了

创建:1_20 16:20

思路,先通过对文件系统操作的迁移,理解ArceOS的文件系统与Linux的文件系统的最基础共同点,然后以此为基础,进行对Linux文件系统的模拟

然后文件系统的迁移要优先考虑一些宏观操作的相同。

重点是能不能找到一些同级抽象的东西,或者说比目标兼容库更底层的操作,并以这些操作为基础组合模拟目标兼容库的底层操作。

做了一些

[FIXED] BUG修复:动态链接编译的时候,尤其是开了没有startfile的那个选项后,entry可能不是main函数

在load.rs中修复:

image-20250121111255172

修改后:

image-20250121115923606

[FIXED] BUG修复:lgamma_r.c文件中的函数在编译后会出现bgu指令,对a5寄存器的空间写,但是a5已经成0了,目前看不出有什么特别的点

创建时间:1_21 20:29

image-20250121202922883

image-20250121203003271

很神奇

出于对sw命令的定位,我做了如下操作:image-20250121203350630

image-20250121203336409

所以,问题定位完成。

问题是,这个东西理论上是有的哇:
image-20250121203808277

image-20250121203822400

可能是因为是全局变量的原因,没有被正确的指定!

image-20250121204100305

image-20250121204335172

所以我们可以知道,要在modify的时候,为这些全局变量做modify。

image-20250121205251093

这个符号我好像早就注意到了,但是一直没有理会,没想到真的出问题了。

一个很值得思考的是,函数是txt,所以位置是固定的,也不用考虑那么多,但是全局变量是什么东西?这个放在哪里?

最后修复方案:image-20250121213221303

阅读计划:https://blog.csdn.net/tjcwt2011/article/details/106520862

[FIXED] 超长期的一个BUG

创建:1_21 20:44 修改: 1_24 11:32

我发现,似乎在某些情况下,qemu在启动-l debug选项的时候就会发生:qemu卡死在一个tlb重填的位置,然后一直卡着,关闭掉qemu之后,反而在qemu.log上一直在写入,但是在文件系统中找不到文件,可是硬盘很快就会占满!具体描述后面我会插视频!

然而这个bug感觉似乎不是随时都可以的,而是在特殊的一段时间内,会频繁的发生,现在就可以,我有一个猜想:==可能是内存剩余空间少的时候,就会发生问题!==

==已经修正==

这个BUG的修正似乎与下面这个有一定的关系,当我修正[这个问题](#[FIXED] 关于在部分情况下使用debug参数和其他参数结果不一致的问题)后,这个超长期BUG就自己消失了。

[FIXED] 关于在部分情况下使用debug参数和其他参数结果不一致的问题

创建:2025_1_22,修改:2025_1_24 11:30

在过去一段时间内,在杨金全同学的帮助下,我发现了在libloader_lib应用中src/main.rs下汇编代码的一处错误,在修正这个错误后,似乎在执行QEMU模拟的时候不会再发生启用debug log参数和启用info log参数在结果上有不同的bug了。

具体如下:

image-20250124113039792

修改后:

image-20250124113059508

由于写下这个记录距离修正BUG已经过了两天,所以记录不是很详细

推测是由于写入的错误,损坏了一些关键信息,而这些信息在启用debug参数后是会被关键依赖,导致控制流程跑飞。具体跑飞包括LoadFault、StoreFault、TLB反复重填写等等。在启用qemulog记录的情况下,还会出现卡死、无法退出模拟,==并且在强行关闭后依然发生着向qemulog持续不停的写入新记录的情况,只能重启解决。这个问题我觉得很有意思,而且应该会导向qemu的一个关键bug。目前qemu的版本为9.1.2,系统是Ubuntu22.04 LTS。目前暂时不准备解决。我捕捉到一次发生的卡死是卡在了TLB重填写的部分,在访问一个地址的时候发生TLB缺失,重填后依然缺失,如此循环。==

image-20250124114220469

这个是一个截图的一部分,但是也完整涵盖了整个循环流程,因为截图中有隐私信息,就不全部展示了。

[Bug reserved.]关于Qemu中可能存在的BUG的讨论

创建:2025-1-24 11:44

[上述BUG](#[FIXED] 关于在部分情况下使用debug参数和其他参数结果不一致的问题)修正前会出现:

推测是由于写入的错误,损坏了一些关键信息,而这些信息在启用debug参数后是会被关键依赖,导致控制流程跑飞。具体跑飞包括LoadFault、StoreFault、TLB反复重填写等等。在启用qemulog记录的情况下,还会出现卡死、无法退出模拟,==并且在强行关闭后依然发生着向qemulog持续不停的写入新记录的情况,只能重启解决。这个问题我觉得很有意思,而且应该会导向qemu的一个关键bug。目前qemu的版本为9.1.2,系统是Ubuntu22.04 LTS。目前暂时不准备解决。我捕捉到一次发生的卡死是卡在了TLB重填写的部分,在访问一个地址的时候发生TLB缺失,重填后依然缺失,如此循环。==

image-20250124114220469

这个是一个截图的一部分,但是也完整涵盖了整个循环流程,因为截图中有隐私信息,就不全部展示了。

QEMU可能存在的BUG点是:在运行的时候卡死,就不能正常退出,而且退出后依然在向log书写,即使删除qemu.log,还是会继续书写,直到将空间占满卡崩Ubuntu。

BUG可以通过以下方式复现,感兴趣的可以去查看:

访问BUG所在的仓库分支,BUG存在于这一条提交记录中。clone之后,在arceos(也就是下载下的那个目录)中切换到对应的mocklibc_libloader分支下的提交记录:Commit 1c38b66,然后在arceos目录下运行命令./loader_lib.sh -l debug,就可以观察到。

再次声明我的环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
qemu --version
qemu-io version 9.1.2
Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers

cargo --version
warning: `/home/marinatoo/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
cargo 1.85.0-nightly (652623b77 2024-12-20)

neofetch
.-/+oossssoo+/-. marinatoo@marinatoo-ASUS-TUF
`:+ssssssssssssssssss+:` ----------------------------
-+ssssssssssssssssssyyssss+- OS: Ubuntu 22.04.4 LTS x86_64
.ossssssssssssssssssdMMMNysssso. Host: ASUS TUF Gaming F15 FX507ZM_FX507ZM 1.0
/ssssssssssshdmmNNmmyNMMMMhssssss/ Kernel: 6.8.0-51-generic
+ssssssssshmydMMMMMMMNddddyssssssss+ Uptime: 1 hour, 46 mins
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Packages: 2675 (dpkg), 21 (snap)
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Shell: bash 5.1.16
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Resolution: 4096x2304
ossyNMMMNyMMhsssssssssssssshmmmhssssssso DE: GNOME 42.9
ossyNMMMNyMMhsssssssssssssshmmmhssssssso WM: Mutter
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ WM Theme: Adwaita
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Theme: Yaru [GTK2/3]
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/ Icons: Yaru [GTK2/3]
+sssssssssdmydMMMMMMMMddddyssssssss+ Terminal: WarpTerminal
/ssssssssssshdmNNNNmyNMMMMhssssss/ CPU: 12th Gen Intel i7-12700H (20) @ 2.300GHz
.ossssssssssssssssssdMMMNysssso. GPU: Intel Alder Lake-P
-+sssssssssssssssssyyyssss+- GPU: NVIDIA GeForce RTX 3060 Mobile / Max-Q
`:+ssssssssssssssssss+:` Memory: 10288MiB / 15608MiB
.-/+oossssoo+/-.


[FIXED] 在关于ArceOS mocklibc_libloader中线程创建的BUG修复[见专题文章]

创建2025_1_24 11:30

[BUG] 关于metadata的新思考,与metadata“返回新的”的BUG记录

创建2025_2_18 17:32:00

[BUG]