#include "config.h"
#include "ansidecl.h"
#include <stdio.h>
#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <time.h>
#include "sim-basics.h"
#include "bfd.h"
#include "sim-utils.h"
#include "gdb/callback.h"
#include "gdb/remote-sim.h"
static void eprintf PARAMS ((host_callback *, const char *, ...));
static void xprintf PARAMS ((host_callback *, const char *, ...));
static void report_transfer_performance
PARAMS ((host_callback *, unsigned long, time_t, time_t));
static void xprintf_bfd_vma PARAMS ((host_callback *, bfd_vma));
bfd *
sim_load_file (sd, myname, callback, prog, prog_bfd, verbose_p, lma_p, do_write)
SIM_DESC sd;
const char *myname;
host_callback *callback;
char *prog;
bfd *prog_bfd;
int verbose_p;
int lma_p;
sim_write_fn do_write;
{
asection *s;
bfd *result_bfd;
time_t start_time = 0;
time_t end_time = 0;
unsigned long data_count = 0;
int found_loadable_section;
if (prog_bfd != NULL)
result_bfd = prog_bfd;
else
{
result_bfd = bfd_openr (prog, 0);
if (result_bfd == NULL)
{
eprintf (callback, "%s: can't open \"%s\": %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
return NULL;
}
}
if (!bfd_check_format (result_bfd, bfd_object))
{
eprintf (callback, "%s: \"%s\" is not an object file: %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
if (prog_bfd == NULL)
bfd_close (result_bfd);
return NULL;
}
if (verbose_p)
start_time = time (NULL);
found_loadable_section = 0;
for (s = result_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
{
bfd_size_type size;
size = bfd_get_section_size_before_reloc (s);
if (size > 0)
{
char *buffer;
bfd_vma lma;
buffer = malloc (size);
if (buffer == NULL)
{
eprintf (callback,
"%s: insufficient memory to load \"%s\"\n",
myname, prog);
if (prog_bfd == NULL)
bfd_close (result_bfd);
return NULL;
}
if (lma_p)
lma = bfd_section_lma (result_bfd, s);
else
lma = bfd_section_vma (result_bfd, s);
if (verbose_p)
{
xprintf (callback, "Loading section %s, size 0x%lx %s ",
bfd_get_section_name (result_bfd, s),
(unsigned long) size,
(lma_p ? "lma" : "vma"));
xprintf_bfd_vma (callback, lma);
xprintf (callback, "\n");
}
data_count += size;
bfd_get_section_contents (result_bfd, s, buffer, 0, size);
do_write (sd, lma, buffer, size);
found_loadable_section = 1;
free (buffer);
}
}
}
if (!found_loadable_section)
{
eprintf (callback,
"%s: no loadable sections \"%s\"\n",
myname, prog);
return NULL;
}
if (verbose_p)
{
end_time = time (NULL);
xprintf (callback, "Start address ");
xprintf_bfd_vma (callback, bfd_get_start_address (result_bfd));
xprintf (callback, "\n");
report_transfer_performance (callback, data_count, start_time, end_time);
}
bfd_cache_close (result_bfd);
return result_bfd;
}
static void
xprintf VPARAMS ((host_callback *callback, const char *fmt, ...))
{
#ifndef ANSI_PROTOTYPES
host_callback *callback;
char *fmt;
#endif
va_list ap;
VA_START (ap, fmt);
#ifndef ANSI_PROTOTYPES
callback = va_arg (ap, host_callback *);
fmt = va_arg (ap, char *);
#endif
(*callback->vprintf_filtered) (callback, fmt, ap);
va_end (ap);
}
static void
eprintf VPARAMS ((host_callback *callback, const char *fmt, ...))
{
#ifndef ANSI_PROTOTYPES
host_callback *callback;
char *fmt;
#endif
va_list ap;
VA_START (ap, fmt);
#ifndef ANSI_PROTOTYPES
callback = va_arg (ap, host_callback *);
fmt = va_arg (ap, char *);
#endif
(*callback->evprintf_filtered) (callback, fmt, ap);
va_end (ap);
}
static void
report_transfer_performance (callback, data_count, start_time, end_time)
host_callback *callback;
unsigned long data_count;
time_t start_time, end_time;
{
xprintf (callback, "Transfer rate: ");
if (end_time != start_time)
xprintf (callback, "%ld bits/sec",
(data_count * 8) / (end_time - start_time));
else
xprintf (callback, "%ld bits in <1 sec", (data_count * 8));
xprintf (callback, ".\n");
}
static void
xprintf_bfd_vma (callback, vma)
host_callback *callback;
bfd_vma vma;
{
xprintf (callback, "0x%lx", (unsigned long) vma);
}