gdb/
[deliverable/binutils-gdb.git] / gdb / nto-tdep.c
1 /* nto-tdep.c - general QNX Neutrino target functionality.
2
3 Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
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
12 the Free Software Foundation; either version 3 of the License, or
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
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22
23 #include "defs.h"
24 #include "gdb_stat.h"
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"
36 #include "objfiles.h"
37
38 #include <string.h>
39
40 #ifdef __CYGWIN__
41 #include <sys/cygwin.h>
42 #endif
43
44 #ifdef __CYGWIN__
45 static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
46 #elif defined(__sun__) || defined(linux)
47 static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
48 #else
49 static char default_nto_target[] = "";
50 #endif
51
52 struct nto_target_ops current_nto_target;
53
54 static char *
55 nto_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. */
73 int
74 nto_map_arch_to_cputype (const char *arch)
75 {
76 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
77 return CPUTYPE_X86;
78 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
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
89 int
90 nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
91 {
92 char *buf, *arch_path, *nto_root, *endian;
93 const char *base;
94 const char *arch;
95 int ret;
96 #define PATH_FMT \
97 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
98
99 nto_root = nto_target ();
100 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
101 {
102 arch = "x86";
103 endian = "";
104 }
105 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
106 "rs6000") == 0
107 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
108 "powerpc") == 0)
109 {
110 arch = "ppc";
111 endian = "be";
112 }
113 else
114 {
115 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
116 endian = gdbarch_byte_order (target_gdbarch)
117 == BFD_ENDIAN_BIG ? "be" : "le";
118 }
119
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));
125 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
126
127 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
128 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
129 arch_path);
130
131 base = lbasename (solib);
132 ret = openp (buf, 1, base, o_flags, temp_pathname);
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;
146 }
147
148 void
149 nto_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 ();
156 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
157 {
158 arch = "x86";
159 endian = "";
160 }
161 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
162 "rs6000") == 0
163 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
164 "powerpc") == 0)
165 {
166 arch = "ppc";
167 endian = "be";
168 }
169 else
170 {
171 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
172 endian = gdbarch_byte_order (target_gdbarch)
173 == BFD_ENDIAN_BIG ? "be" : "le";
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
182 char **
183 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
184 const char **perr)
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
240 /* Link map info to include in an allocated so_list entry */
241
242 struct lm_info
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
260
261 static CORE_ADDR
262 LM_ADDR (struct so_list *so)
263 {
264 if (so->lm_info->l_addr == (CORE_ADDR)-1)
265 {
266 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
267 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
268
269 so->lm_info->l_addr =
270 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
271 }
272 return so->lm_info->l_addr;
273 }
274
275 static CORE_ADDR
276 nto_truncate_ptr (CORE_ADDR addr)
277 {
278 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
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
283 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
284 }
285
286 static Elf_Internal_Phdr *
287 find_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
304 void
305 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
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
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. */
319 int
320 nto_in_dynsym_resolve_code (CORE_ADDR pc)
321 {
322 if (in_plt_section (pc, NULL))
323 return 1;
324 return 0;
325 }
326
327 void
328 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
329 {
330 /* Do nothing. */
331 }
332
333 enum gdb_osabi
334 nto_elf_osabi_sniffer (bfd *abfd)
335 {
336 if (nto_is_nto_target)
337 return nto_is_nto_target (abfd);
338 return GDB_OSABI_UNKNOWN;
339 }
340
341 static 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
366 char *
367 nto_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
375 void
376 nto_initialize_signals (void)
377 {
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
396 }
397
398 /* Provide a prototype to silence -Wmissing-prototypes. */
399 extern initialize_file_ftype _initialize_nto_tdep;
400
401 void
402 _initialize_nto_tdep (void)
403 {
404 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
405 &nto_internal_debugging, _("\
406 Set QNX NTO internal debugging."), _("\
407 Show QNX NTO internal debugging."), _("\
408 When non-zero, nto specific debug info is\n\
409 displayed. Different information is displayed\n\
410 for different positive values."),
411 NULL,
412 NULL, /* FIXME: i18n: QNX NTO internal
413 debugging is %s. */
414 &setdebuglist, &showdebuglist);
415 }
This page took 0.039607 seconds and 5 git commands to generate.