GCC 生成的符號表調試信息剖析

GCC把C語言源文件('.c')編譯成匯編語言文件('.s'),匯編器把匯編語言文件翻譯成目標文件('.o'),最后由鏈接器鏈接所有的目標文件和有關的庫生成可執行文件('a.out')。

如打開'-g'選項,GCC編譯'.c'文件時,把附加的調試信息插進'.s'文件,這些調試信息經匯編器和鏈接器稍加轉換一直傳到可執行文件中。這些調試信息包括行號、變量的類型和作用域、函數名字、函數參數和函數的作用域等源文件的特性。

在某些目標文件中,調試信息用'.stab'打頭的一類匯編指導命令表示,這些指導命令穿插在匯編代碼中,這種調試信息格式叫'Stab',即符號表(Symbol table)。XCOFF和a.out目標文件格式采用Stab調試信息格式。此外,GCC也能在COFF和ECOFF目標文件格式中產生Stab。如要生成Stab調試信息,在GCC編譯源文件時,打開編譯選項'-gstabs+'(此選項將產生GNU調試器擴展的Stab的調試信息)或'-gstabs'。

匯編器處理'.stab'打頭指導命令,把Stab中的調試信息填入'.o'文件的符號表和串表(string table)中,鏈接器合并所有'.o'文件生成只含有一個符號表和一個串表的可執行文件。調試器通過檢索可執行文件中的符號表和串表來獲得程序的調試信息,下面分別介紹Stab的格式,GCC生成Stab和匯編鏈接器對Stab轉換。

?

1 Stab的格式

Stab匯編指導命令有3種格式:'.stabs'(string), '.stabn'(number)和'.stabd'(dot)。在MIPS機器上,GCC采用'.stabn'輸出源程序語句行號的Stab調試信息,而未使用'.stabd',因此,在MIPS機器上,GCC生成的帶有Stab調試信息的匯編代碼中只含'.stabs'和'.stabn'兩種匯編指導命令,'.stabs'和'.stabn'命令格式如下:

.stabs ″STRING″,TYPE,OTHER,DESC,VALUE

.stabn TYPE,OTHER,DESC,VALUE

下面說明Stab匯編指導命令的各域。

″STRING″的一般格式是:″NAME:SYM-DESC TYPE-INFO″

其中,NAME是由Stab表示的符號的名字,如果Stab表示是一個匿名對象,則NAME可省略,一般以一空格代替。SYM-DESC為一字母,它具體表示Stab所描述的是哪一類符號,例如:

SYM-DESC為'F',表示Stab描述的是全局函數;為'f'時,表示局部函數;為'G'時,表示全局變量。TYPE-INFO則表示數據類型信息,它可以是Stab分配給已定義的數據類型的序號,表示對已定義的數據類型的引用;也可以是一串符號,用來定義一種新的數據類型,參見1.3數據類型定義。

OTHER沒有使用,其值保持零。

DESC用編譯開關'-gstabs+'編譯源文件,DESC為源程序的語句行號;用編譯開關'-gstabs'編譯源文件,DESC為零。

VALUE可為一符號地址,或為自動變量在當前棧里相對幀指針的偏移量,或為寄存器變量所分配的寄存器的號碼。

以下各小節將結合實例對Stab描述調試信息的格式作具體的闡述。

1.1 Stab描述程序結構
(1)源文件的名字和路徑

在含有調試信息的匯編代碼中,第一個Stab匯編指導命令指明所編譯的源文件的名字,如果打開GCC編譯開關'-gstabs+',還會指明該源文明所在的目錄,例如:

.stabs ″usr/people/ycq/work / ″, 100, 0, 0, $Ltext( ) #100 is N-SO

.stabs ″example.c″, 100, 0, 0, $Ltext( )

其中TYPE為N-SO,表示該Stab描述的是源文件的名字或路徑,$Ltext( )表示與該文件相對應的代碼區的首地址。

