动态连接库和符号(symbol)

合集下载

大学电路同名端的判定方法

大学电路同名端的判定方法

大学电路同名端的判定方法大学电路中,同名端的判定方法可以通过以下几种方式来进行:1. 端口标注法(Port labeling method):这是最常用的一种判定方法。

在大多数电路图中,每个元件的端口都会被标注上符号,如V、A、B等。

当两个元件的端口标注相同时,即可判定它们为同名端。

例如,当电路图中一个电压源的正极被标注为V,而一个电阻的一端也被标注为V时,就可以认为它们是同名端。

这种方法简单明了,容易理解和操作。

2. 连接关系法(Connection method):这种方法主要适用于复杂的电路图,通过观察元件之间的连接关系来判定同名端。

当两个元件的一个端口与其他元件相连接时,它们很有可能是同名端。

例如,当一个电压源的正极与一个电阻相连接时,可以认为它们是同名端。

对于复杂的电路图,可以借助连线颜色、虚线等手段来帮助观察连接关系。

3. 符号法(Symbol method):这种方法主要适用于线路较为简单的情况,通过观察元件符号的形状和特点来判定同名端。

在大多数电路图中,元件的符号形状是经过标准化的,符号之间存在一定的相似性。

当两个元件的符号之间存在相似性时,即可判定它们为同名端。

例如,在一个电路图中,一个电力源的符号上有两个平行的线段,而一个电压表的符号上也有两个平行的线段,那么可以认为它们是同名端。

4. 连接状态法(Connection status method):这种方法主要适用于已经搭建好的电路实验中,通过测量电路的具体参数来判定同名端。

当两个元件的连接状态相同时,即可判定它们为同名端。

例如,在一个电路实验中,当两个电阻的一端接在同一个节点上,并且测得的电阻值相等时,可以认为它们是同名端。

总之,判定大学电路中同名端的方法主要包括端口标注法、连接关系法、符号法和连接状态法。

不同的方法可以互相补充,根据具体的情况选择合适的方法进行判定。

对于复杂的电路图,可以通过结合多种判定方法来提高准确性。

dlopen、dlsym和dlclose的使用和举例

dlopen、dlsym和dlclose的使用和举例

dlopen、dlsym和dlclose的使用和举例之前用过这三个函数一直没时间整理一下。

今天抽时间整理一下。

1、函数简介dlopen基本定义功能:打开一个动态链接库包含头文件:#include <dlfcn.h>函数定义:void * dlopen( const char * pathname, int mode );函数描述:在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。

使用dlclose()来卸载打开的库。

mode:分为这两种RTLD_LAZY 暂缓决定,等有需要时再解出符号RTLD_NOW 立即决定,返回前解除所有未决定的符号。

RTLD_LOCALRTLD_GLOBAL 允许导出符号RTLD_GROUPRTLD_WORLD返回值:打开错误返回NULL成功,返回库引用编译时候要加入 -ldl (指定dl库)dlsym()功能:根据动态链接库操作句柄与符号,返回符号对应的地址。

包含头文件:#include <dlfcn.h>函数定义:void*dlsym(void* handle,const char* symbol)函数描述:dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。

使用这个函数不但可以获取函数地址,也可以获取变量地址。

handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。

dlclose()dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

上述都是摘抄,总结为链接的时候需要用到dl库,编译的时候需要加上dlfcn.h头文件。

才能保证编译不会报错。

2、生成动态库hello.c函数原型:#include <sys/types.h>#include <signal.h>#include <stdio.h>#include <unistd.h>typedef struct {const char *module;int (*GetValue)(char *pszVal);int (*PrintfHello)();} hello_ST_API;int GetValue(char *pszVal){int retval = -1;if (pszVal)retval = sprintf(pszVal, "%s", "123456");printf("%s, %d, pszVer = %s\n", __FUNCTION__, __LINE__, pszVal);return retval;}int PrintfHello(){int retval = -1;printf("%s, %d, hello everyone\n", __FUNCTION__, __LINE__);return 0;}const hello_ST_API Hello = {.module = "hello",GetValue,PrintfHello,};编译的时候用指令:gcc -shared -o hello.so hello.c上面的函数是用一个全局结构体hello来指向。

