*** 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
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 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
96
97 nto_root = nto_target ();
98 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
99 {
100 arch = "x86";
101 endian = "";
102 }
103 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
104 "rs6000") == 0
105 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
106 "powerpc") == 0)
107 {
108 arch = "ppc";
109 endian = "be";
110 }
111 else
112 {
113 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
114 endian = gdbarch_byte_order (target_gdbarch)
115 == BFD_ENDIAN_BIG ? "be" : "le";
116 }
117
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));
123 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
124
125 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
126 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
127 arch_path);
128
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
136 ret = openp (buf, 1, base, o_flags, temp_pathname);
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;
150 }
151
152 void
153 nto_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 ();
160 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
161 {
162 arch = "x86";
163 endian = "";
164 }
165 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
166 "rs6000") == 0
167 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
168 "powerpc") == 0)
169 {
170 arch = "ppc";
171 endian = "be";
172 }
173 else
174 {
175 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
176 endian = gdbarch_byte_order (target_gdbarch)
177 == BFD_ENDIAN_BIG ? "be" : "le";
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
186 char **
187 nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
188 const char **perr)
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
244 /* Link map info to include in an allocated so_list entry */
245
246 struct lm_info
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
264
265 static CORE_ADDR
266 LM_ADDR (struct so_list *so)
267 {
268 if (so->lm_info->l_addr == (CORE_ADDR)-1)
269 {
270 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
271 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
272
273 so->lm_info->l_addr =
274 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
275 }
276 return so->lm_info->l_addr;
277 }
278
279 static CORE_ADDR
280 nto_truncate_ptr (CORE_ADDR addr)
281 {
282 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
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
287 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
288 }
289
290 static Elf_Internal_Phdr *
291 find_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
308 void
309 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
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
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. */
323 int
324 nto_in_dynsym_resolve_code (CORE_ADDR pc)
325 {
326 if (in_plt_section (pc, NULL))
327 return 1;
328 return 0;
329 }
330
331 void
332 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
333 {
334 /* Do nothing. */
335 }
336
337 enum gdb_osabi
338 nto_elf_osabi_sniffer (bfd *abfd)
339 {
340 if (nto_is_nto_target)
341 return nto_is_nto_target (abfd);
342 return GDB_OSABI_UNKNOWN;
343 }
344
345 static 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
370 char *
371 nto_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
379 void
380 nto_initialize_signals (void)
381 {
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
400 }
401
402 /* Provide a prototype to silence -Wmissing-prototypes. */
403 extern initialize_file_ftype _initialize_nto_tdep;
404
405 void
406 _initialize_nto_tdep (void)
407 {
408 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
409 &nto_internal_debugging, _("\
410 Set QNX NTO internal debugging."), _("\
411 Show QNX NTO internal debugging."), _("\
412 When non-zero, nto specific debug info is\n\
413 displayed. Different information is displayed\n\
414 for different positive values."),
415 NULL,
416 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
417 &setdebuglist, &showdebuglist);
418 }
This page took 0.036941 seconds and 4 git commands to generate.