(2)包含文件

描述包含文件的Stab指明隨后出現的變量、函數等符號所要參考的源文件,調試器由此查找到定義該符號的源文件。STRING為被包含文件名,TYPE=N-SOL,VALUE為被包含文件代碼區的首地址,如:

.stabs ″example.c″, 132, 0, 0, $Ltext1 #132 is N-SOL

(3)行號

行號表示匯編程序中的一段代碼所對應的C源程序的語句行號。匯編指導命令采用'gstabn',TYPE=N-SLINE,DESC表示源程序的語句行號,VALUE為該語句行所對應的一段匯編代碼的起始標號,例如:

.stabn 68, 0, 4, $LM6 #68 is N-SLINE

如果一源程序行所產生的匯編代碼不連續,可用多條'.stabn'表示,而DESC為同一值。

(4) 函數 描述函數的Stab,其TYPE為N-FUN,VALUE為函數的符號地址。SYM-DESC=F表示該函數為全局函數,SYM-DESC=f表示該函數的為局部函數,TYPE-INFO表示該函數的返回值的數據類型。下列為Stab描述局部函數func,其函數返回值為整型。

.stabs ″func: fl ″, 36, 0, 0, func #36 is N-FUN

(5)嵌套函數 嵌套函數是GNU C對標準C的擴充,Stab描述嵌套函數與描述一般函數的方式大致相同,區別是在描述嵌套函數時,在TYPE-INFO之后緊接包含該函數的最內層函數。
下面為一嵌套函數定義的例子,隨后給出了其Stab描述。

