diff --git a/articles/20230929-elf2flt-fix-install.md b/articles/20230929-elf2flt-fix-install.md
new file mode 100644
index 0000000000000000000000000000000000000000..9fd4f9731ef6de396eb5287df82422747faa23ce
--- /dev/null
+++ b/articles/20230929-elf2flt-fix-install.md
@@ -0,0 +1,189 @@
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [spaces codeblock codeinline pangu]
+> Author: Odysseus <320873791@qq.com>
+> Date: 2023/09/19
+> Revisor: walimis <>
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Proposal: [为 ELF2FLT 完善独立编译与安装支持](https://gitee.com/tinylab/riscv-linux/issues/I79PO2)
+> Sponsor: PLCT Lab, ISCAS
+
+# elf2flt 在 RISC-V 64 位下的独立编译和安装支持
+
+## 前言
+
+elf2flt 在设计之初是与 Buildroot 工具链结合使用的,但是它实际上也能搭配本机自带的工具链(例如 `/usr/bin/gcc`)使用。然而,原先的 elf2flt 安装过程存在问题,使得它无法正确安装到本机,与本机工具链结合使用。下面我们以 riscv-lab 下的安装过程为例,来看看其原因何在。
+
+## 过程
+
+首先我们克隆下来原来的 git 仓库,然后开始构建:
+
+```sh
+$ git clone https://gitee.com/tinylab/elf2flt
+$ cd elf2flt
+$ ./configure --target=riscv64-linux-gnu -with-bfd-include-dir=/usr/include/ \
+> --with-binutils-include-dir=/usr/include/ \
+> --with-libbfd=/usr/lib/riscv64-linux-gnu/libbfd.a \
+> --with-libiberty=/usr/lib/riscv64-linux-gnu/libiberty.a \
+> --disable-werror --build=riscv64-linux-gnu
+$ make
+$ sudo make install
+```
+
+它会报错,如下:
+
+```sh
+/usr/bin/install -c -d /usr/local/bin /usr/local/riscv64-linux-gnu/bin /usr/local/riscv64-linux-gnu/lib
+/usr/bin/install -c -m 755 flthdr /usr/local/bin/riscv64-linux-gnu-flthdr
+/usr/bin/install -c -m 755 flthdr /usr/local/riscv64-linux-gnu/bin/flthdr
+/usr/bin/install -c -m 755 elf2flt /usr/local/bin/riscv64-linux-gnu-elf2flt
+/usr/bin/install -c -m 755 elf2flt /usr/local/riscv64-linux-gnu/bin/elf2flt
+[ -f /usr/local/bin/riscv64-linux-gnu-ld.real ] || \
+ mv /usr/local/bin/riscv64-linux-gnu-ld /usr/local/bin/riscv64-linux-gnu-ld.real
+/usr/bin/mv: cannot stat '/usr/local/bin/riscv64-linux-gnu-ld': No such file or directory
+make: *** [Makefile:114: install] Error 1
+```
+
+这里我们可以对应到原 `Makefile.in` 的以下部分:
+
+```makefile
+install:
+ $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(target_bindir) $(DESTDIR)$(target_libdir)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(target_bindir)/$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_ELF2FLT)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(target_bindir)/$(PROG_ELF2FLT)
+ [ -f $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT) $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT)
+ [ -f $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(target_bindir)/ld$(EXEEXT) $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(target_bindir)/ld$(EXEEXT)
+ $(INSTALL) -m 644 $(SRC_LDFILE) $(DESTDIR)$(target_libdir)/$(LDFILE)
+```
+
+这个 `$(bindir)` 和 `$(target_bindir)` 分别是什么呢?我们在 `Makefile.in` 中寻找,发现它们的值如下:
+
+```makefile
+bindir = @bindir@
+
+# ...
+
+target_bindir = $(prefix)/$(TARGET)/bin
+```
+
+这个 `$(prefix)` 在 `./configure` 中被赋默认值:
+
+```sh
+ac_default_prefix=/usr/local
+
+# ...
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+```
+
+因此这里的 `riscv64-linux-gnu-ld` 默认会在 `/usr/local/bin` 下查找,但是那里显然没有,这意味着我们很可能要创建一个软链接,或者直接将别处 `riscv64-linux-gnu-ld` 复制到该目录下面。我们使用 `which` 命令查看我们的交叉工具链在哪里:
+
+```sh
+$ which riscv64-linux-gnu-gcc
+/usr/bin/riscv64-linux-gnu-gcc
+
+$ which riscv64-linux-gnu-ld
+/usr/bin/riscv64-linux-gnu-ld
+```
+
+可以看到工具链调用的是 `/usr/bin` 下的。这里每个人的情况可能会有所不同,后面可能会考虑在配置文件中增加工具链路径的配置选项。
+
+我们对此做出如下修改:
+
+```diff
+install:
+ $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(target_bindir) $(DESTDIR)$(target_libdir)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(target_bindir)/$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_ELF2FLT)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(target_bindir)/$(PROG_ELF2FLT)
++ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(bindir)/$(TARGET)-ld
++ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(target_bindir)/ld
+ [ -f $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT) $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT)
++ mv /usr/bin/$(TARGET)-ld /usr/bin/$(TARGET)-ld_old
++ ln -s $(DESTDIR)$(target_bindir)/ld /usr/bin/$(TARGET)-ld
+ $(INSTALL) -m 644 $(SRC_LDFILE) $(DESTDIR)$(target_libdir)/$(LDFILE)
+```
+
+另外,在 `$(bindir)/` 下的 elf2flt 和 flthdr 实际上是带前缀的,但是它们在被调用时是不带前缀的,因此会出现形如 `ld (ld-elf2flt): execvp: No such file or directory` 的错误。这里需要把链接加上:
+
+```diff
+install:
+ $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(target_bindir) $(DESTDIR)$(target_libdir)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(target_bindir)/$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_ELF2FLT)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(target_bindir)/$(PROG_ELF2FLT)
+ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(bindir)/$(TARGET)-ld
+ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(target_bindir)/ld
+ [ -f $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT) $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT)
+ [ -f $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(target_bindir)/ld$(EXEEXT) $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(target_bindir)/ld$(EXEEXT)
+ mv /usr/bin/$(TARGET)-ld /usr/bin/$(TARGET)-ld_old
+ ln -s $(DESTDIR)$(target_bindir)/ld /usr/bin/$(TARGET)-ld
++ ln -s $(DESTDIR)$(bindir)/$(TARGET)-elf2flt$(EXEEXT) $(DESTDIR)$(bindir)/elf2flt$(EXEEXT)
++ ln -s $(DESTDIR)$(bindir)/$(TARGET)-flthdr$(EXEEXT) $(DESTDIR)$(bindir)/flthdr$(EXEEXT)
+ $(INSTALL) -m 644 $(SRC_LDFILE) $(DESTDIR)$(target_libdir)/$(LDFILE)
+```
+
+到了这一步重新进行安装,过程看起来比较顺利。然而我们编译一个简单的 hello-world 时,仍然发生了 `ld (ld-elf2flt): execvp: No such file or directory` 的错误,如下:
+
+```sh
+$ riscv64-linux-gnu-gcc -nostdinc -nostdlib -I/usr/bin/../lib/gcc/riscv64-linux-gnu/11/include -I/usr/bin/../lib/gcc/riscv64-linux-gnu/11/include-fixed -I/labs/riscv-lab/buildroot/output/host/riscv64-buildroot-linux-uclibc/sysroot/usr/include /labs/riscv-lab/buildroot/output/build/uclibc-1.0.44/lib/crt1.o /usr/lib/gcc/riscv64-linux-gnu/11/crti.o /usr/lib/gcc/riscv64-linux-gnu/11/crtbeginT.o -L/usr/lib/gcc/riscv64-linux-gnu/11 -L/usr/lib/gcc -L/labs/riscv-lab/buildroot/output/build/uclibc-1.0.44/lib -Wl,--build-id=none -Wl,-elf2flt=-r -o hello-b-gcc hello.c --static -lc -lgcc /usr/lib/gcc/riscv64-linux-gnu/11/crtend.o /usr/lib/gcc/riscv64-linux-gnu/11/crtn.o
+ld (ld-elf2flt): execvp: No such file or directory
+collect2: error: ld returned 1 exit status
+```
+
+经查,发现原因是 `$(target_bindir)/` 下面没有程序 `nm`,导致 `ld` 在调用它时出现问题。因此我们加上一句链接:
+
+```diff
+install:
+ $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(target_bindir) $(DESTDIR)$(target_libdir)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_FLTHDR) $(DESTDIR)$(target_bindir)/$(PROG_FLTHDR)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-$(PROG_ELF2FLT)
+ $(INSTALL) -m 755 $(PROG_ELF2FLT) $(DESTDIR)$(target_bindir)/$(PROG_ELF2FLT)
+ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(bindir)/$(TARGET)-ld
+ cp /usr/bin/$(TARGET)-ld $(DESTDIR)$(target_bindir)/ld
+ [ -f $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT) $(DESTDIR)$(bindir)/$(TARGET)-ld.real$(EXEEXT)
+ [ -f $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT) ] || \
+ mv $(DESTDIR)$(target_bindir)/ld$(EXEEXT) $(DESTDIR)$(target_bindir)/ld.real$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(bindir)/$(TARGET)-ld$(EXEEXT)
+ $(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(DESTDIR)$(target_bindir)/ld$(EXEEXT)
+ mv /usr/bin/$(TARGET)-ld /usr/bin/$(TARGET)-ld_old
+ ln -s $(DESTDIR)$(target_bindir)/ld /usr/bin/$(TARGET)-ld
+ ln -s $(DESTDIR)$(bindir)/$(TARGET)-elf2flt$(EXEEXT) $(DESTDIR)$(bindir)/elf2flt$(EXEEXT)
+ ln -s $(DESTDIR)$(bindir)/$(TARGET)-flthdr$(EXEEXT) $(DESTDIR)$(bindir)/flthdr$(EXEEXT)
++ ln -s /usr/bin/$(TARGET)-nm $(DESTDIR)$(target_bindir)/nm
+ $(INSTALL) -m 644 $(SRC_LDFILE) $(DESTDIR)$(target_libdir)/$(LDFILE)
+```
+
+至此问题解决,`riscv64-linux-gnu-gcc` 能够编译出正常的 bFLT 程序:
+
+```sh
+$ riscv64-linux-gnu-gcc -nostdinc -nostdlib -I/usr/bin/../lib/gcc/riscv64-linux-gnu/11/include -I/usr/bin/../lib/gcc/riscv64-linux-gnu/11/include-fixed -I/labs/riscv-lab/buildroot/output/host/riscv64-buildroot-linux-uclibc/sysroot/usr/include /labs/riscv-lab/buildroot/output/build/uclibc-1.0.44/lib/crt1.o /usr/lib/gcc/riscv64-linux-gnu/11/crti.o /usr/lib/gcc/riscv64-linux-gnu/11/crtbeginT.o -L/usr/lib/gcc/riscv64-linux-gnu/11 -L/usr/lib/gcc -L/labs/riscv-lab/buildroot/output/build/uclibc-1.0.44/lib -Wl,--build-id=none -Wl,-elf2flt=-r -o hello-b-gcc hello.c --static -lc -lgcc /usr/lib/gcc/riscv64-linux-gnu/11/crtend.o /usr/lib/gcc/riscv64-linux-gnu/11/crtn.o
+$
+```
+
+## 总结
+
+elf2flt 独立编译和安装存在的问题主要是安装部分,因此在修改 `Makefile.in` 后得以解决。消除 Buildroot 的依赖则是另一个问题,需要仔细观察 Buildroot 交叉编译时依赖了哪些库和头文件,并且想办法去除这些依赖,这里不详细说明。
+
+## 参考资料
+
+- [https://gitee.com/tinylab/riscv-linux/blob/master/articles/20230919-elf2flt-flt-analysis-0.md][001]
+- [https://gitee.com/tinylab/elf2flt][002]
+
+[001]: https://gitee.com/tinylab/riscv-linux/blob/master/articles/20230919-elf2flt-flt-analysis-0.md
+[002]: https://gitee.com/tinylab/elf2flt