如何讓ubuntu12.04(64 bit)下面編譯的程序能在10.04下成功運行

大概可以按照以下步驟進行:

1. 分析那些函數用的是10.04下沒有的glibc的版本

通常12.04下編譯的程序在10.04下運行報glibc2.14沒找到的錯誤,這裏就要找出那個函數用了2.14版本。以應用程序guard爲例

objdump -T guard | grep 2.14

得知時memcpy(),通過網絡查詢得知,memcpy()史上曾經有個較大變動,很不幸,就發生在libc2.14和libc2.2.5(10.04的glibc缺省版本)之間

2. 想辦法讓memcpy靜態鏈接

首先從/usr/lib/x86_64-linux-gnu/libc.a將libc.a拷貝出來,放到一個目錄dir下,

然後抽取出memcpy.o/cacheinfo.o/init-arch.o

ar x memcpy.o libc.a

需要cacheinfo.o是由於memcpy.o對其有依賴,同樣cacheinfo.o對init-arch.o有依賴

3. 迫使編譯工具靜態鏈接上述挑選的obj文件

在需要鏈接的目錄的YBUILD裏頭加入如下鏈接控制項

           link_flags = ['-Wl,--start-group /private/svn/memcpy.o /private/svn/cacheinfo.o \         

                        /private/svn/init-arch.o --end-group',

                        ],

注意:這裏得用start-group和end-group的原因見後面的說明#3

 這個是對要編譯的單個程序起作用,如果希望所有的程序都這樣,那就需要修改scons下面的devel/ymake/site_scons/Cpp.py

在任何一個有link_flags的地方,加入上述選項