dlsym用法 -回复

dlsym用法 -回复

dlsym用法-回复dlsym用法详解:动态链接库中的函数符号查找一、引言在C和C++语言中,动态链接库(Dynamic Link Library,简称DLL)是一种共享库的形式,其中包含了可被外部应用程序调用的函数、全局变量和其他可执行代码。

调用动态链接库中的函数时,需要根据函数名获取其地址,然后通过该地址来进行调用。

dlsym就是一种在动态链接库中查找符号(函数、变量等)地址的方法。

本文将详细介绍dlsym的用法,并逐步解释其实现过程。

二、dlsym函数介绍在Unix和类Unix系统中,dlsym函数用于在动态链接库中查找符号地址。

其原型定义在dlfcn.h头文件中,如下所示:void *dlsym(void *handle, const char *symbol);其中,handle是已经打开的动态链接库的句柄,而symbol是要查找的符号的名称。

dlsym会通过symbol参数在handle所指向的动态链接库中查找symbol对应的地址,并返回该地址的指针。

三、使用dlsym查找动态链接库中的符号地址1. 打开动态链接库首先,我们需要打开一个动态链接库,获取其句柄。

可以使用dlopen函数来打开动态链接库,如下所示:#include <dlfcn.h>void *handle = dlopen("./test.so", RTLD_LAZY);在这个例子中,我们使用了dlopen函数打开了一个名为test.so的动态链接库,并将返回的句柄保存到handle变量中。

RTLD_LAZY是一个标志参数,表示当需要时才解析符号引用。

2. 查找符号地址有了动态链接库的句柄之后,我们可以使用dlsym函数来查找符号的地址。

如下所示:#include <dlfcn.h>void *symbol_ptr = dlsym(handle, "symbol_name");在这个例子中,我们通过在handle所指向的动态链接库中查找名为symbol_name的符号,并将其地址保存到symbol_ptr指针中。

西方哲学中的“符号”概念

西方哲学中的“符号”概念

西方哲学中的“符号”概念“符号”(symbol)是我们在学术和日常语言中频繁使用的一个外来词。

从西方哲学的意义上说,符号就是意义载体。

例如,十字路口的红绿灯、词语“美丽”、公式“1+1=2”、摇头的动作,它们分别指示着特定的交通规则、语义、数学规律和意愿,无一不承载特定意义,因而都是符号。

如此看来,符号可以是物,是词语,也可以是约定俗成的标记,还可以是姿态。

也可以看到,一般而言,符号总是具体而感性的,而它所代表的则是一般的观念。

符号之所以是符号,恰恰在于它能在自身之内把感性和理性、具体和一般合二为一。

从词源学上说,“符号”可以追溯到古希腊词σμβολον(symbolon),它的意思是:“被扔到一起的东西”。

在古希腊,符号通常是某个经由使者在朋友或生意伙伴间传达的信物或公证物。

人们先把某个东西(如硬币、铭牌)一分为二,让每个使者各执其一。

如果两人重逢时能出示各自的一半、并将它们严丝合缝地嵌合起来的话,就可以按照主人的委托完成一桩生意。

因此在最古老的意义上,符号乃是用以保证生意往来中合同和约定的可信性的“身份证”。

词源学考察也向我们暗示出,符号往往是部分的,而它代表的意义则是整体的。

作为载体的符号具有多种形态,对它所代表的意义的解释也因不同文化领域而异。

事实上,“符号”概念内涵丰富而多有歧义,殊难定义,在哲学上也不例外。

不过为了方便理解,我们可以它被考察的方式,对它做出宏观和微观的区分。

宏观意义上的“符号”概念强调符号的存在性质和样态,它所涉及的主要是符号的判定和分类问题。

符号的判定主要是标准问题,根据不同的标准,符号的范围也就有大有小。

比如,有的符号理论家只把语言文字认作符号,有的则把整个世界看作是由符号所充实的。

这里也牵涉到对“符号”与“记号”(sign)从属关系的看法。

在日常语言中二者可以互换使用,指的都是传情达意的载体。

然而在符号理论家那里则有所不同。

有人把“记号”看作一个总概念,而把符号仅仅看作一种特殊的记号;有的则相反,把“记号”看作一种特殊的符号。

linux elf 符号表

linux elf 符号表

linux elf 符号表摘要:1.引言2.Linux ELF 文件结构概述3.符号表的定义与作用4.符号表的类型5.符号表的编码方式6.符号表的应用示例7.结论正文:1.引言Linux 是一个广泛使用的开源操作系统,其背后的核心技术之一就是ELF (Executable and Linkable Format)可执行和可链接文件格式。

在ELF 文件中,符号表是一个重要的组成部分,它记录了程序中各种符号的信息,如函数名、变量名等。

本文将详细介绍Linux ELF 文件中的符号表。

2.Linux ELF 文件结构概述ELF 文件由三部分组成:ELF 头部(ELF Header)、程序头部表(Program Header Table)和节(Section)。

- ELF 头部:包含了ELF 文件的类型、入口地址等信息。

- 程序头部表:包含了多个程序头部,每个程序头部对应一个ELF 节。

- 节:是ELF 文件中可执行代码和数据的组织单位,包含了代码、数据、符号表等各种信息。

3.符号表的定义与作用符号表是一个数据结构,用于存储程序中各种符号的信息,如函数名、变量名等。

在ELF 文件中,符号表位于某个节(Section)内,通常以".symtab" 或".dynsym" 命名。

符号表的主要作用是:- 为调试器提供符号信息,方便程序员调试程序。

- 作为链接器链接目标文件的依据,确保链接过程中符号的正确解析。

4.符号表的类型符号表有多种类型,根据不同的需求和应用场景,可以选择不同类型的符号表:- 普通符号表(Common Symbol Table):包含了所有可见的符号(即在当前模块中定义的符号和在其他模块中引用的符号)。

- 动态符号表(Dynamic Symbol Table):包含了所有动态加载的符号,如共享库中的符号。

- 弱符号表(Weak Symbol Table):包含了弱符号,即在链接过程中可以被其他符号覆盖的符号。

PowerPC上ELF可执行文件的符号解析(一)

PowerPC上ELF可执行文件的符号解析(一)

PowerPC上ELF可执行文件的符号解析(一)一.前言符号解析是Linux系统导入二进制可执行文件的重要过程,它完成的工作包括将一个符号定位到实际的内存位置,并且要保证可以正确引用这些符号。

按解析对象的不同它可以分为变量符号解析和函数符号解析;按解析方式的不同可以分为静态解析和动态解析。

对于静态解析的符号,它们的位置在文件生成时就由link editor(在Linux下通常是ld)已经确定下来了;对于动态解析的符号,他们的位置在程序运行时才由dynamic linker(动态链接器,32位Linux平台下通常是/lib/ld.so.1)确定下来。

我们可以这么认为,如果一个符号在共享库中定义,那么当其他可执行文件或共享库引用这个符号时,就需要对它作动态解析。

变量符号的动态解析过程比较简单,系统在载入程序过程中将变量symbol位置存入到GOT (Global Offset Table)中,引用变量symbol时首先计算出GOT表的实际位置,然后以它作为基址加上(变量symbol在GOT表中的偏移量)就可以从GOT表中取得该symbol的实际位置。

下面以SUSE Linux Enterprise Server 8.1 for IBM pSeries为例,主要讲述和演示32位PowerPC Linux下函数符号的动态解析过程。

二.概念在讲述解析过程之前,先介绍一下在解析过程中要用到的基本概念。

1.ELF(Executable and Linkable Format)文件ELF是Linux缺省采用的可执行文件(包括共享库,object文件)的格式,具体规范参见参考文献[1]、[2]。

这里需要提一下的是section这个概念:section是ELF文件中一段互相了解信息,它可以是一段数据,也可以是一段代码。

