结构体的大小、某个成员的偏移。在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