b4f1bdeb67f6348c4eeb7bb39c5d9a88fd385716
[external/binutils.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_generic_supply_gpregset (const struct regset *regset,
332                              struct regcache *regcache, int regnum,
333                              const void *gregs, size_t len)
334 {
335 }
336
337 void
338 nto_generic_supply_fpregset (const struct regset *regset,
339                              struct regcache *regcache, int regnum,
340                              const void *fpregs, size_t len)
341 {
342 }
343
344 void
345 nto_generic_supply_altregset (const struct regset *regset,
346                               struct regcache *regcache, int regnum,
347                               const void *altregs, size_t len)
348 {
349 }
350
351 void
352 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
353 {
354   /* Do nothing.  */
355 }
356
357 enum gdb_osabi
358 nto_elf_osabi_sniffer (bfd *abfd)
359 {
360   if (nto_is_nto_target)
361     return nto_is_nto_target (abfd);
362   return GDB_OSABI_UNKNOWN;
363 }
364
365 void
366 nto_initialize_signals (void)
367 {
368   /* We use SIG45 for pulses, or something, so nostop, noprint
369      and pass them.  */
370   signal_stop_update (target_signal_from_name ("SIG45"), 0);
371   signal_print_update (target_signal_from_name ("SIG45"), 0);
372   signal_pass_update (target_signal_from_name ("SIG45"), 1);
373
374   /* By default we don't want to stop on these two, but we do want to pass.  */
375 #if defined(SIGSELECT)
376   signal_stop_update (SIGSELECT, 0);
377   signal_print_update (SIGSELECT, 0);
378   signal_pass_update (SIGSELECT, 1);
379 #endif
380
381 #if defined(SIGPHOTON)
382   signal_stop_update (SIGPHOTON, 0);
383   signal_print_update (SIGPHOTON, 0);
384   signal_pass_update (SIGPHOTON, 1);
385 #endif
386 }
387
388 /* Provide a prototype to silence -Wmissing-prototypes.  */
389 extern initialize_file_ftype _initialize_nto_tdep;
390
391 void
392 _initialize_nto_tdep (void)
393 {
394   add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
395                             &nto_internal_debugging, _("\
396 Set QNX NTO internal debugging."), _("\
397 Show QNX NTO internal debugging."), _("\
398 When non-zero, nto specific debug info is\n\
399 displayed. Different information is displayed\n\
400 for different positive values."),
401                             NULL,
402                             NULL, /* FIXME: i18n: QNX NTO internal debugging is %s.  */
403                             &setdebuglist, &showdebuglist);
404 }