int funx (int x)
{
??? int funy (int y)
??? {

??? int funz (int z){return x+y+z; }

??? return funz (x+y);

?? }

?? return funy (x);

生成的Stab為:

.stabs ″funz: fl, funy″, 36, 0, 0, funz.5

.stabs ″funy: fl, funx″, 36, 0, 0, funy.2

.stabs ″funx: Fl″, 36, 0, 0, funx

作用域的描述格式是:TYPE-INFO之后跟','號,然后被描述的函數名跟','號,最后是包含該函數定義的最內層函數的名字。

(6)塊結構 這里塊結構是指C語言函數定義中表示塊語句開始和結束的左、右括號。描述左括號的('{')Stab,其TYPE=N-LBRAC,VALUE為以'$LBB'打頭的匯編語句標號;描述右括號('}')的Stab,其TYPE=N-RBRAC,VALUE為以'$LBE'打頭的匯編語句標號。匯編指導命令為'.stabn'。例如:

.stabn 192, 0, 0, $LBB2 #192 is N-LBRAC

.stabn 224, 0, 0, $LBE2 #224 is N-RBRAC

?


1.2 Stab描述變量

在C語言里,根據變量所具有的不同的存儲分配方式,可把變量分為:自動變量、全局變量、寄存器變量和靜態變量。

(1)自動變量 自動變量存儲在當前函數棧里,因此也叫棧變量。Stab描述自動變量時,TYPE為N-LSYM,Stab描述自動變量在當前函數棧里相對于幀指針的偏移量,SYM-DESC被省缺,如:

.stabs ″x: l″, 128, 0, 0, -12 #128 is N-LSYM

(2)全局變量 全局變量的作用域不局限于定義它的那個文件,可為多個文件使用。Stab描述全局變量時,TYPE為N-GSYM,SYM-DESC為G,VALUE為零,調試器根據全局變量的外部符號獲得其地址,如:char gvar='c';

生成的含Stab的匯編代碼為:

stabs ″gvar: G2″, 32, 0, 0, 0 #32 is N-GSYM

.globl gvar

.data

gvar:

byte 99

例中,匯編器根據'globl gvar'和'gvar: '產生一個外部符號,調試器由此外部符號獲得全局變量'gvar'的地址。

(3)寄存器變量 寄存器變量的值保存在寄存器里,Stab描述寄存器變量時,TYPE為N-RSYM,VALUE為寄存器號,SYM-DESC為'r',如:register int rvar asm ( ″ $30 ″ )生成的Stab為:.stabs ″ rvar: rl″, 64, 0, 0, 30 #64 is N-RSYM

(4)靜態變量 在函數內定義的靜態變量具有函數作用域,在函數外定義的靜態變量具有文件作用域。Stab描述靜態變量時,TYPE為N-STSYM表示該變量已初始化,而TYPE為N-LCSYM表示該變量未初始化,VALUE為變量的符號地址,SYM-DESC為'S'時,該變量的作用域為整個文件,SYM-DESC為'V'時該變量具有函數作用域。如:

static int var_init=2;

static int var_noinit;

假設它們的作用域都為文件作用域,生成的Stab為:

.tabs ″var_init: Sl″ , 38, 0, 0, var_init #38 is N-STSYM

.stabs ″var_noinit: Sl″ , 40, 0, 0, var_noinit #40 is N-LCSYM

(5)參數 C語言中,函數的參數可通過棧或寄存器傳遞,并且通過寄存器傳遞的參數也被保留在棧里,描述由棧傳遞的參數,TYPE=N-PSYM;VALUE為該參數在當前函數棧里相對于幀指針的偏移量,SYM-DESC為'p',如:main (int argc, char * *argv)

生成的Stab為:

.stabs ″main: Fl″ , 36, 0, 0, main #36 is N-FUN

.stabs ″argc: pl″ , 160, 0, 0, 68 #160 is N-PSYM

.stabs ″argv: p20= *21= *2″ , 160, 0, 0,72

寄存器由第2個Stab獲得參數的值,且根據第1個Stab知道該變量為參數。

1.3 數據類型定義

Stab采和匯編指導命令'stab'定義數據類型,TYPE域為N-LSYM,VALUE域為零,其″STRING″域中包含類型定義信息,下面是它的一般格式:

″NAME: SYM-DESC TYPE-NUM=TYPE-DESC…″

NAME為被定義的數據類型的名字;SYM-DESC=T表示聯合、結構和枚舉這3種數據類型,SYM-DESC=t表示其它數據類型;TYPE-NUM為一序號,如'1'表示整型,'2'表示字符型等;TYPE-DESC為類型描述器,更精確地對數據類型加以定義,如:TYPE-DESC= * ,表示指向其它類型的指針,TYPE-DESC=r,表示子界類型。這里介紹內部數據類型和部分其它數據類型的定義。

(1)內部數據類型 C語言的內部數據類型包括整型、字符型、浮點類型和'void'類型等,整型和字符型定義成其自身的子界,如對字符型(char)的定義:

.stabs ″char: t2 = r2; 0; 127; ″, 128, 0, 0, 0 #128 is N-LSYM

在″STRING″中,'r2'是子界類型定義,表示為'2'號類型(字符型)的子界類型,字符型的下界為0,上界為127,浮點類型被定義為整型的子界類型,與整型定義所不同的是,其上界為零,而下界為一正整數,表示該類型的大小(以字節為單位),如:

.stabs ″float: t12= rl; 4; 0; ″,

.stabs ″double: t13= rl; 8; 0; ″, 128, 0, 0, 0

void類型被定義為其自身,即:.stabs ″void: t15 = 15″ , 128, 0, 0, 0

(2)數組類型 定義數組類型時,在類型描述器(TYPE-DESC)'a'之后跟其下標和其元素的類型信息,例如:int vector[3];

生成的匯編代碼為:

.stabs ″vector: G20= arl; 0; 2; 1 ″, 32, 0, 0, vector

.comm vector, 12

(3)結構 聯合和枚舉類型 這3種數據類型都用T作為SYM-DESC。當TYPE-DESC=S時表示結構類型,TYPE-DESC=u時表示聯合類型,TYPE-DESC=e表示枚舉類型,另外枚舉類型和其它兩種數據類型在描述上還有差別,描述枚舉類型時,在TYPE-DESC之后跟其元素的名字和值對(NAME:VALUE),如:enum e_places{first, second=3,last};

生成的Stab為:.stabs ″e_places: T22=first: 0, second: 3, last: 4; ″,128, 0, 0, 0

描述結構和聯合這兩種數據類型時,TYPE-DESC之后為類型的大小,然后是對其元素的描述,其元素描述采用這樣的格式:″名字:類型,相對于結構或聯合始地的按位的偏移量,元素所占的存儲位″。如:

struct s_tag

{

int s_int;

float s_float;

};

生成的Stab為:.stabs ″s_tag: t17=s_int: l, 0, 32: s_float: 12, 32, 32; ; ″, 128, 0, 0, 0

?

2 Stab的生成
GCC編譯C語言源文件時,如果打開編譯選項'-gstabs'或'-gstabs+',則其生成的匯編代碼中就包含有Stab調試信息,以'.stab'打頭的匯編指導命令穿插在匯編代碼中間,下面介紹Stab在匯編代碼中出現的形式以及GCC編譯軟件中與Stab生成相關的幾個主要函數。Stab在匯編代碼中按其生成的順序可分為三部分,如下所示。


1) Stab for the source file
.. Stab for 'source files'
.. Stab for 'Defining types'
.. Stab for 'Initialized global & file-scope static variables'


