cmake sample

cmakeの勉強のようなことをした。
参考にしたページはここここである。特に、後者の記事の最後の表は参考になった。
-I, -o, -L, -lとソースファイルを適切なコマンド・手順で指定すると、実行ファイルなり共有ライブラリなりが出力されるツールだ、と解釈するのが多分平和である。

今回cmakeを試しに使ってみるにあたって作ったsampleはここに上げられている。
全て、cmake .; makeでコンパイルできて、shared_libraryのみ、make installが可能である。

githubのCMakeLists.txtのコメントに、cmake自体の説明はまとめられている。

(1) simple_cmake
最も単純なcmakeのサンプル。

(2) full_executable
実用上利用する、フラグ, -D, -I, -o, -L, -lの指定できるサンプル。

(3) shared_library
共有ライブラリを作成するためのサンプル。

本当はサンプル集を作成するためのCMakeLists.txtも作ってみたかったが、今後の課題とする。

BINARY HACKS #23-#29

registerの参照
以下のようにすることで、stack_pointerとframe_pointer registerを参照できる。

 register void* stack_pointer asm ("%esp");
 register void* frame_pointer asm ("%ebp");

なんでespとebpなのだろう?

インラインアセンブラ

 __asm__ ("アセンブラテンプレート":出力オペランド指定:入力オペランド指定:この操作によって変わってしまうもの);
 __asm__ __volatile__ ("アセンブラテンプレート":出力オペランド指定:入力オペランド指定:この操作によって変わってしまうもの);

出力オペランド指定では、以下のような制約の表記をする。=は
“=&S” (d0)
出力オペランドで指定した変数は、アセンブラテンプレートで順に%0, %1などと参照可能。
また、制約は”0″などと表記できる。
入力オペランド指定では、
“0″ (src)
などとする。これは変数srcに”0″という制約を付ける。”0″は%esiレジスタに割り当てられているので、srcを%esiレジスタに設定するようになっている。
やっていることとしては、

入力オペランドで、C言語の入力される変数をレジスタに割り当て
アセンブラテンプレートを処理する
出力オペランドで、レジスタの値を出力の変数に代入する

操作によって変わってしまうもの、および__volatile__はC言語の最適化回避。

ビルトイン関数
例えば、strlenに文字列リテラルを渡すと、最適化の段階でstrlenを呼ばずに即値に変換してくれる。
このような機能は数学関連、文字列関連の関数でしばしば実装されている。
先頭の0bitを数える__builtin_clz(unsigned int x)などがハッカーに好んで使われると言われているが、何に使うのか皆目わからない。
なお、gccでは以下の1行目は文字列リテラルと同値に扱われない。2行目のようにしなければならない。

const char* str = "hoge";
const char* const str = "hoge";

glibcを使わないプログラミング
libcが大量にリンクされているために、プログラムのコード単純なHello Worldでも5kbを越える。この無駄を排除したい。
これを解決するために、システムコールのみを使うことが解決策としてあげられる。
しかし、C言語のwrite関数などは、アーキテクチャ依存性を排除するための単なるglibcの関数である。
つまり、アーキテクチャに特化したシステムコールを探してこなければならない。
そこで、_syscallNを探しだし、exit, write関数となるべきマクロをコピペする。すると、マクロによって関数を定義することができて、writeコマンドをCPUの命令で実行できる。
これを

 gcc -Os -fno-builtin -fomit-frame-pointer -no-ident -c hello.c
 strip -s hello
 strip -R .data hello #dataセクションはreadelf -S曰く、0バイトだからいらない

TLSの利用
スレッド固有の変数を簡便に利用するためのシステムを使う方法。
TLSはthread local storageといい、グローバル変数に__threadキーワードをつけることで実現できる。
まともな使い道としては、errnoの保持などに利用できる。

pthread_key
TLSはポータブルではなく、gccに特有の機能である。
ポータブルに実装するならば、以下のようにpthreadの機能を用いる。

 pthread_key_t key; 
 pthread_key_create(&key, destructor);

 void* value;
 pthread_thread_setspecific(key, value);
 value = pthread_thread_setspecific(key);

 pthread_key_delete(key);

#27を一回飛ばします。

