12

ゴール:

の「アウトプット」を象徴したい[NSThread callStackSymbols]

補足:

クラッシュログでそれを行う方法を知っています。ただし、コール スタックを調べたいいくつかの問題を調査する必要があります。残念ながら、最近ではフレームワークのアドレスはすべて<redacted>. 適切なポイント(または最後に-質問の最後を参照)でクラッシュを引き起こすことは実際には受け入れられませんが、別の解決策が見つからない場合は、それが道です。

デバイスでテストを実行する必要があるため、シミュレーターを使用できません。

現在のアプローチ:

これを呼び出すと:

NSLog(@"call stack:\n%@", [NSThread callStackSymbols]);

私はこの出力を得る:

2015-12-08 15:04:03.888 Conversion[76776:4410388] call stack:
(
    0   Conversion                          0x000694b5 -[ViewController viewDidLoad] + 128
    1   UIKit                               0x27259f55 <redacted> + 1028
    ...
    9   UIKit                               0x274f67a7 <redacted> + 134
    10  FrontBoardServices                  0x2b358ca5 <redacted> + 232
    11  FrontBoardServices                  0x2b358f91 <redacted> + 44
    12  CoreFoundation                      0x230e87c7 <redacted> + 14
    ...
    16  CoreFoundation                      0x23038ecd CFRunLoopRunInMode + 108
    17  UIKit                               0x272c7607 <redacted> + 526
    18  UIKit                               0x272c22dd UIApplicationMain + 144
    19  Conversion                          0x000767b5 main + 108
    20  libdyld.dylib                       0x34f34873 <redacted> + 2
)

(この出力の「変換」はアプリです。)

これで、このコマンドを使用してアドレスを「記号化」できます。

xcrun atos -o /path/to/Conversion.app -arch arm64 -l 0x0???

そのように実行すると (もちろん に適切な値を指定して-l)、次のようなアドレスを入力する0x000694b5と、次のようなものが吐き出されます-[ViewController viewDidLoad] + 128。もちろん、問題は開始アドレス (-l オプションの値) です。

クラッシュ ログがある場合は、それらを取得できます。とはいえ、無事故で逃げ切りたい。

質問:

Q1:実行時に開始アドレスを決定し、それをログ出力に含めて、atos-lオプションにフィードすることはできますか?

編集:これは次のように可能であるように見えます:(NSProgrammerの回答に感謝https://stackoverflow.com/a/12464678/1396265 )

#import <mach-o/dyld.h>

...
intptr_t slide = _dyld_get_image_vmaddr_slide(0);
const struct mach_header * load_addr = _dyld_get_image_header(0);
NSLog(@"slide %lx load addr %lx", (long)slide, (long)load_addr);

/編集

(フレームワークのメソッド呼び出しに興味があるので、フレームワークの開始アドレスが必要なのは確かです。アプリの開始アドレスは頻繁に変更されます (ランダム化)。フレームワークの開始アドレスがランダム化されているかどうかはまだわかりません。)

Q2:コール スタック内のメソッドを調査する他の方法はありますか? (私のシナリオでは、ブレークポイントもかなり不器用です。)

編集:

Q3:フレームワークのアドレスを記号化するにはどうすればよいですか? たとえば、UIKit の dSYM (または必要なもの) はどこにありますか?

(たとえば、私は何かを持っています: ~/Library/Developer/Xcode/iOS\ DeviceSupport/9.1\ \(13B143\)/Symbols/System/Library/Frameworks/UIKit.framework/。ここで詳細を調べます。)

/編集

多分解決策:

1 つの方法として、ログ出力をファイルに保存し、テストの最後にアプリをクラッシュさせることが考えられます。callStackSymbolsそうすれば、クラッシュ ログで開始アドレスが明らかになり、ログからのコール スタック情報を使用して、出力を記号化できるはずです。次に試してみます。

4

2 に答える 2

6

これまでのところ、ログ スニペットをクラッシュ ログに追加することはうまくいったので、これを回答として追加します。(より良い答えは大歓迎です:-))

準備:

ソース コードの関連する場所に callStackSymbols ロギングを追加します。

NSLog(@"call stack:\n%@", [NSThread callStackSymbols]);

アプリをクラッシュさせます (たとえば、特定の画面を開いたとき):

strcpy(0, "000");

