2014-06-16 94 views
3

好吧,這聽起來像一個愚蠢的問題,但我卡住了:我在lldb調試會話期間讀取變量的值時遇到了問題(事情與gdb一起工作正常)。使用lldb打印變量的內容

我發現了其他人遇到過的錯誤消息比我自己的帖子,但不同的是,我甚至不知道如何打印出最簡單形式的變量的值。

爲了更好地表達我的問題,我將在這裏考慮一個非常簡單的例子。我們打開一個 「main.c」 包含以下代碼:

#include <stdlib.h> 
#include <stdio.h> 

int main(void) { 
    int a = 1; 
    int b = 2; 
    int c = 0; 
    c = a + b; 
    c = c*b; 
    printf("c = %d\n", c); 
    return 0; 
} 

我使用編譯:

[email protected] ~ $ gcc -g main.c 

生成名爲 「a.out的」 一個二進制文件

我然後ivoque lldb:

[email protected] ~ $ lldb-3.4 ./a.out 

我想停在第9行和讀取c的值。因此,我開始通過添加一個斷點:

(lldb) breakpoint set -f main.c -l 9 

然後我運行代碼:

(lldb) run 

截至目前爲止,每一件事情都按預期。現在出現棘手的部分:我想讀取變量c的值。因此,我寫:

(lldb) print c 

而且LLDB返回我:

error: use of undeclared identifier 'c' 
error: 1 errors parsing expression 

當然:

(lldb) expression c 

回報完全相同的錯誤消息。

有什麼我錯過了嗎?任何幫助將非常感激。

我的設置:

  • LLDB: 「LLDB版本3.4(修訂版)」(套餐五: 「3.4〜svn183914-1ubuntu1」)
  • GCC:「海灣合作委員會(Ubuntu的/ Linaro的4.8.1 -10ubuntu9)4.8.1" (套餐五: 「4.8.1-2ubuntu3」)
  • (我的資料庫是那些默認提供的Linux Mint的16)

一些更多的Informa公司以下答案來自@Sean Perry:

1:似乎追加選項-O0不會更改調試器的行爲。

2:我也嘗試使用下面的僞代碼,而不是我以前的一個

#include <stdlib.h> 
#include <stdio.h> 

int main(void) { 
    long a = 1; 
    long b = 2; 
    long c = 0; 
    c = a + b; 
    c += (long) &c; 
    printf("c = %ld\n", c); 
    return 0; 
} 

我不能肯定這就是@Sean佩裏的「使用指針」的意思,但我想它必須防止因爲變量c的地址(或多或少)會隨着二進制文件的每次運行而隨機更改,所以無論如何都要進行代碼優化。

3:最後,我注意到一些有趣的事情:

  • 用gcc編譯[-g -O0]然後用gdb調試:工作
  • 用gcc編譯[-g -O0]然後用LLDB調試:不工作
  • 鏗鏘編譯[-g -O0]然後用gdb調試:工作
  • 鏗鏘編譯[-g -O0]然後用LLDB調試:工作

編輯1:回覆@SeanPerry edit2:區分軟件版本和軟件包版本

+0

