1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
6 Contributed by QNX Software Systems Ltd.
8 This file is part of GDB.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
25 #include "gdb_string.h"
28 #include "cli/cli-decode.h"
29 #include "cli/cli-cmds.h"
34 #include "solib-svr4.h"
41 #include <sys/cygwin.h>
45 static char default_nto_target
[] = "C:\\QNXsdk\\target\\qnx6";
46 #elif defined(__sun__) || defined(linux)
47 static char default_nto_target
[] = "/opt/QNXsdk/target/qnx6";
49 static char default_nto_target
[] = "";
52 struct nto_target_ops current_nto_target
;
57 char *p
= getenv ("QNX_TARGET");
60 static char buf
[PATH_MAX
];
62 cygwin_conv_to_posix_path (p
, buf
);
64 cygwin_conv_to_posix_path (default_nto_target
, buf
);
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
, *endian
, *base
;
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 /* Don't assume basename() isn't destructive. */
131 base
= strrchr (solib
, '/');
135 base
++; /* Skip over '/'. */
137 ret
= openp (buf
, 1, base
, o_flags
, temp_pathname
);
138 if (ret
< 0 && base
!= solib
)
140 sprintf (arch_path
, "/%s", solib
);
141 ret
= open (arch_path
, o_flags
, 0);
145 *temp_pathname
= gdb_realpath (arch_path
);
147 **temp_pathname
= '\0';
154 nto_init_solib_absolute_prefix (void)
156 char buf
[PATH_MAX
* 2], arch_path
[PATH_MAX
];
157 char *nto_root
, *endian
;
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 sprintf (arch_path
, "%s/%s%s", nto_root
, arch
, endian
);
183 sprintf (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
= xcalloc (n
+ 1, sizeof argv
[0]);
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
->bfd
);
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
, NULL
))
333 nto_dummy_supply_regset (struct regcache
*regcache
, char *regs
)
339 nto_elf_osabi_sniffer (bfd
*abfd
)
341 if (nto_is_nto_target
)
342 return nto_is_nto_target (abfd
);
343 return GDB_OSABI_UNKNOWN
;
346 static const char *nto_thread_state_str
[] =
349 "RUNNING", /* 1 0x01 */
350 "READY", /* 2 0x02 */
351 "STOPPED", /* 3 0x03 */
353 "RECEIVE", /* 5 0x05 */
354 "REPLY", /* 6 0x06 */
355 "STACK", /* 7 0x07 */
356 "WAITTHREAD", /* 8 0x08 */
357 "WAITPAGE", /* 9 0x09 */
358 "SIGSUSPEND", /* 10 0x0a */
359 "SIGWAITINFO", /* 11 0x0b */
360 "NANOSLEEP", /* 12 0x0c */
361 "MUTEX", /* 13 0x0d */
362 "CONDVAR", /* 14 0x0e */
363 "JOIN", /* 15 0x0f */
364 "INTR", /* 16 0x10 */
366 "WAITCTX", /* 18 0x12 */
367 "NET_SEND", /* 19 0x13 */
368 "NET_REPLY" /* 20 0x14 */
372 nto_extra_thread_info (struct thread_info
*ti
)
374 if (ti
&& ti
->private
375 && ti
->private->state
< ARRAY_SIZE (nto_thread_state_str
))
376 return (char *)nto_thread_state_str
[ti
->private->state
];
381 nto_initialize_signals (void)
383 /* We use SIG45 for pulses, or something, so nostop, noprint
385 signal_stop_update (target_signal_from_name ("SIG45"), 0);
386 signal_print_update (target_signal_from_name ("SIG45"), 0);
387 signal_pass_update (target_signal_from_name ("SIG45"), 1);
389 /* By default we don't want to stop on these two, but we do want to pass. */
390 #if defined(SIGSELECT)
391 signal_stop_update (SIGSELECT
, 0);
392 signal_print_update (SIGSELECT
, 0);
393 signal_pass_update (SIGSELECT
, 1);
396 #if defined(SIGPHOTON)
397 signal_stop_update (SIGPHOTON
, 0);
398 signal_print_update (SIGPHOTON
, 0);
399 signal_pass_update (SIGPHOTON
, 1);
403 /* Provide a prototype to silence -Wmissing-prototypes. */
404 extern initialize_file_ftype _initialize_nto_tdep
;
407 _initialize_nto_tdep (void)
409 add_setshow_zinteger_cmd ("nto-debug", class_maintenance
,
410 &nto_internal_debugging
, _("\
411 Set QNX NTO internal debugging."), _("\
412 Show QNX NTO internal debugging."), _("\
413 When non-zero, nto specific debug info is\n\
414 displayed. Different information is displayed\n\
415 for different positive values."),
417 NULL
, /* FIXME: i18n: QNX NTO internal
419 &setdebuglist
, &showdebuglist
);