Find some articles about debugging by using the map file.

Source: Internet
Author: User
Article 1Identify the source code error line through the crash address only
As a programmer, what do we worry most about? Is memory leakage? Is the interface hard to see ?...... Wrong! I believe that there will be no objection in my opinion-that is, the program has crashed!

"This program has performed illegal operations and is about to be closed. Please contact your software supplier .", Well, I am afraid this M $ famous saying is something programmers are most worried about. Sometimes, your program runs well on your machine, but it crashes on another machine; sometimes you may encounter illegal operations while writing and testing, but you cannot determine which line of the source code is the cause ...... Is it painful? It doesn't matter. This article can help you out of this dilemma, and even you can proudly ask the user to tell you the crash address, then you can precisely locate the line with errors in the source code. (Amazing, right? Haha .)

First of all, I must emphasize that this method can be used on any compiler on the market. However, I am only familiar with the VC and MASM of M $, so the subsequent sections only introduce how to implement them in these two compilers. please familiarize yourself with the methods used in other compilers.

Well, let's get started! :)

First, the map file of the program must be generated. What is a map file? In short, a map file is the unique text representation of the program's global symbols, source files, and code line numbers. It can be used anywhere and anytime, no additional programs are required. Moreover, this is the only savior that can find the place where the program crashes.

Well, since the map file is so amazing, how should we generate it? In VC, we can press Alt + F7 to open the "Project Settings" option page, select the C/C ++ tab, and enter/ZD in the following project options, select the link tab and enter:/MapInfo: lines and/map: project_name.map in the following project options. Finally, press F7 to compile and generate the EXE executable file and map file.

In MASM, we need to set compilation and connection parameters. I usually do this:

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 makem. bat, and you can input makem filename in the command line to compile and generate the EXE executable file and map file.

Here I will explain the meaning of the added parameters:

/ZD indicates generating row information during compilation
/Map [: Filename] indicates the path and file name of the generated map file
/MapInfo: lines indicates that line information is added when a map file is generated.
/MapInfo: exports indicates that exported functions is added when the map file is generated. (If the DLL file is generated, this option must be added)

OK. We have obtained the map file through the above steps. How can we use it?

Let's start with a simple instance. Open your VC and create a new file:

01 //************************************* ***************************
02 // program name: demonstrate how to identify the source code error line through the crash address
03 // Author: Luo Cong
04 // Date: 2003-2-7
05 // Source: http://www.luocong.com (laoluo's colorful world)
06 // This program will generate an "except 0 error", so that the "invalid operation" dialog box will pop up.
07 // "except 0 errors" will only be generated in the debug version. This program is simplified as much as possible for demonstration.
08 // Note: If you want to reprint it, please keep the program complete and note:
09 // reposted from "Old Luo's colorful world" (http://www.luocong.com)
10 //************************************* ***************************
11
12 Void crash (void)
13 {
14 int I = 1;
15 Int J = 0;
16 I/= J;
17}
18
19 void main (void)
20 {
21 crash ();
22}

Obviously, this program has a "Division by 0 error". If it is compiled in debug mode, it will certainly produce "invalid operations" during runtime ". Okay. Let's run it. The "invalid operation" dialog box appears. Then, click "details, record the address that caused the crash -- on my machine it is 0x0040104a.

Let's take a look at its map file: (because the file content is too long, I omitted useless parts in the middle)

Crashdemo

Timestamp is 3e0000a76 (Fri Feb 07 09:23:02 2003)

Preferred load address is 00400000

