共享库的全局变量以及gcc相关配置
时间:2009-07-02 来源:hylpro
共享库的全局变量
gcc使用的库版本
编译gcc的配置选项
其他gcc信息dump
1)生成动态链接库libtest.so
---test.h---
#ifndef __TEST_H__
#define __TEST_H__
#include <stdio.h>
#include <stdlib.h>
extern int test_a();
extern int test_b();
extern int test_c();
extern int global_test;
#endif
--test.c--
#include "test.h"
int global_test = 0x123456;
int test_a()
{
printf("in test a \n");
printf("%d\n",global_test);
return 0;
}
gcc -g test.h test.c -fPIC -shared -o libtest.so
2)引用这个动态连接库
--main.c---
include "test.h"
#include <errno.h>
int main()
{
int * ptest =(int *) &global_test;
int *perrno = (int *) & errno;
printf("0x%x\n",(unsigned int)ptest);
printf("0x%x\n",(unsigned int)perrno);
}
gcc -I. -ltest -g main.c -o test
3)反汇编
~/works/dll$ gdb -q test
(gdb) disassemble main
Dump of assembler code for function main:
0x08048514 <main+0>: lea 0x4(%esp),%ecx
0x08048518 <main+4>: and $0xfffffff0,%esp
0x0804851b <main+7>: pushl -0x4(%ecx)
0x0804851e <main+10>: push %ebp
0x0804851f <main+11>: mov %esp,%ebp
0x08048521 <main+13>: push %ecx
0x08048522 <main+14>: sub $0x24,%esp
0x08048525 <main+17>: movl $0x804a018,-0x8(%ebp)
0x0804852c <main+24>: call 0x8048418 <__errno_location@plt>
0x08048531 <main+29>: mov %eax,-0xc(%ebp)
0x08048534 <main+32>: mov -0x8(%ebp),%eax
0x08048537 <main+35>: mov %eax,0x4(%esp)
0x0804853b <main+39>: movl $0x8048630,(%esp)
0x08048542 <main+46>: call 0x8048448 <printf@plt>
0x08048547 <main+51>: mov -0xc(%ebp),%eax
0x0804854a <main+54>: mov %eax,0x4(%esp)
0x0804854e <main+58>: movl $0x8048630,(%esp)
0x08048555 <main+65>: call 0x8048448 <printf@plt>
0x0804855a <main+70>: mov $0x0,%eax
0x0804855f <main+75>: add $0x24,%esp
0x08048562 <main+78>: pop %ecx
0x08048563 <main+79>: pop %ebp
---Type <return> to continue, or q <return> to quit---
0x08048564 <main+80>: lea -0x4(%ecx),%esp
0x08048567 <main+83>: ret
End of assembler dump.
(gdb) info symbol 0x804a018
global_test in section .bss
(gdb) disassemble 0x8048418
Dump of assembler code for function __errno_location@plt:
0x08048418 <__errno_location@plt+0>: jmp *0x804a000
0x0804841e <__errno_location@plt+6>: push $0x0
0x08048423 <__errno_location@plt+11>: jmp 0x8048408 <_init+48>
End of assembler dump.
(gdb)
4)通过gdb我们可以看到,引用libtest.so中定义的全局变量global_test在连接的时候就确定的地址804a01,而引用libc中的errno全局变量却需要通过plt/got来确定最终的问题。为什么?
原因探讨:
从/usr/include/errno.h => /usr/include/bits/errno.h可以看到如下定义:
if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */
errno不是纯粹意义上的global variant,所有静态库的数据段可以合并但是text不能,所以有这个现象.
另外一个问题: gcc 连接的时候如何知道用哪个版本的动态连接库:
应该是和所用gcc决定的, 想想在制作发行版的时候对gcc的编译吧, 需要一个libc, 而后,所有的程序都用这个版本的gcc和这个库编译出来的.
查看方法:
gcc -dumpspecs | more 寻找下面的一段:
*link:
%{!static:--eh-frame-hdr} %{m64:-m elf_x86_64} %{!m64:-m elf_i386} --hash-style=both %{shared:-shared} %{!shared:
%{!static: %{rdynamic:-export-dynamic} %{!m64:%{!dynamic-linker:-dynamic-linker %{muclibc:%{mglibc:%e-mgli
bc and -muclibc used together}/lib/ld-uClibc.so.0;:/lib/ld-linux.so.2}}} %{m64:%{!dynamic-linker:-dynamic-linker %
{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld64-uClibc.so.0;:/lib64/ld-linux-x86-64.so.2}}}} %{stat
ic:-static}}
然后 readelf -a /lib/ld-linux.so.2 | more 看看, 这个连接器中有几个支持的glibc库版本(猜测):
Version definition section '.gnu.version_d' contains 6 entries:
Addr: 0x0000000000000638 Offset: 0x000638 Link: 4 (.dynstr)
000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: ld-linux.so.2
0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: GLIBC_2.0
0x0038: Rev: 1 Flags: none Index: 3 Cnt: 2 Name: GLIBC_2.1
0x0054: Parent 1: GLIBC_2.0
0x005c: Rev: 1 Flags: none Index: 4 Cnt: 2 Name: GLIBC_2.3
0x0078: Parent 1: GLIBC_2.1
0x0080: Rev: 1 Flags: none Index: 5 Cnt: 2 Name: GLIBC_2.4
0x009c: Parent 1: GLIBC_2.3
0x00a4: Rev: 1 Flags: none Index: 6 Cnt: 2 Name: GLIBC_PRIVATE
0x00c0: Parent 1: GLIBC_2.4
可以这样:(http://www.linuxsir.org/bbs/showthread.php?t=244899)
gcc -print-file-name=libc.so
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libc.so
cat /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
readlink /lib/libc.so.6
libc-2.7.so
另外途径是:
/lib/libc.so.6
GNU C Library stable release version 2.7, by Roland McGrath et al.
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.2.4 (Ubuntu 4.2.4-1ubuntu1).
Compiled on a Linux >>2.6.24-16-server<< system on 2008-09-12.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
搜索路径可以用gcc --print-search-dir 来查看
install: /usr/lib/gcc/i486-linux-gnu/4.2.4/
programs: =/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/libexec/gcc/i486-linux-gnu/4.2.4/:/usr/libexec/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/bin/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/bin/
libraries: =/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/:/lib/i486-linux-gnu/4.2.4/:/lib/../lib/:/usr/lib/i486-linux-gnu/4.2.4/:/usr/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../:/lib/:/usr/lib/
查看编译gcc的选项:
gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
gcc使用的库版本
编译gcc的配置选项
其他gcc信息dump
1)生成动态链接库libtest.so
---test.h---
#ifndef __TEST_H__
#define __TEST_H__
#include <stdio.h>
#include <stdlib.h>
extern int test_a();
extern int test_b();
extern int test_c();
extern int global_test;
#endif
--test.c--
#include "test.h"
int global_test = 0x123456;
int test_a()
{
printf("in test a \n");
printf("%d\n",global_test);
return 0;
}
gcc -g test.h test.c -fPIC -shared -o libtest.so
2)引用这个动态连接库
--main.c---
include "test.h"
#include <errno.h>
int main()
{
int * ptest =(int *) &global_test;
int *perrno = (int *) & errno;
printf("0x%x\n",(unsigned int)ptest);
printf("0x%x\n",(unsigned int)perrno);
}
gcc -I. -ltest -g main.c -o test
3)反汇编
~/works/dll$ gdb -q test
(gdb) disassemble main
Dump of assembler code for function main:
0x08048514 <main+0>: lea 0x4(%esp),%ecx
0x08048518 <main+4>: and $0xfffffff0,%esp
0x0804851b <main+7>: pushl -0x4(%ecx)
0x0804851e <main+10>: push %ebp
0x0804851f <main+11>: mov %esp,%ebp
0x08048521 <main+13>: push %ecx
0x08048522 <main+14>: sub $0x24,%esp
0x08048525 <main+17>: movl $0x804a018,-0x8(%ebp)
0x0804852c <main+24>: call 0x8048418 <__errno_location@plt>
0x08048531 <main+29>: mov %eax,-0xc(%ebp)
0x08048534 <main+32>: mov -0x8(%ebp),%eax
0x08048537 <main+35>: mov %eax,0x4(%esp)
0x0804853b <main+39>: movl $0x8048630,(%esp)
0x08048542 <main+46>: call 0x8048448 <printf@plt>
0x08048547 <main+51>: mov -0xc(%ebp),%eax
0x0804854a <main+54>: mov %eax,0x4(%esp)
0x0804854e <main+58>: movl $0x8048630,(%esp)
0x08048555 <main+65>: call 0x8048448 <printf@plt>
0x0804855a <main+70>: mov $0x0,%eax
0x0804855f <main+75>: add $0x24,%esp
0x08048562 <main+78>: pop %ecx
0x08048563 <main+79>: pop %ebp
---Type <return> to continue, or q <return> to quit---
0x08048564 <main+80>: lea -0x4(%ecx),%esp
0x08048567 <main+83>: ret
End of assembler dump.
(gdb) info symbol 0x804a018
global_test in section .bss
(gdb) disassemble 0x8048418
Dump of assembler code for function __errno_location@plt:
0x08048418 <__errno_location@plt+0>: jmp *0x804a000
0x0804841e <__errno_location@plt+6>: push $0x0
0x08048423 <__errno_location@plt+11>: jmp 0x8048408 <_init+48>
End of assembler dump.
(gdb)
4)通过gdb我们可以看到,引用libtest.so中定义的全局变量global_test在连接的时候就确定的地址804a01,而引用libc中的errno全局变量却需要通过plt/got来确定最终的问题。为什么?
原因探讨:
从/usr/include/errno.h => /usr/include/bits/errno.h可以看到如下定义:
if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */
errno不是纯粹意义上的global variant,所有静态库的数据段可以合并但是text不能,所以有这个现象.
另外一个问题: gcc 连接的时候如何知道用哪个版本的动态连接库:
应该是和所用gcc决定的, 想想在制作发行版的时候对gcc的编译吧, 需要一个libc, 而后,所有的程序都用这个版本的gcc和这个库编译出来的.
查看方法:
gcc -dumpspecs | more 寻找下面的一段:
*link:
%{!static:--eh-frame-hdr} %{m64:-m elf_x86_64} %{!m64:-m elf_i386} --hash-style=both %{shared:-shared} %{!shared:
%{!static: %{rdynamic:-export-dynamic} %{!m64:%{!dynamic-linker:-dynamic-linker %{muclibc:%{mglibc:%e-mgli
bc and -muclibc used together}/lib/ld-uClibc.so.0;:/lib/ld-linux.so.2}}} %{m64:%{!dynamic-linker:-dynamic-linker %
{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld64-uClibc.so.0;:/lib64/ld-linux-x86-64.so.2}}}} %{stat
ic:-static}}
然后 readelf -a /lib/ld-linux.so.2 | more 看看, 这个连接器中有几个支持的glibc库版本(猜测):
Version definition section '.gnu.version_d' contains 6 entries:
Addr: 0x0000000000000638 Offset: 0x000638 Link: 4 (.dynstr)
000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: ld-linux.so.2
0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: GLIBC_2.0
0x0038: Rev: 1 Flags: none Index: 3 Cnt: 2 Name: GLIBC_2.1
0x0054: Parent 1: GLIBC_2.0
0x005c: Rev: 1 Flags: none Index: 4 Cnt: 2 Name: GLIBC_2.3
0x0078: Parent 1: GLIBC_2.1
0x0080: Rev: 1 Flags: none Index: 5 Cnt: 2 Name: GLIBC_2.4
0x009c: Parent 1: GLIBC_2.3
0x00a4: Rev: 1 Flags: none Index: 6 Cnt: 2 Name: GLIBC_PRIVATE
0x00c0: Parent 1: GLIBC_2.4
可以这样:(http://www.linuxsir.org/bbs/showthread.php?t=244899)
gcc -print-file-name=libc.so
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libc.so
cat /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
readlink /lib/libc.so.6
libc-2.7.so
另外途径是:
/lib/libc.so.6
GNU C Library stable release version 2.7, by Roland McGrath et al.
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.2.4 (Ubuntu 4.2.4-1ubuntu1).
Compiled on a Linux >>2.6.24-16-server<< system on 2008-09-12.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
搜索路径可以用gcc --print-search-dir 来查看
install: /usr/lib/gcc/i486-linux-gnu/4.2.4/
programs: =/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/libexec/gcc/i486-linux-gnu/4.2.4/:/usr/libexec/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/bin/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/bin/
libraries: =/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../i486-linux-gnu/4.2.4/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/:/lib/i486-linux-gnu/4.2.4/:/lib/../lib/:/usr/lib/i486-linux-gnu/4.2.4/:/usr/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i486-linux-gnu/lib/:/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../:/lib/:/usr/lib/
查看编译gcc的选项:
gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
相关阅读 更多 +