1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003-2013 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"
31 #include "solib-svr4.h"
38 #include <sys/cygwin.h>
42 static char default_nto_target
[] = "C:\\QNXsdk\\target\\qnx6";
43 #elif defined(__sun__) || defined(linux)
44 static char default_nto_target
[] = "/opt/QNXsdk/target/qnx6";
46 static char default_nto_target
[] = "";
49 struct nto_target_ops current_nto_target
;
54 char *p
= getenv ("QNX_TARGET");
57 static char buf
[PATH_MAX
];
59 cygwin_conv_path (CCP_WIN_A_TO_POSIX
, p
, buf
, PATH_MAX
);
61 cygwin_conv_path (CCP_WIN_A_TO_POSIX
, default_nto_target
, buf
, PATH_MAX
);
64 return p
? p
: default_nto_target
;
68 /* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
69 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
71 nto_map_arch_to_cputype (const char *arch
)
73 if (!strcmp (arch
, "i386") || !strcmp (arch
, "x86"))
75 if (!strcmp (arch
, "rs6000") || !strcmp (arch
, "powerpc"))
77 if (!strcmp (arch
, "mips"))
79 if (!strcmp (arch
, "arm"))
81 if (!strcmp (arch
, "sh"))
83 return CPUTYPE_UNKNOWN
;
87 nto_find_and_open_solib (char *solib
, unsigned o_flags
, char **temp_pathname
)
89 char *buf
, *arch_path
, *nto_root
, *endian
;
92 int arch_len
, len
, ret
;
94 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
96 nto_root
= nto_target ();
97 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
, "i386") == 0)
102 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
,
104 || strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
,
112 arch
= gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
;
113 endian
= gdbarch_byte_order (target_gdbarch ())
114 == BFD_ENDIAN_BIG
? "be" : "le";
117 /* In case nto_root is short, add strlen(solib)
118 so we can reuse arch_path below. */
120 arch_len
= (strlen (nto_root
) + strlen (arch
) + strlen (endian
) + 2
122 arch_path
= alloca (arch_len
);
123 xsnprintf (arch_path
, arch_len
, "%s/%s%s", nto_root
, arch
, endian
);
125 len
= strlen (PATH_FMT
) + strlen (arch_path
) * 5 + 1;
127 xsnprintf (buf
, len
, PATH_FMT
, arch_path
, arch_path
, arch_path
, arch_path
,
130 base
= lbasename (solib
);
131 ret
= openp (buf
, OPF_TRY_CWD_FIRST
| OPF_RETURN_REALPATH
, base
, o_flags
,
133 if (ret
< 0 && base
!= solib
)
135 xsnprintf (arch_path
, arch_len
, "/%s", solib
);
136 ret
= open (arch_path
, o_flags
, 0);
140 *temp_pathname
= gdb_realpath (arch_path
);
142 *temp_pathname
= NULL
;
149 nto_init_solib_absolute_prefix (void)
151 char buf
[PATH_MAX
* 2], arch_path
[PATH_MAX
];
152 char *nto_root
, *endian
;
155 nto_root
= nto_target ();
156 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
, "i386") == 0)
161 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
,
163 || strcmp (gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
,
171 arch
= gdbarch_bfd_arch_info (target_gdbarch ())->arch_name
;
172 endian
= gdbarch_byte_order (target_gdbarch ())
173 == BFD_ENDIAN_BIG
? "be" : "le";
176 xsnprintf (arch_path
, sizeof (arch_path
), "%s/%s%s", nto_root
, arch
, endian
);
178 xsnprintf (buf
, sizeof (buf
), "set solib-absolute-prefix %s", arch_path
);
179 execute_command (buf
, 0);
183 nto_parse_redirection (char *pargv
[], const char **pin
, const char **pout
,
187 char *in
, *out
, *err
, *p
;
190 for (n
= 0; pargv
[n
]; n
++);
197 argv
= xcalloc (n
+ 1, sizeof argv
[0]);
199 for (i
= 0, n
= 0; n
< argc
; n
++)
218 else if (*p
++ == '2' && *p
++ == '>')
220 if (*p
== '&' && *(p
+ 1) == '1')
228 argv
[i
++] = pargv
[n
];
236 /* The struct lm_info, lm_addr, and nto_truncate_ptr are copied from
237 solib-svr4.c to support nto_relocate_section_addresses
238 which is different from the svr4 version. */
240 /* Link map info to include in an allocated so_list entry */
244 /* Pointer to copy of link map from inferior. The type is char *
245 rather than void *, so that we may use byte offsets to find the
246 various fields without the need for a cast. */
249 /* Amount by which addresses in the binary should be relocated to
250 match the inferior. This could most often be taken directly
251 from lm, but when prelinking is involved and the prelink base
252 address changes, we may need a different offset, we want to
253 warn about the difference and compute it only once. */
256 /* The target location of lm. */
262 lm_addr (struct so_list
*so
)
264 if (so
->lm_info
->l_addr
== (CORE_ADDR
)-1)
266 struct link_map_offsets
*lmo
= nto_fetch_link_map_offsets ();
267 struct type
*ptr_type
= builtin_type (target_gdbarch ())->builtin_data_ptr
;
269 so
->lm_info
->l_addr
=
270 extract_typed_address (so
->lm_info
->lm
+ lmo
->l_addr_offset
, ptr_type
);
272 return so
->lm_info
->l_addr
;
276 nto_truncate_ptr (CORE_ADDR addr
)
278 if (gdbarch_ptr_bit (target_gdbarch ()) == sizeof (CORE_ADDR
) * 8)
279 /* We don't need to truncate anything, and the bit twiddling below
280 will fail due to overflow problems. */
283 return addr
& (((CORE_ADDR
) 1 << gdbarch_ptr_bit (target_gdbarch ())) - 1);
286 static Elf_Internal_Phdr
*
287 find_load_phdr (bfd
*abfd
)
289 Elf_Internal_Phdr
*phdr
;
292 if (!elf_tdata (abfd
))
295 phdr
= elf_tdata (abfd
)->phdr
;
296 for (i
= 0; i
< elf_elfheader (abfd
)->e_phnum
; i
++, phdr
++)
298 if (phdr
->p_type
== PT_LOAD
&& (phdr
->p_flags
& PF_X
))
305 nto_relocate_section_addresses (struct so_list
*so
, struct target_section
*sec
)
307 /* Neutrino treats the l_addr base address field in link.h as different than
308 the base address in the System V ABI and so the offset needs to be
309 calculated and applied to relocations. */
310 Elf_Internal_Phdr
*phdr
= find_load_phdr (sec
->the_bfd_section
->owner
);
311 unsigned vaddr
= phdr
? phdr
->p_vaddr
: 0;
313 sec
->addr
= nto_truncate_ptr (sec
->addr
+ lm_addr (so
) - vaddr
);
314 sec
->endaddr
= nto_truncate_ptr (sec
->endaddr
+ lm_addr (so
) - vaddr
);
317 /* This is cheating a bit because our linker code is in libc.so. If we
318 ever implement lazy linking, this may need to be re-examined. */
320 nto_in_dynsym_resolve_code (CORE_ADDR pc
)
322 if (in_plt_section (pc
))
328 nto_dummy_supply_regset (struct regcache
*regcache
, char *regs
)
334 nto_elf_osabi_sniffer (bfd
*abfd
)
336 if (nto_is_nto_target
)
337 return nto_is_nto_target (abfd
);
338 return GDB_OSABI_UNKNOWN
;
341 static const char *nto_thread_state_str
[] =
344 "RUNNING", /* 1 0x01 */
345 "READY", /* 2 0x02 */
346 "STOPPED", /* 3 0x03 */
348 "RECEIVE", /* 5 0x05 */
349 "REPLY", /* 6 0x06 */
350 "STACK", /* 7 0x07 */
351 "WAITTHREAD", /* 8 0x08 */
352 "WAITPAGE", /* 9 0x09 */
353 "SIGSUSPEND", /* 10 0x0a */
354 "SIGWAITINFO", /* 11 0x0b */
355 "NANOSLEEP", /* 12 0x0c */
356 "MUTEX", /* 13 0x0d */
357 "CONDVAR", /* 14 0x0e */
358 "JOIN", /* 15 0x0f */
359 "INTR", /* 16 0x10 */
361 "WAITCTX", /* 18 0x12 */
362 "NET_SEND", /* 19 0x13 */
363 "NET_REPLY" /* 20 0x14 */
367 nto_extra_thread_info (struct thread_info
*ti
)
369 if (ti
&& ti
->private
370 && ti
->private->state
< ARRAY_SIZE (nto_thread_state_str
))
371 return (char *)nto_thread_state_str
[ti
->private->state
];
376 nto_initialize_signals (void)
378 /* We use SIG45 for pulses, or something, so nostop, noprint
380 signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
381 signal_print_update (gdb_signal_from_name ("SIG45"), 0);
382 signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
384 /* By default we don't want to stop on these two, but we do want to pass. */
385 #if defined(SIGSELECT)
386 signal_stop_update (SIGSELECT
, 0);
387 signal_print_update (SIGSELECT
, 0);
388 signal_pass_update (SIGSELECT
, 1);
391 #if defined(SIGPHOTON)
392 signal_stop_update (SIGPHOTON
, 0);
393 signal_print_update (SIGPHOTON
, 0);
394 signal_pass_update (SIGPHOTON
, 1);