bfd的文件格式识别

 

快乐虾

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

lights@hb165.com

   

本文适用于

bfinutils-2.19

vs2008

   

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

 

 

1.1    文件格式

在使用bfd分析文件时,通常会先用bfd_check_format或者bfd_check_format_matches函数判断文件的类型,使用它们可以将文件分为4类:

/* File formats.  */

 

typedef enum bfd_format

{

  bfd_unknown = 0, /* File format is unknown.  */

  bfd_object,      /* Linker/assembler/compiler output.  */

  bfd_archive,         /* Object archive file.  */

  bfd_core,        /* Core dump.  */

  bfd_type_end         /* Marks the end; don't use it!  */

}

bfd_format;

object为单个的目标文件,如.o.obj之类的,archive则是目标文件的集合,如.a或者.lib文件,core则是dump生成的文件。

1.2    格式检查

先看bfd_check_format函数:

 

/*

FUNCTION

     bfd_check_format

 

SYNOPSIS

     bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);

 

DESCRIPTION

     Verify if the file attached to the BFD @var{abfd} is compatible

     with the format @var{format} (i.e., one of <<bfd_object>>,

     <<bfd_archive>> or <<bfd_core>>).

 

     If the BFD has been set to a specific target before the

     call, only the named target and format combination is

     checked. If the target has not been set, or has been set to

     <<default>>, then all the known target backends is

     interrogated to determine a match.  If the default target

     matches, it is used.  If not, exactly one target must recognize

     the file, or an error results.

 

     The function returns <<TRUE>> on success, otherwise <<FALSE>>

     with one of the following error codes:

 

     o <<bfd_error_invalid_operation>> -

     if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or

     <<bfd_core>>.

 

     o <<bfd_error_system_call>> -

     if an error occured during a read - even some file mismatches

     can cause bfd_error_system_calls.

 

     o <<file_not_recognised>> -

     none of the backends recognised the file format.

 

     o <<bfd_error_file_ambiguously_recognized>> -

     more than one backend recognised the file format.

*/

 

bfd_boolean

bfd_check_format (bfd *abfd, bfd_format format)

{

  return bfd_check_format_matches (abfd, format, NULL);

}

注释里面已经把函数功能讲得很清楚了,只是没涉及具体实现而已,再看bfd_check_format_matches函数:

 

bfd_boolean

bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)

{

  extern const bfd_target binary_vec;

  const bfd_target * const *target;

  const bfd_target **matching_vector = NULL;

  const bfd_target *save_targ, *right_targ, *ar_right_targ;

  int match_count;

  int ar_match_index;

// 判断传入的参数和当前bfd的状态有没有问题

………………….

 

  /* If the target type was explicitly specified, just check that target.  */

  if (!abfd->target_defaulted)

    {

      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */

     goto err_ret;

 

      right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));

 

      if (right_targ)

     goto ok_ret;

………………….

// 错误处理

    }

// 遍历bfd库支持的所有目标格式

  for (target = bfd_target_vector; *target != NULL; target++)

    {

      const bfd_target *temp;

      bfd_error_type err;

// 进行简单初始化工作

………………………………

 

      temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));

// 判断结果

…………………………

    }

// 错误处理

………………………….

}

它的逻辑其实也挺简单的,如果在openr函数中指定的要使用的target名称,那么这个函数将只检验这个指定的target,否则将遍历bfd支持的所有格式。在这里用到了一个叫BFD_SEND_FMT的宏,它的定义为:

#define BFD_SEND_FMT(bfd, message, arglist) /

  (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)

展开后可以发现,具体的检查工作将由bfd_target:: _bfd_check_format这个回调函数完成,不同的target它们的回调函数也是不同的。看看这个函数指针的定义:

  /* Check the format of a file being read.  Return a <<bfd_target *>> or zero.  */

  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *);

对应于需要检查的4种格式,定义4个不同的回调函数。

对于bfd_elf32_bfin_vec这个目标来说,它将这四个函数分别指向:

 

  /* bfd_check_format: check the format of a file being read */

  { _bfd_dummy_target,      /* unknown format */

    bfd_elf32_object_p,     /* assembler/linker output (object file) */

    bfd_elf32_archive_p,    /* an archive */

    bfd_elf32_core_file_p   /* a core file */

  },

 

1.3    bfd_elf32_bfin_vecarchive格式的检查

bfd_elf32_bfin_vec将对archive格式进行检查的函数指针设置为bfd_elf32_archive_p,但在此定义之前还有一个宏定义:

#ifndef bfd_elf32_archive_p

#define bfd_elf32_archive_p bfd_generic_archive_p

#endif

因此,实际将由bfd_generic_archive_p这个函数来进行格式检查:

 

const bfd_target *

bfd_generic_archive_p (bfd *abfd)

{

  struct artdata *tdata_hold;

  char armag[SARMAG + 1];

  bfd_size_type amt;

 

  if (bfd_bread (armag, SARMAG, abfd) != SARMAG)

    {

      if (bfd_get_error () != bfd_error_system_call)

     bfd_set_error (bfd_error_wrong_format);

      return NULL;

    }

 

  bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);

 

  if (strncmp (armag, ARMAG, SARMAG) != 0

      && strncmp (armag, ARMAGB, SARMAG) != 0

      && ! bfd_is_thin_archive (abfd))

    return 0;

…………………

 

  return abfd->xvec;

}

在这个函数里,首先就是读取SARMAG个字节的文件头标志,在elf/ar.h中定义了可能出现的文件头标志:

 

/* Note that the usual '/n' in magic strings may translate to different

   characters, as allowed by ANSI.  '/012' has a fixed value, and remains

   compatible with existing BSDish archives. */

 

#define ARMAG  "!<arch>/012"     /* For COFF and a.out archives.  */

#define ARMAGB "!<bout>/012"     /* For b.out archives.  */

#define ARMAGT "!<thin>/012"     /* For thin archives.  */

#define SARMAG 8

#define ARFMAG "`/012"

很显然,如果想要让bfd支持vdspdlb文件,这是必须重新定义的第一个函数。

1.4    bfd_elf32_bfin_vecobject格式的检查

bfd_elf32_bfin_vec将这个检查函数设置为bfd_elf32_object_p,但是在bfd的代码中并没有直接给出这个函数的定义,而是在elfcode.h中定义了一个宏:

#define elf_object_p            NAME(bfd_elf,object_p)

NAME则定义为:

#define NAME(x, y) x ## 32 ## _ ## y

于是乎elf_object_p这个名称就变成了bfd_elf32_object_p。在elfcode.h中还定义了这样的函数:

 

/* Check to see if the file associated with ABFD matches the target vector

   that ABFD points to.

 

   Note that we may be called several times with the same ABFD, but different

   target vectors, most of which will not match.  We have to avoid leaving

   any side effects in ABFD, or any data it points to (like tdata), if the

   file does not match the target vector.  */

 

const bfd_target *

elf_object_p (bfd *abfd)

{

……………..

}

这也是实际使用的函数。

 

 

参考资料

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

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

objdumpreadelf的区别( 2008-11-10 )

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

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌云阁主

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

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

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

打赏作者

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

抵扣说明:

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

余额充值