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_generic_supply_gpregset (const struct regset *regset,
332 struct regcache *regcache, int regnum,
333 const void *gregs, size_t len)
338 nto_generic_supply_fpregset (const struct regset *regset,
339 struct regcache *regcache, int regnum,
340 const void *fpregs, size_t len)
345 nto_generic_supply_altregset (const struct regset *regset,
346 struct regcache *regcache, int regnum,
347 const void *altregs, size_t len)
352 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
358 nto_elf_osabi_sniffer (bfd *abfd)
360 if (nto_is_nto_target)
361 return nto_is_nto_target (abfd);
362 return GDB_OSABI_UNKNOWN;
366 nto_initialize_signals (void)
368 /* We use SIG45 for pulses, or something, so nostop, noprint
370 signal_stop_update (target_signal_from_name ("SIG45"), 0);
371 signal_print_update (target_signal_from_name ("SIG45"), 0);
372 signal_pass_update (target_signal_from_name ("SIG45"), 1);
374 /* By default we don't want to stop on these two, but we do want to pass. */
375 #if defined(SIGSELECT)
376 signal_stop_update (SIGSELECT, 0);
377 signal_print_update (SIGSELECT, 0);
378 signal_pass_update (SIGSELECT, 1);
381 #if defined(SIGPHOTON)
382 signal_stop_update (SIGPHOTON, 0);
383 signal_print_update (SIGPHOTON, 0);
384 signal_pass_update (SIGPHOTON, 1);
388 /* Provide a prototype to silence -Wmissing-prototypes. */
389 extern initialize_file_ftype _initialize_nto_tdep;
392 _initialize_nto_tdep (void)
394 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
395 &nto_internal_debugging, _("\
396 Set QNX NTO internal debugging."), _("\
397 Show QNX NTO internal debugging."), _("\
398 When non-zero, nto specific debug info is\n\
399 displayed. Different information is displayed\n\
400 for different positive values."),
402 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
403 &setdebuglist, &showdebuglist);