貧乏人のラズパイ(もどき)

Windows7アップデートの嫌がらせが終ったと思ったら、今度は10にすると、 Windows 10のLinux/Ubuntu互換環境でbashを使う こんな楽しい事が出来るとよ、あざ笑うような 記事が流れている。腹立つ事に64Bit版のみですって、今時32Bitを選んで入れる 人も居まい。ああ、古い7ユーザーを締め出す作戦ね。

そんな事で、 Windowsコマンドプロンプトの入門から使いこなしまでの記事が気になった。

Git for Windows を入れると、gitだけではなく、MSYSの新しいのも付いてくるのね。 今入れてる古いMSYSを置き換えるのには良い選択かもね。

いやいや、Windowsと親和する事は止しておこう。なるべく、お近づきにならない 方が幸せってもんです。

Windows10にウブを組み込むを、余計な穴を持ち込む事になるらしい。それに、 組み込むウブが今の所、古いLTSに限られているってどうよ。そこん所が、仮に 自由奔放にどうぞってなっても、間にWinが挟まるって気持ち悪い。

VMWAREとかVBOX上のゲストOSみたいに、Winからきちんと隔離されてる方が、 絶対にトラブルは少ないと思うよ。

やっても、ゲスト側からsmbでマウントして、ファイルを読み書きするぐらいに 留めておいた方が安心、と思うぞ。

FreeBSDではARM出来るか?

変な日本語だ。ARM出来るって、どゆ事? 作るんじゃなくて、使う方ね。 ラズパイって言ったら、Linuxを入れてPythonを動かすってのが定番だけど 、それじゃPCでやるのの何ら変わらない。

そう言っちゃ失礼だろう。I/Oポートが開放されてて、自由に叩けるってのが 売りなんですから。パソコンでそれをやろうとすると、えらく大変になる。

で、ラズパイと言うハードは、色々と付属品やらが必要になり、秋田時に ごみになっちゃうのが心配。そんな理由で、去年、ARMのボードの シュミレータである、qemuを動かした。あの時はLinux上でやったけど、 BSDでは、どうよ? 同じ事が出来るのか? 調べてみよう。 (1年毎の、同じような企画を、ちょっと角度を変えてやるのは、某雑誌 そっくりです。)

$ pkg search qemu
aqemu-0.8.2_1                  Qt 4 based Qemu frontend
kqemu-kmod-devel-1.4.0.p1_5    Kernel Accelerator for QEMU CPU Emulator (development version)
qemu-2.5.1.1                   QEMU CPU Emulator
qemu-cheri-0.d20160624         QEMU emulator with CHERI CPU support
qemu-cheri128-0.d20160624      QEMU emulator with CHERI CPU support (128-bit)
qemu-cheri128m-0.d20160624     QEMU emulator with CHERI CPU support (128-bit, magic compression)
qemu-devel-2.6.0_1             QEMU CPU Emulator - development version
qemu-launcher-1.7.4_6          GTK front-end to Qemu

128-Bitって言う、不穏なやつは何でしょ? それはさておき、qemu-userモードって のが無いなあ。あれはLinuxの特技なのか。

CHERI CPUって何かと思って調べてみたら、 Capability Hardware Enhanced RISC Instructions (CHERI)に行き着いた。始まりはいつも英国からですか。 面白いなあ。

で、user modeはLinuxでしか動かないはずなんだけど、portsの下を見ると、 qemu-user-staticなんてのが用意されてたよ。

    * User mode emulation (Linux host only). In this mode, QEMU can launch
Linux processes compiled for one CPU on another CPU. It can be used to
launch the Wine Windows API emulator or to ease cross-compilation and
cross-debugging.

As QEMU requires no host kernel patches to run, it is very safe and easy to use.

This is a slave port of emulators/qemu-sbruno to build only static
bsd-user targets named like qemu-mips-static.  While still being
experimental people have already built quite a few armv6/mips/mips64
packages using these and e.g. poudriere.  Some notes are also here:

http://wiki.freebsd.org/QemuUserModeHowTo

世の中には、とんがった人が居るなあ。おまいら、頑張りすぎだよ。いいや、もっと やれ!

開発環境としては、クロスコンパイラーとかgdbが用意されてた。世の趨勢として arm版が一番充実してるのは、言うまでもない。

ここまではよい。何でも有りを売りにしてる、FreeBSDなんだから。他のBSDではどうよ。 他のBSDと言っても、NetBSDは、世界CPU遺産にオイラー的には推薦したいぐらいだから、おのずと、OpenBSDがターゲットになろう。

おっと、NetBSDに対して失礼な事言っちゃったな。OpenBSDの本家はNetBSDですから。 本家の方も、色々やってる人が居ましたよ。 qemuでNetBSD/earmを体験する

