【问题标题】:Function to mangle/demangle functions破坏/破坏功能的功能
【发布时间】:2011-06-23 19:15:51
【问题描述】:

我以前,here,已经证明 C++ 函数不容易在汇编中表示。现在我有兴趣以一种或另一种方式阅读它们,因为作为 Valgrind 的一部分的 Callgrind 显示它们被破坏,而在组装时它们被显示为破坏。

所以我想要么破坏 Valgrind 函数输出,要么破坏函数的程序集名称。有人尝试过这样的事情吗?我正在查看website 并发现以下内容:

Code to implement demangling is part of the GNU Binutils package; 
see libiberty/cplus-dem.c and include/demangle.h.

有没有人尝试过这样的事情?我想在 C 中进行 demangle/mangle。

我的编译器是 gcc 4.x。

【问题讨论】:

  • 我不明白您的问题 - 您已经发布了自己的答案,请使用 binutils 中的代码。其他工具链都有类似的库/代码sn-ps,那么问题出在哪里?
  • IIRC 然后 valgrind 已经有一个 --demangle=yes 选项来对输出上的 C++ 符号进行去角化。那么callgrind可以叫valgrind --tool=callgrind --demangle=yes不是吗?
  • @Luther:我打开了另一个论坛来检查我是否对 vallgrind stackoverflow.com/questions/4846411/de-mangeling-in-callgrind 进行了 demangle,但没有人回复。我查看了 linux 手册以解开它没有提供任何东西!你的建议奏效了。谢谢
  • 以下答案仅涵盖 demangle 情况。 mangle 案例是 c++ - Is it possible to mangle typename at runtime? - Stack Overflownote 请参阅此问题链接的问题,以及 that 问题链接的问题)
  • 对于 Python,请参阅 stackoverflow.com/questions/6526500/…

标签: c++ c function assembly name-mangling


【解决方案1】:

这是上面 Dave 版本的轻微变化。这是一个 unique_ptr 版本,对返回类型进行了一些检查,虽然看起来你可以忽略它,但不知何故这似乎不干净。

auto cppDemangle (const char *abiName)
{
    //
    // This function allocates and returns storage in ret
    //
    int status;
    char *ret = abi::__cxa_demangle(abiName, 0 /* output buffer */, 0 /* length */, &status);

    auto deallocator = ( [](char *mem) { if (mem) free((void*)mem); } );

    if (status) {
        // 0: The demangling operation succeeded.
        // -1: A memory allocation failure occurred.
        // -2: mangled_name is not a valid name under the C++ ABI mangling rules.
        // -3: One of the arguments is invalid.
        std::unique_ptr<char, decltype(deallocator) > retval(nullptr, deallocator);
        return retval;
    }

    //
    // Create a unique pointer to take ownership of the returned string so it
    // is freed when that pointers goes out of scope
    //
    std::unique_ptr<char, decltype(deallocator) > retval(ret, deallocator);
    return retval;
}

【讨论】:

  • 您忘记在if(status) { ... } 中返回retval
【解决方案2】:

这是我的 C++11 实现,源自以下页面: http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html

#include <cxxabi.h>  // needed for abi::__cxa_demangle

std::shared_ptr<char> cppDemangle(const char *abiName)
{
  int status;    
  char *ret = abi::__cxa_demangle(abiName, 0, 0, &status);  

  /* NOTE: must free() the returned char when done with it! */
  std::shared_ptr<char> retval;
  retval.reset( (char *)ret, [](char *mem) { if (mem) free((void*)mem); } );
  return retval;
}

为了使返回的 (char *) 上的内存管理更容易,我使用了一个 std::shared_ptr 和一个自定义 lambda 'deleter' 函数,该函数在返回的内存上调用 free()。正因为如此,我永远不必担心自己删除内存,我只是根据需要使用它,当 shared_ptr 超出范围时,内存将被释放。

这是我用来以 (const char *) 形式访问解构类型名称的宏。请注意,您必须打开 RTTI 才能访问“typeid”

#define CLASS_NAME(somePointer) ((const char *) cppDemangle(typeid(*somePointer).name()).get() )

所以,在 C++ 类中,我可以说:

printf("I am inside of a %s\n",CLASS_NAME(this));

【讨论】:

  • 不错。虽然可以做到unique_ptr,或者只是构造一个std::string并立即释放()。
  • 谢谢。 :) 我得看看 unique_ptr (还没有使用它们)。我故意不使用 std::string / immediate free() 方法以避免额外的副本。也就是说,性能影响可能并不重要——我通常只将它用于调试打印,而不是任何类型的速度关键应用程序。无论如何,希望那里有足够的内容供某人根据自己的需要自定义功能。
  • 谢谢戴夫。我只是想指出,如果可以使用 boost,则可以通过 boost/core/demangle.hpp 获得更简洁的选项,如下所示:stackoverflow.com/a/34916852/1797414
【解决方案3】:

使用c++filt 命令行工具对名称进行解密。

【讨论】:

  • 是的,可以在命令行上使用。我相信提问者正在寻找可以从代码中调用的库函数。
  • 这是公认的答案,所以我认为这回答了提问者在寻找什么的问题。
  • 一切都很好,事实上我在阅读您的回答时学到了一些新东西,所以我当然很感激。无论如何,我在下面添加了“来自代码”的版本,因为这是我根据问题的标题来寻找的。我相信这两个答案都会对某人有所帮助。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2015-11-27
  • 2019-06-22
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多