我们知道,Unix操作系统程序的链接分为静态链接和动态链接,静态链接就是把所有所引用到的函数或变量全部地编译到可执行文件中。今天我们就来学习下这方面的知识。
我们先来用GDB来研究一下Unix操作系统程序的反汇编。注意其中的一些部分。那就是if语句。如果条件失败,则会转到
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048368
:push %ebp - 0x08048369
:mov%esp,%ebp - 0x0804836b
:sub$0x18,%esp - 0x0804836e
:and$0xfffffff0,%esp - 0x08048371
:mov$0x0,%eax - 0x08048376
: add$0xf,%eax - 0x08048379
: add$0xf,%eax - 0x0804837c
: shr$0x4,%eax - 0x0804837f
: shl$0x4,%eax - 0x08048382
: sub%eax,%esp - 0x08048384
: movl $0x1,0xfffffffc(%ebp) - 0x0804838b
: movl $0x2,0xfffffff8(%ebp) - 0x08048392
: mov0xfffffffc(%ebp),%eax - 0x08048395
: cmp0xfffffff8(%ebp),%eax - 0x08048398
: je 0x80483b3 - 0x0804839a
: sub$0xc,%esp - 0x0804839d
: push $0x80484b0 - 0x080483a2
: call 0x80482b0 - 0x080483a7
: add$0x10,%esp - 0x080483aa
: movl $0x0,0xfffffff4(%ebp) - 0x080483b1
: jmp0x80483ca - 0x080483b3
: sub$0xc,%esp - 0x080483b6
: push $0x80484b8 - 0x080483bb
: call 0x80482b0 - 0x080483c0
: add$0x10,%esp - 0x080483c3
: movl $0x1,0xfffffff4(%ebp) - 0x080483ca
: mov0xfffffff4(%ebp),%eax - 0x080483cd
: leave - 0x080483ce
: ret - End of assembler dump.
下面是我们Unix操作系统重载printf的so文件。让printf返回后的栈地址变成
- #include
- static int (*_printf)(const char *format, ...) = NULL;
- int printf(const char *format, ...)
- {
- if (_printf == NULL) {
- /* 取得标准库中的printf的函数地址 */
- _printf = (int (*)(const char *format, ...)) dlsym(RTLD_NEXT, "printf");
- /* 把函数返回的地址置到
*/ - __asm__ __volatile__ (
- "movl 0x4(%ebp), %eax \n"
- "addl $15, %eax \n"
- "movl %eax, 0x4(%ebp)"
- );
- return 1;
- }
- /* 重置 printf的返回地址 */
- __asm__ __volatile__ (
- "addl $12, %%esp \n"
- "jmp *%0 \n"
- : /* no output registers */
- : "g" (_printf)
- : "%esp"
- );
- }
你可以在你的Unix操作系统下试试这段代码。
【编辑推荐】
上一篇:对Oracle 性能工具的关注
下一篇:探析Unix操作系统启动