elf文件解析关键数据结构

以下是对这些ELF内部结构体的详细中文注释:

/* ELF文件头结构 (Elf_Internal_Ehdr) */
typedef struct elf_internal_ehdr {
  unsigned char e_ident[EI_NIDENT]; /* ELF魔数(0x7F+'E'+'L'+'F')和标识信息 */
  bfd_vma       e_entry;        /* 程序入口点虚拟地址 */
  bfd_size_type e_phoff;        /* 程序头表在文件中的偏移量 */
  bfd_size_type e_shoff;        /* 节头表在文件中的偏移量 */
  unsigned long e_version;      /* 文件版本号(通常为EV_CURRENT) */
  unsigned long e_flags;        /* 处理器特定标志 */
  unsigned short e_type;        /* 文件类型(ET_REL/ET_EXEC/ET_DYN等) */
  unsigned short e_machine;     /* 目标机器架构(EM_X86_64/EM_ARM等) */
  unsigned int  e_ehsize;       /* ELF头大小(字节) */
  unsigned int  e_phentsize;    /* 程序头表中每个条目的大小 */
  unsigned int  e_phnum;        /* 程序头表条目数量 */
  unsigned int  e_shentsize;    /* 节头表中每个条目的大小 */
  unsigned int  e_shnum;        /* 节头表条目数量 */
  unsigned int  e_shstrndx;     /* 节名称字符串表的节索引 */
} Elf_Internal_Ehdr;

/* 程序头结构 (描述段信息) */
struct elf_internal_phdr {
  unsigned long p_type;   /* 段类型(PT_LOAD/PT_DYNAMIC等) */
  unsigned long p_flags;  /* 段标志(PF_R/PF_W/PF_X组合) */
  bfd_vma p_offset;       /* 段在文件中的偏移量 */
  bfd_vma p_vaddr;        /* 段在内存中的虚拟地址 */
  bfd_vma p_paddr;        /* 段在内存中的物理地址(通常同虚拟地址) */
  bfd_vma p_filesz;       /* 段在文件中的大小 */
  bfd_vma p_memsz;        /* 段在内存中的大小(可能大于filesz) */
  bfd_vma p_align;        /* 段对齐要求(字节对齐) */
};

/* 节头结构 */
typedef struct elf_internal_shdr {
  unsigned int  sh_name;        /* 节名称(在字符串表中的索引) */
  unsigned int  sh_type;        /* 节类型(SHT_PROGBITS/SHT_NOBITS等) */
  bfd_vma       sh_flags;       /* 节标志(SHF_WRITE/SHF_ALLOC等) */
  bfd_vma       sh_addr;        /* 节在内存中的虚拟地址 */
  file_ptr      sh_offset;      /* 节在文件中的偏移量 */
  bfd_size_type sh_size;        /* 节的大小(字节) */
  unsigned int  sh_link;        /* 关联节的索引(根据节类型不同含义不同) */
  unsigned int  sh_info;        /* 附加信息(根据节类型不同含义不同) */
  bfd_vma       sh_addralign;   /* 节对齐要求 */
  bfd_size_type sh_entsize;     /* 条目大小(对于表类型的节) */
  
  /* 内部使用的缓存信息 */
  asection *    bfd_section;    /* 关联的BFD节结构 */
  unsigned char *contents;      /* 节内容缓存 */
} Elf_Internal_Shdr;

/* 压缩头结构 */
typedef struct elf_internal_chdr {
  unsigned int  ch_type;        /* 压缩类型(ELFCOMPRESS_ZLIB等) */
  bfd_size_type ch_size;        /* 未压缩数据的大小 */
  bfd_vma       ch_addralign;   /* 未压缩数据的对齐要求 */
} Elf_Internal_Chdr;

/* 符号表条目结构 */
struct elf_internal_sym {
  bfd_vma       st_value;       /* 符号值(地址/偏移量) */
  bfd_vma       st_size;        /* 符号大小 */
  unsigned long st_name;        /* 符号名称(字符串表索引) */
  unsigned char st_info;        /* 类型和绑定属性(STT_*/STB_*组合) */
  unsigned char st_other;       /* 可见性和目标特定信息 */
  unsigned char st_target_internal; /* 目标架构内部信息 */
  unsigned int  st_shndx;       /* 关联的节索引(SHN_ABS/SHN_COMMON等) */
};

/* 注释段结构 */
typedef struct elf_internal_note {
  unsigned long namesz;         /* 所有者名称的字节长度 */
  unsigned long descsz;         /* 描述数据的字节长度 */
  unsigned long type;           /* 描述数据类型(NT_GNU_ABI_TAG等) */
  char *        namedata;       /* 名称数据起始位置 */
  char *        descdata;       /* 描述数据起始位置 */
  bfd_vma       descpos;        /* 描述数据在文件中的偏移量 */
} Elf_Internal_Note;

/* 重定位条目结构(带加数) */
typedef struct elf_internal_rela {
  bfd_vma r_offset;  /* 需要重定位的位置 */
  bfd_vma r_info;    /* 符号索引和重定位类型 */
  bfd_vma r_addend;  /* 用于计算的常量加数 */
} Elf_Internal_Rela;

/* 动态段条目结构 */
typedef struct elf_internal_dyn {
  bfd_vma d_tag;               /* 动态条目类型(DT_NEEDED/DT_SYMTAB等) */
  union {
    bfd_vma d_val;             /* 整数值 */
    bfd_vma d_ptr;             /* 指针值 */
  } d_un;
} Elf_Internal_Dyn;

/* 版本定义结构(SHT_GNU_verdef节) */
typedef struct elf_internal_verdef {
  unsigned short vd_version;   /* 结构版本 */
  unsigned short vd_flags;     /* 标志(VER_FLG_BASE/VER_FLG_WEAK) */
  unsigned short vd_ndx;       /* 版本索引 */
  unsigned short vd_cnt;       /* 关联的verdaux条目数 */
  unsigned long  vd_hash;      /* 版本名称的哈希值 */
  unsigned long  vd_aux;       /* 到verdaux条目的偏移量 */
  unsigned long  vd_next;      /* 下一个verdef的偏移量 */
  
  /* 以下字段由BFD在读入时设置 */
  bfd *          vd_bfd;             /* 所属BFD */
  const char *   vd_nodename;        /* 版本名称 */
  struct elf_internal_verdef *vd_nextdef;  /* 指向下一个verdef */
  struct elf_internal_verdaux *vd_auxptr;  /* 指向关联的verdaux */
  unsigned int   vd_exp_refno;       /* 链接器使用的引用编号 */
} Elf_Internal_Verdef;

/* 版本定义辅助结构 */
typedef struct elf_internal_verdaux {
  unsigned long vda_name;      /* 版本名称的字符串表偏移 */
  unsigned long vda_next;      /* 下一个verdaux的偏移量 */
  
  /* 以下字段由BFD在读入时设置 */
  const char *vda_nodename;          /* 版本名称字符串 */
  struct elf_internal_verdaux *vda_nextptr; /* 指向下一个verdaux */
} Elf_Internal_Verdaux;

/* 版本需求结构(SHT_GNU_verneed节) */
typedef struct elf_internal_verneed {
  unsigned short vn_version;   /* 结构版本 */
  unsigned short vn_cnt;       /* 关联的vernaux条目数 */
  unsigned long  vn_file;      /* 库名称的字符串表偏移 */
  unsigned long  vn_aux;       /* 到vernaux条目的偏移量 */
  unsigned long  vn_next;      /* 下一个verneed的偏移量 */
  
  /* 以下字段由BFD在读入时设置 */
  bfd *          vn_bfd;             /* 所属BFD */
  const char *   vn_filename;        /* 库名称字符串 */
  struct elf_internal_vernaux *vn_auxptr;  /* 指向关联的vernaux */
  struct elf_internal_verneed *vn_nextref;  /* 指向下一个verneed */
} Elf_Internal_Verneed;