weekを用いて、リンクされているライブラリによって挙動を変化させる
weekはリンク時にundefinedであればそれを0に設定する、というキーワードである。
つまり、例えばlibmがあるかどうかを判別するためのプログラムを以下のように実装することができる。

extern double sqrt(double x) __attribute__ ((week));

void foo {
    if (sqrt) 
        cout << "found" << endl;
    else 
        cout << "not found" << endl;
}

バージョンスクリプトでライブラリ外に出るシンボルを限定する
別のファイルにあるfooとbarが存在し、fooがbarに依存するが、barはライブラリの外部に漏らしたくない、という状況を考える。
この時、以下のバージョンスクリプトlibfoo.mapと、動的ライブラリ作成のためのリンクで-Wl,–version-script,libfoo.mapオプションをつけることで、外部に公開するシンボルを限定できる。

{
    global: foo;
    local: *;
};

C++の場合は、デマングルするためにextern “C++”が必要であることと、デマングルしたときに引数の違いによって関数名の後に後続する文字列があるので、以下のようにする。

{
    global:
        extern "C++" {
            foo::hoge*;
        };
    local *;
};

gcc拡張のvisualityを用いて関数の公開性を制御する
上のversion scriptによる方法は単に隠しているだけなので、PICでコンパイルするとhiddenな関数もPLTを通り、低速である。
gccでは__attribute__ ((visuality(“default”)))を用いることで、より簡便かつ高速な公開非公開の制御ができる。

 #define EXPORT __attribute__ ((visuality("default")))

このオプションをつけて、さらにコンパイル時に、以下をつけることで、defaultと明示的に指定していないシンボルが全てhiddenになる。

-fvisuality=hidden

(attributeはクラスの後、型名の前に付ける)

Syntax Hightlighter Evolvedサンプル

導入はこちら

自分が利用する範囲のsyntaxをここにまとめておく。
今のところ使いたいものは、c, shell, text。
オプションはfirstline, light。

これ、行表示の状態でコピペすると行番号もコピーされて残念なんだけど、解決する方法はないか。

C言語通常

int main(int argc, char** argv)
{
    printf("Hello World!");
    return 0;
}

C言語行表示

int main(int argc, char** argv)
{
    printf("Hello World!");
    return 0;
}

C言語簡易モード

int main(int argc, char** argv)
{
    printf("Hello World!");
    return 0;
}

shell

echo test > /dev/null
aptitude search `echo libgnu`
cd ~; cd -

テキスト

はむっ

もったいないおばけ屋敷

お酒が飲みたい。特にワインが飲みたい。
ワインの銘柄とかも記録したほうが楽しめるのだろうか。

可能性を捨てた成長が怖い。
MMORPGのクラスアップしかり、アナログからデジタルへの流れしかり、でっちあげ開発しかり、世の中の進化は往々にして可能性を捨てる。
専門以外に興味を持って時間を割き、可能性を捨てることのできない僕は甘ちゃんだ。

一方で、あまりにデジタルになれすぎた僕たちがFPGAの性能に驚愕したこと、あるいはでっちあげ開発の蜜の甘さを知ることは、安易に可能性を捨てすぎないための戒めになるだろう。
極振りは最適解ではない。

雨のプールに行くことになるかもしれない。
すると、女の子の服が透けた様子が楽しめるのか、と思ったが、そもそも水着だった。

BINARY HACKS #20-#22

PICを付ける意味
PICは.rel.dynamicを.textに押し付けるオプションである。
PICをつけなくとも、共有ライブラリを正常に動かすことは可能である。しかし、速度面からPICを付ける必要がある。
PICをつけ{ずに, て}コンパイルしたファイルのELFを見る。TEXTRELはテキストの再配置が必要であること、RELCOUNTは再配置の数を表す。
readelf -d fpic-no-pic.so | egrep ‘TEXTREL|RELCOUNT’
readelf -d fpic-pic.so | egrep ‘TEXTREL|RELCOUNT’
とすると、下ではTEXTRELが見つかり、RELCOUNTが多い。
(テキストの再配置って何?RELCOUNTって何?.rel.dynamicって何?)

