編譯原理/計(jì)算機(jī)系列

本書介紹程序設(shè)計(jì)語言編譯程序構(gòu)造的一般原理、基本設(shè)計(jì)方法、主要實(shí)現(xiàn)技術(shù)和一些自動(dòng)構(gòu)造工具。主要內(nèi)容包括:編譯程序概論、文法和語言、詞法分析與有限自動(dòng)機(jī)、自上而下語法分析方法、自下而上語法分析方法等。

編譯原理/計(jì)算機(jī)系列基本信息

書名 編譯原理/計(jì)算機(jī)系列 出版社 安徽大學(xué)出版社
頁數(shù) 238頁 開本 16
作者 王一賓 陳義仁 出版日期 2014年1月1日
語種 簡體中文 ISBN 7566406167

第1章 編譯程序概論

1.1 編程語言與翻譯系統(tǒng)

1.1.1程序設(shè)計(jì)語言

1.1.2 常用的高級語言

1.1.3 編譯程序的概念

1.2 編譯程序的工作過程

1.2.1 詞法分析

1.2.2 語法分析

1.2.3 語義分析和中間代碼產(chǎn)生

1.2.4 代碼優(yōu)化

1.2.5 目標(biāo)代碼生成

1. 3編譯程序的邏輯結(jié)構(gòu)

1.3.1 編譯程序的總體框架

1.3.2 編譯程序的表格管理

1.3.3 編譯程序中的錯(cuò)誤及出錯(cuò)處理

1.3.4 編譯程序的分遍處理

1.3.5 編譯前端與后端

1.4 編譯技術(shù)應(yīng)用

1.4.1 高級語言的實(shí)現(xiàn)

1.4.2 針對計(jì)算機(jī)體系結(jié)構(gòu)的優(yōu)化

1.4.3 新計(jì)算機(jī)體系結(jié)構(gòu)的設(shè)計(jì)

1.4.4 程序翻譯

1.4.5 提高軟件開發(fā)效率的工具

1.5 本章小結(jié)

習(xí)題1

第2章 文法和語言

2.1 符號(hào)和符號(hào)串

2.2 文法和語言的形式定義

2.2.1 文法和上下文無關(guān)文法

2.2.2 推導(dǎo)和語法分析樹

2.2.3 句型、句子和語言

2.3 Chomsky文法分類

2.4 文法和語言的二義性

2.5 文法的等價(jià)及其變換

2.6 本章小結(jié)-.

習(xí)題2

第3章 詞法分析與有限自動(dòng)機(jī)

3.1 詞法分析器的設(shè)計(jì)思想

3.1.1 詞法分析器的任務(wù)和輸出形式

3.1.2 將詞法分析工作分離的考慮

3.2 詞法分析器的設(shè)計(jì)

3.2.1 輸入緩沖區(qū)和預(yù)處理程序

3.2.2 掃描器的工作原理

3.2.3 狀態(tài)轉(zhuǎn)換圖與單詞的識(shí)別

3.2.4 狀態(tài)轉(zhuǎn)換圖的代碼實(shí)現(xiàn)

實(shí)驗(yàn)一 詞法分析器的設(shè)計(jì)

3.3 單詞的描述工具

3.3.1 正規(guī)文法

3.3.2 正規(guī)式與正規(guī)集

3.4 有限自動(dòng)機(jī)

3.4.1 確定有限自動(dòng)機(jī)(DFA)

3.4.2 非確定有限自動(dòng)機(jī)(NFA)

3.4.3 將NFA轉(zhuǎn)換為DFA

3.4.4 確定有限自動(dòng)機(jī)的化簡

3.5正規(guī)文法、正規(guī)式和有限自動(dòng)機(jī)的等價(jià)特性

3.5.1 正規(guī)文法與正規(guī)式的等價(jià)性

3.5.2 正規(guī)文法與有限自動(dòng)機(jī)的等價(jià)性

3.5.3 正規(guī)式與有限自動(dòng)機(jī)的等價(jià)性

3.6 詞法分析器的自動(dòng)構(gòu)造工具--LEX

3.7 本章小結(jié)

習(xí)題3

第4章 自上而下語法分析方法

4.1 語法分析的任務(wù)和分析方法

4.2 自上而下分析的基本思想和面臨的問題

4.2.1 自上而下分析的基本思想一

4.2.2 自上而下分析存在的困難和缺陷

4.3 左遞歸和回溯的消除

4.3.1 消除直接左遞歸

4.3.2 消除間接左遞歸

4.3.3 提取左公因子消除回溯

4.4 LL(1)分析法

4.4.1 FIRST集及其計(jì)算方法

4.4.2 FOLLOW集及其計(jì)算方法

4.4.3 LL(1)文法及LL(1)判定條件

4.4.4 LL(1)分析方法

4.5 不帶回溯的自上而下分析方法

4.5.1 遞歸下降分析程序

4.5.2 預(yù)測分析程序

4.6 LL(1)分析中的錯(cuò)誤處理

實(shí)驗(yàn)二 語法分析器設(shè)計(jì)之一--預(yù)測分析程序

4.7本章小結(jié)

習(xí)題4

第5章 自下而上語法分析方法

5.1 自下而上分析的一般思想和面臨的問題

5.1.1 歸約和"移進(jìn)一歸約"分析法

5.1.2 短語、句柄和最左素短語

5.1.3 規(guī)范歸約與規(guī)范推導(dǎo)

5.1. 4 自下而上分析的核心問題和分析方法

5.1.5 語法分析棧的使用與語法樹的表示

5.2 算符優(yōu)先分析法

5.2.1 算符文法和算符優(yōu)先文法

5.2.2 FIRSTVT集和LASTVT集

5.2.3 算符優(yōu)先關(guān)系表及優(yōu)先函數(shù)

5.2.4 算符優(yōu)先分析算法及其特點(diǎn)

5.2.5 算符優(yōu)先分析中的出錯(cuò)處理

實(shí)驗(yàn)三 語法分析器設(shè)計(jì)之二--算符優(yōu)先分析程序

5.3 LR分析法

5.3.1 LR分析器的工作原理

5.3.2 LR(0)分析器

5.3.3 SLR(1)分析器

