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>
* elfcomm.h (HOST_WIDEST_INT): Move to..

View file

@ -25,7 +25,6 @@
#include "bfd.h"
#include "libiberty.h"
#include "filenames.h"
#include "libbfd.h"
#include <time.h> /* ctime, maybe time_t */
#include <assert.h>
@ -36,11 +35,6 @@
typedef long time_t;
#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. */
@ -216,9 +210,6 @@ list_supported_architectures (const char *name, FILE *f)
free (arches);
}
/* The length of the longest architecture name + 1. */
#define LONGEST_ARCH sizeof ("powerpc:common")
static const char *
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
by its endianness and the architectures it supports. */
by its endianness and the architectures it supports. Also build
info about target/archs. */
static int
display_target_list (void)
do_display_target (const bfd_target *targ, void *data)
{
char *dummy_name;
int t;
int ret = 1;
struct display_target *param = (struct display_target *) data;
bfd *abfd;
size_t amt;
dummy_name = make_temp_file (NULL);
for (t = 0; bfd_target_vector[t]; t++)
param->count += 1;
amt = param->count * sizeof (*param->info);
if (param->alloc < amt)
{
const bfd_target *p = bfd_target_vector[t];
bfd *abfd = bfd_openw (dummy_name, p->name);
int a;
size_t size = ((param->count < 64 ? 64 : param->count)
* sizeof (*param->info) * 2);
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,
endian_string (p->header_byteorder),
endian_string (p->byteorder));
printf (_("%s\n (header %s, data %s)\n"), targ->name,
endian_string (targ->header_byteorder),
endian_string (targ->byteorder));
abfd = bfd_openw (param->filename, targ->name);
if (abfd == NULL)
{
bfd_nonfatal (dummy_name);
ret = 0;
continue;
bfd_nonfatal (param->filename);
param->error = 1;
}
if (! bfd_set_format (abfd, bfd_object))
else 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;
}
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;
bfd_nonfatal (targ->name);
param->error = 1;
}
}
if (ok)
{
if (! bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
ok = FALSE;
}
if (ok)
printf ("%s ", p->name);
else
{
int l = strlen (p->name);
while (l--)
putchar ('-');
putchar (' ');
enum bfd_architecture a;
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
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)
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
BFD has been configured to support. */
static int
display_target_tables (void)
static void
display_target_tables (const struct display_target *arg)
{
int t;
int columns;
int ret = 1;
char *colum;
const char *columns;
int width, start_targ, stop_targ;
enum bfd_architecture arch;
int longest_arch = 0;
columns = 0;
colum = getenv ("COLUMNS");
if (colum != NULL)
columns = atoi (colum);
if (columns == 0)
columns = 80;
t = 0;
while (bfd_target_vector[t] != NULL)
for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
{
int oldt = t, wid;
wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
++t;
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;
const char *s = bfd_printable_arch_mach (arch, 0);
int len = strlen (s);
if (len > longest_arch)
longest_arch = len;
}
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
display_info (void)
{
struct display_target arg;
printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
if (! display_target_list () || ! display_target_tables ())
return 1;
else
return 0;
display_target_list (&arg);
if (!arg.error)
display_target_tables (&arg);
return arg.error;
}
/* Display the archive header for an element as if it were an ls -l listing: