共享库和执行权限
linuxmint吧
全部回复
仅看楼主
level 9
hejiannn 楼主
网上有很多关于共享库和执行权限的讨论,但都没有谈到运行一个共享库的情况。
可能有人说,没事谁会去运行一个共享库。。。但这个确实值得研究下。
例如:
写一个简单的共享库,编译,运行,会出现段错误。。。
这个是不是值得研究下?
2013年02月17日 07点02分 1
level 9
hejiannn 楼主
首先需要研究是动态加载与执行权限的关系。
当映射一个共享库,动态加载并不关心文件权限,只关心把.so文件的特定部分进行映射到内存。准确的说,是把程序头定义的PT_LOAD段按照特定的权限映射到内存。
通过readelf --segments命令可以把上面编译的libfoo.so的程序头列出来看看:
2013年02月17日 07点02分 2
level 9
hejiannn 楼主
从上图可以看到,有两个Type为LOAD的段。
然后看这两个段右边的Flags。
第一个段的Flag是R E,表示可读、可执行。第二个段的Flag是RW,表示可读、可写。
一个是代码段,一个是数据段。代码段可执行,数据段可写。
动态加载时,会使用mmap函数把这些段映射到内存,mmap函数会使用这些Flags来定义内存保护。
2013年02月17日 07点02分 3
level 9
hejiannn 楼主
一个段是否必须有执行权限才能被运行?其实不是这样的,因为段的内容是可读的。
任何一个段,只要可读,就可以把这个段的内容拷贝到具有PROT_EXEC类型的内存区域,然后就可以被执行了。。。
2013年02月17日 07点02分 4
level 9
hejiannn 楼主
回到主题。一楼的共享库为何能被执行,并且报段错误?
共享库也是ELF文件,内核会把ELF文件中Type为LOAD的段映射到内存,并跳转到入口点(e_entry)。
有趣的是共享库为什么会有入口点(e_entry)?entry point是从哪来的?
通过 man ld 发现entry point是通过--entry命令行选项或ENTRY这个linker脚本命令指定的:
2013年02月17日 08点02分 5
level 9
hejiannn 楼主
由于在编译时并没有通过--entry这个命令行选项指定entry point,所以应该是通过ENTRY这个脚本命令指定的。
通过ld --verbose这个命令可以查看缺省的linker script:
果然找到了,entry point 是 _start
2013年02月17日 08点02分 6
level 9
hejiannn 楼主
但是一楼的程序并没有定义_start,所以还需要继续研究。
2013年02月17日 08点02分 7
先打会儿TF2,晚上再继续研究。。。
2013年02月17日 08点02分
1