🧶
Linker ScriptのSORTについて調べる
はじめに
リンカスクリプトを見てると、たまにSORT
とかかれているところが見つかります。
例えば以下。
// cpu/cortexm_common/ldscripts/cortexm_base.ld
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
_isr_vectors = DEFINED(_isr_vectors) ? _isr_vectors : . ;
KEEP(*(SORT(.vectors*))) // <-- ここ
何かをソートしているとは思うのですが、よくわかっていなかったので調べてみました。
Document
以下の記載がある。
Normally, the linker will place files and sections matched by
wildcards in the order in which they are seen during the link.
You can change this by using the SORT_BY_NAME keyword, which
appears before a wildcard pattern in parentheses (e.g., SORT_BY_NAME(.text*)).
When the SORT_BY_NAME keyword is used, the linker will sort the files or
sections into ascending order by name before placing them in the output file.
(省略)
SORT is an alias for SORT_BY_NAME.
動作確認(テストの実行)
Document記載の通りなのでしょうが、ちょっと動作も確認したいところ。
コードを確認したら以下のようなものがありました。
ld/testsuite/ld-scripts/sort_b_n.d
#source: sort_b_n.s
#ld: -T sort_b_n.t
#name: SORT_BY_NAME
#nm: -n
#...
0[0-9a-f]* t text
#...
0[0-9a-f]* t text1
#...
0[0-9a-f]* t text2
#...
0[0-9a-f]* t text3
#pass
testsuite
というフォルダに入っているのでテストコードなのでしょう。
このテストの実行方法を調べたら、似たような事を質問している人がいました。
How to build and run the GNU GAS assembler test suite?
DejaGnu が必要ということなので
インストールしてテストの実行をしてみる。
SORTについてのテストも動いているっぽい。
$ sudo apt install dejagnu
$ mkdir build
$ cd build
$ ../configure
$ make
$ cd ld
$ make check
make check-recursive
(省略)
=== ld tests ===
Schedule of variations:
unix
Running target unix
Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
Using /home/<USERNAME>/binutils-gdb/ld/testsuite/config/default.exp as tool-and-target-specific interface file.
(省略)
Running /home/<USERNAME>/binutils-gdb/ld/testsuite/ld-scripts/sort.exp ...
(省略)
=== ld Summary ===
# of expected passes 2570
# of expected failures 57
# of untested testcases 1
# of unsupported tests 23
./ld-new 2.35
動作確認(link後のバイナリ確認)
テストは動かせたので、SORTの有無で出力されるバイナリにどのような違いがあるかを
確認してみる。
ld/testsuite/ld-scripts/sort_b_n.d で使用しているasmコードを適当なディレクトリに用意。
ファイル名はsample.s
とした。
.section .text2
text2:
.long 0
.section .text3
text3:
.long 0
.section .text1
text1:
.long 0
.text
text:
.long 0
linker scriptは以下の2つを用意。
// sample.ld
SECTIONS
{
.text : {*(SORT_BY_NAME(.text*))}
/DISCARD/ : { *(.*) }
}
// sample2.ld
// SORT_BY_NAMEを削除
SECTIONS
{
.text : {*(.text*)}
/DISCARD/ : { *(.*) }
}
アセンブル、リンクをしてobjdumpで
disassembleの結果を出力。
(ARM用のgccを使用)
$ arm-none-eabi-as -o sample.o sample.s
# それぞれのlinker scriptを指定してlink
$ arm-none-eabi-ld -T sample.ld sample.o -o sample
$ arm-none-eabi-ld -T sample2.ld sample.o -o sample2
# objdumpの結果を出力
$ arm-none-eabi-objdump -D sample > objdump-sample.txt
$ arm-none-eabi-objdump -D sample2 > objdump-sample2.txt
結果を比較。
$ diff -y --left-column objdump-sample.txt objdump-sample2.txt
(
sample: file format elf32-littlearm | sample2: file format elf32-littlearm
(
(
Disassembly of section .text: (
(
00000000 <text>: (
0: 00000000 andeq r0, r0, r0 (
(
00000004 <text1>: | 00000004 <text2>:
4: 00000000 andeq r0, r0, r0 (
(
00000008 <text2>: | 00000008 <text3>:
8: 00000000 andeq r0, r0, r0 (
(
0000000c <text3>: | 0000000c <text1>:
c: 00000000 andeq r0, r0, r0 (
テキストだとちょっと見にくいので、VS Code上で比較した結果。
SORTをつけた場合は、text,text1,text2,text3の順番に並んでいる(下記画像左側)。
Discussion