5.3.4.LR(1)分析器

5.3.5 LALR(1)分析器

5.3.6 二義文法在LR分析中的應(yīng)用

5.3.7 LR分析中的出錯(cuò)處理

實(shí)驗(yàn)四 語法分析器設(shè)計(jì)之三--LR分析程序

5.4 語法分析器的自動(dòng)產(chǎn)生工具--YACC

5.5本章小結(jié)

習(xí)題5

第6章 語法制導(dǎo)翻譯和語義分析

6.1 屬性文法與語法制導(dǎo)翻譯

6.1.1 屬性及屬性文法

6.1.2 綜合屬性與繼承屬性

6.1.3 S-屬性文法與L一屬性文法

6.1.4 基于屬性文法的語法制導(dǎo)翻譯

6.2 語義分析和中間代碼的產(chǎn)生

6.2.1 語義分析的任務(wù)

6.2.2 常見的中間代碼形式

6.3 簡單算術(shù)表達(dá)式及賦值語句的翻譯

6.4 布爾表達(dá)式的翻譯

6.4.1 布爾表達(dá)式的翻譯方法

6.4.2 控制語句中布爾表達(dá)式的翻譯

6.5 控制結(jié)構(gòu)的翻譯

6.5.1 if語句的翻譯

6.5.2 while語句的翻譯

6.5.3 for語句的翻譯

6.5.4 goto語句的翻譯

6.6 說明語句的翻譯

6.6.1 簡單說明語句的翻譯

6.6.2 過程中的說明

6.7 數(shù)組的翻譯

6.7.1 數(shù)組元素的地址計(jì)算

6.7.2 賦值語句中數(shù)組元素的翻譯

6.8 過程調(diào)用語句的翻譯

6.8.1 參數(shù)傳遞的方式

6.8.2 過程調(diào)用的處理

6.9 本章小結(jié)

習(xí)題6

第7章 符號(hào)表

7.1 符號(hào)表的作用與內(nèi)容

7.1.1 符號(hào)表的作用

7.1. 2 符號(hào)表的內(nèi)容與操作

7.2 符號(hào)表的組織與管理

7.2.1 符號(hào)表的組織結(jié)構(gòu)

7.2.2 符號(hào)表的構(gòu)造與查找

7.3 名字的作用范圍

7.4 本章小結(jié)

習(xí)題7

第8章代碼優(yōu)化

8.1 優(yōu)化概述

8.2 局部優(yōu)化

8.2.1 基本塊及流圖

8.2.2 基本塊的DAG表示及其應(yīng)用

8.3 循環(huán)優(yōu)化

8.3.1 代碼外提

8.3.2 強(qiáng)度削弱

8.3.3 刪除歸納變量

8.4 本章小結(jié)

習(xí)題8

第9章 目標(biāo)代碼生成

9.1 代碼生成概述

9.2 目標(biāo)機(jī)器模型

9.3 一種簡單的代碼生成算法

9.3.1 活躍信息與待用信息

9.3.2 寄存器和變量地址描述

9.3.3 簡單代碼生成算法

9.3.4 寄存器分配

9.4 本章小結(jié)

習(xí)題9

參考文獻(xiàn)

編譯原理/計(jì)算機(jī)系列造價(jià)信息

市場價(jià) 信息價(jià) 詢價(jià)
材料名稱 規(guī)格/型號(hào) 市場價(jià)
(除稅)
工程建議價(jià)
(除稅)
行情 品牌 單位 稅率 供應(yīng)商 報(bào)價(jià)日期
計(jì)算機(jī)系統(tǒng) 查看價(jià)格 查看價(jià)格

安吉斯

13% 成都安吉斯智能設(shè)備有限公司廣州辦事處
計(jì)算機(jī)組成原理實(shí)驗(yàn)室 315mmX155mm鋁合金,(按樣品材料尺寸制作) 查看價(jià)格 查看價(jià)格

個(gè) 13% 成都市眾之藝展覽展示有限公司
計(jì)算機(jī) (含標(biāo)準(zhǔn)版軟件) 查看價(jià)格 查看價(jià)格

戴爾

臺(tái) 13% 重慶廣飛電子有限公司
計(jì)算機(jī) JSJ描述:用于安裝巡檢軟件,查看巡邏數(shù)據(jù);種類:電子巡更系統(tǒng); 查看價(jià)格 查看價(jià)格

新聯(lián)盾

臺(tái) 13% 內(nèi)蒙古新聯(lián)盾電子科技有限責(zé)任公司
計(jì)算機(jī) CORE雙核/1.6G 1GM 10/100M 80G DVC-RW 1000M 17"LCD 查看價(jià)格 查看價(jià)格

金迪

個(gè) 13% 四川金迪自控設(shè)備有限公司
計(jì)算機(jī) I7 8G,500G 查看價(jià)格 查看價(jià)格

個(gè) 13% 上海莫威電子科技有限公司
計(jì)算機(jī) 顯示器+主機(jī) 查看價(jià)格 查看價(jià)格

13% 深圳市日進(jìn)鑫科技有限公司
計(jì)算機(jī) E430 查看價(jià)格 查看價(jià)格

臺(tái) 13% 陜西金譽(yù)誠信息工程有限公司
材料名稱 規(guī)格/型號(hào) 除稅
信息價(jià)
含稅
信息價(jià)
行情 品牌 單位 稅率 地區(qū)/時(shí)間
DJS/R系列豪華型配箱 (暗裝)DJR-008 4-8 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-010 8-10 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-020 16-20 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-004 2-4 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-018 14-18 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-012 8-12 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-014 12-14 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
DJS/R系列豪華型配箱 (暗裝)DJR-016 12-16 查看價(jià)格 查看價(jià)格

