77e371c079
This patch starts changing minimal symbols to be independent of the program space. Specifically, it adds a new objfile parameter to MSYMBOL_VALUE_ADDRESS and changes all the code to use it. This is needed so we can change gdb to apply the section offset when a minsym's address is computed, as opposed to baking the offsets into the symbol itself. A few spots still need the unrelocated address. For these, we introduce MSYMBOL_VALUE_RAW_ADDRESS. As a convenience, we also add the new macro BMSYMBOL_VALUE_ADDRESS, which computes the address of a bound minimal symbol. This just does the obvious thing with the fields. Note that this change does not actually enable program space independence. That requires more changes to gdb. However, to ensure that these changes compile properly, this patch does add the needed section lookup code to MSYMBOL_VALUE_ADDRESS -- it just ensures it has no effect at runtime by multiplying the offset by 0. 2014-02-26 Tom Tromey <tromey@redhat.com> * ada-lang.c (ada_main_name): Update. (ada_add_standard_exceptions): Update. * ada-tasks.c (ada_tasks_inferior_data_sniffer): Update. * aix-thread.c (pdc_symbol_addrs, pd_enable): Update. * arm-tdep.c (skip_prologue_function, arm_skip_stub): Update. * auxv.c (ld_so_xfer_auxv): Update. * avr-tdep.c (avr_scan_prologue): Update. * ax-gdb.c (gen_var_ref): Update. * blockframe.c (get_pc_function_start) (find_pc_partial_function_gnu_ifunc): Update. * breakpoint.c (create_overlay_event_breakpoint) (create_longjmp_master_breakpoint) (create_std_terminate_master_breakpoint) (create_exception_master_breakpoint): Update. * bsd-uthread.c (bsd_uthread_lookup_address): Update. * c-valprint.c (c_val_print): Update. * coff-pe-read.c (add_pe_forwarded_sym): Update. * common/agent.c (agent_look_up_symbols): Update. * dbxread.c (find_stab_function_addr, end_psymtab): Update. * dwarf2loc.c (call_site_to_target_addr): Update. * dwarf2read.c (dw2_find_pc_sect_symtab): Update. * elfread.c (elf_gnu_ifunc_record_cache) (elf_gnu_ifunc_resolve_by_got): Update. * findvar.c (default_read_var_value): Update. * frame.c (inside_main_func): Update. * frv-tdep.c (frv_frame_this_id): Update. * glibc-tdep.c (glibc_skip_solib_resolver): Update. * gnu-v3-abi.c (gnuv3_get_typeid, gnuv3_skip_trampoline): Update. * hppa-hpux-tdep.c (hppa64_hpux_search_dummy_call_sequence) (hppa_hpux_find_dummy_bpaddr): Update. * hppa-tdep.c (hppa_symbol_address): Update. * infcmd.c (until_next_command): Update. * jit.c (jit_read_descriptor, jit_breakpoint_re_set_internal): Update. * linespec.c (minsym_found, add_minsym): Update. * linux-nat.c (get_signo): Update. * linux-thread-db.c (inferior_has_bug): Update. * m32c-tdep.c (m32c_return_value) (m32c_m16c_address_to_pointer): Update. * m32r-tdep.c (m32r_frame_this_id): Update. * m68hc11-tdep.c (m68hc11_get_register_info): Update. * machoread.c (macho_resolve_oso_sym_with_minsym): Update. * maint.c (maintenance_translate_address): Update. * minsyms.c (lookup_minimal_symbol_by_pc_name): Update. (frob_address): New function. (lookup_minimal_symbol_by_pc_section_1): Use raw addresses, frob_address. Rename parameter to "pc_in". (compare_minimal_symbols, compact_minimal_symbols): Use raw addresses. (find_solib_trampoline_target, minimal_symbol_upper_bound): Update. * mips-linux-tdep.c (mips_linux_skip_resolver): Update. * mips-tdep.c (mips_skip_pic_trampoline_code): Update. * objc-lang.c (find_objc_msgsend): Update. * objfiles.c (objfile_relocate1): Update. * obsd-tdep.c (obsd_skip_solib_resolver): Update. * p-valprint.c (pascal_val_print): Update. * parse.c (write_exp_msymbol): Update. * ppc-linux-tdep.c (ppc_linux_spe_context_lookup) (ppc_elfv2_skip_entrypoint): Update. * ppc-sysv-tdep.c (convert_code_addr_to_desc_addr): Update. * printcmd.c (build_address_symbolic, msym_info) (address_info): Update. * proc-service.c (ps_pglobal_lookup): Update. * psymtab.c (find_pc_sect_psymtab_closer) (find_pc_sect_psymtab, find_pc_sect_symtab_from_partial): Change msymbol parameter to bound_minimal_symbol. * ravenscar-thread.c (get_running_thread_id): Update. * remote.c (remote_check_symbols): Update. * sh64-tdep.c (sh64_elf_make_msymbol_special): Use raw address. * sol2-tdep.c (sol2_skip_solib_resolver): Update. * solib-dsbt.c (lm_base): Update. * solib-frv.c (lm_base, main_got): Update. * solib-irix.c (locate_base): Update. * solib-som.c (som_solib_create_inferior_hook) (link_map_start): Update. * solib-spu.c (spu_enable_break, ocl_enable_break): Update. * solib-svr4.c (elf_locate_base, enable_break): Update. * spu-tdep.c (spu_get_overlay_table, spu_catch_start) (flush_ea_cache): Update. * stabsread.c (define_symbol, scan_file_globals): Update. * stack.c (find_frame_funname): Update. * symfile-debug.c (debug_qf_expand_symtabs_matching) (debug_qf_find_pc_sect_symtab): Update. * symfile.c (simple_read_overlay_table) (simple_overlay_update): Update. * symfile.h (struct quick_symbol_functions) <find_pc_sect_symtab>: Change type of msymbol to bound_minimal_symbol. * symmisc.c (dump_msymbols): Update. * symtab.c (find_pc_sect_symtab_via_partial) (find_pc_sect_psymtab, find_pc_sect_line, skip_prologue_sal) (search_symbols, print_msymbol_info): Update. * symtab.h (MSYMBOL_VALUE_RAW_ADDRESS): New macro. (MSYMBOL_VALUE_ADDRESS): Redefine. (BMSYMBOL_VALUE_ADDRESS): New macro. * tracepoint.c (scope_info): Update. * tui/tui-disasm.c (tui_find_disassembly_address) (tui_get_begin_asm_address): Update. * valops.c (find_function_in_inferior): Update. * value.c (value_static_field, value_fn_field): Update.
359 lines
8.4 KiB
C
359 lines
8.4 KiB
C
/* Shared utility routines for GDB to interact with agent.
|
|
|
|
Copyright (C) 2009-2014 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifdef GDBSERVER
|
|
#include "server.h"
|
|
#else
|
|
#include "defs.h"
|
|
#include "target.h"
|
|
#include "inferior.h" /* for non_stop */
|
|
#include "objfiles.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include "agent.h"
|
|
#include "filestuff.h"
|
|
|
|
int debug_agent = 0;
|
|
|
|
#ifdef GDBSERVER
|
|
#define DEBUG_AGENT(fmt, args...) \
|
|
if (debug_agent) \
|
|
fprintf (stderr, fmt, ##args);
|
|
#else
|
|
#define DEBUG_AGENT(fmt, args...) \
|
|
if (debug_agent) \
|
|
fprintf_unfiltered (gdb_stdlog, fmt, ##args);
|
|
#endif
|
|
|
|
/* Global flag to determine using agent or not. */
|
|
int use_agent = 0;
|
|
|
|
/* Addresses of in-process agent's symbols both GDB and GDBserver cares
|
|
about. */
|
|
|
|
struct ipa_sym_addresses
|
|
{
|
|
CORE_ADDR addr_helper_thread_id;
|
|
CORE_ADDR addr_cmd_buf;
|
|
CORE_ADDR addr_capability;
|
|
};
|
|
|
|
/* Cache of the helper thread id. FIXME: this global should be made
|
|
per-process. */
|
|
static unsigned int helper_thread_id = 0;
|
|
|
|
static struct
|
|
{
|
|
const char *name;
|
|
int offset;
|
|
int required;
|
|
} symbol_list[] = {
|
|
IPA_SYM(helper_thread_id),
|
|
IPA_SYM(cmd_buf),
|
|
IPA_SYM(capability),
|
|
};
|
|
|
|
static struct ipa_sym_addresses ipa_sym_addrs;
|
|
|
|
static int all_agent_symbols_looked_up = 0;
|
|
|
|
int
|
|
agent_loaded_p (void)
|
|
{
|
|
return all_agent_symbols_looked_up;
|
|
}
|
|
|
|
/* Look up all symbols needed by agent. Return 0 if all the symbols are
|
|
found, return non-zero otherwise. */
|
|
|
|
int
|
|
agent_look_up_symbols (void *arg)
|
|
{
|
|
int i;
|
|
|
|
all_agent_symbols_looked_up = 0;
|
|
|
|
for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
|
|
{
|
|
CORE_ADDR *addrp =
|
|
(CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
|
|
#ifdef GDBSERVER
|
|
|
|
if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
|
|
#else
|
|
struct bound_minimal_symbol sym =
|
|
lookup_minimal_symbol (symbol_list[i].name, NULL,
|
|
(struct objfile *) arg);
|
|
|
|
if (sym.minsym != NULL)
|
|
*addrp = BMSYMBOL_VALUE_ADDRESS (sym);
|
|
else
|
|
#endif
|
|
{
|
|
DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
all_agent_symbols_looked_up = 1;
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int
|
|
agent_get_helper_thread_id (void)
|
|
{
|
|
if (helper_thread_id == 0)
|
|
{
|
|
#ifdef GDBSERVER
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_helper_thread_id,
|
|
(unsigned char *) &helper_thread_id,
|
|
sizeof helper_thread_id))
|
|
#else
|
|
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
|
gdb_byte buf[4];
|
|
|
|
if (target_read_memory (ipa_sym_addrs.addr_helper_thread_id,
|
|
buf, sizeof buf) == 0)
|
|
helper_thread_id = extract_unsigned_integer (buf, sizeof buf,
|
|
byte_order);
|
|
else
|
|
#endif
|
|
{
|
|
warning (_("Error reading helper thread's id in lib"));
|
|
}
|
|
}
|
|
|
|
return helper_thread_id;
|
|
}
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#define SOCK_DIR P_tmpdir
|
|
|
|
#ifndef UNIX_PATH_MAX
|
|
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* Connects to synchronization socket. PID is the pid of inferior, which is
|
|
used to set up the connection socket. */
|
|
|
|
static int
|
|
gdb_connect_sync_socket (int pid)
|
|
{
|
|
#ifdef HAVE_SYS_UN_H
|
|
struct sockaddr_un addr;
|
|
int res, fd;
|
|
char path[UNIX_PATH_MAX];
|
|
|
|
res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
|
|
if (res >= UNIX_PATH_MAX)
|
|
return -1;
|
|
|
|
res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0);
|
|
if (res == -1)
|
|
{
|
|
warning (_("error opening sync socket: %s"), strerror (errno));
|
|
return -1;
|
|
}
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
|
|
if (res >= UNIX_PATH_MAX)
|
|
{
|
|
warning (_("string overflow allocating socket name"));
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
|
|
res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
|
|
if (res == -1)
|
|
{
|
|
warning (_("error connecting sync socket (%s): %s. "
|
|
"Make sure the directory exists and that it is writable."),
|
|
path, strerror (errno));
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
|
|
return fd;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
/* Execute an agent command in the inferior. PID is the value of pid of the
|
|
inferior. CMD is the buffer for command. GDB or GDBserver will store the
|
|
command into it and fetch the return result from CMD. The interaction
|
|
between GDB/GDBserver and the agent is synchronized by a synchronization
|
|
socket. Return zero if success, otherwise return non-zero. */
|
|
|
|
int
|
|
agent_run_command (int pid, const char *cmd, int len)
|
|
{
|
|
int fd;
|
|
int tid = agent_get_helper_thread_id ();
|
|
ptid_t ptid = ptid_build (pid, tid, 0);
|
|
|
|
#ifdef GDBSERVER
|
|
int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
(const unsigned char *) cmd, len);
|
|
#else
|
|
int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
(gdb_byte *) cmd, len);
|
|
#endif
|
|
|
|
if (ret != 0)
|
|
{
|
|
warning (_("unable to write"));
|
|
return -1;
|
|
}
|
|
|
|
DEBUG_AGENT ("agent: resumed helper thread\n");
|
|
|
|
/* Resume helper thread. */
|
|
#ifdef GDBSERVER
|
|
{
|
|
struct thread_resume resume_info;
|
|
|
|
resume_info.thread = ptid;
|
|
resume_info.kind = resume_continue;
|
|
resume_info.sig = GDB_SIGNAL_0;
|
|
(*the_target->resume) (&resume_info, 1);
|
|
}
|
|
#else
|
|
target_resume (ptid, 0, GDB_SIGNAL_0);
|
|
#endif
|
|
|
|
fd = gdb_connect_sync_socket (pid);
|
|
if (fd >= 0)
|
|
{
|
|
char buf[1] = "";
|
|
int ret;
|
|
|
|
DEBUG_AGENT ("agent: signalling helper thread\n");
|
|
|
|
do
|
|
{
|
|
ret = write (fd, buf, 1);
|
|
} while (ret == -1 && errno == EINTR);
|
|
|
|
DEBUG_AGENT ("agent: waiting for helper thread's response\n");
|
|
|
|
do
|
|
{
|
|
ret = read (fd, buf, 1);
|
|
} while (ret == -1 && errno == EINTR);
|
|
|
|
close (fd);
|
|
|
|
DEBUG_AGENT ("agent: helper thread's response received\n");
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
/* Need to read response with the inferior stopped. */
|
|
if (!ptid_equal (ptid, null_ptid))
|
|
{
|
|
struct target_waitstatus status;
|
|
int was_non_stop = non_stop;
|
|
/* Stop thread PTID. */
|
|
DEBUG_AGENT ("agent: stop helper thread\n");
|
|
#ifdef GDBSERVER
|
|
{
|
|
struct thread_resume resume_info;
|
|
|
|
resume_info.thread = ptid;
|
|
resume_info.kind = resume_stop;
|
|
resume_info.sig = GDB_SIGNAL_0;
|
|
(*the_target->resume) (&resume_info, 1);
|
|
}
|
|
|
|
non_stop = 1;
|
|
mywait (ptid, &status, 0, 0);
|
|
#else
|
|
non_stop = 1;
|
|
target_stop (ptid);
|
|
|
|
memset (&status, 0, sizeof (status));
|
|
target_wait (ptid, &status, 0);
|
|
#endif
|
|
non_stop = was_non_stop;
|
|
}
|
|
|
|
if (fd >= 0)
|
|
{
|
|
#ifdef GDBSERVER
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
(unsigned char *) cmd, IPA_CMD_BUF_SIZE))
|
|
#else
|
|
if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
|
|
IPA_CMD_BUF_SIZE))
|
|
#endif
|
|
{
|
|
warning (_("Error reading command response"));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Each bit of it stands for a capability of agent. */
|
|
static unsigned int agent_capability = 0;
|
|
|
|
/* Return true if agent has capability AGENT_CAP, otherwise return false. */
|
|
|
|
int
|
|
agent_capability_check (enum agent_capa agent_capa)
|
|
{
|
|
if (agent_capability == 0)
|
|
{
|
|
#ifdef GDBSERVER
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_capability,
|
|
(unsigned char *) &agent_capability,
|
|
sizeof agent_capability))
|
|
#else
|
|
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
|
gdb_byte buf[4];
|
|
|
|
if (target_read_memory (ipa_sym_addrs.addr_capability,
|
|
buf, sizeof buf) == 0)
|
|
agent_capability = extract_unsigned_integer (buf, sizeof buf,
|
|
byte_order);
|
|
else
|
|
#endif
|
|
warning (_("Error reading capability of agent"));
|
|
}
|
|
return agent_capability & agent_capa;
|
|
}
|
|
|
|
/* Invalidate the cache of agent capability, so we'll read it from inferior
|
|
again. Call it when launches a new program or reconnect to remote stub. */
|
|
|
|
void
|
|
agent_capability_invalidate (void)
|
|
{
|
|
agent_capability = 0;
|
|
}
|