有谁知道如何手动破坏Visual C ++中的名称?

时间:2022-04-23 02:47:54

If I have a function in a .c like

如果我在.c中有一个函数

void foo(int c, char v);

...in my .obj, this becomes a symbol named

......在我的.obj中,这就成了一个名字

_foo

...as per C name mangling rules. If I have a similar function in a .cpp file, this becomes something else entirely, as per the compiler-specific name mangling rules. msvc 12 will give us this:

......根据C名称修改规则。如果我在.cpp文件中有类似的功能,那么根据特定于编译器的名称修改规则,这将成为完全不同的东西。 msvc 12会给我们这个:

?foo@@YAXHD@Z

If I have that function foo in the .cpp file and I want it to use C name mangling rules (assuming I can do without overloading), we can declare it as

如果我在.cpp文件中有这个函数foo并且我希望它使用C名称修改规则(假设我可以不重载),我们可以将其声明为

extern "C" void foo(int c, char v);

...in which case, we're back to good old

......在这种情况下,我们又恢复了良好的状态

_foo

...in the .obj symbol table.

...在.obj符号表中。

My question is, is it possible to go the other way around? If I wanted to simulate C++ name mangling with a C function, this would be easy with gcc because gcc's name mangling rules only make use of identifier-friendly characters, thus the mangled name of foo becomes _ZN3fooEic, and we could easily write

我的问题是,是否有可能走另一条路?如果我想用C函数模拟C ++名称修改,那么使用gcc会很容易,因为gcc的名称修改规则只使用了标识符友好的字符,因此foo的错误名称变成了_ZN3fooEic,我们可以轻松编写

void ZN3fooEic(int c, char v);

Back in Microsoft-compiler-land, I obviously can't create a function whose name is a completely invalid identifier called

回到Microsoft-compiler-land,我显然无法创建一个名为完全无效的标识符的函数

void ?foo@@YAXHD@Z(int c, char v);

...but I'd still like that function to show up with that symbol name in the .obj symbol table.

...但我仍然希望该函数在.obj符号表中显示该符号名称。

Any ideas? I've looked through Visual C++'s supported pragmas, and I don't see anything useful.

有任何想法吗?我查看了Visual C ++支持的pragma,但我没有看到任何有用的东西。

3 个解决方案

#1


6  

You can do this using __identifier:

您可以使用__identifier执行此操作:

#include <stdio.h>

#pragma warning(suppress: 4483)
extern "C" void __cdecl __identifier("?foo@@YAXHD@Z")(int c, char v)
{
    printf("%d %c\n", c, v);
}

void __cdecl foo(int, char);

int main()
{
    foo(10, 'x');
}

#2


7  

You're right. That's not (directly) possible (note: never trust VSC++). However, there exists a nifty workaround if you really need this. First of all, in the C++ file...

你是对的。这不是(直接)可能的(注意:永远不要相信VSC ++)。但是,如果你确实需要这个,那么有一个很好的解决方法。首先,在C ++文件中......

extern "C" int proxy(int i, char c);

int foo(int i, char c)
{
    return proxy(i, c);
}

Then, in the C file...

然后,在C文件中......

int proxy(int i, char c)
{
    // Do whatever you wanna do here
}

Without having to type any mangled name at all, you are now able to call the foo function, which is actually just a wrapper around the C function proxy. This gives you the same effect as if proxy was actually foo, from C++'s point of view. The single penalty here is of course a quick 'n' dirty function call. If the ABI allows it, and the compiler is smart enough, this can be replaced with a single JMP x86 instruction.

您根本无需键入任何受损名称,现在可以调用foo函数,它实际上只是C函​​数代理的包装器。从C ++的角度来看,这给你的效果就像代理实际上是foo一样。这里的单一惩罚当然是快速'n'脏函数调用。如果ABI允许它,并且编译器足够智能,则可以用单个JMP x86指令替换它。

Another way would be to write a function foo in C, and then use MinGW's objcopy in order to rename the symbol...

另一种方法是在C中编写一个函数foo,然后使用MinGW的objcopy来重命名符号......

$ objcopy --redefine-sym "foo=?foo@@YAXHD@Z" foobar.obj

I'm not sure if that's possible just with VSC++ tools. It would be very unstable, unportable, and hacky anyways.

我不确定是否可以使用VSC ++工具。无论如何,这将是非常不稳定,不可移植和hacky。

#3


6  

You might get it to work using a .DEF file. Define your function in your foo.cpp:

您可以使用.DEF文件使其工作。在foo.cpp中定义你的函数:

void foo(int c, char v) { ... } 

Then pass a def file to the linker, that looks like this:

然后将def文件传递给链接器,如下所示:

LIBRARY mylib
EXPORTS
   ?foo@@YAXHD@Z=_foo

Disclaimer: untested, I might be missing some details.

免责声明:未经测试,我可能会遗漏一些细节。

#1


6  

You can do this using __identifier:

您可以使用__identifier执行此操作:

#include <stdio.h>

#pragma warning(suppress: 4483)
extern "C" void __cdecl __identifier("?foo@@YAXHD@Z")(int c, char v)
{
    printf("%d %c\n", c, v);
}

void __cdecl foo(int, char);

int main()
{
    foo(10, 'x');
}

#2


7  

You're right. That's not (directly) possible (note: never trust VSC++). However, there exists a nifty workaround if you really need this. First of all, in the C++ file...

你是对的。这不是(直接)可能的(注意:永远不要相信VSC ++)。但是,如果你确实需要这个,那么有一个很好的解决方法。首先,在C ++文件中......

extern "C" int proxy(int i, char c);

int foo(int i, char c)
{
    return proxy(i, c);
}

Then, in the C file...

然后,在C文件中......

int proxy(int i, char c)
{
    // Do whatever you wanna do here
}

Without having to type any mangled name at all, you are now able to call the foo function, which is actually just a wrapper around the C function proxy. This gives you the same effect as if proxy was actually foo, from C++'s point of view. The single penalty here is of course a quick 'n' dirty function call. If the ABI allows it, and the compiler is smart enough, this can be replaced with a single JMP x86 instruction.

您根本无需键入任何受损名称,现在可以调用foo函数,它实际上只是C函​​数代理的包装器。从C ++的角度来看,这给你的效果就像代理实际上是foo一样。这里的单一惩罚当然是快速'n'脏函数调用。如果ABI允许它,并且编译器足够智能,则可以用单个JMP x86指令替换它。

Another way would be to write a function foo in C, and then use MinGW's objcopy in order to rename the symbol...

另一种方法是在C中编写一个函数foo,然后使用MinGW的objcopy来重命名符号......

$ objcopy --redefine-sym "foo=?foo@@YAXHD@Z" foobar.obj

I'm not sure if that's possible just with VSC++ tools. It would be very unstable, unportable, and hacky anyways.

我不确定是否可以使用VSC ++工具。无论如何,这将是非常不稳定,不可移植和hacky。

#3


6  

You might get it to work using a .DEF file. Define your function in your foo.cpp:

您可以使用.DEF文件使其工作。在foo.cpp中定义你的函数:

void foo(int c, char v) { ... } 

Then pass a def file to the linker, that looks like this:

然后将def文件传递给链接器,如下所示:

LIBRARY mylib
EXPORTS
   ?foo@@YAXHD@Z=_foo

Disclaimer: untested, I might be missing some details.

免责声明:未经测试,我可能会遗漏一些细节。