OpenBSDに有れば、メジャーなものと認定して良いだろう。

OpenBSDではARM出来るか?

調べてみた。CATファイルは、パッケージと提供されてるリスト。これを一度 作っておくと後が楽なんで、OpenBSDをインストール時に手間をかけている。

[ob: ~]$ grep arm CAT
 arm-1.4.5.0p1.tgz
 arm-elf-binutils-2.20p1.tgz
 arm-elf-gdb-7.1p2.tgz
 arm-none-eabi-binutils-2.25.tgz
 arm-none-eabi-gcc-linaro-4.9.2015.03.tgz
 arm-none-eabi-gdb-7.9.1p1.tgz
 arm-none-eabi-newlib-2.2.0.1.tgz
 armagetronad-0.2.8.3.3.tgz
 :

候補が色々出てきたので、ports/develの下を覗いて、どんなものが入るか 一応確認。gccを入れると、必要な物がつられて入ってくる。

# pkg_add arm-none-eabi-gcc-linaro
quirks-2.197 signed on 2016-02-24T23:26:39Z
arm-none-eabi-gcc-linaro-4....:mpfr-3.1.0.3p0: ok
arm-none-eabi-gcc-linaro-4....:libmpc-0.9p1: ok
arm-none-eabi-gcc-linaro-4....:arm-none-eabi-binutils-2.25: ok
arm-none-eabi-gcc-linaro-4.9.2015.03: ok
# pkg_add arm-none-eabi-gdb
quirks-2.197 signed on 2016-02-24T23:26:39Z
Can't install arm-none-eabi-gdb-7.9.1p1 because of conflicts (gdb-7.10.1)
--- arm-none-eabi-gdb-7.9.1p1 -------------------
Can't install arm-none-eabi-gdb-7.9.1p1: conflicts

続いてarm用のgdbを入れようとしたら、i386用のgdbとコンフリクトするってんで 拒否された。後回しにしよう。libcの代替品を入れる。

# arm-none-eabi-newlib-2.2.0.1.tgz
ksh: arm-none-eabi-newlib-2.2.0.1.tgz: not found
# pkg_add arm-none-eabi-newlib-2.2.0.1.tgz
quirks-2.197 signed on 2016-02-24T23:26:39Z
arm-none-eabi-newlib-2.2.0.1: ok

そして、qemuを入れる。

# pkg_add qemu
quirks-2.197 signed on 2016-02-24T23:26:39Z
qemu-2.2.1p19:libnfs-1.9.8: ok
qemu-2.2.1p19:libssh2-1.6.0: ok
qemu-2.2.1p19:atk-2.18.0: ok
qemu-2.2.1p19:jasper-1.900.1p4: ok
qemu-2.2.1p19:shared-mime-info-1.5: ok
qemu-2.2.1p19:gdk-pixbuf-2.32.3: ok
qemu-2.2.1p19:libcroco-0.6.11: ok
qemu-2.2.1p19:librsvg-2.40.13: ok
qemu-2.2.1p19:hicolor-icon-theme-0.15: ok
qemu-2.2.1p19:gtk-update-icon-cache-3.18.7: ok
qemu-2.2.1p19:gnome-icon-theme-3.12.0p3: ok
qemu-2.2.1p19:gnome-icon-theme-symbolic-3.12.0p2: ok
qemu-2.2.1p19:gtk+2-2.24.29: ok
qemu-2.2.1p19:vte-0.28.2p17: ok
qemu-2.2.1p19:libusb1-1.0.20: ok
qemu-2.2.1p19:libiscsi-1.15.0p0: ok
qemu-2.2.1p19:dtc-1.4.1: ok
qemu-2.2.1p19: ok
Look in /usr/local/share/doc/pkg-readmes for extra documentation.

音をちゃんと鳴らずんだか、qemu用のコントロールターミナル用だか知らないけど 関係者が沢山付いてきた。こういうの選択的に入れられるといいのにと何時も 思っちゃうぞ。

最後に衝突回避で導入を拒否されたgdb。パッキングリストをarm用とi386用で 見比べてみたら、本体はしっかり別の名前になってるのに、shareの下とかに 入るものが、同名になってた。こういう理由で混ざるのを嫌ったんだな。

i386用を削除。arm用をインストール。本体だけを/tmpに退避。arm用を削除。 i386用のパッケージをインストール。最後に /tmpに退避したarm用gdbを 所定の位置に移動。まあ、こうして、美しいパッケージ管理が崩れて行くの です。どうせ、半年経つと、新しいOSから入れなおすんで、多少の事は、 見なかった事にします。

gdbでarmのシュミレート

arm用のgdbを入れた時、runも付いてきた。これはgdbが用意してくれるシュミレータ だろうね。動くかやってみる。ソースは、確かgdbのシュミレータの所に有ったやつと 記憶してる。(巻末に添付)