2) Stab for each function defined in main source file or include file
.. Stab for 'Include files'
.. …
.. Stab for 'Line numbers'
.. …
.. Stab for 'function'or'procedure'
.. Stab for 'Parameters'
.. Stab for 'Automatic & Function-scope static variables'Stab for 'Block structures'


3) Stab for 'uninutialized global & file-scope static variables'


第一部分,在文件開始處的Stab,包括被編譯的主文件的名字,C語言內部定義的數據類型,然后是C源文件中定義的初始化全局變量和初始化的具有文件作用域的靜態變量。 第二部分,對應文件(包括被編譯的主文件和包含文件)中定義的每個函數,分別產生這么一串Stab并插入函數的匯編代碼中,包括該函數由哪個文件定義,匯編語句與C源程序的語句行的對應關系,最后是被定義的函數名字、函數的參數、自動變量、本函數中定義的靜態變量以及塊語句結構。

第三部分,在所有函數的匯編代碼之后出現的Stab,包括未初始化全局變量和未初始化的具有文件作用域的靜態變量。

GCC編譯軟件中用于輸出Stab調試信息的函數定義在dbxout.c中,下面列出一些主要函數的名字和功能。

dbxout_init輸出被編譯的主源文件和C語言內部定義的數據類型的Stab。

dbxout_source_file輸出包含文件和Stab。

dbxout_function輸出函數名字、函數的參數、自動變量、函數中定義的靜態變量以及塊結構的Stab。

dbxout_source_line輸出源程序語句行號的Stab。在MIPS機器上由定義在文件mips.c中的函數mips_output_source_line輸出源程序語句行號的Stab。

?


3 Stab的轉換
下面描述可執行文件('a.out')中符號表入口(symbol table entries)的格式,以及其與匯編指導命令的映射關系,并簡要介紹匯編器和鏈接器怎樣對符號表里的數據進行轉換。

每當匯編器遇到符號表匯編指導命令('.stab'),就把其各域填到其輸出文件('.o')的符號表入口的相應的各域中,如果stab含有串域('string'),在符號表里用一指針指向該串在串表的起始位置。在'a.out'文件中符號表入口的格式如下:

struct internal_nlist

{

unsigned long n_strx; /* index into string table of name */

unsigned char n_type; /* type of symbol */

unsigned char n_other; /* misc info (usually empty) */

unsigned short n_desc; /* description field */

bfd_vma n_value; /* value of symbol */

};

