當(dāng)我們的程序中有經(jīng)常使用的模塊,而且這種模塊在其他程序中也會用到,這時(shí)按照軟件重用的思想,我們應(yīng)該將它們生成庫,使得以后編程可以減少開發(fā)代
碼量。這里介紹兩個(gè)命令ar和nm,用來對庫操作。
1、ar基本用法
ar命令可以用來創(chuàng)建、修改庫,也可以從庫中提出單個(gè)模塊。庫是一單獨(dú)的文
件,里面包含了按照特定的結(jié)構(gòu)組織起來的其它的一些文件(稱做此庫文件的member)。原始文件的內(nèi)容、模式、時(shí)間戳、屬主、組等屬性都保留在庫文件
中。
下面是ar命令的格式:
ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername]
[count] archive files...
例如我們可以用ar rv libtest.a hello.o
hello1.o來生成一個(gè)庫,庫名字是test,鏈接時(shí)可以用-ltest鏈接。該庫中存放了兩個(gè)模塊hello.o和hello1.o。選項(xiàng)前可以有
‘-’字符,也可以沒有。下面我們來看看命令的操作選項(xiàng)和任選項(xiàng)。現(xiàn)在我們把{dmpqrtx}部分稱為操作選項(xiàng),而[abcfilNoPsSuvV]部
分稱為任選項(xiàng)。
{dmpqrtx}中的操作選項(xiàng)在命令中只能并且必須使用其中一個(gè),它們的含義如下:
d:從庫中刪除模塊。按模塊
原來的文件名指定要刪除的模塊。如果使用了任選項(xiàng)v則列出被刪除的每個(gè)模塊。
m:該操作是在一個(gè)庫中移動成員。當(dāng)庫中如果有若干模塊有相同的
符號定義(如函數(shù)定義),則成員的位置順序很重要。如果沒有指定任選項(xiàng),任何指定的成員將移到庫的最后。也可以使用’a’,’b’,或’I’任選項(xiàng)移動到
指定的位置。
p:顯示庫中指定的成員到標(biāo)準(zhǔn)輸出。如果指定任選項(xiàng)v,則在輸出成員的內(nèi)容前,將顯示成員的名字。如果沒有指定成員的名字,所
有庫中的文件將顯示出來。
q:快速追加。增加新模塊到庫的結(jié)尾處。并不檢查是否需要替換。’a’,’b’,或’I’任選項(xiàng)對此操作沒有影
響,模塊總是追加的庫的結(jié)尾處。如果使用了任選項(xiàng)v則列出每個(gè)模塊。 這時(shí),庫的符號表沒有更新,可以用’ar
s’或ranlib來更新庫的符號表索引。
r:在庫中插入模塊(替換)。當(dāng)插入的模塊名已經(jīng)在庫中存在,則替換同名的模塊。如果若干模塊中
有一個(gè)模塊在庫中不存在,ar顯示一個(gè)錯(cuò)誤消息,并不替換其他同名模塊。默認(rèn)的情況下,新的成員增加在庫的結(jié)尾處,可以使用其他任選項(xiàng)來改變增加的位置。
t:顯示庫的模塊表清單。一般只顯示模塊名。
x:從庫中提取一個(gè)成員。如果不指定要提取的模塊,則提取庫中所有的模塊。
下面在看看可與操作選項(xiàng)結(jié)合使用的任選項(xiàng):
a:在庫的一個(gè)已經(jīng)存在的成員后面增加一個(gè)新的文件。如果使用任選項(xiàng)a,則應(yīng)該為命
令行中membername參數(shù)指定一個(gè)已經(jīng)存在的成員名。
b:在庫的一個(gè)已經(jīng)存在的成員前面增加一個(gè)新的文件。如果使用任選項(xiàng)b,則應(yīng)該
為命令行中membername參數(shù)指定一個(gè)已經(jīng)存在的成員名。
c:創(chuàng)建一個(gè)庫。不管庫是否存在,都將創(chuàng)建。
f:在庫中截短指
定的名字。缺省情況下,文件名的長度是不受限制的,可以使用此參數(shù)將文件名截短,以保證與其它系統(tǒng)的兼容。
i:在庫的一個(gè)已經(jīng)存在的成員前
面增加一個(gè)新的文件。如果使用任選項(xiàng)i,則應(yīng)該為命令行中membername參數(shù)指定一個(gè)已經(jīng)存在的成員名(類似任選項(xiàng)b)。
l:暫未使
用
N:與count參數(shù)一起使用,在庫中有多個(gè)相同的文件名時(shí)指定提取或輸出的個(gè)數(shù)。
o:當(dāng)提取成員時(shí),保留成員的原始數(shù)
據(jù)。如果不指定該任選項(xiàng),則提取出的模塊的時(shí)間將標(biāo)為提取出的時(shí)間。
P:進(jìn)行文件名匹配時(shí)使用全路徑名。ar在創(chuàng)建庫時(shí)不能使用全路徑名
(這樣的庫文件不符合POSIX標(biāo)準(zhǔn)),但是有些工具可以。
s:寫入一個(gè)目標(biāo)文件索引到庫中,或者更新一個(gè)存在的目標(biāo)文件索引。甚至對于沒
有任何變化的庫也作該動作。對一個(gè)庫做ar s等同于對該庫做ranlib。
S:不創(chuàng)建目標(biāo)文件索引,這在創(chuàng)建較大的庫時(shí)能加快時(shí)間。
u:一般說來,命令ar
r…插入所有列出的文件到庫中,如果你只想插入列出文件中那些比庫中同名文件新的文件,就可以使用該任選項(xiàng)。該任選項(xiàng)只用于r操作選項(xiàng)。
v:該選項(xiàng)用來顯示執(zhí)行操作選項(xiàng)的附加信息。
V:顯示ar的版本。
2、nm基本用法命令
nm用來列出目標(biāo)文件的符號清單。下面是nm命令的格式:
nm [-a|--debug-syms]
[-g|--extern-only] [-B][-C|--demangle] [-D|--dynamic]
[-s|--print-armap][-o|--print-file-name]
[-n|--numeric-sort][-p|--no-sort] [-r|--reverse-sort]
[--size-sort][-u|--undefined-only] [-l|--line-numbers]
[--help][--version] [-t radix|--radix=radix][-P|--portability] [-f
format|--format=format][--target=bfdname] [objfile...]
如果沒有為nm命令指出目
標(biāo)文件,則nm假定目標(biāo)文件是a.out。下面列出該命令的任選項(xiàng),大部分支持“-”開頭的短格式和“—“開頭的長格式。
-A、-o或
--print-file-name:在找到的各個(gè)符號的名字前加上文件名,而不是在此文件的所有符號前只出現(xiàn)文件名一次。
例如nm
libtest.a的輸出如下:
CPThread.o:
00000068 T Main__8CPThreadPv
00000038 T Start__8CPThread
00000014 T _._8CPThread
00000000 T
__8CPThread
00000000 ? __FRAME_BEGIN__
…………………………………
則nm
–A 的輸出如下:
libtest.a:CPThread.o:00000068 T Main__8CPThreadPv
libtest.a:CPThread.o:00000038 T Start__8CPThread
libtest.a:CPThread.o:00000014 T _._8CPThread
libtest.a:CPThread.o:00000000 T __8CPThread
libtest.a:CPThread.o:00000000 ? __FRAME_BEGIN__
…………………………………………………………
-a或--debug-syms:顯示調(diào)試符號。
-B:等同于
--format=bsd,用來兼容MIPS的nm。
-C或--demangle:將低級符號名解碼(demangle)成用戶級名字。這
樣可以使得C++函數(shù)名具有可讀性。
-D或--dynamic:顯示動態(tài)符號。該任選項(xiàng)僅對于動態(tài)目標(biāo)(例如特定類型的共享庫)有意義。
-f format:使用format格式輸出。format可以選取bsd、sysv或posix,該選項(xiàng)在GNU的nm中有用。默認(rèn)為bsd。
-g或--extern-only:僅顯示外部符號。
-n、-v或--numeric-sort:按符號對應(yīng)地址的順序排序,而非按符號
名的字符順序。
-p或--no-sort:按目標(biāo)文件中遇到的符號順序顯示,不排序。
-P或--portability:使
用POSIX.2標(biāo)準(zhǔn)輸出格式代替默認(rèn)的輸出格式。等同于使用任選項(xiàng)-f posix。
-s或--print-armap:當(dāng)列出庫中成員的
符號時(shí),包含索引。索引的內(nèi)容包含:哪些模塊包含哪些名字的映射。
-r或--reverse-sort:反轉(zhuǎn)排序的順序(例如,升序變?yōu)榻?
序)。
--size-sort:按大小排列符號順序。該大小是按照一個(gè)符號的值與它下一個(gè)符號的值進(jìn)行計(jì)算的。
-t
radix或--radix=radix:使用radix進(jìn)制顯示符號值。radix只能為“d”表示十進(jìn)制、“o”表示八進(jìn)制或“x”表示十六進(jìn)制。
--target=bfdname:指定一個(gè)目標(biāo)代碼的格式,而非使用系統(tǒng)的默認(rèn)格式。
-u或--undefined-only:僅顯示
沒有定義的符號(那些外部符號)。
-l或--line-numbers:對每個(gè)符號,使用調(diào)試信息來試圖找到文件名和行號。對于已定義的符
號,查找符號地址的行號。對于未定義符號,查找指向符號重定位入口的行號。如果可以找到行號信息,顯示在符號信息之后。
-V或
--version:顯示nm的版本號。
--help:顯示nm的任選項(xiàng)。
3、示例
1)、創(chuàng)建靜態(tài)庫:
gcc -c hello.c -o hello.o
ar rcs libhello.a hello.o
2)、使用靜態(tài)庫:
gcc -o test test.c
-static -L. -lhello
3)、共享庫版本: version.minor.release
4)、構(gòu)建動態(tài)共享庫:
gcc/g++下加 -fPIC -shared 參數(shù)即可
其中 -fPIC
作用于編譯階段,告訴編譯器產(chǎn)生與位置無關(guān)代碼(Position-Independent
Code),則產(chǎn)生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內(nèi)存的任意位置,都可以正確的執(zhí)行。這正是共享庫所要求的,共
享庫被加載時(shí),在內(nèi)存的位置不是固定的。
可以export LD_DEBUG=files,查看每次加載共享庫的實(shí)際地址。
其中
-shared 作用于鏈接階段,實(shí)際傳遞給鏈接器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)、動態(tài)共享庫的使用:
由共享庫加載器自動加載
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: 指定運(yùn)行時(shí)搜索動態(tài)庫的路徑,可以用環(huán)境變量LD_LIBRARY_PATH指定。
程序自己控制加載、符號解析(使
用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); // 加載動態(tài)庫
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函數(shù)
printf("The cos result
is: %f\n", rev);
dlclose(handle);
return 0;
}
6)、GNU/Linux下動態(tài)庫之加載器為/lib/ld-linux.so,
可執(zhí)行的。
/lib/ld-linux.so ./cos <===> ./cos
7)、有用的環(huán)境變
量
LD_LIBRARY_PATH
指定運(yùn)行時(shí)動態(tài)庫的搜索路徑
LD_DEBUG
調(diào)試用,其值
可為:
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函數(shù)的共享庫名
nm -AD /lib/* /usr/lib/* 2>/dev/null | grep
"cos$"
nm -- 從對象文件中列出符號。
9)、讀取ELF文件格式信息
readelf -Ds
./libfoo.so #讀出共享庫的符號
from:
http://fnstudio.blog.sohu.com/74541293.html
posted on 2010-05-06 22:32
chatler 閱讀(816)
評論(0) 編輯 收藏 引用 所屬分類:
Linux_Coding