]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/nto-tdep.c
* config/tc-arm.c (v7m_psrs): Revert previous delta.
[thirdparty/binutils-gdb.git] / gdb / nto-tdep.c
CommitLineData
1b883d35
KW
1/* nto-tdep.c - general QNX Neutrino target functionality.
2
7b6bb8da 3 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
4c38e0a4 4 Free Software Foundation, Inc.
1b883d35
KW
5
6 Contributed by QNX Software Systems Ltd.
7
8 This file is part of GDB.
9
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
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
1b883d35
KW
13 (at your option) any later version.
14
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.
19
20 You should have received a copy of the GNU General Public License
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1b883d35 22
b4d5ed91 23#include "defs.h"
47979a4b 24#include "gdb_stat.h"
1b883d35
KW
25#include "gdb_string.h"
26#include "nto-tdep.h"
27#include "top.h"
28#include "cli/cli-decode.h"
29#include "cli/cli-cmds.h"
30#include "inferior.h"
31#include "gdbarch.h"
32#include "bfd.h"
33#include "elf-bfd.h"
34#include "solib-svr4.h"
35#include "gdbcore.h"
238ae9af
UW
36#include "objfiles.h"
37
38#include <string.h>
1b883d35
KW
39
40#ifdef __CYGWIN__
41#include <sys/cygwin.h>
42#endif
43
44#ifdef __CYGWIN__
45static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
46#elif defined(__sun__) || defined(linux)
47static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
48#else
49static char default_nto_target[] = "";
50#endif
51
52struct nto_target_ops current_nto_target;
53
54static char *
55nto_target (void)
56{
57 char *p = getenv ("QNX_TARGET");
58
59#ifdef __CYGWIN__
60 static char buf[PATH_MAX];
61 if (p)
62 cygwin_conv_to_posix_path (p, buf);
63 else
64 cygwin_conv_to_posix_path (default_nto_target, buf);
65 return buf;
66#else
67 return p ? p : default_nto_target;
68#endif
69}
70
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. */
73int
74nto_map_arch_to_cputype (const char *arch)
75{
76 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
77 return CPUTYPE_X86;
192cdb19 78 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
1b883d35
KW
79 return CPUTYPE_PPC;
80 if (!strcmp (arch, "mips"))
81 return CPUTYPE_MIPS;
82 if (!strcmp (arch, "arm"))
83 return CPUTYPE_ARM;
84 if (!strcmp (arch, "sh"))
85 return CPUTYPE_SH;
86 return CPUTYPE_UNKNOWN;
87}
88
89int
90nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
91{
91495617
PA
92 char *buf, *arch_path, *nto_root, *endian;
93 const char *base;
1b883d35 94 const char *arch;
d737fd7f 95 int ret;
0df8b418
MS
96#define PATH_FMT \
97 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
1b883d35
KW
98
99 nto_root = nto_target ();
1cf3db46 100 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
101 {
102 arch = "x86";
103 endian = "";
104 }
1cf3db46 105 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 106 "rs6000") == 0
1cf3db46 107 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 108 "powerpc") == 0)
1b883d35
KW
109 {
110 arch = "ppc";
111 endian = "be";
112 }
113 else
114 {
1cf3db46
UW
115 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
116 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 117 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
118 }
119
d737fd7f
KW
120 /* In case nto_root is short, add strlen(solib)
121 so we can reuse arch_path below. */
122 arch_path =
123 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
124 strlen (solib));
1b883d35
KW
125 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
126
d737fd7f
KW
127 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
128 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
1b883d35
KW
129 arch_path);
130
9f37bbcc 131 base = lbasename (solib);
fbdebf46 132 ret = openp (buf, 1, base, o_flags, temp_pathname);
d737fd7f
KW
133 if (ret < 0 && base != solib)
134 {
135 sprintf (arch_path, "/%s", solib);
136 ret = open (arch_path, o_flags, 0);
137 if (temp_pathname)
138 {
139 if (ret >= 0)
140 *temp_pathname = gdb_realpath (arch_path);
141 else
142 **temp_pathname = '\0';
143 }
144 }
145 return ret;
1b883d35
KW
146}
147
148void
149nto_init_solib_absolute_prefix (void)
150{
151 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
152 char *nto_root, *endian;
153 const char *arch;
154
155 nto_root = nto_target ();
1cf3db46 156 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
157 {
158 arch = "x86";
159 endian = "";
160 }
1cf3db46 161 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 162 "rs6000") == 0
1cf3db46 163 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 164 "powerpc") == 0)
1b883d35
KW
165 {
166 arch = "ppc";
167 endian = "be";
168 }
169 else
170 {
1cf3db46
UW
171 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
172 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 173 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
174 }
175
176 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
177
178 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
179 execute_command (buf, 0);
180}
181
182char **
14ef7606
AR
183nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
184 const char **perr)
1b883d35
KW
185{
186 char **argv;
187 char *in, *out, *err, *p;
188 int argc, i, n;
189
190 for (n = 0; pargv[n]; n++);
191 if (n == 0)
192 return NULL;
193 in = "";
194 out = "";
195 err = "";
196
197 argv = xcalloc (n + 1, sizeof argv[0]);
198 argc = n;
199 for (i = 0, n = 0; n < argc; n++)
200 {
201 p = pargv[n];
202 if (*p == '>')
203 {
204 p++;
205 if (*p)
206 out = p;
207 else
208 out = pargv[++n];
209 }
210 else if (*p == '<')
211 {
212 p++;
213 if (*p)
214 in = p;
215 else
216 in = pargv[++n];
217 }
218 else if (*p++ == '2' && *p++ == '>')
219 {
220 if (*p == '&' && *(p + 1) == '1')
221 err = out;
222 else if (*p)
223 err = p;
224 else
225 err = pargv[++n];
226 }
227 else
228 argv[i++] = pargv[n];
229 }
230 *pin = in;
231 *pout = out;
232 *perr = err;
233 return argv;
234}
235
236/* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
237 solib-svr4.c to support nto_relocate_section_addresses
238 which is different from the svr4 version. */
239
ebd67d87
AR
240/* Link map info to include in an allocated so_list entry */
241
1b883d35 242struct lm_info
ebd67d87
AR
243 {
244 /* Pointer to copy of link map from inferior. The type is char *
245 rather than void *, so that we may use byte offsets to find the
246 various fields without the need for a cast. */
247 gdb_byte *lm;
248
249 /* Amount by which addresses in the binary should be relocated to
250 match the inferior. This could most often be taken directly
251 from lm, but when prelinking is involved and the prelink base
252 address changes, we may need a different offset, we want to
253 warn about the difference and compute it only once. */
254 CORE_ADDR l_addr;
255
256 /* The target location of lm. */
257 CORE_ADDR lm_addr;
258 };
259
1b883d35
KW
260
261static CORE_ADDR
262LM_ADDR (struct so_list *so)
263{
ebd67d87
AR
264 if (so->lm_info->l_addr == (CORE_ADDR)-1)
265 {
266 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
b6da22b0 267 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
1b883d35 268
ebd67d87 269 so->lm_info->l_addr =
b6da22b0 270 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
ebd67d87
AR
271 }
272 return so->lm_info->l_addr;
1b883d35
KW
273}
274
275static CORE_ADDR
276nto_truncate_ptr (CORE_ADDR addr)
277{
1cf3db46 278 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
1b883d35
KW
279 /* We don't need to truncate anything, and the bit twiddling below
280 will fail due to overflow problems. */
281 return addr;
282 else
1cf3db46 283 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
1b883d35
KW
284}
285
63807e1d 286static Elf_Internal_Phdr *
1b883d35
KW
287find_load_phdr (bfd *abfd)
288{
289 Elf_Internal_Phdr *phdr;
290 unsigned int i;
291
292 if (!elf_tdata (abfd))
293 return NULL;
294
295 phdr = elf_tdata (abfd)->phdr;
296 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
297 {
298 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
299 return phdr;
300 }
301 return NULL;
302}
303
304void
0542c86d 305nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
1b883d35
KW
306{
307 /* Neutrino treats the l_addr base address field in link.h as different than
308 the base address in the System V ABI and so the offset needs to be
309 calculated and applied to relocations. */
310 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
311 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
312
313 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
314 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
315}
316
d737fd7f
KW
317/* This is cheating a bit because our linker code is in libc.so. If we
318 ever implement lazy linking, this may need to be re-examined. */
319int
320nto_in_dynsym_resolve_code (CORE_ADDR pc)
321{
322 if (in_plt_section (pc, NULL))
323 return 1;
324 return 0;
325}
326
d737fd7f 327void
468e3d51 328nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
329{
330 /* Do nothing. */
331}
332
333enum gdb_osabi
334nto_elf_osabi_sniffer (bfd *abfd)
335{
336 if (nto_is_nto_target)
3d171c85 337 return nto_is_nto_target (abfd);
d737fd7f
KW
338 return GDB_OSABI_UNKNOWN;
339}
340
745a434e
AR
341static const char *nto_thread_state_str[] =
342{
343 "DEAD", /* 0 0x00 */
344 "RUNNING", /* 1 0x01 */
345 "READY", /* 2 0x02 */
346 "STOPPED", /* 3 0x03 */
347 "SEND", /* 4 0x04 */
348 "RECEIVE", /* 5 0x05 */
349 "REPLY", /* 6 0x06 */
350 "STACK", /* 7 0x07 */
351 "WAITTHREAD", /* 8 0x08 */
352 "WAITPAGE", /* 9 0x09 */
353 "SIGSUSPEND", /* 10 0x0a */
354 "SIGWAITINFO", /* 11 0x0b */
355 "NANOSLEEP", /* 12 0x0c */
356 "MUTEX", /* 13 0x0d */
357 "CONDVAR", /* 14 0x0e */
358 "JOIN", /* 15 0x0f */
359 "INTR", /* 16 0x10 */
360 "SEM", /* 17 0x11 */
361 "WAITCTX", /* 18 0x12 */
362 "NET_SEND", /* 19 0x13 */
363 "NET_REPLY" /* 20 0x14 */
364};
365
366char *
367nto_extra_thread_info (struct thread_info *ti)
368{
369 if (ti && ti->private
370 && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
371 return (char *)nto_thread_state_str [ti->private->state];
372 return "";
373}
374
1b883d35 375void
d737fd7f 376nto_initialize_signals (void)
1b883d35 377{
1b883d35
KW
378 /* We use SIG45 for pulses, or something, so nostop, noprint
379 and pass them. */
380 signal_stop_update (target_signal_from_name ("SIG45"), 0);
381 signal_print_update (target_signal_from_name ("SIG45"), 0);
382 signal_pass_update (target_signal_from_name ("SIG45"), 1);
383
384 /* By default we don't want to stop on these two, but we do want to pass. */
385#if defined(SIGSELECT)
386 signal_stop_update (SIGSELECT, 0);
387 signal_print_update (SIGSELECT, 0);
388 signal_pass_update (SIGSELECT, 1);
389#endif
390
391#if defined(SIGPHOTON)
392 signal_stop_update (SIGPHOTON, 0);
393 signal_print_update (SIGPHOTON, 0);
394 signal_pass_update (SIGPHOTON, 1);
395#endif
d737fd7f 396}
1b883d35 397
63807e1d
PA
398/* Provide a prototype to silence -Wmissing-prototypes. */
399extern initialize_file_ftype _initialize_nto_tdep;
400
d737fd7f
KW
401void
402_initialize_nto_tdep (void)
403{
404 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
7915a72c
AC
405 &nto_internal_debugging, _("\
406Set QNX NTO internal debugging."), _("\
407Show QNX NTO internal debugging."), _("\
d737fd7f
KW
408When non-zero, nto specific debug info is\n\
409displayed. Different information is displayed\n\
7915a72c 410for different positive values."),
2c5b56ce 411 NULL,
0df8b418
MS
412 NULL, /* FIXME: i18n: QNX NTO internal
413 debugging is %s. */
2c5b56ce 414 &setdebuglist, &showdebuglist);
1b883d35 415}