*** empty log message ***
[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, *base;
93 const char *arch;
94 int ret;
95 #define PATH_FMT \
96 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
97
98 nto_root = nto_target ();
99 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
100 {
101 arch = "x86";
102 endian = "";
103 }
104 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
105 "rs6000") == 0
106 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
107 "powerpc") == 0)
108 {
109 arch = "ppc";
110 endian = "be";
111 }
112 else
113 {
114 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
115 endian = gdbarch_byte_order (target_gdbarch)
116 == BFD_ENDIAN_BIG ? "be" : "le";
117 }
118
119 /* In case nto_root is short, add strlen(solib)
120 so we can reuse arch_path below. */
121 arch_path =
122 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
123 strlen (solib));
124 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
125
126 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
127 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
128 arch_path);
129
130 /* Don't assume basename() isn't destructive. */
131 base = strrchr (solib, '/');
132 if (!base)
133 base = solib;
134 else
135 base++; /* Skip over '/'. */
136
137 ret = openp (buf, 1, base, o_flags, temp_pathname);
138 if (ret < 0 && base != solib)
139 {
140 sprintf (arch_path, "/%s", solib);
141 ret = open (arch_path, o_flags, 0);
142 if (temp_pathname)
143 {
144 if (ret >= 0)
145 *temp_pathname = gdb_realpath (arch_path);
146 else
147 **temp_pathname = '\0';
148 }
149 }
150 return ret;
151 }
152
153 void
154 nto_init_solib_absolute_prefix (void)
155 {
156 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
157 char *nto_root, *endian;
158 const char *arch;
159
160 nto_root = nto_target ();
161 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
162 {
163 arch = "x86";
164 endian = "";
165 }
166 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
167 "rs6000") == 0
168 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
169 "powerpc") == 0)
170 {
171 arch = "ppc";
172 endian = "be";
173 }
174 else
175 {
176 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
177 endian = gdbarch_byte_order (target_gdbarch)
178 == BFD_ENDIAN_BIG ? "be" : "le";
179 }
180
181 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
182
183 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
184 execute_command (buf, 0);
185 }
186
187 char **
188 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
189 const char **perr)
190 {
191 char **argv;
192 char *in, *out, *err, *p;
193 int argc, i, n;
194
195 for (n = 0; pargv[n]; n++);
196 if (n == 0)
197 return NULL;
198 in = "";
199 out = "";
200 err = "";
201
202 argv = xcalloc (n + 1, sizeof argv[0]);
203 argc = n;
204 for (i = 0, n = 0; n < argc; n++)
205 {
206 p = pargv[n];
207 if (*p == '>')
208 {
209 p++;
210 if (*p)
211 out = p;
212 else
213 out = pargv[++n];
214 }
215 else if (*p == '<')
216 {
217 p++;
218 if (*p)
219 in = p;
220 else
221 in = pargv[++n];
222 }
223 else if (*p++ == '2' && *p++ == '>')
224 {
225 if (*p == '&' && *(p + 1) == '1')
226 err = out;
227 else if (*p)
228 err = p;
229 else
230 err = pargv[++n];
231 }
232 else
233 argv[i++] = pargv[n];
234 }
235 *pin = in;
236 *pout = out;
237 *perr = err;
238 return argv;
239 }
240
241 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
242 solib-svr4.c to support nto_relocate_section_addresses
243 which is different from the svr4 version. */
244
245 /* Link map info to include in an allocated so_list entry */
246
247 struct lm_info
248 {
249 /* Pointer to copy of link map from inferior. The type is char *
250 rather than void *, so that we may use byte offsets to find the
251 various fields without the need for a cast. */
252 gdb_byte *lm;
253
254 /* Amount by which addresses in the binary should be relocated to
255 match the inferior. This could most often be taken directly
256 from lm, but when prelinking is involved and the prelink base
257 address changes, we may need a different offset, we want to
258 warn about the difference and compute it only once. */
259 CORE_ADDR l_addr;
260
261 /* The target location of lm. */
262 CORE_ADDR lm_addr;
263 };
264
265
266 static CORE_ADDR
267 LM_ADDR (struct so_list *so)
268 {
269 if (so->lm_info->l_addr == (CORE_ADDR)-1)
270 {
271 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
272 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
273
274 so->lm_info->l_addr =
275 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
276 }
277 return so->lm_info->l_addr;
278 }
279
280 static CORE_ADDR
281 nto_truncate_ptr (CORE_ADDR addr)
282 {
283 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
284 /* We don't need to truncate anything, and the bit twiddling below
285 will fail due to overflow problems. */
286 return addr;
287 else
288 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
289 }
290
291 static Elf_Internal_Phdr *
292 find_load_phdr (bfd *abfd)
293 {
294 Elf_Internal_Phdr *phdr;
295 unsigned int i;
296
297 if (!elf_tdata (abfd))
298 return NULL;
299
300 phdr = elf_tdata (abfd)->phdr;
301 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
302 {
303 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
304 return phdr;
305 }
306 return NULL;
307 }
308
309 void
310 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
311 {
312 /* Neutrino treats the l_addr base address field in link.h as different than
313 the base address in the System V ABI and so the offset needs to be
314 calculated and applied to relocations. */
315 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
316 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
317
318 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
319 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
320 }
321
322 /* This is cheating a bit because our linker code is in libc.so. If we
323 ever implement lazy linking, this may need to be re-examined. */
324 int
325 nto_in_dynsym_resolve_code (CORE_ADDR pc)
326 {
327 if (in_plt_section (pc, NULL))
328 return 1;
329 return 0;
330 }
331
332 void
333 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
334 {
335 /* Do nothing. */
336 }
337
338 enum gdb_osabi
339 nto_elf_osabi_sniffer (bfd *abfd)
340 {
341 if (nto_is_nto_target)
342 return nto_is_nto_target (abfd);
343 return GDB_OSABI_UNKNOWN;
344 }
345
346 static const char *nto_thread_state_str[] =
347 {
348 "DEAD", /* 0 0x00 */
349 "RUNNING", /* 1 0x01 */
350 "READY", /* 2 0x02 */
351 "STOPPED", /* 3 0x03 */
352 "SEND", /* 4 0x04 */
353 "RECEIVE", /* 5 0x05 */
354 "REPLY", /* 6 0x06 */
355 "STACK", /* 7 0x07 */
356 "WAITTHREAD", /* 8 0x08 */
357 "WAITPAGE", /* 9 0x09 */
358 "SIGSUSPEND", /* 10 0x0a */
359 "SIGWAITINFO", /* 11 0x0b */
360 "NANOSLEEP", /* 12 0x0c */
361 "MUTEX", /* 13 0x0d */
362 "CONDVAR", /* 14 0x0e */
363 "JOIN", /* 15 0x0f */
364 "INTR", /* 16 0x10 */
365 "SEM", /* 17 0x11 */
366 "WAITCTX", /* 18 0x12 */
367 "NET_SEND", /* 19 0x13 */
368 "NET_REPLY" /* 20 0x14 */
369 };
370
371 char *
372 nto_extra_thread_info (struct thread_info *ti)
373 {
374 if (ti && ti->private
375 && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
376 return (char *)nto_thread_state_str [ti->private->state];
377 return "";
378 }
379
380 void
381 nto_initialize_signals (void)
382 {
383 /* We use SIG45 for pulses, or something, so nostop, noprint
384 and pass them. */
385 signal_stop_update (target_signal_from_name ("SIG45"), 0);
386 signal_print_update (target_signal_from_name ("SIG45"), 0);
387 signal_pass_update (target_signal_from_name ("SIG45"), 1);
388
389 /* By default we don't want to stop on these two, but we do want to pass. */
390 #if defined(SIGSELECT)
391 signal_stop_update (SIGSELECT, 0);
392 signal_print_update (SIGSELECT, 0);
393 signal_pass_update (SIGSELECT, 1);
394 #endif
395
396 #if defined(SIGPHOTON)
397 signal_stop_update (SIGPHOTON, 0);
398 signal_print_update (SIGPHOTON, 0);
399 signal_pass_update (SIGPHOTON, 1);
400 #endif
401 }
402
403 /* Provide a prototype to silence -Wmissing-prototypes. */
404 extern initialize_file_ftype _initialize_nto_tdep;
405
406 void
407 _initialize_nto_tdep (void)
408 {
409 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
410 &nto_internal_debugging, _("\
411 Set QNX NTO internal debugging."), _("\
412 Show QNX NTO internal debugging."), _("\
413 When non-zero, nto specific debug info is\n\
414 displayed. Different information is displayed\n\
415 for different positive values."),
416 NULL,
417 NULL, /* FIXME: i18n: QNX NTO internal
418 debugging is %s. */
419 &setdebuglist, &showdebuglist);
420 }
This page took 0.03833 seconds and 4 git commands to generate.