個(gè) 佛山市順德區(qū)2005年2月信息價(jià)
材料名稱 規(guī)格/需求量 報(bào)價(jià)數(shù) 最新報(bào)價(jià)
(元)
供應(yīng)商 報(bào)價(jià)地區(qū) 最新報(bào)價(jià)時(shí)間
計(jì)算機(jī)系統(tǒng) |1348套 1 查看價(jià)格 成都安吉斯智能設(shè)備有限公司廣州辦事處 廣東  廣州市 2015-04-29
中央處理/計(jì)算機(jī)系統(tǒng) 含收費(fèi)計(jì)算機(jī)|1臺(tái) 2 查看價(jià)格 上海商豫智能科技有限公司 全國   2021-12-01
中央處理/計(jì)算機(jī)系統(tǒng) 含收費(fèi)計(jì)算機(jī)|1臺(tái) 1 查看價(jià)格 深圳市銳方達(dá)科技有限公司 全國   2021-11-30
計(jì)算機(jī) 計(jì)算機(jī)|1臺(tái) 3 查看價(jià)格 武漢年創(chuàng)信息科技有限公司 全國   2021-03-01
計(jì)算機(jī) 計(jì)算機(jī)|1個(gè) 3 查看價(jià)格 四川巨杉科技有限公司 四川   2018-05-31
計(jì)算機(jī) 計(jì)算機(jī)|1個(gè) 2 查看價(jià)格 四川聯(lián)合眾安科技有限責(zé)任公司 四川   2018-06-01
計(jì)算機(jī) 計(jì)算機(jī)|2臺(tái) 1 查看價(jià)格 長沙美能電力電氣設(shè)備股份有限公司 全國   2018-06-11
工業(yè)計(jì)算機(jī) 臺(tái)賬計(jì)算機(jī)|2臺(tái) 3 查看價(jià)格 廣東粵中環(huán)境科技有限公司 廣西  梧州市 2022-11-25

編譯原理/計(jì)算機(jī)系列常見問題

  • 計(jì)算機(jī)系統(tǒng)調(diào)試

    這個(gè)系統(tǒng)調(diào)試一般什么時(shí)候用?信息點(diǎn)怎么計(jì)算了? --:你好,這個(gè)點(diǎn)位就是設(shè)備終端的個(gè)數(shù)。 比如,打印機(jī),網(wǎng)絡(luò)插座,微機(jī),掃描儀這些能夠構(gòu)成網(wǎng)絡(luò)系統(tǒng)的設(shè)備 這個(gè)就是當(dāng)設(shè)備比較多的時(shí)候記取的一個(gè)調(diào)試。

  • 軟件需要計(jì)算機(jī)系統(tǒng)配置問題

    CPU呢,小區(qū)的數(shù)據(jù)比較大,處理量比較費(fèi)勁

  • 計(jì)算機(jī)技巧

    打開控制面板-管理工具-服務(wù) 禁用Application Management服務(wù),就能解決了。具體原因不明。

編譯原理/計(jì)算機(jī)系列文獻(xiàn)

南航研究生計(jì)算機(jī)復(fù)試—計(jì)算機(jī)原理與編譯原理考試大綱 南航研究生計(jì)算機(jī)復(fù)試—計(jì)算機(jī)原理與編譯原理考試大綱

格式:pdf

大?。?span id="6txsa4h" class="single-tag-height">9KB

頁數(shù): 1頁

評分: 4.8

南航研究生計(jì)算機(jī)復(fù)試—計(jì)算機(jī)原理與編譯原理 考試大綱: 計(jì)算機(jī)原理部分 第一章 計(jì)算機(jī)各部件的作用和層次結(jié)構(gòu) 第二章 數(shù)據(jù) 一、數(shù)值、非數(shù)值數(shù)據(jù)的表示二、校驗(yàn)碼 第三章 運(yùn)算器 一、算術(shù)和邏輯運(yùn)算的實(shí)現(xiàn) 二、標(biāo)志位 第四章 存儲(chǔ)系統(tǒng)一、存儲(chǔ)器分類、性能指標(biāo)二、存儲(chǔ)器擴(kuò)展方法三、高速 緩存工作原理四、磁表面和光存儲(chǔ)器 第五章 指令系統(tǒng)一、指令格式和尋址方式二、掌握 8086基本指令系統(tǒng)及簡 單匯編語言編程方法 * 第六章 CPU組織 一、CPU的結(jié)構(gòu)與功能二、 CPU控制流程和時(shí)序三、組 合邏輯和微程序控制器設(shè)計(jì)四、掌握 INTEL 微處理器基本結(jié)構(gòu)特征 * 第七章 I/O 組織一、I/O 接口及工作原理 * 二、程序控制傳送和中斷機(jī)制三、 DMA、通道和 I/O 處理機(jī)注:帶 *的部分可以參考《微機(jī)原理與接口技術(shù)》教材 編譯原理部分 第一章:了解有關(guān)編譯程序的基本概念、結(jié)構(gòu) 第二章:掌

立即下載
國外大學(xué)計(jì)算機(jī)系“軟件工程”系列課程分析 國外大學(xué)計(jì)算機(jī)系“軟件工程”系列課程分析

格式:pdf

大?。?span id="ypaik1a" class="single-tag-height">9KB

頁數(shù): 未知

評分: 4.8

國外大學(xué)計(jì)算機(jī)系“軟件工程”系列課程分析

立即下載

來源:MRRiddler ,

blog.mrriddler.com/2017/02/10/計(jì)算機(jī)體系-編譯體系漫游/

要想讓代碼乖乖運(yùn)行,自然代碼要先經(jīng)過編譯,這篇文章就來聊聊編譯體系。

代碼的編譯過程分為四個(gè)階段,預(yù)處理、編譯、匯編、鏈接。而編譯階段是整個(gè)過程中最復(fù)雜的階段,編譯階段還可以分為詞法分析、語法分析、語義分析。

在一頭扎進(jìn)這四個(gè)階段之間,先聊一下語法、語義。人類之所以能在進(jìn)化的歷史長河中,成為動(dòng)物中的佼佼者,進(jìn)化出的復(fù)雜的溝通機(jī)制—語言功不可沒。假如,我說出這句話:你個(gè)產(chǎn)品狗還在改需求!那么語法是啥呢?簡單說就是構(gòu)成這句話的順序,假如順序錯(cuò)亂意思就不同了。那么語義是啥呢?就是語境,根據(jù)我說這句話的情景,才能解釋出你指的是誰。語法在編程語言中,表現(xiàn)出來的就是語法結(jié)構(gòu)和結(jié)合律。語義表現(xiàn)出來的就是上下文(context)。