Start length name class
0001:00000000 0000de04h. Text code
0001: include04 0001000ch. textbss code
000:00000000 00001346 H. RDATA
000:00001346 00000000 H. edata
0003:00000000 00000104 H. CRT $ xca data
0003:00000104 00000104 H. CRT $ xcz data
0003:00000208 00000104 H. CRT $ Xia data
0003: 0000030c 00000109 H. CRT $ xic data
0003:00000418 00000104 H. CRT $ xiz data
0003: 0000051c 00000104 H. CRT $ xpa data
0003: 00000620 00000104 H. CRT $ xpx data
0003: 00000724 00000104 H. CRT $ xpz data
0003: 00000828 00000104 H. CRT $ xta data
0003: 0000092c 00000104 H. CRT $ xtz data
0003: 00000a30 00000b93h. Data data
0003: 201715c4 00001974 H. BSS data
0004:00000000 00000014 H. idata $2 Data
0004:00000014 00000014 H. idata $3 data
0004:00000028 00000110 H. idata $4 Data
0004:00000138 00000110 H. 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 0020.13c 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 0020.14c 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 0020.15c 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 0020.16c 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 0020.17c 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 0020.18c 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 0020.19c Kernel32: kernel32.dll
0004: 000001a0 _ imp _ virtualfree @ 12 001_1a0 Kernel32: kernel32.dll
0004: 000001a4 _ imp _ rtlunwind @ 16 0020.1a4 Kernel32: kernel32.dll
0004: 000001a8 _ imp _ getlasterror @ 0 001_1a8 Kernel32: kernel32.dll
0004: 000001ac _ imp _ setconsolectrlhandler @ 8 001_1ac Kernel32: kernel32.dll
0004: 000001b0 _ imp _ isbadwriteptr @ 8 001_1b0 Kernel32: kernel32.dll
0004: 000001b4 _ imp _ isbadreadptr @ 8 001_1b4 Kernel32: kernel32.dll
0004: 000001b8 _ imp _ heapvalidate @ 12 001_1b8 Kernel32: kernel32.dll
0004: 000001bc _ imp _ getcpinfo @ 8 0020.1bc Kernel32: kernel32.dll
0004: 000001c0 _ imp _ getacp @ 0 001_1c0 Kernel32: kernel32.dll
0004: 000001c4 _ imp _ getoemcp @ 0 0000001c4 Kernel32: kernel32.dll
0004: 000001c8 _ imp _ heapalloc @ 12 001_1c8 Kernel32: kernel32.dll
0004: 000001cc _ imp _ virtualalloc @ 16 0020.1cc Kernel32: kernel32.dll
0004: 000001d0 _ imp _ heaprealloc @ 16 001_1d0 Kernel32: kernel32.dll
0004: 000001d4 _ imp _ multibytetowidechar @ 24 0000001d4 Kernel32: kernel32.dll
0004: 000001d8 _ imp _ lcmapstringa @ 24 001_1d8 Kernel32: kernel32.dll
0004: 000001dc _ imp _ lcmapstringw @ 24 001_1dc Kernel32: kernel32.dll
0004: 000001e0 _ imp _ getstringtypea @ 20 001_1e0 Kernel32: kernel32.dll
0004: 000001e4 _ imp _ getstringtypew @ 16 001_1e4 Kernel32: kernel32.dll
0004: 000001e8 _ imp _ setfilepointer @ 16 001_1e8 Kernel32: kernel32.dll
0004: 000001ec _ imp _ setstdhandle @ 8 001_1ec Kernel32: kernel32.dll
0004: 000001f0 _ imp _ flushfilebuffers @ 4 001_1f0 Kernel32: kernel32.dll
0004: 000001f4 _ imp _ closehandle @ 4 0000001f4 Kernel32: kernel32.dll
0004: 000001f8/177kernel32_null_thunk_data 001_1f8 Kernel32: kernel32.dll

Entry point at 0001: 000000f0

Line numbers for./debug/crashdemo. OBJ (D:/msdev/myprojects/crashdemo. cpp) segment. Text

13 0001:00000020 14 0001:00000038 15 0001: 0000003f 16 0001:00000046
17 0001:00000050 20 0001: 00000070 21 0001: 00000088 22 0001: 0000008d

If you carefully read the RVA + base column, you will find that the first function address is 0x00401070 larger than the crashed address 0x0040104a, so the entry before the address 0x00401070 is the function that generates the crash, that is, this line:

0001:00000020? Crash @ yaxxz 00401020 F crashdemo. OBJ

So what is the function that crashes? Crash @ yaxxz. All function names starting with question marks are c ++ modified names. In our source program, this is the crash () subfunction.

OK. Now we can easily see the name of the function that crashed. Are you very excited? Well, don't be busy first. Next, more advanced moves will be available.

Pay attention to line numbers information, the last part of the map file, which is displayed in this form:

13 0001:00000020

