#include "defs.h"
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include "inferior.h"
#include "symtab.h"
#include "command.h"
#include "gdbcmd.h"
#include "bfd.h"
#include "target.h"
#include "gdbcore.h"
#include "dis-asm.h"
#include "gdb_stat.h"
#include "completer.h"
#include "symfile.h"
#include "objfiles.h"
#include "objc-lang.h"
#include "exceptions.h"
extern void _initialize_core (void);
static void call_extra_exec_file_hooks (char *filename);
typedef void (*hook_type) (char *);
hook_type deprecated_exec_file_display_hook;
static hook_type *exec_file_extra_hooks;
static int exec_file_hook_count = 0;
bfd *core_bfd = NULL;
void
core_file_command (char *args, int from_tty)
{
struct cleanup *cleanups;
char *filename;
char **argv;
dont_repeat ();
if (args == NULL)
{
cleanups = NULL;
filename = NULL;
}
else
{
argv = buildargv (args);
if (argv == NULL)
nomem (0);
cleanups = make_cleanup_freeargv (argv);
if (argv[0] == NULL)
internal_error (__FILE__, __LINE__, "buildargv returned empty vector");
else if (argv[1] != NULL)
error ("more than one core filename was specified");
else
filename = argv[0];
}
core_file_attach (filename, from_tty);
if (cleanups != NULL)
do_cleanups (cleanups);
}
void core_file_attach (char *filename, int from_tty)
{
struct target_ops *t;
t = find_core_target ();
if (t == NULL)
error (_("GDB can't read core files on this machine."));
if (!filename)
(t->to_detach) (filename, from_tty);
else
(t->to_open) (filename, from_tty);
}
static void
call_extra_exec_file_hooks (char *filename)
{
int i;
for (i = 0; i < exec_file_hook_count; i++)
(*exec_file_extra_hooks[i]) (filename);
}
void
specify_exec_file_hook (void (*hook) (char *))
{
hook_type *new_array;
if (deprecated_exec_file_display_hook != NULL)
{
if (exec_file_hook_count == 0)
{
exec_file_extra_hooks = (hook_type *) xmalloc (sizeof (hook_type));
exec_file_extra_hooks[0] = deprecated_exec_file_display_hook;
deprecated_exec_file_display_hook = call_extra_exec_file_hooks;
exec_file_hook_count = 1;
}
exec_file_hook_count++;
new_array =
(hook_type *) xrealloc (exec_file_extra_hooks,
exec_file_hook_count * sizeof (hook_type));
exec_file_extra_hooks = new_array;
exec_file_extra_hooks[exec_file_hook_count - 1] = hook;
}
else
deprecated_exec_file_display_hook = hook;
}
void
close_exec_file (void)
{
#if 0
if (exec_bfd)
bfd_tempclose (exec_bfd);
#endif
}
void
reopen_exec_file (void)
{
#if 0
if (exec_bfd)
bfd_reopen (exec_bfd);
#else
char *filename;
int res;
struct stat st;
long mtime;
if (gdb_quitting)
return;
if (exec_bfd == NULL || strcmp (target_shortname, "exec") != 0)
return;
filename = xstrdup (bfd_get_filename (exec_bfd));
make_cleanup (xfree, filename);
mtime = bfd_get_mtime (exec_bfd);
res = stat (filename, &st);
if (mtime && mtime != st.st_mtime)
{
exec_open (filename, 0);
tell_breakpoints_objfile_changed (NULL);
tell_objc_msgsend_cacher_objfile_changed (NULL);
}
#endif
}
void
validate_files (void)
{
if (exec_bfd && core_bfd)
{
if (!core_file_matches_executable_p (core_bfd, exec_bfd))
warning (_("core file may not match specified executable file."));
else if (bfd_get_mtime (exec_bfd) > bfd_get_mtime (core_bfd))
warning (_("exec file is newer than core file."));
}
}
char *
get_exec_file (int err)
{
if (exec_bfd)
return bfd_get_filename (exec_bfd);
if (!err)
return NULL;
error (_("No executable file specified.\n\
Use the \"file\" or \"exec-file\" command."));
return NULL;
}
void
memory_error (int status, CORE_ADDR memaddr)
{
struct ui_file *tmp_stream = mem_fileopen ();
make_cleanup_ui_file_delete (tmp_stream);
if (status == EIO)
{
fprintf_unfiltered (tmp_stream, "Cannot access memory at address ");
deprecated_print_address_numeric (memaddr, 1, tmp_stream);
}
else
{
fprintf_filtered (tmp_stream, "Error accessing memory address ");
deprecated_print_address_numeric (memaddr, 1, tmp_stream);
fprintf_filtered (tmp_stream, ": %s.",
safe_strerror (status));
}
error_stream (tmp_stream);
}
void
read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
int status;
status = target_read_memory (memaddr, myaddr, len);
if (status != 0)
memory_error (status, memaddr);
}
struct captured_read_memory_integer_arguments
{
CORE_ADDR memaddr;
int len;
int signedp;
union {
LONGEST sresult;
ULONGEST uresult;
} result;
};
static int
do_captured_read_memory_integer (void *data)
{
struct captured_read_memory_integer_arguments *args = (struct captured_read_memory_integer_arguments*) data;
CORE_ADDR memaddr = args->memaddr;
int len = args->len;
if (args->signedp)
args->result.sresult = read_memory_integer (memaddr, len);
else
args->result.uresult = read_memory_unsigned_integer (memaddr, len);
return 1;
}
int
safe_read_memory_integer (CORE_ADDR memaddr, int len, LONGEST *return_value)
{
int status;
struct captured_read_memory_integer_arguments args;
args.memaddr = memaddr;
args.len = len;
args.signedp = 1;
status = catch_errors (do_captured_read_memory_integer, &args,
"", RETURN_MASK_ALL);
if (status)
*return_value = args.result.sresult;
return status;
}
int
safe_read_memory_unsigned_integer (CORE_ADDR memaddr, int len, ULONGEST *return_value)
{
int status;
struct captured_read_memory_integer_arguments args;
args.memaddr = memaddr;
args.len = len;
args.signedp = 0;
status = catch_errors (do_captured_read_memory_integer, &args,
"", RETURN_MASK_ALL);
if (status)
*return_value = args.result.uresult;
return status;
}
LONGEST
read_memory_integer (CORE_ADDR memaddr, int len)
{
char buf[sizeof (LONGEST)];
read_memory (memaddr, buf, len);
return extract_signed_integer (buf, len);
}
ULONGEST
read_memory_unsigned_integer (CORE_ADDR memaddr, int len)
{
char buf[sizeof (ULONGEST)];
read_memory (memaddr, buf, len);
return extract_unsigned_integer (buf, len);
}
void
read_memory_string (CORE_ADDR memaddr, char *buffer, int max_len)
{
char *cp;
int i;
int cnt;
cp = buffer;
while (1)
{
if (cp - buffer >= max_len)
{
buffer[max_len - 1] = '\0';
break;
}
cnt = max_len - (cp - buffer);
if (cnt > 8)
cnt = 8;
read_memory (memaddr + (int) (cp - buffer), cp, cnt);
for (i = 0; i < cnt && *cp; i++, cp++)
;
if (i < cnt && !*cp)
break;
}
}
CORE_ADDR
read_memory_typed_address (CORE_ADDR addr, struct type *type)
{
char *buf = alloca (TYPE_LENGTH (type));
read_memory (addr, buf, TYPE_LENGTH (type));
return extract_typed_address (buf, type);
}
void
write_memory (CORE_ADDR memaddr, const bfd_byte *myaddr, int len)
{
int status;
bfd_byte *bytes = alloca (len);
memcpy (bytes, myaddr, len);
status = target_write_memory (memaddr, bytes, len);
if (status != 0)
memory_error (status, memaddr);
}
void
write_memory_unsigned_integer (CORE_ADDR addr, int len, ULONGEST value)
{
char *buf = alloca (len);
store_unsigned_integer (buf, len, value);
write_memory (addr, buf, len);
}
void
write_memory_signed_integer (CORE_ADDR addr, int len, LONGEST value)
{
char *buf = alloca (len);
store_signed_integer (buf, len, value);
write_memory (addr, buf, len);
}
#if 0
void
generic_search (int len, char *data, char *mask, CORE_ADDR startaddr,
int increment, CORE_ADDR lorange, CORE_ADDR hirange,
CORE_ADDR *addr_found, char *data_found)
{
int i;
CORE_ADDR curaddr = startaddr;
while (curaddr >= lorange && curaddr < hirange)
{
read_memory (curaddr, data_found, len);
for (i = 0; i < len; ++i)
if ((data_found[i] & mask[i]) != data[i])
goto try_again;
*addr_found = curaddr;
return;
try_again:
curaddr += increment;
}
*addr_found = (CORE_ADDR) 0;
return;
}
#endif
char *gnutarget;
static char *gnutarget_string;
static void
show_gnutarget_string (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("The current BFD target is \"%s\".\n"), value);
}
static void set_gnutarget_command (char *, int, struct cmd_list_element *);
static void
set_gnutarget_command (char *ignore, int from_tty, struct cmd_list_element *c)
{
if (strcmp (gnutarget_string, "auto") == 0)
gnutarget = NULL;
else
gnutarget = gnutarget_string;
}
void
set_gnutarget (char *newtarget)
{
if (gnutarget_string != NULL)
xfree (gnutarget_string);
gnutarget_string = savestring (newtarget, strlen (newtarget));
set_gnutarget_command (NULL, 0, NULL);
}
void
_initialize_core (void)
{
struct cmd_list_element *c;
c = add_cmd ("core-file", class_files, core_file_command, _("\
Use FILE as core dump for examining memory and registers.\n\
No arg means have no core file. This command has been superseded by the\n\
`target core' and `detach' commands."), &cmdlist);
set_cmd_completer (c, filename_completer);
add_setshow_string_noescape_cmd ("gnutarget", class_files,
&gnutarget_string, _("(\
Set the current BFD target."), _("\
Show the current BFD target."), _("\
Use `set gnutarget auto' to specify automatic detection."),
set_gnutarget_command,
show_gnutarget_string,
&setlist, &showlist);
if (getenv ("GNUTARGET"))
set_gnutarget (getenv ("GNUTARGET"));
else
set_gnutarget ("auto");
}