預(yù)處理(Preprocess):處理預(yù)處理符(#),包括宏展開、頭文件引入。 詞法分析(Lexical Analysis、Tokenizer):寫出的代碼實(shí)際上就是字符串,此階段需要對字符串進(jìn)行掃描(Scanner),將字符串掃描出分析的最基本單位(token),并在掃描過程中將它們分類,此階段是沒有任何語義的。也可以理解成將代碼掃描出基本表達(dá)式。 語法分析(Syntactic analysis、Parser):生成AST抽象語法樹,檢查語法結(jié)構(gòu),此階段是上下文無關(guān)的。也可以理解成將基本表達(dá)式按語法結(jié)構(gòu)組合成復(fù)合表達(dá)式。 語義分析(Semantic Analysis):語義檢查(比如檢查浮點(diǎn)數(shù)乘以指針,雖然語法結(jié)構(gòu)正確但是語義檢查不合格),將程序與上下文結(jié)合,進(jìn)行靜態(tài)類型分析,確定AST每個(gè)節(jié)點(diǎn)的類型。也可以理解將復(fù)合表達(dá)式結(jié)合環(huán)境(Environment),并且確定基本表達(dá)式、復(fù)合表達(dá)式的類型。 中間碼(Intermediate Representation):與語言無關(guān)、平臺(tái)無關(guān)的中間碼。如果編譯器面向多語言,對于任意語言編譯階段后可以生成通用的中間碼,這樣編譯器就有多語言的高拓展性了。生成中間碼后再交給匯編階段,再生成與平臺(tái)相關(guān)的匯編,這樣使編譯器將平臺(tái)相關(guān)性盡量往后推移。中間碼除了做為“橋接“,對中間碼的優(yōu)化也是整個(gè)編譯過程中的關(guān)鍵優(yōu)化。 匯編(Assemble):對中間碼生成平臺(tái)具體的匯編,在這個(gè)階段添加對多個(gè)平臺(tái)的支持,編譯器就可以跨平臺(tái)了。最后生成機(jī)器碼。 鏈接(Link):將每個(gè)機(jī)器碼編譯單位中引用的其他編譯單位中的變量、函數(shù)符號(hào)修正(fix)成真實(shí)地址。

編譯歷史

編譯的歷史基本就是計(jì)算機(jī)的進(jìn)化史,是很有趣的一段故事。Long time ago… 程序員寫程序都是用紙帶,那時(shí)候還在寫0、1機(jī)器碼。紙帶上打孔就是0,不打孔就是1。然后計(jì)算機(jī)讀取紙帶就是讀取指令。但是就像互聯(lián)網(wǎng)本質(zhì)就是提高效率一樣,這樣寫程序的效率怎能接受?并且,寫程序如果犯了錯(cuò)誤怎么辦?重新從頭到尾再用新紙帶搞一遍?程序員們機(jī)智的開始想辦法了,先是這樣搞:

將指帶有誤的地方,用黑黑的小貼紙?zhí)钌先?,這樣將0改成1了。這也是Patch名字的由來。但是這樣寫指令效率還是太低,程序員們再機(jī)智的想辦法。后來將指令進(jìn)行符號(hào)化(Symbol),抽象出指令集,這時(shí)就出現(xiàn)了匯編,程序員的效率上了一個(gè)檔次。但是新的問題又出現(xiàn)了。在寫過程調(diào)用的時(shí)候,要寫jmp 具體的函數(shù)地址。如果后來要在被調(diào)用的函數(shù)前面添加指令,那么函數(shù)地址也要跟著改。這樣牽一發(fā)動(dòng)全身的感覺可不好,為了讓影響(impact)縮減到最小,不如將函數(shù)地址也符號(hào)化。凡是寫過程調(diào)用先寫成jmp func,等到程序生成機(jī)器碼的時(shí)候,再將func換成真正的函數(shù)地址,這一步也就是將程序員手動(dòng)修正交由匯編器修正。

隨著生產(chǎn)力的提升,程序的規(guī)模越來越大,新的問題出現(xiàn)了,程序膨脹到難以維護(hù)和閱讀了。程序員們就將程序模塊化、層次化。這樣也使編譯的單位更小粒度化。編譯的時(shí)候,不同編譯單位之間的細(xì)節(jié)是互相隔離的。比如,對于C語言系,一個(gè).h和一個(gè).m就構(gòu)成了一個(gè)編譯單位。.m匯編時(shí),是不知道其他.m的全局變量、函數(shù)地址的,而調(diào)用的時(shí)候就只能用符號(hào)進(jìn)行調(diào)用,等到最后所有.m都生成機(jī)器碼后再進(jìn)行統(tǒng)一的修正。而負(fù)責(zé)這一步的就是鏈接器(Linker),這一步也叫重定位(Relocation)。

目標(biāo)文件

經(jīng)過匯編這一階段后,就會(huì)生成目標(biāo)文件。目標(biāo)文件和可執(zhí)行文件已經(jīng)非常相近了,只是有些符號(hào)還未修正,結(jié)構(gòu)上會(huì)進(jìn)行調(diào)整。Windows平臺(tái)下為PE(Portable Executable),Linux平臺(tái)下為ELF(Executable Linkable Format),Mac平臺(tái)下為Mach-O。雖然不同平臺(tái)都有自己的格式,但是它們實(shí)際上都大同小異。下面大體聊一下文件的實(shí)際字段,這些知識(shí)會(huì)為后面我們搞一些符號(hào)重綁定做鋪墊。

section

首先,文件分段(section)。不同的Section放置不同的信息,文件還有一個(gè)section header table放置控制信息。實(shí)際上,就類似圖片格式和mutipart的HTTP報(bào)文。以下是一個(gè)ELF目標(biāo)文件的常見section:

—— —— —— —— —— —— ——

|header | -----> 文件頭

|—— —— —— —— —— —— ——|

|.text | -----> 代碼段

|—— —— —— —— —— —— ——|

|.data | -----> 已初始化全局變量、靜態(tài)變量

|—— —— —— —— —— —— ——|

|.bss | -----> 未初始化全局變量、靜態(tài)變量

|—— —— —— —— —— —— ——|

|other sections... |

|—— —— —— —— —— —— ——|