ログ出力をファイルにリダイレクトします。

FILE *logfile = freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);

実行:

Xcode でアプリを 1 回実行すると、アプリがデバイスにインストールされてから停止します。次に、デバイスでアプリを直接起動して、Xcode がクラッシュをキャッチしないようにします。

アプリを使用して、コール スタックがログに記録されるようにします (何度でも可能です)。

最終的にアプリをクラッシュさせます (私の場合、悪い strcpy を呼び出す特定の画面を開きます)。

ファイルの取得:

Xcode で「ウィンドウ -> デバイス」を開き、デバイスを選択し、アプリを選択してアプリ コンテナーをダウンロードすると、ログ ファイルを抽出できるようになります。

同じ画面でデバイス ログを開き、クラッシュ ログをエクスポートします。

Xcode で [ウィンドウ -> プロジェクト] を開き、プロジェクトを選択して、派生データ フォルダーを Finder に表示します (派生データ パスの右側にある小さな矢印ボタン)。派生データ フォルダーで、"Build/Products/Debug-iphoneos/" に移動し、MyApp.app と MyApp.app.dSYM をコピーします。

クラッシュ ログを調整します。

私にとっては、「バイナリ イメージ:」の直前に余分なスレッド セクションを追加することでうまくいきました。「Binary Images:」の場所を見つけます。「Thread 9999:」という行を挿入します。コール スタック ダンプをコピーして貼り付け、先頭の空白列を削除して、次のようにします。

