********************************************************************** セッションS5-c 分科会3 テーマ:分解 The ハマナ4 コーディネータ:二上 貴夫 氏(東陽テクニカ/SESSAME/東海大学) 日時:2007/8/31 15:10〜17:00 参加人数:54名(終了時) ********************************************************************** 司会:ハマナ4のソースコードを見て,議論をする.ハマナ4は,ハマナプロジェクトが 始まって今年で4年目を迎える.ハマナ1のときは東海大学の人がソースコードを書い ていた.ハマナ1では,ロケットは飛んでいったはいいが,データは半分程度しか取る ことができなかった.それからハマナ2,3,4と進んでいった.ハマナ2からの3年間は いずれもヴィッツがソースコードを書き,実機を製作し,打ち上げを行ってきた.ハ マナ4は3年間のヴィッツの新人教育の集大成といえる. このセッションでは,リアルタイムOSの議論をしたい. また,このセッションでは,リバースエンジニアリングについて考えたい.おそらく, 現在,リバースエンジニアリングを取り入れている会社は存在しない.たぶん,リバ ースエンジニアリングは日本の工学になっていくと思う.たとえば,○○などがある. この分野はそういう意味で確立しているといえる.しかし,日本のソフトウェア工学 においては,まだ,ない.こういった技術(技術とはいえないかもしれないが)は, 一種の逆転の発想であり,今後,伸ばせると思う.このセッションでは,リバースエン ジニアリングの有効性についてみていきたい. ヴィッツの新人の書いたソースコードを材料にしながら議論したい. できあがったものでデータが取れたかどうかも大事だが,ソースコードの品質がどう であるかも大事.プログラムはどうしても篭りがちになる.篭っていても,成長しな い.そこから,抜け出して,みんなでソースコードを見て議論することで新人の成長 につながる. 今回は,ソースコードの解析をビースラッシュ株式会社の2人に任せた. 対象とするプログラムは,ハマナ4の分速5kmチームを扱う.このプログラムを書いた ふたりの成果報告でもある.新人の作ったプログラムがどうであるのか.R&B. - プリント配布 - (人数が多くて40部しかないので,シェアを) A:SESSAMEの方で構造化モデリングをポスター発表でした.その関係で,今回は,司会 の方よりリバースエンジニアリングもできるのではないかといわれ,今回,リバース エンジニアリングをした結果を発表することになった. ハマナ4の分速5kmチームのプログラムをもとにして,ソースコードリバース解析を行 った.プログラムにはいろいろなモードがあるが,今回対象とするのは,ロケットを 打ち上げている箇所を扱った. B:ハマナ4のソースコードをリバースエンジニアリングして解析を行った.まず,リバ ースエンジニアリングについて説明する.リバースエンジニアリングは,複数人で開 発しているときにソースしかないと分かりにくいため,ソースよりも抽象度の高いも のがあった方が分かりやすいということで,現状を可視化している.今回の解析には, リバースエンジニアリングのツールとして,Imagix4Dを用いた.可視化の手段として は,構造図を用いた.構造図は,モジュールの呼び出し関係や情報のやりとりを表現 した図です.モジュールは,ソフトウェアの分割された単位で,関数やマクロに対応 する.モジュールの呼び出し関係は,矢印を用いて表現する. 1つの関数から外の関数コールを,リバースエンジニアリングしてできた構造図に対 して整理しやすくする. たとえば,スイッチをハードウェア的に操作することを考える.リバースエンジニア リングすることで整理し分析しやすくなる. ビースラッシュではその前にプロファイリングを行う.あまりにもソースコードが大 きいと,大きい関数に注目してやる. つまり,特異点がないかを最初に探す. 今回はソースコードがあまり大きくないこともあり,そのまま次の段階に進む. もう1つの準備段階として,タスクの数を把握して,タスクの関係を見てみる. 各タスクで構造図を作成し,各タスクがどうなっているかを調査した. 司会:タスクを分けるのはすごく大事だと思う.自分たちでタスク分割を行ったのか? (ヴィッツ新人に対しての質問) C:分割しないと動けないとこは複数のタスクにするしかないし,というふうにタスク を分割していった. 司会:では,自分たちでタスク分割をやったということですね.ふつうは違う人がやり ますよね?普通は誰がやるの? (観衆に対して) D:普通はソフトをデザインする人がやる.今回は自分がハマナ委員長なので手を出す のをやめ,すべて任せていた. 司会:新人にできると思っている?タスク分割は難しく,新人がやるものではないと 思う.というか,普通はやらないし,できないと思う. いかにしてなされたか本当に謎だと思う.リアルタイムOSを学んで2ヶ月の人が作っ ているが,2ヶ月でできるものではない. E:タスク分割をする上でなんらかのヒントはあったのか? C:新人研修の集中講義という形で先輩から聞いた.例として,周期ハンドラを使って LEDを光らせるといった単純なものを作ったりした.それを参考にしてタスク分割を 行った. 司会:それで答えになっている.つまり新人教育でヒントが与えられていた. D:リアルタイムOSの講義は,90分講義2コマだけです. 司会:びっくり!たったそれだけだったとは. ビースラッシュの方を続きをどうぞ. B:今回の場合には,8つのタスクがある. (各タスクの役割を簡単に説明) mode_task,pre_task,call_task,memory_task,measure_task,pc_task,flush_task ,check_taskがある. mode_taskは,起動時にモードを選択するタスク,pre_taskは,準備用タスク,call_ taskは,周期ハンドラ開始タスク,memory_taskは計測データ記録タスク,measure_task は,加速度・角速度データ計測タスク,pc_taskは,データをPCへ転送するタスク, flush_taskは,EEPROMに保存したデータを,PC転送後消去するタスク,check_taskは, 各デバイスの動作確認をするタスク. まず,静的な解析を行った.mode_taskを見てみた. このタスクに対して,アーキテクチャテンプレートを当てはめてみた.アーキテクチャ テンプレートは,論理,入力,処理,出力,処理の5つのエリアがある. E:字で書いてあるのは関数名? B:はい.手元の資料を見てみてください. このタスクでは,物理的な層を切り離せてていい. E:理由は? B:物理層はアドレスを直接扱うので離れていたほうが,やりやすい. また,保守性もあがる F:マクロじゃダメ? E:レイヤーをきれいに分けたいのは分かる.が,分けたことで必ずしもよくなるとは限 らない.個人のセンスがどうしても影響する.保守性が上がるのか? また,今のレイヤーの分け方で本当に足りているのか? A:論理層,中間層,物理層をまず見る. ソースコードは別問題. E:3層で十分だというものではない? A:そうではない. 今は,minimum3層で分けている.だいたいC言語で書かれているものは2層は必要だと 思う.また,タスクがからんでくると3層は必要かなぁと思う. まずは,3層に分けたほうがいいのではということ. B:次にmemory_taskについてみる. 次にファイルを見ていく. 関数の後ろ側から線が出ている場合,呼んでいる.前に線が出ている場合,呼ばれて いる.今回,ファイル間で循環しているところはなく,階層でファイルが別れていて, 特に問題はないと思う. 次に,ファイルのinclude関係についてみてみる. sfrh80369.hというハードウェア絡みのヘッダファイルが,アプリケーション層(最 上位層)からincludeされていることが分かった.application.cは,最上位であるに も関わらず,ハードウェアを直接触っている関数が入っており,構造図におけるレイ ヤを越えた呼び出し関係として確認できる.ここは,切り離したほうがいい.整理し た方がいいと思う.また,.cファイルと.hファイルの両方からincludeしているところ も見つかった.これらは,includeするのはどちから一方にして関連を減らしておくべ き. C:それは書いた後で私も気づいてました. E:なんで切り離したほうがいい? B:変更が上のほうに影響を及ばしてしまうからです. C:(DIPスイッチの話) E:非常にやりたくない これは,C言語の限界だと思う. ある範囲だけに有効にしたいとかできない. defineだと全部その値になってしまう.この範囲はこのdefine値でといったことができ ない.可視性の局所化ができない. どちらが損害が大きいということはできない. ケースバイケース. ・・・ B:SFRのincludeを入れるかどうか. ハードウェアをレジスタでメインでいじらないといけなくなると どういうふうに呼び出しているか 今回の場合は, DIPスイッチをあえて下位層で書くかどうかは・・・ 入れた部分は問題にしてもいい アドホックにしちゃって includeファイルのリバースエンジニアリングは大事 ケースバイケースでいろいろやる 関数の呼び出し関係はいいが, 物理層のファイルが,上位層のヘッダファイルをincludeしている. 下位層から上位層への矢印と上位層から下位層への矢印の両方向の矢印がある. G:それはどこの場所? B:ADコンバータの入出力を扱っている箇所です. 依存の方向が一方向でないのはいやらしい. ただ,関数単位で見るとOK.あくまで層で見ると両方向の矢印がある. ・・・ H:そのincludeの1行を消してしまえば? 1行残しておく意味はあるのか? I:includeを残しておく弊害は? J:1行残すことにより,そのincludeファイルが使えると思って,そのほかも使ってし まう恐れはある.特にそのソースファイルを別の誰かが修正するときに. 万が一,追加するときにスパゲティになる. 司会:他のプロジェクトで物理層だけ使おうと思ってこの物理層だけを持っていくと, コンパイルが通らない E:物理層だけを持っていけばいいというのは幻想では? ・・・ 次へ行きます B:タスク間で共有される変数についてです. 構造図にした後,平行に動くタスク 動的に解析すると 時間軸をあわせてみたときに大丈夫なのか E:資料ではどこにあたりますか? B:資料では動的な視点の箇所です. すいません.このスライドについては資料にありません. 次はリアルタイム性についてです. どこからも使われないドライバがある. 使われていない関数がある. これは問題です. アプリから呼ばれていない. C:動作が不安定なので,使うのは控えた. ポーリングは悪い. ポーリングだけじゃないとダメなケースもある. OSの機能を使わないといけない. E:細かいことを言い出したらきりがない.たとえば,まず関数名がダメ.関数名を見 ただけでは何の関数なのか分からない. とりあえず,それはいいとして,ADコンバータはマイコンのもの? C:いいえ.今回のADコンバータは外付けのものです. ADコンバータで,タイムアウトがないことが問題. 対応がないソフトは問題です. ハードウェアが壊れたときの対応がないのが問題. 用途がよく分からないのが問題. 非常に危ないと思う. 警告を出すことが大事. 直すかどうかは別問題. J:補足します.タイムアウトについてはもちろん知っていたがあえて教えていなかっ た.今回の開発の範囲ではないと判断した. B:ep2_state その1についてみてみる. リストされたグローバルデータのうち,ep2_stateが複数のタスクから共有されてい る.このデータをアクセスするモジュールの詳細について追跡した. この変数危なくないのか調査してみた. 3つのタスクからドライバが呼ばれている ep2_stateデータ自体のアクセス自体には問題がなかった. ただし,副産物として,ep2_state_openとep2_state_closeが対になっていないこと が判明した.これは,ドライバ側の事情が変わるとメモリリークが発生する可能性が ある.呼び出し箇所は再検討したほうがいい. タスクの凝集度についてみてみる. ad2,ep2がこれに該当する. 例外処理をうまく扱う必要ありだと思う. 特にタスク例外処理について. 初期化前にコールタスクを起動する場合があるので危険. 2つのタスクを見ただけでも 関数メトリクスをみていく. 関数の行数が60以上あるものを示した. それほど大きな関数はなく,全体としてモジュール化されているといえる. B:結論としては, 静的視点でいうと,きれいに切れててよい. 動的視点でいうと,タスク間の共有に直接問題はないように思う. ただ,タイミングについては不安の残るつくりになっている. E:タスクの分け方がきにいらない.タスクは同時に起こるかもしれないという意味なのに 今回のタスクは,同時には起動されることがないものがある.モードごとに呼ぶタスク を変えている.が,1つのタスクにしてもいいのではと思う. イベントのタイミングでみる. タスクを分けて,優先度を決めて 今回は,優先度を気にしていない. つくりやすさの観点から見てみると タスクユニット,図に書きやすい. 機能的に分けているかも 教育的に分けているかも K:ツールの機能についての質問がある. タスクと関数がマトリックス上になるような場合にはうまくいかないのでは? 議論するところに 意味づけとかは別途必要. 人間が設計して残しておかないといけないなぁ. 形式的に能書き的にやる. これだけではない. 午前中の話では,ロギングデータが取れなかった問題がある. 徹夜部屋で話していた. メモリの中身がぐちゃぐちゃになっていた. 理由は結局,昨日の時点では分からなかった. 司会:それは別問題.リバースエンジニアリングしてどうやって問題解決するかが今回 の議題です. メモリがぐちゃぐちゃになっている.何を調べていいのか困っている. L:読み出し自体が正しいか? B:開始アドレスは正しいと思う. 読んでるアドレスはあってる. C:何かしら値は入っている.ただし,0ではない. センサが動作していないわけでもない. 一定の値になっている. もともとそういう値が入っているわけではない. C:初期化で0にしている. O:基板を変えてみてはどうか?ハードウェアは壊れてない?そもそもハードウェアの不良? 正常データのサンプル無い? 正常データを流してみてちゃんと行くのかどうか. C:ペイロード基板をもともと2つ作る予定だったが,1つしかできてない. 2つ目は実装を会社で待っている状態.今度,やってみるつもり. (データを見る) B:後半でぐちゃぐちゃのとこは,ffで一定値. 角速度の値が途中から変なとこに現れている. M:じゃぁ,角速度の値はずっと取れてる?? N:ジャイロは端子がオープンになっている. もともと0かffがはいる. O:得られたデータをもとに議論. 司会:データから何が分かるか. どういうデータがあれば原因を絞り込めるか? 一種のリバース 書き込み位置が違ったのか読み込み位置が違ったのか?? カラムがずれてる. なんでポインタ位置がずれてるかが問題. P:全部のバイトへの読み書きテストは行ったか? B:全部のバイトへの読み書きのテストは行っていない. タスクスタックが壊れることはない. B:昨日,実行テストを行った. Q:毎回,同じ場所でデータが壊れるのか?毎回,ばけはじめのところが違うのか? 後者の場合は他のタスクが影響していると思う. 司会:つまり再現性がどうなのか? C:同じ箇所で壊れているっぽい.常にここ.再現性あり.パターン化されている. E:1分間時間もらってもいいですか?昨日の分科会で入力が4つあって,出力が4つある. 中身はさてどうなっているのかといったものをやった. S:発射前にテストは行った?打ち上げる前は正常に動いていた? C:テストしていない.実は完成したのは,打ち上げの朝にペイロードができた. いきなり打ち上げた. 司会:アメリカでアポロ11号が1回目に打ち上げられ,12号が2回目に打ち上げられた. アポロ12号の打ち上げのとき,フロリダの空は雷雲だった.ただ,アポロ計画は, 人気があった.なので悪天候にも関わらず,打ち上げた.アポロ12号は,打ち上げ 後,雷雲がアポロ12号にあたった.しかし,それにも関わらず,月に着いた.人類 初めて.そして彼らは英雄になった. 実は,アポロ12号は雷雲に当たったとき,停電になっていた.アポロ12号は,実は 停電テストを行っていなかった.しかし,奇跡的にうまくいった. 今回は,時間のため打ち切ります. 結論としては,リバースエンジニアリングはものの作り方をよくする.