|section header table| -----> section控制信息表

|—— —— —— —— —— —— ——|

|.strtab | -----> 字符串表

|—— —— —— —— —— —— ——|

|.symtab | -----> 符號(hào)表

|—— —— —— —— —— —— ——|

|..... |

—— —— —— —— —— —— —— —

.text放置代碼,.data放置已初始化的全局變量和靜態(tài)變量,.bss放置未初始化的全局變量和靜態(tài)變量。為什么代碼和全局變量、靜態(tài)變量要分開放?實(shí)際上,這就是個(gè)等同性問題。代碼段就是可讀的數(shù)據(jù),而全局變量、靜態(tài)變量是可讀可寫的數(shù)據(jù)。如果有多個(gè)進(jìn)程進(jìn)行同一份代碼,這些代碼都是等同的,不需要各自復(fù)制一份。而全局變量、靜態(tài)變量是不等同的,需要各自復(fù)制一份。而分什么又要分已初始化、未初始化呢?目標(biāo)文件未初始化的全局、靜態(tài)變量只需要放置一個(gè)占位符,代表其在.bss。而.bss在鏈接階段,變量不占空間,在裝載時(shí)由操作系統(tǒng)再分配空間??梢钥吹剑热皇俏募袷?,不管怎么設(shè)計(jì),主要的目的就是占更少的空間。

header有很多文件控制信息,就不一一表述了,其中最重要的就是記錄了section header table的起始地址。而section header table記錄了所有section的名字、類型、長度、在文件中的偏移量(offset)等。如果想要尋址到任意section都要通過這個(gè)header table。section header table實(shí)際上是由struct構(gòu)成的數(shù)組。

.strtab放置section名、變量名,包括符號(hào)名的字符串。由于在整個(gè)結(jié)構(gòu)中,字符串的長度是不定的,一般將這些字符串統(tǒng)一放置在一個(gè)table中,然后存儲(chǔ)table中的offset,最后尋址到字符串。比如,在下表中,我想找到girlfriend一詞,我只要拿到.strtab的base地址,加上girlfriend的offset 9就可以找到這個(gè)字符串。

0 1 2 3 4 5 6 7 8

i 0 w a n t 0 a 0

g i r l f r i e n

d

.symtab就是大名鼎鼎的符號(hào)表。每個(gè)目標(biāo)文件都有自己的符號(hào)表,符號(hào)表記錄符號(hào)的映射,符號(hào)可以這樣分:文件外符號(hào)和文件內(nèi)符號(hào),文件外符號(hào)就是使用在其他文件定義的符號(hào),文件內(nèi)符號(hào)除了在文件內(nèi)定義給其他文件使用的符號(hào),還包括每個(gè)section符號(hào),在文件內(nèi)定義光是文件內(nèi)使用的符號(hào)。光文件內(nèi)使用的符號(hào),對鏈接沒有幫助,主要為了崩潰后分析而存在。符號(hào)表也是一個(gè)由struct構(gòu)成的數(shù)組。ELF的32位符號(hào)sturct:

typedef struct {

int32_t st_name;

uint32_t st_value;

int32_t st_size;

unsigned char st_info;

unsigned char st_other;

uint16_t st_shndx;

} ELF32_Sym;

st_name字段就是符號(hào)的名字,表示為在.strtab中的字符串offset。st_info表示是局部符號(hào)、全局符號(hào)還是弱符號(hào)。符號(hào)也可以分為強(qiáng)符號(hào)(Strong Symbol)、弱符號(hào)(Weak Symbol),顧名思義,強(qiáng)符號(hào)有唯一性,弱符號(hào)沒有唯一性,一個(gè)強(qiáng)符號(hào)可以和多個(gè)弱符號(hào)共存,多個(gè)重復(fù)的強(qiáng)符號(hào)不可以共存,鏈接器會(huì)報(bào)出duplicate dymbol,可以用attribute((weak))指明弱符號(hào)。相對的,符號(hào)也有強(qiáng)引用(Strong Reference)、弱引用(Weak Reference),在鏈接進(jìn)行符號(hào)修正的時(shí)候,強(qiáng)引用必須修正,而弱引用可以不修正,可以用attribute((weakref))指明符號(hào)弱引用。

st_shndx字段指明了符號(hào)是文件外符號(hào),還是文件內(nèi)符號(hào)。如果是文件外符號(hào)就為SHN_UNDEF。如果是文件內(nèi)符號(hào)包括給其他文件使用的、光自己使用的、section符號(hào),就為所在section的索引號(hào),而st_value表示所在section的offset。等到鏈接過后,不管是文件外符號(hào)還是文件內(nèi)符號(hào),st_value指明實(shí)際地址。

符號(hào)修飾(Symbol-Decoration)與函數(shù)簽名(Function-Signature)

機(jī)智的同學(xué)已經(jīng)發(fā)現(xiàn)了,如果光按上面聊的方式進(jìn)行符號(hào)鏈接是有問題的,假如目標(biāo)文件有個(gè)func符號(hào)又引用了其他文件同名的func符號(hào),那符號(hào)不就出現(xiàn)沖突了?這里就需要引入函數(shù)簽名,函數(shù)簽名是一個(gè)函數(shù)的名字、參數(shù)類型、所在類名組成的字符串,不同語言、不同編譯器對同一個(gè)函數(shù)生成的函數(shù)簽名是不一樣的,比如OC中函數(shù)簽名還要加上返回變量類型,C++中還要加上NameSpace。在鏈接的時(shí)候,過程調(diào)用符號(hào)不光是函數(shù)名,是對函數(shù)簽名處理后的結(jié)果,全局變量符號(hào)也是經(jīng)過類似用函數(shù)簽名處理后的結(jié)果。這一處理過程就是符號(hào)修飾。

fishhook

fishhook是facebook開源的重綁定Mach-O符號(hào)的庫,最常用來hook C語言函數(shù),而且實(shí)際上只能重新綁定C符號(hào),因?yàn)榉?hào)修飾這一步只去掉了”_”,相當(dāng)于只針對C語言做了符號(hào)修飾。在了解了目標(biāo)文件后,重綁定就不是那么困難了。最基本的思路就是先拿到header,然后通過header拿到section header table,再找到.hash,.hash是一個(gè)用于加快訪問.symtab的哈希結(jié)構(gòu),再索引到.symtab,詳見這里,通過name去.strtab比對符號(hào)名,如果匹配就置換value。

