1

我正在使用 C++ 程序上的 C 客户端对DynamoRIO进行二进制检测,尽管您可能不需要了解 DynamoRIO 来回答我的问题。目前我正在包装一个具有签名的函数:

virtual void foo(Klass& s)

然后在 wrap 函数中,我可以将此函数调用 ( Klass& s) 的参数传递给 void 指针 ( void *arg1)。我需要使用这个参数(即访问字段、调用方法),但是我不能像KlassC++ 类那样将它转换为适当的指针,而我使用的客户端是纯 C 语言。

当我尝试void*通过将其转换为以下内容来打印内容时size_t

printf("%zd\n", (size_t)arg1);

它给了我一个 8 位数字,例如25102856我猜是一个内存地址。

我的问题是如何在我的程序中访问这个对象?

请询问您需要的所有信息,我对所有想法持开放态度。

4

3 回答 3

3

为了使其工作 - 为 getter 和 setter 定义 C 样式包装器,如下例所示:

为你的班级

class Klass {
public:
  int getA() const;
  void setA(int);
  virtua int getB() const;
};

定义包装此类的 C 结构:

typedef int (*GetInt)(void*);
typedef void (*SetInt)(void*,int);
// and similar for other types


struct KlassCInterface {
  void* object;
  GetInt getA;
  SetInt setA;
  GetInt getB;
};

extern "C" int getA(void* obj)
{
    return static_cast<Klass*>(klassObj)->getA();
}
...
KlassCInterface* getCInterface(Klass* obj)
{
   // malloc just in case your client want to use free()
   KlassCInterface* retVal = (KlassCInterface*)malloc(sizeof(KlassCInterface));
   retVal->object = obj;
   retVal->getA = &getA;
   ...
   return retVal;     
}

当您传递 void* 数据时,将其作为 C 接口结构传递:

Klass* obj = new Klass(...);
KlassCInterface* objC = getCInterface(obj);

registerData(objC);

在您的 C 代码中 - 使用此 C 接口:

void doSthWihtKlass(void* data)
{
   KlassCInterface* objC  = (KlassCInterface*)data;
   printf("%d\n", objC->getA(objC->object));
}
于 2012-10-16T18:26:13.120 回答
1

这应该很难做到。您必须了解底层 C++ ABI。G++ 实现了这一点

通常,C++ 类的实现与 C 中的结构非常相似。大致而言,基类对象按照它们的声明顺序排在第一位。然后,该类的所有其他子对象按照它们的声明顺序依次出现。此规则递归地应用于每个封闭对象。多态对象会有不同的布局,因为必须存储更多的信息;特别是,指向虚方法的指针,或指向包含这些指针的结构的指针,必须存储在对象旁边的某个位置。

请注意,ISO 14882 没有解决这些问题。解决这个问题肯定会调用未定义的行为。

关于调用虚拟方法,您将不得不寻找 v-table。再一次,从你的编译器中研究 ABI。

于 2012-10-16T17:37:20.590 回答
1

您需要了解有关指针语义的更多信息(这就是我认为@Alek 的意思)。

首先,您可以使用%pprintf 格式说明符直接打印指针。这通常会产生一些有用的值,例如指针指向的内存位置。

您可以将指针转换为 achar *并使用它直接从内存中读取字节。或者您可以将其转换为 anunsigned char *并使用%x. 您可以将它转换为一个int *并读取一个由您的 C 实现表示的整数 - 例如,可能是一个 8 位字节上的 4 字节 2 的补码小端符号整数,没有未使用的位。

((unsigned long *)(((short *) ptr) + 7))[4]例如,将跳过等于 7 个 short 大小加上 4 个 unsigned long 大小的字节数,并从内存位置读取一个 unsigned long。假设 an 的正确表示(如 C 实现所期望的那样)unsigned long被写入该确切的内存位置,您将获得它的值。

您不仅必须确切地确定在所指向的内存中写入的内容ptr(这就是提到 ABI 的原因),而且生成的程序将是不可移植的,并且可能会随心所欲地更改/中断。

<inttypes.h>您可能还需要标题中指定的精确宽度整数类型。

于 2012-10-19T12:06:29.667 回答