1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
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
;
95 #define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
97 nto_root
= nto_target ();
98 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
, "i386") == 0)
103 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
105 || strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
113 arch
= gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
;
114 endian
= gdbarch_byte_order (target_gdbarch
)
115 == BFD_ENDIAN_BIG
? "be" : "le";
118 /* In case nto_root is short, add strlen(solib)
119 so we can reuse arch_path below. */
121 alloca (strlen (nto_root
) + strlen (arch
) + strlen (endian
) + 2 +
123 sprintf (arch_path
, "%s/%s%s", nto_root
, arch
, endian
);
125 buf
= alloca (strlen (PATH_FMT
) + strlen (arch_path
) * 5 + 1);
126 sprintf (buf
, PATH_FMT
, arch_path
, arch_path
, arch_path
, arch_path
,
129 /* Don't assume basename() isn't destructive. */
130 base
= strrchr (solib
, '/');
134 base
++; /* Skip over '/'. */
136 ret
= openp (buf
, 1, base
, o_flags
, temp_pathname
);
137 if (ret
< 0 && base
!= solib
)
139 sprintf (arch_path
, "/%s", solib
);
140 ret
= open (arch_path
, o_flags
, 0);
144 *temp_pathname
= gdb_realpath (arch_path
);
146 **temp_pathname
= '\0';
153 nto_init_solib_absolute_prefix (void)
155 char buf
[PATH_MAX
* 2], arch_path
[PATH_MAX
];
156 char *nto_root
, *endian
;
159 nto_root
= nto_target ();
160 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
, "i386") == 0)
165 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
167 || strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
175 arch
= gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
;
176 endian
= gdbarch_byte_order (target_gdbarch
)
177 == BFD_ENDIAN_BIG
? "be" : "le";
180 sprintf (arch_path
, "%s/%s%s", nto_root
, arch
, endian
);
182 sprintf (buf
, "set solib-absolute-prefix %s", arch_path
);
183 execute_command (buf
, 0);
187 nto_parse_redirection (char *pargv
[], const char **pin
, const char **pout
,
191 char *in
, *out
, *err
, *p
;
194 for (n
= 0; pargv
[n
]; n
++);
201 argv
= xcalloc (n
+ 1, sizeof argv
[0]);
203 for (i
= 0, n
= 0; n
< argc
; n
++)
222 else if (*p
++ == '2' && *p
++ == '>')
224 if (*p
== '&' && *(p
+ 1) == '1')
232 argv
[i
++] = pargv
[n
];
240 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
241 solib-svr4.c to support nto_relocate_section_addresses
242 which is different from the svr4 version. */
244 /* Link map info to include in an allocated so_list entry */
248 /* Pointer to copy of link map from inferior. The type is char *
249 rather than void *, so that we may use byte offsets to find the
250 various fields without the need for a cast. */
253 /* Amount by which addresses in the binary should be relocated to
254 match the inferior. This could most often be taken directly
255 from lm, but when prelinking is involved and the prelink base
256 address changes, we may need a different offset, we want to
257 warn about the difference and compute it only once. */
260 /* The target location of lm. */
266 LM_ADDR (struct so_list
*so
)
268 if (so
->lm_info
->l_addr
== (CORE_ADDR
)-1)
270 struct link_map_offsets
*lmo
= nto_fetch_link_map_offsets ();
271 struct type
*ptr_type
= builtin_type (target_gdbarch
)->builtin_data_ptr
;
273 so
->lm_info
->l_addr
=
274 extract_typed_address (so
->lm_info
->lm
+ lmo
->l_addr_offset
, ptr_type
);
276 return so
->lm_info
->l_addr
;
280 nto_truncate_ptr (CORE_ADDR addr
)
282 if (gdbarch_ptr_bit (target_gdbarch
) == sizeof (CORE_ADDR
) * 8)
283 /* We don't need to truncate anything, and the bit twiddling below
284 will fail due to overflow problems. */
287 return addr
& (((CORE_ADDR
) 1 << gdbarch_ptr_bit (target_gdbarch
)) - 1);
290 static Elf_Internal_Phdr
*
291 find_load_phdr (bfd
*abfd
)
293 Elf_Internal_Phdr
*phdr
;
296 if (!elf_tdata (abfd
))
299 phdr
= elf_tdata (abfd
)->phdr
;
300 for (i
= 0; i
< elf_elfheader (abfd
)->e_phnum
; i
++, phdr
++)
302 if (phdr
->p_type
== PT_LOAD
&& (phdr
->p_flags
& PF_X
))
309 nto_relocate_section_addresses (struct so_list
*so
, struct target_section
*sec
)
311 /* Neutrino treats the l_addr base address field in link.h as different than
312 the base address in the System V ABI and so the offset needs to be
313 calculated and applied to relocations. */
314 Elf_Internal_Phdr
*phdr
= find_load_phdr (sec
->bfd
);
315 unsigned vaddr
= phdr
? phdr
->p_vaddr
: 0;
317 sec
->addr
= nto_truncate_ptr (sec
->addr
+ LM_ADDR (so
) - vaddr
);
318 sec
->endaddr
= nto_truncate_ptr (sec
->endaddr
+ LM_ADDR (so
) - vaddr
);
321 /* This is cheating a bit because our linker code is in libc.so. If we
322 ever implement lazy linking, this may need to be re-examined. */
324 nto_in_dynsym_resolve_code (CORE_ADDR pc
)
326 if (in_plt_section (pc
, NULL
))
332 nto_dummy_supply_regset (struct regcache
*regcache
, char *regs
)
338 nto_elf_osabi_sniffer (bfd
*abfd
)
340 if (nto_is_nto_target
)
341 return nto_is_nto_target (abfd
);
342 return GDB_OSABI_UNKNOWN
;
345 static const char *nto_thread_state_str
[] =
348 "RUNNING", /* 1 0x01 */
349 "READY", /* 2 0x02 */
350 "STOPPED", /* 3 0x03 */
352 "RECEIVE", /* 5 0x05 */
353 "REPLY", /* 6 0x06 */
354 "STACK", /* 7 0x07 */
355 "WAITTHREAD", /* 8 0x08 */
356 "WAITPAGE", /* 9 0x09 */
357 "SIGSUSPEND", /* 10 0x0a */
358 "SIGWAITINFO", /* 11 0x0b */
359 "NANOSLEEP", /* 12 0x0c */
360 "MUTEX", /* 13 0x0d */
361 "CONDVAR", /* 14 0x0e */
362 "JOIN", /* 15 0x0f */
363 "INTR", /* 16 0x10 */
365 "WAITCTX", /* 18 0x12 */
366 "NET_SEND", /* 19 0x13 */
367 "NET_REPLY" /* 20 0x14 */
371 nto_extra_thread_info (struct thread_info
*ti
)
373 if (ti
&& ti
->private
374 && ti
->private->state
< ARRAY_SIZE (nto_thread_state_str
))
375 return (char *)nto_thread_state_str
[ti
->private->state
];
380 nto_initialize_signals (void)
382 /* We use SIG45 for pulses, or something, so nostop, noprint
384 signal_stop_update (target_signal_from_name ("SIG45"), 0);
385 signal_print_update (target_signal_from_name ("SIG45"), 0);
386 signal_pass_update (target_signal_from_name ("SIG45"), 1);
388 /* By default we don't want to stop on these two, but we do want to pass. */
389 #if defined(SIGSELECT)
390 signal_stop_update (SIGSELECT
, 0);
391 signal_print_update (SIGSELECT
, 0);
392 signal_pass_update (SIGSELECT
, 1);
395 #if defined(SIGPHOTON)
396 signal_stop_update (SIGPHOTON
, 0);
397 signal_print_update (SIGPHOTON
, 0);
398 signal_pass_update (SIGPHOTON
, 1);
402 /* Provide a prototype to silence -Wmissing-prototypes. */
403 extern initialize_file_ftype _initialize_nto_tdep
;
406 _initialize_nto_tdep (void)
408 add_setshow_zinteger_cmd ("nto-debug", class_maintenance
,
409 &nto_internal_debugging
, _("\
410 Set QNX NTO internal debugging."), _("\
411 Show QNX NTO internal debugging."), _("\
412 When non-zero, nto specific debug info is\n\
413 displayed. Different information is displayed\n\
414 for different positive values."),
416 NULL
, /* FIXME: i18n: QNX NTO internal debugging is %s. */
417 &setdebuglist
, &showdebuglist
);