https://docs.oracle.com/cd/E2382401/html/819-0690/chapter6-48031.html

fishhook大體實(shí)現(xiàn)原理就是這樣,只不過對Mach-O平臺(tái)特性改進(jìn)一下方案就行。在Mach-O中類似于section header table的段叫做load commands。并且Mach-O中使用二級命名空間,先分segment,就相當(dāng)于上文中的section,然后再在同一segment中區(qū)分section。

先拿到header,通過header中的ncmds(segment的個(gè)數(shù))和cmdsize(segment的大小)字段就可以找到所有的segment。然后找到.strtab、.symtab、indirect symbol table。這個(gè)indirect symbol table是一個(gè)uint32_t的數(shù)組。它就是nl_symbol_ptr(non-lazy)和la_symbol_ptr(lazy )對應(yīng)的.symtab struct數(shù)組的索引。nl_symbol_ptr和la_symbol_ptr section section中的reserved1字段指明對應(yīng)的indirect symbol table起始o(jì)ffset。只要從這兩個(gè)section對應(yīng)的indirect symbol table起始表項(xiàng)再跳到.symtab去匹配、置換就可以了。

下面是32位下.symtab的struct,可以看到和上段文章講的幾乎一致:

struct nlist {

union {

char *n_name; /* for use when in-core */

uint32_t n_strx; /* index into the string table */

} n_un;

uint8_t n_type; /* type flag, see below */

uint8_t n_sect; /* section number or NO_SECT */

int16_t n_desc; /* see <mach-o/stab.h> */

uint32_t n_value; /* value of this symbol (or stab offset) */

};

上文提到的Mach-O格式如下:

—— —— —— —— —— —— ——

|header |

|—— —— —— —— —— —— ——|

|load commands |

|—— —— —— —— —— —— ——|

|__Text |

|—— —— —— —— —— —— ——| —— __nl_symbol_ptr

|__Data | -----> |

|—— —— —— —— —— —— ——| —— __la_symbol_ptr

|other sections... |

|—— —— —— —— —— —— ——|

|.strtab |

|—— —— —— —— —— —— ——|

|.dynsym | -----> indirect symbol table

|—— —— —— —— —— —— ——|

|..... |

—— —— —— —— —— —— —— —

更加詳細(xì)的格式,推薦這篇文章。

http://turingh.github.io/2016/03/07/mach-o文件格式分析/

鏈接

上面聊了這么多 ,那靜態(tài)鏈接到底是如何將多個(gè)目標(biāo)文件鏈接成一個(gè)可執(zhí)行文件的呢?

靜態(tài)鏈接分為兩階段(Two-pass Linking),第一階段先掃描所有目標(biāo)文件,調(diào)整結(jié)構(gòu)。將所有目標(biāo)文件相同section合并,包括.symtab合并成全局.symtab,然后為每個(gè)section分配虛擬地址,再將全局.symtab中的符號(hào)進(jìn)行置換成虛擬地址。

這里如何將全局.symtab中的符號(hào)置換成虛擬地址呢?實(shí)際上,在分配section虛擬地址后,符號(hào)的虛擬地址按所在section虛擬地址加offset就可以計(jì)算出了。

第二階段將所有符號(hào)進(jìn)行修正。通過重定位表找到所有section中需要被修正的符號(hào)位置,然后從全局.symtab查詢出虛擬地址置換。

每個(gè)section都會(huì)對應(yīng)一個(gè)重定位段,這些重定位段組成一個(gè)重定位表。每個(gè)重定位表項(xiàng)叫做重定位入口(Relocation Entry),它記錄了所需重定向符號(hào)所在段的offset。

靜態(tài)鏈接庫

靜態(tài)鏈接庫就是一組目標(biāo)文件,經(jīng)過壓縮、索引而成的一個(gè)文件形式。當(dāng)我們平時(shí)在使用靜態(tài)鏈接庫的時(shí)候,實(shí)際上鏈接器會(huì)根據(jù)所需的符號(hào),在庫中搜索到相應(yīng)的目標(biāo)文件,并將其鏈接入最終可執(zhí)行文件。

動(dòng)態(tài)鏈接

隨著靜態(tài)鏈接慢慢發(fā)展起來,靜態(tài)鏈接也暴露出了問題。靜態(tài)鏈接將鏈接與被鏈接的目標(biāo)文件結(jié)合的太緊密了,導(dǎo)致如果多個(gè)目標(biāo)文件要鏈接同一個(gè)目標(biāo)文件,那這個(gè)被鏈接的目標(biāo)文件相當(dāng)于要被復(fù)制多份,每個(gè)可執(zhí)行文件都要包含這個(gè)被鏈接的目標(biāo)文件的內(nèi)容,這樣會(huì)占太多冗余空間。那怎么辦?將鏈接與被鏈接的目標(biāo)文件先隔離開,將鏈接的時(shí)機(jī)往后推移,等到裝載的時(shí)候再進(jìn)行鏈接。這樣,讓被鏈接的目標(biāo)文件只占一份空間就好。

既然動(dòng)態(tài)鏈接隔離開了鏈接、被鏈接目標(biāo)文件,鏈接目標(biāo)文件需動(dòng)態(tài)鏈接的符號(hào),就需要先做個(gè)動(dòng)態(tài)鏈接占位符。這也就是說,在目標(biāo)文件鏈接成可執(zhí)行文件時(shí),即使是用作動(dòng)態(tài)鏈接的目標(biāo)文件也要作為動(dòng)態(tài)鏈接庫輸入到鏈接階段,以供目標(biāo)文件識(shí)別哪些符號(hào)是動(dòng)態(tài)符號(hào)。

動(dòng)態(tài)鏈接重定位

