GDB (API)
|
00001 /* Target-dependent code for the IA-64 for GDB, the GNU debugger. 00002 00003 Copyright (C) 2010-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "ia64-tdep.h" 00022 #include "ia64-hpux-tdep.h" 00023 #include "osabi.h" 00024 #include "gdbtypes.h" 00025 #include "solib.h" 00026 #include "target.h" 00027 #include "frame.h" 00028 #include "regcache.h" 00029 #include "gdbcore.h" 00030 #include "inferior.h" 00031 00032 /* A sequence of instructions pushed on the stack when we want to perform 00033 an inferior function call. The main purpose of this code is to save 00034 the output region of the register frame belonging to the function 00035 from which we are making the call. Normally, all registers are saved 00036 prior to the call, but this does not include stacked registers because 00037 they are seen by GDB as pseudo registers. 00038 00039 With Linux kernels, these stacked registers can be saved by simply 00040 creating a new register frame, or in other words by moving the BSP. 00041 But the HP/UX kernel does not allow this. So we rely on this code 00042 instead, that makes functions calls whose only purpose is to create 00043 new register frames. 00044 00045 The array below is the result obtained after assembling the code 00046 shown below. It's an array of bytes in order to make it independent 00047 of the host endianess, in case it ends up being used on more than 00048 one target. 00049 00050 start: 00051 // Save b0 before using it (into preserved reg: r4). 00052 mov r4 = b0 00053 ;; 00054 00055 br.call.dptk.few b0 = stub# 00056 ;; 00057 00058 // Add a nop bundle where we can insert our dummy breakpoint. 00059 nop.m 0 00060 nop.i 0 00061 nop.i 0 00062 ;; 00063 00064 stub: 00065 // Alloc a new register stack frame. Here, we set the size 00066 // of all regions to zero. Eventually, GDB will manually 00067 // change the instruction to set the size of the local region 00068 // to match size of the output region of the function from 00069 // which we are making the function call. This is to protect 00070 // the value of the output registers of the function from 00071 // which we are making the call. 00072 alloc r6 = ar.pfs, 0, 0, 0, 0 00073 00074 // Save b0 before using it again (into preserved reg: r5). 00075 mov r5 = b0 00076 ;; 00077 00078 // Now that we have protected the entire output region of the 00079 // register stack frame, we can call our function that will 00080 // setup the arguments, and call our target function. 00081 br.call.dptk.few b0 = call_dummy# 00082 ;; 00083 00084 // Restore b0, ar.pfs, and return 00085 mov b0 = r5 00086 mov.i ar.pfs = r6 00087 ;; 00088 br.ret.dptk.few b0 00089 ;; 00090 00091 call_dummy: 00092 // Alloc a new frame, with 2 local registers, and 8 output registers 00093 // (8 output registers for the maximum of 8 slots passed by register). 00094 alloc r32 = ar.pfs, 2, 0, 8, 0 00095 00096 // Save b0 before using it to call our target function. 00097 mov r33 = b0 00098 00099 // Load the argument values placed by GDB inside r14-r21 in their 00100 // proper registers. 00101 or r34 = r14, r0 00102 or r35 = r15, r0 00103 or r36 = r16, r0 00104 or r37 = r17, r0 00105 or r38 = r18, r0 00106 or r39 = r19, r0 00107 or r40 = r20, r0 00108 or r41 = r21, r0 00109 ;; 00110 00111 // actual call 00112 br.call.dptk.few b0 = b1 00113 ;; 00114 00115 mov.i ar.pfs=r32 00116 mov b0=r33 00117 ;; 00118 00119 br.ret.dptk.few b0 00120 ;; 00121 00122 */ 00123 00124 static const gdb_byte ia64_hpux_dummy_code[] = 00125 { 00126 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 00127 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 00128 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00129 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x52, 00130 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00131 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 00132 0x02, 0x30, 0x00, 0x00, 0x80, 0x05, 0x50, 0x00, 00133 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 00134 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00135 0x00, 0x02, 0x00, 0x00, 0x30, 0x00, 0x00, 0x52, 00136 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28, 00137 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0xaa, 0x00, 00138 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00139 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02, 00140 0x00, 0x00, 0x29, 0x04, 0x80, 0x05, 0x10, 0x02, 00141 0x00, 0x62, 0x00, 0x40, 0xe4, 0x00, 0x38, 0x80, 00142 0x00, 0x18, 0x3d, 0x00, 0x0e, 0x20, 0x40, 0x82, 00143 0x00, 0x1c, 0x40, 0xa0, 0x14, 0x01, 0x38, 0x80, 00144 0x00, 0x30, 0x49, 0x00, 0x0e, 0x20, 0x70, 0x9a, 00145 0x00, 0x1c, 0x40, 0x00, 0x45, 0x01, 0x38, 0x80, 00146 0x0a, 0x48, 0x55, 0x00, 0x0e, 0x20, 0x00, 0x00, 00147 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 00148 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00149 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x12, 00150 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00151 0x01, 0x55, 0x00, 0x00, 0x10, 0x0a, 0x00, 0x07, 00152 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 00153 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02 00154 }; 00155 00156 /* The offset to be used in order to get the __reason pseudo-register 00157 when using one of the *UREGS ttrace requests (see system header file 00158 /usr/include/ia64/sys/uregs.h for more details). 00159 00160 The documentation for this pseudo-register says that a nonzero value 00161 indicates that the thread stopped due to a fault, trap, or interrupt. 00162 A null value indicates a stop inside a syscall. */ 00163 #define IA64_HPUX_UREG_REASON 0x00070000 00164 00165 /* Return nonzero if the value of the register identified by REGNUM 00166 can be modified. */ 00167 00168 static int 00169 ia64_hpux_can_store_ar_register (int regnum) 00170 { 00171 switch (regnum) 00172 { 00173 case IA64_RSC_REGNUM: 00174 case IA64_RNAT_REGNUM: 00175 case IA64_CSD_REGNUM: 00176 case IA64_SSD_REGNUM: 00177 case IA64_CCV_REGNUM: 00178 case IA64_UNAT_REGNUM: 00179 case IA64_FPSR_REGNUM: 00180 case IA64_PFS_REGNUM: 00181 case IA64_LC_REGNUM: 00182 case IA64_EC_REGNUM: 00183 return 1; 00184 break; 00185 00186 default: 00187 return 0; 00188 break; 00189 } 00190 } 00191 00192 /* The "cannot_store_register" target_ops method. */ 00193 00194 static int 00195 ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum) 00196 { 00197 /* General registers. */ 00198 00199 if (regnum == IA64_GR0_REGNUM) 00200 return 1; 00201 00202 /* FP register. */ 00203 00204 if (regnum == IA64_FR0_REGNUM || regnum == IA64_FR1_REGNUM) 00205 return 1; 00206 00207 /* Application registers. */ 00208 if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_AR0_REGNUM + 127) 00209 return (!ia64_hpux_can_store_ar_register (regnum)); 00210 00211 /* We can store all other registers. */ 00212 return 0; 00213 } 00214 00215 /* Return nonzero if the inferior is stopped inside a system call. */ 00216 00217 static int 00218 ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch) 00219 { 00220 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00221 struct target_ops *ops = ¤t_target; 00222 gdb_byte buf[8]; 00223 int len; 00224 00225 len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL, 00226 buf, IA64_HPUX_UREG_REASON, sizeof (buf)); 00227 if (len == -1) 00228 /* The target wasn't able to tell us. Assume we are not stopped 00229 in a system call, which is the normal situation. */ 00230 return 0; 00231 gdb_assert (len == 8); 00232 00233 return (extract_unsigned_integer (buf, len, byte_order) == 0); 00234 } 00235 00236 /* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux. */ 00237 00238 static int 00239 ia64_hpux_size_of_register_frame (struct frame_info *this_frame, 00240 ULONGEST cfm) 00241 { 00242 int sof; 00243 00244 if (frame_relative_level (this_frame) == 0 00245 && ia64_hpux_stopped_in_syscall (get_frame_arch (this_frame))) 00246 /* If the inferior stopped in a system call, the base address 00247 of the register frame is at BSP - SOL instead of BSP - SOF. 00248 This is an HP-UX exception. */ 00249 sof = (cfm & 0x3f80) >> 7; 00250 else 00251 sof = (cfm & 0x7f); 00252 00253 return sof; 00254 } 00255 00256 /* Implement the push_dummy_code gdbarch method. 00257 00258 This function assumes that the SP is already 16-byte-aligned. */ 00259 00260 static CORE_ADDR 00261 ia64_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, 00262 CORE_ADDR funaddr, struct value **args, int nargs, 00263 struct type *value_type, CORE_ADDR *real_pc, 00264 CORE_ADDR *bp_addr, struct regcache *regcache) 00265 { 00266 ULONGEST cfm; 00267 int sof, sol, sor, soo; 00268 gdb_byte buf[16]; 00269 00270 regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); 00271 sof = cfm & 0x7f; 00272 sol = (cfm >> 7) & 0x7f; 00273 sor = (cfm >> 14) & 0xf; 00274 soo = sof - sol - sor; 00275 00276 /* Reserve some space on the stack to hold the dummy code. */ 00277 sp = sp - sizeof (ia64_hpux_dummy_code); 00278 00279 /* Set the breakpoint address at the first instruction of the bundle 00280 in the dummy code that has only nops. This is where the dummy code 00281 expects us to break. */ 00282 *bp_addr = sp + 0x20; 00283 00284 /* Start the inferior function call from the dummy code. The dummy 00285 code will then call our function. */ 00286 *real_pc = sp; 00287 00288 /* Transfer the dummy code to the inferior. */ 00289 write_memory (sp, ia64_hpux_dummy_code, sizeof (ia64_hpux_dummy_code)); 00290 00291 /* Update the size of the local portion of the register frame allocated 00292 by ``stub'' to match the size of the output region of the current 00293 register frame. This allows us to save the stacked registers. 00294 00295 The "alloc" instruction is located at slot 0 of the bundle at +0x30. 00296 Update the "sof" and "sol" portion of that instruction which are 00297 respectively at bits 18-24 and 25-31 of the bundle. */ 00298 memcpy (buf, ia64_hpux_dummy_code + 0x30, sizeof (buf)); 00299 00300 buf[2] |= ((soo & 0x3f) << 2); 00301 buf[3] |= (soo << 1); 00302 if (soo > 63) 00303 buf[3] |= 1; 00304 00305 write_memory (sp + 0x30, buf, sizeof (buf)); 00306 00307 /* Return the new (already properly aligned) SP. */ 00308 return sp; 00309 } 00310 00311 /* The "allocate_new_rse_frame" ia64_infcall_ops routine for ia64-hpux. */ 00312 00313 static void 00314 ia64_hpux_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp, 00315 int sof) 00316 { 00317 /* We cannot change the value of the BSP register on HP-UX, 00318 so we can't allocate a new RSE frame. */ 00319 } 00320 00321 /* The "store_argument_in_slot" ia64_infcall_ops routine for ia64-hpux. */ 00322 00323 static void 00324 ia64_hpux_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp, 00325 int slotnum, gdb_byte *buf) 00326 { 00327 /* The call sequence on this target expects us to place the arguments 00328 inside r14 - r21. */ 00329 regcache_cooked_write (regcache, IA64_GR0_REGNUM + 14 + slotnum, buf); 00330 } 00331 00332 /* The "set_function_addr" ia64_infcall_ops routine for ia64-hpux. */ 00333 00334 static void 00335 ia64_hpux_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr) 00336 { 00337 /* The calling sequence calls the function whose address is placed 00338 in register b1. */ 00339 regcache_cooked_write_unsigned (regcache, IA64_BR1_REGNUM, func_addr); 00340 } 00341 00342 /* The ia64_infcall_ops structure for ia64-hpux. */ 00343 00344 static const struct ia64_infcall_ops ia64_hpux_infcall_ops = 00345 { 00346 ia64_hpux_allocate_new_rse_frame, 00347 ia64_hpux_store_argument_in_slot, 00348 ia64_hpux_set_function_addr 00349 }; 00350 00351 /* The "dummy_id" gdbarch routine for ia64-hpux. */ 00352 00353 static struct frame_id 00354 ia64_hpux_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) 00355 { 00356 CORE_ADDR sp, pc, bp_addr, bsp; 00357 00358 sp = get_frame_register_unsigned (this_frame, IA64_GR12_REGNUM); 00359 00360 /* Just double-check that the frame PC is within a certain region 00361 of the stack that would be plausible for our dummy code (the dummy 00362 code was pushed at SP + 16). If not, then return a null frame ID. 00363 This is necessary in our case, because it is possible to produce 00364 the same frame ID for a normal frame, if that frame corresponds 00365 to the function called by our dummy code, and the function has not 00366 modified the registers that we use to build the dummy frame ID. */ 00367 pc = get_frame_pc (this_frame); 00368 if (pc < sp + 16 || pc >= sp + 16 + sizeof (ia64_hpux_dummy_code)) 00369 return null_frame_id; 00370 00371 /* The call sequence is such that the address of the dummy breakpoint 00372 we inserted is stored in r5. */ 00373 bp_addr = get_frame_register_unsigned (this_frame, IA64_GR5_REGNUM); 00374 00375 bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); 00376 00377 return frame_id_build_special (sp, bp_addr, bsp); 00378 } 00379 00380 /* Should be set to non-NULL if the ia64-hpux solib module is linked in. 00381 This may not be the case because the shared library support code can 00382 only be compiled on ia64-hpux. */ 00383 00384 struct target_so_ops *ia64_hpux_so_ops = NULL; 00385 00386 /* The "find_global_pointer_from_solib" gdbarch_tdep routine for 00387 ia64-hpux. */ 00388 00389 static CORE_ADDR 00390 ia64_hpux_find_global_pointer_from_solib (struct gdbarch *gdbarch, 00391 CORE_ADDR faddr) 00392 { 00393 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00394 struct target_ops *ops = ¤t_target; 00395 gdb_byte buf[8]; 00396 LONGEST len; 00397 00398 len = target_read (ops, TARGET_OBJECT_HPUX_SOLIB_GOT, 00399 paddress (gdbarch, faddr), buf, 0, sizeof (buf)); 00400 00401 return extract_unsigned_integer (buf, len, byte_order); 00402 } 00403 00404 static void 00405 ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00406 { 00407 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00408 00409 tdep->size_of_register_frame = ia64_hpux_size_of_register_frame; 00410 00411 set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); 00412 set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register); 00413 00414 /* Inferior functions must be called from stack. */ 00415 set_gdbarch_call_dummy_location (gdbarch, ON_STACK); 00416 set_gdbarch_push_dummy_code (gdbarch, ia64_hpux_push_dummy_code); 00417 tdep->infcall_ops = ia64_hpux_infcall_ops; 00418 tdep->find_global_pointer_from_solib 00419 = ia64_hpux_find_global_pointer_from_solib; 00420 set_gdbarch_dummy_id (gdbarch, ia64_hpux_dummy_id); 00421 00422 if (ia64_hpux_so_ops) 00423 set_solib_ops (gdbarch, ia64_hpux_so_ops); 00424 } 00425 00426 /* Provide a prototype to silence -Wmissing-prototypes. */ 00427 extern initialize_file_ftype _initialize_ia64_hpux_tdep; 00428 00429 void 00430 _initialize_ia64_hpux_tdep (void) 00431 { 00432 gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_HPUX_ELF, 00433 ia64_hpux_init_abi); 00434 }