ラベル Vagrant の投稿を表示しています。 すべての投稿を表示
ラベル Vagrant の投稿を表示しています。 すべての投稿を表示

2015/05/23

64bit 版 xv6 を gdb で追う

前回 にも xv6 を読もう、ということで Mac に環境を構築したのですが、 swetland さんによる 64bit 版の xv6 があるみたいで、そっちも読めるようにしたログ。


環境
  • Host
    • Mac OSX Yosemite 10.10.3
    • Vagrant 1.7.2
    • VirtualBox 4.3.26
  • Guest
    • Ubuntu 14.04 on vagrant (chef/ubuntu-14.04)
    • qemu 1.7.91
    • gcc 4.8.2
    • gdb-multiarch 7.7


ブートの流れと gdb で素直に追えない理由

64bit 版の boot loader は memory space を 16 -> 32 -> 64 と拡張しながら起動していくみたいです
切り替えの際に命令セットが変わるので、 16bit(i8086) で attach していた gdb で b main して continute しても main で止まらなかったり、アーキテクチャの設定を間違えると gdb が文句を言ったりします。
この問題は swetland さんの xv6 の README.64bit にも書かれていて、
* gdb pukes when qemu switches from 32bit to 64bit mode
  * this made debugging the mode change entertaining
  * for now attach gdb after the switch
とのこと。
要は切り替えると gdb がダメになるので、切り替えた後に attach しなよ、と。
この切り替えポイントと gdb の attach をどうするか格闘したログ


16bit -> 32bit

boot 部分はアセンブラで直書きされているのでその辺りを読む。

out/bootblock.asm にある
ff 53 1c                call   *0x1c(%ebx)
でどうやら 16bit -> 32bit している様子。
なのでこの命令がある 0x7dc1 に break を置く。
ここは起動直後の gdb での continue で止まる。
stepi すると 0x00100020 に飛ぶ。

ちなみに 0x00100020  は mboot_entry ってやつで、ページテーブルの初期化とかしてるみたいです。
これで 32bit になったので 64bit に飛ぶところを探す。


32bit -> 64bit

メモリが32bitになったので 0x1000a4 とかが指定できる。
64bit mode にしてる部分は out/kernel.asm の
# shift to 64bit segment
 ljmp $8,$(entry64low - mboot_header + mboot_load_addr)
のところみたいです。
私の環境のアドレスだと 0x1000a4 。
ここから stepi すると
Remote 'g' packet reply is too long: 000200000000000000000.....
と言われて gdb で操作できなくなる。
直前に set architecture i386:x86-64 とかしてもダメ。
ということで、 16 -> 32 した gdb はそのままで新しい gdb を上げる。
新しい gdb で symbol-file と set arch してから target remote すると gdb を待つ状態になるので、古い gdb で continue してエラーが出てから quit 。
古い gdb は落ちて新しいの 64bit で繋がるので、これで b main とかが効くようになります。


Ubuntu 14.04 に環境を作る

  • sudo apt-get install -y gcc git qemu gdb-multiarch vim zsh
  • git clone https://github.com/swetland/xv6.git xv6-64bit
とか。
Makefile の QEMU を qemu-system-x86_64 にして、64bit build の時は X64 って環境変数を作る。
gdb で debug する時は tool/gdbinit.tmpl の symbol-file kernel を symbol-file/kernel.elf にする。
あとは
  • make 
  • make qemu-nox-gdb
してから gdb-multiarch でいけます。
最初の gdb-multiarch の .gdbinit は
echo + target remote localhost:25900\ntarget remote localhost:25900
echo + symbol-file out/kernel.elf\nsymbol-file out/kernel.elf
break *0x7dc1continuestepibreak *0x1000a4
echo + please attach another gdb.\n
とか。32bit mode での最後の ljmp までは2つめの gdb-multiarch でいけます。
2つ目の gdb-multiarch の .gdbinit は
set architecture i386:x86-64:intel
echo + target remote localhost:25900\ntarget remote localhost:25900
echo + symbol-file out/kernel.elf\nsymbol-file out/kernel.elf

とか。 2つ目を接続してから1つ目を continue すると良い。

