How to Use the map file to find the cause of program crash

Source: Internet
Author: User

(Reprinted)

How to Use the map file to find the cause of program crash

Author Wouter dhondt translation Feng Yicheng (fengyc@pset.suntec.net)

[Interpreter] When we debug a program, we get used to the constant step in, step in... however, if we find that the debug version of the EXE can run completely normally, but the release version is often inexplicably crash. What should I do ?? It doesn't matter. This article helps you solve this problem :) of course, if you want to comprehensively improve your debug capability, read John Robbins's book "debugging Applications, but you have to read the English version. The Chinese version is too bad!

Introduction

Writing neat programs is one thing. When the user notifies you that the program crashes, you know that it is best to correct these errors before adding new properties of the program. If you are lucky enough, the user will provide you with a crash address, there is still a long way to go to solve this problem. With the crash address, how do you determine what went wrong?

Create a map file

First, you need the map file. If you do not have a map file, it is almost impossible for you to find the specific code line with your program error through the crash address. Let me teach you how to create a suitable map file first. For this reason, we created a new project (mapfile): In VC ++ 6.0, I created a new project that applies the Win32 application option and chose 'typical "Hello word! "Application", so that the generated map file can meet the requirements described below.

After a new project is generated, we adjust the Project Settings of release. On the C/C ++ properties page, set the debug info value to "line numbers only ".

Many people forget this step, but if you want to get a suitable map file, you need to set this option, which will not affect your release program. The next step is the link property page. You need to select the "generate mapfile" option. In the project options editing box, enter the/MapInfo: lines and/MapInfo: exports switches.

Now you can compile and link your project. After the link, you can find the. Map File (together with the EXE file) in your intermediate directory ).

Read the map file

After the boring work above, the next step is interesting: how to read the map file. We use a crash instance to introduce how to read map files. So we have to let the program crash first, so I added the following two lines of code at the end of the initinstance () function:

Char * pempty = NULL;
* Pempty = 'X'; // The number of rows is 119th.

I believe that you can find other code to crash your program. Now recompile and link the project. If you run your program, the program will crash and get the message 'the instruction at "0x004011a1" referenced memory at "0x00000000 ". 0x00000000 memory cannot be written.

Now, you can use notepad or similar editing tools to open the map file. The map file is as follows:

The header of the map file contains the module name, indicating the timestamp of the Project LINK time and the preferred loading address (usually 0x00400000, unless it is a DLL ). The Section information after the file header is organized by the link program to the Section information of various OBJ and Lib files.

Mapfile

Timestamp is 3df6394d (Tue Dec 10 19:58:21 2002)

Preferred load address is 00400000

Start length name class
0001:00000000 000038feh. Text code
000:00000000 000000f4h. idata $5 Data
0002: 000000f8 00000394 H. RDATA data
0002: 0000048c 00000028 H. idata $2 Data
0002: 000004b4 00000014 H. idata $3 data
0002: 000004c8 000000f4h. idata $4 Data
0002: 000005bc 0000040ah. idata $6 data
0002: 000009c6 00000000 H. edata
0003:00000000 00000004 H. CRT $ xca data
0003:00000004 00000004 H. CRT $ xcz data
0003:00000008 00000004 H. CRT $ Xia data
0003: 0000000c 00000004 H. CRT $ xic data
0003:00000010 00000004 H. CRT $ xiz data
0003:00000014 00000004 H. CRT $ xpa data
0003:00000018 00000004 H. CRT $ xpz data
0003: 0000001c 00000004 H. CRT $ xta data
0003:00000020 00000004 H. CRT $ xtz data
0003:00000030 00002490 H. Data
0003: 12724c0 000005fch. BSS data
0004:00000000 00000250 H. rsrc $01 data
0004:00000250 00000720 H. rsrc $02 data

After Section information, you can see the common function information. Note the "public" section below. If you have a static C function, it will not appear in the "public" section. Fortunately, the line numbers section still reflects information about static functions. The most important part of the "public" function information is the function name and the information in the RVA + base column. The RVA + base information is the start address of the function.

Address publics by value RVA + base Lib: Object

0001:00000000 _ winmain @ 16 00401000 F mapfile. OBJ
0001: 000000c0? Myregisterclass @ yagpauhinstance __@ Z 004010c0 F mapfile. OBJ
000:00000150? Initinstance @ yahpauhinstance __@ h @ Z 00401150 F mapfile. OBJ
0001: 000001b0? Wndproc @ ygjpauhwnd __@ @ iij @ Z 004011b0 F mapfile. OBJ
000:00000310? About @ ygjpauhwnd __@ @ iij @ Z 00401310 F mapfile. OBJ
000:00000350 _ winmaincrtstartup 00401350 F libc: wincrt0.obj
000:00000446 _ amsg_exit 00401446 F libc: wincrt0.obj
0001: 0000048f _ cinit 0040148f libc: crt0dat. OBJ
0001: 000004bc _ exit 004014bc F libc: crt0dat. OBJ
0001: 000004cd _ exit 004014cd F libc: crt0dat. OBJ
0001: 00000591 _ xcptfilter 00401591 F libc: winxfltr. OBJ
0001: 00000715 _ wincmdln 00401715 F libc: wincmdln. OBJ
// Snipped for better reading
0003: ipv2ab4 _ fpinit 00408ab4 <Common>
0003: 20172ab8 _ acmdln 00408ab8 <Common>

