2014年2月26日 星期三

如何找出 iOS crash log 中的 symbol name

從 Sam 那看到的參考文章: 别用symbolicatecrash来解析crash log了 - Wonderffee's Blog

若 binary 是別人產生, crash log 也是別人產生時, 可以照以下的方式對回 symbols:

  1. 取得產生 crash log 對應 app binary 的 archive 目錄下的 dSYMs 目錄。
  2. 在命令列下輸入: $ mdimport dSYMs
  3. 將 crash log 存成 xxx.crash (副檔名必須是 .crash)。
  4. 打開 XCode 的 Oraganizer, 點選 Library 下的 Devices Logs, 點選 Import, 選擇 xxx.crash。

結果會顯示在畫面右側。

2014年2月24日 星期一

lldb to gdb command

官方連結: LLDB to GDB Command Map

在這備忘自己常用的指令:

  • return EXPR -> thread return EXPR

顯示 step out 後的傳回值

出處:

#/usr/bin/env python
 
import lldb
 
# Put _this_ file into ~/Library/lldb/thread_return.py
# Put the following line into ~/.lldbinit
#     command script import ~/Library/lldb/thread_return.py
 
def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand('command script add -f thread_return.thread_return thread_return')
 
def thread_return(debugger, command, result, internal_dict):
    '''Prints the return value of the last function you stepped out from.
    
    This is very useful if the return was a complex expression. This lldb command
    prevents you from needing to create a temporary variable just to inspect the return value'''
 
    # If anyone knows a way of doing this without using needing to script lldb in python...
    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    print >> result, str(thread.return_value)
    return lldb.thread.return_value

2014年2月21日 星期五

用 vim tab 批次處理多個檔案

最近才發覺 vim 有強大的批次處理功能, 相見恨晚啊。

在命令列同時開啟多個檔案到多個 tab

vim -p module/*.h

開啟 module 目錄下全部 .h 檔, 用一個 tab 編輯一個檔案。

需配合 tabpagemax 使用 (set tabpagemax=1000), 預設 tabpagemax=10, 不太夠用。

在 vim 內開啟多個檔案到多個 tab

:args module/*.h
:argdo :tabe

效果同上一個作法。但 argdo 為了加速讀檔會先關掉 syntax, 要自己加指令開啟 syntax:

:args module/*.h | execute 'argdo tabe %' | syntax on

在 vim 內更改全部 tab 內容並存檔

:tabdo :% s/xxx/ooo/
:tabdo :w

第一行對全部 tab 逐一執行 :% s/xxx/ooo/, 第二行則是逐一執行 :w。一但有 tab 無法執行指令, 就會停下來。

:tabdo 可用的場合很多, 比方說我習慣用 vim -p 一次開啟多個 core dump 的 backtrace, 然後用:tabdo normal zR unfold 全部檔案, 還有用 :tabdo 下指令 highlight 關鍵字:

:tabdo hi KeywordTemp ctermfg=red
:tabdo syn match KeywordTemp /SOME_KEYWORD/
方便閱讀不同 core dump 中共通的部份。

2014年2月19日 星期三

git 的入門文件

記錄一下我學 git 的過程。這些文件看起來都滿不錯的, 應該也適用沒接觸過 DVCS 的人 (我先前有用 mercurial 的經驗)。

Pro Git

先在網路查些基礎指令 (介紹愈短愈好), 還有抄別人的 git config 簡化成自己的版本, 就這樣上工一陣子。

然後需要 merge branch 時, 看這本第三章講 branch 的部份, 有許多圖示說明 git 內部資料的變化, 一目了然。看不懂的時候就回頭翻第二章, 滿容易上手的。

Git Tutorials and Training | Atlassian

平時要用什麼指令就 google 一下, 再點進 stackoverflow 看別人的說明。這樣瞎用了一陣子後, 回來快速掃一遍這裡的說明, 才比較有系統地記下常用指令。

Btw, 以前學 mercurial 的時候是先有系統地掃一遍常用指令, 再開始用。這回學 git 反過來, 覺得這樣學也不錯。或許基礎比較紮實後, 學類似的新東西時, 採取要用再補的方式會比較有效率。

2014年2月9日 星期日

從 third-party library 的 console 錯誤訊息找出更多線索

最近遇到一個不錯的小例子, 可以比較完整地記錄用到的相關指令。更多關於 gdb 的說明, 見 gdb 初步心得

問題

Ubuntu 下執行程式後看到 "Gtk-WARNING **: cannot open display:", 然後程式就掛了。

解決過程

為了獲取更多線索, 我想找出是那段程式輸出這個錯誤訊息。由 "Gtk-WARNING" 可知是 Gtk+ 函式庫輸出的錯誤訊息。所以得先取得 Gtk+ 的 debug symbol 和原始碼:

$ dpkg -l | grep gtk
...
ii  libgtk2.0-0
...

找出已安裝的 Gtk+ 函式庫叫做 libgtk2.0, 接著找出它對應的 debug symbol package 和原始碼:

$ aptitude search libgtk2.0
i   libgtk2.0-0             - GTK+ graphical user interface library
...
i   libgtk2.0-0-dbg         - GTK+ libraries and debugging symbols
...
i   libgtk2.0-dev           - development files for the GTK+ library
...

然後安裝 debug symbol, 還有取得 Gtk+ 的原始碼:

$ aptitude install libgtk2.0-0-dbg
$ apt-get source libgtk2.0-dev

從取得的原始碼找看看有沒有 "cannot open display":

$ cd gtk+2.0-2.24.10/
$ grep "cannot open display" -R .
./gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./gdk/gdk.c:      g_warning ("cannot open display: %s", display_name ? display_name : "");
./.pc/071_no_offscreen_widgets_grabbing.patch/gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./.pc/100_overlay_scrollbar_loading.patch/gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./ChangeLog.pre-2-12:   * gtk/gtkmain.c: (gtk_init): Fix "cannot open display" error message

讀一下字串出現相關的位置, 找出函式 gtk_init_check 和 gdk_init_check。看來沒有找錯方向, 於是可以用 cgdb 執行程式, 進入 gdb 後輸入:

(gdb) b gtk_init_check
(gdb) b gdk_init_check
(gdb) directory /my/path/to/gtk+2.0-2.24.10/
(gdb) set substitute-path /.../gtk+2.0-2.24.10/ /my/path/to/gtk+2.0-2.24.10/
(gdb) r
  • directory 用來載入 Gtk+ 原始碼。debug symbol package 裡沒有含這部份。
  • 編譯封裝 Gtk+ 的路徑十之八九和我放 Gtk+ 原始碼的路徑不同, 所以要用 set substitute-path 替換路徑, gdb 才知道如何顯示對應的原始碼。上面的 "..." 是執行 backtrace 時看到的路徑, 這裡簡化用 "..." 表示。

再來就在中斷點附近輸出收到的值, 看看 backtrace, 看看附近的原始碼, 獲得更多線索後就解決問題了。原來是我忘了呼叫 setenv("DISPLAY", ":0"), gdk_init_check() 發現無法產生 GdkDisplay, 所以就掛了。

C++ 能否用 memcpy 複製 class / struct 的資料?

答案是: POD (plain old data) type 可以。POD type 可和 C 互通, CPP Reference POD Type 的介紹: Specifies that the type is POD (Plain Old Data) type. Thi...