VC程序的SECTION(3):.text
来源:互联网 发布:数控激光切割机编程 编辑:程序博客网 时间:2024/06/05 14:13
快乐虾
http://blog.csdn.net/lights_joy/
lights@wo.com.cn
本文适用于
Xp sp3 / Vs2008
欢迎转载,但请保留作者信息
这个节看起来很容易理解,不就是存放代码的嘛,看看头信息:
SECTION HEADER #2
.text name
3482 virtual size
11000 virtual address (00411000 to 00414481)
3600 size of raw data
400 file pointer to raw data (00000400 to 000039FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
比较.textbss可以看到这一节是只读的,但.textbss则是可以读写的。
下面讨论一下几个比较有意思的问题。
1.1.1 ILT表
查看符号表,可以发现从.text节的开始到第一个函数代码中间有一段空间:
0002:000003a0 ?add@@YAHHH@Z 004113a0 f demo.obj
根据.textbss节中获取的信息,我们可以知道当启用增量链接时,这一段空间用于存放ILT表。
1.1.2 DLL中的函数
在符号表中还有这样一些有趣的符号:
0002:000024e2 _GetCurrentProcessId@0 004134e2 f kernel32:KERNEL32.dll
0002:000024e8 _GetSystemTimeAsFileTime@4 004134e8 f kernel32:KERNEL32.dll
这些函数应该是在DLL中实现的,为何会出现符号表中呢?而且每个函数都只有6个字节,在反汇编中看看到底是什么:
GetCurrentProcessId:
004134E2 jmp dword ptr [__imp__GetCurrentProcessId@0 (4181BCh)]
GetSystemTimeAsFileTime:
004134E8 jmp dword ptr [__imp__GetSystemTimeAsFileTime@4 (4181B8h)]
又是jmp,又是ILT?关闭增量链接,再看这段地址,依然存放,很不幸地猜想失败。
在函数中加上对此函数的调用,在符号表中可以看到GetCurrentProcessId的地址发生了变化:
0002:00000446 _GetCurrentProcessId@0 00411446 f kernel32:KERNEL32.dll
但反汇编的结果显示它的内容并没有变化:
GetCurrentProcessId:
00411446 jmp dword ptr [__imp__GetCurrentProcessId@0 (418198h)]
再看调用者的反汇编代码:
int n = GetCurrentProcessId();
004113FE mov esi,esp
00411400 call dword ptr [__imp__GetCurrentProcessId@0 (418198h)]
00411406 cmp esi,esp
00411408 call @ILT+315(__RTC_CheckEsp) (411140h)
0041140D mov dword ptr [n],eax
这里直接调用的是__imp__GetCurrentProcessId@0函数,那么为什么还要生成前面那个jmp代码呢?据说这个问题深究起来比较复杂,先放过它,到DLL中学习它。
1.1.3 自定义节
使用
#pragma code_seg("code1")
可以自定义一个code section,节的名字就是code1,需要注意的是这个语句的作用范围为当前文件。
试试看:
#pragma code_seg("code1")
int add(int a, int b)
{
return a + b + 10;
}
int _tmain(int argc, _TCHAR* argv[])
{
add(3, 4);
return 0;
}
用dumpbin查看生成的头信息,发现多了一个节:
SECTION HEADER #1
code1 name
77 virtual size
1000 virtual address (00401000 to 00401076)
200 size of raw data
400 file pointer to raw data (00000400 to 000005FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
对照符号表中这一节的符号:
0001:00000000 ?add@@YAHHH@Z 00401000 f demo.obj
0001:00000030 _main 00401030 f demo.obj
非常符合我们的期望。
1.1.4 改变节中函数的顺序
下面尝试改变code1节中main函数与add函数的顺序。
在code1这个节名称的后面加上尾缀:
#pragma code_seg("code1$b")int add(int a, int b){ return a + b + 10;} #pragma code_seg("code1$a")int _tmain(int argc, _TCHAR* argv[]){ add(3, 4); return 0;}
VS将$之前的部分视为节的名称,再根据$后的字母进行排序。
再看生成的符号表:
0001:00000000 _main 00401000 f demo.obj
0001:00000040 ?add@@YAHHH@Z 00401040 f demo.obj
符合我们的期望。
当不加$及之后的尾缀时,默认放在最前。
利用链接器的这种特性,我们很容易就可以获取一个节的起始位置和结束位置。
1.1.5 获取.text节的起始地址
.text用于默认存放代码,VS并没有象GNU TOOLCHAIN那样提供链接器的符号,因而只有自己动态查询,就像这样的:
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
HMODULE hModule;
MODULEINFO modinfo;
DWORD dwBase, cbNeeded;
BYTE* lpbuf;
HANDLE hProcess = ::GetCurrentProcess();
EnumProcessModules(hProcess, &hModule, sizeof(HMODULE), &cbNeeded);
GetModuleInformation( hProcess, hModule, &modinfo, sizeof(MODULEINFO) );
// 根据lpBaseOfDll得到其它的数据
lpbuf = (BYTE*)modinfo.lpBaseOfDll;
//取得节数目
pfh = (PIMAGE_FILE_HEADER) ((LPVOID)((BYTE *)(lpbuf)+((PIMAGE_DOS_HEADER)(lpbuf))-> e_lfanew+sizeof(DWORD)));
int nSectionCount = pfh-> NumberOfSections;
poh = (PIMAGE_OPTIONAL_HEADER)(pfh + 1);
psh = (PIMAGE_SECTION_HEADER) ((LPVOID)((BYTE *)pfh + sizeof(IMAGE_FILE_HEADER) + pfh->SizeOfOptionalHeader));
dwBase = 0;
for(int i = 0; i < nSectionCount; i++)
{
if(strcmp( ".text", (char *)psh->Name) == 0)
{
dwBase = (DWORD)modinfo.lpBaseOfDll + psh->VirtualAddress;
}
psh++;
}
- VC程序的SECTION(3):.text
- VC枚举配置文件的Section存入Map
- VC应用程序中的SECTION(1):准备工作
- 设置3维视图的Section Box 的范围(Section Box坐标系统)
- ".section .text.lock,\"ax\"\n" \
- VC 中TEXT、_T、L的区别
- VC 中TEXT、_T、L的区别
- VC 中TEXT、_T、L的区别
- VC 中TEXT、_T、L的区别
- 一个好用的程序编辑软件Sublime Text 3
- Section mismatch in reference from the variable to the function.devinit.text:spiadc_probe()的解决方法
- VC的Profile(测试程序瓶颈)
- VC的托盘程序
- VC的拨号上网程序
- VC的托盘程序
- VC的拨号上网程序
- 有趣的vc程序
- VC的托盘程序
- 我在Salira的800天(2009.5.20~2011.7.29)-三.研究与学习篇
- mysql特殊查询
- 一个体现Java接口及工厂模式优点的例子
- 深入浅出C++之private/public/protected
- 菜鸟之驱动开发4
- VC程序的SECTION(3):.text
- 云参考框架 (大图)
- vs2010+wdk7600+XXX环境配置,随后2步最重要,其他和网上搜的大同小异
- CInternetSession的简单使用
- menu.addIntentOptions 添加动态菜单
- 我在Salira的800天(2009.5.20~2011.7.29)-四.总结篇
- Explain plan Oracle优化工具安装及使用
- 【Qt】Web与本地应用的混合开发
- Sql Server 2008 R2 error:40 错误处理