Entry point at 000:00000350

Static symbols

0001: 12735d0 leadup1 004045d0 F libc: memmove. OBJ
0001: 12735fc leadup2 004045fc F libc: memmove. OBJ
// Snipped for better reading
0001: 00000577 _ initterm 00401577 F libc: crt0dat. OBJ
0001: 0000046b _ fast_error_exit 0040146b F libc: wincrt0.obj

The public function is followed by the Line Information Section (you have set the link property page to use/MapInfo: lines and select "line numbers" on the C/C ++ property page "). After that, the export information is displayed. As long as your program has an output function and the link property page contains/MapInfo: exports, you can get the export information.

Line numbers for. \ release \ mapfile. OBJ (F: \ mapfile. cpp) segment. Text

24 0001:00000000 30 000:00000004 31 0001: 0000001b 32 0001:00000027
35 0001: 0000002d 53 0001:00000041 40 0001:00000047 43 0001:00000050
45 0001: 00000077 47 0001: 00000088 48 0001: 0000008f 52 0001: 000000ad
53 0001: 000000b3 71 0001: 000000c0 80 0001: 000000c3 81 0001: 000000c8
82 0001: 000000ff 86 000:00000114 88 000:00000135 89 000:00000145
102 000:00000150 108 000:00000155 110 0001: 00000188 122: 0000018d
115 0001: 0000018e 116 0001: 0000019a 119 0001: 000001a1 121 0001: 000001a8
122 0001: 000001ae 135 0001: 000001b0 143: 000001cc 0001 172: 000001ee
175 0001: 0000020d 149 000:00000216 157 0001: 0000022c 175 000:00000248
154 000:000000000174 0001: 0000025f 175 0001: 00000261 151: 0000026a
174 0001: 00000287 175 0001: 00000289 161: 0001 00000294 164: 000002a8
165 0001: 000002b6 166 0001: 000002d8 174: 000002e7 0001 175: 000002e9
169 0001: 000002f2 174 0001: 000002fa 175 0001: 000002fc 179 0001:00000310
186 0001: 0000031e 193 0001: 0000032e 194 000:00000330 188 000:00000333
183 000:00000344 194 000:00000349

Now we can find out where the code crashes. First, determine which function contains the crash address. Browse the "RVA + base" column and find the first function with a larger address than the collapsed address. The previous function of this function is the function with a crash. In our example, the crash address is 0x004011a1, which is located between 0x00401150 and 0x004011b0, so that we know what the crash function is? Initinstance @ yahpauhinstance __@ h @ Z. The number of letters starting with a question mark is C ++ decorated name. You can pass C ++ decorated name as a command line parameter to the undname. exe program of Platform SDK to get the original function name. In most cases, you do not need to do this. By observing the C ++ decorated name, we can know the original function name (here, the function name is initinstance ())

The above is an important step in bug tracking. But we can do better: we can find the line of code that causes the crash! We need to do some basic hexadecimal calculations, so we need a calculator. First, calculate the following value: crash address-preferred load address-0x1000.

The address is the offset relative to the first code section. Therefore, this calculation is required. Minus the preferred loading address, we can get the offset (logically) relative to the start position of the file, but why do we need to subtract 0x1000? Because the address in line numbers is the offset from the start position of the Code section. The first part of the binary code is portable executable (PE), which has a length of 0 x bytes. Therefore, in our example, the crash address (the offset relative to the Code Section) should be 0x004011a1-0x00400000-0x1000 = 0x1a1

Now let's look at the line information section of the map file. Each line looks like 30 0001:00000004. The first number is the number of rows, and the second number is the offset value of this line of code against the code section. If we want to find the number of lines of the crash code, we just need to use the same method as the located crash function: Find the first offset greater than the collapsed address we calculated, in this case, the previous offset occurs. In our example, 0x1a1 is before 0x1a8, then we can determine that the crash occurs in the 119 row of the mapfile. cpp file.

Keep track of Map Files

Each release has its own map file. It is not a bad idea to include a map file when releasing an EXE file. In this way, you can ensure that the current EXE has a suitable map file. You can make each EXE in the system have a corresponding map file, but we all know that this may eventually cause some problems. The map file does not contain any information you want to know, it is useless to users. However, when a program crashes, if you do not have a map file, you can at least provide the map file to the user.

Thank you

Thanks to John Robbins's book "debugging Applications" for their help.
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.