昨日正準備要有所作為,卻發現上游裡面有根本的短少!這該怎麼辦才好呢?決定今天來好好研究一下貢獻的規則,go 語言社群的規則和 github 上面直接單純的 PR 模式是不一樣的。
我們先重新回顧昨日展示的繼有重定型態
1730 // Relocation types for RISC-V processors.
1731 type R_RISCV int
1732
1733 const (
1734 R_RISCV_NONE R_RISCV = 0 /* No relocation. */
1735 R_RISCV_32 R_RISCV = 1 /* Add 32 bit zero extended symbol value */
1736 R_RISCV_64 R_RISCV = 2 /* Add 64 bit symbol value. */
1737 R_RISCV_RELATIVE R_RISCV = 3 /* Add load address of shared object. */
1738 R_RISCV_COPY R_RISCV = 4 /* Copy data from shared object. */
1739 R_RISCV_JUMP_SLOT R_RISCV = 5 /* Set GOT entry to code address. */
1740 R_RISCV_TLS_DTPMOD32 R_RISCV = 6 /* 32 bit ID of module containing symbol */
1741 R_RISCV_TLS_DTPMOD64 R_RISCV = 7 /* ID of module containing symbol */
1742 R_RISCV_TLS_DTPREL32 R_RISCV = 8 /* 32 bit relative offset in TLS block */
1743 R_RISCV_TLS_DTPREL64 R_RISCV = 9 /* Relative offset in TLS block */
1744 R_RISCV_TLS_TPREL32 R_RISCV = 10 /* 32 bit relative offset in static TLS block */
1745 R_RISCV_TLS_TPREL64 R_RISCV = 11 /* Relative offset in static TLS block */
1746 )
這是 src/debug/elf/elf.go 檔案裡面的重定部分,未免也太少了吧!來看在 RISC-V 基金會的官方文件裡面有多少個?目前有定義的有 0~56,共 57 個,剩下的則是保留區。由於篇幅太多,筆者就不引用以免灌水。
看來,目前 riscv-go 上面的實作這 12 個重定型態的編號與手冊上的編號恰好一樣,但有沒有可能這只是巧合?我們有兩個地方可以檢查,
首先我們查查看當初的 commit 在哪裡
git blame src/debug/elf/elf.go
從裡面隨意挑一行來看,比方說 1734 行的 R_RISCV_NONE
無重定型態好了,
...
a5e7fc4fc62 src/debug/elf/elf.go (Amol Bhave 2016-11-16 23:49:56
...
我們發現是 Amol Bhave 這個人在前年底的貢獻。有了 commit 號碼之後,也能夠看看這個 patch 長什麼樣了:
$ git show a5e7fc4fc62
commit a5e7fc4fc62b6ed21bc30fd934f53a55111d1238
Author: Amol Bhave <ammubhave@gmail.com>
Date: Wed Nov 16 23:49:56 2016 +0000
debug/elf: Add RISC-V definitions to debug/elf
This is the first step in getting cgo to work. cgo uses debug/elf
for elf parsing.
Change-Id: I7ec1c73206ed0b89e483660fe572fd53aa37a905
diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go
index 6e6c801a49..17a9549e82 100644
--- a/src/debug/elf/elf.go
+++ b/src/debug/elf/elf.go
@@ -237,6 +237,7 @@ const (
EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */
EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */
EM_AARCH64 Machine = 183 /* ARM 64-bit Architecture (AArch64) */
+ EM_RISCV Machine = 243 /* RISC-V */
...
哇,RISC-V 的機器編號竟然是在這裡訂的?那這可是一個重要 patch 呢!裡面的描述是,這是讓 cgo 函式庫能夠正確運作的第一步(果然重要)。省略的部份之後不久就有我們一開始引用的那些重定型態定義。
但是這又更啟筆者疑竇:這些重定就足夠 cgo 運作了嗎?
從 git 考古沒有什麼進展,看看另外這個專案吧!至少人家的完整度是有目共睹的。先來到 /riscv-tools/riscv-gnu-toolchain/riscv-binutils-gdb
路徑之內搜尋,預計應該會在某個標頭檔裡面吧?
$ find ./ -name "*.h" | xargs grep R_RISCV_CALL
./bfd/bfd-in2.h: BFD_RELOC_RISCV_CALL,
./bfd/bfd-in2.h: BFD_RELOC_RISCV_CALL_PLT,
./bfd/libbfd.h: "BFD_RELOC_RISCV_CALL",
./bfd/libbfd.h: "BFD_RELOC_RISCV_CALL_PLT",
./include/elf/riscv.h: RELOC_NUMBER (R_RISCV_CALL, 18)
./include/elf/riscv.h: RELOC_NUMBER (R_RISCV_CALL_PLT, 19)
抓到了,大概就是最後面這兩行吧。進去看看:
/* Relocation types. */
START_RELOC_NUMBERS (elf_riscv_reloc_type)
/* Relocation types used by the dynamic linker. */
RELOC_NUMBER (R_RISCV_NONE, 0)
RELOC_NUMBER (R_RISCV_32, 1)
RELOC_NUMBER (R_RISCV_64, 2)
RELOC_NUMBER (R_RISCV_RELATIVE, 3)
RELOC_NUMBER (R_RISCV_COPY, 4)
RELOC_NUMBER (R_RISCV_JUMP_SLOT, 5)
RELOC_NUMBER (R_RISCV_TLS_DTPMOD32, 6)
RELOC_NUMBER (R_RISCV_TLS_DTPMOD64, 7)
RELOC_NUMBER (R_RISCV_TLS_DTPREL32, 8)
RELOC_NUMBER (R_RISCV_TLS_DTPREL64, 9)
RELOC_NUMBER (R_RISCV_TLS_TPREL32, 10)
RELOC_NUMBER (R_RISCV_TLS_TPREL64, 11)
/* Relocation types not used by the dynamic linker. */
RELOC_NUMBER (R_RISCV_BRANCH, 16)
RELOC_NUMBER (R_RISCV_JAL, 17)
RELOC_NUMBER (R_RISCV_CALL, 18)
RELOC_NUMBER (R_RISCV_CALL_PLT, 19)
RELOC_NUMBER (R_RISCV_GOT_HI20, 20)
...
唉呀,看這個註解,找到原因啦!所有的線索都兜在一起了!因為他們的最終目標是 cgo,而 go 語言與 C 語言的聯動是透過動態連結來完成的,所以他們就對 12 之後的部份不屑一顧啦!
那筆者究竟該如何自處呢?這真是個好問題......
最近幾天實在忙到有點崩壞,還好今天在考古的過程中還能挖掘出一些之前想不懂的東西。事實上,就算他們目標是 cgo 而已,也不代表 elf.go 這個檔案就只能有這個能力;我們不是擺明了有的用途嗎?而且其他的每一種架構也都有完整的重定型態列表,所以這不能阻止筆者的貢獻!問題只在要摸清楚他們的貢獻模式了,目前還不是很懂 GerritHub 的用法。無論如何,趁著週末好好研究衝刺一下鐵人賽的終點線吧!各位讀者,我們明日再會!