2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree (
Thread 9999:
0   MyApp                               0x00000001001d95f8 -[MyClass myMethod:] + 100
1   UIKit                               0x000000018a5fc2ac <redacted> + 172
2   UIKit                               0x000000018a5d5ca4 <redacted> + 88
3   UIKit                               0x000000018a5d5b8c <redacted> + 460
4   UIKit                               0x000000018a5d5cc0 <redacted> + 116
5   UIKit                               0x000000018a5d5b8c <redacted> + 460
6   UIKit                               0x000000018a5d5cc0 <redacted> + 116
7   UIKit                               0x000000018a5d5b8c <redacted> + 460
8   UIKit                               0x000000018a8e85ac <redacted> + 460
9   UIKit                               0x000000018a5d4abc <redacted> + 96
10  UIKit                               0x000000018a935b7c <redacted> + 344
11  UIKit                               0x000000018a9306f8 <redacted> + 124
12  UIKit                               0x000000018aa584d8 <redacted> + 44
13  UIKit                               0x000000018a933d9c <redacted> + 188
14  UIKit                               0x000000018a70b668 <redacted> + 116
15  UIKit                               0x000000018a70b454 <redacted> + 252
16  UIKit                               0x000000018a70af38 <redacted> + 1404
17  UIKit                               0x000000018a70a9a8 <redacted> + 124
18  UIKit                               0x000000018a616d3c <redacted> + 312
19  UIKit                               0x000000018a616bc4 <redacted> + 108
20  QuartzCore                          0x0000000189dddc2c <redacted> + 284
21  libdispatch.dylib                   0x000000019a3a96a8 <redacted> + 16
22  libdispatch.dylib                   0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844
23  CoreFoundation                      0x00000001850001f8 <redacted> + 12
24  CoreFoundation                      0x0000000184ffe060 <redacted> + 1628
25  CoreFoundation                      0x0000000184f2cca0 CFRunLoopRunSpecific + 384
26  GraphicsServices                    0x000000018ff94088 GSEventRunModal + 180
27  UIKit                               0x000000018a644ffc UIApplicationMain + 204
28  MyApp                               0x0000000100093918 main + 124
29  libdyld.dylib                       0x000000019a3da8b8 <redacted> + 4

Binary Images:
...

「Thread 9999:」行により、symbolicatecrashスクリプトは次の行を記号化する必要があります。私は 9999 を選択したので、これらが追加されたセクションであることがわかります。

シンボリケーションを実行します。

symbolicatecrashスクリプトを見つけます。

$ find /Applications/Xcode.app -name symbolicatecrash -type f
/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash
$ 

シンボリック コマンドは、次のようになります。

$ symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash

DEVELOPER_DIR を設定し、スクリプトへのパスを追加する必要があるため、最終的には次のようになります。

$ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash

または、見やすくするためにラップします。

$ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' ...
/Applications/Xcode.app/Contents/SharedFrameworks/ ...
DTDeviceKitBase.framework/Versions/A/Resources/ ...
symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash

結果:

シンボリック スニペットは次のようになります。

2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree (
Thread 9999:
0   MyApp                               0x00000001001d95f8 -[MyClass myMethod:] (MyFile.m:15)
1   UIKit                               0x000000018a5fc2ac -[UIScrollView _willMoveToWindow:] + 172
2   UIKit                               0x000000018a5d5ca4 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 88
3   UIKit                               0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460
4   UIKit                               0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116
5   UIKit                               0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460
6   UIKit                               0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116
7   UIKit                               0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460
8   UIKit                               0x000000018a8e85ac __UIViewWillBeRemovedFromSuperview + 460
9   UIKit                               0x000000018a5d4abc -[UIView(Hierarchy) removeFromSuperview] + 96
10  UIKit                               0x000000018a935b7c __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke596 + 344
11  UIKit                               0x000000018a9306f8 -[UIPresentationController transitionDidFinish:] + 124
12  UIKit                               0x000000018aa584d8 -[_UICurrentContextPresentationController transitionDidFinish:] + 44
13  UIKit                               0x000000018a933d9c __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188
14  UIKit                               0x000000018a70b668 -[_UIViewControllerTransitionContext completeTransition:] + 116
15  UIKit                               0x000000018a70b454 -[UITransitionView notifyDidCompleteTransition:] + 252
16  UIKit                               0x000000018a70af38 -[UITransitionView _didCompleteTransition:] + 1404
17  UIKit                               0x000000018a70a9a8 -[UITransitionView _transitionDidStop:finished:] + 124
18  UIKit                               0x000000018a616d3c -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
19  UIKit                               0x000000018a616bc4 -[UIViewAnimationState animationDidStop:finished:] + 108
20  QuartzCore                          0x0000000189dddc2c CA::Layer::run_animation_callbacks(void*) + 284
21  libdispatch.dylib                   0x000000019a3a96a8 _dispatch_client_callout + 16
22  libdispatch.dylib                   0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844
23  CoreFoundation                      0x00000001850001f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
24  CoreFoundation                      0x0000000184ffe060 __CFRunLoopRun + 1628
25  CoreFoundation                      0x0000000184f2cca0 CFRunLoopRunSpecific + 384
26  GraphicsServices                    0x000000018ff94088 GSEventRunModal + 180
27  UIKit                               0x000000018a644ffc UIApplicationMain + 204
28  MyApp                               0x0000000100093918 main (main.m:16)
29  libdyld.dylib                       0x000000019a3da8b8 <redacted> + 4


Binary Images:
...

もっと簡単なアプローチが見つからない限り、これが今のところ私にとっての方法です。ログ ファイルからコール スタックを取得し、先頭の空白を削除してクラッシュ ログに挿入するスクリプトを作成すると便利な場合があります。

于 2015-12-09T15:38:38.413 に答える
0

シンボリックカテクラッシュ

Apple は、クラッシュ レポートのシンボリケーション プロセス全体を迅速化するスクリプトを XCode と共に出荷しています。dSYM、アプリのバイナリ、クラッシュ レポートがある場合、これがおそらく最も簡単なシンボリケーションの方法です。アドレスについて心配する必要はありません。このスクリプトはクラッシュ ダンプ ファイル全体を解析し、ATOS を使用してすべてのアドレスをシンボルに解決します。

システムで「symbolicatecrash」を見つけます。

cd /Applications/Xcode.app
find . -name symbolicatecrash

DEVELOPER_DIR 環境変数が存在しない場合はエクスポートします

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

.app バイナリ、クラッシュ レポート、および .dSYM ファイルを一時フォルダー (例: ~/tmp) にコピーします。以下の例のようにスクリプトを実行します。

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash -v ApteligentExampleApp.crash ApteligentExampleApp.app.dSYM/

すべてがうまくいけば、スクリプトはクラッシュ ファイル全体をシンボリック化し、結果をターミナル ウィンドウに出力します。このスクリプトは、ATOS やその他のツールを使用して手動で実行できないことは何も実行しませんが、必要なものをはるかに迅速に取得できます。

ソース

于 2017-01-13T01:36:42.303 に答える