OSDN Git Service

* gc.h (gc_process_relocs): Call is_section_foldable_candidate to
[pf3gnuchains/pf3gnuchains3x.git] / gdb / nto-tdep.c
1 /* nto-tdep.c - general QNX Neutrino target functionality.
2
3    Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
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 "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
96
97   nto_root = nto_target ();
98   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
99     {
100       arch = "x86";
101       endian = "";
102     }
103   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
104                    "rs6000") == 0
105            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
106                    "powerpc") == 0)
107     {
108       arch = "ppc";
109       endian = "be";
110     }
111   else
112     {
113       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
114       endian = gdbarch_byte_order (target_gdbarch)
115                == BFD_ENDIAN_BIG ? "be" : "le";
116     }
117
118   /* In case nto_root is short, add strlen(solib)
119      so we can reuse arch_path below.  */
120   arch_path =
121     alloca (strlen (nto_root) + strlen (arch) + strlen (endian) + 2 +
122             strlen (solib));
123   sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
124
125   buf = alloca (strlen (PATH_FMT) + strlen (arch_path) * 5 + 1);
126   sprintf (buf, PATH_FMT, arch_path, arch_path, arch_path, arch_path,
127            arch_path);
128
129   /* Don't assume basename() isn't destructive.  */
130   base = strrchr (solib, '/');
131   if (!base)
132     base = solib;
133   else
134     base++;                     /* Skip over '/'.  */
135
136   ret = openp (buf, 1, base, o_flags, temp_pathname);
137   if (ret < 0 && base != solib)
138     {
139       sprintf (arch_path, "/%s", solib);
140       ret = open (arch_path, o_flags, 0);
141       if (temp_pathname)
142         {
143           if (ret >= 0)
144             *temp_pathname = gdb_realpath (arch_path);
145           else
146             **temp_pathname = '\0';
147         }
148     }
149   return ret;
150 }
151
152 void
153 nto_init_solib_absolute_prefix (void)
154 {
155   char buf[PATH_MAX * 2], arch_path[PATH_MAX];
156   char *nto_root, *endian;
157   const char *arch;
158
159   nto_root = nto_target ();
160   if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name, "i386") == 0)
161     {
162       arch = "x86";
163       endian = "";
164     }
165   else if (strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
166                    "rs6000") == 0
167            || strcmp (gdbarch_bfd_arch_info (target_gdbarch)->arch_name,
168                    "powerpc") == 0)
169     {
170       arch = "ppc";
171       endian = "be";
172     }
173   else
174     {
175       arch = gdbarch_bfd_arch_info (target_gdbarch)->arch_name;
176       endian = gdbarch_byte_order (target_gdbarch)
177                == BFD_ENDIAN_BIG ? "be" : "le";
178     }
179
180   sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
181
182   sprintf (buf, "set solib-absolute-prefix %s", arch_path);
183   execute_command (buf, 0);
184 }
185
186 char **
187 nto_parse_redirection (char *pargv[], const char **pin, const char **pout, 
188                        const char **perr)
189 {
190   char **argv;
191   char *in, *out, *err, *p;
192   int argc, i, n;
193
194   for (n = 0; pargv[n]; n++);
195   if (n == 0)
196     return NULL;
197   in = "";
198   out = "";
199   err = "";
200
201   argv = xcalloc (n + 1, sizeof argv[0]);
202   argc = n;
203   for (i = 0, n = 0; n < argc; n++)
204     {
205       p = pargv[n];
206       if (*p == '>')
207         {
208           p++;
209           if (*p)
210             out = p;
211           else
212             out = pargv[++n];
213         }
214       else if (*p == '<')
215         {
216           p++;
217           if (*p)
218             in = p;
219           else
220             in = pargv[++n];
221         }
222       else if (*p++ == '2' && *p++ == '>')
223         {
224           if (*p == '&' && *(p + 1) == '1')
225             err = out;
226           else if (*p)
227             err = p;
228           else
229             err = pargv[++n];
230         }
231       else
232         argv[i++] = pargv[n];
233     }
234   *pin = in;
235   *pout = out;
236   *perr = err;
237   return argv;
238 }
239
240 /* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
241    solib-svr4.c to support nto_relocate_section_addresses
242    which is different from the svr4 version.  */
243
244 /* Link map info to include in an allocated so_list entry */
245
246 struct lm_info
247   {
248     /* Pointer to copy of link map from inferior.  The type is char *
249        rather than void *, so that we may use byte offsets to find the
250        various fields without the need for a cast.  */
251     gdb_byte *lm;
252
253     /* Amount by which addresses in the binary should be relocated to
254        match the inferior.  This could most often be taken directly
255        from lm, but when prelinking is involved and the prelink base
256        address changes, we may need a different offset, we want to
257        warn about the difference and compute it only once.  */
258     CORE_ADDR l_addr;
259
260     /* The target location of lm.  */
261     CORE_ADDR lm_addr;
262   };
263
264
265 static CORE_ADDR
266 LM_ADDR (struct so_list *so)
267 {
268   if (so->lm_info->l_addr == (CORE_ADDR)-1)
269     {
270       struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
271       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
272
273       so->lm_info->l_addr =
274         extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, ptr_type);
275     }
276   return so->lm_info->l_addr;
277 }
278
279 static CORE_ADDR
280 nto_truncate_ptr (CORE_ADDR addr)
281 {
282   if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8)
283     /* We don't need to truncate anything, and the bit twiddling below
284        will fail due to overflow problems.  */
285     return addr;
286   else
287     return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1);
288 }
289
290 static Elf_Internal_Phdr *
291 find_load_phdr (bfd *abfd)
292 {
293   Elf_Internal_Phdr *phdr;
294   unsigned int i;
295
296   if (!elf_tdata (abfd))
297     return NULL;
298
299   phdr = elf_tdata (abfd)->phdr;
300   for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
301     {
302       if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
303         return phdr;
304     }
305   return NULL;
306 }
307
308 void
309 nto_relocate_section_addresses (struct so_list *so, struct target_section *sec)
310 {
311   /* Neutrino treats the l_addr base address field in link.h as different than
312      the base address in the System V ABI and so the offset needs to be
313      calculated and applied to relocations.  */
314   Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
315   unsigned vaddr = phdr ? phdr->p_vaddr : 0;
316
317   sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
318   sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
319 }
320
321 /* This is cheating a bit because our linker code is in libc.so.  If we
322    ever implement lazy linking, this may need to be re-examined.  */
323 int
324 nto_in_dynsym_resolve_code (CORE_ADDR pc)
325 {
326   if (in_plt_section (pc, NULL))
327     return 1;
328   return 0;
329 }
330
331 void
332 nto_dummy_supply_regset (struct regcache *regcache, char *regs)
333 {
334   /* Do nothing.  */
335 }
336
337 enum gdb_osabi
338 nto_elf_osabi_sniffer (bfd *abfd)
339 {
340   if (nto_is_nto_target)
341     return nto_is_nto_target (abfd);
342   return GDB_OSABI_UNKNOWN;
343 }
344
345 static const char *nto_thread_state_str[] =
346 {
347   "DEAD",               /* 0  0x00 */
348   "RUNNING",    /* 1  0x01 */
349   "READY",      /* 2  0x02 */
350   "STOPPED",    /* 3  0x03 */
351   "SEND",               /* 4  0x04 */
352   "RECEIVE",    /* 5  0x05 */
353   "REPLY",      /* 6  0x06 */
354   "STACK",      /* 7  0x07 */
355   "WAITTHREAD", /* 8  0x08 */
356   "WAITPAGE",   /* 9  0x09 */
357   "SIGSUSPEND", /* 10 0x0a */
358   "SIGWAITINFO",        /* 11 0x0b */
359   "NANOSLEEP",  /* 12 0x0c */
360   "MUTEX",      /* 13 0x0d */
361   "CONDVAR",    /* 14 0x0e */
362   "JOIN",               /* 15 0x0f */
363   "INTR",               /* 16 0x10 */
364   "SEM",                /* 17 0x11 */
365   "WAITCTX",    /* 18 0x12 */
366   "NET_SEND",   /* 19 0x13 */
367   "NET_REPLY"   /* 20 0x14 */
368 };
369
370 char *
371 nto_extra_thread_info (struct thread_info *ti)
372 {
373   if (ti && ti->private
374       && ti->private->state < ARRAY_SIZE (nto_thread_state_str))
375     return (char *)nto_thread_state_str [ti->private->state];
376   return "";
377 }
378
379 void
380 nto_initialize_signals (void)
381 {
382   /* We use SIG45 for pulses, or something, so nostop, noprint
383      and pass them.  */
384   signal_stop_update (target_signal_from_name ("SIG45"), 0);
385   signal_print_update (target_signal_from_name ("SIG45"), 0);
386   signal_pass_update (target_signal_from_name ("SIG45"), 1);
387
388   /* By default we don't want to stop on these two, but we do want to pass.  */
389 #if defined(SIGSELECT)
390   signal_stop_update (SIGSELECT, 0);
391   signal_print_update (SIGSELECT, 0);
392   signal_pass_update (SIGSELECT, 1);
393 #endif
394
395 #if defined(SIGPHOTON)
396   signal_stop_update (SIGPHOTON, 0);
397   signal_print_update (SIGPHOTON, 0);
398   signal_pass_update (SIGPHOTON, 1);
399 #endif
400 }
401
402 /* Provide a prototype to silence -Wmissing-prototypes.  */
403 extern initialize_file_ftype _initialize_nto_tdep;
404
405 void
406 _initialize_nto_tdep (void)
407 {
408   add_setshow_zinteger_cmd ("nto-debug", class_maintenance,
409                             &nto_internal_debugging, _("\
410 Set QNX NTO internal debugging."), _("\
411 Show QNX NTO internal debugging."), _("\
412 When non-zero, nto specific debug info is\n\
413 displayed. Different information is displayed\n\
414 for different positive values."),
415                             NULL,
416                             NULL, /* FIXME: i18n: QNX NTO internal debugging is %s.  */
417                             &setdebuglist, &showdebuglist);
418 }