1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc.
5 Contributed by QNX Software Systems Ltd.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "gdb_string.h"
27 #include "cli/cli-decode.h"
28 #include "cli/cli-cmds.h"
33 #include "solib-svr4.h"
40 #include <sys/cygwin.h>
44 static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
45 #elif defined(__sun__) || defined(linux)
46 static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
48 static char default_nto_target[] = "";
51 struct nto_target_ops current_nto_target;
56 char *p = getenv ("QNX_TARGET");
59 static char buf[PATH_MAX];
61 cygwin_conv_path (CCP_WIN_A_TO_POSIX, p, buf, PATH_MAX);
63 cygwin_conv_path (CCP_WIN_A_TO_POSIX, default_nto_target, buf, PATH_MAX);
66 return p ? p : default_nto_target;
70 /* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
71 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
73 nto_map_arch_to_cputype (const char *arch)
75 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
77 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
79 if (!strcmp (arch, "mips"))
81 if (!strcmp (arch, "arm"))
83 if (!strcmp (arch, "sh"))
85 return CPUTYPE_UNKNOWN;
89 nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
91 char *buf, *arch_path, *nto_root, *endian;
96 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
98 nto_root = nto_target ();
99 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
104 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
106 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
114 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
115 endian = gdbarch_byte_order (target_gdbarch)
116 == BFD_ENDIAN_BIG ? "be" : "le";
119 /* In case nto_root is short, add strlen(solib)
120 so we can reuse arch_path below. */
122 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
124 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
126 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
127 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
130 base = lbasename (solib);
131 ret = openp (buf, 1, base, o_flags, temp_pathname);
132 if (ret < 0 && base != solib)
134 sprintf (arch_path, "/%s", solib);
135 ret = open (arch_path, o_flags, 0);
139 *temp_pathname = gdb_realpath (arch_path);
141 **temp_pathname = '\0';
148 nto_init_solib_absolute_prefix (void)
150 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
151 char *nto_root, *endian;
154 nto_root = nto_target ();
155 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
160 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
162 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
170 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
171 endian = gdbarch_byte_order (target_gdbarch)
172 == BFD_ENDIAN_BIG ? "be" : "le";
175 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
177 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
178 execute_command (buf, 0);
182 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
186 char *in, *out, *err, *p;
189 for (n = 0; pargv[n]; n++);
196 argv = xcalloc (n + 1, sizeof argv[0]);
198 for (i = 0, n = 0; n < argc; n++)
217 else if (*p++ == '2' && *p++ == '>')
219 if (*p == '&' && *(p + 1) == '1')
227 argv[i++] = pargv[n];
235 /* The struct lm_info, lm_addr, and nto_truncate_ptr are copied from
236 solib-svr4.c to support nto_relocate_section_addresses
237 which is different from the svr4 version. */
239 /* Link map info to include in an allocated so_list entry */
243 /* Pointer to copy of link map from inferior. The type is char *
244 rather than void *, so that we may use byte offsets to find the
245 various fields without the need for a cast. */
248 /* Amount by which addresses in the binary should be relocated to
249 match the inferior. This could most often be taken directly
250 from lm, but when prelinking is involved and the prelink base
251 address changes, we may need a different offset, we want to
252 warn about the difference and compute it only once. */
255 /* The target location of lm. */
261 lm_addr (struct so_list *so)
263 if (so->lm_info->l_addr == (CORE_ADDR)-1)
265 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
266 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
268 so->lm_info->l_addr =
269 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
271 return so->lm_info->l_addr;
275 nto_truncate_ptr (CORE_ADDR addr)
277 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
278 /* We don't need to truncate anything, and the bit twiddling below
279 will fail due to overflow problems. */
282 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
285 static Elf_Internal_Phdr *
286 find_load_phdr (bfd *abfd)
288 Elf_Internal_Phdr *phdr;
291 if (!elf_tdata (abfd))
294 phdr = elf_tdata (abfd)->phdr;
295 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
297 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
304 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
306 /* Neutrino treats the l_addr base address field in link.h as different than
307 the base address in the System V ABI and so the offset needs to be
308 calculated and applied to relocations. */
309 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
310 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
312 sec->addr = nto_truncate_ptr (sec->addr + lm_addr (so) - vaddr);
313 sec->endaddr = nto_truncate_ptr (sec->endaddr + lm_addr (so) - vaddr);
316 /* This is cheating a bit because our linker code is in libc.so. If we
317 ever implement lazy linking, this may need to be re-examined. */
319 nto_in_dynsym_resolve_code (CORE_ADDR pc)
321 if (in_plt_section (pc, NULL))
327 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
333 nto_elf_osabi_sniffer (bfd *abfd)
335 if (nto_is_nto_target)
336 return nto_is_nto_target (abfd);
337 return GDB_OSABI_UNKNOWN;
340 static const char *nto_thread_state_str[] =
343 "RUNNING", /* 1 0x01 */
344 "READY", /* 2 0x02 */
345 "STOPPED", /* 3 0x03 */
347 "RECEIVE", /* 5 0x05 */
348 "REPLY", /* 6 0x06 */
349 "STACK", /* 7 0x07 */
350 "WAITTHREAD", /* 8 0x08 */
351 "WAITPAGE", /* 9 0x09 */
352 "SIGSUSPEND", /* 10 0x0a */
353 "SIGWAITINFO", /* 11 0x0b */
354 "NANOSLEEP", /* 12 0x0c */
355 "MUTEX", /* 13 0x0d */
356 "CONDVAR", /* 14 0x0e */
357 "JOIN", /* 15 0x0f */
358 "INTR", /* 16 0x10 */
360 "WAITCTX", /* 18 0x12 */
361 "NET_SEND", /* 19 0x13 */
362 "NET_REPLY" /* 20 0x14 */
366 nto_extra_thread_info (struct thread_info *ti)
368 if (ti && ti->private
369 && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
370 return (char *)nto_thread_state_str [ti->private->state];
375 nto_initialize_signals (void)
377 /* We use SIG45 for pulses, or something, so nostop, noprint
379 signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
380 signal_print_update (gdb_signal_from_name ("SIG45"), 0);
381 signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
383 /* By default we don't want to stop on these two, but we do want to pass. */
384 #if defined(SIGSELECT)
385 signal_stop_update (SIGSELECT, 0);
386 signal_print_update (SIGSELECT, 0);
387 signal_pass_update (SIGSELECT, 1);
390 #if defined(SIGPHOTON)
391 signal_stop_update (SIGPHOTON, 0);
392 signal_print_update (SIGPHOTON, 0);
393 signal_pass_update (SIGPHOTON, 1);
397 /* Provide a prototype to silence -Wmissing-prototypes. */
398 extern initialize_file_ftype _initialize_nto_tdep;
401 _initialize_nto_tdep (void)
403 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
404 &nto_internal_debugging, _("\
405 Set QNX NTO internal debugging."), _("\
406 Show QNX NTO internal debugging."), _("\
407 When non-zero, nto specific debug info is\n\
408 displayed. Different information is displayed\n\
409 for different positive values."),
411 NULL, /* FIXME: i18n: QNX NTO internal
413 &setdebuglist, &showdebuglist);