如何找到地址&运行时C ++函数的长度(MinGW) [英] How to find the address & length of a C++ function at runtime (MinGW)

查看:145
本文介绍了如何找到地址&运行时C ++函数的长度(MinGW)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我使用MinGW(海湾合作委员会(gcc)),因为这是我第一次发布到stackoverflow,所以我想感谢你们所有的宝贵的职位, 4.4.0)在Windows-7(64) - 更具体地说我使用诺基亚Qt + MinGW但Qt没有参与我的问题。



我需要找到地址以及 - 更重要的是我的应用程序在运行时的特定功能的长度,以便对这些功能进行编码/解码并实现软件保护系统。

我已经找到了通过假定静态函数在源文件中一个接一个地放置,计算函数长度的解决方案是合乎逻辑的,它也被顺序地放置在编译的目标文件中,随后放在内存中。



不幸的是,只有在整个CPP文件编译时使用g ++ -O0(优化级别= 0)选项编译时才是如此。
如果我使用g ++ -O2(这是我的项目的默认值)进行编译,编译器似乎重定位了一些函数,结果计算得到的函数长度似乎不正确和负(!) 。



即使我在源文件中放置了#pragma GCC optimize 0行,
也应该是 g ++ -O0命令行选项。

我想g ++ -O2指示编译器执行一些全局文件级优化(某些函数重定位?),它是不能通过使用#pragma指令来避免。



您是否有任何想法如何避免这种情况,而无需使用-O0选项编译整个文件?
OR:你知道任何其他方法可以在运行时查找函数的长度吗?



我为你准备了一个小例子,和结果用不同的编译选项来突出显示这种情况。




来源:



  // ================================ =================================== 
// test.cpp
//
//意图:在运行时查找函数的addr和长度
//问题:使用g ++ -O0
编译时,应用程序输出是正确的//但它是错误的当编译时使用g ++ -O2
//(尽管存在指令#pragma GCC optimize 0)
// ================ ================================================== =

#include< stdio.h>
#include< math.h>

#pragma GCC优化0

