【问题标题】:Interpose C struct function pointer插入 C 结构函数指针
【发布时间】:2018-11-29 09:29:27
【问题描述】:

我正在尝试在 macOS 上的动态库内的 C 结构中插入声明为指针的函数。

我在 libA.dylib 中有这个结构:

libA.h:

typedef struct AStruct {
    int (*sub)(AStruct *pAStruct, int a, int b);
} AStruct;

extern "C" AStruct * AStruct_new();

libA.cpp:

int sub(AStruct *pAStruct, int a, int b) {
    return a - b;
}

AStruct * AStruct_new() {
    AStruct *pAStruct = (AStruct *)malloc(sizeof(AStruct));
    pAStruct->sub = *sub;
    return pAStruct;
}

在名称修改后,我发现库中对应的名称是这样的:_Z3subP7AStructii

在我的 dylib(我将其注入客户端代码)中,我正在这样做:

typedef struct AStruct {
    int (*sub)(AStruct *pAStruct, int a, int b);
} AStruct;

extern "C" int _Z3subP7AStructii(AStruct *pAStruct, int a, int b);

int _sub(AStruct *pAStruct, int a, int b) {
    printf("interposed %s: ", __func__);
    return pAStruct->sub(pAStruct, a, b);
} DYLD_INTERPOSE(_sub, _Z3subP7AStructii)

DYLD_INTERPOSE - 是来自 here 的 Apple 宏

相同的代码成功地适用于常规 C 函数、C++ 静态/实例方法,但无法弄清楚 struct 中的函数指针有什么问题:(

【问题讨论】:

  • 与问题无关:尝试:extern "C" int sub(.... 以避免名称混淆(尽管 sub 是一种常见名称)。
  • 关键是我无法控制libA中的代码,这只是一个例子:(
  • 还有其他问题,例如您似乎将结构 AStruct 复制到您自己的代码中,这使其容易受到攻击,因为如果您的结构与 libA 中的结构之间甚至有一个字符不匹配,那么当您破坏one definition rule 时,您将有未定义的行为。这种不匹配甚至可能是一个空格。
  • 它适用于常规 C 函数和 C++ 方法,无法理解我在这个带有结构函数指针的演示中做错了什么

标签: c++ c macos


【解决方案1】:

如果我理解正确,您希望所有对sub(或者更确切地说是_Z3subP7AStructii)的调用实际上是调用您的_sub 函数吗?问题是当“客户端”调用some_astruct->sub(...)时它实际上并没有直接调用_Z3subP7AStructii,因此你的_sub函数不会被调用。

换句话说,“客户端”没有调用_Z3subP7AStructii,而是调用了some_astruct->sub 指向的任何东西。 _Z3subP7AStructii 函数甚至不能被 libA 库导出(即与例如 static 有内部链接),它仍然可以通过结构调用。

对此的可能解决方案不是“插入”sub 函数,而是AStruct_create 函数。在您的版本中调用原始版本,然后将结构中指向 sub 函数的指针替换为您自己的函数(可能保存原始版本以便您可以使用它)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 2021-01-26
    • 2015-06-12
    • 2012-02-17
    相关资源
    最近更新 更多