如何找到一个C ++函数在运行时的地址&长度(MinGW的)(How to find the add

2019-10-29 03:37发布

由于这是我的第一篇到计算器,我要感谢大家的宝贵的职位,对我帮助很大,在过去。

我在Windows-7使用的MinGW(GCC 4.4.0)(64) - 更具体的我用诺基亚的Qt + MinGW的,但Qt是不参与我的问题。

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

我已经发现了如何计算的函数的长度,通过假定静态函数在一个源文件放置一个后彼此的溶液中,这是合乎逻辑要也顺序地放置的编译对象文件中,随后在存储器中。

不幸的是只有当整个CPP文件与选项编译这是真的:“G ++ -O0”(优化级别= 0)。 如果我用“G ++ -02”(这是我的项目的默认设置)编译,编译器似乎搬迁一些功能,因此计算功能长度似乎是不正确的和负的(!)。

发生这种情况,即使我把源文件中“的#pragma GCC优化0”线,它被认为是一个“G ++ -O0”命令行选项的等价物。

我想,“G ++ -02”指示编译器执行未使用#pragma指令避免一些全球性的文件级优化(部分功能搬迁?)。

你有任何想法如何避免这种情况,而不必编译整个文件用-O0选项? OR:你知不知道任何其他方法来找到在运行时函数的长度?

我准备一个小例子给你,结果用不同的编译选项,以突出的情况。


来源:

// ===================================================================
// 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);
    }
}

当用“克++ -O0”编译(正确的)输出:

[注意“C3”字节(=组件“保留”)在所有功能的结束]

======================
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

当用 “克++ -O2” 编译错误输出:(a)函数test_01地址&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.
Test End

Answer 1:

发生这种情况,即使我把源文件中“的#pragma GCC优化0”线,它被认为是一个“G ++ -O0”命令行选项的等价物。

我不相信这是真实的:它被认为是附接的等效__attribute__((optimize(0)))随后定义函数,这将导致具有不同的优化电平被编译的那些功能 。 但是,这并不影响在顶层发生的事情,而命令行选项呢。

如果你真的必须这样做依靠顶层排序可怕的事情,尝试-fno-toplevel-reorder选项。 我怀疑它是添加一个好主意__attribute__((noinline))有问题的功能,以及。



文章来源: How to find the address & length of a C++ function at runtime (MinGW)