]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/nto-tdep.c
* read.h (s_vendor_attribute): Move to...
[thirdparty/binutils-gdb.git] / gdb / nto-tdep.c
CommitLineData
1b883d35
KW
1/* nto-tdep.c - general QNX Neutrino target functionality.
2
0b302171 3 Copyright (C) 2003-2004, 2007-2012 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"
1b883d35
KW
27#include "inferior.h"
28#include "gdbarch.h"
29#include "bfd.h"
30#include "elf-bfd.h"
31#include "solib-svr4.h"
32#include "gdbcore.h"
238ae9af
UW
33#include "objfiles.h"
34
35#include <string.h>
1b883d35
KW
36
37#ifdef __CYGWIN__
38#include <sys/cygwin.h>
39#endif
40
41#ifdef __CYGWIN__
42static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
43#elif defined(__sun__) || defined(linux)
44static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
45#else
46static char default_nto_target[] = "";
47#endif
48
49struct nto_target_ops current_nto_target;
50
51static char *
52nto_target (void)
53{
54 char *p = getenv ("QNX_TARGET");
55
56#ifdef __CYGWIN__
57 static char buf[PATH_MAX];
58 if (p)
90375a0e 59 cygwin_conv_path (CCP_WIN_A_TO_POSIX, p, buf, PATH_MAX);
1b883d35 60 else
90375a0e 61 cygwin_conv_path (CCP_WIN_A_TO_POSIX, default_nto_target, buf, PATH_MAX);
1b883d35
KW
62 return buf;
63#else
64 return p ? p : default_nto_target;
65#endif
66}
67
68/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
69 CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */
70int
71nto_map_arch_to_cputype (const char *arch)
72{
73 if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
74 return CPUTYPE_X86;
192cdb19 75 if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
1b883d35
KW
76 return CPUTYPE_PPC;
77 if (!strcmp (arch, "mips"))
78 return CPUTYPE_MIPS;
79 if (!strcmp (arch, "arm"))
80 return CPUTYPE_ARM;
81 if (!strcmp (arch, "sh"))
82 return CPUTYPE_SH;
83 return CPUTYPE_UNKNOWN;
84}
85
86int
87nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
88{
91495617
PA
89 char *buf, *arch_path, *nto_root, *endian;
90 const char *base;
1b883d35 91 const char *arch;
d737fd7f 92 int ret;
0df8b418
MS
93#define PATH_FMT \
94 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
1b883d35
KW
95
96 nto_root = nto_target ();
1cf3db46 97 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
98 {
99 arch = "x86";
100 endian = "";
101 }
1cf3db46 102 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 103 "rs6000") == 0
1cf3db46 104 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 105 "powerpc") == 0)
1b883d35
KW
106 {
107 arch = "ppc";
108 endian = "be";
109 }
110 else
111 {
1cf3db46
UW
112 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
113 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 114 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
115 }
116
d737fd7f
KW
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));
1b883d35
KW
122 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
123
d737fd7f
KW
124 buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
125 sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
1b883d35
KW
126 arch_path);
127
9f37bbcc 128 base = lbasename (solib);
fbdebf46 129 ret = openp (buf, 1, base, o_flags, temp_pathname);
d737fd7f
KW
130 if (ret < 0 && base != solib)
131 {
132 sprintf (arch_path, "/%s", solib);
133 ret = open (arch_path, o_flags, 0);
134 if (temp_pathname)
135 {
136 if (ret >= 0)
137 *temp_pathname = gdb_realpath (arch_path);
138 else
139 **temp_pathname = '\0';
140 }
141 }
142 return ret;
1b883d35
KW
143}
144
145void
146nto_init_solib_absolute_prefix (void)
147{
148 char buf[PATH_MAX * 2], arch_path[PATH_MAX];
149 char *nto_root, *endian;
150 const char *arch;
151
152 nto_root = nto_target ();
1cf3db46 153 if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
1b883d35
KW
154 {
155 arch = "x86";
156 endian = "";
157 }
1cf3db46 158 else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 159 "rs6000") == 0
1cf3db46 160 || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
1143fffb 161 "powerpc") == 0)
1b883d35
KW
162 {
163 arch = "ppc";
164 endian = "be";
165 }
166 else
167 {
1cf3db46
UW
168 arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
169 endian = gdbarch_byte_order (target_gdbarch)
4c6b5505 170 == BFD_ENDIAN_BIG ? "be" : "le";
1b883d35
KW
171 }
172
173 sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
174
175 sprintf (buf, "set solib-absolute-prefix %s", arch_path);
176 execute_command (buf, 0);
177}
178
179char **
14ef7606
AR
180nto_parse_redirection (char *pargv[], const char **pin, const char **pout,
181 const char **perr)
1b883d35
KW
182{
183 char **argv;
184 char *in, *out, *err, *p;
185 int argc, i, n;
186
187 for (n = 0; pargv[n]; n++);
188 if (n == 0)
189 return NULL;
190 in = "";
191 out = "";
192 err = "";
193
194 argv = xcalloc (n + 1, sizeof argv[0]);
195 argc = n;
196 for (i = 0, n = 0; n < argc; n++)
197 {
198 p = pargv[n];
199 if (*p == '>')
200 {
201 p++;
202 if (*p)
203 out = p;
204 else
205 out = pargv[++n];
206 }
207 else if (*p == '<')
208 {
209 p++;
210 if (*p)
211 in = p;
212 else
213 in = pargv[++n];
214 }
215 else if (*p++ == '2' && *p++ == '>')
216 {
217 if (*p == '&' && *(p + 1) == '1')
218 err = out;
219 else if (*p)
220 err = p;
221 else
222 err = pargv[++n];
223 }
224 else
225 argv[i++] = pargv[n];
226 }
227 *pin = in;
228 *pout = out;
229 *perr = err;
230 return argv;
231}
232
b23518f0 233/* The struct lm_info, lm_addr, and nto_truncate_ptr are copied from
1b883d35
KW
234 solib-svr4.c to support nto_relocate_section_addresses
235 which is different from the svr4 version. */
236
ebd67d87
AR
237/* Link map info to include in an allocated so_list entry */
238
1b883d35 239struct lm_info
ebd67d87
AR
240 {
241 /* Pointer to copy of link map from inferior. The type is char *
242 rather than void *, so that we may use byte offsets to find the
243 various fields without the need for a cast. */
244 gdb_byte *lm;
245
246 /* Amount by which addresses in the binary should be relocated to
247 match the inferior. This could most often be taken directly
248 from lm, but when prelinking is involved and the prelink base
249 address changes, we may need a different offset, we want to
250 warn about the difference and compute it only once. */
251 CORE_ADDR l_addr;
252
253 /* The target location of lm. */
254 CORE_ADDR lm_addr;
255 };
256
1b883d35
KW
257
258static CORE_ADDR
b23518f0 259lm_addr (struct so_list *so)
1b883d35 260{
ebd67d87
AR
261 if (so->lm_info->l_addr == (CORE_ADDR)-1)
262 {
263 struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
b6da22b0 264 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
1b883d35 265
ebd67d87 266 so->lm_info->l_addr =
b6da22b0 267 extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
ebd67d87
AR
268 }
269 return so->lm_info->l_addr;
1b883d35
KW
270}
271
272static CORE_ADDR
273nto_truncate_ptr (CORE_ADDR addr)
274{
1cf3db46 275 if (gdbarch_ptr_bit (target_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
1cf3db46 280 return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
1b883d35
KW
281}
282
63807e1d 283static Elf_Internal_Phdr *
1b883d35
KW
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
0542c86d 302nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
1b883d35
KW
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
b23518f0
PM
310 sec->addr = nto_truncate_ptr (sec->addr + lm_addr (so) - vaddr);
311 sec->endaddr = nto_truncate_ptr (sec->endaddr + lm_addr (so) - vaddr);
1b883d35
KW
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
d737fd7f 324void
468e3d51 325nto_dummy_supply_regset (struct regcache *regcache, char *regs)
d737fd7f
KW
326{
327 /* Do nothing. */
328}
329
330enum gdb_osabi
331nto_elf_osabi_sniffer (bfd *abfd)
332{
333 if (nto_is_nto_target)
3d171c85 334 return nto_is_nto_target (abfd);
d737fd7f
KW
335 return GDB_OSABI_UNKNOWN;
336}
337
745a434e
AR
338static const char *nto_thread_state_str[] =
339{
340 "DEAD", /* 0 0x00 */
341 "RUNNING", /* 1 0x01 */
342 "READY", /* 2 0x02 */
343 "STOPPED", /* 3 0x03 */
344 "SEND", /* 4 0x04 */
345 "RECEIVE", /* 5 0x05 */
346 "REPLY", /* 6 0x06 */
347 "STACK", /* 7 0x07 */
348 "WAITTHREAD", /* 8 0x08 */
349 "WAITPAGE", /* 9 0x09 */
350 "SIGSUSPEND", /* 10 0x0a */
351 "SIGWAITINFO", /* 11 0x0b */
352 "NANOSLEEP", /* 12 0x0c */
353 "MUTEX", /* 13 0x0d */
354 "CONDVAR", /* 14 0x0e */
355 "JOIN", /* 15 0x0f */
356 "INTR", /* 16 0x10 */
357 "SEM", /* 17 0x11 */
358 "WAITCTX", /* 18 0x12 */
359 "NET_SEND", /* 19 0x13 */
360 "NET_REPLY" /* 20 0x14 */
361};
362
363char *
364nto_extra_thread_info (struct thread_info *ti)
365{
366 if (ti && ti->private
367 && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
368 return (char *)nto_thread_state_str [ti->private->state];
369 return "";
370}
371
1b883d35 372void
d737fd7f 373nto_initialize_signals (void)
1b883d35 374{
1b883d35
KW
375 /* We use SIG45 for pulses, or something, so nostop, noprint
376 and pass them. */
2ea28649
PA
377 signal_stop_update (gdb_signal_from_name ("SIG45"), 0);
378 signal_print_update (gdb_signal_from_name ("SIG45"), 0);
379 signal_pass_update (gdb_signal_from_name ("SIG45"), 1);
1b883d35
KW
380
381 /* By default we don't want to stop on these two, but we do want to pass. */
382#if defined(SIGSELECT)
383 signal_stop_update (SIGSELECT, 0);
384 signal_print_update (SIGSELECT, 0);
385 signal_pass_update (SIGSELECT, 1);
386#endif
387
388#if defined(SIGPHOTON)
389 signal_stop_update (SIGPHOTON, 0);
390 signal_print_update (SIGPHOTON, 0);
391 signal_pass_update (SIGPHOTON, 1);
392#endif
d737fd7f 393}