aboutsummaryrefslogtreecommitdiff
path: root/gdb/nto-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/nto-tdep.c')
-rw-r--r--gdb/nto-tdep.c521
1 files changed, 0 insertions, 521 deletions
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
deleted file mode 100644
index eeef52db..0000000
--- a/gdb/nto-tdep.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/* nto-tdep.c - general QNX Neutrino target functionality.
-
- Copyright (C) 2003-2024 Free Software Foundation, Inc.
-
- Contributed by QNX Software Systems Ltd.
-
- 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/>. */
-
-#include <sys/stat.h>
-#include "nto-tdep.h"
-#include "extract-store-integer.h"
-#include "top.h"
-#include "inferior.h"
-#include "infrun.h"
-#include "gdbarch.h"
-#include "bfd.h"
-#include "elf-bfd.h"
-#include "solib-svr4.h"
-#include "gdbcore.h"
-#include "objfiles.h"
-#include "source.h"
-#include "gdbsupport/pathstuff.h"
-
-#define QNX_NOTE_NAME "QNX"
-#define QNX_INFO_SECT_NAME "QNX_info"
-
-#ifdef __CYGWIN__
-#include <sys/cygwin.h>
-#endif
-
-#ifdef __CYGWIN__
-static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
-#elif defined(__sun__) || defined(linux)
-static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
-#else
-static char default_nto_target[] = "";
-#endif
-
-struct nto_target_ops current_nto_target;
-
-static const registry<inferior>::key<struct nto_inferior_data>
- nto_inferior_data_reg;
-
-static char *
-nto_target (void)
-{
- char *p = getenv ("QNX_TARGET");
-
-#ifdef __CYGWIN__
- static char buf[PATH_MAX];
- if (p)
- cygwin_conv_path (CCP_WIN_A_TO_POSIX, p, buf, PATH_MAX);
- else
- cygwin_conv_path (CCP_WIN_A_TO_POSIX, default_nto_target, buf, PATH_MAX);
- return buf;
-#else
- return p ? p : default_nto_target;
-#endif
-}
-
-/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
- CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
-int
-nto_map_arch_to_cputype (const char *arch)
-{
- if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
- return CPUTYPE_X86;
- if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
- return CPUTYPE_PPC;
- if (!strcmp (arch, "mips"))
- return CPUTYPE_MIPS;
- if (!strcmp (arch, "arm"))
- return CPUTYPE_ARM;
- if (!strcmp (arch, "sh"))
- return CPUTYPE_SH;
- return CPUTYPE_UNKNOWN;
-}
-
-int
-nto_find_and_open_solib (const char *solib, unsigned o_flags,
- gdb::unique_xmalloc_ptr<char> *temp_pathname)
-{
- char *buf, *arch_path, *nto_root;
- const char *endian;
- const char *base;
- const char *arch;
- int arch_len, len, ret;
-#define PATH_FMT \
- "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
-
- nto_root = nto_target ();
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "i386") == 0)
- {
- arch = "x86";
- endian = "";
- }
- else if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "rs6000") == 0
- || strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "powerpc") == 0)
- {
- arch = "ppc";
- endian = "be";
- }
- else
- {
- arch = gdbarch_bfd_arch_info (gdbarch)->arch_name;
- endian = gdbarch_byte_order (gdbarch)
- == BFD_ENDIAN_BIG ? "be" : "le";
- }
-
- /* In case nto_root is short, add strlen(solib)
- so we can reuse arch_path below. */
-
- arch_len = (strlen (nto_root) + strlen (arch) + strlen (endian) + 2
- + strlen (solib));
- arch_path = (char *) alloca (arch_len);
- xsnprintf (arch_path, arch_len, "%s/%s%s", nto_root, arch, endian);
-
- len = strlen (PATH_FMT) + strlen (arch_path) * 5 + 1;
- buf = (char *) alloca (len);
- xsnprintf (buf, len, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
- arch_path);
-
- base = lbasename (solib);
- ret = openp (buf, OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, base, o_flags,
- temp_pathname);
- if (ret < 0 && base != solib)
- {
- xsnprintf (arch_path, arch_len, "/%s", solib);
- ret = open (arch_path, o_flags, 0);
- if (temp_pathname)
- {
- if (ret >= 0)
- *temp_pathname = gdb_realpath (arch_path);
- else
- temp_pathname->reset (NULL);
- }
- }
- return ret;
-}
-
-void
-nto_init_solib_absolute_prefix (void)
-{
- char buf[PATH_MAX * 2], arch_path[PATH_MAX];
- char *nto_root;
- const char *endian;
- const char *arch;
-
- nto_root = nto_target ();
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "i386") == 0)
- {
- arch = "x86";
- endian = "";
- }
- else if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "rs6000") == 0
- || strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name,
- "powerpc") == 0)
- {
- arch = "ppc";
- endian = "be";
- }
- else
- {
- arch = gdbarch_bfd_arch_info (gdbarch)->arch_name;
- endian = gdbarch_byte_order (gdbarch)
- == BFD_ENDIAN_BIG ? "be" : "le";
- }
-
- xsnprintf (arch_path, sizeof (arch_path), "%s/%s%s", nto_root, arch, endian);
-
- xsnprintf (buf, sizeof (buf), "set solib-absolute-prefix %s", arch_path);
- execute_command (buf, 0);
-}
-
-char **
-nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
- const char **perr)
-{
- char **argv;
- const char *in, *out, *err, *p;
- int argc, i, n;
-
- for (n = 0; pargv[n]; n++);
- if (n == 0)
- return NULL;
- in = "";
- out = "";
- err = "";
-
- argv = XCNEWVEC (char *, n + 1);
- argc = n;
- for (i = 0, n = 0; n < argc; n++)
- {
- p = pargv[n];
- if (*p == '>')
- {
- p++;
- if (*p)
- out = p;
- else
- out = pargv[++n];
- }
- else if (*p == '<')
- {
- p++;
- if (*p)
- in = p;
- else
- in = pargv[++n];
- }
- else if (*p++ == '2' && *p++ == '>')
- {
- if (*p == '&' && *(p + 1) == '1')
- err = out;
- else if (*p)
- err = p;
- else
- err = pargv[++n];
- }
- else
- argv[i++] = pargv[n];
- }
- *pin = in;
- *pout = out;
- *perr = err;
- return argv;
-}
-
-static CORE_ADDR
-lm_addr (const solib &so)
-{
- auto *li = gdb::checked_static_cast<const lm_info_svr4 *> (so.lm_info.get ());
-
- return li->l_addr;
-}
-
-static CORE_ADDR
-nto_truncate_ptr (CORE_ADDR addr)
-{
- gdbarch *gdbarch = current_inferior ()->arch ();
- if (gdbarch_ptr_bit (gdbarch) == sizeof (CORE_ADDR) * 8)
- /* We don't need to truncate anything, and the bit twiddling below
- will fail due to overflow problems. */
- return addr;
- else
- return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (gdbarch)) - 1);
-}
-
-static Elf_Internal_Phdr *
-find_load_phdr (bfd *abfd)
-{
- Elf_Internal_Phdr *phdr;
- unsigned int i;
-
- if (!elf_tdata (abfd))
- return NULL;
-
- phdr = elf_tdata (abfd)->phdr;
- for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
- {
- if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
- return phdr;
- }
- return NULL;
-}
-
-void
-nto_relocate_section_addresses (solib &so, target_section *sec)
-{
- /* Neutrino treats the l_addr base address field in link.h as different than
- the base address in the System V ABI and so the offset needs to be
- calculated and applied to relocations. */
- Elf_Internal_Phdr *phdr = find_load_phdr (sec->the_bfd_section->owner);
- unsigned vaddr = phdr ? phdr->p_vaddr : 0;
-
- sec->addr = nto_truncate_ptr (sec->addr + lm_addr (so) - vaddr);
- sec->endaddr = nto_truncate_ptr (sec->endaddr + lm_addr (so) - vaddr);
-}
-
-/* This is cheating a bit because our linker code is in libc.so. If we
- ever implement lazy linking, this may need to be re-examined. */
-int
-nto_in_dynsym_resolve_code (CORE_ADDR pc)
-{
- if (in_plt_section (pc))
- return 1;
- return 0;
-}
-
-void
-nto_dummy_supply_regset (struct regcache *regcache, char *regs)
-{
- /* Do nothing. */
-}
-
-static void
-nto_sniff_abi_note_section (bfd *abfd, asection *sect, void *obj)
-{
- const char *sectname;
- unsigned int sectsize;
- /* Buffer holding the section contents. */
- char *note;
- unsigned int namelen;
- const char *name;
- const unsigned sizeof_Elf_Nhdr = 12;
-
- sectname = bfd_section_name (sect);
- sectsize = bfd_section_size (sect);
-
- if (sectsize > 128)
- sectsize = 128;
-
- if (sectname != NULL && strstr (sectname, QNX_INFO_SECT_NAME) != NULL)
- *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
- else if (sectname != NULL && strstr (sectname, "note") != NULL
- && sectsize > sizeof_Elf_Nhdr)
- {
- note = XNEWVEC (char, sectsize);
- bfd_get_section_contents (abfd, sect, note, 0, sectsize);
- namelen = (unsigned int) bfd_h_get_32 (abfd, note);
- name = note + sizeof_Elf_Nhdr;
- if (sectsize >= namelen + sizeof_Elf_Nhdr
- && namelen == sizeof (QNX_NOTE_NAME)
- && 0 == strcmp (name, QNX_NOTE_NAME))
- *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
-
- XDELETEVEC (note);
- }
-}
-
-enum gdb_osabi
-nto_elf_osabi_sniffer (bfd *abfd)
-{
- enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
-
- bfd_map_over_sections (abfd,
- nto_sniff_abi_note_section,
- &osabi);
-
- return osabi;
-}
-
-static const char * const nto_thread_state_str[] =
-{
- "DEAD", /* 0 0x00 */
- "RUNNING", /* 1 0x01 */
- "READY", /* 2 0x02 */
- "STOPPED", /* 3 0x03 */
- "SEND", /* 4 0x04 */
- "RECEIVE", /* 5 0x05 */
- "REPLY", /* 6 0x06 */
- "STACK", /* 7 0x07 */
- "WAITTHREAD", /* 8 0x08 */
- "WAITPAGE", /* 9 0x09 */
- "SIGSUSPEND", /* 10 0x0a */
- "SIGWAITINFO", /* 11 0x0b */
- "NANOSLEEP", /* 12 0x0c */
- "MUTEX", /* 13 0x0d */
- "CONDVAR", /* 14 0x0e */
- "JOIN", /* 15 0x0f */
- "INTR", /* 16 0x10 */
- "SEM", /* 17 0x11 */
- "WAITCTX", /* 18 0x12 */
- "NET_SEND", /* 19 0x13 */
- "NET_REPLY" /* 20 0x14 */
-};
-
-const char *
-nto_extra_thread_info (struct target_ops *self, struct thread_info *ti)
-{
- if (ti != NULL && ti->priv != NULL)
- {
- nto_thread_info *priv = get_nto_thread_info (ti);
-
- if (priv->state < ARRAY_SIZE (nto_thread_state_str))
- return nto_thread_state_str [priv->state];
- }
- return "";
-}
-
-void
-nto_initialize_signals (void)
-{
- /* We use SIG45 for pulses, or something, so nostop, noprint
- and pass them. */
- signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
- signal_print_update (gdb_signal_from_name ("SIG45"), 0);
- signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
-
- /* By default we don't want to stop on these two, but we do want to pass. */
-#if defined(SIGSELECT)
- signal_stop_update (SIGSELECT, 0);
- signal_print_update (SIGSELECT, 0);
- signal_pass_update (SIGSELECT, 1);
-#endif
-
-#if defined(SIGPHOTON)
- signal_stop_update (SIGPHOTON, 0);
- signal_print_update (SIGPHOTON, 0);
- signal_pass_update (SIGPHOTON, 1);
-#endif
-}
-
-/* Read AUXV from initial_stack. */
-LONGEST
-nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
- LONGEST len, size_t sizeof_auxv_t)
-{
- gdb_byte targ32[4]; /* For 32 bit target values. */
- gdb_byte targ64[8]; /* For 64 bit target values. */
- CORE_ADDR data_ofs = 0;
- ULONGEST anint;
- LONGEST len_read = 0;
- gdb_byte *buff;
- enum bfd_endian byte_order;
- int ptr_size;
-
- if (sizeof_auxv_t == 16)
- ptr_size = 8;
- else
- ptr_size = 4;
-
- /* Skip over argc, argv and envp... Comment from ldd.c:
-
- The startup frame is set-up so that we have:
- auxv
- NULL
- ...
- envp2
- envp1 <----- void *frame + (argc + 2) * sizeof(char *)
- NULL
- ...
- argv2
- argv1
- argc <------ void * frame
-
- On entry to ldd, frame gives the address of argc on the stack. */
- /* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little
- * endian. So we just read first 4 bytes. */
- if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0)
- return 0;
-
- byte_order = gdbarch_byte_order (current_inferior ()->arch ());
-
- anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order);
-
- /* Size of pointer is assumed to be 4 bytes (32 bit arch.) */
- data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and
- NULL terminating pointer in
- argv. */
-
- /* Now loop over env table: */
- anint = 0;
- while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size)
- == 0)
- {
- if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0)
- anint = 1; /* Keep looping until non-null entry is found. */
- else if (anint)
- break;
- data_ofs += ptr_size;
- }
- initial_stack += data_ofs;
-
- memset (readbuf, 0, len);
- buff = readbuf;
- while (len_read <= len-sizeof_auxv_t)
- {
- if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t)
- == 0)
- {
- /* Both 32 and 64 bit structures have int as the first field. */
- const ULONGEST a_type
- = extract_unsigned_integer (buff, sizeof (targ32), byte_order);
-
- if (a_type == AT_NULL)
- break;
- buff += sizeof_auxv_t;
- len_read += sizeof_auxv_t;
- }
- else
- break;
- }
- return len_read;
-}
-
-/* Return nto_inferior_data for the given INFERIOR. If not yet created,
- construct it. */
-
-struct nto_inferior_data *
-nto_inferior_data (struct inferior *const inferior)
-{
- struct inferior *const inf = inferior ? inferior : current_inferior ();
- struct nto_inferior_data *inf_data;
-
- gdb_assert (inf != NULL);
-
- inf_data = nto_inferior_data_reg.get (inf);
- if (inf_data == NULL)
- inf_data = nto_inferior_data_reg.emplace (inf);
-
- return inf_data;
-}