如何在保持其功能的同时绕过标准C ++函数 [英] How to Bypass a Standard C++ Function While Maintaining Its Functionality
问题描述
我正在寻找一种方法来重新定义一组POSIX函数,然后通过调用原始函数来结束重定义。这个想法是,我试图创建一个层,可以限制可以调用哪些操作系统API,取决于哪个配置文件是活动的。
例如,如果在一个配置文件中,我不允许使用strcpy,我想能够导致编译时错误(通过static_assert)或打印一些在屏幕上说strcpy不允许在此配置文件,如下:
MY_string.h
#include< string.h>
char * strcpy(char * restrict s1,const char * restrict s2)
{
#if defined(PROFILE_PASS_THROUGH)
printf(strcpy is not allowed in this profile \\\
);
return strcpy(s1,s2);
#elif defined(PROFILE_ERROR)
static_assesrt(0,strcpy不允许在此配置文件\\\
);
return 0;
#else
return strcpy(s1,s2);
#endif
}
MY_string.h
#define PROFILE_PASS_THROUGH
#includeMY_string.h
int main()
{
char temp1 [10];
char temp2 [10];
sprintf(temp2,Testing);
if(0 = strcpy(temp1,temp2))
{
printf(temp1 is%s\\\
,temp1);
}
return 0;
}
现在我意识到上面写的代码不能正确编译strcpy的重定义,但是有没有一种方法允许这种功能,而不玩宏或创建我自己的标准的c和c ++库?
-
您可以编写一个预处理器,将对标准例程的调用更改为对您自己的例程的调用。这样的预处理器可能很复杂,取决于你是否需要识别完整的C ++语法来区分使用命名空间的调用,或者你可以随意识别调用。
-
您可以链接到自己的库,生成具有已解析名称的可重定位对象模块。您的库将包含具有标准名称的例程,例如
strcpy
,可以执行您想要的任何代码,并调用其他名称,例如Mystrcpy
。由此生成的对象模块然后与第二库和标准库链接。第二个库包含具有那些名称的例程,例如Mystrcpy
,它调用原始库名称strcpy
。这样做的细节当然取决于你的链接器。目标是有一个这样的链:原始代码调用strcpy
。这被解析为第一个库中的strcpy
版本。该版本调用Mystrcpy
。Mystrcpy
调用标准库strcpy
。 -
-
GCC链接器有一个
- wrap
开关,用于解析对foo
的调用__ wrap_foo
并将对__ real_foo
(您将在实现中使用)的调用解析为真实的foo
。
在某些系统上,您可以使用自定义程序使用
dlsym
和< dlfcn.h>
中定义的其他函数加载包含标准实现的动态库,通过 dlsym
返回的指针调用它们,而不是通过源代码中的常用名称。 另请参阅在Windows,UNIX和Macintosh OS X平台上拦截任意函数。
I am looking for a way to be able to redefine a set of POSIX functions but then end the redefinition with a call to the original function. The idea is that I am trying to create a layer that can restrict what OS API's can be called depending on which "profile" is active. This "profile" determines what set of functions are allowed and any not specified should not be used.
For example, if in one profile I am not allowed to use strcpy, I would like to be able to either cause a compile time error (via static_assert) or print something to the screen saying "strcpy is not allowed in this profile" such as below:
MY_string.h
#include <string.h>
char *strcpy(char *restrict s1, const char *restrict s2)
{
#if defined(PROFILE_PASS_THROUGH)
printf("strcpy is not allowed in this profile\n");
return strcpy(s1, s2);
#elif defined(PROFILE_ERROR)
static_assesrt(0, "strcpy is not allowed in this profile\n");
return 0;
#else
return strcpy(s1, s2);
#endif
}
So that way within main.cpp I can use MY_string.h
#define PROFILE_PASS_THROUGH
#include "MY_string.h"
int main()
{
char temp1[10];
char temp2[10];
sprintf(temp2, "Testing");
if (0 = strcpy(temp1, temp2))
{
printf("temp1 is %s\n", temp1);
}
return 0;
}
Now I realize that the code I have written above will not compile properly due to the redefinition of strcpy, but is there a way to allow this sort of functionality without playing around with macros or creating my own standard c and c++ libraries?
You can write a preprocessor that changes calls to the standard routine to calls to your own routine. Such a preprocessor might be complicated, depending whether you need to recognize the full C++ grammar to distinguish calls using name spaces and so on or you can get away with more casual recognition of the calls.
You can link with your own library, producing a relocatable object module with resolved names stripped. Your library would contain routines with the standard names, such as
strcpy
, that execute whatever code you desire and call other names, such asMystrcpy
. The object module produced by this is then linked with a second library and with the standard library. The second library contains routines with those names, such asMystrcpy
, that call the original library namesstrcpy
. The details for doing this are of course dependent on your linker. The goal is to have a chain like this: Original code callsstrcpy
. This is resolved to the version ofstrcpy
in the first library. That version callsMystrcpy
.Mystrcpy
calls the standard librarystrcpy
.You can compile to assembly and edit the names in the assembly so that your routines are called instead of the standard library routines.
On some systems, you can use
dlsym
and other functions defined in<dlfcn.h>
to load the dynamic library that contains the standard implementations and to call them via pointers returned bydlsym
instead of by the usual names in source code.The GCC linker has a
--wrap
switch that resolves calls tofoo
to your routine__wrap_foo
and resolves calls to__real_foo
(which you would use in your implementation) to the realfoo
.
See also Intercepting Arbitrary Functions on Windows, UNIX, and Macintosh OS X Platforms.
这篇关于如何在保持其功能的同时绕过标准C ++函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!