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
;
71 nto_set_target (struct nto_target_ops
*targ
)
73 nto_regset_id
= targ
->regset_id
;
74 nto_supply_gregset
= targ
->supply_gregset
;
75 nto_supply_fpregset
= targ
->supply_fpregset
;
76 nto_supply_altregset
= targ
->supply_altregset
;
77 nto_supply_regset
= targ
->supply_regset
;
78 nto_register_area
= targ
->register_area
;
79 nto_regset_fill
= targ
->regset_fill
;
80 nto_fetch_link_map_offsets
= targ
->fetch_link_map_offsets
;
83 /* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
84 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
86 nto_map_arch_to_cputype (const char *arch
)
88 if (!strcmp (arch
, "i386") || !strcmp (arch
, "x86"))
90 if (!strcmp (arch
, "rs6000") || !strcmp (arch
, "powerpc"))
92 if (!strcmp (arch
, "mips"))
94 if (!strcmp (arch
, "arm"))
96 if (!strcmp (arch
, "sh"))
98 return CPUTYPE_UNKNOWN
;
102 nto_find_and_open_solib (char *solib
, unsigned o_flags
, char **temp_pathname
)
104 char *buf
, *arch_path
, *nto_root
, *endian
, *base
;
107 #define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
109 nto_root
= nto_target ();
110 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
, "i386") == 0)
115 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
117 || strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
125 arch
= gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
;
126 endian
= gdbarch_byte_order (target_gdbarch
)
127 == BFD_ENDIAN_BIG
? "be" : "le";
130 /* In case nto_root is short, add strlen(solib)
131 so we can reuse arch_path below. */
133 alloca (strlen (nto_root
) + strlen (arch
) + strlen (endian
) + 2 +
135 sprintf (arch_path
, "%s/%s%s", nto_root
, arch
, endian
);
137 buf
= alloca (strlen (PATH_FMT
) + strlen (arch_path
) * 5 + 1);
138 sprintf (buf
, PATH_FMT
, arch_path
, arch_path
, arch_path
, arch_path
,
141 /* Don't assume basename() isn't destructive. */
142 base
= strrchr (solib
, '/');
146 base
++; /* Skip over '/'. */
148 ret
= openp (buf
, 1, base
, o_flags
, 0, temp_pathname
);
149 if (ret
< 0 && base
!= solib
)
151 sprintf (arch_path
, "/%s", solib
);
152 ret
= open (arch_path
, o_flags
, 0);
156 *temp_pathname
= gdb_realpath (arch_path
);
158 **temp_pathname
= '\0';
165 nto_init_solib_absolute_prefix (void)
167 char buf
[PATH_MAX
* 2], arch_path
[PATH_MAX
];
168 char *nto_root
, *endian
;
171 nto_root
= nto_target ();
172 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
, "i386") == 0)
177 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
179 || strcmp (gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
,
187 arch
= gdbarch_bfd_arch_info (target_gdbarch
)->arch_name
;
188 endian
= gdbarch_byte_order (target_gdbarch
)
189 == BFD_ENDIAN_BIG
? "be" : "le";
192 sprintf (arch_path
, "%s/%s%s", nto_root
, arch
, endian
);
194 sprintf (buf
, "set solib-absolute-prefix %s", arch_path
);
195 execute_command (buf
, 0);
199 nto_parse_redirection (char *pargv
[], const char **pin
, const char **pout
,
203 char *in
, *out
, *err
, *p
;
206 for (n
= 0; pargv
[n
]; n
++);
213 argv
= xcalloc (n
+ 1, sizeof argv
[0]);
215 for (i
= 0, n
= 0; n
< argc
; n
++)
234 else if (*p
++ == '2' && *p
++ == '>')
236 if (*p
== '&' && *(p
+ 1) == '1')
244 argv
[i
++] = pargv
[n
];
252 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
253 solib-svr4.c to support nto_relocate_section_addresses
254 which is different from the svr4 version. */
256 /* Link map info to include in an allocated so_list entry */
260 /* Pointer to copy of link map from inferior. The type is char *
261 rather than void *, so that we may use byte offsets to find the
262 various fields without the need for a cast. */
265 /* Amount by which addresses in the binary should be relocated to
266 match the inferior. This could most often be taken directly
267 from lm, but when prelinking is involved and the prelink base
268 address changes, we may need a different offset, we want to
269 warn about the difference and compute it only once. */
272 /* The target location of lm. */
278 LM_ADDR (struct so_list
*so
)
280 if (so
->lm_info
->l_addr
== (CORE_ADDR
)-1)
282 struct link_map_offsets
*lmo
= nto_fetch_link_map_offsets ();
283 struct type
*ptr_type
= builtin_type (target_gdbarch
)->builtin_data_ptr
;
285 so
->lm_info
->l_addr
=
286 extract_typed_address (so
->lm_info
->lm
+ lmo
->l_addr_offset
, ptr_type
);
288 return so
->lm_info
->l_addr
;
292 nto_truncate_ptr (CORE_ADDR addr
)
294 if (gdbarch_ptr_bit (target_gdbarch
) == sizeof (CORE_ADDR
) * 8)
295 /* We don't need to truncate anything, and the bit twiddling below
296 will fail due to overflow problems. */
299 return addr
& (((CORE_ADDR
) 1 << gdbarch_ptr_bit (target_gdbarch
)) - 1);
302 static Elf_Internal_Phdr
*
303 find_load_phdr (bfd
*abfd
)
305 Elf_Internal_Phdr
*phdr
;
308 if (!elf_tdata (abfd
))
311 phdr
= elf_tdata (abfd
)->phdr
;
312 for (i
= 0; i
< elf_elfheader (abfd
)->e_phnum
; i
++, phdr
++)
314 if (phdr
->p_type
== PT_LOAD
&& (phdr
->p_flags
& PF_X
))
321 nto_relocate_section_addresses (struct so_list
*so
, struct section_table
*sec
)
323 /* Neutrino treats the l_addr base address field in link.h as different than
324 the base address in the System V ABI and so the offset needs to be
325 calculated and applied to relocations. */
326 Elf_Internal_Phdr
*phdr
= find_load_phdr (sec
->bfd
);
327 unsigned vaddr
= phdr
? phdr
->p_vaddr
: 0;
329 sec
->addr
= nto_truncate_ptr (sec
->addr
+ LM_ADDR (so
) - vaddr
);
330 sec
->endaddr
= nto_truncate_ptr (sec
->endaddr
+ LM_ADDR (so
) - vaddr
);
333 /* This is cheating a bit because our linker code is in libc.so. If we
334 ever implement lazy linking, this may need to be re-examined. */
336 nto_in_dynsym_resolve_code (CORE_ADDR pc
)
338 if (in_plt_section (pc
, NULL
))
344 nto_generic_supply_gpregset (const struct regset
*regset
,
345 struct regcache
*regcache
, int regnum
,
346 const void *gregs
, size_t len
)
351 nto_generic_supply_fpregset (const struct regset
*regset
,
352 struct regcache
*regcache
, int regnum
,
353 const void *fpregs
, size_t len
)
358 nto_generic_supply_altregset (const struct regset
*regset
,
359 struct regcache
*regcache
, int regnum
,
360 const void *altregs
, size_t len
)
365 nto_dummy_supply_regset (struct regcache
*regcache
, char *regs
)
371 nto_elf_osabi_sniffer (bfd
*abfd
)
373 if (nto_is_nto_target
)
374 return nto_is_nto_target (abfd
);
375 return GDB_OSABI_UNKNOWN
;
379 nto_initialize_signals (void)
381 /* We use SIG45 for pulses, or something, so nostop, noprint
383 signal_stop_update (target_signal_from_name ("SIG45"), 0);
384 signal_print_update (target_signal_from_name ("SIG45"), 0);
385 signal_pass_update (target_signal_from_name ("SIG45"), 1);
387 /* By default we don't want to stop on these two, but we do want to pass. */
388 #if defined(SIGSELECT)
389 signal_stop_update (SIGSELECT
, 0);
390 signal_print_update (SIGSELECT
, 0);
391 signal_pass_update (SIGSELECT
, 1);
394 #if defined(SIGPHOTON)
395 signal_stop_update (SIGPHOTON
, 0);
396 signal_print_update (SIGPHOTON
, 0);
397 signal_pass_update (SIGPHOTON
, 1);
401 /* Provide a prototype to silence -Wmissing-prototypes. */
402 extern initialize_file_ftype _initialize_nto_tdep
;
405 _initialize_nto_tdep (void)
407 add_setshow_zinteger_cmd ("nto-debug", class_maintenance
,
408 &nto_internal_debugging
, _("\
409 Set QNX NTO internal debugging."), _("\
410 Show QNX NTO internal debugging."), _("\
411 When non-zero, nto specific debug info is\n\
412 displayed. Different information is displayed\n\
413 for different positive values."),
415 NULL
, /* FIXME: i18n: QNX NTO internal debugging is %s. */
416 &setdebuglist
, &showdebuglist
);