0
点赞
收藏
分享

微信扫一扫

随想录(windows静态库和动态库)


【 声明:版权所有,欢迎转载,请勿用于商业用途。】

 

    在软件编程当中,动态库还是很有意思的。相比较静态库而言,动态库不管是开发、还是升级等方面都比较方便。当然为了适应动态库的这种动态加载的特点,编译器在生成动态库的时候,对于外面的数据和函数访问都不是直接访问,一般都是间接调用的,这是有动态库本身的特点决定的。我们可以做一个简单的例子,

 

1、首先在vs2010或者vs2015上面创建一个动态库工程,

extern "C" _declspec(dllexport) int add(int a, int b);
extern "C" _declspec(dllexport) int value = 10;

int add(int a, int b)
{
return a + b;
}

 

2、编译生成对应的lib文件和dll文件,姑且称之为add.lib & add.dll。

 

3、创建一个app工程,准备调用这个dll文件,

#include "stdafx.h"

#pragma comment(lib,"../Debug/add.lib")

extern "C" _declspec(dllimport) int add(int a, int b);
extern "C" _declspec(dllimport) int value;

int main()
{
printf("%d\n", add(1,2));
printf("%d\n", value);
return 0;
}

 

4、编译app工程,可以正常运行,说明app成功执行。

 

5、分别在main函数的第1行、第2行,dll工程的DllMain添加断点,

a,首先DllMain被断住,继续运行

b,接着main的第一行被断住,继续运行

c,接着main的第二行被断住,继续运行

d,最后DllMain被断住,可以观察到DllMain被断住两次。

 

6、分析远程函数的调用方法,可以观察是间接调用,观察反汇编代码,

printf("%d\n", add(1,2));
001317CE mov esi,esp
001317D0 push 2
001317D2 push 1
001317D4 call dword ptr ds:[13A0ECh]

    在0x001317D4后面还有一个jmp跳转,

_add:
79BC10D2 jmp add (79BC15A0h)

 

7、分析全局变量的调用,

printf("%d\n", value);
001317F2 mov eax,dword ptr ds:[0013A0E8h]
001317F7 mov ecx,dword ptr [eax]
001317F9 push ecx
001317FA push 136B30h
001317FF call _printf (0131325h)
00131804 add esp,8

    这里value数值的获取,很明显是首先获取eax地址,再从eax获取ecx而来,ecx就是value的数值。

 

8、静态库

  如果是静态库,代码就比较简单了,

//a.cpp

extern "C" int sub(int data)
{
return 1;
}

// b.cpp

#pragma comment(lib,"../Debug/sub.lib")

extern "C" int sub(int);

 

9、总结

    既然是动态库,涉及到外部的函数和变量,总是要多绕一点弯。linux下面使用.got & .got.plt来完成的。或者大家在名称上面有一点不同,但是其实原理都是一致的。动态库的正确执行还需要加载器和操作系统的积极配合,主要是loader的工作做的更多一些。

 

举报

相关推荐

0 条评论