2012-01-31 19 views
0

ここでは非常に奇妙で具体的な問題があります。私たちは一見有効なコードをリンカに入れて、リンカは、有効なptrラベルを削除するなど、いくつかの間違いを犯しています。代わりに値を0に置き換えます。しかしどこでもそうではありません。それはかなり恣意的な点から始まります。有効なコードを無効なコードに置き換えるリンカ

背景:私たちは、(社内のコンパイラのようなアプリケーションで)手作業で生成されたアセンブリのチャンクをまとめ、必要に応じて変数を追加することで、アセンブリに変換されるインタープリタ言語を持っています。これは、現在の形式であるにもかかわらず、もはやそうでない場合、約10年間働いているシステムなので、この方法の妥当性は現在問題ではありません。このアセンブリは、Microsoftアセンブラ(ml.exeまたはMASM)を使用してobjファイルにアセンブルされます。

別の手順で、このobjファイルは、Microsoft Incremental Linkerを使用して、実行可能ファイルを作成するためのいくつかの他のライブラリ(静的ライブラリとdllのインポートライブラリ)とリンクされます。

が続いアセンブリ(.ASM)ファイルの一部であり、それが最初のステップでOBJファイルを作成し、アセンブラ出力:

call _c_rt_strcmp    
mov di, 1     
mov ebp, esp     
cmp ax, 0     
je sym2148     
dec di      
sym2148: mov [ebp+6], di   
add esp, 6     
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 0bb49h  
pop ax 
mov byte ptr [ebx],al 
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 012656h   
push  ebx      
mov eax, OFFSET sym2151 
push eax 
call _c_rt_strcmp    
mov di, 1     
mov ebp, esp     
cmp ax, 0     
je sym2152     
dec di      
sym2152: mov [ebp+6], di   
add esp, 6     
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 0bb32h  
pop ax 
mov byte ptr [ebx],al 
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 012656h   
push  ebx      
mov eax, OFFSET sym2155 
push eax 
call _c_rt_strcmp    
mov di, 1     
mov ebp, esp     
cmp ax, 0     
je sym2156     
dec di      
sym2156: mov [ebp+6], di   
add esp, 6     
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 0bb4ah  
pop ax 
mov byte ptr [ebx],al 
mov  ebx, dword ptr [_smfv1_ptr]  
add  ebx, 0126bbh   
push  ebx      
mov eax, OFFSET sym2159 
push eax 
call _c_rt_strcmp 

限り私が見ることができるように、それは、正しいと理にかなっている。私は、これを生成するコードは文字列を比較し、文字列の比較結果に基づいて値を格納すると信じています。それは20-30のセクションなので、最初のビットが投稿される前に10以上のグループがあります、そして最後に私が投稿したビットの約15-20です。

004093D2 call  00629570 
004093D7 mov   di,1 
004093DB mov   ebp,esp 
004093DD cmp   ax,0 
004093E1 je   004093E5 
004093E3 dec   di 
004093E5 mov   word ptr [ebp+6],di 
004093E9 add   esp,6 
004093EC mov   ebx,dword ptr ds:[64174Ch] 
004093F2 add   ebx,0BB49h 
004093F8 pop   ax 
004093FA mov   byte ptr [ebx],al 
004093FC mov   ebx,dword ptr ds:[64174Ch] 
00409402 add   ebx,12656h 
00409408 push  ebx 
00409409 mov   eax,0 
0040940E push  eax 
0040940F call  00409414 
00409414 mov   di,1 
00409418 mov   ebp,esp 
0040941A cmp   ax,0 
0040941E je   00409422 
00409420 dec   di 
00409422 mov   word ptr [ebp+6],di 
00409426 add   esp,6 
00409429 mov   ebx,dword ptr ds:[0] 
0040942F add   ebx,0BB32h 
00409435 pop   ax 
00409437 mov   byte ptr [ebx],al 
00409439 mov   ebx,dword ptr ds:[0] 
0040943F add   ebx,12656h 
00409445 push  ebx 
00409446 mov   eax,0 
0040944B push  eax 
0040944C call  00409451 
00409451 mov   di,1 
00409455 mov   ebp,esp 
00409457 cmp   ax,0 
0040945B je   0040945F 
0040945D dec   di 
0040945F mov   word ptr [ebp+6],di 
00409463 add   esp,6 
00409466 mov   ebx,dword ptr ds:[0] 
0040946C add   ebx,0BB4Ah 
00409472 pop   ax 
00409474 mov   byte ptr [ebx],al 
00409476 mov   ebx,dword ptr ds:[0] 
0040947C add   ebx,126BBh 
00409482 push  ebx 
00409483 mov   eax,0 
00409488 push  eax 
00409489 call  0040948E 