比如可执行代码信息就放在.text section 中,被用户初始化的变量会放在.data section中,没有被用户初始化的变量会放在.bss section(bss是below stack segment的缩写)中。

嵌入式系统程序设计(6章)赖晓晨

嵌入式系统程序设计(6章)赖晓晨

4. 共享库错误函数
函数原型: const char *dlerror(void); 功能描述:当动态链接库操作函数 (dlopen、dlsym、dlclose)执 行失败时,dlerror可以返回出错信息, 返回值为NULL时表示操作函数执行成 功。
【例6-2】
/* ch6_2 sub.h */ #ifndef SUB_H #define SUB_H int square(int); #endif /* ch6_2 sub.c */ #include <stdio.h> int square(int a) { printf("the square of the number is:"); return a*a; }
打开共享库(续)
功能描述:参数中的libname一般是库的绝对路径, 这样dlopen会直接装载该文件;如果只是指定了库名 称,在dlopen会按照下面的机制去搜寻:
根据环境变量LD_LIBRARY_PATH查找; 根据/etc/ld.so.cache查找; 依次在/lib和/usr/lib目录查找。
库分类
静态库,是在执行程序运行前就已经加入到执 行码中,在物理上成为执行程序的一部分。
共享库,是在执行程序启动时加载到执行程序 中,可以被多个执行程序共享使用。 动态链接库,其实并不是一种真正的库类型, 应该是一种库的使用技术,应用程序可以在运 行过程中随时加载和使用库。
库命名约定
所有库都以lib开头,表示一个库文件;
}
handle=dlopen("/lib/libmydll.so", RTLD_LAZY); if(!handle) { printf("%s\n",dlerror()); 如未找到函数,显 } 示error中的错误 fp=dlsym(handle, "square"); 信息 if((error=dlerror())!=NULL) { printf("%s\n",error); dlclose(handle); exit(1); } printf("now call the function square.\n"); result = (*fp)(n); printf(" %d\n",result); dlclose(handle); return 0;

了解动态链接(五)——动态符号表

了解动态链接(五)——动态符号表

了解动态链接(五)——动态符号表ilocker:关注 Android 安全(新⼊⾏,0基础) QQ: 2597294287动态符号表 (.dynsym) ⽤来保存与动态链接相关的导⼊导出符号,不包括模块内部的符号。

⽽ .symtab 则保存所有符号,包括 .dynsym 中的符号。

动态符号表中所包含的符号的符号名保存在动态符号字符串表 .dynstr 中。

使⽤ readelf 查看 .dynsym 表,如:readelf --dyn-syms libstdc++.so。

可以看到,.dynsym 表包含39项。

__cxa_atexit 是⼀个导⼊符号,⽽ __cxa_guard_acquire 则是⼀个导出符号。

搜索 android libstdc++ 库的源码,能找到该导出函数的定义:书上说很多动态链接的模块同时拥有 .dynsym 和 .symtab 两个表,但我查看了 android 下的⼏个系统共享库:libc.so、.liblog.so、libm.so、libstdc++.so,都是只有 .dynsym。

其实按我的理解,so 库中就是只有 .dynsym 就可以了,⽤于动态链接时的符号查找和地址重定位。

.symtab 中的内部符号,此时已经没什么⽤了,所以没必要存在 .symtab。

补充:后来发现,android 5 系统中的 libc 等 so 中是具有 .symtab 和 .strtab 的。

另外,对于⾃⼰使⽤ NDK 开发的 so,在 \libs\armeabi 下的 so 是经过 strip 的(最后被打包到 apk 中的)so,在这个 so 中是没有 .symtab 和 .strtab 的。

但在 \obj\local\armeabi 下,有未经过 strip 处理的 so,他⾥⾯是有 .symtab 和 .strtab 的,默认在⽂件中,位于所有 section 的最后。

在 android 的 linker 进⾏符号重定位⼯作时,⾸先要在符号表中查找符号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

