如何在保持其功能的同时绕过标准C ++函数 [英] How to Bypass a Standard C++ Function While Maintaining Its Functionality

查看:234
本文介绍了如何在保持其功能的同时绕过标准C ++函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法来重新定义一组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 ++库?

解决方案


  1. 您可以编写一个预处理器,将对标准例程的调用更改为对您自己的例程的调用。这样的预处理器可能很复杂,取决于你是否需要识别完整的C ++语法来区分使用命名空间的调用,或者你可以随意识别调用。


  2. 您可以链接到自己的库,生成具有已解析名称的可重定位对象模块。您的库将包含具有标准名称的例程,例如 strcpy ,可以执行您想要的任何代码,并调用其他名称,例如 Mystrcpy 。由此生成的对象模块然后与第二库和标准库链接。第二个库包含具有那些名称的例程,例如 Mystrcpy ,它调用原始库名称 strcpy 。这样做的细节当然取决于你的链接器。目标是有一个这样的链:原始代码调用 strcpy 。这被解析为第一个库中的 strcpy 版本。该版本调用 Mystrcpy Mystrcpy 调用标准库 strcpy



  3. 在某些系统上,您可以使用自定义程序使用 dlsym < dlfcn.h> 中定义的其他函数加载包含标准实现的动态库,通过 dlsym 返回的指针调用它们,而不是通过源代码中的常用名称。


  4. GCC链接器有一个 - wrap 开关,用于解析对 foo 的调用 __ wrap_foo 并将对 __ real_foo (您将在实现中使用)的调用解析为真实的 foo


另请参阅在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?

解决方案

  1. 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.

  2. 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 as Mystrcpy. 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 as Mystrcpy, that call the original library names strcpy. The details for doing this are of course dependent on your linker. The goal is to have a chain like this: Original code calls strcpy. This is resolved to the version of strcpy in the first library. That version calls Mystrcpy. Mystrcpy calls the standard library strcpy.

  3. You can compile to assembly and edit the names in the assembly so that your routines are called instead of the standard library routines.

  4. 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 by dlsym instead of by the usual names in source code.

  5. The GCC linker has a --wrap switch that resolves calls to foo to your routine __wrap_foo and resolves calls to __real_foo (which you would use in your implementation) to the real foo.

See also Intercepting Arbitrary Functions on Windows, UNIX, and Macintosh OS X Platforms.

这篇关于如何在保持其功能的同时绕过标准C ++函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