Find the source code error line only through the crash address
1. Set up the compiler to generate the map file at compile time.
(1) C + +:/zd
(2) Link:
/map[:filename]
/map:lines
/map:export (used when DLL)
2. Using the Map file
(1) After browsing the rva+base, you will find the first function address larger than the crash address, the entry function before this address, which is the function that produces the crash.
(2) Determine the xxx.obj where the resulting crash function is located.
Use formula:
Crash row offset = Crash Address (Crash addresses)-base address (ImageBase adress)-0x1000
Computed "Crash code line offset".
(3) In the map file species, the crash is located in the Xxx.obj line numbers information information to find the first one than the "Crash code line cheap" Large row memory address,
This address corresponds to the row's previous line, which is the crash line.
========================================
Reference:
Title: Find the source code error line only through the crash address (11,000 words)
Sender: Lao Luo
Time: 2003-2-7 14:01:56
Detailed information:
As a programmer, we are usually most worried about what to see. is a memory leak. The interface is not good-looking. ...... Wrong. I believe there is no objection to my view-that is, the program has collapsed.
"The program has performed an illegal operation and is about to close. Please contact your software vendor. ", hehe, this sentence m$" famous words ", I am afraid the programmer is most worried about seeing things. Sometimes, your own program runs well on your own machine, but when it comes to someone else's machine, it breaks down, and sometimes I get the illegal operation in the process of writing and testing, but I can't determine which line in the source code is causing it ... Is it painful? It doesn't matter, this article can help you out of this predicament, even after you can proudly ask users to tell you the crash address, and then you can accurately locate the source code error in the line. (It's amazing.) Oh. )
First of all, I must stress that this method can be used on any compiler currently available on the market. But I'm only familiar with m$ VC and MASM, so the next section only describes how to implement them in these two compilers, and ask readers to master the methods used on other compilers.
Now, let's get this over with. :)
You must first generate the program's MAP file. What is a MAP file. Simply put, the MAP file is the only textual representation of the program's global symbols, source files, and code line number information, which can be used anywhere, anytime, without additional program support. And that's the only way to find out where the program crashed.
Well, now that the MAP file is so magical, how do we build it? In VC, we can press ALT+F7, open the Project Settings Options page, select the C + + tab, and enter the following project options:/zd, and then select the Link tab, at the bottom of project O Ptions inside Input:/mapinfo:lines and/map:project_name.map. Finally press F7 to compile the build EXE executable and MAP file.
In MASM, we want to set compilation and connection parameters, which I usually do:
RC%1.rc
ML/C/coff/zd%1.asm
Link/subsystem:windows/mapinfo:exports/mapinfo:lines/map:%1.map%1.obj%1.res
Save it as a makem.bat, you can enter Makem filename at the command line to compile the build EXE executable and MAP file.
Let me first explain the meaning of the parameters added:
/ZD indicates that line information is generated at compile time
/map[:filename] represents the path and filename of the build map file
/mapinfo:lines represents adding line information when generating a MAP file
/mapinfo:exports indicates that when the MAP file is generated, add exported functions (if the DLL file is generated, this option will be added)
OK, we've got the MAP file through the steps above, so how do we use it?
Let's start with a simple example, please open your VC, create a new file like this:
01//****************************************************************
02//Program Name: Demonstrates how to find the source code error line through the crash address
03//Author: Rocon
04//Date: 2003-2-7
05//Source: Http://www.luocong.com (the fun of the Old World)
06//This program will produce "except 0 error", so that the "Illegal Operation" dialog box will pop up.
07//"Except 0 errors" will only be generated under the Debug version, this program is as simple as possible to demonstrate.
08//Note: If you wish to reprint, please keep this procedure complete, and indicate:
09//reprinted from "The Fun world of the old" (http://www.luocong.com)
10//****************************************************************
11
void Crash (void)
13 {
int i = 1;
int j = 0;
I/= J;
17}
18
void Main (void)
20 {
Crash ();
22}
Obviously this program has "except 0 errors", in the Debug mode of compiling, the runtime will certainly produce "illegal operation." OK, let's run it, sure enough, the "Illegal Operation" dialog box appears, and then we click on the "Details" button to record the address where the crash occurred--0x0040104a on my machine.
Then look at its MAP file: (because the file content is too long, the middle of the useless Part I omitted)
Crashdemo
Timestamp is 3e430a76 (Fri Feb 07 09:23:02 2003)
Preferred load address is 00400000
Start Length Name Class
0001:00000000 0000de04h. Text CODE
0001:0000de04 0001000cH. TEXTBSS CODE
0002:00000000 00001346H. Rdata DATA
0002:00001346 00000000H. Edata DATA
0003:00000000 00000104H. Crt$xca DATA
0003:00000104 00000104H. Crt$xcz DATA
0003:00000208 00000104H. Crt$xia DATA
0003:0000030c 00000109H. Crt$xic DATA
0003:00000418 00000104H. Crt$xiz DATA
0003:0000051c 00000104H. Crt$xpa DATA
0003:00000620 00000104H. Crt$xpx DATA
0003:00000724 00000104H. Crt$xpz DATA
0003:00000828 00000104H. Crt$xta DATA
0003:0000092C 00000104H. Crt$xtz DATA
0003:00000a30 00000b93h. Data data
0003:000015C4 00001974H. BSS DATA
0004:00000000 00000014H. idata$2 DATA
0004:00000014 00000014H. Idata$3 DATA
0004:00000028 00000110H. idata$4 DATA
0004:00000138 00000110H. Idata$5 DATA
0004:00000248 000004afH. idata$6 DATA
Address publics by Value rva+base Lib:object
0001:00000020? crash@ @YAXXZ 00401020 F crashdemo.obj
0001:00000070 _main 00401070 F crashdemo.obj
0004:00000000 __import_descriptor_kernel32 00424000 Kernel32:KERNEL32.dll
0004:00000014 __null_import_descriptor 00424014 Kernel32:KERNEL32.dll
0004:00000138 __imp__getcommandlinea@0 00424138 Kernel32:KERNEL32.dll
0004:0000013c __imp__getversion@0 0042413c Kernel32:KERNEL32.dll
0004:00000140 __imp__exitprocess@4 00424140 Kernel32:KERNEL32.dll
0004:00000144 __imp__debugbreak@0 00424144 Kernel32:KERNEL32.dll
0004:00000148 __imp__getstdhandle@4 00424148 Kernel32:KERNEL32.dll
0004:0000014c __imp__writefile@20 0042414c Kernel32:KERNEL32.dll
0004:00000150 __imp__interlockeddecrement@4 00424150 Kernel32:KERNEL32.dll
0004:00000154 __imp__outputdebugstringa@4 00424154 Kernel32:KERNEL32.dll
0004:00000158 __imp__getprocaddress@8 00424158 Kernel32:KERNEL32.dll
0004:0000015c __imp__loadlibrarya@4 0042415c Kernel32:KERNEL32.dll
0004:00000160 __imp__interlockedincrement@4 00424160 Kernel32:KERNEL32.dll
0004:00000164 __imp__getmodulefilenamea@12 00424164 Kernel32:KERNEL32.dll
0004:00000168 __imp__terminateprocess@8 00424168 Kernel32:KERNEL32.dll
0004:0000016c __imp__getcurrentprocess@0 0042416c Kernel32:KERNEL32.dll
0004:00000170 __imp__unhandledexceptionfilter@4 00424170 Kernel32:KERNEL32.dll
0004:00000174 __imp__freeenvironmentstringsa@4 00424174 Kernel32:KERNEL32.dll
0004:00000178 __imp__freeenvironmentstringsw@4 00424178 Kernel32:KERNEL32.dll
0004:0000017c __imp__widechartomultibyte@32 0042417c Kernel32:KERNEL32.dll
0004:00000180 __imp__getenvironmentstrings@0 00424180 Kernel32:KERNEL32.dll
0004:00000184 __imp__getenvironmentstringsw@0 00424184 Kernel32:KERNEL32.dll
0004:00000188 __imp__sethandlecount@4 00424188 Kernel32:KERNEL32.dll
0004:0000018c __imp__getfiletype@4 0042418c Kernel32:KERNEL32.dll
0004:00000190 __imp__getstartupinfoa@4 00424190 Kernel32:KERNEL32.dll
0004:00000194 __imp__heapdestroy@4 00424194 Kernel32:KERNEL32.dll
0004:00000198 __imp__heapcreate@12 00424198 Kernel32:KERNEL32.dll
0004:0000019c __imp__heapfree@12 0042419c Kernel32:KERNEL32.dll
0004:000001a0 __imp__virtualfree@12 004241a0 Kernel32:KERNEL32.dll
0004:000001A4 __imp__rtlunwind@16 004241a4 Kernel32:KERNEL32.dll
0004:000001a8 __imp__getlasterror@0 004241a8 Kernel32:KERNEL32.dll
0004:000001ac __imp__setconsolectrlhandler@8 004241ac Kernel32:KERNEL32.dll
0004:000001b0 __imp__isbadwriteptr@8 004241b0 Kernel32:KERNEL32.dll
0004:000001B4 __imp__isbadreadptr@8 004241b4 Kernel32:KERNEL32.dll
0004:000001b8 __imp__heapvalidate@12 004241b8 Kernel32:KERNEL32.dll
0004:000001BC __imp__getcpinfo@8 004241BC Kernel32:KERNEL32.dll
0004:000001C0 __imp__getacp@0 004241c0 Kernel32:KERNEL32.dll
0004:000001C4 __imp__getoemcp@0 004241c4 Kernel32:KERNEL32.dll
0004:000001c8 __imp__heapalloc@12 004241c8 Kernel32:KERNEL32.dll
0004:000001cc __imp__virtualalloc@16 004241cc Kernel32:KERNEL32.dll
0004:000001d0 __imp__heaprealloc@16 004241d0 Kernel32:KERNEL32.dll
0004:000001d4 __imp__multibytetowidechar@24 004241d4 Kernel32:KERNEL32.dll
0004:000001d8 __imp__lcmapstringa@24 004241d8 Kernel32:KERNEL32.dll
0004:000001DC __imp__lcmapstringw@24 004241DC Kernel32:KERNEL32.dll
0004:000001E0 __imp__getstringtypea@20 004241e0 Kernel32:KERNEL32.dll
0004:000001e4 __imp__getstringtypew@16 004241e4 Kernel32:KERNEL32.dll
0004:000001e8 __imp__setfilepointer@16 004241e8 Kernel32:KERNEL32.dll
0004:000001ec __imp__setstdhandle@8 004241ec Kernel32:KERNEL32.dll
0004:000001f0 __imp__flushfilebuffers@4 004241f0 Kernel32:KERNEL32.dll
0004:000001f4 __imp__closehandle@4 004241f4 Kernel32:KERNEL32.dll
0004:000001f8/177kernel32_null_thunk_data 004241f8 Kernel32:KERNEL32.dll
Entry point at 0001:000000f0
Line numbers for./debug/crashdemo.obj (d:/msdev/myprojects/crashdemo/crashdemo.cpp) segment. Text
0001:00000020 0001:00000038 0001:0000003f 16 0001:00000046
0001:00000050 0001:00000070 0001:00000088 0001:0000008d
If you take a closer look at Rva+base, you will find that the first function address that is larger than the crash address 0x0040104a is 0x00401070, so the entry before 0x00401070 this address is the function that produces the crash, which is the line:
0001:00000020? crash@ @YAXXZ 00401020 F crashdemo.obj
So the function of the crash is? crash@ @YAXXZ, all function names that begin with a question mark are the names of C + + adornments. In our source program, the Crash () is the child function.
OK, now that we can easily know the name of the function that crashed, aren't you excited about it? Oh, first do not busy, next, the more powerful tricks to the appearance.
Notice that the last part of the MAP file--The line numbers information--is displayed in this form:
13 0001:00000020
The first number represents the line number of the code in the source code, and the second number is the offset of the line of code in the code snippet to which it belongs.
If you are looking for line numbers, you need to do some hexadecimal subtraction using the following formula:
Crash row offset = Crash Address (Crash addresses)-base address (ImageBase adress)-0x1000
Why would you do that? Careful friend may notice rva+base This column, we get the crash address is by the offset address (RVA) + base address (base), so in the calculation of line number to the base address minus, in general, the value of the base address is 0x00400000. In addition, because the normal PE file's code snippet starts from the 0x1000 offset, it must also subtract the 0x1000.
Well, with that in mind, we can do a primary subtraction calculation:
Crash row offset = 0x0040104a-0x00400000-0x1000 = 0x4a
If you browse the code line information for the MAP file, you will see that the calculated results are not exceeded, but the closest number is in the CrashDemo.cpp file:
16 0001:00000046
Which is the 16th line in the source code, let's look at the source code:
I/= J;
Ha... That's the 16th line, indeed.
Excited about it. Me too. :)
Method has been introduced, from now on, we can pinpoint to the source code in the crash line, and as long as the compiler can generate MAP files (including VC, MASM, VB, BCB, Delphi ...). ), this method is applicable. We often complain about m$ products how poor, but in fact m$ or unintentionally provide a lot of valuable information to us, but we often do not know how to use it ... Believe this, you can more calmly face the "illegal operation" hint. You can even ask the user to provide a crash address and then sit at home and find the wrong line and fix it.
Isn't it cool? :)
Lao Luo
2003-2-7