statifier
動的リンクが必要な実行ファイルを、必要のない実行ファイルに変換する。
statifiere /usr/bin/php php2
実行してみないと動的リンク先が決められないライブラリを利用している場合は、–set=LD_PRELOAD=”a.so b.so”などとする。
これが必要な状況は、/lib/libnss*.soと、/usr/lib/gconv/*.soである。

gccのGNU拡張
(1) ビルトイン関数
文字列リテラルを出力するだけのprintfはputsに置き換えられるなど。
LD_PRELOADのオーバライドで問題が起きることがあるので、これの状況を知るための関数が用意されている。
(2) アトリビュート
関数やデータの性質を記述し、特別な意味を付加したり、呼び出しの最適化を期待する。
宣言時に
int foo(void) __attribute__((つけたいアトリビュート));
などとする。
(3) ラベルの参照
ラベルを&&をつけることで、関数ポインタとして扱うことが出来る。なお、関数ポインタなので減算加算が可能である。
void *label = &&error;
goto *label;
error:

(これは実際に使ってみないと、何が使えるのかよくわからなそう)

研究室に存在する生活ー1日目

昨日は9:20-20:10に研究室に存在していた。午前中は自分の勉強、午後は研究関連の調べ物を行った。
勉強は良い時間設定だった。夕飯で眠くなって帰ってしまったが、帰らずに粘った方が良かった。

ご飯を早くとか朝から来てとか、そういう雰囲気がなく、皆が随分とのんびりしていて、随分と雑草が放置されている。
僕は研究とは何なのかが分かっていない。組織としての研究室が持つ目標も分からない。

評価に一喜一憂して、不安に駆動されることは果てしなく格好悪い。
漠然とした恐怖に唆されて、頑張って、評価を得たと信じて、浮き沈みを繰り返す。
目をつむって淡々と快楽主義的に生きるのが良い、と割り切ったつもりでも、評価への恐怖は僕を動かすのに寄与するし、評価されれば安心する。

色々思うことはあるが、真似事から始める他ないのだ。

パズドラを始めた。麒麟が出たので、Wキリン25倍パでごり押しが楽しい。

BINARY HACKS #14-#19

c++filtについて
nm cpp.o
とすると、cppの名前マングリングによって、_Z3fooiのような読みづらいシンボルが得られる。
これは、
nm cpp.o | c++filt
nm –demangle cpp.o
によって解決できる。

addr2line(needs -g)
ポインタからソースコードの行を特定するためのコマンド。
addr2line -e ./a.out 0×8048764
-fオプションをつけることで、関数名もわかるようになる。
addr2line -e ./a.out 0×8048764

strip
ユーザのプログラムをstripして、開発者のところにしていないバイナリを残すと、コアファイルをコピーすることで開発環境でデバッグ可能。
strip ./a.out
-dオプションは、だいたい-gによる部分だけを削除する。すると、完全にデバッグできなくなる状況を避けられる。
strip -d ./a.out
.o, .aをstripするとシンボルが全部消えてしまう。

ar
作成(r: 新規挿入既存置換、c: 警告抑止, u: 新規のみ置換, s: ranlib)、閲覧、展開
ar rcus libhoge.a 1.o 2.o 3.o …
ar tv libhoge.a
ar xv libhoge.a

C++からCを呼び出す
一点のみ注意が必要である。Cのheaderで以下のようにすればよい。
#ifdef __cplusplus
extern “C” {
/*Cのコードいっぱい*/
}
#endif
extern “C”をつけると、C++の名前マングルの対象外となる。C++ではリンクが通れば型のミスはないと思われるが、Cでは間違ったプロトタイプ宣言が可能。extern “C”をつけた部分では、型の安全性がCレベルまで低下する。でも、普通に考えたらヘッダファイルが存在するはずなので、CからでもC++からでも使えるプロトタイプ宣言を作っておけば問題ない。
参考: http://hakobe932.hatenablog.com/entry/20090104/1231073299

