获取全局变量存储的地址范围

问题描述 投票:0回答:1

我正在尝试查找全局变量在二进制 exec (ELF) 中的存储位置。

在我的最终上下文中,我的 exec 不是直接执行的,而是从另一个程序调用的,所以我不能使用

dlopen
__data_start
我在这里看了这篇文章:

如何在运行时确定共享库中全局变量的地址范围?

这确实很有趣,但是我的一些共享变量不在 Employed Russian 的方法返回的范围内。 如果将所有内容放在一个复制器中:

_end

我用
#define _GNU_SOURCE #include <link.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #define N 16 static int tab[N]; uintmax_t data_start; uintmax_t data_end; static int smpi_global_callback( struct dl_phdr_info *info, size_t size, void *data ){ int p_type, p_flags; for (size_t j = 0; j < info->dlpi_phnum; j++) { p_type = info->dlpi_phdr[j].p_type; p_flags = info->dlpi_phdr[j].p_flags; if( p_type == PT_LOAD && p_flags == PF_R|PF_W ){ data_start = info->dlpi_addr + info->dlpi_phdr->p_vaddr; data_end = info->dlpi_addr + info->dlpi_phdr->p_vaddr + info->dlpi_phdr->p_memsz; printf( "begin = %2zu ; end = %2zu\n", data_start, data_end ); return 0; /* always the same values so return after the first one */ } } return 0; } int main(){ int i = getpid(); dl_iterate_phdr(smpi_global_callback, NULL); tab[0] = i; printf( "ptr: %p %2zu\n", &tab, (uintmax_t)&tab ); printf( "ptr: %p %2zu\n", tab, (uintmax_t)tab ); printf( "ptr: %p %2zu\n", &data_start, (uintmax_t)data_start ); printf( "ptr: %p %2zu\n", &data_end, (uintmax_t)data_end ); return EXIT_SUCCESS; }

编译它,我得到类似的东西:

gcc -o myexec myexec.c -fPIC

一些观察:

数组超出第一个范围
  • $ ./myexec begin = 93878406574144 ; end = 93878406574872 begin = 140732748611584 ; end = 140732748615005 begin = 140256805367872 ; end = 140256805368656 begin = 140256807493632 ; end = 140256807497096 tab ptr: 0x5561c513b080 93878406590592 &tab ptr: 0x5561c513b080 93878406590592 data_start ptr: 0x5561c513b060 140256807493632 data_end ptr: 0x5561c513b068 140256807497096
  • 位于第四个范围的开头
  • data_start
  • 就在第四个范围结束之后
    
    
  • 是不是因为一些没有被
data_end

禁用的搬迁?我可以禁用它,或者找到真实位置吗?

    

c global-variables elf
1个回答
0
投票
通过以十六进制打印所有值并对齐地址,以便更容易比较,您的代码将受益匪浅。
  1. 在打印第一个
  2. -fPIC
  3. RW
    段后,您将从回调中返回,但不能保证只有一个这样的段(尽管
    通常
    只有一个)。 这个表达:
  4. LOAD
  5. 并没有像你想象的那样做。
  6. && p_flags == PF_R|PF_W
  7. tab
    完全
    相同。 您正在从 DSO 打印
  8. &tab
  9. ,但您只对主要可执行文件感兴趣。
    您正在打印 
  10. begin/end
  11. ,但
    可能
    您本来想打印 &data_start
    当您应该使用第 
  12. data_start
  13. 时,您正在使用第
    0
    
    
    纠正这些错误,我得到了预期范围内的所有地址:
  14. dlpi_phdr

代码:

j

© www.soinside.com 2019 - 2024. All rights reserved.