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