static int test_01(int p1)
{
putchar('a');
putchar('\\\
');
返回1;


static int test_02(int p1)
{
putchar('b');
putchar('b');
putchar('\\\
');
返回2;


static int test_03(int p1)
{
putchar('c');
putchar('\\\
');
返回3;


static int test_04(int p1)
{
putchar('d');
putchar('\\\
');
返回4;
}

//打印一个特定地址和长度的HexDump
void HexDump(void * startAddr,long len)
{
unsigned char * buf =(unsigned char *)startAddr;
printf(addr:%ld,len:%ld\\\
,(long)startAddr,len);
len =(long)fabs(len);
while(len)
{
printf(%02x。,* buf);
buf ++;
len--;
}
printf(\\\
);


$ b int main(int argc,char * argv [])
{
printf(========= ============= \\\
);
long fun_len =(long)test_02 - (long)test_01;
HexDump((void *)test_01,fun_len);

printf(====================== \\\
);
fun_len =(long)test_03 - (long)test_02;
HexDump((void *)test_02,fun_len);

printf(====================== \\\
);
fun_len =(long)test_04 - (long)test_03;
HexDump((void *)test_03,fun_len);

printf(Test End \\\
);
getchar();

//只是一个技巧来阻止优化器将test_xx()函数作为未使用的
清除,如果(argc> 1)
{
test_01(1);
test_02(2);
test_03(3);
test_04(4);


code




用g ++ -O0编译时的(正确)输出:

[注意在所有函数结尾的'c3'字节(=汇编'ret')]



  ====================== 
addr:4199344,len:37
55.89.e5.83.ec.18.c7.04.24.61.00.00.00.e8.4e.62.00.00.c7.04.24.0a.00.00.00.e8.42
.62.00.00.b8.01.00.00.00.c9.c3。
======================
addr:4199381,len:49
55.89.e5.83.ec.18 .c7.04.24.62.00.00.00.e8.29.62.00.00.c7.04.24.62.00.00.00.e8.1d
.62.00.00.c7.04.24.0a.00.00.00.e8.11.62.00.00 .b8.02.00.00.00.c9.c3。
======================
addr:4199430,len:37
55.89.e5.83.ec.18 .c7.04.24.63.00.00.00.e8.f8.61.00.00.c7.04.24.0a.00.00.00.e8.ec
.61.00.00.b8.03.00.00.00.c9.c3。
测试结束






错误输出时用g ++ -O2编译:
(a)function test_01 addr& len似乎是正确的
(b)函数test_02,test_03具有负值长度,

和乐趣。 test_02长度也是不正确的。



  ==================== == 
addr:4199416,len:36
83.ec.1c.c7.04.24.61.00.00.00.e8.c5.61.00.00.c7.04.24.0a.00.00.00.e8 .b9.61.00.00
.b8.01.00.00.00.83.c4.1c.c3。
======================
addr:4199452,len:-72
83.ec.1c.c7。 04.24.62.00.00.00.e8.a1.61.00.00.c7.04.24.62.00.00.00.e8.95.61.00.00
.c7.04.24.0a.00.00.00.e8.89.61.00.00.b8。 02.00.00.00.83.c4.1c.c3.57.56.53.83.ec.2
0.8b.5c.24.34.8b.7c.24.30.89.5c.24.08.89.7c.24.04.c7.04。
======================
addr:4199380,len:-36
83.ec.1c.c7。 04.24.63.00.00.00.e8.e9.61.00.00.c7.04.24.0a.00.00.00.e8.dd.61.00.00
.b8.03.00.00.00.83.c4.1c.c3。
。测试结束


解决方案

即使我在源文件中放置了#pragma GCC optimize 0行,这应该等同于g ++ -O0命令行选项。


我不相信这是真的:它应该等同于附加 __属性__((optimize(0)))到随后定义的函数,这些函数会使用不同的优化级别进行编译。但是,这并不影响最高层次上的操作,而命令行选项则会影响它。



如果您确实需要依靠顶级订购来做可怕的事情,请尝试 -fno-toplevel-reorder 选项。我怀疑将 __ attribute __((noinline))添加到相关函数中是一个好主意。


As this is my first post to stackoverflow I want to thank you all for your valuable posts that helped me a lot in the past.

I use MinGW (gcc 4.4.0) on Windows-7(64) - more specifically I use Nokia Qt + MinGW but Qt is not involved in my Question.

I need to find the address and -more important- the length of specific functions of my application at runtime, in order to encode/decode these functions and implement a software protection system.

I already found a solution on how to compute the length of a function, by assuming that static functions placed one after each other in a source-file, it is logical to be also sequentially placed in the compiled object file and subsequently in memory.

Unfortunately this is true only if the whole CPP file is compiled with option: "g++ -O0" (optimization level = 0). If I compile it with "g++ -O2" (which is the default for my project) the compiler seems to relocate some of the functions and as a result the computed function length seems to be both incorrect and negative(!).

This is happening even if I put a "#pragma GCC optimize 0" line in the source file, which is supposed to be the equivalent of a "g++ -O0" command line option.

I suppose that "g++ -O2" instructs the compiler to perform some global file-level optimization (some function relocation?) which is not avoided by using the #pragma directive.

Do you have any idea how to prevent this, without having to compile the whole file with -O0 option? OR: Do you know of any other method to find the length of a function at runtime?

I prepare a small example for you, and the results with different compilation options, to highlight the case.


The Source:

// ===================================================================
// test.cpp
//
// Intention: To find the addr and length of a function at runtime
// Problem:   The application output is correct when compiled with: "g++ -O0"
//            but it's erroneous when compiled with "g++ -O2"
//            (although a directive "#pragma GCC optimize 0" is present)
// ===================================================================

#include <stdio.h>
#include <math.h>

#pragma GCC optimize 0

static int test_01(int p1)
{
    putchar('a');
    putchar('\n');
    return 1;
}

static int test_02(int p1)
{
    putchar('b');
    putchar('b');
    putchar('\n');
    return 2;
}

static int test_03(int p1)
{
    putchar('c');
    putchar('\n');
    return 3;
}

static int test_04(int p1)
{
    putchar('d');
    putchar('\n');
    return 4;
}

// Print a HexDump of a specific address and length
void HexDump(void *startAddr, long len)
{
    unsigned char *buf = (unsigned char *)startAddr;
    printf("addr:%ld, len:%ld\n", (long )startAddr, len);
    len = (long )fabs(len);
    while (len)
    {
        printf("%02x.", *buf);
        buf++;
        len--;
    }
    printf("\n");
}


int main(int argc, char *argv[])
{
    printf("======================\n");
    long fun_len = (long )test_02 - (long )test_01;
    HexDump((void *)test_01, fun_len);

    printf("======================\n");
    fun_len = (long )test_03 - (long )test_02;
    HexDump((void *)test_02, fun_len);

    printf("======================\n");
    fun_len = (long )test_04 - (long )test_03;
    HexDump((void *)test_03, fun_len);

    printf("Test End\n");
    getchar();

    // Just a trick to block optimizer from eliminating test_xx() functions as unused
    if (argc > 1)
    {
      test_01(1);
      test_02(2);
      test_03(3);
      test_04(4);
    }
}


The (correct) Output when compiled with "g++ -O0":

[note the 'c3' byte (= assembly 'ret') at the end of all functions]

======================
addr:4199344, len:37
55.89.e5.83.ec.18.c7.04.24.61.00.00.00.e8.4e.62.00.00.c7.04.24.0a.00.00.00.e8.42
.62.00.00.b8.01.00.00.00.c9.c3.
======================
addr:4199381, len:49
55.89.e5.83.ec.18.c7.04.24.62.00.00.00.e8.29.62.00.00.c7.04.24.62.00.00.00.e8.1d
.62.00.00.c7.04.24.0a.00.00.00.e8.11.62.00.00.b8.02.00.00.00.c9.c3.
======================
addr:4199430, len:37
55.89.e5.83.ec.18.c7.04.24.63.00.00.00.e8.f8.61.00.00.c7.04.24.0a.00.00.00.e8.ec
.61.00.00.b8.03.00.00.00.c9.c3.
Test End


The erroneous Output when compiled with "g++ -O2": (a) function test_01 addr & len seem correct (b) functions test_02, test_03 have negative lengths,

and fun. test_02 length is also incorrect.

======================
addr:4199416, len:36
83.ec.1c.c7.04.24.61.00.00.00.e8.c5.61.00.00.c7.04.24.0a.00.00.00.e8.b9.61.00.00
.b8.01.00.00.00.83.c4.1c.c3.
======================
addr:4199452, len:-72
83.ec.1c.c7.04.24.62.00.00.00.e8.a1.61.00.00.c7.04.24.62.00.00.00.e8.95.61.00.00
.c7.04.24.0a.00.00.00.e8.89.61.00.00.b8.02.00.00.00.83.c4.1c.c3.57.56.53.83.ec.2
0.8b.5c.24.34.8b.7c.24.30.89.5c.24.08.89.7c.24.04.c7.04.
======================
addr:4199380, len:-36
83.ec.1c.c7.04.24.63.00.00.00.e8.e9.61.00.00.c7.04.24.0a.00.00.00.e8.dd.61.00.00
.b8.03.00.00.00.83.c4.1c.c3.
Test End

解决方案

This is happening even if I put a "#pragma GCC optimize 0" line in the source file, which is supposed to be the equivalent of a "g++ -O0" command line option.

I don't believe this is true: it is supposed to be the equivalent of attaching __attribute__((optimize(0))) to subsequently defined functions, which causes those functions to be compiled with a different optimisation level. But this does not affect what goes on at the top level, whereas the command line option does.

If you really must do horrible things that rely on top level ordering, try the -fno-toplevel-reorder option. And I suspect that it would be a good idea to add __attribute__((noinline)) to the functions in question as well.

这篇关于如何找到地址&amp;运行时C ++函数的长度(MinGW)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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