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));
if (abfd == NULL) abfd = bfd_openw (param->filename, targ->name);
if (abfd == NULL)
{
bfd_nonfatal (param->filename);
param->error = 1;
}
else if (!bfd_set_format (abfd, bfd_object))
{
if (bfd_get_error () != bfd_error_invalid_operation)
{ {
bfd_nonfatal (dummy_name); bfd_nonfatal (targ->name);
ret = 0; param->error = 1;
continue;
}
if (! bfd_set_format (abfd, bfd_object))
{
if (bfd_get_error () != bfd_error_invalid_operation)
{
bfd_nonfatal (p->name);
ret = 0;
}
bfd_close_all_done (abfd);
continue;
} }
}
else
{
enum bfd_architecture a;
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) if (bfd_set_arch_mach (abfd, a, 0))
printf (" %s\n", {
bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); printf (" %s\n", bfd_printable_arch_mach (a, 0));
bfd_close_all_done (abfd); param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
}
} }
unlink (dummy_name); if (abfd != NULL)
free (dummy_name); bfd_close_all_done (abfd);
return ret; return param->error;
} }
/* Print a table showing which architectures are supported for entries static void
FIRST through LAST-1 of bfd_target_vector (targets across, display_target_list (struct display_target *arg)
architectures down). */ {
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 static int
display_info_table (int first, int last) do_info_size (int targ, int width, const struct display_target *arg)
{ {
int t; while (targ < arg->count)
int ret = 1; {
char *dummy_name; width -= strlen (arg->info[targ].name) + 1;
int a; if (width < 0)
return targ;
++targ;
}
return targ;
}
/* Print heading of target names. */ /* Print header 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); static void
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) do_info_header (int targ, int stop_targ, const struct display_target *arg)
if (strcmp (bfd_printable_arch_mach ((enum bfd_architecture) a, 0), {
"UNKNOWN!") != 0) while (targ != stop_targ)
{ printf ("%s ", arg->info[targ++].name);
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) /* Print a table row. */
{
bfd_nonfatal (p->name);
ret = 0;
ok = FALSE;
}
if (ok) static void
{ do_info_row (int targ, int stop_targ, enum bfd_architecture a,
if (! bfd_set_format (abfd, bfd_object)) const struct display_target *arg)
{ {
if (bfd_get_error () != bfd_error_invalid_operation) while (targ != stop_targ)
{ {
bfd_nonfatal (p->name); if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
ret = 0; fputs (arg->info[targ].name, stdout);
} else
ok = FALSE; {
} int l = strlen (arg->info[targ].name);
} while (l--)
putchar ('-');
if (ok) }
{ ++targ;
if (! bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) if (targ != stop_targ)
ok = FALSE; putchar (' ');
} }
if (ok)
printf ("%s ", p->name);
else
{
int l = strlen (p->name);
while (l--)
putchar ('-');
putchar (' ');
}
if (abfd != NULL)
bfd_close_all_done (abfd);
}
putchar ('\n');
}
unlink (dummy_name);
free (dummy_name);
return ret;
} }
/* 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: