1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003-2016 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/>. */
31 #include "solib-svr4.h"
35 #define QNX_NOTE_NAME "QNX"
36 #define QNX_INFO_SECT_NAME "QNX_info"
39 #include <sys/cygwin.h>
43 static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
44 #elif defined(__sun__) || defined(linux)
45 static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
47 static char default_nto_target[] = "";
50 struct nto_target_ops current_nto_target;
52 static const struct inferior_data *nto_inferior_data_reg;
57 char *p = getenv ("QNX_TARGET");
60 static char buf[PATH_MAX];
62 cygwin_conv_path (CCP_WIN_A_TO_POSIX, p, buf, PATH_MAX);
64 cygwin_conv_path (CCP_WIN_A_TO_POSIX, default_nto_target, buf, PATH_MAX);
67 return p ? p : default_nto_target;
71 /* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
72 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
74 nto_map_arch_to_cputype (const char *arch)
76 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
78 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
80 if (!strcmp (arch, "mips"))
82 if (!strcmp (arch, "arm"))
84 if (!strcmp (arch, "sh"))
86 return CPUTYPE_UNKNOWN;
90 nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
92 char *buf, *arch_path, *nto_root;
96 int arch_len, len, ret;
98 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
100 nto_root = nto_target ();
101 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name, "i386") == 0)
106 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name,
108 || strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name,
116 arch = gdbarch_bfd_arch_info (target_gdbarch ())->arch_name;
117 endian = gdbarch_byte_order (target_gdbarch ())
118 == BFD_ENDIAN_BIG ? "be" : "le";
121 /* In case nto_root is short, add strlen(solib)
122 so we can reuse arch_path below. */
124 arch_len = (strlen (nto_root) + strlen (arch) + strlen (endian) + 2
126 arch_path = (char *) alloca (arch_len);
127 xsnprintf (arch_path, arch_len, "%s/%s%s", nto_root, arch, endian);
129 len = strlen (PATH_FMT) + strlen (arch_path) * 5 + 1;
130 buf = (char *) alloca (len);
131 xsnprintf (buf, len, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
134 base = lbasename (solib);
135 ret = openp (buf, OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, base, o_flags,
137 if (ret < 0 && base != solib)
139 xsnprintf (arch_path, arch_len, "/%s", solib);
140 ret = open (arch_path, o_flags, 0);
144 *temp_pathname = gdb_realpath (arch_path);
146 *temp_pathname = NULL;
153 nto_init_solib_absolute_prefix (void)
155 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
160 nto_root = nto_target ();
161 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name, "i386") == 0)
166 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name,
168 || strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name,
176 arch = gdbarch_bfd_arch_info (target_gdbarch ())->arch_name;
177 endian = gdbarch_byte_order (target_gdbarch ())
178 == BFD_ENDIAN_BIG ? "be" : "le";
181 xsnprintf (arch_path, sizeof (arch_path), "%s/%s%s", nto_root, arch, endian);
183 xsnprintf (buf, sizeof (buf), "set solib-absolute-prefix %s", arch_path);
184 execute_command (buf, 0);
188 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
192 char *in, *out, *err, *p;
195 for (n = 0; pargv[n]; n++);
202 argv = XCNEWVEC (char *, n + 1);
204 for (i = 0, n = 0; n < argc; n++)
223 else if (*p++ == '2' && *p++ == '>')
225 if (*p == '&' && *(p + 1) == '1')
233 argv[i++] = pargv[n];
241 /* The struct lm_info, lm_addr, and nto_truncate_ptr are copied from
242 solib-svr4.c to support nto_relocate_section_addresses
243 which is different from the svr4 version. */
245 /* Link map info to include in an allocated so_list entry */
249 /* Pointer to copy of link map from inferior. The type is char *
250 rather than void *, so that we may use byte offsets to find the
251 various fields without the need for a cast. */
254 /* Amount by which addresses in the binary should be relocated to
255 match the inferior. This could most often be taken directly
256 from lm, but when prelinking is involved and the prelink base
257 address changes, we may need a different offset, we want to
258 warn about the difference and compute it only once. */
261 /* The target location of lm. */
267 lm_addr (struct so_list *so)
269 if (so->lm_info->l_addr == (CORE_ADDR)-1)
271 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
272 struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
274 so->lm_info->l_addr =
275 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
277 return so->lm_info->l_addr;
281 nto_truncate_ptr (CORE_ADDR addr)
283 if (gdbarch_ptr_bit (target_gdbarch ()) == sizeof (CORE_ADDR) * 8)
284 /* We don't need to truncate anything, and the bit twiddling below
285 will fail due to overflow problems. */
288 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch ())) - 1);
291 static Elf_Internal_Phdr *
292 find_load_phdr (bfd *abfd)
294 Elf_Internal_Phdr *phdr;
297 if (!elf_tdata (abfd))
300 phdr = elf_tdata (abfd)->phdr;
301 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
303 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
310 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
312 /* Neutrino treats the l_addr base address field in link.h as different than
313 the base address in the System V ABI and so the offset needs to be
314 calculated and applied to relocations. */
315 Elf_Internal_Phdr *phdr = find_load_phdr (sec->the_bfd_section->owner);
316 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
318 sec->addr = nto_truncate_ptr (sec->addr + lm_addr (so) - vaddr);
319 sec->endaddr = nto_truncate_ptr (sec->endaddr + lm_addr (so) - vaddr);
322 /* This is cheating a bit because our linker code is in libc.so. If we
323 ever implement lazy linking, this may need to be re-examined. */
325 nto_in_dynsym_resolve_code (CORE_ADDR pc)
327 if (in_plt_section (pc))
333 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
339 nto_sniff_abi_note_section (bfd *abfd, asection *sect, void *obj)
341 const char *sectname;
342 unsigned int sectsize;
343 /* Buffer holding the section contents. */
345 unsigned int namelen;
347 const unsigned sizeof_Elf_Nhdr = 12;
349 sectname = bfd_get_section_name (abfd, sect);
350 sectsize = bfd_section_size (abfd, sect);
355 if (sectname != NULL && strstr (sectname, QNX_INFO_SECT_NAME) != NULL)
356 *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
357 else if (sectname != NULL && strstr (sectname, "note") != NULL
358 && sectsize > sizeof_Elf_Nhdr)
360 note = XNEWVEC (char, sectsize);
361 bfd_get_section_contents (abfd, sect, note, 0, sectsize);
362 namelen = (unsigned int) bfd_h_get_32 (abfd, note);
363 name = note + sizeof_Elf_Nhdr;
364 if (sectsize >= namelen + sizeof_Elf_Nhdr
365 && namelen == sizeof (QNX_NOTE_NAME)
366 && 0 == strcmp (name, QNX_NOTE_NAME))
367 *(enum gdb_osabi *) obj = GDB_OSABI_QNXNTO;
374 nto_elf_osabi_sniffer (bfd *abfd)
376 enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
378 bfd_map_over_sections (abfd,
379 nto_sniff_abi_note_section,
385 static const char *nto_thread_state_str[] =
388 "RUNNING", /* 1 0x01 */
389 "READY", /* 2 0x02 */
390 "STOPPED", /* 3 0x03 */
392 "RECEIVE", /* 5 0x05 */
393 "REPLY", /* 6 0x06 */
394 "STACK", /* 7 0x07 */
395 "WAITTHREAD", /* 8 0x08 */
396 "WAITPAGE", /* 9 0x09 */
397 "SIGSUSPEND", /* 10 0x0a */
398 "SIGWAITINFO", /* 11 0x0b */
399 "NANOSLEEP", /* 12 0x0c */
400 "MUTEX", /* 13 0x0d */
401 "CONDVAR", /* 14 0x0e */
402 "JOIN", /* 15 0x0f */
403 "INTR", /* 16 0x10 */
405 "WAITCTX", /* 18 0x12 */
406 "NET_SEND", /* 19 0x13 */
407 "NET_REPLY" /* 20 0x14 */
411 nto_extra_thread_info (struct target_ops *self, struct thread_info *ti)
414 && ti->priv->state < ARRAY_SIZE (nto_thread_state_str))
415 return (char *)nto_thread_state_str [ti->priv->state];
420 nto_initialize_signals (void)
422 /* We use SIG45 for pulses, or something, so nostop, noprint
424 signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
425 signal_print_update (gdb_signal_from_name ("SIG45"), 0);
426 signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
428 /* By default we don't want to stop on these two, but we do want to pass. */
429 #if defined(SIGSELECT)
430 signal_stop_update (SIGSELECT, 0);
431 signal_print_update (SIGSELECT, 0);
432 signal_pass_update (SIGSELECT, 1);
435 #if defined(SIGPHOTON)
436 signal_stop_update (SIGPHOTON, 0);
437 signal_print_update (SIGPHOTON, 0);
438 signal_pass_update (SIGPHOTON, 1);
442 /* Read AUXV from initial_stack. */
444 nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf,
445 LONGEST len, size_t sizeof_auxv_t)
447 gdb_byte targ32[4]; /* For 32 bit target values. */
448 gdb_byte targ64[8]; /* For 64 bit target values. */
449 CORE_ADDR data_ofs = 0;
451 LONGEST len_read = 0;
453 enum bfd_endian byte_order;
456 if (sizeof_auxv_t == 16)
461 /* Skip over argc, argv and envp... Comment from ldd.c:
463 The startup frame is set-up so that we have:
468 envp1 <----- void *frame + (argc + 2) * sizeof(char *)
473 argc <------ void * frame
475 On entry to ldd, frame gives the address of argc on the stack. */
476 /* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little
477 * endian. So we just read first 4 bytes. */
478 if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0)
481 byte_order = gdbarch_byte_order (target_gdbarch ());
483 anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order);
485 /* Size of pointer is assumed to be 4 bytes (32 bit arch.) */
486 data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and
487 NULL terminating pointer in
490 /* Now loop over env table: */
492 while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size)
495 if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0)
496 anint = 1; /* Keep looping until non-null entry is found. */
499 data_ofs += ptr_size;
501 initial_stack += data_ofs;
503 memset (readbuf, 0, len);
505 while (len_read <= len-sizeof_auxv_t)
507 if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t)
510 /* Both 32 and 64 bit structures have int as the first field. */
511 const ULONGEST a_type
512 = extract_unsigned_integer (buff, sizeof (targ32), byte_order);
514 if (a_type == AT_NULL)
516 buff += sizeof_auxv_t;
517 len_read += sizeof_auxv_t;
525 /* Allocate new nto_inferior_data object. */
527 static struct nto_inferior_data *
528 nto_new_inferior_data (void)
530 struct nto_inferior_data *const inf_data
531 = XCNEW (struct nto_inferior_data);
536 /* Free inferior data. */
539 nto_inferior_data_cleanup (struct inferior *const inf, void *const dat)
544 /* Return nto_inferior_data for the given INFERIOR. If not yet created,
547 struct nto_inferior_data *
548 nto_inferior_data (struct inferior *const inferior)
550 struct inferior *const inf = inferior ? inferior : current_inferior ();
551 struct nto_inferior_data *inf_data;
553 gdb_assert (inf != NULL);
556 = (struct nto_inferior_data *) inferior_data (inf, nto_inferior_data_reg);
557 if (inf_data == NULL)
559 set_inferior_data (inf, nto_inferior_data_reg,
560 (inf_data = nto_new_inferior_data ()));
566 /* Provide a prototype to silence -Wmissing-prototypes. */
567 extern initialize_file_ftype _initialize_nto_tdep;
570 _initialize_nto_tdep (void)
572 nto_inferior_data_reg
573 = register_inferior_data_with_cleanup (NULL, nto_inferior_data_cleanup);