天天看點

linux elf指令,實戰:Linux上修改ELF檔案的方法

7zip/bin/7za x -y -bd "-o/temp/94ac6fe8-1a16-43d8-8fa9-c4e2f2bd0445" "/downloadedPackageDir/package.zip"來解壓

7zip/bin/7za -mm=lzma -mx9 -r -a mac64.zip來重新壓縮,以符合某些内部規定。在linux上,隻找到32位版本的7zip,有可能有64位,沒找到,-mx9報錯,ERROR: Can't allocate required memory! 于是把-mx9改成-mmt4暫時work around.

curl -o localPath https://serverPath來下載下傳

curl -u ****:**** -X PUT https://serverPath -T localPath來上傳。

解決這些問題後。本地Linux跑過,嘗試AWS機器,發現不行,報錯。

14:09:13/mnt/data/jenkins/workspace/3PUploadLinux/7zip/bin/7za x -y -bd "-o/mnt/data/jenkins/workspace/3PUploadLinux/temp/984fa08a-a187-434b-bb7a-666b22c86526" "/mnt/data/jenkins/workspace/3PUploadLinux/downloadedPackageDir/package.zip"

14:09:13Traceback (most recent call last):

14:09:13 File "/mnt/data/jenkins/workspace/3PUploadLinux/upload.py", line 124, in

14:09:13 ret_code = main()

14:09:13 File "/mnt/data/jenkins/workspace/3PUploadLinux/upload.py", line 84, in main

14:09:13 ret_code = subprocess.call(shlex.split(commandline), stdout = outputfile)

14:09:13 File "/usr/lib64/python2.7/subprocess.py", line 524, in call

14:09:13 return Popen(*popenargs, **kwargs).wait()

14:09:13 File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__

14:09:13 errread, errwrite)

14:09:13 File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child

14:09:13 raise child_exception

14:09:13OSError: [Errno 2] No such file or directory

也不知道哪個檔案找不到,懷穎很多問題,還有權限,後來幹脆直接調指令。

7zip/bin/7za: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

發現問題在于/lib/ld-linux.so.2沒有。這個網上說yum install glibc.i686就可以解決,但是遠端的AWS機器,根本沒有權限,怎麼辦。于是想到把本地Linux上的檔案弄出來.lld binary可以看到目标加載的檔案在哪裡。在Linux上,有叫SHARE LIBRARY的庫,也有一個叫解釋器的。可能類似MAC上的dyld,但是還沒完全搞透。暫且當成是普通的library吧。在一台Linux上操作git沒有UI也難受,把檔案傳上來以後,需要7zip能加載同路徑的新檔案。這涉及到Linux上有ELF格式修改。一直都沒涉獵這塊,之前隻有PE和MACHO的經驗。又不想讀檔案自己寫工具,于是找一下有沒有Linux版本的install_name_tool。于是在

找到了我要的,patchelf工具。這個是帶源碼的,自己編譯。

wget https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.gz

tar -zxf patchelf-0.9.tar.gz

cd patchelf-0.9

./configure --prefix=/usr

make && make install

這樣patchelf 就可以用了.

patchelf --print-interpreter 可以得到和readelf -l類似的結果,得到解釋器的路徑

patchelf --print-rpath可以得到rpath路徑。

于是用patchelf --set-rpath和 patchelf --set-interpreter來修改解釋器和查找路徑。最後終于能得到一個在AWS機器上能跑的版本。lld 可以在本地測試,但是發現還是用的/lib/ld-linux.so.2,遠端不讓運作lld指令,隻好直接試。最後成功完成任務。

檢視RPATH

對于任意的elf檔案,可以使用$ readelf -d xxx | grep 'R*PATH'來檢視。

結果有兩類,一個是RPATH,另一個是RUNPATH。前文也說了,一般情況下,RPATH為空,而RUNPATH不為空。

RPATH中有個特殊的辨別符$ORIGIN。這個辨別符代表elf檔案自身所在的目錄。當希望使用相對位置尋找.so檔案,就需要利用$ORIGIN設定RPATH。多個路徑之間使用冒号:隔開。

還未進行嘗試,先記錄一下。