/* 版本需求辅助结构 */
typedef struct elf_internal_vernaux {
  unsigned long  vna_hash;     /* 依赖名称的哈希值 */
  unsigned short vna_flags;    /* 标志 */
  unsigned short vna_other;    /* 未使用 */
  unsigned long  vna_name;     /* 版本名称的字符串表偏移 */
  unsigned long  vna_next;     /* 下一个vernaux的偏移量 */
  
  /* 以下字段由BFD在读入时设置 */
  const char *vna_nodename;          /* 版本名称字符串 */
  struct elf_internal_vernaux *vna_nextptr; /* 指向下一个vernaux */
} Elf_Internal_Vernaux;

/* 版本符号结构(SHT_GNU_versym节) */
typedef struct elf_internal_versym {
  unsigned short vs_vers;      /* 版本索引 */
} Elf_Internal_Versym;

/* 符号信息结构 */
typedef struct {
  unsigned short int si_boundto;  /* 符号绑定目标 */
  unsigned short int si_flags;    /* 符号标志 */
} Elf_Internal_Syminfo;

/* 辅助向量结构(用于核心转储) */
typedef struct {
  bfd_vma a_type;    /* 辅助向量类型(AT_*) */
  bfd_vma a_val;     /* 辅助向量值 */
} Elf_Internal_Auxv;

/* 程序段映射结构(描述节如何分配到段) */
struct elf_segment_map {
  struct elf_segment_map *next;  /* 下一个段 */
  unsigned long p_type;          /* 段类型 */
  unsigned long p_flags;         /* 段标志 */
  bfd_vma p_paddr;               /* 段物理地址 */
  bfd_vma p_vaddr_offset;        /* 段虚拟地址偏移量 */
  bfd_vma p_align;               /* 段对齐 */
  bfd_vma p_size;                /* 段大小 */
  
  /* 标志位字段 */
  unsigned int p_flags_valid : 1;    /* p_flags是否有效 */
  unsigned int p_paddr_valid : 1;    /* p_paddr是否有效 */
  unsigned int p_align_valid : 1;    /* p_align是否有效 */
  unsigned int p_size_valid : 1;     /* p_size是否有效 */
  unsigned int includes_filehdr : 1;  /* 是否包含文件头 */
  unsigned int includes_phdrs : 1;    /* 是否包含程序头表 */
  unsigned int no_sort_lma : 1;       /* 是否禁止LMA排序 */
  
  unsigned int idx;           /* 原始排序索引 */
  unsigned int count;         /* 包含的节数量 */
  asection *sections[1];      /* 节指针数组(实际长度由count决定) */
};

关键结构说明:

  1. ELF文件头(Elf_Internal_Ehdr)

    • 包含ELF文件的元信息,如目标架构、文件类型、程序/节头表位置等
    • e_ident 前4字节必须是\x7FELF
  2. 程序头(Elf_Internal_Phdr)

    • 描述如何将文件映射到内存的段(Segment)信息
    • PT_LOAD类型的段会被实际加载到内存
  3. 节头(Elf_Internal_Shdr)

    • 描述ELF文件中的各个节(Section)
    • 包含节类型、大小、位置等元信息
  4. 动态链接相关结构

    • Elf_Internal_Dyn 描述动态链接器需要的信息
    • Elf_Internal_Verdef/Elf_Internal_Verdaux 处理符号版本控制
  5. 符号表结构(Elf_Internal_Sym)

    • 包含符号名称、值、大小和绑定信息
    • st_shndx 特殊值如SHN_UNDEF(未定义)、SHN_ABS(绝对符号)

这些结构体共同构成了ELF文件的完整描述,涵盖了从文件头到各个节区、符号表、重定位信息等所有核心数据。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容