如果stab含有串(如: .stabs),域n_strx為該串在串表里以字節為單位的偏移量,串以空字符(″ /0″)標記結尾,如果 stab不含串(如:.stabn),則n_strx的值為零。

符號表里n_type域的值在于0xlf(十進制值:31)的入口或項(entry)是由編譯器生成的符號表調試信息轉換來的,而其它入口是由匯編器和鏈接器加進去的用戶在源程序中定義的符號。

鏈接器合并所有目標文件,整理好外部定義符號,生成一個符號表和一個串表。在UNIX系統下用命令'nmap'可分別觀察經匯編和鏈接之后的'.o'與'a.out'文件中包含有調試信息的
符號表。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454184.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454184.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《操作系統》OS學習(一):OS相關

清華大學操作系統OS(向勇、陳渝)視頻地址:http://www.xuetangx.com/courses/course-v1:TsinghuaX30240243Xsp/about 在ucore實驗中,一些基本的常用工具如下: 命令行shell: bash shell -- 有對文件和目錄操作的各種命令…

Android4.0藍牙使能的詳細解析

毫無疑問,bluetooth的打開是在Settings中進行的操作。因此,冤有頭,債有主,我們來到了Settings.java中,果然發現了相關的代碼如下: mBluetoothEnabler new BluetoothEnabler(context, new Switch(context));…

第一次沖刺

本人小組分工角色:產品負責人 本組沖刺訂單介紹:經過小組的成員討論,我們大概確立了一個沖刺的訂單是完成一個簡易的長沙學院網站項目。 最后完成情況概述:經過大約兩周的努力,我們組的編程人員運用python構建了一個簡…

移動端導出excel_連載系列【4】Excel開發移動端quot;APPquot;

前三篇文章介紹了百度地圖生成器、源代碼編輯器、GPS經緯度批量轉換工具、源代碼編輯器中添加自定義功能按鈕和地圖控件。這些寫好的Java Script代碼雖然可以實現所有期望的結果,但畢竟不是一個HTML文件,不便于傳播和使用,更無法變成一個類似…

《操作系統》OS學習(二):啟動、中斷、異常

Bootloader:加載OS。操作系統一開始是放在DISK(硬盤)中,并不是放在內存中。 BIOS:基本I/O處理系統。存放在ROMRead-Only Memory)只讀存儲中 BIOS(Basic Input/Output System)基本輸入輸出系統。…

[GCC for C]編譯選項---IDE掩蓋下的天空

編譯選項 ---------IDE掩蓋下的天空 /*************************************** * gcc for c language ***************************************/ Single Source to Executable $ gcc helloworld.c [-o howdy] 默認生成的名字a.exe ______________________________________ …

2016級算法第二次上機-F.ModricWang's Number Theory II

891 ModricWangs Number Theory II 思路 使得序列的最大公約數不為1,就是大于等于2,就是找到一個大于等于2的數,它能夠整除序列中的所有數。 考慮使得一個數d整除數組中所有數的代價: 如果一個數不能被b整除,那么可以花…

常用css屬性集(持續更新…)

禁止換行,超出部分顯示…:a. 代碼:.hide_word{ max-width: 100px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } b. 效果: 本文轉自 bilinyee博客,原文鏈接: http://blog.51cto.co…

parallels網絡初始化失敗_33 個神經網絡「煉丹」技巧

自然語言處理Andrej Karpathy 是深度學習計算機視覺領域、與領域的研究員。博士期間師從李飛飛。在讀博期間,兩次在谷歌實習,研究在 Youtube 視頻上的大規模特征學習,2015 年在 DeepMind 實習,研究深度強化學習。畢業后&#xff0…

《操作系統》OS學習(三):系統調用

例子 首先看一個標準C庫的例子:當我們程序中使用了C庫中的printf()函數,實際在底層是在內核態中調用了write()函數。圖中右側則是將程序代碼與C庫都算到應用程序中,內核提供了一個系統調用接口。 從這個例子我們可以得到以下幾點&#xff1a…