上面已經(jīng)聊完了在鏈接階段對靜態(tài)鏈接進(jìn)行重定位,根據(jù)符號(hào)所在section的虛擬地址和所在section的offset。而動(dòng)態(tài)鏈接可以這樣重定位嗎?不行,這時(shí)動(dòng)態(tài)鏈接庫的地址還沒有確定,必須等到裝載以后操作系統(tǒng)分配。那可以等到裝載以后,確定地址后再直接進(jìn)行重定位嗎?不行,假如動(dòng)態(tài)鏈接庫被多個(gè)進(jìn)程引用,裝載時(shí)動(dòng)態(tài)鏈接庫進(jìn)行重定位,動(dòng)態(tài)鏈接庫映射到每個(gè)進(jìn)程中的虛擬地址都不一樣,動(dòng)態(tài)鏈接庫只能對一個(gè)進(jìn)程重定位,那么動(dòng)態(tài)鏈接庫就不是共享的了。那怎么搞?

通過.got(global offset table),.got就是一個(gè)指針數(shù)組,.got存儲(chǔ)引用符號(hào)的實(shí)際地址。而代碼段引用符號(hào)直接更改為引用.got項(xiàng)的位移,這在鏈接階段以后就不會(huì)再改變了。然后將.got分配在.data section,裝載時(shí)每個(gè)進(jìn)程復(fù)制一份并修正。實(shí)際上,動(dòng)態(tài)鏈接重定位指的就是在裝載的時(shí)候,根據(jù)全局符號(hào)表修正.got表項(xiàng)。動(dòng)態(tài)鏈接庫使用全局變量、靜態(tài)變量、引用文件外過程調(diào)用都要經(jīng)過.got。.got就像indirection table一樣,解決多進(jìn)程共享動(dòng)態(tài)鏈接庫。

這樣,動(dòng)態(tài)鏈接庫雖然在不同進(jìn)程中有不同的映射虛擬空間,但物理空間上共享。.got在不同進(jìn)程中,虛擬空間和物理空間都不共享。如下圖所示:

virtual address -> physical address

—— —— —— —— —— —— ——

|processA |

|—— —— —— —— —— —— ——|

|..... |

|—— —— —— —— —— —— ——|

|dynamic libiraries |----------

|—— —— —— —— —— —— ——| |

|..... | | |..... |

|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|

|.got |---------|---------->|.got |

|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|

|..... | | |..... |

|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|

----------->|dynamic libiraries |

—— —— —— —— —— —— —— | |—— —— —— —— —— —— ——|

|processB | | |..... |

|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|

|..... | | ------>|.got |

|—— —— —— —— —— —— ——| | | |—— —— —— —— —— —— ——|

|dynamic libiraries |---------- | |..... |

|—— —— —— —— —— —— ——| |

|..... | |

|—— —— —— —— —— —— ——| |

|.got |---------------

|—— —— —— —— —— —— ——|

|..... |

|—— —— —— —— —— —— ——|

動(dòng)態(tài)鏈接庫文件外符號(hào)重定位用.got就搞定了,那動(dòng)態(tài)鏈接庫文件內(nèi)符號(hào)呢?靜態(tài)鏈接同樣是在鏈接階段重定位就搞定了。動(dòng)態(tài)鏈接將絕對尋址指令更換成相對尋址指令,只要指令的offset不變,相對尋址指令就可根據(jù)當(dāng)前地址和offset得到正確的地址,這樣文件內(nèi)符號(hào)根本不需要重定位了?;谝陨蟽牲c(diǎn)的處理,代碼段在鏈接后就不需要更改了,這樣的代碼段也叫做地址無關(guān)碼(PIC),也就是說代碼段和裝載后的地址無關(guān)。

延遲綁定(PLT)

由于要跳過.got引用動(dòng)態(tài)鏈接庫的符號(hào),動(dòng)態(tài)鏈接庫比靜態(tài)鏈接庫慢5%左右,但相比于節(jié)省的大量空間還是很劃算的。除此之外,動(dòng)態(tài)鏈接還會(huì)有其他的問題,裝載時(shí)需要進(jìn)行重定位,會(huì)導(dǎo)致性能下降。不如,直接延遲綁定,等到過程調(diào)用符號(hào)運(yùn)行時(shí)被用到再進(jìn)行重定位。

整個(gè)過程強(qiáng)烈推薦這篇文章,要想理解動(dòng)態(tài)鏈接重定位,沒有比追匯編更好的方法了。動(dòng)態(tài)鏈接和延遲綁定整個(gè)過程都是由動(dòng)態(tài)鏈接器幫我們完成的。當(dāng)引用符號(hào)(callq)時(shí),先jmpq去plt結(jié)構(gòu),使用了PLT,引用符號(hào)就要先jmpq去plt結(jié)構(gòu)。如果沒找到相應(yīng)的地址,然后再jmpq去.got.plt或.got中。再把符號(hào)相應(yīng).rela.plt表中的索引和.got.plt相應(yīng)的表項(xiàng),pushq入棧,rela.plt中有符號(hào)的類型和名字。再jmp到動(dòng)態(tài)鏈接庫中(_dl_fixup),去全局符號(hào)表中找到符號(hào)相應(yīng)的地址。再將地址reloc到.got.plt或.got相應(yīng)表項(xiàng)。然后就完成了延遲綁定,下次引用同樣的符號(hào)就可以jmpq去plt結(jié)構(gòu)找到地址。

http://sysfork.com/post/linux-dynamic-lib-lazy-load/

引用

程序員的自我修養(yǎng)—鏈接、裝載與庫

關(guān)注「ImportNew」,看技術(shù)干貨

編譯是從源代碼(通常為高級語言)到能直接被計(jì)算機(jī)或虛擬機(jī)執(zhí)行的目標(biāo)代碼(通常為低級語言或機(jī)器語言)的翻譯過程。然而,也存在從低級語言到高級語言的編譯器,這類編譯器中用來從由高級語言生成的低級語言代碼重新生成高級語言代碼的又被叫做反編譯器。也有從一種高級語言生成另一種高級語言的編譯器,或者生成一種需要進(jìn)一步處理的的中間代碼的編譯器(又叫級聯(lián))。

典型的編譯器輸出是由包含入口點(diǎn)的名字和地址, 以及外部調(diào)用(到不在這個(gè)目標(biāo)文件中的函數(shù)調(diào)用)的機(jī)器代碼所組成的目標(biāo)文件。一組目標(biāo)文件,不必是同一編譯器產(chǎn)生,但使用的編譯器必需采用同樣的輸出格式,可以鏈接在一起并生成可以由用戶直接執(zhí)行的EXE,

