我有一个特定的类,它仅作为全局数组的元素分配(想象一下文件句柄的示例)。
class MyClass;
MyClass A[1000];
我需要破解一个 C++ 编译器(例如 g++ 或 clang),以强制该类发出和解释指针,而不是作为该数组内的索引的地址。
所以这意味着我需要类的方法来接受索引作为“this”指针和构造函数来返回数组内的索引而不是指针。
因为我使用的是 x86 架构,所以当类的大小为 1 2 4 或 8 字节时,将这种索引转换为“有效地址”只是寻址模式的问题。
为了管理某种“外部指针”或类似的东西,这种可能性可能已经存在。
我发现知道的是 CLANG 内部的功能如下所述:
使用地址空间#256 对指针进行注释会导致它是相对于 X86 GS 段寄存器生成的代码,而地址空间#257 会导致它相对于 X86 FS 段。请注意,这是一个非常非常低级的功能,只有在您知道自己在做什么时才应该使用(例如在 OS 内核中)。
这是一个例子:
#define GS_RELATIVE __attribute__((address_space(256))) int foo(int GS_RELATIVE *P) { return *P; }
https://clang.llvm.org/docs/LanguageExtensions.html#memory-references-to-specified-segments
这可以解决相对性问题,但不能解决索引乘以到达地址。但是无论如何都不清楚如何使用它来从对象构造函数中获取相对地址。
这个问题由于不够清楚而被搁置,但无论如何我已经使用最终简单的方法解决了它,这里是解决方案的草稿(我最后到达),以帮助理解同样的问题也是一个可能的解决方案。
一个如此复杂的问题可以用足够“简单”的方法来解决,这似乎很奇怪。这正是我需要的解决方案,因为我可以将索引用作对象。
// compilation using g++ on x86 with flags -O3 -m32
// vect is the class we are acting upon
struct vect{
int dummy_for_clarity_of_offset;
int x;
// the "mull" method just multiplies member x with i and j
// according to the regparm(3) convention parameters up to 3 are passed in
// registers, so the pointer to the vect structure is passed in EAX the i parameter
// is passed in EDX and the j parameter in ECX (So the order is EAX EDX ECX )
__attribute__ ((noinline)) __attribute__ ((regparm(3))) void mull(int i,int j){
asm ("leal (%esi,%eax,8),%eax"); // the index in eax is converted to address
x*=i*j;
}
};
register vect* A asm ("%esi"); // the vect* A holds the start address of our array and
// is a register variable as it is the base of our calcs
// the same operations as above but as a function instead of method
__attribute__ ((noinline)) __attribute__ ((regparm(3))) void mull(vect& a,int i,int j)
{
asm ("leal (%esi,%eax,8),%eax");
a.x*=i*j;
}
int main(int argc, char **argv)
{
vect* A1=new(vect[0x10]);
A=A1;
A[1].x=9;
vect* p=(vect*)1; // according to "our convention" should point to A[1]
int i0=11;int i1=21;
mull(*p,10,20); // multiplies the member x of A[1] with 10 and 20
p->mull(i0,i1); // multiplies the member x of A[1] with 11 and 21
}