快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
bfinutils-2.19
vs2008
欢迎转载,但请保留作者信息
Objdump可以用于实现二进制文件的信息读取,其对二进制文件的读取依赖于bfd库,显示的代码实际并不长。
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。如果不设置为NULL,bfd库将只使用指定的target进行处理,如果指定了与文件实际类型不符合的名称,bfd将无法进行下一步的工作。
static void
display_file (char *filename, char *target)
{
bfd *file;
bfd *arfile = NULL;
if (get_file_size (filename) < 1)
{
exit_status = 1;
return;
}
// 打开指定文件,由于target为NULL,BFD将指定一个默认的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进行单个文件的显示。
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 )
bfd对elf32格式的支持( 2008-11-7 )
objdump与readelf的区别( 2008-11-10 )