レジストリで設定する。Debugger_*は例なので、Debuggerキーに変える。
sprintfっぽい文法です。
で設定。
で設定。V2系列では、OllyDebugの設定から行える。
いくつかの理由(ntdll内RaiseExceptionとか)により、トラップ時にはまず使い物にならない。 MinGWビルドでなおかつgdbではじめから走らせる場合はそうでもないようだが。
foobar2000など、例外時にログとミニダンプを残すものがある。それらも含めて簡単に見てみる。
Windows標準でついてきますし、意外に使えます。
わかっているので、先に述べておくと、原因は、classをインライン化したためにメンバ関数の オフセット/スタックがalignment不定となっておきるようになったSSE movapsのalignmentエラーによるもので、 MinGW 4.1以降で採用された__attribute__((force_align_arg_pointer))をclass宣言時に使用するようにして解決しました。
にどんどん追加される設定だと探すのがちょっと面倒かもしれません。フォールト ->という部分を 探せば原因がわかります。
*----> スレッド Id 0xa00 の状態のダンプ <----*
eax=00000000 ebx=012eba80 ecx=000001e0 edx=00000000 esi=012ebb08 edi=012ebaa4
eip=66a6c233 esp=0289fb1c ebp=0289fb94 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
*** ERROR: Symbol file could not be found. Defaulted to export symbols for \
C:\Program Files\YAMAHA\Vstplugins\Wind\Freeverb3VST_Impulser2.dll -
ファンクション: Freeverb3VST_Impulser2
66a6c20c 90 nop
66a6c20d 90 nop
66a6c20e 90 nop
66a6c20f 90 nop
66a6c210 0f57c0 xorps xmm0,xmm0
66a6c213 c783bc00000000000000 mov dword ptr [ebx+0xbc],0x0
66a6c21d 0f2e83b4000000 ucomiss xmm0,dword ptr [ebx+0xb4]
66a6c224 f30f100d689dbd66 movssx xmm1,dword ptr [Freeverb3VST_Impulser2+0x399d68 (66bd9d68)]
66a6c22c 727b jb Freeverb3VST_Impulser2+0x22c2a9 (66a6c2a9)
66a6c22e f30f1155b8 movssx dword ptr [ebp-0x48],xmm2
フォールト ->66a6c233 0f295dc8 movaps oword ptr [ebp-0x38],xmm3 \
ss:0023:0289fb5c=7c8024b77c94da2a0000000300000180
66a6c237 f30f1165a8 movssx dword ptr [ebp-0x58],xmm4
66a6c23c f30f110424 movssx dword ptr [esp],xmm0
66a6c241 e8ca710000 call Freeverb3VST_Impulser2+0x233410 (66a73410)
66a6c246 d95da4 fstp dword ptr [ebp-0x5c]
66a6c249 f30f106da4 movssx xmm5,dword ptr [ebp-0x5c]
66a6c24e f30f1083c0000000 movssx xmm0,dword ptr [ebx+0xc0]
66a6c256 f30f108bc4000000 movssx xmm1,dword ptr [ebx+0xc4]
66a6c25e 0f28f5 movaps xmm6,xmm5
66a6c261 f30f5ef0 divss xmm6,xmm0
66a6c265 f30f59c8 mulss xmm1,xmm0
≪以降はobjdump -Sで得られる内容で、静的なコードなら↑と同じはずです。≫
≪c++filtを通すと、C++ demangleできます。≫
66a6c20f: 90 nop
66a6c210: 0f 57 c0 xorps %xmm0,%xmm0
66a6c213: c7 83 bc 00 00 00 00 movl $0x0,0xbc(%ebx)
66a6c21a: 00 00 00
66a6c21d: 0f 2e 83 b4 00 00 00 ucomiss 0xb4(%ebx),%xmm0
66a6c224: f3 0f 10 0d 68 9d bd movss 0x66bd9d68,%xmm1
66a6c22b: 66
66a6c22c: 72 7b jb 66a6c2a9 \
<__ZN3fv312limitmodel_f14processreplaceEPfS1_S1_S1_l+0x449>
66a6c22e: f3 0f 11 55 b8 movss %xmm2,-0x48(%ebp)
66a6c233: 0f 29 5d c8 movaps %xmm3,-0x38(%ebp)
66a6c237: f3 0f 11 65 a8 movss %xmm4,-0x58(%ebp)
66a6c23c: f3 0f 11 04 24 movss %xmm0,(%esp)
66a6c241: e8 ca 71 00 00 call 66a73410 <_logf>
66a6c246: d9 5d a4 fstps -0x5c(%ebp)
66a6c249: f3 0f 10 6d a4 movss -0x5c(%ebp),%xmm5
66a6c24e: f3 0f 10 83 c0 00 00 movss 0xc0(%ebx),%xmm0
66a6c255: 00
66a6c256: f3 0f 10 8b c4 00 00 movss 0xc4(%ebx),%xmm1
66a6c25d: 00
66a6c25e: 0f 28 f5 movaps %xmm5,%xmm6
66a6c261: f3 0f 5e f0 divss %xmm0,%xmm6
66a6c265: f3 0f 59 c8 mulss %xmm0,%xmm1
66a6c269: f3 0f 10 83 c8 00 00 movss 0xc8(%ebx),%xmm0
66a6c270: 00
66a6c271: f3 0f 58 c6 addss %xmm6,%xmm0
66a6c275: f3 0f 5e c8 divss %xmm0,%xmm1
66a6c279: f3 0f 10 83 cc 00 00 movss 0xcc(%ebx),%xmm0
66a6c280: 00
66a6c281: f3 0f 5c c1 subss %xmm1,%xmm0
66a6c285: f3 0f 5c c5 subss %xmm5,%xmm0
66a6c289: f3 0f 11 04 24 movss %xmm0,(%esp)
66a6c28e: e8 ad 71 00 00 call 66a73440 <_expf>
66a6c293: f3 0f 10 65 a8 movss -0x58(%ebp),%xmm4
66a6c298: f3 0f 10 55 b8 movss -0x48(%ebp),%xmm2
66a6c29d: 0f 28 5d c8 movaps -0x38(%ebp),%xmm3
66a6c2a1: d9 5d a4 fstps -0x5c(%ebp)
66a6c2a4: f3 0f 10 4d a4 movss -0x5c(%ebp),%xmm1
66a6c2a9: 0f 2e e1 ucomiss %xmm1,%xmm4
66a6c2ac: 0f 86 ae 02 00 00 jbe 66a6c560 \
<__ZN3fv312limitmodel_f14processreplaceEPfS1_S1_S1_l+0x700>
66a6c2b2: f3 0f 11 8b 14 01 00 movss %xmm1,0x114(%ebx)
ebp=0289fb94で、movaps %xmm3,-0x38(%ebp)だと、アクセス先である289EB5Cはalignment不整合なので、 Segmentation Faultになります。movupsだとOKなんですがね。
foobar2000\crash reportsにlog(Log)とdmp(User Mini Dump)が残る。
結論から言うと、明示的に認められるまで解放してはいけないクラスを 不定の状態にしたままVST構造体内に保持していた上に、ポインタへのポインタを 書くべきところをただのポインタと間違って書いていたために、突然のアクセスによって Segmentation Faultとなったものです。ちょっとわかりにくいです。ログの大事なところは下の通りです。
Illegal operation:
Code: C0000005h, flags: 00000000h, address: 77BF60B4h
Access violation, operation: write, address: 6687C2DDh
Registers:
EAX: 6687C2DD, EBX: 6687C240, ECX: 66B8AA1B, EDX: 00395E20
ESI: 00000002, EDI: 6687C2DD, EBP: 02E2F6B0, ESP: 02E2F690
Crash location:
Module: msvcrt
Offset: 360B4h
Symbol: "strcat" (+74h)
Stack dump analysis:
Address: 668449A3h (Freeverb3VST_Impulser2+49A3h)
Address: 6687C2DDh (Freeverb3VST_Impulser2+3C2DDh)
Address: 66B8AA1Ah (Freeverb3VST_Impulser2+34AA1Ah)
残念ながら、MinGWシンボルはWindows非互換なので、objdump -Sなりで見つかる関数のアドレス をソースと対応させる作業が必要になります。Visual C++だとそんな必要はないです。 foobar2000はダンプファイル(*.dmp)も残してくれるので、使ってみましょう。WinDBGで読み込めます。 Disassemblyでコードを見られます。msvcrt内で起きたので、MSVCRTのバグかと 誤認するかもしれませんが、そうではありません。
77bf60a5 f7c103000000 test ecx,3
77bf60ab 7419 je msvcrt!strcat+0x86 (77bf60c6)
77bf60ad 8a11 mov dl,byte ptr [ecx]
77bf60af 41 inc ecx
77bf60b0 84d2 test dl,dl
77bf60b2 7464 je msvcrt!strcat+0xd8 (77bf6118)
77bf60b4 8817 mov byte ptr [edi],dl
77bf60b6 47 inc edi
77bf60b7 f7c103000000 test ecx,3
77bf60bd 75ee jne msvcrt!strcat+0x6d (77bf60ad)
77bf60bf eb05 jmp msvcrt!strcat+0x86 (77bf60c6)
77bf60c1 8917 mov dword ptr [edi],edx
77bf60c3 83c704 add edi,4
77bf60c6 bafffefe7e mov edx,7EFEFEFFh
77bf60cb 8b01 mov eax,dword ptr [ecx]
77bf60cd 03d0 add edx,eax
77bf60b4でediに書き込むのですが、その書き込み先は6687C2DDで、 関数のオフセットで、あからさまにおかしいですね。&(アドレス演算子)を足して解決しました。 関数の型チェックは重要です。
結論から言うと、上の方でのべたSSE alignmentエラーと同じです。重要なところはWinDBGを含めて以下の通りです。
Illegal operation:
Code: C0000005h, flags: 00000000h, address: 64B6AEF8h
Access violation, operation: read, address: FFFFFFFFh
Registers:
EAX: 00000001, EBX: 040503B0, ECX: 0012F390, EDX: 7C94E514
ESI: 040503EC, EDI: 040503B0, EBP: 0012F490, ESP: 0012F408
Crash location:
Module: Freeverb3VST_WindCompressor
Offset: 22AEF8h
Loaded modules:
(中略)
Freeverb3VST_WindCompressor loaded at 64940000h - 64E22000h
Stack dump analysis:
Address: 6497B681h (Freeverb3VST_WindCompressor+3B681h)
Address: 77EDED69h (GDI32+ED69h), symbol: "CreateFontIndirectA" (+46h)
WinDBG Disassembly 64940000+22AEF8 (=OffsetとDllのロードアドレスで計算)
64b6aebe e88d88e0ff call Freeverb3VST_WindCompressor+0x33750 (64973750)
64b6aec3 8b83ac000000 mov eax,dword ptr [ebx+0ACh]
64b6aec9 8b550c mov edx,dword ptr [ebp+0Ch]
64b6aecc 89442404 mov dword ptr [esp+4],eax
64b6aed0 891424 mov dword ptr [esp],edx
64b6aed3 e8a887e0ff call Freeverb3VST_WindCompressor+0x33680 (64973680)
64b6aed8 0f57c0 xorps xmm0,xmm0
64b6aedb c745c000000000 mov dword ptr [ebp-40h],0
64b6aee2 c745cc00000000 mov dword ptr [ebp-34h],0
64b6aee9 8db42600000000 lea esi,[esi]
64b6aef0 f30f100d4828c764 movss xmm1,dword ptr [Freeverb3VST_WindCompressor+0x332848 (64c72848)]
ここ≫64b6aef8 0f2945a8 movaps xmmword ptr [ebp-58h],xmm0
64b6aefc f30f594dcc mulss xmm1,dword ptr [ebp-34h]
64b6af01 f30f5c0d3c28c764 subss xmm1,dword ptr [Freeverb3VST_WindCompressor+0x33283c (64c7283c)]
64b6af09 f30f110c24 movss dword ptr [esp],xmm1
64b6af0e f30f114d98 movss dword ptr [ebp-68h],xmm1
64b6af13 e858f3ddff call Freeverb3VST_WindCompressor+0xa270 (6494a270)
64b6af18 f30f104d98 movss xmm1,dword ptr [ebp-68h]
64b6af1d f30f110c24 movss dword ptr [esp],xmm1
64b6af22 d95dd0 fstp dword ptr [ebp-30h]
64b6af25 e846f3ddff call Freeverb3VST_WindCompressor+0xa270 (6494a270)
64b6af2a 0f2845a8 movaps xmm0,xmmword ptr [ebp-58h]
64b6af2e d95d94 fstp dword ptr [ebp-6Ch]
64b6af31 f30f105594 movss xmm2,dword ptr [ebp-6Ch]
64b6af36 0f28ca movaps xmm1,xmm2
64b6af39 0f540d5028c764 andps xmm1,xmmword ptr [Freeverb3VST_WindCompressor+0x332850 (64c72850)]
64b6af40 0f2f0d6028c764 comiss xmm1,dword ptr [Freeverb3VST_WindCompressor+0x332860 (64c72860)]
計算すると、alignmentがあいませんね。これも先ほど同じ解法で解決しました。
エラーの箇所がわかっても、その原因の場所が異なっていたりして、気付くまでは結構骨がおれるものです。 Windowsバイナリは特別の理由がないかぎりVC++でビルドしたほうがよいですね。MinGWを使っていると、 例外をDLL外に出してはいけなくなったり、DLL間ではExceptionはやりとりできなくなったり(正確には、 共有ライブラリを利用すればできないことはないけれど、ユーザにインストールさせるのが面倒だとか)だとか、 重箱の隅的な内容が増えてしまいます。
OllyDbg Q&A (Digital Travesia)
Digital Travesia 〜 でじたる とらべしあ 〜 推薦図書/パッケージソフト一覧
速習講座: クラッシュを分析してアプリケーションにおけるセキュリティの脆弱性を検出する
A few years pass; you���re still selling Qxyzrhjjjjukltks like crazy; but now
there are lots of Qxyzrhjjjjukltk clones on the market, like the open source
FireQx, and lots of headphones, and you all keep inventing new features that
require changes to the headphone jack and it���s driving the headphone makers
crazy because they have to test their new designs out against every
Qxyzrhjjjjukltk clone which is costly and time consuming and frankly most of
them don���t have time and just get it to work on the most popular
Qxyzrhjjjjukltk 5.0, and if that works, they���re happy, but of course when you
plug the headphones into FireQx 3.0 lo and behold they explode in your hands
because of a slight misunderstanding about some obscure thing in the spec
which nobody really understands called hasLayout, and everybody understands
that when it���s raining the hasLayout property is true and the voltage is
supposed to increase to support the windshield-wiper feature, but there seems
to be some debate over whether hail and snow are rain for the purpose of
hasLayout, because the spec just doesn���t say. FireQx 3.0 treats snow as rain,
because you need windshield wipers in the snow, Qxyzrhjjjjukltk 5.0 does not,
because the programmer who worked on that feature lives in a warm part of Mars
without snow and doesn���t have a driver���s license anyway. Yes, they have
driver���s licenses on Mars.
-- Joel Spolsky
-- Martian Headsets ( http://www.joelonsoftware.com/items/2008/03/17.html )
A lot of software developers are seduced by the old "80/20" rule. It seems to
make a lot of sense: 80% of the people use 20% of the features. So you
convince yourself that you only need to implement 20% of the features, and you
can still sell 80% as many copies.
Unfortunately, it's never the same 20%. Everybody uses a different set of
features. In the last 10 years I have probably heard of dozens of companies
who, determined not to learn from each other, tried to release "lite" word
processors that only implement 20% of the features. This story is as old as
the PC. Most of the time, what happens is that they give their program to a
journalist to review, and the journalist reviews it by writing their review
using the new word processor, and then the journalist tries to find the "word
count" feature which they need because most journalists have precise word
count requirements, and it's not there, because it's in the "80% that nobody
uses," and the journalist ends up writing a story that attempts to claim
simultaneously that lite programs are good, bloat is bad, and I can't use this
damn thing 'cause it won't count my words. If I had a dollar for every time
this has happened I would be very happy.
-- Joel Spolsky
-- "Strategy Letter IV: Bloatware and the 80/20 Myth" ( http://www.joelonsoftware.com/articles/fog0000000020.html )