The first number indicates the code line number in the source code, and the second number indicates the offset of the code line in the code segment to which it belongs.

To find the code row number, use the following formula to perform hexadecimal subtraction:

Crash line offset = crash address-base address (imagebase address)-0x1000

Why? Careful friends may be aware of the RVA + base column. The crash address we get is obtained from the offset address (RVA) + base address (base, therefore, when calculating the row number, subtract the base address. Generally, the base address value is 0x00400000. In addition, because the code segments of a PE file generally start from 0x1000 offset, 0x1000 must be subtracted.

Now that we understand this, we can perform the primary subtraction calculation:

Crash line offset = 0x0040104a-0x00400000-0x1000 = 0x4a

If you browse the code line information of the map file, you will see that the calculation result is no more than, but the nearest number is in the crashdemo. cpp file:

16 0001:00000046

That is to say, in the source code of line 16th, let's look at the source code:

16 I/= J;

Ha !!! That's exactly 16th lines!

Excited? The same is true for me! :)

The method has been introduced. From now on, we can precisely locate the crash line in the source code, and as long as the compiler can generate Map Files (including VC, MASM, VB, BCB, Delphi ......), This method is applicable. We often complain about how the product of M $ is poor, but in fact M $ still intentionally or unintentionally provides a lot of valuable information to us, but we often don't know how to use it ...... I believe that in this way, you will be more comfortable with the "illegal operations" prompt. You can even ask the user to provide the address for the crash, and then you can sit at home and comfortably find the wrong line and make corrections.

Is it nice? :)

 

 

 

 

 

 

 

 

 

 

Article 2

Tips for using map file to remove objects

Last update: 03/11/2004

The main materials: http://www.codeproject.com/debug/mapfile.asp

Introduction

What is the greatest division of the program when it is used? The cause is that the program cannot be found after the program is completed. Most people simply use the splitter. When the splitter cannot be found, they have to use the printf trace outputdebugstring method, but none of them work, the true reliability depends on map file for guidance. In addition, if the program has already entered the release mode, security is also in the hands of the customer. If you unfortunately want to delete the program, you only need to ask for map file.

Map file is used by linker to convert object files into binary (exe, DLL ,...) the corresponding table generated by the system, that is, how the linker loader of the system uploads data to the two-element image's dynamic table. With this map generator, coupled with the Assembly source code generated by compiler, it becomes the best tool for finding a program as a machine.

Set up a map file

The hypervisor of the top column refers to the vc6 setting method. In fact, vc7 is similar. In the Properties dialog of the project, choose "linker-> debugging ".

  • Generate map file-> Yes
  • Map exports-> Yes
  • Map lines-> Yes

I will change the handler output to assembly, machine code, and source (/FACS) in C/C ++> output files ), this is more comprehensive than other users.

How to Use Map File to remove objects

There is a program under the false settings:

<font face="Courier New" size="3">// main.cpp void main(){    char* pEmpty = NULL;    *pEmpty = 'x';}</font>

This program will generate two types, Main. COD and Main. map. An Error Reporting screen appears in Windows 2 k/XP, and the response in the dialog box is used to view the response, it tells you that when modname: main.exe, modver: 0.0.0.0, offset 00011cc8, there is a minidump (but following the instructions, this minidump cannot be copied/paste... you can only copy the case to the path listed by him ).

If you attempt to write a row in the VC, the VC ide will tell you that an unhandled exception occurs in 0x00411cc8.

We are interested in how to calculate the line of the queue from the address 00011cc8 or 00411cc8.

First look at the top of the map file. We want to find the base address:

map_debug  Timestamp is 404eb1b2 (Tue Mar 09 22:12:02 2004)  Preferred load address is 00400000  Start         Length     Name                   Class 0001:00000000 00010000H .textbss                DATA 0002:00000000 00012492H .text                   CODE 0003:00000000 00002687H .rdata                  DATA 0003:00002688 0000014aH .rdata$debug            DATA

