November 2013

Mac風の2本指スクロールに慣れてしまったので、このへんみながら、Windowsでも同様のことができるようにした

Windowsタッチパッドが見違えるほど使いやすくなる「TwoFingerScroll」 http://www.lifehacker.jp/2012/09/120925twofingerscroll.html

どうも TwoFingerScrollは本家の更新が止まっており、派生版を使う必要があるようだ。
派生版は以下

http://forum.tabletpcreview.com/hp-touchsmart-tm2-wacom/38405-twofingerscroll-v1-0-7-update-two-finger-scrolling-done-right-more.html

http://www.mediafire.com/?g65i8ivgq6aaesx
このエントリーをはてなブックマークに追加

忘れないうちにメモ
Linuxで普通に実行ファイルつくると.commentセクションとデバッグインフォメーションの
二箇所にコンパイラのバージョンが入ってる。これはobjdumpやreadelfで観測できる。

なぜこんなテクニックを知る必要があるかというとバグ報告で嘘のコンパイラバージョンを
報告してくる輩はけしてレアではないからである

1つめ。.comment セクションを objdumpで表示

% objdump -s -j .comment a.out

a.out: file format elf64-x86-64

Contents of section .comment:
0000 4743433a 2028474e 55292034 2e342e36 GCC: (GNU) 4.4.6
0010 20323031 32303330 35202852 65642048 20120305 (Red H
0020 61742034 2e342e36 2d342900 4743433a at 4.4.6-4).GCC:
0030 2028474e 55292034 2e342e37 20323031 (GNU) 4.4.7 201
0040 32303331 33202852 65642048 61742034 20313 (Red Hat 4
0050 2e342e37 2d332900 .4.7-3).


これはCentOS 6.4 でコンパイルした、ただの Hello World プログラム。
なんでバージョンが複数出てくるかというと、一般に実行ファイルには
コンパイル時にいくつかのcrtファイルが静的リンクされるのだが、
それらは、OSのマイナー版アップ時にgccバージョンが上がった時に、
リコンパイルされないことが多いので、a.outとずれちゃうんだね。

一般に一番新しいバージョンが a.out のコンパイルに使われたもので
それ以外はリンクされてるcrtをコンパイルしたときのもの。


つぎ、readelfでdebug info読んだもの。こっちのほうがストレートに
a.outの情報だけが出てきて便利。ただし、デバッグ情報必要なので
使えない時はつかえない。

% readelf -wi a.out | grep -i producer
< c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.4.7 20120313 (Red Hat 4.4.7-3)




ところで、gccがどうやって .commentセクションに書き込んでいるか調べたのだが、これが結構面白い
gcc -s hello.c すると、以下の様なアセンブリソースが現れる。



.file "hello.c"
.section .rodata
.LC0:
.string "hello"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits


ここで、 .identという pseudo assembler directiveを使っていることがわかった。
マニュアルを見ると

http://www.sourceware.org/binutils/docs-2.12/as.info/Ident.html#Ident

.ident

This directive is used by some assemblers to place tags in object files. as simply accepts the directive for source-file compatibility with such assemblers, but does not actually emit anything for it.



なんて書いてあるが、なに、うそっぱちである。信じてはいけない。
ためしに、ここに Gachapin here!! とか書くと


% objdump -s -j .comment a.out        

a.out: file format elf64-x86-64

Contents of section .comment:
0000 4743433a 2028474e 55292034 2e342e36 GCC: (GNU) 4.4.6
0010 20323031 32303330 35202852 65642048 20120305 (Red H
0020 61742034 2e342e36 2d342900 4743433a at 4.4.6-4).GCC:
0030 2028474e 55292034 2e342e37 20323031 (GNU) 4.4.7 201
0040 32303331 33202852 65642048 61742034 20313 (Red Hat 4
0050 2e342e37 2d332900 47616368 6170696e .4.7-3).Gachapin
0060 20686572 65212100 here!!.


