いけむランド

はてダからやってきました

unable to remap が rebase で解決しなかった時の話

cygwin をそれなりに触っていると unable to remap というエラーに出会ったことがあると思います。


だいたい発生するのは自分でビルドした DLL を使うバイナリを起動した時でこういう場合には /bin/rebaseall はパッケージの DLL しか対象としないために自分でビルドした DLL をオプションで追加で指定してやる必要があります。

その方法については他の方の記事がぐぐれば出てくるので、そちらを参照してください。


自分の手元で起きた時も同じ問題だと思って rebase していたのですが、何故かある時から rebase しても解決できないようになりました。

いろいろ調べてみた結果、-b オプションでデフォルトのベースアドレスを 0x70000000 から小さい値に変えてみたら上手くいきました。*1

ところがしばらくすると -b オプションでも解決できなくなってしまいました。さらにぐぐってみたりしましたが、さすがにこれ以上は出てきませんでした...。


ふとエラーメッセージを見た感じで勝手に 32bit 空間が足りないんじゃないか?となんとなく思って Virtualbox に 64bit で OS から再インストールしたら、何故か発生しなくなりました。

704 名無しさん@お腹いっぱい。 2011/10/04 (火) 18:04:54
Cygwin使っている人いますか? その20 (UNIX板)

fork()地獄について
常識みたいだけど俺は知らなかったので書いとく
Vista以降ではrebaseallだけでなくpeflagsallってのも実行して、さらに
再起動する必要もあるみたいね

Vista以降にはセキュリティのためにASLRという機能があって、
これがcygwinのfork()エミュレーションと相性が悪いようだ
cygwinではrebaseallでDLLをロードするベースアドレスを衝突しないように
割り振っているけれども
ASLRでは、重要なデータや関数の位置が固定だと攻撃されやすいので
OSがランダムにリロケートするようになっている

PEにはASLRを許可するフラグ(DynamicBase)があって、
cygwinではpeflags.exeというツールでそれを弄れるようになっている
現在のPEのフラグは、objdump -p foo.exeとかやれば見れる

rebaseall同様、インストールされているexeやdllなどのフラグを全て書き換えるために
peflagsallというシェルスクリプトも提供されているので、それを使えってことの
ようだ
ただしこれらは/etc/setup以下から対象となるリストを取ってくるので、
野良ビルドしたもの(perlpythonの拡張を後で入れたりした場合もありがち)は
含まれない
そういう環境ではスクリプトを弄るなどして自分で対処しないといけないと思う

ぶっちゃけWin7 64bitとかだと、死にかけのcygwinを無理やり使っているような
感じがしないでもない……


自分の手元の環境だと cygwin ports から DLL を持ってきていたりもしているため、もしかしたら base の割り当てを使い切っていたのかもしれないですね。

% head -5 /tmp/rebase.log
/usr/lib/virtuoso/hosting/wikiv.dll: new base = 1fba0000, new size = 50000
/usr/lib/virtuoso/hosting/wbxml2.dll: new base = 1fbf0000, new size = 10000
/usr/lib/virtuoso/hosting/mediawiki.dll: new base = 1fc00000, new size = 60000
/usr/lib/virtuoso/hosting/im.dll: new base = 1fc60000, new size = 10000
/usr/lib/virtuoso/hosting/creolewiki.dll: new base = 1fc70000, new size = 50000
%

*1:ただし、小さくし過ぎると逆に動かなくなることがありましたので注意してください。