Don't include libbfd.h outside of bfd, part 5

A rewrite of the code in bucomm.c supporting objdump -i, to use
bfd_iterate_over_targets rather than accessing bfd_target_vector
directly.  Calculates widest arch string rather than using an
out of date constant.  Stashes info from the first display of valid
target/arch combinations for use in second tabular display.

binutils/
	* bucomm.c: Don't include libbfd.h.
	(endian_string, display_target_list): Delete forward declaration.
	(display_info_table, display_target_tables): Likewise.
	(LONGEST_ARCH): Delete.
	(struct display_target): New.
	(do_display_target): New function.
	(display_target_list, display_info): Rewrite functions.
	(display_info_table): Delete.
	(do_info_size, do_info_header, do_info_row): New functions.
This commit is contained in:
Alan Modra 2016-07-16 13:30:41 +09:30
parent 4212b42d79
commit aac502f7d7
2 changed files with 172 additions and 148 deletions

View File

@ -1,3 +1,15 @@
2016-07-16 Alan Modra <amodra@gmail.com>
* bucomm.c: Don't include libbfd.h.
(endian_string, display_target_list): Delete forward declaration.
(display_info_table, display_target_tables): Likewise.
(LONGEST_ARCH): Delete.
(struct display_target): New.
(do_display_target): New function.
(display_target_list, display_info): Rewrite functions.
(display_info_table): Delete.
(do_info_size, do_info_header, do_info_row): New functions.
2016-07-16 Alan Modra <amodra@gmail.com> 2016-07-16 Alan Modra <amodra@gmail.com>
* elfcomm.h (HOST_WIDEST_INT): Move to.. * elfcomm.h (HOST_WIDEST_INT): Move to..

View File

