Fix date of last entry.
[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
47979a4b 22#include "gdb_stat.h"
1b883d35
KW
23#include "gdb_string.h"
24#include "nto-tdep.h"
25#include "top.h"
26#include "cli/cli-decode.h"
27#include "cli/cli-cmds.h"
28#include "inferior.h"
29#include "gdbarch.h"
30#include "bfd.h"
31#include "elf-bfd.h"
32#include "solib-svr4.h"
33#include "gdbcore.h"
238ae9af
UW
34#include "objfiles.h"
35
36#include <string.h>
1b883d35
KW
37
38#ifdef __CYGWIN__
39#include <sys/cygwin.h>
40#endif
41
42#ifdef __CYGWIN__
43static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
44#elif defined(__sun__) || defined(linux)
45static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
46#else
47static char default_nto_target[] = "";
48#endif
49
50struct nto_target_ops current_nto_target;
51
52static char *
53nto_target (void)
54{
55 char *p = getenv ("QNX_TARGET");
56
57#ifdef __CYGWIN__
58 static char buf[PATH_MAX];
59 if (p)
60 cygwin_conv_to_posix_path (p, buf);
61 else
62 cygwin_conv_to_posix_path (default_nto_target, buf);
63 return buf;
64#else
65 return p ? p : default_nto_target;
66#endif
67}
68
d737fd7f 69void
3d171c85 70nto_set_target (struct nto_target_ops *targ)
d737fd7f
KW
71{
72 nto_regset_id = targ->regset_id;
73 nto_supply_gregset = targ->supply_gregset;
74 nto_supply_fpregset = targ->supply_fpregset;
75 nto_supply_altregset = targ->supply_altregset;
76 nto_supply_regset = targ->supply_regset;
77 nto_register_area = targ->register_area;
78 nto_regset_fill = targ->regset_fill;
79 nto_fetch_link_map_offsets = targ->fetch_link_map_offsets;
80}
81
1b883d35
KW
82/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
83 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
84int
85nto_map_arch_to_cputype (const char *arch)
86{
87 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
88 return CPUTYPE_X86;
192cdb19 89 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
1b883d35
KW
90 return CPUTYPE_PPC;
91 if (!strcmp (arch, "mips"))
92 return CPUTYPE_MIPS;
93 if (!strcmp (arch, "arm"))
94 return CPUTYPE_ARM;
95 if (!strcmp (arch, "sh"))
96 return CPUTYPE_SH;
97 return CPUTYPE_UNKNOWN;
98}
99
100int
101nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
102{
d737fd7f 103 char *buf, *arch_path, *nto_root, *endian, *base;
1b883d35 104 const char *arch;
d737fd7f
KW
105 int ret;
106#define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
1b883d35
KW
107
108 nto_root = nto_target ();
1143fffb 109 if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
110 {
111 arch = "x86";
112 endian = "";
113 }
1143fffb
UW
114 else if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
115 "rs6000") == 0
116 || strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
117 "powerpc") == 0)
1b883d35
KW
118 {
119 arch = "ppc";
120 endian = "be";
121 }
122 else
123 {
1143fffb 124 arch = gdbarch_bfd_arch_info (current_gdbarch)->arch_name;
4c6b5505
UW
125 endian = gdbarch_byte_order (current_gdbarch)
126 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
127 }
128
d737fd7f
KW
129 /* In case nto_root is short, add strlen(solib)
130 so we can reuse arch_path below. */
131 arch_path =
132 alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
133 strlen (solib));
1b883d35
KW
134 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
135
d737fd7f
KW
136 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
137 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
1b883d35
KW
138 arch_path);
139
d737fd7f
KW
140 /* Don't assume basename() isn't destructive. */
141 base = strrchr (solib, '/');
142 if (!base)
143 base = solib;
144 else
145 base++; /* Skip over '/'. */
146
147 ret = openp (buf, 1, base, o_flags, 0, temp_pathname);
148 if (ret < 0 && base != solib)
149 {
150 sprintf (arch_path, "/%s", solib);
151 ret = open (arch_path, o_flags, 0);
152 if (temp_pathname)
153 {
154 if (ret >= 0)
155 *temp_pathname = gdb_realpath (arch_path);
156 else
157 **temp_pathname = '\0';
158 }
159 }
160 return ret;
1b883d35
KW
161}
162
163void
164nto_init_solib_absolute_prefix (void)
165{
166 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
167 char *nto_root, *endian;
168 const char *arch;
169
170 nto_root = nto_target ();
1143fffb 171 if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
172 {
173 arch = "x86";
174 endian = "";
175 }
1143fffb
UW
176 else if (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
177 "rs6000") == 0
178 || strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name,
179 "powerpc") == 0)
1b883d35
KW
180 {
181 arch = "ppc";
182 endian = "be";
183 }
184 else
185 {
1143fffb 186 arch = gdbarch_bfd_arch_info (current_gdbarch)->arch_name;
4c6b5505
UW
187 endian = gdbarch_byte_order (current_gdbarch)
188 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
189 }
190
191 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
192
193 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
194 execute_command (buf, 0);
195}
196
197char **
198nto_parse_redirection (char *pargv[], char **pin, char **pout, char **perr)
199{
200 char **argv;
201 char *in, *out, *err, *p;
202 int argc, i, n;
203
204 for (n = 0; pargv[n]; n++);
205 if (n == 0)
206 return NULL;
207 in = "";
208 out = "";
209 err = "";
210
211 argv = xcalloc (n + 1, sizeof argv[0]);
212 argc = n;
213 for (i = 0, n = 0; n < argc; n++)
214 {
215 p = pargv[n];
216 if (*p == '>')
217 {
218 p++;
219 if (*p)
220 out = p;
221 else
222 out = pargv[++n];
223 }
224 else if (*p == '<')
225 {
226 p++;
227 if (*p)
228 in = p;
229 else
230 in = pargv[++n];
231 }
232 else if (*p++ == '2' && *p++ == '>')
233 {
234 if (*p == '&' && *(p + 1) == '1')
235 err = out;
236 else if (*p)
237 err = p;
238 else
239 err = pargv[++n];
240 }
241 else
242 argv[i++] = pargv[n];
243 }
244 *pin = in;
245 *pout = out;
246 *perr = err;
247 return argv;
248}
249
250/* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
251 solib-svr4.c to support nto_relocate_section_addresses
252 which is different from the svr4 version. */
253
254struct lm_info
255{
256 /* Pointer to copy of link map from inferior. The type is char *
257 rather than void *, so that we may use byte offsets to find the
258 various fields without the need for a cast. */
259 char *lm;
260};
261
262static CORE_ADDR
263LM_ADDR (struct so_list *so)
264{
265 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
266
ec20a626
UW
267 return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset,
268 builtin_type_void_data_ptr);
1b883d35
KW
269}
270
271static CORE_ADDR
272nto_truncate_ptr (CORE_ADDR addr)
273{
819844ad 274 if (gdbarch_ptr_bit (current_gdbarch) == sizeof (CORE_ADDR) * 8)
1b883d35
KW
275 /* We don't need to truncate anything, and the bit twiddling below
276 will fail due to overflow problems. */
277 return addr;
278 else
819844ad 279 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (current_gdbarch)) - 1);
1b883d35
KW
280}
281
282Elf_Internal_Phdr *
283find_load_phdr (bfd *abfd)
284{
285 Elf_Internal_Phdr *phdr;
286 unsigned int i;
287
288 if (!elf_tdata (abfd))
289 return NULL;
290
291 phdr = elf_tdata (abfd)->phdr;
292 for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
293 {
294 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
295 return phdr;
296 }
297 return NULL;
298}
299
300void
301nto_relocate_section_addresses (struct so_list *so, struct section_table *sec)
302{
303 /* Neutrino treats the l_addr base address field in link.h as different than
304 the base address in the System V ABI and so the offset needs to be
305 calculated and applied to relocations. */
306 Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
307 unsigned vaddr = phdr ? phdr->p_vaddr : 0;
308
309 sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
310 sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
311}
312
d737fd7f
KW
313/* This is cheating a bit because our linker code is in libc.so. If we
314 ever implement lazy linking, this may need to be re-examined. */
315int
316nto_in_dynsym_resolve_code (CORE_ADDR pc)
317{
318 if (in_plt_section (pc, NULL))
319 return 1;
320 return 0;
321}
322
323void
324nto_generic_supply_gpregset (const struct regset *regset,
325 struct regcache *regcache, int regnum,
326 const void *gregs, size_t len)
327{
328}
329
330void
331nto_generic_supply_fpregset (const struct regset *regset,
332 struct regcache *regcache, int regnum,
333 const void *fpregs, size_t len)
334{
335}
336
337void
338nto_generic_supply_altregset (const struct regset *regset,
339 struct regcache *regcache, int regnum,
340 const void *altregs, size_t len)
341{
342}
343
344void
468e3d51 345nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
346{
347 /* Do nothing. */
348}
349
350enum gdb_osabi
351nto_elf_osabi_sniffer (bfd *abfd)
352{
353 if (nto_is_nto_target)
3d171c85 354 return nto_is_nto_target (abfd);
d737fd7f
KW
355 return GDB_OSABI_UNKNOWN;
356}
357
1b883d35 358void
d737fd7f 359nto_initialize_signals (void)
1b883d35 360{
1b883d35
KW
361 /* We use SIG45 for pulses, or something, so nostop, noprint
362 and pass them. */
363 signal_stop_update (target_signal_from_name ("SIG45"), 0);
364 signal_print_update (target_signal_from_name ("SIG45"), 0);
365 signal_pass_update (target_signal_from_name ("SIG45"), 1);
366
367 /* By default we don't want to stop on these two, but we do want to pass. */
368#if defined(SIGSELECT)
369 signal_stop_update (SIGSELECT, 0);
370 signal_print_update (SIGSELECT, 0);
371 signal_pass_update (SIGSELECT, 1);
372#endif
373
374#if defined(SIGPHOTON)
375 signal_stop_update (SIGPHOTON, 0);
376 signal_print_update (SIGPHOTON, 0);
377 signal_pass_update (SIGPHOTON, 1);
378#endif
d737fd7f 379}
1b883d35 380
d737fd7f
KW
381void
382_initialize_nto_tdep (void)
383{
384 add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
7915a72c
AC
385 &nto_internal_debugging, _("\
386Set QNX NTO internal debugging."), _("\
387Show QNX NTO internal debugging."), _("\
d737fd7f
KW
388When non-zero, nto specific debug info is\n\
389displayed. Different information is displayed\n\
7915a72c 390for different positive values."),
2c5b56ce 391 NULL,
7915a72c 392 NULL, /* FIXME: i18n: QNX NTO internal debugging is %s. */
2c5b56ce 393 &setdebuglist, &showdebuglist);
1b883d35 394}
This page took 0.415493 seconds and 4 git commands to generate.