公司名稱 | 諸暨漫游未來影院有限公司 | 成立時(shí)間 | 2015年08月18日 |
---|---|---|---|
總部地點(diǎn) | 諸暨市暨陽(yáng)街道苧蘿東路122號(hào)朗臻新天地B212-B222 |
諸暨永利房產(chǎn)開發(fā)有限公司還是不錯(cuò)的,技術(shù)支持、健全的售后服務(wù),我們有好的產(chǎn)品和專業(yè)的銷售和技術(shù)團(tuán)隊(duì),目前團(tuán)隊(duì)人數(shù)有30人。 地址:紹興 暨陽(yáng)街道友誼路158號(hào) 主要經(jīng)營(yíng)一般經(jīng)營(yíng)項(xiàng)目:房地產(chǎn)咨詢 房地產(chǎn)...
諸暨市品位銅門制造有限公司的產(chǎn)品防盜性特強(qiáng)。專業(yè)高級(jí)防盜鎖、保險(xiǎn)栓、門縫明暗栓、外口看不見鎖體和鎖芯、屬標(biāo)準(zhǔn)內(nèi)置鎖。貴而層次高,銅門豪華氣派,顯示貴族身份,品味上升,價(jià)值位高。拿不銹鋼本錢和加工費(fèi)與市...
請(qǐng)問諸暨興達(dá)家居市場(chǎng)有限公司好嗎?
諸暨興達(dá)家居市場(chǎng)有限公司是不錯(cuò)的,家居產(chǎn)品種類豐富,價(jià)格實(shí)惠,產(chǎn)品做工很精湛,看得出在做工方面非常用心,沒有發(fā)現(xiàn)瑕疵,材料選用純正材質(zhì),架構(gòu)結(jié)實(shí)。非常符合日常使用要求,產(chǎn)品憑借美觀,舒適,實(shí)用,人性話...
格式:pdf
大小:65KB
頁(yè)數(shù): 16頁(yè)
評(píng)分: 4.6
諸暨市城市建設(shè)投資發(fā)展有限公司 諸暨市濱江北路延伸段綠地公園建設(shè)項(xiàng)目 環(huán) 境 影 響 報(bào) 告 表 (簡(jiǎn)要本) 紹興市環(huán)球環(huán)境保護(hù)科學(xué)設(shè)計(jì)研究院有限公司 國(guó)環(huán)評(píng)證乙字號(hào)第 2005號(hào) 二 0一三年二月 目 錄 第一章 建設(shè)項(xiàng)目基本情況 ............................................................................. 1 1.1項(xiàng)目由來 ................................................................................................. 1 第二章 項(xiàng)目周邊環(huán)境及保護(hù)目標(biāo) ............................................................... 3 2.1項(xiàng)目地理位置
格式:pdf
大?。?span id="n6a1r60" class="single-tag-height">65KB
頁(yè)數(shù): 5頁(yè)
評(píng)分: 4.5
每日 條信息更新,多維度檢索、企業(yè)資80000+ 質(zhì)匹配、甲方監(jiān)控等功能,讓中標(biāo)快人一步! www.bidizhaobiao.com 本報(bào)告于 2019年9月19日 生成 1/5 www.bidizhaobiao.com 招標(biāo)投標(biāo)企業(yè)報(bào)告 杭州經(jīng)緯工程管理咨詢有限公司諸暨分公司 每日 條信息更新,多維度檢索、企業(yè)資80000+ 質(zhì)匹配、甲方監(jiān)控等功能,讓中標(biāo)快人一步! www.bidizhaobiao.com 本報(bào)告于 2019年9月19日 生成 2/5 www.bidizhaobiao.com 本報(bào)告于 2019年9月19日 生成 您所看到的報(bào)告內(nèi)容為截至該時(shí)間點(diǎn)該公司的數(shù)據(jù)快照 目錄 1. 基本信息:工商信息 2. 招投標(biāo)情況: 招標(biāo)數(shù)量、招標(biāo)情況、招標(biāo)行業(yè)分布、投標(biāo)企業(yè)排名、中標(biāo)企業(yè) 排名 3. 股東及出資信息 4. 風(fēng)險(xiǎn)信息:經(jīng)營(yíng)異常、股權(quán)出資、動(dòng)產(chǎn)抵押、稅務(wù)信息
影院建設(shè)項(xiàng)目在籌備后,進(jìn)入設(shè)計(jì)施工期,由施工方代為設(shè)計(jì)電影院,或者進(jìn)行設(shè)計(jì)招標(biāo),而電影院設(shè)計(jì)就是整個(gè)影院建設(shè)的關(guān)鍵部分,它一般的住宅設(shè)計(jì)不同,因?yàn)殡娪霸航ǔ珊笪宓绞陜?nèi)不會(huì)更換裝修風(fēng)格,要保持該階段內(nèi)的時(shí)尚新穎感。
影院設(shè)計(jì)構(gòu)成
通用的電影院設(shè)計(jì)結(jié)構(gòu)包括等候大廳、票房、賣品部、檢票口、過道走廊、影廳、放映室、廁所,有條件的還要建設(shè)貴賓室、吸煙區(qū)、貴賓廳、員工休息室、辦公區(qū)等。
影院元素
影院設(shè)計(jì)。影院元素包括幾個(gè)系統(tǒng):等候大廳主題系統(tǒng)、售票系統(tǒng)、賣品系統(tǒng)、影務(wù)系統(tǒng)、電影放映系統(tǒng)、影廳、廁所、影院文化系統(tǒng)、影訊發(fā)布系統(tǒng)、影院輔助系統(tǒng)等。 售票系統(tǒng)是指由賣票柜臺(tái)和電子售票系統(tǒng)組成的設(shè)備設(shè)施,包括售票柜臺(tái)、選座電腦顯示屏、會(huì)員通道、Led大屏幕等。 賣品系統(tǒng)是指由賣品柜臺(tái)、賣品銷售系統(tǒng)、各種可樂機(jī)、飲料柜員機(jī)、爆米花機(jī)、各種冰柜、賣品庫(kù)房、賣品制作間等組成。 影務(wù)系統(tǒng)是指由檢票口票臺(tái)、進(jìn)場(chǎng)時(shí)鐘組成。
電影放映系統(tǒng)是指放映室內(nèi)設(shè)施和各種放映設(shè)備、放映工作區(qū)、停片區(qū)、倒片區(qū)、撿片區(qū)等組成。
影廳由廳號(hào)、隔音幕墻、階梯座位、放映窗口、控制臺(tái)、溫濕度儀、銀幕及輔助設(shè)施、環(huán)繞立體聲音箱、清潔燈、測(cè)光等、散場(chǎng)燈、地角燈、其他各種修飾燈,一級(jí)出入場(chǎng)通道組成。
影院文化系統(tǒng)主要是指在一些等候區(qū)域和諧的融入一些電影院特色的文化宣傳圖片或文化墻,還包括影城大廳主題海報(bào)燈箱、國(guó)道走廊海報(bào)燈箱等。
影訊發(fā)布系統(tǒng)是指電影院大廳、廁所、吸煙區(qū)的各種電視墻和電視。
大廳主題系統(tǒng)包括大廳雕飾、大廳四周高層相應(yīng)象征物件和各種效果的燈組。
影院的設(shè)計(jì)風(fēng)格和色彩
影院設(shè)計(jì)。電影院的設(shè)計(jì)風(fēng)格除了時(shí)尚、三五年不落伍之外,一般都要與國(guó)際接軌。電影院的風(fēng)格要融入當(dāng)?shù)氐奈幕厣谏史矫鎽T用藍(lán)色主題、紅色主題和黃色主題,凸顯現(xiàn)代影院娛樂功能,因此顏色鮮艷明快,同時(shí)又有一定的厚重感,不張揚(yáng)。大廳、走廊裝飾凸顯層次。
項(xiàng)目施工
項(xiàng)目施工是在現(xiàn)有電影院設(shè)計(jì)圖紙的基礎(chǔ)上進(jìn)行的,對(duì)一些圖紙未提及文化,要進(jìn)行重新創(chuàng)意設(shè)計(jì)。
項(xiàng)目施工期從原材料送達(dá)之日起算起,一般需要3個(gè)月(90天)時(shí)間,先從框架結(jié)構(gòu)做起,分離出等候大廳、影廳區(qū)、放映去、辦公區(qū),然后再進(jìn)行影廳拆分、座位鋼結(jié)構(gòu)搭建、再到天花板、各種空燈、幕墻、座椅、地毯安裝,最后是立體聲系統(tǒng)安裝、銀幕安裝和地角燈的安裝調(diào)試。最后是影城票房、賣品部進(jìn)駐和大廳施工。
影城施工通常由4~5個(gè)施工隊(duì)伍同時(shí)施工,包括鋼結(jié)構(gòu)施工隊(duì)、幕墻施工隊(duì)、地磚施工隊(duì)、地毯座椅施工隊(duì)和造景施工隊(duì)組成,一級(jí)強(qiáng)電、弱電等。
城市中越來越多的購(gòu)物中心出現(xiàn),電影院幾乎成了其標(biāo)配之一。但就像是購(gòu)物中心的服飾品牌、餐飲種類大同小異,電影院的空間設(shè)計(jì)也罕有新意。
4D動(dòng)感影院介紹
4D動(dòng)感影院,由三維立體電影和周圍的環(huán)境模擬組成的四維空間,它是在3d立體電影的基礎(chǔ)上加環(huán)境特效、模擬仿真而組成的新型影視產(chǎn)品,通過給觀眾以電影內(nèi)容聯(lián)動(dòng)的物理刺激,來增強(qiáng)臨場(chǎng)感的效果。隨著影院娛樂技術(shù)的發(fā)展和娛樂市場(chǎng)的需求,人們不僅將震動(dòng)、墜落、吹風(fēng)、噴水、撓癢等特技引入3D影院,還根據(jù)影片的情景精心設(shè)計(jì)出煙霧、雨、光電、氣泡等效果,形成了一種獨(dú)特的體驗(yàn),這就是當(dāng)今十分流行的4D影院。
4D動(dòng)感影院組成
4D動(dòng)感影院整體系統(tǒng)由專業(yè)級(jí)、震撼的立體投影,銀幕, 4D座椅,環(huán)境特效, 數(shù)碼音響,影院總控制系統(tǒng)等組成。其相比較于其他類型影院,具有主題突出、科技含量高、效果逼真、娛樂性強(qiáng)等特點(diǎn)和優(yōu)勢(shì)。
動(dòng)感影院環(huán)境特效
廣州全影匯VR“4D動(dòng)感影院”可以添加刮風(fēng),下雨,下雪,閃電,煙霧,泡泡等特效,觀影時(shí)影片里會(huì)出現(xiàn)風(fēng),雨,電,煙霧,泡泡等自然現(xiàn)象時(shí),特效設(shè)備也將同步出現(xiàn)這些自然現(xiàn)象,讓體驗(yàn)者感受到近乎極致和身臨其境的參與感與互動(dòng)性!
系統(tǒng)框架結(jié)構(gòu)圖
4D動(dòng)感影院與4D游戲采用相同的工作原理,是利用專業(yè)的3D開發(fā)引擎,借助3D立體電視、投影器等顯示設(shè)備、立體眼鏡等接收設(shè)備,通過兩部具有一定視覺差的影像(即模擬人體雙眼的立體成像功能所塑造的影像)組合,在觀眾或玩家參與過程體現(xiàn)出較強(qiáng)互動(dòng)性的效果。
4D動(dòng)感座椅特效
全影匯VR4D動(dòng)感平臺(tái)可以精準(zhǔn)模擬前傾、后仰、左傾、右傾、墜落、顛簸、吹風(fēng)、噴水、掃腿、捅背、震股等動(dòng)作。當(dāng)影片出現(xiàn)以下場(chǎng)景時(shí),你會(huì)體驗(yàn)到相對(duì)應(yīng)的特效。例如:影片情節(jié)里摩托向左或向右拐彎時(shí),座椅會(huì)做出相應(yīng)的動(dòng)作;影片情節(jié)里從高空向下墜落時(shí),座椅會(huì)模擬快速向下。這一系列電影情節(jié)動(dòng)感座椅都能模擬并且完全同步!
多款連排動(dòng)感座椅
4D動(dòng)感座椅是建立4D動(dòng)感影院必不可少的構(gòu)成元素之一,4D動(dòng)感座椅可以根據(jù)4D動(dòng)感影院中特效座椅的布置故事情節(jié)的不同而由計(jì)算機(jī)控制做出不同的特技效果來,例如,墜落,震蕩,噴風(fēng),噴雨等等,再配上精心設(shè)計(jì)出來的煙霧、雨、光電、氣泡、氣味等,從而營(yíng)造一種與影片內(nèi)容相一致的全感知環(huán)境。
4D動(dòng)感影院施工案例
環(huán)幕4D動(dòng)感影院不同于一般的電影屏幕,采用柱面環(huán)幕投影顯示方式,將觀賞著圍繞在中心。屏幕上的超長(zhǎng)跨度的廣闊畫面充滿觀賞者的視野,全方位立體聲與影片情節(jié)相輔相成、完美配合,演繹精彩絕倫的沉浸式視聽享受。柱面投影屏幕的弧度有360度、270度、180度等多種選擇,可根據(jù)場(chǎng)地具體情況進(jìn)行個(gè)性化設(shè)計(jì)和施工,保證4D環(huán)幕動(dòng)感影院效果。
4D動(dòng)感影院成功案例
全影匯VR科技貴州遵義動(dòng)感影院成功案例等采用立體投影系統(tǒng),結(jié)合擁有自主知識(shí)產(chǎn)權(quán)的動(dòng)感設(shè)備、環(huán)境特效、燈光特效系統(tǒng), 將從視覺、聽覺、嗅覺、感覺等方面,為觀眾帶來身臨其境前所未有的刺激體驗(yàn)。
全影匯:http://www.chinavrway.com
來源:MRRiddler ,
blog.mrriddler.com/2017/02/10/計(jì)算機(jī)體系-編譯體系漫游/
要想讓代碼乖乖運(yùn)行,自然代碼要先經(jīng)過編譯,這篇文章就來聊聊編譯體系。
代碼的編譯過程分為四個(gè)階段,預(yù)處理、編譯、匯編、鏈接。而編譯階段是整個(gè)過程中最復(fù)雜的階段,編譯階段還可以分為詞法分析、語法分析、語義分析。
在一頭扎進(jìn)這四個(gè)階段之間,先聊一下語法、語義。人類之所以能在進(jìn)化的歷史長(zhǎng)河中,成為動(dòng)物中的佼佼者,進(jìn)化出的復(fù)雜的溝通機(jī)制—語言功不可沒。假如,我說出這句話:你個(gè)產(chǎn)品狗還在改需求!那么語法是啥呢?簡(jiǎn)單說就是構(gòu)成這句話的順序,假如順序錯(cuò)亂意思就不同了。那么語義是啥呢?就是語境,根據(jù)我說這句話的情景,才能解釋出你指的是誰。語法在編程語言中,表現(xiàn)出來的就是語法結(jié)構(gòu)和結(jié)合律。語義表現(xiàn)出來的就是上下文(context)。
預(yù)處理(Preprocess):處理預(yù)處理符(#),包括宏展開、頭文件引入。 詞法分析(Lexical Analysis、Tokenizer):寫出的代碼實(shí)際上就是字符串,此階段需要對(duì)字符串進(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)的中間碼。如果編譯器面向多語言,對(duì)于任意語言編譯階段后可以生成通用的中間碼,這樣編譯器就有多語言的高拓展性了。生成中間碼后再交給匯編階段,再生成與平臺(tái)相關(guān)的匯編,這樣使編譯器將平臺(tái)相關(guān)性盡量往后推移。中間碼除了做為“橋接“,對(duì)中間碼的優(yōu)化也是整個(gè)編譯過程中的關(guān)鍵優(yōu)化。 匯編(Assemble):對(duì)中間碼生成平臺(tái)具體的匯編,在這個(gè)階段添加對(duì)多個(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名字的由來。但是這樣寫指令效率還是太低,程序員們?cè)贆C(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é)是互相隔離的。比如,對(duì)于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的名字、類型、長(zhǎng)度、在文件中的偏移量(offset)等。如果想要尋址到任意section都要通過這個(gè)header table。section header table實(shí)際上是由struct構(gòu)成的數(shù)組。
.strtab放置section名、變量名,包括符號(hào)名的字符串。由于在整個(gè)結(jié)構(gòu)中,字符串的長(zhǎng)度是不定的,一般將這些字符串統(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),對(duì)鏈接沒有幫助,主要為了崩潰后分析而存在。符號(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)。相對(duì)的,符號(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ù)類型、所在類名組成的字符串,不同語言、不同編譯器對(duì)同一個(gè)函數(shù)生成的函數(shù)簽名是不一樣的,比如OC中函數(shù)簽名還要加上返回變量類型,C++中還要加上NameSpace。在鏈接的時(shí)候,過程調(diào)用符號(hào)不光是函數(shù)名,是對(duì)函數(shù)簽名處理后的結(jié)果,全局變量符號(hào)也是經(jīng)過類似用函數(shù)簽名處理后的結(jié)果。這一處理過程就是符號(hào)修飾。
fishhook
fishhook是facebook開源的重綁定Mach-O符號(hào)的庫(kù),最常用來hook C語言函數(shù),而且實(shí)際上只能重新綁定C符號(hào),因?yàn)榉?hào)修飾這一步只去掉了”_”,相當(dāng)于只針對(duì)C語言做了符號(hào)修飾。在了解了目標(biāo)文件后,重綁定就不是那么困難了。最基本的思路就是先拿到header,然后通過header拿到section header table,再找到.hash,.hash是一個(gè)用于加快訪問.symtab的哈希結(jié)構(gòu),再索引到.symtab,詳見這里,通過name去.strtab比對(duì)符號(hào)名,如果匹配就置換value。
https://docs.oracle.com/cd/E2382401/html/819-0690/chapter6-48031.html
fishhook大體實(shí)現(xiàn)原理就是這樣,只不過對(duì)Mach-O平臺(tái)特性改進(jìn)一下方案就行。在Mach-O中類似于section header table的段叫做load commands。并且Mach-O中使用二級(jí)命名空間,先分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 )對(duì)應(yīng)的.symtab struct數(shù)組的索引。nl_symbol_ptr和la_symbol_ptr section section中的reserved1字段指明對(duì)應(yīng)的indirect symbol table起始o(jì)ffset。只要從這兩個(gè)section對(duì)應(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ì)對(duì)應(yīng)一個(gè)重定位段,這些重定位段組成一個(gè)重定位表。每個(gè)重定位表項(xiàng)叫做重定位入口(Relocation Entry),它記錄了所需重定向符號(hào)所在段的offset。
靜態(tài)鏈接庫(kù)
靜態(tài)鏈接庫(kù)就是一組目標(biāo)文件,經(jīng)過壓縮、索引而成的一個(gè)文件形式。當(dāng)我們平時(shí)在使用靜態(tài)鏈接庫(kù)的時(shí)候,實(shí)際上鏈接器會(huì)根據(jù)所需的符號(hào),在庫(kù)中搜索到相應(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)鏈接庫(kù)輸入到鏈接階段,以供目標(biāo)文件識(shí)別哪些符號(hào)是動(dòng)態(tài)符號(hào)。
動(dòng)態(tài)鏈接重定位
上面已經(jīng)聊完了在鏈接階段對(duì)靜態(tài)鏈接進(jìn)行重定位,根據(jù)符號(hào)所在section的虛擬地址和所在section的offset。而動(dòng)態(tài)鏈接可以這樣重定位嗎?不行,這時(shí)動(dòng)態(tài)鏈接庫(kù)的地址還沒有確定,必須等到裝載以后操作系統(tǒng)分配。那可以等到裝載以后,確定地址后再直接進(jìn)行重定位嗎?不行,假如動(dòng)態(tài)鏈接庫(kù)被多個(gè)進(jìn)程引用,裝載時(shí)動(dòng)態(tài)鏈接庫(kù)進(jìn)行重定位,動(dòng)態(tài)鏈接庫(kù)映射到每個(gè)進(jìn)程中的虛擬地址都不一樣,動(dòng)態(tài)鏈接庫(kù)只能對(duì)一個(gè)進(jìn)程重定位,那么動(dòng)態(tài)鏈接庫(kù)就不是共享的了。那怎么搞?
通過.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)鏈接庫(kù)使用全局變量、靜態(tài)變量、引用文件外過程調(diào)用都要經(jīng)過.got。.got就像indirection table一樣,解決多進(jìn)程共享動(dòng)態(tài)鏈接庫(kù)。
這樣,動(dòng)態(tài)鏈接庫(kù)雖然在不同進(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)鏈接庫(kù)文件外符號(hào)重定位用.got就搞定了,那動(dòng)態(tài)鏈接庫(kù)文件內(nèi)符號(hào)呢?靜態(tài)鏈接同樣是在鏈接階段重定位就搞定了。動(dòng)態(tài)鏈接將絕對(duì)尋址指令更換成相對(duì)尋址指令,只要指令的offset不變,相對(duì)尋址指令就可根據(jù)當(dāng)前地址和offset得到正確的地址,這樣文件內(nèi)符號(hào)根本不需要重定位了?;谝陨蟽牲c(diǎn)的處理,代碼段在鏈接后就不需要更改了,這樣的代碼段也叫做地址無關(guān)碼(PIC),也就是說代碼段和裝載后的地址無關(guān)。
延遲綁定(PLT)
由于要跳過.got引用動(dòng)態(tài)鏈接庫(kù)的符號(hào),動(dòng)態(tài)鏈接庫(kù)比靜態(tài)鏈接庫(kù)慢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)鏈接庫(kù)中(_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)—鏈接、裝載與庫(kù)關(guān)注「ImportNew」,看技術(shù)干貨