@ -25,7 +25,6 @@
#include "bfd.h" #include "bfd.h"
#include "libiberty.h" #include "libiberty.h"
#include "filenames.h" #include "filenames.h"
#include "libbfd.h"
#include <time.h> /* ctime, maybe time_t */ #include <time.h> /* ctime, maybe time_t */
#include <assert.h> #include <assert.h>
@ -36,11 +35,6 @@
typedef long time_t; typedef long time_t;
#endif #endif
#endif #endif
static const char * endian_string (enum bfd_endian);
static int display_target_list (void);
static int display_info_table (int, int);
static int display_target_tables (void);
/* Error reporting. */ /* Error reporting. */
@ -216,9 +210,6 @@ list_supported_architectures (const char *name, FILE *f)
free (arches); free (arches);
} }
/* The length of the longest architecture name + 1. */
#define LONGEST_ARCH sizeof ("powerpc:common")
static const char * static const char *
endian_string (enum bfd_endian endian) endian_string (enum bfd_endian endian)
{ {
@ -230,184 +221,205 @@ endian_string (enum bfd_endian endian)
} }
} }
/* Data passed to do_display_target and other target iterators. */
struct display_target {
/* Temp file. */
char *filename;
/* Return status. */
int error;
/* Number of targets. */
int count;
/* Size of info in bytes. */
size_t alloc;
/* Per-target info. */
struct {
/* Target name. */
const char *name;
/* Non-zero if target/arch combination supported. */
unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1];
} *info;
};
/* List the targets that BFD is configured to support, each followed /* List the targets that BFD is configured to support, each followed
by its endianness and the architectures it supports. */ by its endianness and the architectures it supports. Also build
info about target/archs. */
static int static int
display_target_list (void) do_display_target (const bfd_target *targ, void *data)
{ {
char *dummy_name; struct display_target *param = (struct display_target *) data;
int t; bfd *abfd;
int ret = 1; size_t amt;
dummy_name = make_temp_file (NULL); param->count += 1;
for (t = 0; bfd_target_vector[t]; t++) amt = param->count * sizeof (*param->info);
if (param->alloc < amt)
{ {
const bfd_target *p = bfd_target_vector[t]; size_t size = ((param->count < 64 ? 64 : param->count)
bfd *abfd = bfd_openw (dummy_name, p->name); * sizeof (*param->info) * 2);
int a; param->info = xrealloc (param->info, size);
memset ((char *) param->info + param->alloc, 0, size - param->alloc);
param->alloc = size;
}
param->info[param->count - 1].name = targ->name;
printf (_("%s\n (header %s, data %s)\n"), p->name, printf (_("%s\n (header %s, data %s)\n"), targ->name,
endian_string (p->header_byteorder), endian_string (targ->header_byteorder),
endian_string (p->byteorder)); endian_string (targ->byteorder));
abfd = bfd_openw (param->filename, targ->name);
if (abfd == NULL) if (abfd == NULL)
{ {
bfd_nonfatal (dummy_name); bfd_nonfatal (param->filename);
ret = 0; param->error = 1;
continue;
} }
else if (!bfd_set_format (abfd, bfd_object))
if (! bfd_set_format (abfd, bfd_object))
{ {
if (bfd_get_error () != bfd_error_invalid_operation) if (bfd_get_error () != bfd_error_invalid_operation)
{ {
bfd_nonfatal (p->name); bfd_nonfatal (targ->name);
ret = 0; param->error = 1;
}
bfd_close_all_done (abfd);
continue;
}
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
printf (" %s\n",
bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
bfd_close_all_done (abfd);
}
unlink (dummy_name);
free (dummy_name);
return ret;
}
/* Print a table showing which architectures are supported for entries
FIRST through LAST-1 of bfd_target_vector (targets across,
architectures down). */
static int
display_info_table (int first, int last)
{
int t;
int ret = 1;
char *dummy_name;
int a;
/* Print heading of target names. */
printf ("\n%*s", (int) LONGEST_ARCH, " ");
for (t = first; t < last && bfd_target_vector[t]; t++)
printf ("%s ", bfd_target_vector[t]->name);
putchar ('\n');
dummy_name = make_temp_file (NULL);
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
if (strcmp (bfd_printable_arch_mach ((enum bfd_architecture) a, 0),
"UNKNOWN!") != 0)
{
printf ("%*s ", (int) LONGEST_ARCH - 1,
bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
for (t = first; t < last && bfd_target_vector[t]; t++)
{
const bfd_target *p = bfd_target_vector[t];
bfd_boolean ok = TRUE;
bfd *abfd = bfd_openw (dummy_name, p->name);
if (abfd == NULL)
{
bfd_nonfatal (p->name);
ret = 0;
ok = FALSE;
}
if (ok)
{
if (! bfd_set_format (abfd, bfd_object))
{
if (bfd_get_error () != bfd_error_invalid_operation)
{
bfd_nonfatal (p->name);
ret = 0;
}
ok = FALSE;
} }
} }
if (ok)
{
if (! bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
ok = FALSE;
}
if (ok)
printf ("%s ", p->name);
else else
{ {
int l = strlen (p->name); enum bfd_architecture a;
while (l--)
putchar ('-'); for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
putchar (' '); if (bfd_set_arch_mach (abfd, a, 0))
{
printf (" %s\n", bfd_printable_arch_mach (a, 0));
param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
}
} }
if (abfd != NULL) if (abfd != NULL)
bfd_close_all_done (abfd); bfd_close_all_done (abfd);
}
putchar ('\n');
}
unlink (dummy_name);
free (dummy_name);
return ret; return param->error;
}
static void
display_target_list (struct display_target *arg)
{
arg->filename = make_temp_file (NULL);
arg->error = 0;
arg->count = 0;
arg->alloc = 0;
arg->info = NULL;
bfd_iterate_over_targets (do_display_target, arg);
unlink (arg->filename);
free (arg->filename);
}
/* Calculate how many targets we can print across the page. */
static int
do_info_size (int targ, int width, const struct display_target *arg)
{
while (targ < arg->count)
{
width -= strlen (arg->info[targ].name) + 1;
if (width < 0)
return targ;
++targ;
}
return targ;
}
/* Print header of target names. */
static void
do_info_header (int targ, int stop_targ, const struct display_target *arg)
{
while (targ != stop_targ)
printf ("%s ", arg->info[targ++].name);
}
/* Print a table row. */
static void
do_info_row (int targ, int stop_targ, enum bfd_architecture a,
const struct display_target *arg)
{
while (targ != stop_targ)
{
if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
fputs (arg->info[targ].name, stdout);
else
{
int l = strlen (arg->info[targ].name);
while (l--)
putchar ('-');
}
++targ;
if (targ != stop_targ)
putchar (' ');
}
} }
/* Print tables of all the target-architecture combinations that /* Print tables of all the target-architecture combinations that
BFD has been configured to support. */ BFD has been configured to support. */
static int static void
display_target_tables (void) display_target_tables (const struct display_target *arg)
{ {
int t; const char *columns;
int columns; int width, start_targ, stop_targ;
int ret = 1; enum bfd_architecture arch;
char *colum; int longest_arch = 0;
columns = 0; for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
colum = getenv ("COLUMNS");
if (colum != NULL)
columns = atoi (colum);
if (columns == 0)
columns = 80;
t = 0;
while (bfd_target_vector[t] != NULL)
{ {
int oldt = t, wid; const char *s = bfd_printable_arch_mach (arch, 0);
int len = strlen (s);
wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; if (len > longest_arch)
++t; longest_arch = len;
while (wid < columns && bfd_target_vector[t] != NULL)
{
int newwid;
newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
if (newwid >= columns)
break;
wid = newwid;
++t;
}
if (! display_info_table (oldt, t))
ret = 0;
} }
return ret; width = 0;
columns = getenv ("COLUMNS");
if (columns != NULL)
width = atoi (columns);
if (width == 0)
width = 80;
for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ)
{
stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg);
printf ("\n%*s", longest_arch + 1, " ");
do_info_header (start_targ, stop_targ, arg);
putchar ('\n');
for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
{
if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0)
{
printf ("%*s ", longest_arch,
bfd_printable_arch_mach (arch, 0));
do_info_row (start_targ, stop_targ, arch, arg);
putchar ('\n');
}
}
}
} }
int int
display_info (void) display_info (void)
{ {
struct display_target arg;
printf (_("BFD header file version %s\n"), BFD_VERSION_STRING); printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
if (! display_target_list () || ! display_target_tables ())
return 1; display_target_list (&arg);
else if (!arg.error)
return 0; display_target_tables (&arg);
return arg.error;
} }
/* Display the archive header for an element as if it were an ls -l listing: /* Display the archive header for an element as if it were an ls -l listing: