程序员的自我修养

p247

共享库构造和析构函数

GCC提供共享库的构造函数,早函数声明时加上“__attribute__((constructor))”属性即可成为共享库构造函数,会在共享库被加载时执行,即在main函数之前执行。使用dlopen()打开时会在dlopen()返回前执行。
同样“__attribute__((destructor))”表示共享库析构函数,在main()函数返回后会被执行。如果使用dlclose()卸载共享库则会在dlclose()返回前执行。
如果有多个构造函数可以传一个优先级参数如:
void __attribute__((constructor(5))) init_function1(void);
void __attribute__((constructor(10))) init_function2(void);
优先级数字越小,优先级越高。析构函数则刚好相反。

共享库脚本

共享库不止是动态链接的ELF的共享文件(.so),还可以是符合格式的链接脚本文件。
例如可以把C运行库和数学库组成一个新的libfoo.so,内容可以如下:
GROUP { /lib/libc.so.6 /lib/libm.so.2 }

程序的内存布局

p284
32位系统中windows会将高地址的2GB分给内核,linux会将高地址的1GB分给内核,剩下的成为用户空间。

应用程序的地址空间有如下几个默认区:

  • 栈 :用于维护函数调用的上下文,通常在用户控件的最高地址处分配,由高到低增长,大概几M大小。
  • 堆 :用来容纳程序动态分配的内存,位于栈的下方,由低到高增长。一般没有固定存储区域,几百M大小往上。
  • 可执行文件映像 :将可执行文件的内存读取或映射到这个区。
  • 保留区 :对内存中收到保护而禁止访问的内存区域的总称。

linux下如果可执行文件以来其他共享库,那么系统就会为它在从0x40000000开始的地址分配响应的空间,并将共享库装入该空间。

和栈相关的寄存器
i386下栈顶由esp寄存器进行定位,esp指向栈顶。
由于栈的生长方向从上到下,亚展会使esp减小,弹栈会使esp增大。

ebp用于标识访问的参数地址,ebp又称为帧指针(Frame Pointer)

编译完的汇编中,在函数地址后跟着几个nop地址,可以插入用于跳转的指令,用此机制实现Hook

posted @ 2023-11-01 14:38  fashow  阅读(5)  评论(0编辑  收藏  举报