2013-01-01から1年間の記事一覧
文字列リテラルのシンボル解決について見ていきます。 1 #include <stdio.h> 2 3 const char *dummy_string; 4 const char *string; 5 6 int main() 7 { 8 dummy_string = "123456"; 9 string = "ABCDEF"; 10 11 printf("string = %p\n", string); 12 13 return 0; 14</stdio.h>…
今回は、関数の呼び出し部分の実行コードについて、リンク前とリンク後で比較してみます。 d: e8 f3 ff ff ff call 5 80483c1: e8 f3 ff ff ff call 80483b9 ありゃ、該当のコード「e8 f3 ff ff ff」には、まったく変化なしですね。局所変数の場合、オブジェ…
変数の論理アドレスが実行コード中に埋め込まれる場所は、以下の.rel.text(再配置テーブル)で管理されます。 Relocation section '.rel.text' at offset 0x410 contains 2 entries: Offset Info Type Sym.Value Sym. Name 00000005 00000401 R_386_32 0000…
以下は、あるオブジェクトファイルの機械語コードのダンプです。 $ gcc -c sample.c -Wall $ objdump -d sample.o -M intel (略) 00000000 <main>: 0: 55 push ebp 1: 89 e5 mov ebp,esp 3: 8b 15 04 00 00 00 mov edx,DWORD PTR ds:0x4 9: a1 08 00 00 00 mov e</main>…
自己参照構造体のエイリアスを定義するとき、構造体のタグ名とエイリアスを重複させないように、エイリアスの先頭に「_」(アンダースコア)をつけたものをタグ名とする定義を見かけますが・・・ /* ×悪い例 */ typedef struct _NODE{ int node_id; struct _…
システムリソースの上限を設定する。すべての情報を表示する。 $ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7826 max locked memo…
前回見たように、.dynstrセクションは、.dynsymセクションヘッダのsh_nameが参照する文字列(シンボル名)を格納しています。 # # .dynstr セクションヘッダ # $ od -x -A x -j0x123c -N0x28 sample 00123c 0056 0000 0003 0000 0002 0000 820c 0804 00124c …
セクションヘッダおよびセクションの内容をダンプしてみます。 # # .dynsym # # セクションヘッダ $ od -x -A x -j0x1214 -N0x28 sample 001214 004e 0000 000b 0000 0002 0000 81cc 0804 001224 01cc 0000 0040 0000 0006 0000 0001 0000 001234 0004 0000 …
セクションヘッダの内容をダンプしてみます。 # # .gnu.hash # # セクションヘッダ $ od -x -A x -j0x11ec -N0x28 sample 0011ec 0044 0000 fff6 6fff 0002 0000 81ac 0804 0011fc 01ac 0000 0020 0000 0005 0000 0000 0000 00120c 0004 0000 0004 0000 0012…
「.note.*」セクションは、「注釈セクション」というものらしいです。「ORACLE Documentation リンカーとライブラリ 第7章オブジェクトファイル 注釈セクション」 http://docs.oracle.com/cd/E19620-01/805-5821/6j5ga47bq/index.html#chapter6-18048オブジ…
徹夜でやってて、たまに寝落ちが入ってきたので、そろそろ投げやりモードですが(笑)セクションヘッダのダンプ。 $ od -x -A x -w16 -j0x119c -N0x28 sample 00119c 0023 0000 0007 0000 0002 0000 8168 0804 0011ac 0168 0000 0020 0000 0000 0000 0000 00…
ELF形式について、徹底的に調べ尽くしてみます。ELFヘッダの構造体の定義は、「/usr/include/elf.h」に、データ型の定義は「/usr/include/stdint.h」でそれぞれ定義されています。 /* /usr/include/elf.h */ 26 /* Standard ELF types. */ 27 28 #include <stdint.h> 2</stdint.h>…
前回は、.shstrtabセクションからセクション名を抽出し、セクションヘッダ一覧に代入しました。 オフセット 内容 サイズ 管理セクション名 0x0000114c セクションヘッダ0 28h(40d)バイト "\0" 0x00001174 セクションヘッダ1 28h(40d)バイト ".interp" 0x0000…
今回、セクションヘッダが30個あるという情報を、ELF形式ファイルの先頭から48(0x30)バイト目の位置にある2バイトの情報(e_shnum)から取得しましたが、これはつまり、セクション実体が30個あるということでもあります。セクションヘッダとは、それに対応…
今回は、以下のソースコードをコンパイルして、そのバイナリを解析します。 /* sample.c */ 1 #include <stdio.h> 2 3 int main(void) 4 { 5 return 0; 6 } まずコンパイル。 $ gcc sample.c -o sample -Wallodコマンドで、実行ファイルの先頭にあるELFヘッダ(52バイ</stdio.h>…
関数の内容を動的に書き換えることをやってみます。 サンプルソースは、「リンカ・ローダ実践開発テクニック」(p139)より。 /* overwrite.c */ 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 int value; 6 char buffer[100]; 7 8 void func1() { value += 1; }</stdlib.h></string.h></stdio.h>…
前回は、関数の動的書き換えを行うプログラムを実行したところ、書き込み禁止領域に対して書き込もうとするため保護違反が発生し、プログラムはSIG_SEGVで終了しました。そこで、func1()が.textセクションではなく、.dataセクションに配置されるように、リン…
・『C言語ポインタ完全制覇 (標準プログラマーズライブラリ)』(前橋 和弥/技術評論社)「ポインタでつまづく」ほどの初心者段階は卒業しており、ポインタ配列、配列へのポインタ、多次元配列は「C言語ユーザー」として一応使えてはいるが、この記述がコン…
char、unsigned charの表現可能な数値の範囲は、 -128 0 127 255 CHAR +++++++++++------------- UCHAR -------------+++++++++++++charの0〜127がunsigned charの0〜127とビット列を共有しているのは当然ですが、 charの-128〜-1は、unsigned charの128〜25…
前回までで、メモリ上のデータの参照/代入に必要な情報は、「位置」「長さ」「解釈の仕方」だ、と書きましたが、逆に言うと、その3つさえ分かれば、何でもできてしまいます。それがC言語の恐ろしいところですが…以下は、アドレス0x804A024に位置する1バイト…
今回は、変数の残りのキモである「データの長さ」「データを正しく解釈する方法」についてです。データの長さ前回は、メモリ上の特定領域にアクセスするための「位置情報」(アドレス)について書きました。この位置情報を使って、特定領域にアクセスすると…
今まで、さんざんポインタと配列をいじり倒しながら試行錯誤してきましたが、そろそろ「そもそも変数とは何か?」という本質論について考える時が来たようです。プログラミングの入門書によくある説明で、変数とは「番号のついた箱」と言われます。データ格…
前回の擬似argv実装を、いい感じにリライトしてみた(つもり)です。 マジックナンバーがかっこ悪いですが、動的配列の機能はC99からなので使用禁止。使用する変数は、以下の通り。 変数 役割 char string 文字列の実体を格納する領域 char *arg_plist[] 各…
main()の引数である、「char **argv」の擬似変数「char **argv2」を実装してみます。 引数文字列の実体をスタックの連続領域に作成し、 各文字列の位置情報を管理するポインタ配列を作成し、 ポインタ配列の位置情報をargv2に格納する という流れでやってい…
式の展開規則実際のコーディングでは、扱う配列はたかだか二次元配列までがほとんどなので、一次元・二次元配列の展開手順は反復練習で身体で覚えてしまって、それ以上の多次元配列になれば、以下の展開規則を再帰的に当てはめて展開していけばいいかと思い…
今まで見てきたように、間接演算子*の作用は、以下のようにまとめられると思います。char型配列の配列arrが以下のようにあるとき、 +------+------+------+------+------+ arr | arr0 | arr1 | arr2 | … | arrN | +------+------+------+------+------+式中…
式中において、ポインタに間接演算子*をつけると、参照先の値に展開される…というのは当たり前ですが、int型変数へのポインタに*をつけると、int型の値に展開される。 char型変数へのポインタに*をつけると、char型の値に展開される。 ポインタ型変数へのポ…
C言語中級者にとっての鬼門と言っても過言ではない、配列とポインタ絡みのところが、いつまで立ってもモヤモヤして気持ち悪い!ので、何回かに分けて、基礎からまとめてみたいと思います。宣言と初期化char型配列の宣言時の初期化子には、以下例のように文字…
以下について、sizeofでサイズを調べてみます。 文字リテラル 空文字 文字列リテラル char型配列 int型配列 int型二次元配列 int型二次元配列の最上位次元の先頭要素の間接参照 int型二次元配列の間接参照 char型配列の集合を管理するポインタ配列 char型配…
間接演算子*と、constが混在した場合の変数宣言について、まとめてみました。 # syntax constの修飾対象 1 const chat *p ポインタの参照先オブジェクト 2 char * const p ポインタ変数そのもの 3 const char * const p 1かつ2 ちなみに、以下のような記述も…