2011-01-10 Michael Snyder <msnyder@vmware.com>
[deliverable/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{
d737fd7f 92 char *buf, *arch_path, *nto_root, *endian, *base;
1b883d35 93 const char *arch;
d737fd7f
KW
94 int ret;
95#define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
1b883d35
KW
96
97 nto_root = nto_target ();
1cf3db46 98 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
99 {
100 arch = "x86";
101 endian = "";
102 }
1cf3db46 103 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 104 "rs6000") == 0
1cf3db46 105 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 106 "powerpc") == 0)
1b883d35
KW
107 {
108 arch = "ppc";
109 endian = "be";
110 }
111 else
112 {
1cf3db46
UW
113 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
114 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 115 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
116 }
117
d737fd7f
KW
118 /* In case nto_root is short, add strlen(solib)
119 so we can reuse arch_path below. */
120 arch_path =
121 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
122 strlen (solib));
1b883d35
KW
123 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
124
d737fd7f
KW
125 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
126 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
1b883d35
KW
127 arch_path);
128
d737fd7f
KW
129 /* Don't assume basename() isn't destructive. */
130 base = strrchr (solib, '/');
131 if (!base)
132 base = solib;
133 else
134 base++; /* Skip over '/'. */
135
fbdebf46 136 ret = openp (buf, 1, base, o_flags, temp_pathname);
d737fd7f
KW
137 if (ret < 0 && base != solib)
138 {
139 sprintf (arch_path, "/%s", solib);
140 ret = open (arch_path, o_flags, 0);
141 if (temp_pathname)
142 {
143 if (ret >= 0)
144 *temp_pathname = gdb_realpath (arch_path);
145 else
146 **temp_pathname = '\0';
147 }
148 }
149 return ret;
1b883d35
KW
150}
151
152void
153nto_init_solib_absolute_prefix (void)
154{
155 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
156 char *nto_root, *endian;
157 const char *arch;
158
159 nto_root = nto_target ();
1cf3db46 160 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
161 {
162 arch = "x86";
163 endian = "";
164 }
1cf3db46 165 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 166 "rs6000") == 0
1cf3db46 167 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 168 "powerpc") == 0)
1b883d35
KW
169 {
170 arch = "ppc";
171 endian = "be";
172 }
173 else
174 {
1cf3db46
UW
175 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
176 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 177 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
178 }
179
180 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
181
182 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
183 execute_command (buf, 0);
184}
185
186char **
14ef7606
AR
187nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
188 const char **perr)
1b883d35
KW
189{
190 char **argv;
191 char *in, *out, *err, *p;
192 int argc, i, n;
193
194 for (n = 0; pargv[n]; n++);
195 if (n == 0)
196 return NULL;
197 in = "";
198 out = "";
199 err = "";
200
201 argv = xcalloc (n + 1, sizeof argv[0]);
202 argc = n;
203 for (i = 0, n = 0; n < argc; n++)
204 {
205 p = pargv[n];
206 if (*p == '>')
207 {
208 p++;
209 if (*p)
210 out = p;
211 else
212 out = pargv[++n];
213 }
214 else if (*p == '<')
215 {
216 p++;
217 if (*p)
218 in = p;
219 else
220 in = pargv[++n];
221 }
222 else if (*p++ == '2' && *p++ == '>')
223 {
224 if (*p == '&' && *(p + 1) == '1')
225 err = out;
226 else if (*p)
227 err = p;
228 else
229 err = pargv[++n];
230 }
231 else
232 argv[i++] = pargv[n];
233 }
234 *pin = in;
235 *pout = out;
236 *perr = err;
237 return argv;
238}
239
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. */
243
ebd67d87
AR
244/* Link map info to include in an allocated so_list entry */
245
1b883d35 246struct lm_info
ebd67d87
AR
247 {
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. */
251 gdb_byte *lm;
252
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. */
258 CORE_ADDR l_addr;
259
260 /* The target location of lm. */
261 CORE_ADDR lm_addr;
262 };
263
1b883d35
KW
264
265static CORE_ADDR
266LM_ADDR (struct so_list *so)
267{
ebd67d87
AR
268 if (so->lm_info->l_addr == (CORE_ADDR)-1)
269 {
270 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
b6da22b0 271 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
1b883d35 272
ebd67d87 273 so->lm_info->l_addr =
b6da22b0 274 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
ebd67d87
AR
275 }
276 return so->lm_info->l_addr;
1b883d35
KW
277}
278
279static CORE_ADDR
280nto_truncate_ptr (CORE_ADDR addr)
281{
1cf3db46 282 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
1b883d35
KW
283 /* We don't need to truncate anything, and the bit twiddling below
284 will fail due to overflow problems. */
285 return addr;
286 else
1cf3db46 287 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
1b883d35
KW
288}
289
63807e1d 290static Elf_Internal_Phdr *
1b883d35
KW
291find_load_phdr (bfd *abfd)
292{
293 Elf_Internal_Phdr *phdr;
294 unsigned int i;
295
296 if (!elf_tdata (abfd))
297 return NULL;
298
299 phdr = elf_tdata (abfd)->phdr;
300 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
301 {
302 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
303 return phdr;
304 }
305 return NULL;
306}
307
308void
0542c86d 309nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
1b883d35
KW
310{
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;
316
317 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
318 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
319}
320
d737fd7f
KW
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. */
323int
324nto_in_dynsym_resolve_code (CORE_ADDR pc)
325{
326 if (in_plt_section (pc, NULL))
327 return 1;
328 return 0;
329}
330
d737fd7f 331void
468e3d51 332nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
333{
334 /* Do nothing. */
335}
336
337enum gdb_osabi
338nto_elf_osabi_sniffer (bfd *abfd)
339{
340 if (nto_is_nto_target)
3d171c85 341 return nto_is_nto_target (abfd);
d737fd7f
KW
342 return GDB_OSABI_UNKNOWN;
343}
344
745a434e
AR
345static const char *nto_thread_state_str[] =
346{
347 "DEAD", /* 0 0x00 */
348 "RUNNING", /* 1 0x01 */
349 "READY", /* 2 0x02 */
350 "STOPPED", /* 3 0x03 */
351 "SEND", /* 4 0x04 */
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 */
364 "SEM", /* 17 0x11 */
365 "WAITCTX", /* 18 0x12 */
366 "NET_SEND", /* 19 0x13 */
367 "NET_REPLY" /* 20 0x14 */
368};
369
370char *
371nto_extra_thread_info (struct thread_info *ti)
372{
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];
376 return "";
377}
378
1b883d35 379void
d737fd7f 380nto_initialize_signals (void)
1b883d35 381{
1b883d35
KW
382 /* We use SIG45 for pulses, or something, so nostop, noprint
383 and pass them. */
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);
387
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);
393#endif
394
395#if defined(SIGPHOTON)
396 signal_stop_update (SIGPHOTON, 0);
397 signal_print_update (SIGPHOTON, 0);
398 signal_pass_update (SIGPHOTON, 1);
399#endif
d737fd7f 400}
1b883d35 401
63807e1d
PA
402/* Provide a prototype to silence -Wmissing-prototypes. */
403extern initialize_file_ftype _initialize_nto_tdep;
404
d737fd7f
KW
405void
406_initialize_nto_tdep (void)
407{
408 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
7915a72c
AC
409 &nto_internal_debugging, _("\
410Set QNX NTO internal debugging."), _("\
411Show QNX NTO internal debugging."), _("\
d737fd7f
KW
412When non-zero, nto specific debug info is\n\
413displayed. Different information is displayed\n\
7915a72c 414for different positive values."),
2c5b56ce 415 NULL,
7915a72c 416 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
2c5b56ce 417 &setdebuglist, &showdebuglist);
1b883d35 418}
This page took 0.704169 seconds and 4 git commands to generate.