红联Linux门户
Linux帮助

如何获取linux-gate.so.1动态库

发布时间:2016-03-20 11:02:30来源:linux网站作者:ALAWSWF

经常有提到在Linux下每个可执行文件都依赖于几个最为基本的动态库,其中一个就是linux-gate.so.1。

如何获取linux-gate.so.1动态库

从上面ldd给出的结果可以看出,这个linux-gate.so.1动态库有一些异样,libc.so.6的实际动态库路径在/lib/tls/i686/cmov/libc.so.6,而ld-linux.so.2是在/lib/ld-linux.so.2。那么不禁要问一个问题linux-gate.so.1这个动态库的路径是什么,是文件系统中那个文件呢?其实这个文件是内核映射上去的,并非存在实际的动态库文件,对于这个具体问题我们后续再做详细分析,这里仅仅做如何获取linux-gate.so.1动态库的方法。


通常情况下,比如在suse10, suse11系统上,linux-gate.so.1被映射到ffffe000-fffff000这个高端内存段里面。此时将这段内存导出到文件比较简单,可以使用下面脚本,帮助各位导出:

#!/bin/bash 
VDSO_FILE_NAME=linux-gate.dso 
cat /proc/self/maps|grep "vdso" 
VDSO_ADDR=`cat /proc/self/maps|grep "vdso" |awk -F '-' '{print $1 }'` 
echo "Current VDSO address is 0x$VDSO_ADDR" 

VDSO_BLOCK=`echo |awk '{print substr("'${VDSO_ADDR}'",1,5)}'` 
((SKIP_BLOCKS=16#$VDSO_BLOCK)) 
echo "We have $SKIP_BLOCKS blocks before VDSO library" 

echo "Ready to generate $VDSO_FILE_NAME from block $SKIP_BLOCKS" 
dd if=/proc/self/mem of=$VDSO_FILE_NAME bs=4096 skip=$SKIP_BLOCKS count=1 

echo "Generate $VDSO_FILE_NAME Done" 


在suse系统上执行的结果:

~> ./cat_linux_gate_so.sh 
ffffe000-fffff000 ---p 00000000 00:00 0  [vdso] 
Current VDSO address is 0xffffe000 
We have 1048574 blocks before VDSO library 
Ready to generate linux-gate.dso from block 1048574 
1+0 records in 
1+0 records out 
4096 bytes (4.1 kB) copied, 4.2e-05 seconds, 97.5 MB/s 
Generate linux-gate.dso Done 

~> file -b linux-gate.dso 
ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped 
~> objdump -T linux-gate.dso 


linux-gate.dso: 文件格式 elf32-i386 
 
DYNAMIC SYMBOL TABLE: 
ffffe400 ld  .text  00000000  .text 
ffffe478 ld  .eh_frame_hdr  00000000  .eh_frame_hdr 
ffffe49c ld  .eh_frame  00000000  .eh_frame 
ffffe620 ld  .useless   00000000  .useless 
ffffe400 gDF .text  00000014  LINUX_2.5   __kernel_vsyscall 
00000000 gDO *ABS*  00000000  LINUX_2.5   LINUX_2.5 
ffffe440 gDF .text  00000007  LINUX_2.5   __kernel_rt_sigreturn 
ffffe420 gDF .text  00000008  LINUX_2.5   __kernel_sigreturn 


在ubuntu 上情况比较复杂,在此也耽误了不少时间,因为ubuntu映射到的内存地址是不固定的,每个进程映射的位置都是不同的。


多次执行:

cat /proc/self/maps|grep "vdso" 

b7f47000-b7f48000 r-xp b7f47000 00:00 0  [vdso]

b7f5f000-b7f60000 r-xp b7f5f000 00:00 0  [vdso]

b7f54000-b7f55000 r-xp b7f54000 00:00 0  [vdso]


因此上面脚本无法实现同一个进程内映射内存导出。为了实现同一进程内导出,这里采用简单C编程的方法实现。

基本原理和上面脚本一致,首先通过/proc/self/maps找到vsdo映射内存的地址,然后导出映射内存到文件linux-gate.dso。

int main(int argc, char **argv) 

FILE *pFile = NULL; 
void *paddr = NULL; 

char buffer[BUFFER_SIZE]; 
char address[BUFFER_SIZE]; 
char block[BLOCK_SIZE]; 

char c; 
int i, ineedreset, iblocks, iSize; 

pFile = fopen("/proc/self/maps", "r"); 
if (NULL == pFile) 

printf("/proc/self/maps fopen failed, error!\r\n"); 
return 1; 

/* 查找vdso动态库映射内存位置  */ 
i = 0; 
ineedreset = 1; 
memset(buffer, 0, BUFFER_SIZE); 
while(1)  

c = fgetc (pFile); 
if (c != EOF)  

printf("%c", c); 
if (c == '\r' || c == '\n') 

i = 0; 
ineedreset = 1; 
} else 

if (ineedreset) 

if (NULL != strstr(buffer, "vdso")) 

printf("I have got vdso section.\r\n"); 
break; 

memset(buffer, 0, BUFFER_SIZE); 
ineedreset = 0; 
}
buffer[i++] = c; 

}else 

break; 

printf("vsdo line is:%s\r\n", buffer); 
fclose(pFile); 
pFile = NULL; 

/* 获取起始地址 */ 
memset(address, 0, BUFFER_SIZE); 
for (i = 0; buffer[i] != '-'; i++) 

address[i] = buffer[i]; 
if (buffer[i] == '-') 
break; 

paddr = (void *) Hex2Ulong(address); 
printf("Current VDSO address is 0x%x\r\n", paddr); 
iblocks = (unsigned long)paddr / BLOCK_SIZE; 
printf("We have %d blocks before VDSO library\r\n", iblocks); 
printf("Ready to generate linux-gate.dso from block %d\r\n", iblocks); 

/* 导出vdso动态文件 */ 
pFile = fopen("./linux-gate.dso", "w"); 
if (NULL == pFile) 

printf("fopen linux-gate.dso failed, exit!\r\n"); 
return 1; 

printf("Head:0x%x-%c-%c-%c\r\n", *((char *)paddr + 0),*((char *)paddr + 1),*((char *)paddr + 2),*((char *)paddr + 3)); 
memcpy(block, paddr, BLOCK_SIZE); 
iSize = fwrite(block, 1, BLOCK_SIZE, pFile); 
if (BLOCK_SIZE != iSize) 

perror("fwrite error:\r\n"); 

printf("copy %d/%d bytes from 0x%x to the file\r\n", iSize, BLOCK_SIZE, paddr); 

fclose(pFile); 
printf("Generate linux-gate.dso Done\r\n"); 

return 0; 


然后看下导出的结果:

如何获取linux-gate.so.1动态库

这样我们就能在动态映射的情况下也能导出动态库。app_linux_gate_so.c如果做适当修改就能导出所有映射的动态内存库,用于DEBUG和验证了。


本文永久更新地址:http://www.linuxdiyf.com/linux/19089.html