のように、.commentセクションに文字列が増えたことが確認できる。
(gcc 4.4.7 の文字列が消えないのは 4.4.7でコンパイルされてるcrtも含んでいるため)

なお、リンクされてる crt一覧をとりたいときは以下のようにする

gcc hello.c -Wl,-t
/opt/rh/devtoolset-2/root/usr/libexec/gcc/x86_64-redhat-linux/4.8.0/ld:
mode elf_x86_64
/usr/lib/../lib64/crt1.o
/usr/lib/../lib64/crti.o
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.0/crtbegin.o
/tmp/ccfPagMG.o
/lib64/libgcc_s.so.1
/lib64/libc.so.6
(/usr/lib64/libc_nonshared.a)elf-init.oS
/lib64/ld-linux-x86-64.so.2
/lib64/libgcc_s.so.1
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.0/crtend.o
/usr/lib/../lib64/crtn.o


備忘録なので特に結論はない
このエントリーをはてなブックマークに追加

Linuxでは ioctlは

/usr/include/sys/ioctl.h:
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

というプロトタイプになっているんだけど、なぜか manでは

int ioctl(int d, int request, ...);

と書いてあり、一致していないという問題があった。
実装がBSD互換で、manがOpenGroupのSUS準拠だったわけだね。

わたしがmanの問題だとおもって2012年1月にmanにチケットきったんだけどほうちされてて、

https://bugzilla.kernel.org/show_bug.cgi?id=42705

2012年7月にはLinusが glibcの実装の方を直すべきと主張して、glibcのほうにチケットを発行、

http://sourceware.org/bugzilla/show_bug.cgi?id=14362

どうなるのかやきもきしていたが、Michael 的にはmanは実装と一致すべきと思ったのだろう、
manを変更したとの連絡がとどいた。

これで使用法誤解がへるといいな。

以下、技術的および歴史的な状況の解説

・当初、ioctlはPOSIXに含まれていなかったのでBSD系は引数がunsigned long, SYSV系がintと分裂してた。
・glibcは、すごく昔の段階で多数派のBSDに日和った
・STREAMSをPOSIXに含めるときにioctlがPOSIXに追加された。しかし、それは(規格上は)STREAMS専用インタフェースで他の用途はしらんがな状態。かつ最新の規格ではSTREAMSはすでにobsolete
・世間の大多数のソフトは引数をintだと決め打っている。Macに至ってはカーネルが(BSD互換なので)unsigned longなのに、システムコンポーネントが int だと思って処理しているような箇所があり、

int action = (level ? TIOCSBRK : TIOCCBRK);
...
ioctl(fd, action, ...);

というコードが符号拡張で0xFFFFFFFF.... となってしまって、常に ENOTTY になってしまう有り様だった(Linusいわく)

・Linuxでは、そういうアホなユーザーランドへの対策として、64bitでも上位32bitは無視しているのでこの問題はおきない。たとえ、同様のミスをユーザーランドがしたとしても
・これをもって、Linusはカーネルはintでいいようになっていると主張していたが、manのほうのチケットでDavidが指摘したように、実際には最上位ビットも使っているので unsigned int 相当の動きをしている(Linusは暗黙の変換でうまくいくと主張していたが、まあ、そこはそれ)
・Linus的には 「So please fix the ioctl() declaration. "unsigned long" is misleading and actively incorrect and can cause bugs on non-Linux operating systems.」とglibcが直したほうが、よそのOSでのバグがなくなるんだと主張していたが、glibc関係者からは「Macにアホなバグがるから、glibcを直せってのはロジックが無茶苦茶だ」という反発がじゃっかんあったりなかったり。

とかなんとか迷走していた。
なお余談だが、Rubyもまったく同じバグが最近まであったのだが、1.9.3でわたしが直した。

備忘録なので、このエントリに特に結論はない。
このエントリーをはてなブックマークに追加

↑このページのトップヘ