genius dynamic linkerdynamic是什么意思

19063人阅读
Android支撑技术(1)
&&& &&&&&&&&&&&&&&&&&&
Tag&&&&&&& Type&&&&&&&&&&&&&&&&&&&&&&&& Name/Value
0x (NEEDED)&& &&&&&&&&&&&&&&&&&&Shared library: [libc.so.6]
0x0000000c (INIT)&&&&&&&&&&&&&&&&&&&&& &&&&&& 0xb8a8
0x0000000d (FINI)&&&&&&&&&&&&&&&&&&&&&& &&& 0x555c4
0x (HASH)&&&&&&&&&&&&&&&&&&&&&& 0x8128
0x (STRTAB)&&&&&&&&&&&&&&&&&&&& & 0xa004
0x (SYMTAB)&&&&&&&&&&&&&&&&&&&& 0x8aa4
0x0000000a (STRSZ)&&&&&&&&&&&&&&&&&&&&& && 2902 (bytes)
0x0000000b (SYMENT)&&&&&&&&&&&&&&&&&&&& 16 (bytes)
0x (DEBUG)&&&&&&&&&&&&&&&&&&&&& &&&&&&&&& 0x0
0x (PLTGOT)&&&&&&&&&&&&&&&&&&&& 0x710dc
0x (PLTRELSZ)&&&&&&&&&&&&&&&&&& & 2464 (bytes)
0x (PLTREL)&&&&&&&&&&&&&&&&&&&& & REL
0x (JMPREL)&&&&&&&&&&&&&&&&&&& && 0xaf08
0x (REL)&&&&&&&&&&&&&&&&&&&&&&& && 0xae98
0x (RELSZ)&&&&&&&&&&&&&&&&&&&&& & 112 (bytes)
0x (RELENT)&& &&&&&&&&&&&&&&&&&& 8 (bytes)
Num:&&& Value& &Size &Type&&& Bind&& &&&&Vis&&&&& &&Ndx &&Name
0:& && &0 &NOTYPE& LOCAL& &DEFAULT& UND
6: &&&& 28 &FUNC&&& GLOBAL &DEFAULT&&& 7& &__ashldi3
7: &&&& 58 &FUNC&&& GLOBAL &DEFAULT& UND &_ZNK7android7RefBase9decS
8: &&&& 32 &FUNC&&& GLOBAL &DEFAULT& UND &ioctl
9: &&&& 18 &FUNC&&& GLOBAL &DEFAULT& UND &_ZN7android7String8D1Ev
10: &&&& 16 &FUNC&&& GLOBAL& DEFAULT& UND &_ZNK7android8EventHub16ge
11: &&&& 32 &FUNC&&& GLOBAL &DEFAULT& UND& strerror
12: &&&&& 0 &NOTYPE& GLOBAL &DEFAULT& ABS &__exidx_end
Offset&&&& Info&&& &&Type&&&&&&&&&&& &&&&&&Sym.Value& Sym. Name
&&R_ARM_JUMP_SLOT&& && fileno
&&R_ARM_JUMP_SLOT&& 0000b8dc&& getpagesize
&&R_ARM_JUMP_SLOT&& && fputs
&&R_ARM_JUMP_SLOT&& && abort
&&R_ARM_JUMP_SLOT&& && __errno_location
Offset&&&& Info&&& &&Type&&&&&&&&&&& Sym.Value& Sym. Name
00001e15 &R_ARM_GLOB_DAT&&& && __fini_array_end
00002f15 &R_ARM_GLOB_DAT&&& && __gmon_start__
&R_ARM_GLOB_DAT&&& && __fini_array_start
&R_ARM_GLOB_DAT&&& && __init_array_end
00012e15 &R_ARM_GLOB_DAT&&& && __init_array_start
&R_ARM_COPY&&&&&&& &00072a00&& __timezone
&R_ARM_COPY&&&&&&& &00072a04&& __daylight
R_ARM_JUMP_SLOT
/*in sys_execve-&do_execve-&search_binary_handler-&load_elf_binary*/
elf_entry = load_elf_interp(&loc-&interp_elf_ex,interpreter,&interp_map_addr, load_bias);
start_thread(regs, elf_entry, bprm-&p);&&&&&& //start to execute linker
load_elf_binary&create_elf_tables
/*in __linker_init()*/
&&&&&&& /* extract information passed from the kernel */
while(vecs[0] != 0){
switch(vecs[0]){
case AT_PHDR:
si-&phdr = (Elf32_Phdr*) vecs[1];
case AT_PHNUM:
si-&phnum = (int) vecs[1];
case AT_ENTRY:
si-&entry = vecs[1];&&&&&&&&&&&&&&& /*entry of the executable image.*/
vecs += 2;
si = alloc_info(argv[0]);&&&&&&&&&&&&&&&&& /*name of exe */
if(si == 0) {
si-&flags |= FLAG_EXE;&&&&&&&&&&&&&&&& /*exe not share library*/
for(d = si-& *d; d += 2) {
&&&&& f(d[0] == DT_NEEDED){&&&&&&&&&&&& //it &s a needed share library.
&&&&& soinfo *lsi = find_library(si-&strtab + d[1]);& //get soinfo by name&&&&&&&&&
&&&&& if(lsi == 0) {
&&&&&&&&&}
lsi-&refcount++;&&&&&&&&&&&&&&&&& // &Increment it&s referenced count
&&& while(libbase & LIBLAST) {& //LIBLAST=0x
base = mmap((void*) libbase, sz, PROT_READ | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(((unsigned)base) == libbase) {
if(base != MAP_FAILED)
&&&&&& munmap(base, sz);
libbase += LIBINC;&&& // LIBINC = 0x
pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr-&p_flags),MAP_PRIVATE | && MAP_FIXED, fd,phdr-&p_offset & (~PAGE_MASK));
&&&&&&&&&&
if (!(phdr-&p_flags & PF_W)) {
if ((unsigned)pbase & si-&wrprotect_start)
si-&wrprotect_start = (unsigned)
if (((unsigned)pbase + len) & si-&wrprotect_end)
si-&wrprotect_end = (unsigned)pbase +
&&&&&&&&&&&& mprotect(pbase, len,PFLAGS_TO_PROT(phdr-&p_flags) | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&& PROT_WRITE);
&&&&&& private anonymous mappings
if (tmp & (base + phdr-&p_vaddr + phdr-&p_memsz)) {
extra_base = mmap((void *)tmp, extra_len
Elf32_Addr&&&&&& r_&&&&&&&&&& //
Elf32_Word&&&&& r_&&&&&&&&&&&&&&&&& & //
.rel.dyn&&&&&&& :
*(.rel.init)
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.fini)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
*(.rel.ctors)
*(.rel.dtors)
*(.rel.got)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
.rel.plt&&&&&&& : { *(.rel.plt) }
if(si-&plt_rel) {&&&&&&&&&&&&&&&&&&&&&&&&& /*it &s a .rel.plt (DT_JMPREL) section*/
if(reloc_library(si, si-&plt_rel, si-&plt_rel_count))//binding all the external func
if(si-&rel) {&&&&&&&&&&&&&&&&&&&&&&&&&&&& /*it &s a .rel.dyn (DT_REL)section*/
if(reloc_library(si, si-&rel, si-&rel_count))
符号绑定示意图
/*in reloc_library ()*/
for (idx = 0; idx & ++idx) {&&&&&&&&& //count = si-&plt_rel_count.
unsigned type = ELF32_R_TYPE(rel-&r_info);
unsigned sym = ELF32_R_SYM(rel-&r_info);
unsigned reloc = (unsigned)(rel-&r_offset + si-&base);
if(sym != 0) {
&&/*search symbol within solist*/
s = _do_lookup(si, strtab + symtab[sym].st_name, &base);
if ((s-&st_shndx == SHN_UNDEF) && (s-&st_value != 0)) {return -1;}
/* in _do_lookup
for(si = (s == NULL) && (si != NULL); si = si-&next)
if((si-&flags & FLAG_ERROR) || (si == user_si))
s = _do_lookup_in_so(si, name, &elf_hash);
if (s != NULL) {
*base = si-&
Elf32_Sym *s;
Elf32_Sym *symtab = si-&
const char *strtab = si-&
n = hash % si-&
for(n = si-&bucket[hash % si-&nbucket]; n != 0; n = si-&chain[n]){
s = symtab +
if(strcmp(strtab + s-&st_name, name)) /* only concern ourselves with &&&&&&&&&&&&&&&&&& global symbols */&&&&&
switch(ELF32_ST_BIND(s-&st_info)){
case STB_GLOBAL:
if(s-&st_shndx == 0)& /* no section == undefined */
case STB_WEAK:
/*in reloc_library*/
sym_addr = (unsigned)(s-&st_value + base);&& /*get the actual address.*/
sym_name = (char *)(strtab + symtab[sym].st_name);
switch(type){
case R_ARM_JUMP_SLOT:
case R_ARM_GLOB_DAT:
case R_ARM_ABS32:
*((unsigned*)reloc) = sym_
case R_ARM_RELATIVE:
if(sym){return -1; }
*((unsigned*)reloc) += si-&
case R_ARM_COPY:
memcpy((void*)reloc, (void*)sym_addr, s-&st_size);& /*object in RW seg*/
default: return -1;
&return 0;
if (si-&wrprotect_start != 0xffffffff && si-&wrprotect_end != 0) {
mprotect((void *)si-&wrprotect_start, si-&wrprotect_end - &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&si-&wrprotect_start, PROT_READ | PROT_EXEC);
bl&&& __linker_init&& /* linker init returns the _entry address in the main image */
mov pc, r0
$ arm-none-linux-gnueabi-gcc -fpic -nostdlib -Wl,-T,armelf.xsc, -shared, -Bsymbolic -o libhello.so &hello.c&&&& /*create shared object*/
$ arm-none-linux-gnueabi-gcc -c start.c &&&&&& $ arm-none-linux-gnueabi-gcc -c main.c&&&&& $ arm-none-linux-gnueabi-ld --dynamic-linker /system/bin/linker -nostdlib /&& -rpath /system/lib -rpath ~/tmp/android/system/lib -L . /
-L ~/tmp/android/system/lib -lc -lhello -o hello2 start.o main.o
Linkers and loaders.
How to write shared libraries.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:56928次
排名:千里之外
评论:19条
(1)(1)(2)(5)(1)(1)指定dynamic linker以使用高版本GCC - 推酷
指定dynamic linker以使用高版本GCC
今天有人问怎么在没有root的不可更新老旧Linux环境里使用高版本GCC,主要困难在于GCC对glibc版本有一定要求。假设使用现成的GCC二进制包,解压到本地后执行
/lib64/libc.so.6: version `GLIBC_2.14' not found
,即系统glibc的
中缺乏更高版本的符号(参考
info '(ld) VERSION'
)。使用新符号通常表示API有更新,不过很多时候旧版本的库也能用,可能有两个原因:一是编译机器的库版本可能较新,soname版本号较高,编译出来的可执行文件也会有较高的版本要求;二是源文件因保守指定了较高的版本号,实际上旧版本也能用。
比如最近ncurses主版本号更新到6,
/usr/lib/libncursesw.so.5
/usr/lib/libncursesw.so.6
,导致很多可执行文件没法用了:
% ldd /usr/lib/j8/bin/jconsole
linux-vdso.so.1 (0x00007ffcdb9ec000)
libedit.so.2 =& /usr/lib/libedit.so.2 (0x00007fd995a09000)
libdl.so.2 =& /usr/lib/libdl.so.2 (0x00007fd)
libncursesw.so.5 =& not found
libc.so.6 =& /usr/lib/libc.so.6 (0x00007fd)
/lib64/ld-linux-x86-64.so.2 (0x00007fd995c45000)
不想重新编译的话,可以软链接做一个
libncursesw.so.5
默认会查找的路径下,或者运行时指定环境变量
LD_LIBRARY_PATH
。另外还有一种修改可执行文件的方法:用十六进制编辑工具把
section中的字串
libncursesw.so.5
libncursesw.so.6
。再次执行时,
将会用新的名字查找依赖的库,就顺利找到了
/usr/lib/libncursesw.so.6
,但做这样的修改得保证新的路径名长度小于等于原长,否则会覆盖
中后面的字串。另一种办法是构造一个新的
放到ELF的其他地方,并变更section header中的
地址信息,非常麻烦。
回到正题,xptree下载了
gcc-c++-4.8.3-9.el7.x86_64.rpm
gcc-4.8.3-9.el7.x86_64.rpm
,解压后执行,报错:
/lib64/libc.so.6: version `GLIBC_2.14' not found
glibc-2.17-78.el7.x86_64.rpm
/usr/bin/python: relocation error: MY_LOCAL/lib64/libc.so.6: symbol_dl_starting_up, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2with link time referenceg++: relocation error: MY_LOCAL/lib64/libc.so.6: symbol _dl_starting_up,version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link timereference
ld-linux-x86-64.so.2
(dynamic linker,下面简称为
)的版本也有要求。就像修改依赖库的路径那样,修改program header中的
bbe -b '/\x2flib64\x2fld-linux-x86-64.so.2/:27' -e 'L 1' -e 'r 0 /tmp/l/ld.so\0' bin/gcc -o bin/gcc.new
中第一次出现的
/lib64/ld-linux-x86-64.so.2
/tmp/l/ld.so\0
,可以观察到:
% ldd bin/gcc.new
linux-vdso.so.1 (0x00007ffff85f5000)
libm.so.6 =& /usr/lib/libm.so.6 (0xca000)
libc.so.6 =& /usr/lib/libc.so.6 (0x6000)
/tmp/l/ld.so (0xbc8000)
调用的可执行文件如
等可能也得做同样修改。之后
即可执行,但编译生成的可执行文件还使用原先的dynamic linkter,也许会在某些情况下无法执行。一种办法是在用
链接时指定
-Wl,--dynamic-linker,/tmp/l/ld.so
,这样产生的可执行文件就会使用
/tmp/l/ld.so
作为dynamic linker。另一种方法是修改
中的built-in specs:
% gcc -dumpspecs......*link:...%{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}.........
可执行文件
中找这段字串,把
/lib64/ld-linux-x86-64.so.2}}}
/tmp/l/ld.so}}}
后填充空格。这样得到的
产生的可执行文件就会使用新的dynamic linker了:
% bin/gcc.new -xc - -o a &&& 'int main(){}'% ldd a
linux-vdso.so.1 (0x00007ffeff9b3000)
libc.so.6 =& /usr/lib/libc.so.6 (0xfe5b000)
/tmp/l/ld.so (0xff000)
跳出XY problem
如果要装的东西多些,可以考虑Gentoo Prefix、
等,还有unprivileged LXC containers等。轻量省事的方法是userspace chroot
,不需要root,但弊端是运行的进程处于ptrace下,而一个进程不能被ptrace两次,因此gdb、strace等都没法用。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 dynamic linker 的文章

 

随机推荐