xv6 を fork してみる

結局やることは
  • .gdbinit の書き換え
  • 16 -> 32 bit 版 gdb 用 .gdbinit
  • 32 -> 64 bit 版 gdb 用 .gdbinit
  • QEMU の設定
  • X64 を設定
とか沢山あったので、 fork してみました
3つ shell を上げて
  • (1) make
  • (1) make qemu-nox-gdb
  • (2) gdb-multiarch -x .gdbinit64 
    • please attach another gdb と出たら
  • (3) gdb-multiarch -x .gdbinit64-2
  • (2) continue
  • (2) exit
    • すると (3) の gdb が繋がるので
  • (3) b main
  • (3) continue
    • とかができます。
(3) の gdb の attach 時に 'Bogus trace status reply from target: PacketSize=1000' と出る場合もありますが、もう一度  $ gdb-multiarch -x .gdbinit64-2 すると繋がります。

メモリがきちんと64bitになっていればok。
The target architecture is assumed to be i386:x86-64:intel+ target remote localhost:259000x00000000001000e0 in ?? ()+ symbol-file out/kernel.elf(gdb) 
とかですね。
あとは main から読むなりなんなりできます。



コマンドまとめ

vagrant 上の Ubuntu 14.04 にて 3 つ shell を上げます。それぞれが(1), (2), (3) です。

(1) $ sudo apt-get install -y gcc git qemu gdb-multiarch vim zsh
(1) $ git clone https://github.com/atton-/xv6.git xv6-64bit
(1,2,3) $ cd xv6-64bit
(1) $ make
(1) $ make qemu-nox-gdb
(2) $ gdb-multiarch -x .gdbinit64
    please attach と出たら
(3) $ gdb-multiarch -x .gdbinit64-2
(2) $ continue
    して Remote 'g' packet reply is too long: 000200000000000000000.....
    と言われると思うので(2) の gdb を落とす
(3) $ b main
(3) $ continue
    main で止まります。
(3) の attach に失敗したら (3) をもう一度  gdb-multiarch -x .gdbinit64-2  で上げると良いはずです。

2013/10/11

Vagrant で box が add できない

時系列は前後するのですが、 Vagrant 導入時にちょっと引っかかった内容。

Vagrant は ruby base だと聞いていたので導入は
$ gem install vagrant
でやったところ、入るのは 1.0.x 系列らしい。

1.0.x 系列で CentOS の最新版や Fedoraの最新版の box を add しようとすると、ダウンロード終了後の展開時に
Failed to untar the box file. This is usually because you're
attempting to add a box that isn't a valid box file. Please
double check that the box file is properly packaged.
とか言われて落ちる。
VAGRANT_HOME の関係で、ホームディレクトリでやると良い  とか それでもダメだったからバージョン低い box でやった とかいろいろ対策があるみたい。
私は前者はダメで、後者の方のバージョンが低い CentOS の box を指定すれば add できた。

実際何が原因だったかと言えば、 vagrant のバージョンでした。最新だと問題無し。
Vagrant 公式の最新は 1.3.4 で、これは gem からだと入らないみたい。
dmg を落としてきてインストールする必要がある。

インストールした Vagrant は /Applications/Vagrant/bin くらいに command があるけれど /usr/bin に symlink が貼られている様子。
なので、 gem の方をアンインストールして dmg な /usr/bin/vagrant の方を優先するようにすると実行できる vagrant が 1.3.4 に。
1.3.4 だと fodora19 の box も問題無く add できた。
gem の方を uninstall しなくても良いかもしれないけれど、パスの優先度を変えたり追加するのも面倒だったので gem の方を消すことで対処。

とりあえず最新の fedora を box 化するような人が古い Vagrant 使うはずがなかったんやー、みたいなオチで一つ。

Vagrant + Puppet で Fedora 19 に MySQL を入れる

MySQL な環境を構築しよう、ということになったけれど、どうせなので Vagrant でやることに。
と思ったら非常にいろいろハマったのでメモ。

環境

  • OS X Mountain Lion
  • Vagrant 1.3.4

Vagrant のインストール

