「Hello World!」の中身を探る意義と環境構築、main(C言語)のアセンブラコードの読み方:main()関数の前には何があるのか(1)(2/4 ページ)
C言語の「Hello World!」プログラムで使われる、printfやmainの中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。初回は、「Hello World!」の中身を探る意義と環境構築について触れ、mainのアセンブラコードを読んでみる。
ハロー・ワールドに触れてみる
まずは、本書で扱うサンプル・プログラムについて説明したい。サンプル・プログラムのソースコードとコンパイル方法、実行時の出力などを簡単になぞっておこうと思う。
また本書ではLinuxのカーネル・ソースコードなど、様々なソフトウェアのソースコードを参照する。
さらにハロー・ワールドに対して、様々な解析を行う。
具体的にはデバッガを用いた動的解析や、実行ファイルの静的解析などを行う。ライブラリのソースコードを参照したり、実行ファイルをバイナリファイルとして直接扱うようなこともある。
そしてこれらの解析のためには、解析用の様々なツール類も必要になる。本書ではそうしたツール利用の環境を気軽に利用できるようにするために、VM(Virtual Machine)によるCentOS 環境のイメージを用意している。
本章では準備として、サンプル・プログラムと参照用の各種ソースコード、さらにVMによるCentOS環境について説明しよう。
ハロー・ワールドのサンプル・プログラム
まずは本書で扱うハロー・ワールドのサンプル・プログラムを説明しよう。リスト1.1がハロー・ワールドのサンプルだ。ファイル名はhello.cとする。
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello World! %d %s\n", argc, argv[0]); return 0; }
本書で主に扱うプログラムは、これだけだ。ただの数行のプログラムなので、覚えることは難しくはないだろう。
なおリスト1.1ではmain()関数の引数としてargcとargvをとり、それをprintf()に渡して出力している。
一般的なハロー・ワールドはそこまでしていないかもしれないが、これは本書では引数の処理等を見たいためにそのようにしている。まあひとまずはそのようなものとして、気にしなくても構わない。
ここで気にしなければならないのは、以下のようなことだ。
- printf()という関数を呼んでいるが、呼び出し先ではどのようなことが行われているのだろうか?
- main()という関数があるが、これはどこから呼ばれて、どこに戻るのだろうか?
- stdio.hというファイルをインクルードしているが、これはいったいどこにある、どのようなファイルなのだろうか?
こうした「素朴な疑問」をとことん探っていくのが、本書の目的になる。
サンプル・プログラムのダウンロードについて
サンプル・プログラムのソースコードや生成済みの実行ファイルなどは、書籍のサポートページからhello.zipというファイルとしてダウンロードできる。
http://kozos.jp/books/helloworld/ hello.zip
本書で扱う実行ファイルはリスト1.1のサンプル・プログラムを後述のCentOS6の環境でコンパイルし生成したものだ。
同等の環境を用意して実行ファイルを新たに生成することは可能だが、実行ファイルを生成しなおした場合、たとえ環境を合わせたとしても、生成される実行ファイルは微妙に異なるものになる可能性がある。ツールやライブラリのバージョンの違いなどが影響する可能性があるためだ。
このため本文中で行っている操作を正確になぞりたいようなときには、自身の環境で生成した実行ファイルではなく、上記サイトのコンパイル済みの実行ファイルを利用してほしい。
なおhello.zipを解凍する際には、以下のディレクトリ上に展開するようにしてほしい。これはGDBによるデバッグ時にソースコードが参照されるため、ソースコードを実行ファイルの生成時のディレクトリに合わせて配置しておいたほうが問題が起きにくいからだ。
/home/user
hello.zipを展開すると12 個のファイルがあり、それぞれ表1.1のような意味を持っている。実行ファイルについては、様々な条件でコンパイルしたものを用意している。
ファイル名 | ファイル種別 | 概要 | |
---|---|---|---|
Makefile | Makefile | 実行ファイルの生成用 | |
hello.c | Cソースコード | サンプル・プログラムのソースコード | |
hello | 実行ファイル | 静的リンクしたもの(主にこれを解析する) | |
hello-normal | 実行ファイル | 共有ライブラリを使った、通常のコンパイル | |
hello-opt | 実行ファイル | -O1で最適化 | |
hello-opt2 | 実行ファイル | -O2で最適化 | |
hello-opts | 実行ファイル | -Osで最適化 | |
hello-nfp | 実行ファイル | フレームポインタを利用しない | |
hello-ndbg | 実行ファイル | デバッグオプションを無効化 | |
hello-strip | 実行ファイル | stripによるサイズ削減 | |
simple.c | Cソースコード | さらにシンプルなハロー・ワールド | |
simple | 実行ファイル | sample.cのコンパイル済み実行ファイル |
各種ソースコードの入手について
本書では以下のソフトウェアのソースコードを参照している。
- Linuxカーネル
- GNU C Library(glibc)
- FreeBSD
- GNU Debugger(GDB)
- Newlib
これらのソースコードはそれぞれの本家の配布サイトからも取得できるが、上述した本書のサポートサイトにも置いてある。またサポートサイトには、本家サイトへのリンクも張ってある。
VMによるCentOS環境の利用について
本書の内容はCentOS 6の32ビット版の環境で確認してある。
よってPC上にCentOSをインストールすれば、本書の内容を確認することは可能だ。また、もちろんUbuntuなどの他のGNU/LinuxディストリビューションやCygwin、FreeBSDなどの環境でも本書の手順に従った操作はできるかとは思う。
しかしツール類のバージョンなどがそろわない場合、細かい手順や結果等が微妙に異なる可能性がある。
実際に確認を行った環境は以下のVMイメージにしてあり、本書のサポートサイトからダウンロードできるようにしてある。
helloworld-CentOS6.ova
よって、やはり本書の内容を正確になぞりたいようなときには、上記のVMイメージを利用するのがいいだろう。解析だけならばそれほどの違いは無いかもしれないが、実行ファイルを生成する場合には、環境によって大きな差異が発生する。
なお上記VMイメージを利用する場合、yum updateするかどうかは悩ましい問題だ。ライブラリ類が更新されると実行ファイル生成時のアドレス配置などが変わってくる可能性は十分にある。インターネットに接続しない環境でセキュリティ的な安全性が確保されるならば、yum updateをしないで使うことも考えられる。このあたりは自己責任で判断してほしい。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- プログラミング言語Cについて知ろう
プログラミング言語の基本となる「C」。正しい文法や作法を身に付けよう。Cには確かに学ぶだけの価値がある(編集部) - シェルコード解析に必携の「5つ道具」
コンピュータウイルスの解析などに欠かせないリバースエンジニアリング技術ですが、何だか難しそうだな、という印象を抱いている人も多いのではないでしょうか。この連載では、「シェルコード」を例に、実践形式でその基礎を紹介していきます。(編集部) - 【 od 】コマンド――ファイルを8進数や16進数でダンプする
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、「od」コマンドです。