Linux共用對象之編譯參數fPIC

来源:http://www.cnblogs.com/zc2014blog/archive/2017/08/03/7278035.html
-Advertisement-
Play Games

轉載自:http://www.cnblogs.com/cswuyg/p/3830703.html 在Linux系統中,動態鏈接文件稱為動態共用對象(DSO,Dynamic Shared Objects),簡稱共用對象,一般是以.so為擴展名的文件。在Windows系統中,則稱為動態鏈接庫(Dynam ...


轉載自:http://www.cnblogs.com/cswuyg/p/3830703.html   在Linux系統中,動態鏈接文件稱為動態共用對象(DSO,Dynamic Shared Objects),簡稱共用對象,一般是以.so為擴展名的文件。在Windows系統中,則稱為動態鏈接庫(Dynamic Linking Library),很多以.dll為擴展名。這裡只備忘Linux的共用對象。     在實現一共用對象時,最一般的編譯鏈接命令行為: 
 g++ -fPIC -shared test.cc -o lib.so
    或者是:
    g++ -fPIC test.cpp -c -o test.o
    ld -shared test.o -o lib.so
    上面的命令行中-shared表明產生共用庫,而-fPIC則表明使用地址無關代碼。PIC:Position Independent Code.         Linux下編譯共用庫時,必須加上-fPIC參數,否則在鏈接時會有錯誤提示(有資料說AMD64的機器才會出現這種錯誤,但我在Inter的機器上也出現了):
/usr/bin/ld: test.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
test.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
   如何確認一個共用對象是PIC呢?
readelf -d foo.so |grep TEXTREL 
如果上邊的shell有任何輸出,則說明這foo.so不是PIC。TEXTREL表示代碼段重定位表地址,PIC的共用對象不會包含任何代碼段重定位表。     fPIC的目的是什麼?共用對象可能會被不同的進程載入到不同的位置上,如果共用對象中的指令使用了絕對地址、外部模塊地址,那麼在共用對象被載入時就必鬚根據相關模塊的載入位置對這個地址做調整,也就是修改這些地址,讓它在對應進程中能正確訪問,而被修改到的段就不能實現多進程共用一份物理記憶體,它們在每個進程中都必須有一份物理記憶體的拷貝。fPIC指令就是為了讓使用到同一個共用對象的多個進程能儘可能多的共用物理記憶體,它背後把那些涉及到絕對地址、外部模塊地址訪問的地方都抽離出來,保證代碼段的內容可以多進程相同,實現共用。     抽離出這部分特殊的指令、地址之後,放到了一個叫做GOT(Global Offset Table)的地方,它放在數據段中,每一個進程都有獨立的一份,裡面的內容可能是變數的地址、函數的地址,不同進程它的內容很可能是不同的,這部分就是被隔離開的“地址相關”內容。模塊被載入的時候,會把GOT表的內容填充好(在沒有延遲綁定的情況下)。代碼段要訪問到GOT時,通過類似於window的call/pop/sub指令得到GOT對應項的地址。     對於模塊中全局變數的訪問,為瞭解決可執行文件跟模塊可能擁有同一個全局變數的問題(此時,模塊內的全局變數會被覆蓋為可執行文件中的全局變數),對模塊中的全局變數訪問也通過GOT間接訪問。     這樣子,每一次訪問全局變數、外部函數都需要去計算在GOT中的位置,然後再通過對應項的值訪問變數、調用函數。從運行性能上來說,比裝載時重定位要差點。裝載時重定位就是不使用fPIC參數,代碼段需要一個重定位表,在裝載時修正所有特殊地址,以後運行時不需要再有GOT位置計算和間接訪問。(但是,我在自己機子上測試,編譯鏈接共用庫時,沒法不使用fPIC參數,可能多數系統都要求必須有fPIC)     如果在裝載時就去計算GOT的內容,那麼會影響載入速度,於是就有了延遲綁定(Lazy Binding),直到用時才去填充GOT。它使用到了PLT(Procedure Linkage Table):每一項都是一小段代碼,對應於本運行模塊要引用的函數。函數調用時,先到這裡,然後再到GOT。在函數第一次被調用時,進入PLT跳到載入器,載入器計算函數的真正地址,然後將地址寫入GOT對應項,以後的調用就直接從PLT跳到GOT記錄的函數位置。這樣也減少了運行時多次調用多次計算GOT位置。     PIC的共用對象也會有重定位表,數據段中的GOT、數據的絕對地址引用,這些都是需要重定位的。
  readelf -r Lib.so
  可以看到共用對象的重定位表,.rel.dyn是對數據引用的修正,.rel.plt是對函數引用的修正。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在使用FastQC之後,如果我們發現了一些問題(序列質量不高),那麼我們該使用什麼樣的工具,去解決這些問題呢? fastx Toolkit是包含處理fastq/fasta文件的一系列的工具,它是基於java開發的,我們高通量測序最常用到的是使用這個軟體進行reads的裁剪(trim) FASTQ-t ...
  • 前面說了,我們要儘量少用GNOME圖形界面,而應該以使用BASH命令行為主。 SHELL Shell是操作系統內核的殼,因為我們不能直接操作系統的內核Kernel,只能通過Shell去操作,Shell可以簡單理解為用戶向操作系統發送指令的代理。 看下麵兩張圖。 GNOME指的是圖形界面,BASH就是 ...
  • 一、編譯安裝Apache 1、解決依賴關係 (1)編譯安裝apr (2)編譯安裝apr-util (3)httpd-2.4.27編譯過程也要依賴於pcre-devel軟體包,需要事先安裝 (4)創建用戶,組 2、編譯安裝httpd-2.4.27 3、配置Apache 二、編譯安裝Mysql 1、準備 ...
  • 一.背景由來 需求經常變化,每次都要發給相關人員查看,本地查看還需要設置相容性,太麻煩了。因此考慮是否可以利用伺服器來實時更新原型文件了。 二.相關準備 首先需要一臺閑置伺服器,(其實只要幾g的空間足夠。) 其他就是相關文件準備了,Tomcat,jdk等等。 三.具體搭建 1.安裝jdk a.在官網 ...
  • 利用awk分析data.csv中label列各取值的分佈. 在終端執行head data.csv查看數據: 因為行內包含換行符的項會被分成多行(例如上面的第3,4行),所以需要結合正則匹配 -F ',' 表示根據逗號分隔; $(NF-1)~/^[A-Z][0-9]/ 表示分隔後的倒數第二項(在此指取 ...
  • CentOS系統上使用rpm命令管理程式包:安裝、卸載、升級、查詢、校驗、資料庫維護 1.基本安裝 2.rpm選項 3.軟體包腳本 4.軟體包的升級 升級時的註意事項: 不要對內核進行升級操作,linux支持多內核並存,所以直接安裝新內核就好. 如果升級時原程式的配置文件被更改過的話,新程式不會覆蓋 ...
  • 1、下載fastqc 2、解壓 3、 給予執行許可權,否則執行的時候會顯示沒有許可權 cd FastQCchmod 755 fastqc 4、加入到PATH export PATH=/home/h/FastQC/:$PATH 4、加入到PATH 5、測試 fastqc --help 5、測試 使用例子 ...
  • 1.來源 開始我還不知道cron到底來源於哪裡,不求甚解的我也沒做過多瞭解,現在突然用到所以寫一下。 cron計劃任務 其實只是linux 一個執行計劃的一個工具或者執行程式。 在Linux系統中,計劃任務一般是由cron承擔,我們可以把cron設置為開機時自動啟動。cron啟動後,它會讀取它的所有 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...