动态连接库和符号(symbol)shared library (.so)"Program Library Howto-Shared Libraries"是很好的材料, 下面的内容多是据此整理的.定义:Shared libraries are libraries that are loaded by programs when they start.使用shared library(共享库)会有很多好处, 比如软件升级, 不难想象.命名约定:1. soname: 每个共享库都有一个soname, 形式为"libNAME.so.x", 其中x是版本号. 如"libc.so.6".2. real name: 真正的库文件, 一般形式为"soname.y[.z]", 即"libName.so.x.y[.z]", 其中y是minor number, z是release number, 是可选的. 如"libattr.so.1.1.0".3. linker name: compiler用来请求库时使用的名字, 一般是没有版本号的soname.放置位置&amp; load/preload:共享库一般放在一些约定的目录下, 如/usr/lib/, /usr/local/lib, /lib/等. 这其实是遵循FHS的, 比如/usr/local/lib下放置的一般是用户开发的库.在启动程序时, program loader(ld-linux.so.x)会找到并加载程序需要的共享库, loader查找的路径一般就是上述的几个目录, 这些目录在/etc/ld.so.conf文件中配置.如果只想覆盖共享库的某几个函数, 保持其余函数不变, 则可以将共享库名字和函数名字输入到/etc/ld.so.preload中, 这里面定义的规则会覆盖标准规则.cache arrangement &amp; ldconfig实际上, 在启动程序时再去搜寻所需的共享库不是高效做法, 所以loader使用了cache. ldconfig的作用就是读取文件/etc/ld.so.conf, 在各个库目录中, 对共享库设置合适的symbolic link(使得遵守命名约定), 然后写入某种数据到/etc/ld.so.cache, 这个文件再今后就被其他程序使用, 从而大幅提升了共享库的查找速度.所以在每加入/移除一个共享库, 或者修改了/etc/ld.so.conf(即修改库目录)的时候, 最要运行ldconfig.创建共享库step1. 编译出object files, 需要使用-fPIC或-fpic flag. fPIC和fpic的区别是, 前者生成的文件更大, 不过具有更好的平台无关性, 后者恰好相反. 这说明前者为了platform-independence做了更多工作.step2. 用-Wl向linker传递参数. 如: "gcc -shared-Wl,-soname,libmystuff.so.1 -o libmystuff.so.1.0.1 a.o b.o -lc".step3. 把共享库拷贝到约定的某个目录下即可, 如/usr/local/lib.step4. ldconfig -n /path/to/lib.elfelf的内容参考"elf &amp; libelf, elftoolchain", 它是一种格式,也是一种规范, 可以用libelf写程序去操作它, 可以用objdump、nm和readelf去读取elf文件的内容.symbols我也已经熟悉共享库了, 我知道ldconfig的作用, 我知道常用的库放置目录, 我知道ltrace, ldd可以用来帮助确认某程序和某些共享库的关联关系是否正确.所以, 如果没有symbols这一节, 本篇文章存在的意义不大. "Inside ELF Symbol Tables"是绝佳的资料, 当然正如很多网文一样, 它仅是帮助理解, 而不涉及很深的细节. 细节标准什么的还是要看书和文档了, 这方面很不错的书籍就是校友的&lt;程序员的自我修养&gt;了.查看elf规范, 你必然可以看到symtab和dynsym, 如"ELF-64 Object File Format"中"4.Sections"就列出了标准的sections, .symtab和.dynsym就是其中之二.实际上, 我们知道机器可执行的是machine code, 而我们使用的高级语言编程, 并不是利用晦涩的机器码, 而是用human-readable的变量名, 函数名等, 这些名字就是symbolic name. 编译器在编译时收集symbol信息, 并储存在object file的.symtab和.dynsym中. symbols是linker和debugger所必需的信息, 如果没有symbols, 试想debugger如何能展示给用户调试信息了? 如果没有symbol, 而只有地址(相对于object file的offset), linker如何能够链接多个object file了?对于linker和symbol, 我们可以做个小实验: // 编写一个简单的a.c$ cat a.cvoid func(void){printf("call func()\n");}$ nm a.o00000000 T funcU puts// 编写一个简单的main.c$ cat main.c#include &lt;stdio.h&gt;extern void func(void);int main({func();return 0;}$ nm main.oU func00000000 T main// 正常情况下$ gcc main.o a.o -o main$ ./maincall func()// 为了验证symbol对于linker来说是必需品, 我做如下操作$ file a.oa.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped$ strip a.o$ file a.oa.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), stripped$ gcc main.o a.o -o mainmain.o: In function `main':/home/xan/lab/main.c:7: undefined reference to `func'collect2: ld returned 1 exit status这个小实验证实了symbols对于linker的重要性, 同时使用file看出"not stripped"-&gt;"stripped"的变化, 说的就是去除了symbols信息.现在假使我们生成了最后的可执行文件(当然是elf格式了), 那么这个elf中是否包含symbols呢? 其中又是否需要symbols呢?不妨先下结论: 一般地, 生成的可执行文件都是包含symbols, 不过这些信息不是程序执行所必需的, 可以通过strip(Discard symbols from object files)去除.同样可以做个小实验:// 仍用上面实验的代码$ file mainmain: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped$ ./maincall func()$ strip main$ file mainmain: ELF 32-bit LSB executable, Intel 80386, version 1(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped$ ./maincall func()$这个小实验证实了symbols对于可执行文件来说不是必需的, 这是因为可执行的代码都是machine code, 只需要address信息, 无需symbol信息.对于elf和symbols, 还是好理解的啦. 就是我elf文件中留了一席之地给你放symbols, compiler在生成elf时会往其中填充. debugger/nm/readelf等可以来读取. 不过这些symbols不是程序执行必需的, 所以完全可以去除, 只不过去除之后, debugger就读不到信息了.而对于共享库来说, 情况略复杂些了. 我们来特别说明.共享库和symbols在继续下去之前, 先来看两个事实.$ ldd /bin/lslinux-gate.so.1 =&gt; (0xb7711000)libselinux.so.1 =&gt; /lib/libselinux.so.1(0xb76e5000)librt.so.1 =&gt; /lib/i686/cmov/librt.so.1(0xb76dc000)libacl.so.1 =&gt; /lib/libacl.so.1 (0xb76d4000)libc.so.6 =&gt; /lib/i686/cmov/libc.so.6 (0xb758d000)libdl.so.2 =&gt; /lib/i686/cmov/libdl.so.2(0xb7589000)/lib/ld-linux.so.2 (0xb7712000)libpthread.so.0 =&gt; /lib/i686/cmov/libpthread.so.0 (0xb7570000)libattr.so.1 =&gt; /lib/libattr.so.1 (0xb756b000)$ nm /lib/i686/cmov/libc.so.6nm: /lib/i686/cmov/libc.so.6: no symbols --&gt; libattr, libacl也一样, 都显示"no symbols"// 而libpthread有一大串$ nm /lib/i686/cmov/libpthread.so.0 | tailU twalk@@GLIBC_2.0U uname@@GLIBC_2.0U unlink@@GLIBC_2.00000c930 t unwind_cleanup0000c970 t unwind_stop0000cfd0 W vfork0000de90 W wait0000df50 W waitpid0000c140 t walker0000d020 W write这仅仅是因为有些库做了strip, 而其他库没做strip而已? 还是说对于某些共享库来说, symbols也是必需的?目前不知答案, 分析下去.前面提到.symtab和.dynsym两个不同的symbol table, 它们有什么区别?.dynsym是.symtab的一个子集, 大家都有疑问, 为什么要两个信息重合的结构?需要先了解allocable/non-allocable ELF section, ELF文件包含一些sections(如code和data)是在运行时需要的, 这些sections被称为allocable; 而其他一些sections仅仅是linker,debugger等工具需要, 在运行时并不需要, 这些sections被称为non-allocable的. 当linker构建ELF文件时, 它把allocable的数据放到一个地方, 将non-allocable的数据放到其他地方. 当OS加载ELF文件时, 仅仅allocable的数据被映射到内存, non-allocable的数据仍静静地呆在文件里不被处理. strip就是用来移除某些non-allocable sections的..symtab包含大量linker,debugger需要的数据, 但并不为runtime必需, 它是non-allocable的; .dynsym包含.symtab的一个子集, 比如共享库所需要在runtime加载的函数对应的symbols, 它世allocable的.因此, 得到答案:1. strip移除的应是.symtab.2. nm读取的应是.symtab: 上面发现的libattr等nm结果为空, libpthread nm结果非空应是正常的.3. 共享库包含的.dynsym是runtime必需的, 是allocable的. 可做验证, 期望的结果为:1. strip libpthread, ls依然能够工作.2. strip libpthread, nm libpthread得到结果为空.3. 可以通过设置nm options, 或使用readelf读出.dynsym的内容.$ sudo strip /lib/i686/cmov/libpthread-2.11.3.so$ file /lib/i686/cmov/libpthread-2.11.3.so/lib/i686/cmov/libpthread-2.11.3.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped$ ls...(输出正确结果)$ nm /lib/i686/cmov/libpthread-2.11.3.sonm: /lib/i686/cmov/libpthread-2.11.3.so: no symbols$ readelf -s /lib/i686/cmov/libpthread-2.11.3.so | tail322: 0000b6a0 292 FUNC GLOBAL DEFAULT 13 __pthread_clock_gettime@@GLIBC_PRIV ATE323: 0000ec30 46 FUNC GLOBAL DEFAULT 13 pthread_mutex_consistent_@@GLIBC_2.4324: 0000b3a0 50 FUNC GLOBAL DEFAULT 13 pthread_testcancel@@GLIBC_2.0325: 0000d6b0 111 FUNC WEAK DEFAULT 13 fsync@@GLIBC_2.0326: 0000d1f0 180 FUNC WEAK DEFAULT 13 fcntl@@GLIBC_2.0327: 0000dde0 176 FUNC WEAK DEFAULT 13tcdrain@@GLIBC_2.0328: 00009390 7 FUNC GLOBAL DEFAULT 13 pthread_mutexattr_destroy@@GLIBC_2.0329: 00006de0 23 FUNC GLOBAL DEFAULT 13 pthread_yield@@GLIBC_2.2330: 000077c0 259 FUNC GLOBAL DEFAULT 13 pthread_mutex_init@@GLIBC_2.0331: 000093c0 49 FUNC GLOBAL DEFAULT 13 pthread_mutexattr_setpsha@@GLIBC_2.2$ readelf -s /lib/libattr.so.1.1.0 | tail48: 00002f50 50 FUNC GLOBAL DEFAULT 13 lremovexattr@@ATTR_1.049: 00003010 57 FUNC GLOBAL DEFAULT 13 llistxattr@@ATTR_1.050: 00002ae0 50 FUNC GLOBAL DEFAULT 13 attr_copy_check_permissio@@ATTR_1.151: 00001b50 259 FUNC GLOBAL DEFAULT 13 attr_set@@ATTR_1.052: 00002b20 1002 FUNC GLOBAL DEFAULT 13 attr_copy_action53: 000031f0 71 FUNC GLOBAL DEFAULT 13setxattr@@ATTR_1.054: 00001380 543 FUNC GLOBAL DEFAULT 13 attr_list@@ATTR_1.255: 000030d0 64 FUNC GLOBAL DEFAULT 13 lgetxattr@@ATTR_1.056: 00002fd0 57 FUNC GLOBAL DEFAULT 13 flistxattr@@ATTR_1.057: 00002f10 50 FUNC GLOBAL DEFAULT 13 fremovexattr@@ATTR_1.0至此, 对symbols和共享库,ELF的关系的了解告一段落. more既然已经说到共享库(shared library), 不妨稍微提一下动态装载库(Dynamically Loaded Libraries), 共享库是在程序startup 时被加载, 而DLL(注意区别于windows下的概念)则是在程序运行过程中显式被加载, 实际上就是调用dlopen,dlsym等接口显式地打开共享库, 显示地查找库中的symbol, 然后找到对应的代码去执行.How To Write Shared Libraries by Ulrich Drepper.--EOF--。

相关文档
最新文档