歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> GNUC庫----調試系統問題並進行修訂

GNUC庫----調試系統問題並進行修訂

日期:2017/3/6 15:47:56   编辑:關於Unix
一種調試 glibc 函數的好方法是用您自己的版本覆蓋所關注的函數。在沒有 root 許可權和不必重新編譯 libc 源代碼的情況下就可以完成這個任務。想象一下編寫您自己的 open() 版本該有多激動啊! 如果您沒有應用程序的源代碼並且由於 C 的 GNU 庫(glibc)函數
  一種調試 glibc 函數的好方法是用您自己的版本覆蓋所關注的函數。在沒有 root 許可權和不必重新編譯 libc 源代碼的情況下就可以完成這個任務。想象一下編寫您自己的 open() 版本該有多激動啊!
  
  如果您沒有應用程序的源代碼並且由於 C 的 GNU 庫(glibc)函數正將某些錯誤信息返回給該應用程序而使它失敗,那麼您該怎麼辦?因為 glibc 是開放源碼,所以您當然可以獲得其源代碼、對它進行更改、重新構建和安裝。然而,這不適合那些膽怯的人,因為雖然 API 有很好的文檔說明,但 GNU C 庫的內部組織卻沒有。查找正確的函數原型只是眾多挑戰中的第一個。它還是一個很大的包,所以第一次編譯時,它將花一些時間(glibc 2.2.2 有 8552 個文件和 1775440 行代碼,包括注釋)。
  
  更好的方法
  比重新構建 glibc 更好的方法是選擇性地覆蓋一個函數。許多現代的 Unix 都支持預裝入用戶定義庫這一概念。這些庫可以是完整的替代(即,glibc 的專用版本)也可以是子集 — 甚至是一個函數。首先,通過設置 LD_LIBRARY_PATH 來包含庫的專用版本,您可以使用 glibc 的專用版本。可通過使用 LD_PRELOAD 環境值來使用您編寫的庫例程的子集。LD_LIBRARY_PATH 和 LD_PRELOAD 都是由動態 ELF 鏈接器/裝入器控制的。它使用第一個匹配來滿足任何符號名。通過預裝入您自己的庫或函數版本,您“短路”了正常路徑,這樣就允許您覆蓋它。
  
  這裡是一個示例 makefile,它覆蓋 glibc 函數 setresgid():
  
  覆蓋 setresgid() 的 Makefile
   #
   # Makefile
   #
  
   all: libs setresgid-tester
  
   #
   # Make a shared Library
   #
   libs: libfuncs.c
       gcc -shared -Wl,-soname,libfuncs.so.1 -o libfuncs.so.1.0 libfuncs.c
       ln -s libfuncs.so.1.0 libfuncs.so.1
       ln -s libfuncs.so.1 libfuncs.so
  
   #
   # Here is a program that calls setresgid() for testing
   #
   setresgid-tester: setresgid-tester.c
       gcc -o setresgid-tester setresgid-tester.c
  文件 libfuncs.c 包含我的 setresgid() 專用版本。實現它以支持與原始 setresgid() 相同的參數數目時要小心,並在其它方面完成與原始 setresgid() 相同的操作,盡管我的版本欺騙該應用程序並始終返回 0。
  
  關注的第二個文件是 setresgid-tester.c。它通過調用 setresgid() 試驗新函數。
  
  這是動態庫的源代碼:
  
  替換庫
   /*
   Put all the functions you want to override here
   */
   #include
   #include
   #include
  
   int errno;
  
   int
   setresgid(rgid, egid, sgid)
       gid_t rgid,egid,sgid;
   {
    errno=1;
    printf("It me the shim, Hi there!\n");
    return(0);
  
   }
  
  您還需要一個簡單方法來測試您的 setresgid() 專用版本。可以使用 strace 或 ltrace 來監視進程運行。這是普通測試示例的源代碼:
  
  普通測試示例
   /*
    setresgid() system/library call tester
   */
   #include
   #include
   main(){
    setresgid(0,0,0);
   }
  
  現在,編譯該庫,設置 LD_PRELOAD shell 變量,然後運行測試應用程序。您可能還需要設置 LD_LIBRARY_PATH。
  
  運行測試應用程序
  export LD_PRELOAD=libfuncs.so
  export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
  ./setresgid-tester
  It's me the shim, Hi there!
  
  還可以通過使用 ldd 列出動態鏈接庫來確認是否正在使用專用庫:
  
  確認專用庫的使用
  [jay@prion ld_preload]$ ldd setresgid-tester
      libfuncs.so => libfuncs.so (0x40018000)
      libc.so.6 => /lib/libc.so.6 (0x40022000)
      /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  結束語
  編寫 GNU C 庫函數的專用版本是調試系統問題或進行快速修正的好方法。使用 LD_PRELOAD shell 變量,可以選擇性地用您自己的專用版本來覆蓋系統 C 庫函數。這種技術可用於 Linux 和 Solaris 環境。

Copyright © Linux教程網 All Rights Reserved