【问题定位】全局变量的命名对其在静态存储区中地址的分配影响

背景:

程序运行异常时发现使用的A全局变量中的成员值被修改,经定位是B全局变量存在地址越界操作;
为了复现验证,搭建了简易测试程序后,竟然无法复现(A全局成员被修改)!!!。
后来一步步回退,当把全局变量名也保持一致时,问题可复现。

简易测试程序:

struct rte_pci_device testa[1];
struct mem_info mem_infos[PAGE_MAX][1];

#if 1
struct rte_pci_device* test_fun(struct rte_pci_device *p_dev,const char *dirname, uint16_t domain, uint8_t bus,
      uint8_t devid, uint8_t function)
{
  char filename[PATH_MAX];

   unsigned long tmp;
   struct rte_pci_device *dev = p_dev;
   
   ...
   ...
   tmp = 0x1086;
    
   printf("bp2:vaddr=%p\n",mem_infos[0][0].vaddr);

   dev->vendor_id = (uint16_t)tmp;
   printf("bp3:vaddr=%p\n",mem_infos[0][0].vaddr);

 return dev;
}

int pci_scan(void)
{
 char dirname[PATH_MAX];
 int index = 0;
 uint16_t domain;
 uint8_t bus, devid, function;
 ...
 ...
 ...
 while(index<=1)
 {
  if(test_fun(testa+index,dirname, domain, bus, devid, function))
  {
   index++;
  }

 }

 return 0;
}

过程描述:

rte_pci_device结构:对齐后有128字节
1.同一个测试程序,只是将全局变量testa恢复成原程序名chiper_pci后就能复现。
2. 查看程序地址信息:
A:测试程序将全局变量命名为testa时;

0000000000410c38  w      .data  0000000000000000              data_start
0000000000410c48 g       .bss   0000000000000000              __bss_start__
0000000000410d58 g       .bss   0000000000000000              _bss_end__
0000000000410c48 g       .data  0000000000000000              _edata
0000000000400844 g     F .text  000000000000002c              uio_init
0000000000400960 g     F .fini  0000000000000000              _fini
0000000000410d58 g       .bss   0000000000000000              __bss_end__
0000000000410c50 g     O .bss   0000000000000028              testa
0000000000400520       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.17
0000000000400530       F *UND*  0000000000000000              memset@@GLIBC_2.17
0000000000410c78 g     O .bss   0000000000000004              sum_fpga
0000000000410c38 g       .data  0000000000000000              __data_start
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000410c40 g     O .data  0000000000000000              .hidden __dso_handle
0000000000400550       F *UND*  0000000000000000              abort@@GLIBC_2.17
0000000000400970 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000400560       F *UND*  0000000000000000              puts@@GLIBC_2.17
0000000000410c80 g     O .bss   00000000000000d8              mem_infos       
00000000004008e0 g     F .text  0000000000000078              __libc_csu_init
0000000000410d58 g       .bss   0000000000000000              _end
0000000000400580 g     F .text  0000000000000000              _start
0000000000410d58 g       .bss   0000000000000000              __end__
0000000000410c48 g       .bss   0000000000000000              __bss_start
0000000000400870 g     F .text  000000000000006c              main
0000000000000000  w      *UND*  0000000000000000              _Jv_RegisterClasses
0000000000410c48 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000400570       F *UND*  0000000000000000              printf@@GLIBC_2.17
00000000004004e0 g     F .init  0000000000000000              _init

B:测试程序将全局变量命名为chiper_pci时;

0000000000410c38  w      .data  0000000000000000              data_start
0000000000410c48 g       .bss   0000000000000000              __bss_start__
0000000000410d58 g       .bss   0000000000000000              _bss_end__
0000000000410c48 g       .data  0000000000000000              _edata
0000000000400844 g     F .text  000000000000002c              uio_init
0000000000400960 g     F .fini  0000000000000000              _fini
0000000000410d58 g       .bss   0000000000000000              __bss_end__
0000000000400520       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.17
0000000000400530       F *UND*  0000000000000000              memset@@GLIBC_2.17
0000000000410c50 g     O .bss   0000000000000004              sum_fpga
0000000000410c38 g       .data  0000000000000000              __data_start
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000410c40 g     O .data  0000000000000000              .hidden __dso_handle
0000000000400550       F *UND*  0000000000000000              abort@@GLIBC_2.17
0000000000400970 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000400560       F *UND*  0000000000000000              puts@@GLIBC_2.17
0000000000410c80 g     O .bss   00000000000000d8              mem_infos
00000000004008e0 g     F .text  0000000000000078              __libc_csu_init
0000000000410c58 g     O .bss   0000000000000028              chiper_pci
0000000000410d58 g       .bss   0000000000000000              _end
0000000000400580 g     F .text  0000000000000000              _start
0000000000410d58 g       .bss   0000000000000000              __end__
0000000000410c48 g       .bss   0000000000000000              __bss_start
0000000000400870 g     F .text  000000000000006c              main
0000000000000000  w      *UND*  0000000000000000              _Jv_RegisterClasses
0000000000410c48 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000400570       F *UND*  0000000000000000              printf@@GLIBC_2.17
00000000004004e0 g     F .init  0000000000000000              _init

验证结果:

同一个程序,全局的不同命名,编译器在静态存储区分配的地址是不相同的。
从而导致命名chiper_pci时,地址分配在比mem_infos低位,以至于在对chiper_pci越界操作时,会对mem_infos造成影响。

ps:测试环境是arm平台版本,后续基于x86平台编译程序无法复现,原因:不通平台编译出的程序对应的地址分支差异很大,x86版本两个全局变量跨度非常远,逻辑分析只有增加循环次数,才会有影响(不排除其他版本/平台编译器会直接像A情况一样,直接分配到高地址位)

原因分析:

在Linux下,编译器通常使用一种名为Name Mangling的技术来实现函数重载和命名空间等功能。在使用Name Mangling时,编译器会把函数名或变量名转换成编译器可以识别的形式,以保证符号在链接期间能够正确地解析和匹配。
因此,在对全局变量进行NameMangling时,编译器可能会根据变量名、作用域等多种因素生成不同的内部名称,并在编译器内部维护一个符号表,把变量名和对应的内部名称进行映射。所以即使全局变量的名字不同,它们在程序运行时可能会被分配到不同的内存地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wyh_halo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值