GNU/Linux下庫機制筆記

作者: comcat 發表日期: 2006-09-08 10:44                http://comcat.blog.openrays.org/blog.php?do=showone&tid=69

1. 創建靜態庫:
gcc -c hello.c -o hello.o
ar rcs libhello.a hello.o

2. 使用靜態庫:
gcc -o test test.c -static -L. -lhello


3. 共享庫版本: version.minor.release


4. 構建動態共享庫:

gcc/g++下加 -fPIC -shared 參數即可

其中 -fPIC 作用於編譯階段,告訴編譯器產生與位置無關代碼(Position-Independent Code),
則產生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內存的任意
位置,都可以正確的執行。這正是共享庫所要求的,共享庫被加載時,在內存的位置不是固定的。
可以export LD_DEBUG=files,查看每次加載共享庫的實際地址。

其中 -shared 作用於鏈接階段,實際傳遞給鏈接器ld,讓其添加作爲共享庫所需要的額外描述
信息,去除共享庫所不需的信息。

可以分解爲如下步驟:

I. gcc -c err.c -fPIC -o err.o
II. gcc -shared -o liberr.so.0.0 err.o

II <==> ld -Bshareable -o liberr.so.0.0 err.o

III. ln -s liberr.so.0.0 liberr.so



5. 動態共享庫的使用:

a. 由共享庫加載器自動加載

gcc -o test test.c -lerr -L. -Wl,-rpath=./

-Wl,option
Pass option as an option to the linker. If option contains commas,
it is split into multiple options at the commas.

-rpath: 指定運行時搜索動態庫的路徑,可以用環境變量LD_LIBRARY_PATH指定。


b. 程序自己控制加載、符號解析(使用libc6之dl庫)

gcc cos.c -o cos -ldl

/* cos.c */
#include <stdio.h>
#include <dlfcn.h>

int main()
{
void *handle;
double (*cosine)(double);
char *error;
double rev;

handle = dlopen("libm.so", RTLD_LAZY); // 加載動態庫
if(!handle)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}

dlerror();

cosine = dlsym(handle, "cos"); // 解析符號cos
if((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
exit(1);
}

rev = cosine(3.1415926); // 使用cos函數
printf("The cos result is: %f\n", rev);

dlclose(handle);

return 0;
}




6. GNU/Linux下動態庫之加載器爲/lib/ld-linux.so, 可執行的。

/lib/ld-linux.so ./cos <===> ./cos


7. 有用的環境變量

LD_LIBRARY_PATH

指定運行時動態庫的搜索路徑

LD_DEBUG

調試用,其值可爲:

libs display library search paths
reloc display relocation processing
files display progress for input file
symbols display symbol table processing
bindings display information about symbol binding
versions display version dependencies
all all previous options combined
statistics display relocation statistics
unused determined unused DSOs
help display this help message and exit


8. 搜索含有cos函數的共享庫名

nm -AD /lib/* /usr/lib/* 2>/dev/null | grep "cos$"

nm -- 從對象文件中列出符號。


9. 讀取ELF文件格式信息

readelf -Ds ./libfoo.so #讀出共享庫的符號

發佈了1 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章