ILD

lib/asm-offsets.c的作用
作者:Herbert Yuan 邮箱:yuanjp@hust.edu.cn
发布时间:2017-12-10 站点:Inside Linux Development

结构体的大小、某个成员的偏移。在c代码中可以用sizeof;将0转换成结构体指针,再取成员地址获得。但是在汇编代码中,没法直接获取这些信息。linux内核采用了一个技巧,生成一个头文件,使用宏定义这些大小信息。u-boot引用了这个技巧。


/lib/asm-offsets.c的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <common.h>
 
#include <linux/kbuild.h>
 
int main(void)
{
    /* Round up to make sure size gives nice stack alignment */
    DEFINE(GENERATED_GBL_DATA_SIZE,
        (sizeof(struct global_data) + 15) & ~15);
 
    DEFINE(GENERATED_BD_INFO_SIZE,
        (sizeof(struct bd_info) + 15) & ~15);
 
    DEFINE(GD_SIZE, sizeof(struct global_data));
 
    DEFINE(GD_BD, offsetof(struct global_data, bd));
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
    DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base));
#endif
 
    DEFINE(GD_RELOCADDR, offsetof(struct global_data, relocaddr));
 
    DEFINE(GD_RELOC_OFF, offsetof(struct global_data, reloc_off));
 
    DEFINE(GD_START_ADDR_SP, offsetof(struct global_data, start_addr_sp));
 
    return 0;
}


生成的头文件generic-asm-offsets.h的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __GENERIC_ASM_OFFSETS_H__
#define __GENERIC_ASM_OFFSETS_H__
/*
 * DO NOT MODIFY.
 *
 * This file was generated by Kbuild
 */
 
#define GENERATED_GBL_DATA_SIZE 176 /* (sizeof(struct global_data) + 15) & ~15 @ */
#define GENERATED_BD_INFO_SIZE 128 /* (sizeof(struct bd_info) + 15) & ~15  @ */
#define GD_SIZE 168 /* sizeof(struct global_data)  @ */
#define GD_BD 0 /* offsetof(struct global_data, bd)   @ */
#define GD_RELOCADDR 44 /* offsetof(struct global_data, relocaddr)    @ */
#define GD_RELOC_OFF 64 /* offsetof(struct global_data, reloc_off)    @ */
#define GD_START_ADDR_SP 60 /* offsetof(struct global_data, start_addr_sp)    @ */
 
#endif


方法生成一个汇编文件asm-offset.s,从汇编文件中提取这些信息。


其编译过程如下:

  /work/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc -Wp,-MD,arch/arm/lib/.asm-offsets.s.d  -nostdinc -isystem /work/toolchain/arm-unknown-linux-gnueabi/bin/../lib/gcc/arm-unknown-linux-gnueabi/6.3.0/include -Iinclude  -I/work/s3c2440/u-boot-2017.09/include  -I/work/s3c2440/u-boot-2017.09/arch/arm/include -include /work/s3c2440/u-boot-2017.09/include/linux/kconfig.h  -I/work/s3c2440/u-boot-2017.09/. -I. -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -fno-pic -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv4t -D__LINUX_ARM_ARCH__=4 -DDO_DEPS_ONLY    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(asm_offsets)"  -D"KBUILD_MODNAME=KBUILD_STR(asm_offsets)"  -fverbose-asm -S -o arch/arm/lib/asm-offsets.s /work/s3c2440/u-boot-2017.09/arch/arm/lib/asm-offsets.c


set -e; : '  CHK     include/generated/asm-offsets.h'; mkdir -p include/generated/; (set -e; echo "#ifndef __ASM_OFFSETS_H__"; echo "#define __ASM_OFFSETS_H__"; echo "/*"; echo " * DO NOT MODIFY."; echo " *"; echo " * This file was generated by Kbuild"; echo " */"; echo ""; sed -ne "s:[[:space:]]*\.ascii[[:space:]]*\"\(.*\)\":\1:; /^->/{s:->#\(.*\):/* \1 */:; s:^->\([^ ]*\) [\$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; s:^->\([^ ]*\) [\$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; echo ""; echo "#endif" ) < arch/arm/lib/asm-offsets.s > include/generated/asm-offsets.h.tmp; if [ -r include/generated/asm-offsets.h ] && cmp -s include/generated/asm-offsets.h include/generated/asm-offsets.h.tmp; then rm -f include/generated/asm-offsets.h.tmp; else : '  UPD     include/generated/asm-offsets.h'; mv -f include/generated/asm-offsets.h.tmp include/generated/asm-offsets.h; fi


参考

https://stackoverflow.com/questions/32777462/whats-purpose-of-arm64-kernel-asm-offsets-c


Copyright © insidelinuxdev.net 2017. Some Rights Reserved.