qemu-system-arm
armに関する記事を見てたら、 初歩から学ぶ、マイコン開発とARMプロセッサー なんてのに出会った。
クロス開発をやる為に、何の疑問もなく qemu-user-static, gcc-arm-linux-gnueabi を入れて ウブに環境を作ったけど、世は雲の中に環境が 有るのが当たり前なのね。ちっとも知らんかったぞ。
それは兎も角、 mbed OSとは何かなんてトピックがあった。誰かさんが好きなIoTについての動向記事だ。 armみたいな石は、安いんで大量に使うにはうってつけ。更に市場を拡大しましょってんで やっきになっている。そして、お山の大将になりたくて、優位性を示すべく頑張ってる訳ね。
コーヒーサーバーに、石を(無理して)くっつけてみたり。。。何でも有りのインターネットでは 既にその為のプロトコルがRFCになってた。興味が有ったので、RFCを取り寄せてみたぞ。
Network Working Group L. Masinter Request for Comments: 2324 1 April 1998 Category: Informational Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) Increasingly, home and consumer devices are being connected to the Internet. Early networking experiments demonstrated vending devices connected to the Internet for status monitoring [COKE]. One of the first remotely _operated_ machine to be hooked up to the Internet, the Internet Toaster, (controlled via SNMP) was debuted in 1990 [RFC2235].
先例はSNMP上に実装したトースターか。そして、HTTPを拡張してコーヒーポットとの やり取りを提案するとな。
下記はコーヒーポットからのレスポンス。ヘッダーを拡張する形で実装する。
Accept-Additions = "Accept-Additions" ":" #( addition-range [ accept-params ] ) addition-type = ( "*" | milk-type | syrup-type | sweetener-type | spice-type | alcohol-type ) *( ";" parameter ) milk-type = ( "Cream" | "Half-and-half" | "Whole-milk" | "Part-Skim" | "Skim" | "Non-Dairy" ) syrup-type = ( "Vanilla" | "Almond" | "Raspberry" | "Chocolate" ) alcohol-type = ( "Whisky" | "Rum" | "Kahlua" | "Aquavit" )
コーヒーにウィスキーを入れるなんて、初めて聞いたぞ。つらつら見てくと、 ステータスコードも拡張されてた。そう、あの、404 Blog Not Found みたいなやつね。
2.3.2 418 I'm a teapot Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout.
コーヒーポットと思っていたら、ティーポットでございますってステータスも 用意してた。これは、Teaに恨みがあるLisper用だな。
スッチィーが、コーヒーと紅茶のポットを掲げて、機内サービス中。
Tea Coffe? と言いながら回ってます。やがてLisperの所へ来て、Coff? って、尋ねます。
コーヒーを飲みたかった Lisperは、Yesの積もりで思わず、T と回答。
スッチーは、並々と紅茶をカップに注いだとさ。そんなこんなで、TeaとCoffeの区別は しっかりしておかんとな。
コーヒーとアルコールって、世界中にある楽しみ方なんだね。紅茶とブランディーってのは 知ってたけど、コーヒーまで酒ってのは思い至らなかった。
有名なのは、アイリッシュ・コーヒーらしい。アイリッシュ(アイルランド)には、有名な ミスト・ウィスキー(ミルク入りウィスキー、乳白色してる)ってのがあるから、それをたらせば、アイリッシュ・コーヒーの出来上がりか。
一度、やってみたいぞ。って、家にウィスキー無いじゃん。これから熱くなるから、 ハイボールとでも洒落込んで、そのウィスキーを流用すればOK。
ああ、飲み物で思い出した。台湾だかの自販機で売ってる、日本茶。どれもこれも、砂糖入り なのね。あれには、びっくりしたよ。気が向いたらやってみるか。
FreeBSDはどうよ
前回やった、arm用の小さなカーネルもどき、i386なLinuxに移植したら、当然SEGV。それを 回避する方法が見つかった。で、その時にStack領域に実行属性がついてきた事に気がついた。 これって梅雨の季節のかびの温床と言うか、ウィルスの巣にならないかい。OpenBSDのあの人が 怒るだろうね。
本当に怒るかは、環境を作ってやってみればいいだろうけど、面倒なのでBSDのお仲間、FreeBSDでは どうか、調べてみるよ。
clangに--builtinのスイッチが無かったので、それを外してコンパイル。objdumpした 結果が下記。
app.img: file format elf32-i386-freebsd app.img architecture: i386, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x000101c8 Program Header: LOAD off 0x00001000 vaddr 0x00010000 paddr 0x00010000 align 2**12 filesz 0x000001ed memsz 0x000001ed flags r-x LOAD off 0x00002000 vaddr 0x101f1000 paddr 0x101f1000 align 2**12 filesz 0x00000000 memsz 0x00002000 flags rw- STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2 filesz 0x00000000 memsz 0x00000000 flags rwx
うーん、FreeBSDよお前もそうか。で、気を取り直して実行してみると
[sakae@fb10 ~/src/i386]$ ./app.img elf_load_section: truncated ELF file Abort trap
Linuxでは文句も言わずに実行出来ちゃったんだけど、FreeBSDでは、不完全なファイルって 事で、実行を拒否された。お前はウィルスバスターか!
念のために、どこでチェックしてるか見ておく。きっとカーネル内のローダーで、不正ファイルの 判定をしてるに違いない。
[sakae@fb10 ~]$ cd /sys/kern/ [sakae@fb10 /sys/kern]$ fgrep 'elf_load_section' * imgact_elf.c: uprintf("elf_load_section: truncated ELF file\n");
おお、kernel内で使うprintfは自前で用意してるね。前回、生意気にもカーネルファイルって 言ったけど、それの具備する条件に、全部自分の中だけで完結していなければならないってのがある。 すなわち、一般ユーザーが使うライブラリィは使えないって事。ライブラリィにウィルスが 注入でもされていたら、大変な事になりますからね。
あと、ユーザーが使うlibcとかlibmみたいなやつは、ユーザー空間に鎮座する。それをカーネルが 利用するって事になると、空間の切り替えとかで、大きなロスを生む。そんなこんなで、 カーネルに必要なものを、全部カーネル側に用意するんだった。と、頭の整理をしましたよ。
/* * It's necessary to fail if the filsz + offset taken from the * header is greater than the actual file pager object's size. * If we were to allow this, then the vm_map_find() below would * walk right off the end of the file object and into the ether. * * While I'm here, might as well check for something else that * is invalid: filsz cannot be greater than memsz. */ if ((off_t)filsz + offset > imgp->attr->va_size || filsz > memsz) { uprintf("elf_load_section: truncated ELF file\n"); return (ENOEXEC); }
作りが悪いファイルは、怪しいって事でエラーにしてるのね。行け行けドンドンのLinuxとは 違う訳だな。逆に軽いノリのLinuxは、この問題をどう処理してるのがリナス君に聞いて みたいぞ。
qemuを自前でコンパイルしてみる
qemu-system-armを自前で入れて、遊んでみる。遊ぶってのはソース観光の事ね。
[sakae@fedora qemu]$ mkdir build [sakae@fedora qemu]$ cd build [sakae@fedora build]$ ../configure --target-list=arm-softmmu --disable-docs Disabling libtool due to broken toolchain support ERROR: glib-2.22 gthread-2.0 is required to compile QEMU
早速エラーの洗礼を受けた。gthreadをサポートしたglibが必要って事?gthreadって パッケージが有るかと思ったら、そんなの無いし。。。ぐぐる先生に聞いたら、glibの開発パッケージを入れろとな。 上記エラーからそんなの想像出来ないよ。初心者お断りフィルターがかかっているんだな。
[sakae@fedora qemu]$ sudo dnf install glib2-devel
入れてあげた。最初glib-develを入れて、戸惑ったのは秘密だ。で、先に進むとまたもやエラー。 今度は解決策が提示されてたぞ。
ERROR: pixman >= 0.21.8 not present. Your options: (1) Preferred: Install the pixman devel package (any recent distro should have packages as Xorg needs pixman too). (2) Fetch the pixman submodule, using: git submodule update --init pixman
方針2に従って、qemuのtop-dirで、ソースをお取り寄せ。
[sakae@fedora qemu]$ git submodule update --init pixman Submodule 'pixman' (git://anongit.freedesktop.org/pixman) registered for path 'pixman' Cloning into 'pixman'... :
先に進むかと思ったら DTC (libfdt) も必要との事。また、gitのお世話になる。で、やっとこさ config出来たんで、make
[sakae@fedora build]$ make GEN arm-softmmu/config-devices.mak.tmp GEN arm-softmmu/config-devices.mak GEN config-all-devices.mak GEN config-host.h (cd /home/sakae/src/qemu/pixman; autoreconf -v --install) /bin/sh: autoreconf: コマンドが見つかりません Makefile:182: recipe for target '/home/sakae/src/qemu/pixman/configure' failed make: *** [/home/sakae/src/qemu/pixman/configure] Error 127
エラーの嵐、エラー潰しのもぐら叩きが無料で楽しめます。autoconf libtool とかが、効果的でしたよ。
makeする時に、何分かかるか調べたら
: CC arm-softmmu/target-arm/crypto_helper.o GEN trace/generated-helpers.c CC arm-softmmu/trace/generated-helpers.o LINK arm-softmmu/qemu-system-arm CPP optionrom/multiboot.asm AS optionrom/multiboot.o Building optionrom/multiboot.img Building optionrom/multiboot.raw Signing optionrom/multiboot.bin CPP optionrom/linuxboot.asm AS optionrom/linuxboot.o Building optionrom/linuxboot.img Building optionrom/linuxboot.raw Signing optionrom/linuxboot.bin CPP optionrom/kvmvapic.asm AS optionrom/kvmvapic.o Building optionrom/kvmvapic.img Building optionrom/kvmvapic.raw Signing optionrom/kvmvapic.bin real 10m11.719s user 5m27.159s sys 3m47.546s
こんな風に、10分かかってました。以前gdbをコンパイルした時は13分かかっていたから、 まあ、速い方ですな。
一応、出来たのを確認
[sakae@fedora build]$ arm-softmmu/qemu-system-arm -version QEMU emulator version 2.3.50, Copyright (c) 2003-2008 Fabrice Bellard
そして、早速、gdbにかけて見ると言う変態的な態度を取ります。メインは、qemu/vl.c に 有るとな。
折角なので、前回やったカーネルもどきを実行してみると
[sakae@fedora arm]$ make run qemu-system-arm -M versatilepb -nographic -kernel app.img audio: Could not init `oss' audio driver hello, ARM on Fedora 1234 1234 QEMU 2.3.50 monitor - type 'help' for more information (qemu) quit
惜しいな、ちょいと警告が出てきた。もう一度、ossを禁止にしてコンパイルしてみるか。 調べたらossを禁止には出来ないようだ。残念でした。このエラーを消すにはossのドライバーを 入れればいいんだな。(やらないけど)
gdbを使って、どのあたりを回っているか調べようとしたら、fedoraではselinuxとかが 効いていてptraceが禁止になってた。解除する方法が載ってたので試してみたけどだめだったので、 舞台をウブに移してやってみた。(ええ、性懲りもなくウブでもqemuをコンパイルしたのさ。 色々な環境でコンパイルすると経験値が上がるな。fedoraのそれとは違ったエラーを楽しめ ましたよ)
カーネルモードのアプリを動かして、キー入力待ちになった時の、qemuの状態。
(gdb) bt #0 0xb7209be0 in __kernel_vsyscall () #1 0xb6d4a4b2 in __GI_ppoll (fds=0xb9ce7688, nfds=4, timeout=0xbff88cc8, sigmask=0x0) at ../sysdeps/unix/sysv/linux/ppoll.c:56 #2 0xb75020a5 in ppoll (__ss=0x0, __timeout=0xbff88d04, __nfds=4, __fds=0xb9ce7688) at /usr/include/i386-linux-gnu/bits/poll2.h:77 #3 qemu_poll_ns (fds=0xb9ce7688, nfds=4, timeout=1000000000) at /home/sakae/src/qemu/qemu-timer.c:322 #4 0xb7501711 in os_host_main_loop_wait (timeout=1000000000) at /home/sakae/src/qemu/main-loop.c:239 #5 main_loop_wait (nonblocking=0) at /home/sakae/src/qemu/main-loop.c:494 #6 0xb7271247 in main_loop () at /home/sakae/src/qemu/vl.c:1786 #7 main (argc=6, argv=0xbff89004, envp=0xbff89020) at /home/sakae/src/qemu/vl.c:4382
ここでずっと止まったままかと思ったら違った。
(gdb) c Continuing. Program received signal SIGUSR1, User defined signal 1. [Switching to Thread 0xb32eeb40 (LWP 2300)] memory_region_access_valid (mr=0xb9add248, addr=24, size=4, is_write=false) at /home/sakae/src/qemu/memory.c:1074 1074 { (gdb) Continuing. Program received signal SIGUSR1, User defined signal 1. pl011_read (opaque=0xb9add000, offset=24, size=4) at /home/sakae/src/qemu/hw/char/pl011.c:64 64 { (gdb) c Continuing. Program received signal SIGUSR1, User defined signal 1. io_readl (retaddr=<optimized out>, addr=<optimized out>, iotlbentry=<optimized out>, env=0xb9835658) at /home/sakae/src/qemu/softmmu_template.h:156 156 cpu->mem_io_pc = retaddr;
つらつらと、動き回っているよ。qemu/hw/char/pl011.c なんて、前回見た所だな。 ちゃんとポーリングしてる。
(gdb) b /home/sakae/src/qemu/hw/char/pl011.c:64 Breakpoint 1 at 0xb73fec20: file /home/sakae/src/qemu/hw/char/pl011.c, line 64. (gdb) c Continuing. Breakpoint 1, pl011_read (opaque=0xb9add000, offset=24, size=4) at /home/sakae/src/qemu/hw/char/pl011.c:64 64 { (gdb) bt #0 pl011_read (opaque=0xb9add000, offset=24, size=4) at /home/sakae/src/qemu/hw/char/pl011.c:64 #1 0xb72bced5 in memory_region_read_accessor (mr=0xb9add248, addr=24, value=0xb32edcf0, size=4, shift=0, mask=4294967295, attrs=...) at /home/sakae/src/qemu/memory.c:400 #2 0xb72bccfc in access_with_adjusted_size (addr=<optimized out>, value=0xb32edcf0, size=4, access_size_min=1, access_size_max=<optimized out>, access=0xb72bce80 <memory_region_read_accessor>, mr=0xb9add248, attrs=...) at /home/sakae/src/qemu/memory.c:516 #3 0xb72beb21 in memory_region_dispatch_read1 (attrs=..., size=4, pval=0xb32edcf0, addr=24, mr=0xb9add248) at /home/sakae/src/qemu/memory.c:1128 #4 memory_region_dispatch_read (mr=0xb9add248, addr=24, pval=0xb32edcf0, size=4, attrs=...) at /home/sakae/src/qemu/memory.c:1147 #5 0xb72c9c81 in io_readl (retaddr=<optimized out>, addr=<optimized out>, iotlbentry=<optimized out>, env=0xb9835658) at /home/sakae/src/qemu/softmmu_template.h:162 #6 helper_le_ldul_mmu (env=0xb9835658, addr=270471192, oi=33, retaddr=3024027107) at /home/sakae/src/qemu/softmmu_template.h:208 #7 0xb43efe66 in ?? () #8 0x00000080 in ?? () #9 0x0000007f in ?? () #10 0x101f1018 in ?? () #11 0x00000000 in ?? ()
大分道しるべが出来たな。でも、スレッドで動いていて、追い駆けるの大変そう。あちこち 引き回されそうで、恐い。
都会は色々あって、羨ましい。