其他分享
首页 > 其他分享> > 如何在保留标准C功能的同时绕过它

如何在保留标准C功能的同时绕过它

作者:互联网

我正在寻找一种方法,能够重新定义一组POSIX函数,但随后通过调用原始函数来结束重新定义.我的想法是,我试图创建一个可以限制哪个OS 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\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
}

这样在main.cpp中,我可以使用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;
}

现在我意识到,由于重新定义了strcpy,上面编写的代码将无法正确编译,但是有没有办法允许这种功能而又不使用宏或创建我自己的标准c和c库?

解决方法:

>您可以编写一个预处理程序,将对标准例程的调用更改为对您自己的例程的调用.这样的预处理器可能很复杂,取决于您是否需要识别完整的C语法以使用名称空间来区分调用,等等,还是可以通过更随意地识别调用来摆脱困境.
>您可以链接到自己的库,从而生成可重定位的对象模块,其中剥离了已解析的名称.您的库将包含具有标准名称的例程,例如strcpy,该例程将执行所需的任何代码,并调用其他名称,例如Mystrcpy.然后将由此产生的对象模块与第二个库和标准库链接.第二个库包含具有这些名称的例程,例如Mystrcpy,这些例程将调用原始库名称strcpy.当然,具体操作取决于您的链接器.目标是要有这样一个链:原始代码调用strcpy.这已解析为第一个库中的strcpy版本.该版本称为Mystrcpy. Mystrcpy调用标准库strcpy.
>您可以编译程序集并在程序集中编辑名称,以便调用例程而不是标准库例程.
>在某些系统上,可以使用dlsym和在< dlfcn.h>中定义的其他函数.加载包含标准实现的动态库,并通过dlsym返回的指针(而不是源代码中的常用名称)调用它们.
> GCC链接器具有–wrap开关,可将对foo的调用解析为例程__wrap_foo,并将对__real_foo的调用(将在实现中使用)解析为对实际foo的调用.

另请参见Intercepting Arbitrary Functions on Windows, UNIX, and Macintosh OS X Platforms.

标签:c,redefinition
来源: https://codeday.me/bug/20191012/1903643.html