* solib-svr4.c (LM_ADDR_FROM_LINK_MAP): Use builtin types of
[deliverable/binutils-gdb.git] / gdb / nto-tdep.c
CommitLineData
1b883d35
KW
1/* nto-tdep.c - general QNX Neutrino target functionality.
2
9b254dd1 3 Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
1b883d35
KW
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
1b883d35
KW
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1b883d35 21
b4d5ed91 22#include "defs.h"
47979a4b 23#include "gdb_stat.h"
1b883d35
KW
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"
238ae9af
UW
35#include "objfiles.h"
36
37#include <string.h>
1b883d35
KW
38
39#ifdef __CYGWIN__
40#include <sys/cygwin.h>
41#endif
42
43#ifdef __CYGWIN__
44static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
45#elif defined(__sun__) || defined(linux)
46static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
47#else
48static char default_nto_target[] = "";
49#endif
50
51struct nto_target_ops current_nto_target;
52
53static char *
54nto_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
d737fd7f 70void
3d171c85 71nto_set_target (struct nto_target_ops *targ)
d737fd7f
KW
72{
73 nto_regset_id = targ->regset_id;
74 nto_supply_gregset = targ->supply_gregset;
75 nto_supply_fpregset = targ->supply_fpregset;
76 nto_supply_altregset = targ->supply_altregset;
77 nto_supply_regset = targ->supply_regset;
78 nto_register_area = targ->register_area;
79 nto_regset_fill = targ->regset_fill;
80 nto_fetch_link_map_offsets = targ->fetch_link_map_offsets;
81}
82
1b883d35
KW
83/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
84 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
85int
86nto_map_arch_to_cputype (const char *arch)
87{
88 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
89 return CPUTYPE_X86;
192cdb19 90 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
1b883d35
KW
91 return CPUTYPE_PPC;
92 if (!strcmp (arch, "mips"))
93 return CPUTYPE_MIPS;
94 if (!strcmp (arch, "arm"))
95 return CPUTYPE_ARM;
96 if (!strcmp (arch, "sh"))
97 return CPUTYPE_SH;
98 return CPUTYPE_UNKNOWN;
99}
100
101int
102nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
103{
d737fd7f 104 char *buf, *arch_path, *nto_root, *endian, *base;
1b883d35 105 const char *arch;
d737fd7f
KW
106 int ret;
107#define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
1b883d35
KW
108
109 nto_root = nto_target ();
1cf3db46 110 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
111 {
112 arch = "x86";
113 endian = "";
114 }
1cf3db46 115 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 116 "rs6000") == 0
1cf3db46 117 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 118 "powerpc") == 0)
1b883d35
KW
119 {
120 arch = "ppc";
121 endian = "be";
122 }
123 else
124 {
1cf3db46
UW
125 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
126 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 127 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
128 }
129
d737fd7f
KW
130 /* In case nto_root is short, add strlen(solib)
131 so we can reuse arch_path below. */
132 arch_path =
133 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
134 strlen (solib));
1b883d35
KW
135 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
136
d737fd7f
KW
137 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
138 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
1b883d35
KW
139 arch_path);
140
d737fd7f
KW
141 /* Don't assume basename() isn't destructive. */
142 base = strrchr (solib, '/');
143 if (!base)
144 base = solib;
145 else
146 base++; /* Skip over '/'. */
147
148 ret = openp (buf, 1, base, o_flags, 0, temp_pathname);
149 if (ret < 0 && base != solib)
150 {
151 sprintf (arch_path, "/%s", solib);
152 ret = open (arch_path, o_flags, 0);
153 if (temp_pathname)
154 {
155 if (ret >= 0)
156 *temp_pathname = gdb_realpath (arch_path);
157 else
158 **temp_pathname = '\0';
159 }
160 }
161 return ret;
1b883d35
KW
162}
163
164void
165nto_init_solib_absolute_prefix (void)
166{
167 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
168 char *nto_root, *endian;
169 const char *arch;
170
171 nto_root = nto_target ();
1cf3db46 172 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
173 {
174 arch = "x86";
175 endian = "";
176 }
1cf3db46 177 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 178 "rs6000") == 0
1cf3db46 179 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 180 "powerpc") == 0)
1b883d35
KW
181 {
182 arch = "ppc";
183 endian = "be";
184 }
185 else
186 {
1cf3db46
UW
187 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
188 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 189 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
190 }
191
192 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
193
194 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
195 execute_command (buf, 0);
196}
197
198char **
14ef7606
AR
199nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
200 const char **perr)
1b883d35
KW
201{
202 char **argv;
203 char *in, *out, *err, *p;
204 int argc, i, n;
205
206 for (n = 0; pargv[n]; n++);
207 if (n == 0)
208 return NULL;
209 in = "";
210 out = "";
211 err = "";
212
213 argv = xcalloc (n + 1, sizeof argv[0]);
214 argc = n;
215 for (i = 0, n = 0; n < argc; n++)
216 {
217 p = pargv[n];
218 if (*p == '>')
219 {
220 p++;
221 if (*p)
222 out = p;
223 else
224 out = pargv[++n];
225 }
226 else if (*p == '<')
227 {
228 p++;
229 if (*p)
230 in = p;
231 else
232 in = pargv[++n];
233 }
234 else if (*p++ == '2' && *p++ == '>')
235 {
236 if (*p == '&' && *(p + 1) == '1')
237 err = out;
238 else if (*p)
239 err = p;
240 else
241 err = pargv[++n];
242 }
243 else
244 argv[i++] = pargv[n];
245 }
246 *pin = in;
247 *pout = out;
248 *perr = err;
249 return argv;
250}
251
252/* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
253 solib-svr4.c to support nto_relocate_section_addresses
254 which is different from the svr4 version. */
255
ebd67d87
AR
256/* Link map info to include in an allocated so_list entry */
257
1b883d35 258struct lm_info
ebd67d87
AR
259 {
260 /* Pointer to copy of link map from inferior. The type is char *
261 rather than void *, so that we may use byte offsets to find the
262 various fields without the need for a cast. */
263 gdb_byte *lm;
264
265 /* Amount by which addresses in the binary should be relocated to
266 match the inferior. This could most often be taken directly
267 from lm, but when prelinking is involved and the prelink base
268 address changes, we may need a different offset, we want to
269 warn about the difference and compute it only once. */
270 CORE_ADDR l_addr;
271
272 /* The target location of lm. */
273 CORE_ADDR lm_addr;
274 };
275
1b883d35
KW
276
277static CORE_ADDR
278LM_ADDR (struct so_list *so)
279{
ebd67d87
AR
280 if (so->lm_info->l_addr == (CORE_ADDR)-1)
281 {
282 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
b6da22b0 283 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
1b883d35 284
ebd67d87 285 so->lm_info->l_addr =
b6da22b0 286 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
ebd67d87
AR
287 }
288 return so->lm_info->l_addr;
1b883d35
KW
289}
290
291static CORE_ADDR
292nto_truncate_ptr (CORE_ADDR addr)
293{
1cf3db46 294 if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
1b883d35
KW
295 /* We don't need to truncate anything, and the bit twiddling below
296 will fail due to overflow problems. */
297 return addr;
298 else
1cf3db46 299 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
1b883d35
KW
300}
301
302Elf_Internal_Phdr *
303find_load_phdr (bfd *abfd)
304{
305 Elf_Internal_Phdr *phdr;
306 unsigned int i;
307
308 if (!elf_tdata (abfd))
309 return NULL;
310
311 phdr = elf_tdata (abfd)->phdr;
312 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
313 {
314 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
315 return phdr;
316 }
317 return NULL;
318}
319
320void
321nto_relocate_section_addresses (struct so_list *so, struct section_table *sec)
322{
323 /* Neutrino treats the l_addr base address field in link.h as different than
324 the base address in the System V ABI and so the offset needs to be
325 calculated and applied to relocations. */
326 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
327 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
328
329 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
330 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
331}
332
d737fd7f
KW
333/* This is cheating a bit because our linker code is in libc.so. If we
334 ever implement lazy linking, this may need to be re-examined. */
335int
336nto_in_dynsym_resolve_code (CORE_ADDR pc)
337{
338 if (in_plt_section (pc, NULL))
339 return 1;
340 return 0;
341}
342
343void
344nto_generic_supply_gpregset (const struct regset *regset,
345 struct regcache *regcache, int regnum,
346 const void *gregs, size_t len)
347{
348}
349
350void
351nto_generic_supply_fpregset (const struct regset *regset,
352 struct regcache *regcache, int regnum,
353 const void *fpregs, size_t len)
354{
355}
356
357void
358nto_generic_supply_altregset (const struct regset *regset,
359 struct regcache *regcache, int regnum,
360 const void *altregs, size_t len)
361{
362}
363
364void
468e3d51 365nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
366{
367 /* Do nothing. */
368}
369
370enum gdb_osabi
371nto_elf_osabi_sniffer (bfd *abfd)
372{
373 if (nto_is_nto_target)
3d171c85 374 return nto_is_nto_target (abfd);
d737fd7f
KW
375 return GDB_OSABI_UNKNOWN;
376}
377
1b883d35 378void
d737fd7f 379nto_initialize_signals (void)
1b883d35 380{
1b883d35
KW
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
d737fd7f 399}
1b883d35 400
d737fd7f
KW
401void
402_initialize_nto_tdep (void)
403{
404 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
7915a72c
AC
405 &nto_internal_debugging, _("\
406Set QNX NTO internal debugging."), _("\
407Show QNX NTO internal debugging."), _("\
d737fd7f
KW
408When non-zero, nto specific debug info is\n\
409displayed. Different information is displayed\n\
7915a72c 410for different positive values."),
2c5b56ce 411 NULL,
7915a72c 412 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
2c5b56ce 413 &setdebuglist, &showdebuglist);
1b883d35 414}
This page took 0.460052 seconds and 4 git commands to generate.