Bfd对elf文件头的处理

 

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

   

本文适用于

bfinutils-2.19

vs2008

   

欢迎转载,但请保留作者信息

 

 

1.1    数值转换

elf文件中,最开始的就是文件头,用结构体表示就是:

typedef struct {

  unsigned char    e_ident[16];       /* ELF "magic number" */

  unsigned char    e_type[2];         /* Identifies object file type */

  unsigned char    e_machine[2];      /* Specifies required architecture */

  unsigned char    e_version[4];      /* Identifies object file version */

  unsigned char    e_entry[4];        /* Entry point virtual address */

  unsigned char    e_phoff[4];        /* Program header table file offset */

  unsigned char    e_shoff[4];        /* Section header table file offset */

  unsigned char    e_flags[4];        /* Processor-specific flags */

  unsigned char    e_ehsize[2];       /* ELF header size in bytes */

  unsigned char    e_phentsize[2];        /* Program header table entry size */

  unsigned char    e_phnum[2];        /* Program header table entry count */

  unsigned char    e_shentsize[2];        /* Section header table entry size */

  unsigned char    e_shnum[2];        /* Section header table entry count */

  unsigned char    e_shstrndx[2];         /* Section header string table index */

} Elf32_External_Ehdr;

这个结构体表现了文件头中各个字段所占用的字节数,但是并没有考虑这些值是以bigendian还是littleendian方式存放的。为了方便使用,bfd另外定义了一个内部使用的结构体进行表示:

typedef struct elf_internal_ehdr {

  unsigned char        e_ident[EI_NIDENT]; /* ELF "magic number" */

  bfd_vma     e_entry; /* Entry point virtual address */

  bfd_size_type        e_phoff; /* Program header table file offset */

  bfd_size_type        e_shoff; /* Section header table file offset */

  unsigned long        e_version;    /* Identifies object file version */

  unsigned long        e_flags; /* Processor-specific flags */

  unsigned short   e_type;       /* Identifies object file type */

  unsigned short   e_machine;    /* Specifies required architecture */

  unsigned int         e_ehsize; /* ELF header size in bytes */

  unsigned int         e_phentsize;  /* Program header table entry size */

  unsigned int         e_phnum; /* Program header table entry count */

  unsigned int         e_shentsize;  /* Section header table entry size */

  unsigned int         e_shnum; /* Section header table entry count */

  unsigned int         e_shstrndx;   /* Section header string table index */

} Elf_Internal_Ehdr;

此外还定义了elf_swap_ehdr_inelf_swap_ehdr_out两个函数在这两种表示方式之间进行转换:

 

/* Translate an ELF file header in external format into an ELF file header in

   internal format.  */

 

static void

elf_swap_ehdr_in (bfd *abfd,

           const Elf_External_Ehdr *src,

           Elf_Internal_Ehdr *dst)

{

  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;

  memcpy (dst->e_ident, src->e_ident, EI_NIDENT);

  dst->e_type = H_GET_16 (abfd, src->e_type);

  dst->e_machine = H_GET_16 (abfd, src->e_machine);

  dst->e_version = H_GET_32 (abfd, src->e_version);

  if (signed_vma)

    dst->e_entry = H_GET_SIGNED_WORD (abfd, src->e_entry);

  else

    dst->e_entry = H_GET_WORD (abfd, src->e_entry);

  dst->e_phoff = H_GET_WORD (abfd, src->e_phoff);

  dst->e_shoff = H_GET_WORD (abfd, src->e_shoff);

  dst->e_flags = H_GET_32 (abfd, src->e_flags);

  dst->e_ehsize = H_GET_16 (abfd, src->e_ehsize);

  dst->e_phentsize = H_GET_16 (abfd, src->e_phentsize);

  dst->e_phnum = H_GET_16 (abfd, src->e_phnum);

  dst->e_shentsize = H_GET_16 (abfd, src->e_shentsize);

  dst->e_shnum = H_GET_16 (abfd, src->e_shnum);

  dst->e_shstrndx = H_GET_16 (abfd, src->e_shstrndx);

}

在这个函数中,使用了H_GET_16这样的宏来进行值的转换,看看它的定义:

#define H_GET_16  bfd_h_get_16

#define bfd_h_get_16(abfd, ptr) /

  BFD_SEND (abfd, bfd_h_getx16, (ptr))

#define BFD_SEND(bfd, message, arglist) /

  ((*((bfd)->xvec->message)) arglist)

也就是说,它将调用不同的target提供的回调函数来完成数值的转换,比如对于elf32-bfin这个target,它的bfd_h_getx16这个回调函数指向bfd_getl16这个函数。

 

bfd_vma

bfd_getl16 (const void *p)

{

  const bfd_byte *addr = p;

  return (addr[1] << 8) | addr[0];

}

1.2    文件头存储

elf的后端数据表示中,用

      struct elf_obj_tdata *elf_obj_data;

来表示elf格式的所有数据,其中struct elf_obj_tdata就保存了elf文件头:

 

/* Some private data is stashed away for future use using the tdata pointer

   in the bfd structure.  */

 

struct elf_obj_tdata

{

  Elf_Internal_Ehdr elf_header[1];   /* Actual data, but ref like ptr */

  ………………….

};

要读写这个文件头的数据,可以用

#define elf_elfheader(bfd)  (elf_tdata(bfd) -> elf_header)

这个宏来取得此文件头。

1.3    e_machine

在文件头中,有个叫e_machine的字段,用以表示此elf文件数据适用的CPU类型,在elf/common.h中定义了一百多种的CPU类型,比如:

#define EM_386           3  /* Intel 80386 */

#define EM_BLACKFIN    106  /* ADI Blackfin */

不过在vdspdoj文件中,并没有使用EM_BLACKFIN这个值,而是使用了不在定义中的值34。因而在elf32-bfin这个目标处理时,将不再进行后继处理。为了让bfd支持doj格式的文件,自定义一个值:

#define EM_VDSP_DOJ         34  /*vdsp doj file*/

修改elf_object_p函数:

  /* Check that the ELF e_machine field matches what this particular

     BFD format expects.  */

  if (ebd->elf_machine_code != i_ehdrp->e_machine

      && (ebd->elf_machine_alt1 == 0

       || i_ehdrp->e_machine != ebd->elf_machine_alt1)

      && (ebd->elf_machine_alt2 == 0

       || i_ehdrp->e_machine != ebd->elf_machine_alt2))

    {

      if (ebd->elf_machine_code != EM_NONE)

     goto got_wrong_format_error;

………………………………..

    }

这个判断条件可以改为:

     /* Check that the ELF e_machine field matches what this particular

     BFD format expects.  */

     if (ebd->elf_machine_code != i_ehdrp->e_machine

         && (ebd->elf_machine_alt1 == 0

         || i_ehdrp->e_machine != ebd->elf_machine_alt1)

         && (ebd->elf_machine_alt2 == 0

         || i_ehdrp->e_machine != ebd->elf_machine_alt2) &&

         i_ehdrp->e_machine != EM_VDSP_DOJ)

     {

………………..

 

 

 

 

参考资料

bfd对多目标的支持 2008-9-25

bfdelf32格式的支持( 2008-11-7 )

objdumpreadelf的区别( 2008-11-10 )

objdump代码分析( 2008-11-10 )

bfd的文件格式识别 2008-11-10

bfd的后端数据表示( 2008-11-10 )

Bfd中的内存泄漏 2008-11-13

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值