返回
Featured image of post Linux系统中的XCP标定技术点

Linux系统中的XCP标定技术点

解惑在Linux系统中XCP标定的虚拟地址和MAP文件的关系

解惑在Linux系统中XCP标定的虚拟地址和MAP文件的关系

什么是XCP

XCP的全名是通用测量和校正协定(Universal Measurement and Calibration Protocol),是ASAM提出的网络通讯协定,目的是要连接校正系统及电子控制单元(ECU)。此一协定可以在运行时读写微处理器里的变数以及内存。可以用计时器或是运作条件触发事件,同步触发或读取完整的资料集。也可以用XCP烧录快闪存储器。 —- 维基百科

虚拟地址空间

虚拟地址(vitural address)和物理地址(Physical Address) 在现代的操作系统中,为了让其他的程序能方便的运行在操作系统上,需要完成的一个很重要的抽象是「每个程序有自己的地址空间,且地址空间范围是一样的」,这将会减少了上层程序的大量麻烦,否则程序本身要维护自己需要的物理内存,这也会导致极大程度的不安全。个执行上看到的地址空间,就是虚拟内存。而访问虚拟内存的地址就是虚拟地址(Virtual Address),与之对应的是物理地址(Physical Address)。

一个小程序

#include <stdio.h>
int num;
int main(void)
{
    printf("num addr:\t\t%p\n",&num);
    return 0;
}

执行结果:

$ num addr:		0x55d87ad22034
$ num addr:		0x561a3b94b034
$ num addr:		0x55ded5b71034

由于Linux系统使用的是虚拟地址,可知每次的地址都不一样。

MAP 文件

map文件就是通过编译器编译之后,生成的程序、数据及IO空间信息的一种映射文件,里面包含函数大小,入口地址等一些重要信息。

gcc 生成 MAP 文件 增加参数 ”-Wl,-Map,out.map“ 即可

Linux下根据MAP生成 A2L文件

A2L文件中保存有需要标定的地址,标定地址即根据MAP 文件获取的全局变量地址

豁然开朗的demo

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define __USE_GNU
#include <link.h>

void *baseAddr;
static int dump_phdr(struct dl_phdr_info *pinfo, size_t size, void *data)
{
    // Application modules has no name
    if (0 == strlen(pinfo->dlpi_name))
    {
        extern char __data_start;
        baseAddr = (void*)pinfo->dlpi_addr;
    }
    return 0;
}

int num;
int main(void)
{
    dl_iterate_phdr(dump_phdr, NULL);
    printf("base addr:\t\t%p\n",baseAddr);
    printf("num addr:\t\t%p\n",&num);
    printf("num relative addr:\t0x%lx\n", (uint64_t)((void*)&num - baseAddr));
    return 0;
}

程序输出:

base addr:              0x55b2f6a5f000
num addr:               0x55b2f6c60018
num relative addr:      0x201018

MAP 文件:

.bss            0x0000000000201010       0x18
 *(.dynbss)
 .dynbss        0x0000000000201010        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0000000000201010        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
 .bss           0x0000000000201010        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
 .bss           0x0000000000201010        0x1 /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
 .bss           0x0000000000201011        0x0 /tmp/ccgkH8UK.o
 .bss           0x0000000000201011        0x0 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .bss           0x0000000000201011        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
 .bss           0x0000000000201011        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
 *(COMMON)
 *fill*         0x0000000000201011        0x7 
 COMMON         0x0000000000201018       0x10 /tmp/ccgkH8UK.o
                0x0000000000201018                num
                0x0000000000201020                baseAddr
                0x0000000000201028                . = ALIGN ((. != 0x0)?0x8:0x1)

由以上demo可知 通过 dl_iterate_phdr() 这个函数实现了变量地址的过程,解决虚拟地址带来的标定问题。

京ICP备2021008845号 | PV:
Built with Hugo
Theme Stack designed by Jimmy