gpt4 book ai didi

linux - 如何在 Linux x86_64 系统上获取 VDSO 的大小

转载 作者:太空狗 更新时间:2023-10-29 12:23:44 24 4
gpt4 key购买 nike

我想以一种可以使用 objdump -D 验证它是否正确的方式将 VDSO 转储到磁盘。

我们可以使用 getauxval(AT_SYSINFO_EHDR) 获取 VDSO 的基地址,如 vdso(7) 中所述。但是如何获得对象的大小呢?

我碰巧知道它恰好有两页那么长,但我不确定我是否可以信赖它。

我在 ELF header 中看不到任何指示对象整体大小的内容,我还尝试通过 dl_iterate_phdr(3) 迭代和转储这些部分到 no喜悦(大概这会跳过 ELF header ?)。

有什么想法吗?我真的必须从过程映射中删除大小吗?

最佳答案

VDSO header 为您提供了文件的开头。要找到结尾,请计算以下项的最大值:

  • 程序头表中所有段的结尾(偏移+大小)
  • 节头表结束
  • 程序头表结束

然后将开始和结束之间的所有内容写入磁盘。下面的程序应该可以解决问题:

#include <stdlib.h>
#include <stdio.h>
#include <sys/auxv.h>

struct elf_fhdr_64
{
uint32_t magic;
uint8_t ei_class;
uint8_t ei_data;
uint8_t ei_version;
uint8_t ei_osabi;
uint8_t ei_abiversion;
uint8_t pad[7];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff; // program header offset
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum; // number of program headers
uint16_t e_shentsize;
uint16_t e_shnum;
// ...
};

struct elf_phdr_64
{
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset; // offset in file
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz; // size in file
// ...
};

struct elf_shdr_64
{
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr; // virtual addr when loaded
uint64_t sh_offset; // offset in file
uint64_t sh_size; // size in file
// ...
};

int main(int argc, char **argv)
{
unsigned long vdso_hdr = getauxval(AT_SYSINFO_EHDR);

uint32_t elf_magic = * (uint32_t *)vdso_hdr;
if (elf_magic == 0x464C457F) {
printf("has elf magic, proceeding...\n");
}
else {
printf("no elf magic.\n");
exit(1);
}

struct elf_fhdr_64 * fhdrp = (struct elf_fhdr_64 *) vdso_hdr;

int num_phdrs = fhdrp->e_phnum;
uint16_t phentsize = fhdrp->e_phentsize;

long max_offs = 0;

for (int i = 0; i < num_phdrs; i++) {
struct elf_phdr_64 * phdr = (struct elf_phdr_64 *)(vdso_hdr
+ fhdrp->e_phoff + i * phentsize);
long file_offs = phdr->p_offset + phdr->p_filesz;
if (max_offs < file_offs) max_offs = file_offs;
}

int num_shdrs = fhdrp->e_shnum;
int shentsize = fhdrp->e_shentsize;

for (int i = 0; i < num_shdrs; i++) {
struct elf_shdr_64 * shdr = (struct elf_shdr_64 *)(vdso_hdr
+ fhdrp->e_shoff + i * shentsize);
long file_offs = shdr->sh_offset + shdr->sh_size;
if (max_offs < file_offs) max_offs = file_offs;
}

// section table:
int section_table_max = fhdrp->e_shoff + (num_shdrs * shentsize);
if (max_offs < section_table_max) max_offs = section_table_max;

// phdrs table:
int phdr_table_max = fhdrp->e_phoff + (num_phdrs * phentsize);
if (max_offs < phdr_table_max) max_offs = section_table_max;

FILE * outfile = fopen("test-vdso.so", "wb");
if (outfile) {
fwrite((void *) vdso_hdr, 1, max_offs, outfile);
fclose(outfile);
}

return 0;
}

关于linux - 如何在 Linux x86_64 系统上获取 VDSO 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49071746/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com