objdump代码分析

 

快乐虾

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

[email protected]

 

本文适用于

bfinutils-2.19

vs2008

 

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

 

Objdump可以用于实现二进制文件的信息读取,其对二进制文件的读取依赖于bfd库,显示的代码实际并不长。

1.1    主程序:main

static char *default_target = NULL;  /* Default at runtime.  */

int

main (int argc, char **argv)

{

  int c;

  char *target = default_target;

  bfd_boolean seenflag = FALSE;

………………………

// bfd库初始化

  bfd_init ();

  set_default_bfd_target ();

……………………..

// 参数提取

  while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW",

                 long_options, (int *) 0))

      != EOF)

{

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

}

// 判断参数是否合法

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

// 显示

  if (formats_info)

    exit_status = display_info ();

  else

    {

      if (optind == argc)

     display_file ("a.out", target);

      else

     for (; optind < argc;)

       display_file (argv[optind++], target);

    }

// 结束工作

  END_PROGRESS (program_name);

 

  return exit_status;

}

整个过程并不复杂,实际工作交由display_file这个函数来完成。

唯一需要注意的是这里将default_target设置为NULL,这样bfd库将读取二进制文件的头信息,查找最适合处理此类文件的target。如果不设置为NULLbfd库将只使用指定的target进行处理,如果指定了与文件实际类型不符合的名称,bfd将无法进行下一步的工作。

1.2    显示所有文件:display_file

 

static void

display_file (char *filename, char *target)

{

  bfd *file;

  bfd *arfile = NULL;

 

  if (get_file_size (filename) < 1)

    {

      exit_status = 1;

      return;

    }

// 打开指定文件,由于targetNULLBFD将指定一个默认的target,并标记为使用默认的target处理。

// 返回一个bfd指针,所有文件操作都由它完成。

  file = bfd_openr (filename, target);

  if (file == NULL)

    {

      nonfatal (filename);

      return;

    }

 

  /* If the file is an archive, process all of its elements.  */

  if (bfd_check_format (file, bfd_archive))

    {

      bfd *last_arfile = NULL;

 

      printf (_("In archive %s:/n"), bfd_get_filename (file));

      for (;;)

     {

       bfd_set_error (bfd_error_no_error);

 

       arfile = bfd_openr_next_archived_file (file, arfile);

       if (arfile == NULL)

         {

           if (bfd_get_error () != bfd_error_no_more_archived_files)

         nonfatal (bfd_get_filename (file));

           break;

         }

 

       display_bfd (arfile);

 

       if (last_arfile != NULL)

         bfd_close (last_arfile);

       last_arfile = arfile;

     }

 

      if (last_arfile != NULL)

     bfd_close (last_arfile);

    }

  else

    display_bfd (file);

 

  bfd_close (file);

}

这段代码先判断是否是静态库文件,如果是则将此静态库文件中的每一个子文件显示出来。由于静态库文件仅仅是将一些单个的目标文件集合在一起(如.o.obj之类的),它并没有改变这些.o或者.obj文件的格式,因此最后使用同一个函数display_bfd进行单个文件的显示。

1.3    单个文件显示:display_bfd

 

static void

display_bfd (bfd *abfd)

{

  char **matching;

 

  if (bfd_check_format_matches (abfd, bfd_object, &matching))

    {

      dump_bfd (abfd);

      return;

    }

// 以下进行错误分析与处理

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

}

转向dump_bfd函数执行。

 

/* Dump selected contents of ABFD.  */

 

static void

dump_bfd (bfd *abfd)

{

  /* If we are adjusting section VMA's, change them all now.  Changing

     the BFD information is a hack.  However, we must do it, or

     bfd_find_nearest_line will not do the right thing.  */

  if (adjust_section_vma != 0)

    {

      bfd_boolean has_reloc = (abfd->flags & HAS_RELOC);

      bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);

    }

 

  if (! dump_debugging_tags)

    printf (_("/n%s:     file format %s/n"), bfd_get_filename (abfd),

         abfd->xvec->name);

  if (dump_ar_hdrs)

    print_arelt_descr (stdout, abfd, TRUE);

  if (dump_file_header)

    dump_bfd_header (abfd);

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

}

根据指定的参数一项项地显示内容,比如dump_bfd_header就是这样的:

ar static void

dump_bfd_header (bfd *abfd)

{

  char *comma = "";

 

  printf (_("architecture: %s, "),

       bfd_printable_arch_mach (bfd_get_arch (abfd),

                      bfd_get_mach (abfd)));

  printf (_("flags 0x%08x:/n"), abfd->flags);

 

#define PF(x, y)    if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}

  PF (HAS_RELOC, "HAS_RELOC");

  PF (EXEC_P, "EXEC_P");

  PF (HAS_LINENO, "HAS_LINENO");

  PF (HAS_DEBUG, "HAS_DEBUG");

  PF (HAS_SYMS, "HAS_SYMS");

  PF (HAS_LOCALS, "HAS_LOCALS");

  PF (DYNAMIC, "DYNAMIC");

  PF (WP_TEXT, "WP_TEXT");

  PF (D_PAGED, "D_PAGED");

  PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");

  PF (HAS_LOAD_PAGE, "HAS_LOAD_PAGE");

  printf (_("/nstart address 0x"));

  bfd_printf_vma (abfd, abfd->start_address);

  printf ("/n");

}

整个主程序的逻辑挺简单的,除了判断是否为静态库文件之外都是顺序执行。

 

 

参考资料

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

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

objdumpreadelf的区别( 2008-11-10 )

 

 

 

你可能感兴趣的:(File,header,null,代码分析,archive,debugging)