OSDN Git Service

* gdb.hp/gdb.aCC/Makefile.in (Makefile): Remove.
[pf3gnuchains/sourceware.git] / gdb / nto-tdep.c
1 /* nto-tdep.c - general QNX Neutrino target functionality.
2
3    Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011
4    Free Software Foundation, Inc.
5
6    Contributed by QNX Software Systems Ltd.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include "defs.h"
24 #include "gdb_stat.h"
25 #include "gdb_string.h"
26 #include "nto-tdep.h"
27 #include "top.h"
28 #include "cli/cli-decode.h"
29 #include "cli/cli-cmds.h"
30 #include "inferior.h"
31 #include "gdbarch.h"
32 #include "bfd.h"
33 #include "elf-bfd.h"
34 #include "solib-svr4.h"
35 #include "gdbcore.h"
36 #include "objfiles.h"
37
38 #include <string.h>
39
40 #ifdef __CYGWIN__
41 #include <sys/cygwin.h>
42 #endif
43
44 #ifdef __CYGWIN__
45 static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
46 #elif defined(__sun__) || defined(linux)
47 static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
48 #else
49 static char default_nto_target[] = "";
50 #endif
51
52 struct nto_target_ops current_nto_target;
53
54 static char *
55 nto_target (void)
56 {
57   char *p = getenv ("QNX_TARGET");
58
59 #ifdef __CYGWIN__
60   static char buf[PATH_MAX];
61   if (p)
62     cygwin_conv_to_posix_path (p, buf);
63   else
64     cygwin_conv_to_posix_path (default_nto_target, buf);
65   return buf;
66 #else
67   return p ? p : default_nto_target;
68 #endif
69 }
70
71 /* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
72    CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h.  */
73 int
74 nto_map_arch_to_cputype (const char *arch)
75 {
76   if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
77     return CPUTYPE_X86;
78   if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc"))
79     return CPUTYPE_PPC;
80   if (!strcmp (arch, "mips"))
81     return CPUTYPE_MIPS;
82   if (!strcmp (arch, "arm"))
83     return CPUTYPE_ARM;
84   if (!strcmp (arch, "sh"))
85     return CPUTYPE_SH;
86   return CPUTYPE_UNKNOWN;
87 }
88
89 int
90 nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
91 {
92   char *buf, *arch_path, *nto_root, *endian, *base;
93   const char *arch;
94   int ret;
95 #define PATH_FMT \
96   "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
97
98   nto_root = nto_target ();
99   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
100     {
101       arch = "x86";
102       endian = "";
103     }
104   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
105                    "rs6000") == 0
106            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
107                    "powerpc") == 0)
108     {
109       arch = "ppc";
110       endian = "be";
111     }
112   else
113     {
114       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
115       endian = gdbarch_byte_order (target_gdbarch)
116                == BFD_ENDIAN_BIG ? "be" : "le";
117     }
118
119   /* In case nto_root is short, add strlen(solib)
120      so we can reuse arch_path below.  */
121   arch_path =
122     alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
123             strlen (solib));
124   sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
125
126   buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
127   sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
128            arch_path);
129
130   /* Don't assume basename() isn't destructive.  */
131   base = strrchr (solib, '/');
132   if (!base)
133     base = solib;
134   else
135     base++;                     /* Skip over '/'.  */
136
137   ret = openp (buf, 1, base, o_flags, temp_pathname);
138   if (ret < 0 && base != solib)
139     {
140       sprintf (arch_path, "/%s", solib);
141       ret = open (arch_path, o_flags, 0);
142       if (temp_pathname)
143         {
144           if (ret >= 0)
145             *temp_pathname = gdb_realpath (arch_path);
146           else
147             **temp_pathname = '\0';
148         }
149     }
150   return ret;
151 }
152
153 void
154 nto_init_solib_absolute_prefix (void)
155 {
156   char buf[PATH_MAX * 2], arch_path[PATH_MAX];
157   char *nto_root, *endian;
158   const char *arch;
159
160   nto_root = nto_target ();
161   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
162     {
163       arch = "x86";
164       endian = "";
165     }
166   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
167                    "rs6000") == 0
168            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
169                    "powerpc") == 0)
170     {
171       arch = "ppc";
172       endian = "be";
173     }
174   else
175     {
176       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
177       endian = gdbarch_byte_order (target_gdbarch)
178                == BFD_ENDIAN_BIG ? "be" : "le";
179     }
180
181   sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
182
183   sprintf (buf, "set solib-absolute-prefix %s", arch_path);
184   execute_command (buf, 0);
185 }
186
187 char **
188 nto_parse_redirection (char *pargv[], const char **pin, const char **pout, 
189                        const char **perr)
190 {
191   char **argv;
192   char *in, *out, *err, *p;
193   int argc, i, n;
194
195   for (n = 0; pargv[n]; n++);
196   if (n == 0)
197     return NULL;
198   in = "";
199   out = "";
200   err = "";
201
202   argv = xcalloc (n + 1, sizeof argv[0]);
203   argc = n;
204   for (i = 0, n = 0; n < argc; n++)
205     {
206       p = pargv[n];
207       if (*p == '>')
208         {
209           p++;
210           if (*p)
211             out = p;
212           else
213             out = pargv[++n];
214         }
215       else if (*p == '<')
216         {
217           p++;
218           if (*p)
219             in = p;
220           else
221             in = pargv[++n];
222         }
223       else if (*p++ == '2' && *p++ == '>')
224         {
225           if (*p == '&' && *(p + 1) == '1')
226             err = out;
227           else if (*p)
228             err = p;
229           else
230             err = pargv[++n];
231         }
232       else
233         argv[i++] = pargv[n];
234     }
235   *pin = in;
236   *pout = out;
237   *perr = err;
238   return argv;
239 }
240
241 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
242    solib-svr4.c to support nto_relocate_section_addresses
243    which is different from the svr4 version.  */
244
245 /* Link map info to include in an allocated so_list entry */
246
247 struct lm_info
248   {
249     /* Pointer to copy of link map from inferior.  The type is char *
250        rather than void *, so that we may use byte offsets to find the
251        various fields without the need for a cast.  */
252     gdb_byte *lm;
253
254     /* Amount by which addresses in the binary should be relocated to
255        match the inferior.  This could most often be taken directly
256        from lm, but when prelinking is involved and the prelink base
257        address changes, we may need a different offset, we want to
258        warn about the difference and compute it only once.  */
259     CORE_ADDR l_addr;
260
261     /* The target location of lm.  */
262     CORE_ADDR lm_addr;
263   };
264
265
266 static CORE_ADDR
267 LM_ADDR (struct so_list *so)
268 {
269   if (so->lm_info->l_addr == (CORE_ADDR)-1)
270     {
271       struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
272       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
273
274       so->lm_info->l_addr =
275         extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
276     }
277   return so->lm_info->l_addr;
278 }
279
280 static CORE_ADDR
281 nto_truncate_ptr (CORE_ADDR addr)
282 {
283   if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
284     /* We don't need to truncate anything, and the bit twiddling below
285        will fail due to overflow problems.  */
286     return addr;
287   else
288     return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
289 }
290
291 static Elf_Internal_Phdr *
292 find_load_phdr (bfd *abfd)
293 {
294   Elf_Internal_Phdr *phdr;
295   unsigned int i;
296
297   if (!elf_tdata (abfd))
298     return NULL;
299
300   phdr = elf_tdata (abfd)->phdr;
301   for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
302     {
303       if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
304         return phdr;
305     }
306   return NULL;
307 }
308
309 void
310 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
311 {
312   /* Neutrino treats the l_addr base address field in link.h as different than
313      the base address in the System V ABI and so the offset needs to be
314      calculated and applied to relocations.  */
315   Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
316   unsigned vaddr = phdr ? phdr->p_vaddr : 0;
317
318   sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
319   sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
320 }
321
322 /* This is cheating a bit because our linker code is in libc.so.  If we
323    ever implement lazy linking, this may need to be re-examined.  */
324 int
325 nto_in_dynsym_resolve_code (CORE_ADDR pc)
326 {
327   if (in_plt_section (pc, NULL))
328     return 1;
329   return 0;
330 }
331
332 void
333 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
334 {
335   /* Do nothing.  */
336 }
337
338 enum gdb_osabi
339 nto_elf_osabi_sniffer (bfd *abfd)
340 {
341   if (nto_is_nto_target)
342     return nto_is_nto_target (abfd);
343   return GDB_OSABI_UNKNOWN;
344 }
345
346 static const char *nto_thread_state_str[] =
347 {
348   "DEAD",               /* 0  0x00 */
349   "RUNNING",    /* 1  0x01 */
350   "READY",      /* 2  0x02 */
351   "STOPPED",    /* 3  0x03 */
352   "SEND",               /* 4  0x04 */
353   "RECEIVE",    /* 5  0x05 */
354   "REPLY",      /* 6  0x06 */
355   "STACK",      /* 7  0x07 */
356   "WAITTHREAD", /* 8  0x08 */
357   "WAITPAGE",   /* 9  0x09 */
358   "SIGSUSPEND", /* 10 0x0a */
359   "SIGWAITINFO",        /* 11 0x0b */
360   "NANOSLEEP",  /* 12 0x0c */
361   "MUTEX",      /* 13 0x0d */
362   "CONDVAR",    /* 14 0x0e */
363   "JOIN",               /* 15 0x0f */
364   "INTR",               /* 16 0x10 */
365   "SEM",                /* 17 0x11 */
366   "WAITCTX",    /* 18 0x12 */
367   "NET_SEND",   /* 19 0x13 */
368   "NET_REPLY"   /* 20 0x14 */
369 };
370
371 char *
372 nto_extra_thread_info (struct thread_info *ti)
373 {
374   if (ti && ti->private
375       && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
376     return (char *)nto_thread_state_str [ti->private->state];
377   return "";
378 }
379
380 void
381 nto_initialize_signals (void)
382 {
383   /* We use SIG45 for pulses, or something, so nostop, noprint
384      and pass them.  */
385   signal_stop_update (target_signal_from_name ("SIG45"), 0);
386   signal_print_update (target_signal_from_name ("SIG45"), 0);
387   signal_pass_update (target_signal_from_name ("SIG45"), 1);
388
389   /* By default we don't want to stop on these two, but we do want to pass.  */
390 #if defined(SIGSELECT)
391   signal_stop_update (SIGSELECT, 0);
392   signal_print_update (SIGSELECT, 0);
393   signal_pass_update (SIGSELECT, 1);
394 #endif
395
396 #if defined(SIGPHOTON)
397   signal_stop_update (SIGPHOTON, 0);
398   signal_print_update (SIGPHOTON, 0);
399   signal_pass_update (SIGPHOTON, 1);
400 #endif
401 }
402
403 /* Provide a prototype to silence -Wmissing-prototypes.  */
404 extern initialize_file_ftype _initialize_nto_tdep;
405
406 void
407 _initialize_nto_tdep (void)
408 {
409   add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
410                             &nto_internal_debugging, _("\
411 Set QNX NTO internal debugging."), _("\
412 Show QNX NTO internal debugging."), _("\
413 When non-zero, nto specific debug info is\n\
414 displayed. Different information is displayed\n\
415 for different positive values."),
416                             NULL,
417                             NULL, /* FIXME: i18n: QNX NTO internal
418                                      debugging is %s.  */
419                             &setdebuglist, &showdebuglist);
420 }