いけむランド

はてダからやってきました

x86_64-elf-gcc を触ってみる

homebrew に x86_64-elf-gcc があることに気づいてたので触ってみることにしました。

$ brew info x86_64-elf-gcc
x86_64-elf-gcc: stable 10.2.0 (bottled)
The GNU compiler collection for x86_64-elf
https://gcc.gnu.org
/usr/local/Cellar/x86_64-elf-gcc/10.2.0 (584 files, 122MB) *
  Poured from bottle on 2020-08-03 at 07:35:56
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/x86_64-elf-gcc.rb
==> Dependencies
Required: gmp ✔, libmpc ✔, mpfr ✔, x86_64-elf-binutils ✔
$

とりあえず Hello, world! することにします。

$ cat main.c
int main() { printf("Hello, world!\n"); }
$ x86_64-elf-gcc main.c
main.c:1:10: fatal error: stdio.h: No such file or directory
    1 | #include <stdio.h>
      |          ^~~~~~~~~
compilation terminated.
$

ヘッダファイルが見当たらないため、動かす予定の環境 (Ubuntu 20.04.1 LTS) のパッケージから引っこ抜くことにします。

$ wget http://mirrors.kernel.org/ubuntu/pool/main/g/glibc/libc6-dev_2.31-0ubuntu9_amd64.deb
$ dpkg -x libc6-dev_2.31-0ubuntu9_amd64.deb ${HOME}/sys-root/ubuntu
$

インクルードパスを追加して、再コンパイルしてみます。

$ x86_64-elf-gcc main.c -I ${HOME}/sys-root/ubuntu/usr/include -I ${HOME}/sys-root/ubuntu/usr/include/x86_64-linux-gnu
/usr/local/opt/x86_64-elf-binutils/bin/x86_64-elf-ld: cannot find crt0.o: No such file or directory
/usr/local/opt/x86_64-elf-binutils/bin/x86_64-elf-ld: cannot find -lc
collect2: error: ld returned 1 exit status
$

コンパイルはできますが、リンクでこけます。 libc6-devel にはそもそも crt0.o が入っていないようです。

一応、生成されたオブジェクトが ELF かどうかを確認しておきます。

$ x86_64-elf-gcc main.c -I ${HOME}/sys-root/ubuntu/usr/include -I ${HOME}/sys-root/ubuntu/usr/include/x86_64-linux-gnu -c
$ file main.o
main.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$

続きは ubuntu 側でやってみます。(scp などで適当にコピーします)

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
$ gcc main.o
/usr/bin/ld: main.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
collect2: error: ld returned 1 exit status
$

mac 側で -fPIE をつけてコンパイルしなおし、それを再度 ubuntu 側に持っていきます。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
$ gcc main.o
$ ./a.out
Hello, world!
$

リンクまでさせたい場合は自前で gcc をコンパイルする必要がありそうです。