Silence a few -Wmissing-prototypes warnings.
[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 void
71 nto_set_target (struct nto_target_ops *targ)
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
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.  */
85 int
86 nto_map_arch_to_cputype (const char *arch)
87 {
88   if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
89     return CPUTYPE_X86;
90   if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
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
101 int
102 nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
103 {
104   char *buf, *arch_path, *nto_root, *endian, *base;
105   const char *arch;
106   int ret;
107 #define PATH_FMT "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
108
109   nto_root = nto_target ();
110   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
111     {
112       arch = "x86";
113       endian = "";
114     }
115   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
116                    "rs6000") == 0
117            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
118                    "powerpc") == 0)
119     {
120       arch = "ppc";
121       endian = "be";
122     }
123   else
124     {
125       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
126       endian = gdbarch_byte_order (target_gdbarch)
127                == BFD_ENDIAN_BIG ? "be" : "le";
128     }
129
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));
135   sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
136
137   buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
138   sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
139            arch_path);
140
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;
162 }
163
164 void
165 nto_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 ();
172   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
173     {
174       arch = "x86";
175       endian = "";
176     }
177   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
178                    "rs6000") == 0
179            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
180                    "powerpc") == 0)
181     {
182       arch = "ppc";
183       endian = "be";
184     }
185   else
186     {
187       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
188       endian = gdbarch_byte_order (target_gdbarch)
189                == BFD_ENDIAN_BIG ? "be" : "le";
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
198 char **
199 nto_parse_redirection (char *pargv[], const char **pin, const char **pout, 
200                        const char **perr)
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
256 /* Link map info to include in an allocated so_list entry */
257
258 struct lm_info
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
276
277 static CORE_ADDR
278 LM_ADDR (struct so_list *so)
279 {
280   if (so->lm_info->l_addr == (CORE_ADDR)-1)
281     {
282       struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
283       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
284
285       so->lm_info->l_addr =
286         extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
287     }
288   return so->lm_info->l_addr;
289 }
290
291 static CORE_ADDR
292 nto_truncate_ptr (CORE_ADDR addr)
293 {
294   if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
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
299     return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
300 }
301
302 static Elf_Internal_Phdr *
303 find_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
320 void
321 nto_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
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.  */
335 int
336 nto_in_dynsym_resolve_code (CORE_ADDR pc)
337 {
338   if (in_plt_section (pc, NULL))
339     return 1;
340   return 0;
341 }
342
343 void
344 nto_generic_supply_gpregset (const struct regset *regset,
345                              struct regcache *regcache, int regnum,
346                              const void *gregs, size_t len)
347 {
348 }
349
350 void
351 nto_generic_supply_fpregset (const struct regset *regset,
352                              struct regcache *regcache, int regnum,
353                              const void *fpregs, size_t len)
354 {
355 }
356
357 void
358 nto_generic_supply_altregset (const struct regset *regset,
359                               struct regcache *regcache, int regnum,
360                               const void *altregs, size_t len)
361 {
362 }
363
364 void
365 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
366 {
367   /* Do nothing.  */
368 }
369
370 enum gdb_osabi
371 nto_elf_osabi_sniffer (bfd *abfd)
372 {
373   if (nto_is_nto_target)
374     return nto_is_nto_target (abfd);
375   return GDB_OSABI_UNKNOWN;
376 }
377
378 void
379 nto_initialize_signals (void)
380 {
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
399 }
400
401 /* Provide a prototype to silence -Wmissing-prototypes.  */
402 extern initialize_file_ftype _initialize_nto_tdep;
403
404 void
405 _initialize_nto_tdep (void)
406 {
407   add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
408                             &nto_internal_debugging, _("\
409 Set QNX NTO internal debugging."), _("\
410 Show QNX NTO internal debugging."), _("\
411 When non-zero, nto specific debug info is\n\
412 displayed. Different information is displayed\n\
413 for different positive values."),
414                             NULL,
415                             NULL, /* FIXME: i18n: QNX NTO internal debugging is %s.  */
416                             &setdebuglist, &showdebuglist);
417 }