[ob: arm-asm]$ make
arm-none-eabi-as hello.s -o z.o
arm-none-eabi-ld z.o
arm-none-eabi-run a.out
Hello, world.
[ob: arm-asm]$ ./a.out
./a.out[1]: syntax error: `^A$@4・ス$B^B^B^E4' unexpected
[ob: arm-asm]$ file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1

Linuxでは、単独で動いたけど、そういう支援(qemu-user-static ?)が無い 環境では、シュミレータが必要って事だな。

[ob: arm-asm]$ arm-none-eabi-gdb a.out
 :
This GDB was configured as "--host=i386-unknown-openbsd5.9 --target=arm-none-eabi".
Type "show configuration" for configuration details.
 :
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section .text, size 0x58 vma 0x8000
Start address 0x8000
Transfer rate: 704 bits in <1 sec.
(gdb) run
Starting program: /home/sakae/src/arm-asm/a.out
Hello, world.
[Inferior 1 (process 42000) exited normally]

こういう手間をかけない為に、runが有るのだな。

[ob: arm-asm]$ arm-none-eabi-run -d -t a.out
pc: 8000,  nop                  ; (mov r0, r0)
pc: 8004,  bl   0x00000014
pc: 8018,  movw r4, #32776      ; 0x8008
pc: 801c,  movt r4, #0
pc: 8020,  mov  r0, #3
pc: 8024,  mov  r1, r4
pc: 8028,  svc  0x00123456
pc: 802c,  add  r4, r4, #1
pc: 8030,  sub  r3, r3, r3
pc: 8034,  ldrb r5, [r4, r3]
pc: 8038,  teq  r5, #0
pc: 803c,  bne  0xffffffe4
pc: 8020,  mov  r0, #3
pc: 8024,  mov  r1, r4
pc: 8028,  svc  0x00123456
     :
pc: 8028,  svc  0x00123456
Hello, world.
pc: 802c,  add  r4, r4, #1
pc: 8030,  sub  r3, r3, r3
pc: 8034,  ldrb r5, [r4, r3]
pc: 8038,  teq  r5, #0
pc: 803c,  bne  0xffffffe4
pc: 8040,  mov  r0, #24
pc: 8044,  ldr  r1, [pc, #8]    ; 0x00000010
pc: 8048,  svc  0x00123456

こんな事も出来たんですねぇ。段々思い出してきたぞ。

ふと、このアセンブラコードに、入力するシステムコールが無いか気になった。 確か、元はgdb/sim/armの中に有るソースで実現されてたはず。広い空き地の有る ウブの/tmpに展開して確認。armos.cが担当してた。

          switch (state->Reg[0])
            {
            case -1:
              /* This can happen when a SWI is interrupted (eg receiving a
                 ctrl-C whilst processing SWIRead()).  The SWI will complete
                 returning -1 in r0 to the caller.  If GDB is then used to
                 resume the system call the reason code will now be -1.  */
              return TRUE;

              /* Unimplemented reason codes.  */
            case AngelSWI_Reason_ReadC:
            case AngelSWI_Reason_TmpNam:
            case AngelSWI_Reason_System:
            case AngelSWI_Reason_EnterSVC:
            default:
              state->Emulate = FALSE;
              return FALSE;

なんか、入力系は、問題有って駄目みたい。強引に

            case AngelSWI_Reason_WriteC:
              {
                char tmp = ARMul_SafeReadByte (state, addr);
                (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
                OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
                break;
              }

を手本に改造してみたけど、思い通りの動きをしなかったぞ。もう、アセンブラ直は 諦めましょ。ああ、それから、runのオプションが微妙に変わってて、-dなんて、 ウブのそれには無かったぞ。

Angelを探していた時に見つけたのを、記念に記録しておく。

DebugMonハンドラ再び ── newlib向けシステムコールの実

QEMU ARM で遊ぼう

newlibを使ってみる

アセンブラだけじゃ体力と言うか知力が足りなくなるので、C語をやってみる。 組み込み用にnewlibが使えるようにgccが構築されてるから。(glibcは大き過ぎて 使えない/使えない)

#include <stdio.h>

char buff[256];

int main(){
        printf("Hello ARM, input pls.\n");
        fgets(buff,255,stdin);
        fputs(buff,stdout);
}
[ob: hello]$ arm-none-eabi-gcc -g hello.c
[ob: hello]$ arm-none-eabi-gdb -q a.out
Reading symbols from a.out...done.
(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section .init, size 0x18 vma 0x8000
Loading section .text, size 0x3a34 vma 0x8018
Loading section .fini, size 0x18 vma 0xba4c
Loading section .rodata, size 0x1c vma 0xba64
Loading section .ARM.exidx, size 0x8 vma 0xba80
Loading section .eh_frame, size 0x4 vma 0xba88
Loading section .init_array, size 0x4 vma 0x1ba8c
Loading section .fini_array, size 0x4 vma 0x1ba90
Loading section .jcr, size 0x4 vma 0x1ba94
Loading section .data, size 0x958 vma 0x1ba98
Start address 0x8120
Transfer rate: 139136 bits in <1 sec.
(gdb) b main
Breakpoint 1 at 0x8260: file hello.c, line 6.

出来た物を動かすのは、runを経由するかgdbのシュミレーションモードを 使うとな。

(gdb) run
Starting program: /home/sakae/hello/a.out

Breakpoint 1, main () at hello.c:6
6               printf("Hello ARM, input pls.\n");
(gdb) s
puts (s=0xbe90 "Hello ARM, input pls.")
    at ../../../.././newlib/libc/stdio/puts.c:138
138     ../../../.././newlib/libc/stdio/puts.c: No such file or directory.
(gdb) s
_puts_r (ptr=0x1, s=0x1ffff8 "\344\276\001")
    at ../../../.././newlib/libc/stdio/puts.c:80
80      in ../../../.././newlib/libc/stdio/puts.c
(gdb) c
Continuing.
Hello ARM, input pls.
Hoge Funga
Hoge Funga
[Inferior 1 (process 42000) exited normally]

残念ながらnewlibのソースが入っていないので、見る事は出来ないけど、 printfがputsに置き換えられているぐらいの事は、見て取れる。 後は、昔買ったハロワ本を開いて見れば良いのでしょうか。

見たら、armのシュミレーション環境の作り方とnewlibについて言及されてた。 シュミレーション環境を作ると、newlibの中まで、gdbで潜って行けるとな。 gccやらgdbやらnewlibなんて言うのをコンパイルしてる。

さぞかしコンパイルに時間がかかるだろうと覚悟してFreeBSDに舞台を移してから取り掛かったら、何と 1時間弱で環境が出来た。

$ du -sh /home/sakae/cross2/
1.1G    /home/sakae/cross2/
$ du -sh /usr/local/cross2/
169M    /usr/local/cross2/

大事なソース類が入っているから絶対消すなが、容量1.1G。バイナリ類は、169Mか。 これだけで、syscallが発せられる所を観察出来るって素敵。

$ PATH=/usr/local/cross2/bin:$PATH
$ arm-elf-gcc -g hello.c
$ arm-elf-run a.out
Hello ARM, input pls.
Good env !
Good env !
$ arm-elf-gdb a.out
GNU gdb (GDB) 7.3.1
  :
This GDB was configured as "--host=i386-unknown-freebsd10.2 --target=arm-elf".
Reading symbols from /usr/home/sakae/hello/a.out...done.
(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section .init, size 0x1c vma 0x8000
  :
Loading section .data, size 0x9d0 vma 0x19b44
Start address 0x8110
Transfer rate: 338080 bits in <1 sec.
(gdb) b main
Breakpoint 1 at 0x8254: file hello.c, line 6.
(gdb) run
Starting program: /usr/home/sakae/hello/a.out

Breakpoint 1, main () at hello.c:6
6               printf("Hello ARM, input pls.\n");
(gdb) s
printf (fmt=0x19b5c "/usr/home/sakae/hello/a.out")
    at ../../../../../../../toolchain/gcc-3.4.6/newlib/libc/stdio/printf.c:48
48        struct _reent *ptr = _REENT;

今度は、ちゃんと潜れる。

hello.s

# hello.s run on gdb sim mode or run cmd.
        .macro invalid
# This is "undefined" but it's not properly decoded yet.
        .word 0x07ffffff
# This is stc which isn't recognized yet.
        stc 0,cr0,[r0]
        .endm

        .global _start
_start:
        nop
        bl skip_output
hello_text:
        .asciz "Hello, world.\n"

        .p2align 2
skip_output:
        movw r4, #:lower16:hello_text
        movt r4, #:upper16:hello_text
output_next:
# Output a character
        mov r0,#3
        mov r1,r4
        swi #0x123456
# Load next character, see if done.
        add r4,r4,#1
        sub r3,r3,r3
        ldrb r5,[r4,r3]
        teq r5,#0
        bne output_next
done:
        mov r0,#0x18
        ldr r1,exit_code
        swi #0x123456

# If that fails, try to die with an invalid insn.
        invalid
exit_code:
        .word 0x20026

etc

感の良い人なら、既にお気付きと思うが、オイラーの駄文は書置きしてる。

今、その原稿を溜めておくリングバッファーがFULLになっており、先行記事が 執筆出来ない状態なんだ。よって、これから暫くの間は、記事のフラッシュを 進めるため、更新頻度を上げる事にします。

記事が底を着いたら、頻度を元に戻す事にします。