我試過複製粘貼你的確切代碼,並用'Ubuntu 4.8.2-19ubuntu1'和'Ubuntu/Linaro 4.7.3-12ubuntu1'編譯它,並試着用lldb-3.4([stable branch] (http://llvm.org/apt/)),它的工作(即'(lldb)打印c'導致'(i​​nt)$ 0 = 3') – Scis

+0

@Scis:Awkward ...你在32位或64位機器上? (只是想知道在我使用的64位版本的gcc中是否會出現一個小故障)。我的gcc版本是Ubuntu/Linaro 4.8.1-10ubuntu9,我的lldb版本是「lldb 3.4版(修訂版)」。 我有點困惑這是一個穩定還是不穩定的構建......一方面,我的倉庫中的lldb包被標記爲「svn」,另一方面我安裝了它,輸入「aptitude install lldb- 3.4「,這正是您在[link](http://llvm.org/apt/)上建議我閱讀的頁面上給出的說明。你知道我能找到這個嗎? –

+0

我使用的是64位ubuntu 14.04 LTS。至於安裝,似乎我們都以同樣的方式安裝它(按照建議安裝'clang-3.4'的方式?嘗試再次運行'apt-get install clang-3.4 lldb-3.4'也許有一些版本不匹配 - 這當然只是一個猜測,但這又是一個奇怪的行爲) – Scis

回答

2

好像使用gcc 4.8.1lldb-3.4

時,使用gcc-4.8.2gcc-4.7.3工作得很好,這是一個具體問題。

+1

該死的,你比我更快發佈答案! (^ .-)​​ –

0

這段代碼非常簡單我敢打賭,llvm已經完全刪除了變量。嘗試編譯優化禁用(-O0),看看它是否有幫助。除此之外,使用一個指針或者做一些更復雜的事情,這樣編譯器不會刪除你的數學計算,並用預先計算的值替換它。

+0

一個簡單的方法來測試這可能是在二進制文件上使用'objdump',看看它產生了什麼代碼。不過,如果它與'gdb'一起工作.. – cnicutar

+0

感謝您的回覆!我在你的回答之後嘗試了幾件事,但不幸的是我不是很成功......我用今天的嘗試結果完成了我原來的問題。 –

+0

@cnicutar我使用objdump的反彙編二進制文件,它似乎有一個加法和乘法的二進制文件回事: 000000000040052d

: [...] 400551:\t 48 8B 55 E8 \t MOV -0x18 (%RBP),%的RDX 400555:\t 48 01 D0 \t添加%的RDX,%RAX 400558:\t 48 89 45 F8 \t MOV%RAX,-0x8(%RBP) [...] 40055c:\t 48 8b 45 f8 \t mov -0x8(%rbp),%rax 400560:\t 48 0f af 45 f0 \t imul -0x10(%rbp),%rax 400565:\t 48 89 45 F8 \t MOV%RAX,-0x8(%RBP) [...] 這不是一個 「硬」 證明,但我想這意味着必須有一個C變量的某處。 –

1

調查您所看到的行爲的最佳方法是查看調試信息。在Mac OS X系統上,如果您未創建dSYM,則可以在.dSYM軟件包或.o文件上運行dwarfdump。調試信息包含編譯器和調試器關於在哪裏查找變量的指令。

在直播過程中,隨着LLDB,你可以有LLDB告訴你,所有的局部變量都存儲(在DWARF位置表達式語言表示)image lookup -v -a $pc(或im loo -va $pc的簡稱)。

如果有一個程序,其中gdb無法打印變量,而lldb 在同一個電腦地址不能,那聽起來好像它可能是一個lldb錯誤。調試信息是最終的事實(就調試器而言)關於變量的存儲位置以及它們「存活」的時間。在優化的代碼中,它們可能適用於功能的很短的部分。

從黑客的角度來看,事實的真正來源是讀取彙編代碼。通常,在優化過程中,編譯器不會跟蹤變量的位置以及它可能 - 它可能變量在給定的pc地址不可用,但是如果您仔細閱讀組件,可能會找到仍保存在堆棧上的最後一個值的副本&等。

+0

感謝您的信息!我顯然對這一切都很陌生,因此我從來沒有真正深入研究過二進制代碼,所以你對我說的話很有意思。我擡頭看看'$ pc'是什麼(我發現了這個),但後來我想知道:是否還有其他「特殊」變量可能與'lldb'調試相關? –

+0

其他問題:雖然DWARF格式是一種標準的調試格式,但* .dSYM文件的生成是一種普遍的做法,或者它大部分與Mac有關?爲什麼你似乎更喜歡從編譯的代碼本身分離調試信息?奇怪的是,我找不到'gcc'或'clang'或選項來生成這些* .dSYM'文件,但我可能忽略了它... –