1 /* nto-tdep.c - general QNX Neutrino target functionality.
3 Copyright (C) 2003, 2004, 2007, 2008, 2009 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_to_posix_path (p, buf);
63 cygwin_conv_to_posix_path (default_nto_target, buf);
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, *base;
94 #define PATH_FMT "%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 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
122 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
124 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
125 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
128 /* Don't assume basename() isn't destructive. */
129 base = strrchr (solib, '/');
133 base++; /* Skip over '/'. */
135 ret = openp (buf, 1, base, o_flags, temp_pathname);
136 if (ret < 0 && base != solib)
138 sprintf (arch_path, "/%s", solib);
139 ret = open (arch_path, o_flags, 0);
143 *temp_pathname = gdb_realpath (arch_path);
145 **temp_pathname = '\0';
152 nto_init_solib_absolute_prefix (void)
154 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
155 char *nto_root, *endian;
158 nto_root = nto_target ();
159 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
164 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
166 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
174 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
175 endian = gdbarch_byte_order (target_gdbarch)
176 == BFD_ENDIAN_BIG ? "be" : "le";
179 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
181 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
182 execute_command (buf, 0);
186 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
190 char *in, *out, *err, *p;
193 for (n = 0; pargv[n]; n++);
200 argv = xcalloc (n + 1, sizeof argv[0]);
202 for (i = 0, n = 0; n < argc; n++)
221 else if (*p++ == '2' && *p++ == '>')
223 if (*p == '&' && *(p + 1) == '1')
231 argv[i++] = pargv[n];
239 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
240 solib-svr4.c to support nto_relocate_section_addresses
241 which is different from the svr4 version. */
243 /* Link map info to include in an allocated so_list entry */
247 /* Pointer to copy of link map from inferior. The type is char *
248 rather than void *, so that we may use byte offsets to find the
249 various fields without the need for a cast. */
252 /* Amount by which addresses in the binary should be relocated to
253 match the inferior. This could most often be taken directly
254 from lm, but when prelinking is involved and the prelink base
255 address changes, we may need a different offset, we want to
256 warn about the difference and compute it only once. */
259 /* The target location of lm. */
265 LM_ADDR (struct so_list *so)
267 if (so->lm_info->l_addr == (CORE_ADDR)-1)
269 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
270 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
272 so->lm_info->l_addr =
273 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
275 return so->lm_info->l_addr;
279 nto_truncate_ptr (CORE_ADDR addr)
281 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
282 /* We don't need to truncate anything, and the bit twiddling below
283 will fail due to overflow problems. */
286 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
289 static Elf_Internal_Phdr *
290 find_load_phdr (bfd *abfd)
292 Elf_Internal_Phdr *phdr;
295 if (!elf_tdata (abfd))
298 phdr = elf_tdata (abfd)->phdr;
299 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
301 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
308 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
310 /* Neutrino treats the l_addr base address field in link.h as different than
311 the base address in the System V ABI and so the offset needs to be
312 calculated and applied to relocations. */
313 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
314 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
316 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
317 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
320 /* This is cheating a bit because our linker code is in libc.so. If we
321 ever implement lazy linking, this may need to be re-examined. */
323 nto_in_dynsym_resolve_code (CORE_ADDR pc)
325 if (in_plt_section (pc, NULL))
331 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
337 nto_elf_osabi_sniffer (bfd *abfd)
339 if (nto_is_nto_target)
340 return nto_is_nto_target (abfd);
341 return GDB_OSABI_UNKNOWN;
345 nto_initialize_signals (void)
347 /* We use SIG45 for pulses, or something, so nostop, noprint
349 signal_stop_update (target_signal_from_name ("SIG45"), 0);
350 signal_print_update (target_signal_from_name ("SIG45"), 0);
351 signal_pass_update (target_signal_from_name ("SIG45"), 1);
353 /* By default we don't want to stop on these two, but we do want to pass. */
354 #if defined(SIGSELECT)
355 signal_stop_update (SIGSELECT, 0);
356 signal_print_update (SIGSELECT, 0);
357 signal_pass_update (SIGSELECT, 1);
360 #if defined(SIGPHOTON)
361 signal_stop_update (SIGPHOTON, 0);
362 signal_print_update (SIGPHOTON, 0);
363 signal_pass_update (SIGPHOTON, 1);
367 /* Provide a prototype to silence -Wmissing-prototypes. */
368 extern initialize_file_ftype _initialize_nto_tdep;
371 _initialize_nto_tdep (void)
373 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
374 &nto_internal_debugging, _("\
375 Set QNX NTO internal debugging."), _("\
376 Show QNX NTO internal debugging."), _("\
377 When non-zero, nto specific debug info is\n\
378 displayed. Different information is displayed\n\
379 for different positive values."),
381 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
382 &setdebuglist, &showdebuglist);