首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MSVC中的去噪

MSVC中的去噪
EN

Stack Overflow用户
提问于 2012-12-08 12:59:28
回答 4查看 16.5K关注 0票数 11

我如何在MSVC中拆解名字?gcc有abi::__cxa_demangle函数。在MSDN中,我找到了UnDecorateSymbolName:

http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms681400%28v=vs.85%29.aspx

不幸的是,即使是这样的符号,这个函数也不能取消装饰:

代码语言:javascript
复制
#include <Windows.h>
#include <DbgHelp.h>

#include <cstdlib>
#include <iostream>
#include <typeinfo>

int main()
{
    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);

    if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
    {
        std::cout << "SymInitialize returned error: " << GetLastError() << '\n';
        return EXIT_FAILURE;
    }

    class Foo {};
    Foo instance;

    const char* decorated_name = typeid(instance).name();
    char undecorated_name[1024];
    if (!UnDecorateSymbolName(decorated_name, undecorated_name, sizeof(undecorated_name) / sizeof(*undecorated_name), UNDNAME_COMPLETE))
    {
        std::cout << "UnDecorateSymbolName returned error: " << GetLastError() << '\n';
        return EXIT_FAILURE;
    }

    std::cout << "Decorated name: " << decorated_name << '\n'
              << "Undecorated name: " << undecorated_name << '\n';
}

输出

装饰名称:?AVFoo@?4?main@ 未装饰名称:?AVFoo@?4?main@

如果我做错了?

我在某个地方听说过_unDName函数,但是我找不到它的任何例子。在哪个头文件中定义了它?

EN

回答 4

Stack Overflow用户

发布于 2014-04-27 02:52:42

Visual已经发布了一个名为undname的实用程序。对于我的VS2010和VS2013安装,它安装在%VSINSTALL%\vc\bin目录中。对于x64平台,在%VSINSTALL%\vc\ And 64\bin目录中。

示例用法是:

代码语言:javascript
复制
D:\work\VS2013>undname "?static_x@?1??getX@@YAAAUX@@XZ@4U2@A"
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?static_x@?1??getX@@YAAAUX@@XZ@4U2@A"
is :- "struct X `struct X & __cdecl getX(void)'::`2'::static_x"

另一种获取名称的方法是使用/FAsc /Faoutput.asm编译器选项,它将生成程序集列表,在该列表中,每个损坏的名称都会被注释为它的名字。见This link for reference

票数 20
EN

Stack Overflow用户

发布于 2013-10-28 14:41:44

UndecorateSymbolName/__unDName似乎无法处理函数本地名称。如果您将类定义移动到全局范围,.name()将返回已经被蒙蔽的名称(使用.raw_name()获取损坏的名称)。

要手动拆分(全局)原始名称,需要对代码进行两个更改:

1)跳过错误名称(即从'?'开始)中的前导期。

2)而不是0,使用标志值0x2800 (UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY)。

我从VS2012的CRT来源中发现了这一点:

代码语言:javascript
复制
  if ((pTmpUndName = __unDName(NULL, (this->_M_d_name)+1, 0,
         &_malloc_base, &_free_base, 
         UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY)) == NULL)
票数 8
EN

Stack Overflow用户

发布于 2020-04-17 09:12:38

2019年更新。

(1)类型(实例).name()--在请求中使用--已经返回未修饰的名称:在本例中不需要进一步查询

(2)即使去掉初始点,bin文件夹中提供的命令UNDNAME.EXE也不能正常工作。例如,".?AVFoo@?1??main@@YAHXZ@“被简化为”??int __cdecl main(void)'::2':: AVFoo ",给出了一个无效的名称AVFoo。正确的名字必须是Foo

(3) dbghelp ()也不能工作。

(4)可以从编译器生成的指令typeid()程序集中推断出正确的代码。

下面是一个小程序,它将正确地消除所有C++损坏的符号:

代码语言:javascript
复制
// compile as: cl -W3 und.c

#include <windows.h>
#include "dbghelp.h"
#include <stdio.h>

#pragma comment(lib, "dbghelp.lib")

extern char *__unDName(char*, const char*, int, void*, void*, int);

int
main(int argc, char **argv)
{
    const char *decorated_name = 0;
    char undecorated_name[1024];

    if (argc == 2) decorated_name = argv[1];
    else {
        printf("usage: %s <decorated_name>\n", argv[0]);
        return 1;
        }

    __unDName(undecorated_name, decorated_name+1, 1024, malloc, free, 0x2800);

    printf("Decorated name: %s\n", decorated_name);
    printf("Undecorated name: %s\n", undecorated_name);
    return 0;
}

例如:

和".?AVFoo@?1??main@@YAHXZ@“ 装饰名称:.?AVFoo@?1??main@@YAHXZ@ 未修饰名称:类int __cdecl main(void)'::2'::Foo

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13777681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档