link_flags +=('-Wl, -start-group /private/svn/memcpy.o /private/svn/cacheinfo.o \

                        /private/svn/init-arch.o --end-group')

重新編譯就可以了

4. 如何驗證memcpy確實時靜態鏈接的,我們拿memcpy和memmove做一個對比

objdump -R guard | grep memcpy
00000000009d7bf8 R_X86_64_JUMP_SLOT  __memcpy_chk

objdump -R guard | grep memmove
00000000009d7588 R_X86_64_JUMP_SLOT  __memmove_chk
00000000009d7b88 R_X86_64_JUMP_SLOT  memmove

objdump -t guard | grep memcpy
000000000069afc4 g     F .text    0000000000000031              _ZN4base9c16memcpyEPtPKtm
0000000000441950 g     F .text    0000000000000465              memcpy
0000000000000000       F *UND*    0000000000000000              __memcpy_chk@@GLIBC_2.3.4

objdump -t guard | grep memmove
0000000000000000       F *UND*    0000000000000000              __memmove_chk@@GLIBC_2.3.4
000000000069af93 g     F .text    0000000000000031              _ZN4base10c16memmoveEPtPKtm
0000000000000000       F *UND*    0000000000000000              memmove@@GLIBC_2.2.5  ===============>未定義


說明:

1. 還有另外一種辦法是把memcpy wrap起來,然後自己實現memcpy(),在鏈接的時候也需要--wrap memcpy選項,加選項的辦法同上面的一樣

2. 如果還有其他版本不匹配的函數,則可以簡單地把gcc降級爲4.4(12.04缺省是4.6),先安裝gcc4.4,然後修改符號鏈接文件gcc指向gcc4.4

ls -al /usr/bin/gcc

lrwxrwxrwx 1 root root 7 Dec 28 13:18 /usr/bin/gcc -> gcc-4.4

3. 鏈接選項使用start-group和end-group的原因

-( archives -) or --start-group archives --end-group

The archives should be a list of archive files. They may be either explicit file names, or -l options.

The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved.

Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.

4. 如果你用的32bit的ubuntu12.04,恭喜你,你可能沒這個煩惱

/lib32$ readelf -s libc.so.6 | grep 2.14                         =============》32bit的libc.so裏頭memcpy的版本不是2.14,而是2.0的

    80: 000ef480    61 FUNC    GLOBAL DEFAULT   12 clock_adjtime@@GLIBC_2.14

   469: 0002f140    91 FUNC    GLOBAL DEFAULT   12 sigorset@@GLIBC_2.0

   551: 000efe50    75 FUNC    GLOBAL DEFAULT   12 name_to_handle_at@@GLIBC_2.14

  1042: 000eff20    61 FUNC    GLOBAL DEFAULT   12 setns@@GLIBC_2.14

  1056: 000efea0   122 FUNC    GLOBAL DEFAULT   12 open_by_handle_at@@GLIBC_2.14

  1177: 000f0bc0   192 FUNC    GLOBAL DEFAULT   12 sendmmsg@@GLIBC_2.14

  1184: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS GLIBC_2.14

  1415: 000e8170    57 FUNC    GLOBAL DEFAULT   12 syncfs@@GLIBC_2.14

  2014: 0014ae80   128 FUNC    GLOBAL DEFAULT   13 __libc_freeres@@GLIBC_2.1

  2114: 000f2710    19 FUNC    WEAK   DEFAULT   12 mcount@@GLIBC_2.0

  2214: 00034400    69 FUNC    GLOBAL DEFAULT   12 __strtoull_internal@@GLIBC_2.0

  2314: 0007d110   120 FUNC    GLOBAL DEFAULT   12 _obstack_free@@GLIBC_2.0

readelf -s libc.so.6 | grep memcpy

   352: 00098290    51 FUNC    WEAK   DEFAULT   12 wmemcpy@@GLIBC_2.0

   357: 00082da0    70 FUNC    GLOBAL DEFAULT   12 __memcpy_by2@@GLIBC_2.1.1

   363: 00082d60    51 FUNC    GLOBAL DEFAULT   12 __memcpy_by4@@GLIBC_2.1.1

   851: 00083da0    48 FUNC    GLOBAL DEFAULT   12 __memcpy_c@@GLIBC_2.1.1

   868: 00082df0    59 FUNC    GLOBAL DEFAULT   12 __memcpy_g@@GLIBC_2.1.1

  1069: 00104760    62 FUNC    GLOBAL DEFAULT   12 __wmemcpy_chk@@GLIBC_2.4

  1193: 0007f530    70 IFUNC   GLOBAL DEFAULT   12 memcpy@@GLIBC_2.0

  1722: 00101560    70 IFUNC   GLOBAL DEFAULT   12 __memcpy_chk@@GLIBC_2.3.4

 而64bit就不一樣,用的時2.14的

/lib/x86_64-linux-gnu$ readelf -s libc.so.6 | grep 2.14
    70: 0000000000182b14     4 OBJECT  GLOBAL DEFAULT   15 _sys_nerr@@GLIBC_2.12
    74: 00000000000f4200    37 FUNC    GLOBAL DEFAULT   12 clock_adjtime@@GLIBC_2.14
   515: 00000000000f4900    40 FUNC    GLOBAL DEFAULT   12 name_to_handle_at@@GLIBC_2.14
   967: 00000000000f4990    37 FUNC    GLOBAL DEFAULT   12 setns@@GLIBC_2.14
   981: 00000000000f4930    94 FUNC    GLOBAL DEFAULT   12 open_by_handle_at@@GLIBC_2.14
  1094: 00000000000f5b10   157 FUNC    GLOBAL DEFAULT   12 sendmmsg@@GLIBC_2.14
  1100: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS GLIBC_2.14
  1107: 00000000000917e0    60 IFUNC   GLOBAL DEFAULT   12 memcpy@@GLIBC_2.14
  1310: 00000000000ed290    37 FUNC    GLOBAL DEFAULT   12 syncfs@@GLIBC_2.14
  1944: 0000000000182b14     4 OBJECT  GLOBAL DEFAULT   15 sys_nerr@@GLIBC_2.12
  2014: 00000000000bb3f0    70 FUNC    GLOBAL DEFAULT   12 ntp_gettime@@GLIBC_2.2.5
  2114: 00000000000e70a0    37 FUNC    GLOBAL DEFAULT   12 __pipe@@GLIBC_2.2.5
/lib/x86_64-linux-gnu$ readelf -s libc.so.6 | grep memcpy
   329: 00000000000a1530     9 FUNC    WEAK   DEFAULT   12 wmemcpy@@GLIBC_2.2.5
   993: 000000000010ba20    27 FUNC    GLOBAL DEFAULT   12 __wmemcpy_chk@@GLIBC_2.4
  1107: 00000000000917e0    60 IFUNC   GLOBAL DEFAULT   12 memcpy@@GLIBC_2.14
  1109: 000000000008bbc0    71 IFUNC   GLOBAL DEFAULT   12 memcpy@GLIBC_2.2.5
  1599: 0000000000108190    60 IFUNC   GLOBAL DEFAULT   12 __memcpy_chk@@GLIBC_2.3.4

5. 嘗試過其他方法,但都繞不過memcpy使用2.14版本的問題

比如鏈接選項加入“-static-libstd++“或者”-static-libgcc','-static'是想所有的都靜態鏈接,但最終鏈接報錯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章