Vagrant のサイト から最新な 1.3.4 をインストール。
ちなみに /usr/bin/vagrant くらいにシンボリックリンクが貼られるので、 rbenv な vagrant は uninstall した。


Fedora 19 を入れる

Vagrantbox.es から最新な Fedora19 を使うことに。
$ vagrant box add fodora-19 https://dl.dropboxusercontent.com/u/86066173/fedora-19.box
これで box がダウンロードされる。
box は直接起動する訳じゃなくて、
$ vagrant up
した時にコピーされて起動するみたい。
なので
$ vagrant destroy
しても box そのものは消えない。



Puppet で MySQL を入れる

入れようと思ったら大量にハマるなど。
以下に導入ログとトラブルシュートなログ類。

Puppet の Install

$ vagrant plugin install puppet
くらい。 gem からでも入るっぽいけれど、vagrant な例に習って gem の puppet は uninstall した。

Puppet の設定

Vagrantfile に書かれているやつをコメントアウトする。
  config.vm.provision :puppet do |puppet|
    puppet.manifests_path = "manifests"
    puppet.manifest_file  = "mysql.pp"
  end
とか。
mysql.pp とかはマニフェストの名前。何でも良いはず。
ディレクトリ構成は
.
├── Vagrantfile
└── manifests
    └── mysql.pp
みたいな感じになる。
この状態で mysql.pp に設定を書いていく感じ。

 

Puppet の実行

puppet で環境を構築するのは provision すると良いみたい。
up の時に provision も実行するなら
$ vagrant up --provision
しないなら
$ vagrant up --no-provision
1.3 系だと up は初回は provision が走って、次回以降は走らないのがデフォらしい
ちなみに up してる時にも
$ vagrant provision
で provision が実行されて puppet が走る。



エラーログ

ここからエラーログ

IP アドレスが取得できないっぽい

$ vagrant provision
した時に
Running Puppet with mysql.pp...
Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
Could not retrieve ipaddress6: undefined method `scan' for nil:NilClass
Could not retrieve netmask: undefined method `split' for nil:NilClass
Warning: Could not retrieve fact ipaddress
とか怒られる。
IP が見えてないっぽい。
fedora19 には最初から ifconfig とかが入ってないらしいので
$ yum install net-tools
しておく必要があるみたい。
この辺も manifest に書いておくと怒られない。
ちなみにこう怒られたのは yum update の時。

hostname と DNS 周りが変らしい

warning: Could not retrieve fact fqdn
とも言われた。
この辺は hostname が fqdn に対応してない(のかな?)っぽいのと、dnsな設定が変らしい。
どうやら VM の domain が適切に設定できてないとダメらしい。
/etc/resolve.conf に domain な記述が無いといけないらしい
んで、 resolve.conf は vagrant が勝手に設定するらしいので、実行するホストの環境によっては設定されなかったりするっぽい。
generated by NetworkManager とか書かれてたので vagrant 側じゃなくて fedora 側が勝手に作ってるのかもしれないけれど。
無理矢理 /etc/hostname に hostname を書いて、 /etc/resolve.conf に domain を書くと出ない。
ちなみに hostname と dnsdomainname コマンドがおかしい時に出てくるエラーらしい
あと vagrant ssh して
$ factor | grep fqdn
すると、エラーが出る方には fqdn な値が無かったり。
この辺設定できるとエラーは出ないのかもしれない。

そもそも MySQL が Fedora19 に無い

$ yum install mysql
とかがダメで
$ yum intall community-mysql
とからしい
しかも接続してみると MySQL じゃなくて MariaDB とか出てくる。
調べてみると fedora19 から MySQL の default が MariaDB だとか


Vagrantfile と manifests/mysql.pp

書き方はググりながらだったので省略するとして、最終的にできた Vagrantfile と manifest はこんな感じ。
mysql をインストール + 有効化とパッケージのアップデートをしてくれます。
あと hostname の設定。


最終的に

$ vagrant up
$ vagrant provision
で起動と環境構築をしてくれるようになりました。
便利だけれど実行できるようになるまで大分ハマった。
この辺ささっとできると良いのかなーうーん。