2013-03-11 87 views
2

我正在處理鏈接幾個靜態庫的iOS應用程序。挑戰在於,這些鏈接庫定義了不同實現的相同方法名稱。奇怪的是,我沒有得到任何duplicate symbol definition錯誤;但毫不奇怪,我最終只能訪問該方法的一個實現。在靜態iOS庫中重寫符號

更清楚,說我有力霸和libB,他們都定義一個全局的C法稱爲FUNC1()

當我鏈接都力霸和libB,做出FUNC1(通話),它解析到libA或libB的實現,沒有任何編譯警告。但是,我需要能夠分別訪問libA的func1()和libB的func1()。

There's a similar SO post,解釋它如何可以在C完成(通過符號重命名),但不幸的是,我發現,objcopy工具不會對ARM架構(因此iPhone)工作。

(我將它提交到App Store,因此,動態鏈接不是一個選項)

+0

如果你有任何庫的源代碼,那麼解決方案是顯而易見的。或者,你可以使用'lipo'將兩個庫打包成一個,如果我的內存不足,應該只保留其中一個符號。 – 2013-03-11 18:09:36

+0

謝謝@ RichardJ.RossIII,但我沒有源代碼,不確定你的建議會有幫助,因爲我想分開保存這些符號,我需要它們兩個,我不想將它們還原爲一個符號 – 2013-03-11 19:19:02

+0

我會比如說使用'dlopen'和'dlsym'動態地分別加載符號,但不幸的是,現在蘋果禁止使用這些符號,這將不起作用。我不是''.a'文件結構的專家,但我有一種感覺,可以通過十六進制編輯器手動執行此操作。讓我嘗試一下,我會看看我能否幫助你。 – 2013-03-11 19:24:37

回答

2

看來,你是幸運的 - 你仍然可以使用ARM二進制格式命名的符號,它只是有點更哈克比objcopy方法...

注意:這只是最低限度了測試,我強烈建議你嘗試在此之前做好備份所有庫的的問題!

另請注意,這僅適用於未使用C++編譯器編譯的文件!如果在這些文件上使用C++編譯器,則此失敗。

  1. 首先,您將需要一個體面的十六進制編輯器,在這個例子中,我將使用Hex Fiend
  2. 接下來,你會打開你的庫的副本,讓我們稱之爲lib1-renamed.a,並用它做了以下內容:

    • 查找符號的你希望的名字重新命名。可以使用nm工具找到它,或者,如果您知道標題名稱,則應該設置它。接下來,您將使用十六進制惡魔,並對舊名稱進行文本替換(在本例中爲foo),併爲其指定一個新名稱(在此例中爲bar)。這些名字必須具有相同的長度,否則會破壞二進制的偏移量!

      注意:如果有多個函數包含foo的名稱,則可能有問題。現在

  3. ,你必須編輯你改變了圖書館的頭,使用新的函數名(bar),而不是舊的。

如果你已經完成了三個簡單的以上步驟正確,你現在應該能夠成功編譯&鏈接的兩個文件,並呼籲雙方實現。

如果你想用一個通用二進制做到這一點(例如,一個仿真器上的作品也一樣),你最好關閉使用lipo兩個二進制文件分開,使用了i386/X64二進制objcopy,然後在ARM二進制上使用我的方法,並將其與lipo重新組合。

†:不保證簡單性,理查德J.羅斯三世超級保修也不保證。有關超級保修的更多信息,請立即致電1-800-FREE-WARRANTY。那現在是1-800-FREE-WARRANTY!

+0

明天測試這個第一件事,非常感謝你的努力(和你的腳註更多!):) – 2013-03-11 20:48:40

+1

@EgeAkpinar不要忘記你的免費超級保證! – 2013-03-11 20:51:20

+0

事實證明,我不需要保修,因爲它像一個魅力。我曾嘗試重命名,但錯過了我應該重新命名爲相同的長度。非常感謝! – 2013-03-12 10:18:06