We are interested in the length and length of all sections before the load address 00400000 and code segment. In this example, the length of code segment is 0x00010000, remember the useful information.

 Address         Publics by Value              Rva+Base     Lib:Object  0000:00000000       __except_list              00000000     <absolute></absolute> 0000:00000000       ___safe_se_handler_table   00000000     <absolute></absolute> 0000:00000000       ___safe_se_handler_count   00000000     <absolute></absolute> 0001:00000000       __enc$textbss$begin        00401000     <linker-defined></linker-defined> 0001:00010000       __enc$textbss$end          00411000     <linker-defined></linker-defined> 0002:00000a50       __RTC_InitBase             00411a50 f   LIBCD:init.obj 0002:00000a90       __RTC_Shutdown             00411a90 f   LIBCD:init.obj 0002:00000ab0       _mainCRTStartup            00411ab0 f   LIBCD:crt0.obj 0002:00000ca0       _main                      00411ca0 f   main.obj

In the next section, we need to remember the offset (RVA + base value) of our program function. It is usually faster to search for it from LIB: object. In this example, we only have one function, and its RVA + base is 00411ca0.

Because the program in this example is too small, linker will not generate the third map file, that is, the address of the original program line response, as described in the textbook, this doesn't matter much because we have a more refined experience. cod available.

In Windows report, the offset value is calculated, while in VC report, the offset value is not calculated. Therefore, you can find that if the value of VC report is reset to preferred load address, you can get the windows report value.

00411cc8-00400000 = 00011cc8

This offset refers to the offset of the entire binary image, and there is a fixed length before the code segment, so we need to merge it, to know the offset of code segment.

00011cc8-00010000 = 100001cc8

Next, calculate the Offset Value of the main function:

00411ca0-00400000-00010000 = 100001ca0

So we can find the offset between the place where the sending cursor is located and the main function is:

20171cc8-20171ca0 = 28

Then we can find out main. COD.

; 3    : char* pEmpty = 0;   0001ec7 45 f8 00 0000 00 mov DWORD PTR _pEmpty$[ebp], 0 ; 4    : *pEmpty = 'x';   000258b 45 f8 mov eax, DWORD PTR _pEmpty$[ebp]  00028c6 00 78 mov BYTE PTR [eax], 120; 00000078H

Where offset 28 is the issue instruction (mov byte PTR [eax], 120 ), we can push back the problem with 4th lines of the program with COD statistics.

How does GCC generate map file?

Using GCC to generate a. COD attack will be slightly troublesome:

G ++-C-g-wa,-a,-ad main. cpp> main. COD

However, you should find that there is-G, so the. O records produced by it cannot be linked. We have run the-wa,-a,-ad command to notify all debug ctives ves of the as queue. However, if you want to keep the debugging rules, use G ++-s main. CPP produces main. check whether the Assembly of the production code is the same. The. COD segment generated in this example is as follows:

    31                    main:  32 0000 55                    pushl %ebp  33 0001 89E5                  movl %esp,%ebp  34 0003 83EC18                subl $24,%esp   1:main.c        **** int main()   2:main.c        **** {  36                    .LM1:   3:main.c        ****         char* p = 0;  38                    .LM2:  39                    .LBB2:  40 0006 C745FC00              movl $0,-4(%ebp)  40      000000   4:main.c        ****         *p = 'x';  42                    .LM3:  43 000d 8B45FC                movl -4(%ebp),%eax  44 0010 C60078                movb $120,(%eax)   5:main.c        **** }

Map workers are produced by LD, But we generally submit them to GCC for replacement:

G ++-O main. O-wl,-map, Main. Map

When the program fails, you can use GDB to check the core information:

GDB main core.19320

If there is no debug info, GDB will only tell you that #0 0x080483d0 in main () is better, because if your program is handled using strip-name, you cannot see main! Next, let's take a look at the map file. Because the ELF format is better than the PE format used in windows, there is not much problem with the offset keyword, you only need to find the base address of main:

 .text          0x080482d0       0x24 /usr/lib/crt1.o                0x080482d0                _start .text          0x080482f4       0x24 /usr/lib/crti.o *fill*         0x08048318        0x8 2425393296 .text          0x08048320       0xa0 /usr/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtbegin.o .text          0x080483c0       0x18 main.o                0x080483c0                main *fill*         0x080483d8        0x8 2425393296

Therefore, the data address of the main function 0x080483c0 is known, and 0x080483d0 is dropped. Therefore, if the offset is 0x00000010, the correct location can be quickly found in. COD memory.

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.