cygwin/gcc與MinGW

cygwin/gcc和MinGW都是gcc在windows下的編譯環境,但是它們有什么區別?在實際工作中如何選擇這兩種編譯器呢?cygwin/gcc完全可以和在linux下的gcc劃等號,這個從boost庫的劃分中就可以看出來端倪,cygwin下的gcc和linux下的gcc使用的是相同的T…

JavaScript服務器端開發技術(對象屬性的枚舉與查詢)

既然對象是屬性的集合,那么檢測與枚舉集合中的屬性就是一項重要任務。對此,我們來分別看一下ES3和ES5提供的解決方案。 1) ES3枚舉方案 示例代碼: var contacts{ ID:[0,1,2,3,4,5], names:["Zero","One","Two&q…

treelistview 所有節點失去焦點_垃圾詢盤過濾,焦點科技的 Milvus 實踐

文章作者:黎陽,焦點科技軟件開發工程師李成龍,Zilliz 數據工程師Milvus (https://milvus.io/) 向量搜索引擎開源半年以來,全球已經有數百家企業或組織用戶。焦點科技是一家以 B2B 外貿交易為主營業務的科技公司,也是 M…

《操作系統》OS學習(四):計算機體系結構、內存層次和地址生成

計算機除了計算能力之外還有存儲能力,存儲能力即計算機擁有一系列的存儲介質,我們可以在存儲介質上存儲我們的代碼和數據。計算機體系結構中約定了哪些地方可以用來存儲數據:CPU內的寄存器、內存和外存。不同的存儲介質,容量、速度…

GCC中SIMD指令的應用方法

X86架構上的多媒體應用開發,如果能夠使用SIMD指令進行優化, 性能將大大提高。目前,IA-32的SIMD指令包括MMX,SSE,SSE2等幾級。 在GCC的開發環境中,有幾種使用SIMD指令的方式,本文逐一介紹。X86的…

使用angular4和asp.net core 2 web api做個練習項目(二), 這部分都是angular

上一篇: http://www.cnblogs.com/cgzl/p/7755801.html 完成client.service.ts: import { Injectable } from angular/core; import { Http, Headers } from angular/http; import { Observable } from rxjs/Observable; import { ErrorHandler } from angular/core; import rxj…

leelen可視對講怎么接線_樓宇對講系統怎么布線 樓宇對講系統布線方式【介紹】...

隨著智能小區規模不斷增加,樓宇可視對講系統應用越來越廣泛,因而視頻信號的傳輸方式與布線設計顯得越來越重要。視頻信號與數據和音頻信號不同,可行的一種傳輸方式為視頻信號基帶傳輸,下面小編就簡要介紹一下這種傳輸方式和布線方…

路由匯總實例

5.2.2.2 路由匯總策略 之前提到過,在網絡管理員計劃好子網選擇并進行預期地路由匯總時,手動路由匯總工作能取得最佳效果。例如,之前的例子設定好了一個考慮周全的計劃,管理員只使用遠離Yosemite路由器并以10.2開頭的子網。這個規定…

《操作系統》OS學習(五):連續內存分配 內存碎片、動態分配、碎片整理、伙伴系統

內存碎片 在沒有其他方式輔助的情況下,我們分配給一個進程的內存是連續的。在分配時候我們需要有動態分配與碎片處理。如何理解呢?就是每個進程需要一塊內存,我們要選取合適的位置的內存分配給它。當有的進程先結束了內存還給操作系統&#…

GCC 中文手冊 - 摘自純C論壇

GCC Section: GNU Tools (1) Updated: 2003/12/05 Index Return to Main Contents NAME gcc,g-GNU工程的C和C編譯器(egcs-1.1.2) 總覽(SYNOPSIS) gcc[option|filename ]... g[option|filename ]... 警告(WARNING) 本手冊頁內容摘自GNU C編譯器的完整文檔,僅限于解釋選項的含義…