1130803Smarcel/* nto-tdep.c - general QNX Neutrino target functionality. 2130803Smarcel 3130803Smarcel Copyright 2003 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel Contributed by QNX Software Systems Ltd. 6130803Smarcel 7130803Smarcel This file is part of GDB. 8130803Smarcel 9130803Smarcel This program is free software; you can redistribute it and/or modify 10130803Smarcel it under the terms of the GNU General Public License as published by 11130803Smarcel the Free Software Foundation; either version 2 of the License, or 12130803Smarcel (at your option) any later version. 13130803Smarcel 14130803Smarcel This program is distributed in the hope that it will be useful, 15130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 16130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17130803Smarcel GNU General Public License for more details. 18130803Smarcel 19130803Smarcel You should have received a copy of the GNU General Public License 20130803Smarcel along with this program; if not, write to the Free Software 21130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 22130803Smarcel Boston, MA 02111-1307, USA. */ 23130803Smarcel 24130803Smarcel#include "gdb_stat.h" 25130803Smarcel#include "gdb_string.h" 26130803Smarcel#include "nto-tdep.h" 27130803Smarcel#include "top.h" 28130803Smarcel#include "cli/cli-decode.h" 29130803Smarcel#include "cli/cli-cmds.h" 30130803Smarcel#include "inferior.h" 31130803Smarcel#include "gdbarch.h" 32130803Smarcel#include "bfd.h" 33130803Smarcel#include "elf-bfd.h" 34130803Smarcel#include "solib-svr4.h" 35130803Smarcel#include "gdbcore.h" 36130803Smarcel 37130803Smarcel#ifdef __CYGWIN__ 38130803Smarcel#include <sys/cygwin.h> 39130803Smarcel#endif 40130803Smarcel 41130803Smarcel#ifdef __CYGWIN__ 42130803Smarcelstatic char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6"; 43130803Smarcel#elif defined(__sun__) || defined(linux) 44130803Smarcelstatic char default_nto_target[] = "/opt/QNXsdk/target/qnx6"; 45130803Smarcel#else 46130803Smarcelstatic char default_nto_target[] = ""; 47130803Smarcel#endif 48130803Smarcel 49130803Smarcelstruct nto_target_ops current_nto_target; 50130803Smarcel 51130803Smarcelstatic char * 52130803Smarcelnto_target (void) 53130803Smarcel{ 54130803Smarcel char *p = getenv ("QNX_TARGET"); 55130803Smarcel 56130803Smarcel#ifdef __CYGWIN__ 57130803Smarcel static char buf[PATH_MAX]; 58130803Smarcel if (p) 59130803Smarcel cygwin_conv_to_posix_path (p, buf); 60130803Smarcel else 61130803Smarcel cygwin_conv_to_posix_path (default_nto_target, buf); 62130803Smarcel return buf; 63130803Smarcel#else 64130803Smarcel return p ? p : default_nto_target; 65130803Smarcel#endif 66130803Smarcel} 67130803Smarcel 68130803Smarcel/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86, 69130803Smarcel CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h. */ 70130803Smarcelint 71130803Smarcelnto_map_arch_to_cputype (const char *arch) 72130803Smarcel{ 73130803Smarcel if (!strcmp (arch, "i386") || !strcmp (arch, "x86")) 74130803Smarcel return CPUTYPE_X86; 75130803Smarcel if (!strcmp (arch, "rs6000") || !strcmp (arch, "powerpc")) 76130803Smarcel return CPUTYPE_PPC; 77130803Smarcel if (!strcmp (arch, "mips")) 78130803Smarcel return CPUTYPE_MIPS; 79130803Smarcel if (!strcmp (arch, "arm")) 80130803Smarcel return CPUTYPE_ARM; 81130803Smarcel if (!strcmp (arch, "sh")) 82130803Smarcel return CPUTYPE_SH; 83130803Smarcel return CPUTYPE_UNKNOWN; 84130803Smarcel} 85130803Smarcel 86130803Smarcelint 87130803Smarcelnto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname) 88130803Smarcel{ 89130803Smarcel char *buf, arch_path[PATH_MAX], *nto_root, *endian; 90130803Smarcel const char *arch; 91130803Smarcel char *path_fmt = "%s/lib:%s/usr/lib:%s/usr/photon/lib\ 92130803Smarcel:%s/usr/photon/dll:%s/lib/dll"; 93130803Smarcel 94130803Smarcel nto_root = nto_target (); 95130803Smarcel if (strcmp (TARGET_ARCHITECTURE->arch_name, "i386") == 0) 96130803Smarcel { 97130803Smarcel arch = "x86"; 98130803Smarcel endian = ""; 99130803Smarcel } 100130803Smarcel else if (strcmp (TARGET_ARCHITECTURE->arch_name, "rs6000") == 0 101130803Smarcel || strcmp (TARGET_ARCHITECTURE->arch_name, "powerpc") == 0) 102130803Smarcel { 103130803Smarcel arch = "ppc"; 104130803Smarcel endian = "be"; 105130803Smarcel } 106130803Smarcel else 107130803Smarcel { 108130803Smarcel arch = TARGET_ARCHITECTURE->arch_name; 109130803Smarcel endian = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "be" : "le"; 110130803Smarcel } 111130803Smarcel 112130803Smarcel sprintf (arch_path, "%s/%s%s", nto_root, arch, endian); 113130803Smarcel 114130803Smarcel buf = alloca (strlen (path_fmt) + strlen (arch_path) * 5 + 1); 115130803Smarcel sprintf (buf, path_fmt, arch_path, arch_path, arch_path, arch_path, 116130803Smarcel arch_path); 117130803Smarcel 118130803Smarcel return openp (buf, 1, solib, o_flags, 0, temp_pathname); 119130803Smarcel} 120130803Smarcel 121130803Smarcelvoid 122130803Smarcelnto_init_solib_absolute_prefix (void) 123130803Smarcel{ 124130803Smarcel char buf[PATH_MAX * 2], arch_path[PATH_MAX]; 125130803Smarcel char *nto_root, *endian; 126130803Smarcel const char *arch; 127130803Smarcel 128130803Smarcel nto_root = nto_target (); 129130803Smarcel if (strcmp (TARGET_ARCHITECTURE->arch_name, "i386") == 0) 130130803Smarcel { 131130803Smarcel arch = "x86"; 132130803Smarcel endian = ""; 133130803Smarcel } 134130803Smarcel else if (strcmp (TARGET_ARCHITECTURE->arch_name, "rs6000") == 0 135130803Smarcel || strcmp (TARGET_ARCHITECTURE->arch_name, "powerpc") == 0) 136130803Smarcel { 137130803Smarcel arch = "ppc"; 138130803Smarcel endian = "be"; 139130803Smarcel } 140130803Smarcel else 141130803Smarcel { 142130803Smarcel arch = TARGET_ARCHITECTURE->arch_name; 143130803Smarcel endian = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "be" : "le"; 144130803Smarcel } 145130803Smarcel 146130803Smarcel sprintf (arch_path, "%s/%s%s", nto_root, arch, endian); 147130803Smarcel 148130803Smarcel sprintf (buf, "set solib-absolute-prefix %s", arch_path); 149130803Smarcel execute_command (buf, 0); 150130803Smarcel} 151130803Smarcel 152130803Smarcelchar ** 153130803Smarcelnto_parse_redirection (char *pargv[], char **pin, char **pout, char **perr) 154130803Smarcel{ 155130803Smarcel char **argv; 156130803Smarcel char *in, *out, *err, *p; 157130803Smarcel int argc, i, n; 158130803Smarcel 159130803Smarcel for (n = 0; pargv[n]; n++); 160130803Smarcel if (n == 0) 161130803Smarcel return NULL; 162130803Smarcel in = ""; 163130803Smarcel out = ""; 164130803Smarcel err = ""; 165130803Smarcel 166130803Smarcel argv = xcalloc (n + 1, sizeof argv[0]); 167130803Smarcel argc = n; 168130803Smarcel for (i = 0, n = 0; n < argc; n++) 169130803Smarcel { 170130803Smarcel p = pargv[n]; 171130803Smarcel if (*p == '>') 172130803Smarcel { 173130803Smarcel p++; 174130803Smarcel if (*p) 175130803Smarcel out = p; 176130803Smarcel else 177130803Smarcel out = pargv[++n]; 178130803Smarcel } 179130803Smarcel else if (*p == '<') 180130803Smarcel { 181130803Smarcel p++; 182130803Smarcel if (*p) 183130803Smarcel in = p; 184130803Smarcel else 185130803Smarcel in = pargv[++n]; 186130803Smarcel } 187130803Smarcel else if (*p++ == '2' && *p++ == '>') 188130803Smarcel { 189130803Smarcel if (*p == '&' && *(p + 1) == '1') 190130803Smarcel err = out; 191130803Smarcel else if (*p) 192130803Smarcel err = p; 193130803Smarcel else 194130803Smarcel err = pargv[++n]; 195130803Smarcel } 196130803Smarcel else 197130803Smarcel argv[i++] = pargv[n]; 198130803Smarcel } 199130803Smarcel *pin = in; 200130803Smarcel *pout = out; 201130803Smarcel *perr = err; 202130803Smarcel return argv; 203130803Smarcel} 204130803Smarcel 205130803Smarcel/* The struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from 206130803Smarcel solib-svr4.c to support nto_relocate_section_addresses 207130803Smarcel which is different from the svr4 version. */ 208130803Smarcel 209130803Smarcelstruct lm_info 210130803Smarcel{ 211130803Smarcel /* Pointer to copy of link map from inferior. The type is char * 212130803Smarcel rather than void *, so that we may use byte offsets to find the 213130803Smarcel various fields without the need for a cast. */ 214130803Smarcel char *lm; 215130803Smarcel}; 216130803Smarcel 217130803Smarcelstatic CORE_ADDR 218130803SmarcelLM_ADDR (struct so_list *so) 219130803Smarcel{ 220130803Smarcel struct link_map_offsets *lmo = nto_fetch_link_map_offsets (); 221130803Smarcel 222130803Smarcel return (CORE_ADDR) extract_signed_integer (so->lm_info->lm + 223130803Smarcel lmo->l_addr_offset, 224130803Smarcel lmo->l_addr_size); 225130803Smarcel} 226130803Smarcel 227130803Smarcelstatic CORE_ADDR 228130803Smarcelnto_truncate_ptr (CORE_ADDR addr) 229130803Smarcel{ 230130803Smarcel if (TARGET_PTR_BIT == sizeof (CORE_ADDR) * 8) 231130803Smarcel /* We don't need to truncate anything, and the bit twiddling below 232130803Smarcel will fail due to overflow problems. */ 233130803Smarcel return addr; 234130803Smarcel else 235130803Smarcel return addr & (((CORE_ADDR) 1 << TARGET_PTR_BIT) - 1); 236130803Smarcel} 237130803Smarcel 238130803SmarcelElf_Internal_Phdr * 239130803Smarcelfind_load_phdr (bfd *abfd) 240130803Smarcel{ 241130803Smarcel Elf_Internal_Phdr *phdr; 242130803Smarcel unsigned int i; 243130803Smarcel 244130803Smarcel if (!elf_tdata (abfd)) 245130803Smarcel return NULL; 246130803Smarcel 247130803Smarcel phdr = elf_tdata (abfd)->phdr; 248130803Smarcel for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) 249130803Smarcel { 250130803Smarcel if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) 251130803Smarcel return phdr; 252130803Smarcel } 253130803Smarcel return NULL; 254130803Smarcel} 255130803Smarcel 256130803Smarcelvoid 257130803Smarcelnto_relocate_section_addresses (struct so_list *so, struct section_table *sec) 258130803Smarcel{ 259130803Smarcel /* Neutrino treats the l_addr base address field in link.h as different than 260130803Smarcel the base address in the System V ABI and so the offset needs to be 261130803Smarcel calculated and applied to relocations. */ 262130803Smarcel Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd); 263130803Smarcel unsigned vaddr = phdr ? phdr->p_vaddr : 0; 264130803Smarcel 265130803Smarcel sec->addr = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr); 266130803Smarcel sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr); 267130803Smarcel} 268130803Smarcel 269130803Smarcelstatic void 270130803Smarcelfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, 271130803Smarcel int which, CORE_ADDR reg_addr) 272130803Smarcel{ 273130803Smarcel nto_regset_t regset; 274130803Smarcel 275130803Smarcel/* See corelow.c:get_core_registers for values of WHICH. */ 276130803Smarcel if (which == 0) 277130803Smarcel { 278130803Smarcel memcpy ((char *) ®set, core_reg_sect, 279130803Smarcel min (core_reg_size, sizeof (regset))); 280130803Smarcel nto_supply_gregset ((char *) ®set); 281130803Smarcel } 282130803Smarcel else if (which == 2) 283130803Smarcel { 284130803Smarcel memcpy ((char *) ®set, core_reg_sect, 285130803Smarcel min (core_reg_size, sizeof (regset))); 286130803Smarcel nto_supply_fpregset ((char *) ®set); 287130803Smarcel } 288130803Smarcel} 289130803Smarcel 290130803Smarcelvoid 291130803Smarcelnto_dummy_supply_regset (char *regs) 292130803Smarcel{ 293130803Smarcel /* Do nothing. */ 294130803Smarcel} 295130803Smarcel 296130803Smarcel/* Register that we are able to handle ELF file formats using standard 297130803Smarcel procfs "regset" structures. */ 298130803Smarcelstatic struct core_fns regset_core_fns = { 299130803Smarcel bfd_target_elf_flavour, /* core_flavour */ 300130803Smarcel default_check_format, /* check_format */ 301130803Smarcel default_core_sniffer, /* core_sniffer */ 302130803Smarcel fetch_core_registers, /* core_read_registers */ 303130803Smarcel NULL /* next */ 304130803Smarcel}; 305130803Smarcel 306130803Smarcelvoid 307130803Smarcel_initialize_nto_tdep (void) 308130803Smarcel{ 309130803Smarcel add_setshow_cmd ("nto-debug", class_maintenance, var_zinteger, 310130803Smarcel &nto_internal_debugging, "Set QNX NTO internal debugging.\n\ 311130803SmarcelWhen non-zero, nto specific debug info is\n\ 312130803Smarceldisplayed. Different information is displayed\n\ 313130803Smarcelfor different positive values.", "Show QNX NTO internal debugging.\n", 314130803Smarcel NULL, NULL, &setdebuglist, &showdebuglist); 315130803Smarcel 316130803Smarcel /* We use SIG45 for pulses, or something, so nostop, noprint 317130803Smarcel and pass them. */ 318130803Smarcel signal_stop_update (target_signal_from_name ("SIG45"), 0); 319130803Smarcel signal_print_update (target_signal_from_name ("SIG45"), 0); 320130803Smarcel signal_pass_update (target_signal_from_name ("SIG45"), 1); 321130803Smarcel 322130803Smarcel /* By default we don't want to stop on these two, but we do want to pass. */ 323130803Smarcel#if defined(SIGSELECT) 324130803Smarcel signal_stop_update (SIGSELECT, 0); 325130803Smarcel signal_print_update (SIGSELECT, 0); 326130803Smarcel signal_pass_update (SIGSELECT, 1); 327130803Smarcel#endif 328130803Smarcel 329130803Smarcel#if defined(SIGPHOTON) 330130803Smarcel signal_stop_update (SIGPHOTON, 0); 331130803Smarcel signal_print_update (SIGPHOTON, 0); 332130803Smarcel signal_pass_update (SIGPHOTON, 1); 333130803Smarcel#endif 334130803Smarcel 335130803Smarcel /* Register core file support. */ 336130803Smarcel add_core_fns (®set_core_fns); 337130803Smarcel} 338