中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C程序中讓兩個不同版本的庫共存

發布時間:2020-10-03 15:43:20 來源:網絡 閱讀:505 作者:重歸混沌 欄目:編程語言

原文連接:http://blog.gotocoding.com/archives/875


今天有同學提出,如何在一個C程序中讓兩個不同版本的庫共存。


首先想到的方案是,把其中一個版本的庫函數全部重命名,比如把每一個函數名都加一個_v2的后綴。

人工替換到沒什么,但是如果函數個數超過10個,就有點不拿人當人使了。


而使有工具去替換就會遇到一些棘手的問題,如何識別哪些是函數,哪些是系統函數(系統函數不需要添加后綴)等。


隨后想到的另一個解決方案是C++的方案,為其中一個版本庫中的所有文件添加命名空間。然后使用g++將這部分代碼編譯成.o文件,之后再使用gcc將這些.o文件與整個程序中的其他代碼進行鏈接。


不過需要注意的是,g++編譯后所有導出接口名都會變化得不那么直觀。



第三種方案完全解決了以上兩種方案的痛點。


考慮一個C語言的編譯鏈接過程。


首先會將每個c文件編譯成.o文件。


在編譯過程中,導出函數并不會被實際分配地址,而是將函數名以F符號的方式存在.o文件的符號表中。


在本c文件調用的函數如果不存在于本文件,也會生成一個UND的符號存在.o文件的符號表中。


在鏈接過程中,鏈接器接收輸入的.o文件,為每個.o文件中的符號分存地址,并生成可執行文件。


有了這幾點事實,問題就變得的簡單多了。


首先將其中一個版本的庫中所有代碼編譯為.o文件。然后收集所有.o文件中的F符號。


由于整個庫代碼有內部依賴關系,收集到的F符號必然是所有.o文件中UND符號的超集。


換句話說,所有的F符號名就是我們要重命名的所有函數名。


這里我們需要借助objdump和objcopy工具。objdump -t 用于列表.o文件的符號表,objcopy用于重命名符號。


我隨手寫了一段用于過慮F符號的lua腳本

1
2
3
4
5
6
7
8
9
10
11
12
13
--rename.lua
local list = {}
local reg = "([^%s]+)%s+([^%s]+)%s+([^%s]+)"..
        "%s+([^%s]+)%s+([^%s]+)%s+([^%s]+)"
for l in io.stdin:lines() do
        local a,b,c,d,e,f = string.match(l, reg)
        if a and c == "F" then
                list[#list + 1] = " --redefine-sym "
                list[#list + 1] = string.format("%s=%s_v2", f, f)
        end
end
print("#/bin/sh")
print("objcopy " .. table.concat(list) .. " $1")

我們可以使用如下命令來收集所有.o文件的F符號, 并產生修改符號所用的腳本

1
find . -name '*.o' | xargs objdump -t | ./lua rename > rename.sh

現在我們只需要再執行一條命令就可以把所有函數名增加一個_v2的后綴.

1
find . -name '*.o' | xargs -n 1 sh ./rename.sh

至此,我們這個版本的庫代碼的所有函數名已經全部增加了_v2后綴。

這些被處理過的.o文件與我們將所有.c代碼中函數名重命名之后編譯出的.o文件完全一等價。


8月2號補充:

在實際使用中發現, 局部函數(static 函數)符號有可能會被gcc做修飾,將被修飾的符號重命名會給我們帶來一些麻煩,而我們原本也不需要去處理局部函數。


因此對rename.lua做如下修改,過慮掉非全局符號:

1
2
3
4
5
6
7
8
9
10
11
12
13
--rename.lua
local list = {}
local reg = "([^%s]+)%s+([^%s]+)%s+([^%s]+)"..
        "%s+([^%s]+)%s+([^%s]+)%s+([^%s]+)"
for l in io.stdin:lines() do
        local a,b,c,d,e,f = string.match(l, reg)
        if a and c == "F" and b == "g" then
                list[#list + 1] = " --redefine-sym "
                list[#list + 1] = string.format("%s=%s_v2", f, f)
        end
end
print("#/bin/sh")
print("objcopy " .. table.concat(list) .. " $1")


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

崇仁县| 二手房| 林西县| 吉隆县| 建瓯市| 尤溪县| 岳西县| 莎车县| 连平县| 惠安县| 舞阳县| 冕宁县| 乌兰察布市| 英吉沙县| 浦江县| 威信县| 吴江市| 漯河市| 楚雄市| 曲松县| 车险| 秦皇岛市| 泌阳县| 临颍县| 鹤峰县| 黄山市| 教育| 克拉玛依市| 综艺| 江达县| 铅山县| 姜堰市| 黎平县| 广东省| 喀喇沁旗| 泽库县| 古丈县| 辽中县| 顺平县| 兴宁市| 班玛县|