daily update
[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 ();
1143fffb 110 if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
111 {
112 arch = "x86";
113 endian = "";
114 }
1143fffb
UW
115 else if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
116 "rs6000") == 0
117 || strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
118 "powerpc") == 0)
1b883d35
KW
119 {
120 arch = "ppc";
121 endian = "be";
122 }
123 else
124 {
1143fffb 125 arch = gdbarch_bfd_arch_info (current_gdbarch)->arch_name;
4c6b5505
UW
126 endian = gdbarch_byte_order (current_gdbarch)
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 ();
1143fffb 172 if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
173 {
174 arch = "x86";
175 endian = "";
176 }
1143fffb
UW
177 else if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
178 "rs6000") == 0
179 || strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
180 "powerpc") == 0)
1b883d35
KW
181 {
182 arch = "ppc";
183 endian = "be";
184 }
185 else
186 {
1143fffb 187 arch = gdbarch_bfd_arch_info (current_gdbarch)->arch_name;
4c6b5505
UW
188 endian = gdbarch_byte_order (current_gdbarch)
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 **
199nto_parse_redirection (char *pargv[], char **pin, char **pout, char **perr)
200{
201 char **argv;
202 char *in, *out, *err, *p;
203 int argc, i, n;
204
205 for (n = 0; pargv[n]; n++);
206 if (n == 0)
207 return NULL;
208 in = "";
209 out = "";
210 err = "";
211
212 argv = xcalloc (n + 1, sizeof argv[0]);
213 argc = n;
214 for (i = 0, n = 0; n < argc; n++)
215 {
216 p = pargv[n];
217 if (*p == '>')
218 {
219 p++;
220 if (*p)
221 out = p;
222 else
223 out = pargv[++n];
224 }
225 else if (*p == '<')
226 {
227 p++;
228 if (*p)
229 in = p;
230 else
231 in = pargv[++n];
232 }
233 else if (*p++ == '2' && *p++ == '>')
234 {
235 if (*p == '&' && *(p + 1) == '1')
236 err = out;
237 else if (*p)
238 err = p;
239 else
240 err = pargv[++n];
241 }
242 else
243 argv[i++] = pargv[n];
244 }
245 *pin = in;
246 *pout = out;
247 *perr = err;
248 return argv;
249}
250
251/* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
252 solib-svr4.c to support nto_relocate_section_addresses
253 which is different from the svr4 version. */
254
255struct lm_info
256{
257 /* Pointer to copy of link map from inferior. The type is char *
258 rather than void *, so that we may use byte offsets to find the
259 various fields without the need for a cast. */
260 char *lm;
261};
262
263static CORE_ADDR
264LM_ADDR (struct so_list *so)
265{
266 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
267
ec20a626
UW
268 return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset,
269 builtin_type_void_data_ptr);
1b883d35
KW
270}
271
272static CORE_ADDR
273nto_truncate_ptr (CORE_ADDR addr)
274{
819844ad 275 if (gdbarch_ptr_bit (current_gdbarch) == sizeof (CORE_ADDR) * 8)
1b883d35
KW
276 /* We don't need to truncate anything, and the bit twiddling below
277 will fail due to overflow problems. */
278 return addr;
279 else
819844ad 280 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (current_gdbarch)) - 1);
1b883d35
KW
281}
282
283Elf_Internal_Phdr *
284find_load_phdr (bfd *abfd)
285{
286 Elf_Internal_Phdr *phdr;
287 unsigned int i;
288
289 if (!elf_tdata (abfd))
290 return NULL;
291
292 phdr = elf_tdata (abfd)->phdr;
293 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
294 {
295 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
296 return phdr;
297 }
298 return NULL;
299}
300
301void
302nto_relocate_section_addresses (struct so_list *so, struct section_table *sec)
303{
304 /* Neutrino treats the l_addr base address field in link.h as different than
305 the base address in the System V ABI and so the offset needs to be
306 calculated and applied to relocations. */
307 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
308 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
309
310 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
311 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
312}
313
d737fd7f
KW
314/* This is cheating a bit because our linker code is in libc.so. If we
315 ever implement lazy linking, this may need to be re-examined. */
316int
317nto_in_dynsym_resolve_code (CORE_ADDR pc)
318{
319 if (in_plt_section (pc, NULL))
320 return 1;
321 return 0;
322}
323
324void
325nto_generic_supply_gpregset (const struct regset *regset,
326 struct regcache *regcache, int regnum,
327 const void *gregs, size_t len)
328{
329}
330
331void
332nto_generic_supply_fpregset (const struct regset *regset,
333 struct regcache *regcache, int regnum,
334 const void *fpregs, size_t len)
335{
336}
337
338void
339nto_generic_supply_altregset (const struct regset *regset,
340 struct regcache *regcache, int regnum,
341 const void *altregs, size_t len)
342{
343}
344
345void
468e3d51 346nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
347{
348 /* Do nothing. */
349}
350
351enum gdb_osabi
352nto_elf_osabi_sniffer (bfd *abfd)
353{
354 if (nto_is_nto_target)
3d171c85 355 return nto_is_nto_target (abfd);
d737fd7f
KW
356 return GDB_OSABI_UNKNOWN;
357}
358
1b883d35 359void
d737fd7f 360nto_initialize_signals (void)
1b883d35 361{
1b883d35
KW
362 /* We use SIG45 for pulses, or something, so nostop, noprint
363 and pass them. */
364 signal_stop_update (target_signal_from_name ("SIG45"), 0);
365 signal_print_update (target_signal_from_name ("SIG45"), 0);
366 signal_pass_update (target_signal_from_name ("SIG45"), 1);
367
368 /* By default we don't want to stop on these two, but we do want to pass. */
369#if defined(SIGSELECT)
370 signal_stop_update (SIGSELECT, 0);
371 signal_print_update (SIGSELECT, 0);
372 signal_pass_update (SIGSELECT, 1);
373#endif
374
375#if defined(SIGPHOTON)
376 signal_stop_update (SIGPHOTON, 0);
377 signal_print_update (SIGPHOTON, 0);
378 signal_pass_update (SIGPHOTON, 1);
379#endif
d737fd7f 380}
1b883d35 381
d737fd7f
KW
382void
383_initialize_nto_tdep (void)
384{
385 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
7915a72c
AC
386 &nto_internal_debugging, _("\
387Set QNX NTO internal debugging."), _("\
388Show QNX NTO internal debugging."), _("\
d737fd7f
KW
389When non-zero, nto specific debug info is\n\
390displayed. Different information is displayed\n\
7915a72c 391for different positive values."),
2c5b56ce 392 NULL,
7915a72c 393 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
2c5b56ce 394 &setdebuglist, &showdebuglist);
1b883d35 395}
This page took 0.452466 seconds and 4 git commands to generate.