所以我們電腦上的文件都是經(jīng)過編譯后的文件。

一、什么是編譯

1、利用編譯程序從源語言編寫的源程序產(chǎn)生目標(biāo)程序的過程。

2、用編譯程序產(chǎn)生目標(biāo)程序的動(dòng)作。 編譯就是把高級語言變成計(jì)算機(jī)可以識(shí)別的2進(jìn)制語言,計(jì)算機(jī)只認(rèn)識(shí)1和0,編譯程序把人們熟悉的語言換成2進(jìn)制的。 編譯程序把一個(gè)源程序翻譯成目標(biāo)程序的工作過程分為五個(gè)階段:詞法分析;語法分析;語義檢查和中間代碼生成;代碼優(yōu)化;目標(biāo)代碼生成。主要是進(jìn)行詞法分析和語法分析,又稱為源程序分析,分析過程中發(fā)現(xiàn)有語法錯(cuò)誤,給出提示信息。

二、什么是反編譯

計(jì)算機(jī)軟件反向工程(Reverse engineering)也稱為計(jì)算機(jī)軟件還原工程,是指通過對他人軟件的目標(biāo)程序(可執(zhí)行程序)進(jìn)行“逆向分析、研究”工作,以推導(dǎo)出他人的軟件產(chǎn)品所使用的思路、原理、結(jié)構(gòu)、算法、處理過程、運(yùn)行方法等設(shè)計(jì)要素,某些特定情況下可能推導(dǎo)出源代碼。反編譯作為自己開發(fā)軟件時(shí)的參考,或者直接用于自己的軟件產(chǎn)品中。

三、 Java類的編譯與反編譯

我們在最初學(xué)習(xí)Java的時(shí)候,會(huì)接觸到兩個(gè)命令:javac和java,那個(gè)時(shí)候我們就知道,javac是用來編譯Java類的,就是將我們寫好的helloworld.java文件編譯成helloworld.class文件。

class文件打破了C或者C++等語言所遵循的傳統(tǒng),使用這些傳統(tǒng)語言寫的程序通常首先被編譯,然后被連接成單獨(dú)的、專門支持特定硬件平臺(tái)和操作系統(tǒng)的二進(jìn)制文件。通常情況下,一個(gè)平臺(tái)上的二進(jìn)制可執(zhí)行文件不能在其他平臺(tái)上工作。而Java class文件是可以運(yùn)行在任何支持Java虛擬機(jī)的硬件平臺(tái)和操作系統(tǒng)上的二進(jìn)制文件。

那么反編譯呢,就是通過helloworld.class文件得到j(luò)ava文件(或者說是程序員能看懂的Java文件)

四、什么時(shí)候會(huì)用到反編譯

1、我們只有一個(gè)類的class文件,但是我們又看不懂Java的class文件,那么我們可以把它反編譯成我們可以看得懂的文件。

2、學(xué)習(xí)Java過程中,JDK的每個(gè)版本都會(huì)加入越來越多的語法糖,有些時(shí)候我們想知道Java一些實(shí)現(xiàn)細(xì)節(jié),我們可以借助反編譯。

關(guān)注“動(dòng)力節(jié)點(diǎn)Java學(xué)院”微信公眾號(hào),獲取更多最新Java技術(shù),如果你對編程有興趣,想要成為優(yōu)秀的Java程序員,那么動(dòng)力節(jié)點(diǎn)Java零基礎(chǔ)班現(xiàn)已開啟免費(fèi)試學(xué)階段,對于想學(xué)Java的同學(xué)無疑是好消息,親自考察教學(xué)質(zhì)量,機(jī)會(huì)就在眼前,針對不方便前來的同學(xué),可以關(guān)注動(dòng)力節(jié)點(diǎn)Java全套免費(fèi)視頻,趕快學(xué)起來吧

編譯原理/計(jì)算機(jī)系列相關(guān)推薦
  • 相關(guān)百科
  • 相關(guān)知識(shí)
  • 相關(guān)專欄

最新詞條

安徽省政采項(xiàng)目管理咨詢有限公司 數(shù)字景楓科技發(fā)展(南京)有限公司 懷化市人民政府電子政務(wù)管理辦公室 河北省高速公路京德臨時(shí)籌建處 中石化華東石油工程有限公司工程技術(shù)分公司 手持無線POS機(jī) 廣東合正采購招標(biāo)有限公司 上海城建信息科技有限公司 甘肅鑫禾國際招標(biāo)有限公司 燒結(jié)金屬材料 齒輪計(jì)量泵 廣州采陽招標(biāo)代理有限公司河源分公司 高鋁碳化硅磚 博洛尼智能科技(青島)有限公司 燒結(jié)剛玉磚 深圳市東海國際招標(biāo)有限公司 搭建香蕉育苗大棚 SF計(jì)量單位 福建省中億通招標(biāo)咨詢有限公司 泛海三江 威海鼠尾草 廣東國咨招標(biāo)有限公司 Excel 數(shù)據(jù)處理與分析應(yīng)用大全 甘肅中泰博瑞工程項(xiàng)目管理咨詢有限公司 山東創(chuàng)盈項(xiàng)目管理有限公司 當(dāng)代建筑大師 廣西北纜電纜有限公司 拆邊機(jī) 大山檳榔 上海地鐵維護(hù)保障有限公司通號(hào)分公司 甘肅中維國際招標(biāo)有限公司 舌花雛菊 湖北鑫宇陽光工程咨詢有限公司 GB8163標(biāo)準(zhǔn)無縫鋼管 中國石油煉化工程建設(shè)項(xiàng)目部 華潤燃?xì)猓ㄉ虾#┯邢薰? 韶關(guān)市優(yōu)采招標(biāo)代理有限公司 莎草目 建設(shè)部關(guān)于開展城市規(guī)劃動(dòng)態(tài)監(jiān)測工作的通知 電梯平層準(zhǔn)確度 廣州利好來電氣有限公司 蘇州弘創(chuàng)招投標(biāo)代理有限公司