• 通过map文件找程序崩溃的代码行


    一,配置vs

    二,程序崩溃界面

    // ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    
    
    void fun(bool flag)
    {
        if (flag) {
            printf("hello world
    ");
        }
        else {
            printf("sorry.
    ");
        }
        int a = 0, b = 4;
        int c = b / a;
    }
    
    int main()
    {
        bool m = false;
        fun(m);
        //std::cout << "Hello World!
    ";
        system("pause");
        return 0;
    }
    
    // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
    // 调试程序: F5 或调试 >“开始调试”菜单
    
    // 入门使用技巧: 
    //   1. 使用解决方案资源管理器窗口添加/管理文件
    //   2. 使用团队资源管理器窗口连接到源代码管理
    //   3. 使用输出窗口查看生成输出和其他消息
    //   4. 使用错误列表窗口查看错误
    //   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
    //   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

    三,map文件

    0003:00000030 00000388H .bss                    DATA
     0004:00000000 0000002dH .msvcjmc                DATA
     0005:00000000 00000060H .rsrc$01                DATA
     0005:00000060 00000180H .rsrc$02                DATA
    
      Address         Publics by Value              Rva+Base       Lib:Object
    
     0000:00000000       ___hybrid_code_map_count   00000000     <absolute>
     0000:00000000       ___AbsoluteZero            00000000     <absolute>
     0000:00000000       ___hybrid_code_map         00000000     <absolute>
     0000:00000000       ___volatile_metadata       00000000     <absolute>
     0000:00000000       ___hybrid_auxiliary_iat    00000000     <absolute>
     0000:00000000       ___guard_longjmp_count     00000000     <absolute>
     0000:00000000       ___dynamic_value_reloc_table 00000000     <absolute>
     0000:00000000       ___guard_iat_count         00000000     <absolute>
     0000:00000000       ___enclave_config          00000000     <absolute>
     0000:00000000       ___guard_fids_count        00000000     <absolute>
     0000:00000000       ___guard_longjmp_table     00000000     <absolute>
     0000:00000000       ___guard_iat_table         00000000     <absolute>
     0000:00000000       ___guard_fids_table        00000000     <absolute>
     0000:00000002       ___safe_se_handler_count   00000002     <absolute>
     0000:00000100       ___guard_flags             00000100     <absolute>
     0000:00000000       ___ImageBase               00400000     <linker-defined>
     0001:00000000       ?__empty_global_delete@@YAXPAX@Z 00401000 f i ConsoleApplication1.obj
     0001:00000040       ?__empty_global_delete@@YAXPAXI@Z 00401040 f i ConsoleApplication1.obj
     0001:00000080       ?fun@@YAX_N@Z              00401080 f   ConsoleApplication1.obj
     0001:00000100       __JustMyCode_Default       00401100 f i ConsoleApplication1.obj
     0001:00000110       ___local_stdio_printf_options 00401110 f i ConsoleApplication1.obj
     0001:00000160       __vfprintf_l               00401160 f i ConsoleApplication1.obj
     0001:000001d0       _main                      004011d0 f   ConsoleApplication1.obj
     0001:00000240       _printf                    00401240 f i ConsoleApplication1.obj
     0001:000002c0       @__CheckForDebuggerJustMyCode@4 004012c0 f   MSVCRTD:debugger_jmc.obj
     0001:00000300       @_RTC_AllocaHelper@12      00401300 f   MSVCRTD:stack.obj
     0001:00000340       @_RTC_CheckStackVars2@12   00401340 f   MSVCRTD:stack.obj
     0001:00000420       @_RTC_CheckStackVars@8     00401420 f   MSVCRTD:stack.obj
     0001:00000490       __RTC_CheckEsp             00401490 f   MSVCRTD:stack.obj

    如果仔细浏览 Rva+Base 这栏,你会发现第一个比崩溃地址大的地址0x00401080,所以在 这个地址之前的那个入口就是产生崩溃的函数

    因此,发生崩溃的函数就是 ?Crash@@YAXXZ ,所有以问号开头的函数名称都是 C++ 修饰的名称

    什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号、源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方、任何时候使用,不需要有额外的程序进行支持。而且,这是唯一能找出程序崩溃的地方的救星。

    好吧,既然 MAP 文件如此神奇,那么我们应该如何生成它呢?在 VC 中,我们可以按下 Alt+F7 ,打开“Project Settings”选项页,选择 C/C++ 选项卡,并在最下面的 Project Options 里面输入:/Zd ,然后要选择 Link 选项卡,在最下面的 Project Options 里面输入: /mapinfo:lines 和 /map:PROJECT_NAME.map 。最后按下 F7 来编译生成 EXE 可执行文件和 MAP 文件。

    在 MASM 中,我们要设置编译和连接参数,我通常是这样做的:

    rc %1.rc
    ml /c /coff /Zd %1.asm
    link /subsystem:windows /mapinfo:exports /mapinfo:lines /map:%1.map %1.obj %1.res

    把它保存成 makem.bat ,就可以在命令行输入 makem filename 来编译生成 EXE 可执行文件和 MAP 文件了。

    在此我先解释一下加入的参数的含义:

    /Zd 表示在编译的时候生成行信息
    /map[:filename] 表示生成 MAP 文件的路径和文件名
    /mapinfo:lines 表示生成 MAP 文件时,加入行信息
    /mapinfo:exports 表示生成 MAP 文件时,加入 exported functions (如果生成的是 DLL 文件,这个选项就要加上)

    参考:

    https://blog.csdn.net/anddy926/article/details/7695476/
    https://blogs.msdn.microsoft.com/hopperx/2006/09/14/using-map-files-part-1/

    https://blog.csdn.net/u012138730/article/details/90611728

  • 相关阅读:
    JavaScript基础学习(三)—数组
    JavaScript基础学习(二)—JavaScript基本概念
    JavaScript基础学习(一)—JavaScript简介
    HTML基础学习(二)—CSS
    HTML基础学习(一)—HTML
    JDBC基础学习(六)—数据库连接池
    JDBC基础学习(五)—批处理插入数据
    js_页面关闭beforeunload事件
    css3_box-shadow使用记录
    jq_$.extend和$.fn.extend插件开发和方法的封装
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/11096771.html
Copyright © 2020-2023  润新知