auxiliary vector 是内核ELF二进制加载器提供给用户空间的一些信息的集合,包括可执行的入口地址、线程的gid、线程uid、vdso入口地址等等。不过,普通应用程序通常不需要关心这些信息,目前主要是动态链接器(ld-linux.so)在使用这些信息。通过auxiliary vector,动态链接器可以方便的获取那些它所需要的来自内核的信息。内核为动态链接器提供了一种方便的获取系统信息的途径。可以方便的将一些标准信息提供给动态链接器。虽然有些信息也可以通过系统调用来获得,但通过auxiliary vector的方式更加轻量级。
auxiliary vector 包含一系列的键值对(type value pair),每一个键(type)对应一个值(value)。它包含的键比较多,下面从man手册中摘抄几个type:
AT_BASE - The base address of the program interpreter (usually, the dynamic linker).
AT_BASE_PLATFORM - A pointer to a string (PowerPC and MIPS only). On PowerPC, this identifies the real platform; may differ from AT_PLATFORM. On MIPS, this identifies the ISA level (since
Linux 5.7).
AT_CLKTCK - The frequency with which times(2) counts. This value can also be obtained via sysconf(_SC_CLK_TCK).
AT_DCACHEBSIZE - The data cache block size.
AT_EGID - The effective group ID of the thread.
AT_ENTRY - The entry address of the executable.
AT_EUID - The effective user ID of the thread.
AT_EXECFD - File descriptor of program.
AT_EXECFN - A pointer to a string containing the pathname used to execute
the program.
...
查看方法
1)脚本查看
$ LD_SHOW_AUXV=1 sleep 1
AT_SYSINFO_EHDR: 0x7fff16938000
AT_HWCAP: 78bfbff
AT_PAGESZ: 4096
AT_CLKTCK: 100
AT_PHDR: 0x55ee3c9a8040
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x7fbf9fc64000
AT_FLAGS: 0x0
AT_ENTRY: 0x55ee3c9ac335
AT_UID: 1016
AT_EUID: 1016
AT_GID: 1016
AT_EGID: 1016
AT_SECURE: 0
AT_RANDOM: 0x7fff16900f19
AT_HWCAP2: 0x0
AT_EXECFN: /usr/libexec/pk-command-not-found
AT_PLATFORM: x86_64
2)编程查看
getauxval()系统调用可以获得指定键(type)的值,该系统调用的头文件是 sys/auxv.h 。
#include <stdio.h>
#include <sys/auxv.h>
int main(void) {
void *entry = (void *)getauxval(AT_ENTRY);
printf("the entry of the process is: 0x%0lx\n", entry);
long clock = getauxval(AT_CLKTCK);
printf("the clktck is: %ld\n", clock);
void *base_addr = (void *)getauxval(AT_BASE);
printf("the base address is: 0x%0lx\n", base_addr);
long data_cache_block_size = getauxval(AT_DCACHEBSIZE);
printf("the data cache block size is: %d\n", data_cache_block_size);
char *pathname = (char *)getauxval(AT_EXECFN);
printf("the path of the process running is: %s\n", pathname);
long pagesize = (long)getauxval(AT_PAGESZ);
printf("the page size of the process is: %d\n", pagesize);
void *vdso_entry = (void *)getauxval(AT_SYSINFO);
printf("the vdso entry is: 0x%0lx\n", vdso_entry);
void *vdso_ehdr = (void *)getauxval(AT_SYSINFO_EHDR);
printf("the vdso ehdr is: 0x%0lx\n", vdso_ehdr);
return 0;
}
运行结果:
$ gcc main.c -o main
$ ./main
the entry of the process is: 0x4004b0
the clktck is: 100
the base address is: 0x7fa663453000
the data cache block size is: 0
the path of the process running is: ./main
the page size of the process is: 4096
the vdso entry is: 0x0
the vdso ehdr is: 0x7ffd5cde6000