CからC++を呼び出す
C++コードをg++でコンパイル、Cコードをgccでコンパイル、g++でリンクすることを考える。
4点注意が必要である。(1)(2)は「C++からCを呼び出す」の理由、(3)はCのコードにC++の例外が通るとプログラムが落ちることによる。
(1) C++のheaderをifdef, extern “C”でくくる。
#ifdef __cplusplus
extern “C” {
/*Cのコードいっぱい*/
}
#endif
(2) C++のソースをextern “C”でくくる
extern “C” {
int cpp_func(void) {return 0;}
}
(3) C++のソースが例外を投げるならば、例えば以下のようにする。
extern “C” {
int cpp_func(void) try {throw -1;} catch(…) {return -1}
}
(4) 関数ポインタを引数に取るCの関数は-fexceptionsでコンパイルしなければならない。このオプションをつけると、全ての関数についてフレーム解放処理を挿入する。
なお、glibcのqsort, bsearchなどは、このオプションをつけてコンパイルされている。

警告の出ない名前衝突–C言語
gccでたまに経験する、名前衝突しているのに何故か警告も出ずに、実行時に予想していないほうのシンボルが呼ばれるアレ。
これの原因は
(1) 静的ライブラリを作成する時のarコマンドは、ただのアーカイバなので、シンボル名とか見てない。
(2) 動的リンクのSONAMEとNEEDEDの対応付けも、一番初めに見つかった方を利用している。
逆に、回避可能な条件は以下である。
(1) 動的リンクを利用しておらず
(2) .oを全てまとめてリンクして実行ファイルを作成するとき

警告の出ない名前衝突–C++言語
C++ではもう一つ罠が増える。.oを全てまとめてリンクしていても期待したシンボルが参照されない可能性がある。
原因は、
(3) inlineで定義するweekシンボルがnon-weekシンボルの存在により無視されるから。これは.hの中に定義が入っていたとしたら、それが複数の.cppにincludeされると重複して定義されてしまうため、後で解決してやろうという気持ちによる。
回避方法は、
(3) inlineで定義するシンボルを作らない、もしくは、無名namespaceでリンケージリークを防ぐ。無名namespaceによってmoduleにシンボルを閉じ込めれば、当然モジュール内でしか利用できなくなるが、今回のような大域領域での名前衝突は解決できる。

これからの身の振り方について

NHKロボコンに負けてから、自己肯定感が地を這っている。
それが悪いという訳ではないが、このままでは実害が出かねない。具体的には、たぶん卒業が出来ない。

今まで自分はロボコンにだけ力を注いで、あらゆる意味で失敗した。
注力は怖いが卒業はしたい。

何をやるべきかを考えてみることにした。
ロボコンの時の反省を生かして、以下を実現する生活スタイルを設計したい。

-仕事する
-勉強する
-身体が健康である
-精神が健全である

仕事について。
研究室にコミットしなすぎている。研究室の中に僕の身体が存在する意味は大きい。
欲を言えば、コミットしている感覚を得たい。
帰りは、用事がなければ22:00が妥当だと思う。

勉強について。
単位が5.5単位足りてない。授業で埋まる日が出来てしまう。
僕の性質上、スキル習得を止めることはできないので、修行としての勉強時間が必要だ。
ぐだりたくないので、人に伝えるようにしたい。
僕はマルチタスクに対応していないので、勉強時間に仕事はしない。

健康について。
睡眠時間を確保するべきである。布団の中に入っているコアタイムをを作るだけで改善すると思われる。
病気の放置は負債を肥大化する。皮膚の異常を放っておいたために、今、6~7倍の負債を払わなければならなくなっている。

精神について。
人と食事ができない今の状況は改善したい。会話ができなくなる状況には陥りたくない。

以上を具体化するために、以下を行いたい。

-用事がなければ、8:40-22:00まで研究室にいる
-2:00-7:00を睡眠、12:00-22:00を仕事、それ以外を勉強に割り当てる。
-授業に行く
-数学・英語・情報・回路・環境構築などの中で、これをやるというものを常にただ1つ持っておく
-常にただ1冊、読んでいる本を作る
-適宜、読書・勉強・論文を、ブログにまとめる
-適宜、病院に行く
-午前2時には寝る
-筋トレや薬など、日課を作る
-週1回外出する

上記のことを実現するために、
-本
-勉強
-日課リスト
を管理する必要がある。TwitterのBioとかで。

プール行きたい。
すっぽん食べたい。