実際のクラッシュの場所は0x00409429です:後

は、実行可能クラッシュしたときのVisual C++ 5.0(古い私が知っているが、これは残念ながら、レガシーシステム上にある)を示すことをクラッシュ位置の解体図です。 。

2つのコードは、同じセクションのコードと同じです。ただし、.asmファイルの最初のものはリンカに入り、もう1つはリンカから出てきます。

私は、0のアドレスを参照解除しようとしているため、その場所でクラッシュしています。もちろん、それは失敗するでしょう。また、0x004093D2、0x0040940F、0x0040944C、0x00409489の異なる関数呼び出しを見てみると、最初のものだけが有効です。他の関数呼び出しは単に関数呼び出しを呼び出しているだけです。そして、この破損したコードは、そのファイルで定義されている次の15〜20個の同様のコードセグメントのために継続されます。

両方のセクションで関数呼び出しと不良ポインターの対応する行を見ると、.asmファイルですべてが正しいように見えますが、何らかの形でリンカーはコンパイル時にすべてを破棄しますexe、そして非常に特定の場所では、正しく構築されたファイル内のコードの前に同様のチャンクがあるためです。

"LINK:warning LNK4049:ローカル定義シンボル" _smfv1_ptr "をインポートしました。しかし、それが働いていても同じ警告が表示されていました。

使用されたアセンブラは、ml.exeバージョン6.11であり、リンカーは、Visual C++ 5.0の両方のバージョンであったlink.exeバージョン5.10.7303でした。アセンブルされたコードは正しいと思われるので、私はVisual Studio 2005、2008、および2010からリンカーを試して、変更があるかどうか確認します。

私はこの種のエラーを作り出すことができるとは想像もできませんし、記号がうんざりしているかもしれないと思っていましたが、場所にジャンプします(小さなif文の場合)彼らはリンカーを通過した後に正常に動作します。

リンカの中でシンボルテーブルなどが過負荷になっている可能性はありますか?それは悪い値またはデフォルト値に戻っているだけですか?

+0

私は正常に接続するために投稿をお勧めしたいが、何のポイントは、このような古いツールでは全くありません。リンカー警告を取り除くことに焦点を当てます。あなたのツールを更新してください。 –

+1

Wow、Visual C++ 5.0?私は誰もが少なくともVisual C++ 6に更新したと思っていました...この問題をデバッグしてこの質問を書いた時間は、最近のバージョンのコンパイラでコードをコンパイルすることに費やされました。 –

+0

皆さん、私はそれが古いことを知っています。アップグレードは可能ですが、問題が解決する場合に限り、Visual Studio 2005、2008、および2010のリンカーを使用してテストしたところ、まったく同じ問題で同じ実行可能ファイルが作成されました。 生成されたアセンブリがまったく同じように見えるため、アセンブラは以前のバージョンです。それでも正しい。 – NaimK

答えて

1

次のアドレスへの呼び出しは、.objファイル内のすべての呼び出しがE8 00 00 00 00として出力されていることに気づいた場合には、未解決のシンボル参照の明確な記号です。いくつかのデータ参照についてもゼロがあります(sym2151、_smfv1_ptrへの参照、sym2159)。奇妙なのは、_c_rt_strcmpへの最初の呼び出しが解決されたことです。私はあなたが見つけることができるすべての警告/デバッグ/冗長スイッチを有効にし、あらゆる種類のリストとマップファイルを生成することをお勧めします。多分何かが飛び出すでしょう。

0

わかりましたので、最終的な結果は、MASMアセンブラ「ML.EXE」のビジュアルC++バージョンのバグであることのようです(大きな驚き、ハァッ?)

だから、のバージョンに移動Visual Studio 2005で提供されていたマスとリンクは、私たちのための最良の解決策であるようです。あなたの助けの人たちのための

感謝:)

関連する問題