用List和Map文件定位bug

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
	char* ptr = NULL;
	*ptr = 'A';
	return 0;
}

这段程序bug很显见,要定位bug也不难。但是,如果把这代码发布出去,直接运行会有这样的错误,最多看到汇编指令:

这时怎么定位程序?

首先0x00CA1378,这地址看着有点高,一般程序加载在0x00400000,看着就是随机地址加载。怎么验证是随机地址加载?程序的bug只有一处,每次运行都应该在同一处发生bug。但是再次运行程序,bug的地址发生了变化:

这就可以确定是随机地址加载。因此首先在属性-链接器-高级选项中关闭随机基址和打开固定基址。

这之后,每次发生bug的地址都是固定的,到此可以确定bug地址。

但是,源码不在发布现场,现场也没调试器。定位代码还是不方便。有什么办法可以大概的定位到哪条语句?这时就如文章标题所说用到Map文件和List文件:

产生List文件:属性-c/c++-输出文件-汇编程序输出:程序集、机器码和源代码 (/FAcs)

产生Map文件:属性-连接器-调试-生成映射文件:是 (/MAP)

这里解释一下各个文件的意义:

List文件,包含源文件编译后(未连接)的行号和重定位汇编代码,如下:

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

	TITLE	C:\studio\mapAsm\mapAsm\mapAsm\mapAsm.cpp
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC	_wmain
EXTRN	__RTC_Shutdown:PROC
EXTRN	__RTC_InitBase:PROC
;	COMDAT rtc$TMZ
; File c:\studio\mapasm\mapasm\mapasm\mapasm.cpp
rtc$TMZ	SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ	ENDS
;	COMDAT rtc$IMZ
rtc$IMZ	SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ	ENDS
;	COMDAT _wmain
_TEXT	SEGMENT
_ptr$ = -8						; size = 4
_argc$ = 8						; size = 4
_argv$ = 12						; size = 4
_wmain	PROC						; COMDAT

; 8    : {

  00000	55		 push	 ebp
  00001	8b ec		 mov	 ebp, esp
  00003	81 ec cc 00 00
	00		 sub	 esp, 204		; 000000ccH
  00009	53		 push	 ebx
  0000a	56		 push	 esi
  0000b	57		 push	 edi
  0000c	8d bd 34 ff ff
	ff		 lea	 edi, DWORD PTR [ebp-204]
  00012	b9 33 00 00 00	 mov	 ecx, 51			; 00000033H
  00017	b8 cc cc cc cc	 mov	 eax, -858993460		; ccccccccH
  0001c	f3 ab		 rep stosd

; 9    : 	char* ptr = NULL;

  0001e	c7 45 f8 00 00
	00 00		 mov	 DWORD PTR _ptr$[ebp], 0

; 10   : 	*ptr = 'A';

  00025	8b 45 f8	 mov	 eax, DWORD PTR _ptr$[ebp]
  00028	c6 00 41	 mov	 BYTE PTR [eax], 65	; 00000041H

; 11   : 	return 0;

  0002b	33 c0		 xor	 eax, eax

; 12   : }

  0002d	5f		 pop	 edi
  0002e	5e		 pop	 esi
  0002f	5b		 pop	 ebx
  00030	8b e5		 mov	 esp, ebp
  00032	5d		 pop	 ebp
  00033	c3		 ret	 0
_wmain	ENDP
_TEXT	ENDS
END
Map文件:连接后各个符号的链接地址,因为编译器假设连接地址就是加载地址,所以在固定基址的情况下程序会按链接地址加载到内存0x40000;但是启用了随机基址,那就连接地址跟加载地址不同,真心不好定位了。如图,显示了各个文件的链接地址:

  Address         Publics by Value              Rva+Base       Lib:Object

 0000:00000000       ___safe_se_handler_table   00000000     <absolute>
 0000:00000000       ___safe_se_handler_count   00000000     <absolute>
 0000:00000000       ___ImageBase               00400000     <linker-defined>
 0001:00000000       __enc$textbss$begin        00401000     <linker-defined>
 0001:00010000       __enc$textbss$end          00411000     <linker-defined>
 0002:00000350       _wmain                     00411350 f   mapAsm.obj
 0002:000003a0       __RTC_InitBase             004113a0 f   MSVCRTD:_init_.obj
 0002:000003e0       __RTC_Shutdown             004113e0 f   MSVCRTD:_init_.obj
 0002:00000520       _wmainCRTStartup           00411520 f   MSVCRTD:wcrtexe.obj
 0002:00000840       _NtCurrentTeb              00411840 f i MSVCRTD:wcrtexe.obj
 0002:000008e0       __RTC_NumErrors            004118e0 f   MSVCRTD:_userapi_.obj
 0002:000008f0       __RTC_GetErrDesc           004118f0 f   MSVCRTD:_userapi_.obj
 0002:00000910       __RTC_SetErrorType         00411910 f   MSVCRTD:_userapi_.obj
 0002:00000940       __RTC_SetErrorFunc         00411940 f   MSVCRTD:_userapi_.obj
 0002:00000970       __RTC_SetErrorFuncW        00411970 f   MSVCRTD:_userapi_.obj

程序异常发生在0x411378,正好在mapAsm.obj文件范围内:

异常指令的地址是0x411378,而mapAsm的地址是0x411350,两者相差0x28B。来看下这个偏移上的源文件和汇编代码:

; 10   : 	*ptr = 'A';

  00025	8b 45 f8	 mov	 eax, DWORD PTR _ptr$[ebp]
  00028	c6 00 41	 mov	 BYTE PTR [eax], 65	; 00000041H

果然是给空指针赋值引起~。知道Map文件和List文件的作用了吧。

附注,gcc也有类似功能,可参考如下连接:

http://blog.csdn.net/lanxinju/article/details/5900986

http://blog.chinaunix.net/uid-24567872-id-209622.html


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值