static int amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR *unwind_info, CORE_ADDR *image_base, CORE_ADDR *start_rva, CORE_ADDR *end_rva) { struct obj_section *sec; pe_data_type *pe; IMAGE_DATA_DIRECTORY *dir; struct objfile *objfile; unsigned long lo, hi; CORE_ADDR base; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* Get the corresponding exception directory. */ sec = find_pc_section (pc); if (sec == NULL) return -1; objfile = sec->objfile; pe = pe_data (sec->objfile->obfd); dir = &pe->pe_opthdr.DataDirectory[PE_EXCEPTION_TABLE]; base = pe->pe_opthdr.ImageBase + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); *image_base = base; /* Find the entry. Note: This does not handle dynamically added entries (for JIT engines). For this, we would need to ask the kernel directly, which means getting some info from the native layer. For the rest of the code, however, it's probably faster to search the entry ourselves. */ lo = 0; hi = dir->Size / sizeof (struct external_pex64_runtime_function); *unwind_info = 0; while (lo <= hi) { unsigned long mid = lo + (hi - lo) / 2; struct external_pex64_runtime_function d; CORE_ADDR sa, ea; if (target_read_memory (base + dir->VirtualAddress + mid * sizeof (d), (gdb_byte *) &d, sizeof (d)) != 0) return -1; sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); if (pc < base + sa) hi = mid - 1; else if (pc >= base + ea) lo = mid + 1; else if (pc >= base + sa && pc < base + ea) { /* Got it. */ *start_rva = sa; *end_rva = ea; *unwind_info = extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); break; } else break; } if (frame_debug) fprintf_unfiltered (gdb_stdlog, "amd64_windows_find_unwind_data: image_base=%s, unwind_data=%s\n", paddress (gdbarch, base), paddress (gdbarch, *unwind_info)); if (*unwind_info & 1) { /* Unofficially documented unwind info redirection, when UNWIND_INFO address is odd (http://www.codemachine.com/article_x64deepdive.html). */ struct external_pex64_runtime_function d; CORE_ADDR sa, ea; if (target_read_memory (base + (*unwind_info & ~1), (gdb_byte *) &d, sizeof (d)) != 0) return -1; *start_rva = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); *end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); *unwind_info = extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); } return 0; }
static void store_register (struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); int addr[MAX_REGISTER_SIZE]; int nr, isfloat; /* Fetch the register's value from the register cache. */ regcache_raw_collect (regcache, regno, addr); /* -1 can be a successful return value, so infer errors from errno. */ errno = 0; nr = regmap (gdbarch, regno, &isfloat); /* Floating-point registers. */ if (isfloat) rs6000_ptrace32 (PT_WRITE_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0); /* Bogus register number. */ else if (nr < 0) { if (regno >= gdbarch_num_regs (gdbarch)) fprintf_unfiltered (gdb_stderr, "gdb error: register no %d not implemented.\n", regno); } /* Fixed-point registers. */ else { if (regno == gdbarch_sp_regnum (gdbarch)) /* Execute one dummy instruction (which is a breakpoint) in inferior process to give kernel a chance to do internal housekeeping. Otherwise the following ptrace(2) calls will mess up user stack since kernel will get confused about the bottom of the stack (%sp). */ exec_one_dummy_insn (regcache); /* The PT_WRITE_GPR operation is rather odd. For 32-bit inferiors, the register's value is passed by value, but for 64-bit inferiors, the address of a buffer containing the value is passed. */ if (!ARCH64 ()) rs6000_ptrace32 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid), (int *) nr, *addr, 0); else { /* PT_WRITE_GPR requires the buffer parameter to point to an 8-byte area, even if the register is really only 32 bits. */ long long buf; if (register_size (gdbarch, regno) == 8) memcpy (&buf, addr, 8); else buf = *addr; rs6000_ptrace64 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid), nr, 0, &buf); } } if (errno) { perror (_("ptrace write")); errno = 0; } }
static void amd64_windows_frame_decode_insns (struct frame_info *this_frame, struct amd64_windows_frame_cache *cache, CORE_ADDR unwind_info) { CORE_ADDR save_addr = 0; CORE_ADDR cur_sp = cache->sp; struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int j; for (j = 0; ; j++) { struct external_pex64_unwind_info ex_ui; /* There are at most 256 16-bit unwind insns. */ gdb_byte insns[2 * 256]; gdb_byte *p; gdb_byte *end_insns; unsigned char codes_count; unsigned char frame_reg; unsigned char frame_off; /* Read and decode header. */ if (target_read_memory (cache->image_base + unwind_info, (gdb_byte *) &ex_ui, sizeof (ex_ui)) != 0) return; if (frame_debug) fprintf_unfiltered (gdb_stdlog, "amd64_windows_frame_decodes_insn: " "%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x\n", paddress (gdbarch, unwind_info), ex_ui.Version_Flags, ex_ui.SizeOfPrologue, ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset); /* Check version. */ if (PEX64_UWI_VERSION (ex_ui.Version_Flags) != 1 && PEX64_UWI_VERSION (ex_ui.Version_Flags) != 2) return; if (j == 0 && (cache->pc >= cache->image_base + cache->start_rva + ex_ui.SizeOfPrologue)) { /* Not in the prologue. We want to detect if the PC points to an epilogue. If so, the epilogue detection+decoding function is sufficient. Otherwise, the unwinder will consider that the PC is in the body of the function and will need to decode unwind info. */ if (amd64_windows_frame_decode_epilogue (this_frame, cache) == 1) return; /* Not in an epilog. Clear possible side effects. */ memset (cache->prev_reg_addr, 0, sizeof (cache->prev_reg_addr)); } codes_count = ex_ui.CountOfCodes; frame_reg = PEX64_UWI_FRAMEREG (ex_ui.FrameRegisterOffset); if (frame_reg != 0) { /* According to msdn: If an FP reg is used, then any unwind code taking an offset must only be used after the FP reg is established in the prolog. */ gdb_byte buf[8]; int frreg = amd64_windows_w2gdb_regnum[frame_reg]; get_frame_register (this_frame, frreg, buf); save_addr = extract_unsigned_integer (buf, 8, byte_order); if (frame_debug) fprintf_unfiltered (gdb_stdlog, " frame_reg=%s, val=%s\n", gdbarch_register_name (gdbarch, frreg), paddress (gdbarch, save_addr)); } /* Read opcodes. */ if (codes_count != 0 && target_read_memory (cache->image_base + unwind_info + sizeof (ex_ui), insns, codes_count * 2) != 0) return; end_insns = &insns[codes_count * 2]; p = insns; /* Skip opcodes 6 of version 2. This opcode is not documented. */ if (PEX64_UWI_VERSION (ex_ui.Version_Flags) == 2) { for (; p < end_insns; p += 2) if (PEX64_UNWCODE_CODE (p[1]) != 6) break; } for (; p < end_insns; p += 2) { int reg; if (frame_debug) fprintf_unfiltered (gdb_stdlog, " op #%u: off=0x%02x, insn=0x%02x\n", (unsigned) (p - insns), p[0], p[1]); /* Virtually execute the operation. */ if (cache->pc >= cache->image_base + cache->start_rva + p[0]) { /* If there is no frame registers defined, the current value of rsp is used instead. */ if (frame_reg == 0) save_addr = cur_sp; switch (PEX64_UNWCODE_CODE (p[1])) { case UWOP_PUSH_NONVOL: /* Push pre-decrements RSP. */ reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; cache->prev_reg_addr[reg] = cur_sp; cur_sp += 8; break; case UWOP_ALLOC_LARGE: if (PEX64_UNWCODE_INFO (p[1]) == 0) cur_sp += 8 * extract_unsigned_integer (p + 2, 2, byte_order); else if (PEX64_UNWCODE_INFO (p[1]) == 1) cur_sp += extract_unsigned_integer (p + 2, 4, byte_order); else return; break; case UWOP_ALLOC_SMALL: cur_sp += 8 + 8 * PEX64_UNWCODE_INFO (p[1]); break; case UWOP_SET_FPREG: cur_sp = save_addr - PEX64_UWI_FRAMEOFF (ex_ui.FrameRegisterOffset) * 16; break; case UWOP_SAVE_NONVOL: reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; cache->prev_reg_addr[reg] = save_addr - 8 * extract_unsigned_integer (p + 2, 2, byte_order); break; case UWOP_SAVE_NONVOL_FAR: reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; cache->prev_reg_addr[reg] = save_addr - 8 * extract_unsigned_integer (p + 2, 4, byte_order); break; case UWOP_SAVE_XMM128: cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] = save_addr - 16 * extract_unsigned_integer (p + 2, 2, byte_order); break; case UWOP_SAVE_XMM128_FAR: cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] = save_addr - 16 * extract_unsigned_integer (p + 2, 4, byte_order); break; case UWOP_PUSH_MACHFRAME: if (PEX64_UNWCODE_INFO (p[1]) == 0) { cache->prev_rip_addr = cur_sp + 0; cache->prev_rsp_addr = cur_sp + 24; cur_sp += 40; } else if (PEX64_UNWCODE_INFO (p[1]) == 1) { cache->prev_rip_addr = cur_sp + 8; cache->prev_rsp_addr = cur_sp + 32; cur_sp += 48; } else return; break; default: return; } } /* Adjust with the length of the opcode. */ switch (PEX64_UNWCODE_CODE (p[1])) { case UWOP_PUSH_NONVOL: case UWOP_ALLOC_SMALL: case UWOP_SET_FPREG: case UWOP_PUSH_MACHFRAME: break; case UWOP_ALLOC_LARGE: if (PEX64_UNWCODE_INFO (p[1]) == 0) p += 2; else if (PEX64_UNWCODE_INFO (p[1]) == 1) p += 4; else return; break; case UWOP_SAVE_NONVOL: case UWOP_SAVE_XMM128: p += 2; break; case UWOP_SAVE_NONVOL_FAR: case UWOP_SAVE_XMM128_FAR: p += 4; break; default: return; } } if (PEX64_UWI_FLAGS (ex_ui.Version_Flags) != UNW_FLAG_CHAININFO) break; else { /* Read the chained unwind info. */ struct external_pex64_runtime_function d; CORE_ADDR chain_vma; chain_vma = cache->image_base + unwind_info + sizeof (ex_ui) + ((codes_count + 1) & ~1) * 2; if (target_read_memory (chain_vma, (gdb_byte *) &d, sizeof (d)) != 0) return; cache->start_rva = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); cache->end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); unwind_info = extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); if (frame_debug) fprintf_unfiltered (gdb_stdlog, "amd64_windows_frame_decodes_insn (next in chain):" " unwind_data=%s, start_rva=%s, end_rva=%s\n", paddress (gdbarch, unwind_info), paddress (gdbarch, cache->start_rva), paddress (gdbarch, cache->end_rva)); } /* Allow the user to break this loop. */ QUIT; } /* PC is saved by the call. */ if (cache->prev_rip_addr == 0) cache->prev_rip_addr = cur_sp; cache->prev_sp = cur_sp + 8; if (frame_debug) fprintf_unfiltered (gdb_stdlog, " prev_sp: %s, prev_pc @%s\n", paddress (gdbarch, cache->prev_sp), paddress (gdbarch, cache->prev_rip_addr)); }
static void sparclite_udp_write (bfd *from_bfd, asection *from_sec, file_ptr from_addr, bfd_vma to_addr, int len) { unsigned char buffer[2000]; unsigned short checksum; static int pkt_num = 0; static unsigned long old_addr = -1; int i; while (1) { if (to_addr != old_addr) { buffer[0] = 0x1; /* Load command */ buffer[1] = 0x1; /* Loading address */ buffer[2] = to_addr >> 24; buffer[3] = to_addr >> 16; buffer[4] = to_addr >> 8; buffer[5] = to_addr; checksum = 0; for (i = 0; i < 6; i++) checksum += buffer[i]; checksum &= 0xff; send_udp_buf (udp_fd, buffer, 6); i = recv_udp_buf (udp_fd, buffer, sizeof buffer, -1); if (i < 1) error ("Got back short checksum for load addr."); if (checksum != buffer[0]) error ("Got back bad checksum for load addr."); pkt_num = 0; /* Load addr resets packet seq # */ old_addr = to_addr; } bfd_get_section_contents (from_bfd, from_sec, buffer + 6, from_addr, len); checksum = calc_checksum (buffer + 6, len); buffer[0] = 0x1; /* Load command */ buffer[1] = 0x2; /* Loading data */ buffer[2] = pkt_num >> 8; buffer[3] = pkt_num; buffer[4] = checksum >> 8; buffer[5] = checksum; send_udp_buf (udp_fd, buffer, len + 6); i = recv_udp_buf (udp_fd, buffer, sizeof buffer, 3); if (i == 0) { fprintf_unfiltered (gdb_stderr, "send_data: timeout sending %d bytes to address 0x%x retrying\n", len, to_addr); continue; } if (buffer[0] != 0xff) error ("Got back bad response for load data."); old_addr += len; pkt_num++; return; }
static int enable_break2 (void) { int success = 0; char **bkpt_namep; asection *interp_sect; if (!enable_break1_done || enable_break2_done) return 1; enable_break2_done = 1; /* First, remove all the solib event breakpoints. Their addresses may have changed since the last time we ran the program. */ remove_solib_event_breakpoints (); interp_text_sect_low = interp_text_sect_high = 0; interp_plt_sect_low = interp_plt_sect_high = 0; /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect) { unsigned int interp_sect_size; gdb_byte *buf; bfd *tmp_bfd = NULL; int status; CORE_ADDR addr, interp_loadmap_addr; gdb_byte addr_buf[FRV_PTR_SIZE]; struct int_elf32_fdpic_loadmap *ldm; volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ interp_sect_size = bfd_section_size (exec_bfd, interp_sect); buf = alloca (interp_sect_size); bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, interp_sect_size); /* Now we need to figure out where the dynamic linker was loaded so that we can load its symbols and place a breakpoint in the dynamic linker itself. This address is stored on the stack. However, I've been unable to find any magic formula to find it for Solaris (appears to be trivial on GNU/Linux). Therefore, we have to try an alternate mechanism to find the dynamic linker's base address. */ TRY_CATCH (ex, RETURN_MASK_ALL) { tmp_bfd = solib_bfd_open (buf); } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } status = frv_fdpic_loadmap_addresses (target_gdbarch, &interp_loadmap_addr, 0); if (status < 0) { warning (_("Unable to determine dynamic linker loadmap address.")); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: interp_loadmap_addr = %s\n", hex_string_custom (interp_loadmap_addr, 8)); ldm = fetch_loadmap (interp_loadmap_addr); if (ldm == NULL) { warning (_("Unable to load dynamic linker loadmap at address %s."), hex_string_custom (interp_loadmap_addr, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } /* Record the relocated start and end address of the dynamic linker text and plt section for svr4_in_dynsym_resolve_code. */ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { interp_text_sect_low = bfd_section_vma (tmp_bfd, interp_sect); interp_text_sect_low += displacement_from_map (ldm, interp_text_sect_low); interp_text_sect_high = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); } interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); if (interp_sect) { interp_plt_sect_low = bfd_section_vma (tmp_bfd, interp_sect); interp_plt_sect_low += displacement_from_map (ldm, interp_plt_sect_low); interp_plt_sect_high = interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); } addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr"); if (addr == 0) { warning (_("Could not find symbol _dl_debug_addr in dynamic linker")); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (prior to relocation) = %s\n", hex_string_custom (addr, 8)); addr += displacement_from_map (ldm, addr); if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (after relocation) = %s\n", hex_string_custom (addr, 8)); /* Fetch the address of the r_debug struct. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"), hex_string_custom (addr, 8)); } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf); /* Fetch the r_brk field. It's 8 bytes from the start of _dl_debug_addr. */ if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"), hex_string_custom (addr + 8, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf); /* Now fetch the function entry point. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"), hex_string_custom (addr, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf); /* We're done with the temporary bfd. */ bfd_close (tmp_bfd); /* We're also done with the loadmap. */ xfree (ldm); /* Now (finally!) create the solib breakpoint. */ create_solib_event_breakpoint (addr); return 1; }
static struct so_list * frv_current_sos (void) { CORE_ADDR lm_addr, mgot; struct so_list *sos_head = NULL; struct so_list **sos_next_ptr = &sos_head; /* Make sure that the main executable has been relocated. This is required in order to find the address of the global offset table, which in turn is used to find the link map info. (See lm_base() for details.) Note that the relocation of the main executable is also performed by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core files, this hook is called too late in order to be of benefit to SOLIB_ADD. SOLIB_ADD eventually calls this this function, frv_current_sos, and also precedes the call to SOLIB_CREATE_INFERIOR_HOOK(). (See post_create_inferior() in infcmd.c.) */ if (main_executable_lm_info == 0 && core_bfd != NULL) frv_relocate_main_executable (); /* Fetch the GOT corresponding to the main executable. */ mgot = main_got (); /* Locate the address of the first link map struct. */ lm_addr = lm_base (); /* We have at least one link map entry. Fetch the the lot of them, building the solist chain. */ while (lm_addr) { struct ext_link_map lm_buf; CORE_ADDR got_addr; if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "current_sos: reading link_map entry at %s\n", hex_string_custom (lm_addr, 8)); if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf, sizeof (lm_buf)) != 0) { warning (_("frv_current_sos: Unable to read link map entry. Shared object chain may be incomplete.")); break; } got_addr = extract_unsigned_integer (lm_buf.l_addr.got_value, sizeof (lm_buf.l_addr.got_value)); /* If the got_addr is the same as mgotr, then we're looking at the entry for the main executable. By convention, we don't include this in the list of shared objects. */ if (got_addr != mgot) { int errcode; char *name_buf; struct int_elf32_fdpic_loadmap *loadmap; struct so_list *sop; CORE_ADDR addr; /* Fetch the load map address. */ addr = extract_unsigned_integer (lm_buf.l_addr.map, sizeof lm_buf.l_addr.map); loadmap = fetch_loadmap (addr); if (loadmap == NULL) { warning (_("frv_current_sos: Unable to fetch load map. Shared object chain may be incomplete.")); break; } sop = xcalloc (1, sizeof (struct so_list)); sop->lm_info = xcalloc (1, sizeof (struct lm_info)); sop->lm_info->map = loadmap; sop->lm_info->got_value = got_addr; sop->lm_info->lm_addr = lm_addr; /* Fetch the name. */ addr = extract_unsigned_integer (lm_buf.l_name, sizeof (lm_buf.l_name)); target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1, &errcode); if (solib_frv_debug) fprintf_unfiltered (gdb_stdlog, "current_sos: name = %s\n", name_buf); if (errcode != 0) warning (_("Can't read pathname for link map entry: %s."), safe_strerror (errcode)); else { strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1); sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; xfree (name_buf); strcpy (sop->so_original_name, sop->so_name); } *sos_next_ptr = sop; sos_next_ptr = &sop->next; } else { main_lm_addr = lm_addr; } lm_addr = extract_unsigned_integer (lm_buf.l_next, sizeof (lm_buf.l_next)); } enable_break2 (); return sos_head; }
/* Standard implementation of print_subexp for use in language_defn vectors. */ void print_subexp_standard (struct expression *exp, int *pos, struct ui_file *stream, enum precedence prec) { unsigned tem; const struct op_print *op_print_tab; int pc; unsigned nargs; char *op_str; int assign_modify = 0; enum exp_opcode opcode; enum precedence myprec = PREC_NULL; /* Set to 1 for a right-associative operator. */ int assoc = 0; struct value *val; char *tempstr = NULL; op_print_tab = exp->language_defn->la_op_print_tab; pc = (*pos)++; opcode = exp->elts[pc].opcode; switch (opcode) { /* Common ops */ case OP_SCOPE: myprec = PREC_PREFIX; assoc = 0; fputs_filtered (type_name_no_tag (exp->elts[pc + 1].type), stream); fputs_filtered ("::", stream); nargs = longest_to_int (exp->elts[pc + 2].longconst); (*pos) += 4 + BYTES_TO_EXP_ELEM (nargs + 1); fputs_filtered (&exp->elts[pc + 3].string, stream); return; case OP_LONG: { struct value_print_options opts; get_raw_print_options (&opts); (*pos) += 3; value_print (value_from_longest (exp->elts[pc + 1].type, exp->elts[pc + 2].longconst), stream, &opts); } return; case OP_DOUBLE: { struct value_print_options opts; get_raw_print_options (&opts); (*pos) += 3; value_print (value_from_double (exp->elts[pc + 1].type, exp->elts[pc + 2].doubleconst), stream, &opts); } return; case OP_VAR_VALUE: { struct block *b; (*pos) += 3; b = exp->elts[pc + 1].block; if (b != NULL && BLOCK_FUNCTION (b) != NULL && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)) != NULL) { fputs_filtered (SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)), stream); fputs_filtered ("::", stream); } fputs_filtered (SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol), stream); } return; case OP_LAST: (*pos) += 2; fprintf_filtered (stream, "$%d", longest_to_int (exp->elts[pc + 1].longconst)); return; case OP_REGISTER: { const char *name = &exp->elts[pc + 2].string; (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); fprintf_filtered (stream, "$%s", name); return; } case OP_BOOL: (*pos) += 2; fprintf_filtered (stream, "%s", longest_to_int (exp->elts[pc + 1].longconst) ? "TRUE" : "FALSE"); return; case OP_INTERNALVAR: (*pos) += 2; fprintf_filtered (stream, "$%s", internalvar_name (exp->elts[pc + 1].internalvar)); return; case OP_FUNCALL: (*pos) += 2; nargs = longest_to_int (exp->elts[pc + 1].longconst); print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered (" (", stream); for (tem = 0; tem < nargs; tem++) { if (tem != 0) fputs_filtered (", ", stream); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } fputs_filtered (")", stream); return; case OP_NAME: nargs = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1); fputs_filtered (&exp->elts[pc + 2].string, stream); return; case OP_STRING: { struct value_print_options opts; nargs = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1); /* LA_PRINT_STRING will print using the current repeat count threshold. If necessary, we can temporarily set it to zero, or pass it as an additional parameter to LA_PRINT_STRING. -fnf */ get_user_print_options (&opts); LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, &exp->elts[pc + 2].string, nargs, NULL, 0, &opts); } return; case OP_BITSTRING: nargs = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM ((nargs + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT); fprintf_unfiltered (stream, "B'<unimplemented>'"); return; case OP_OBJC_NSSTRING: /* Objective-C Foundation Class NSString constant. */ { struct value_print_options opts; nargs = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1); fputs_filtered ("@\"", stream); get_user_print_options (&opts); LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, &exp->elts[pc + 2].string, nargs, NULL, 0, &opts); fputs_filtered ("\"", stream); } return; case OP_OBJC_MSGCALL: { /* Objective C message (method) call. */ char *selector; (*pos) += 3; nargs = longest_to_int (exp->elts[pc + 2].longconst); fprintf_unfiltered (stream, "["); print_subexp (exp, pos, stream, PREC_SUFFIX); if (0 == target_read_string (exp->elts[pc + 1].longconst, &selector, 1024, NULL)) { error (_("bad selector")); return; } if (nargs) { char *s, *nextS; s = alloca (strlen (selector) + 1); strcpy (s, selector); for (tem = 0; tem < nargs; tem++) { nextS = strchr (s, ':'); gdb_assert (nextS); /* Make sure we found ':'. */ *nextS = '\0'; fprintf_unfiltered (stream, " %s: ", s); s = nextS + 1; print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } } else { fprintf_unfiltered (stream, " %s", selector); } fprintf_unfiltered (stream, "]"); /* "selector" was malloc'd by target_read_string. Free it. */ xfree (selector); return; } case OP_ARRAY: (*pos) += 3; nargs = longest_to_int (exp->elts[pc + 2].longconst); nargs -= longest_to_int (exp->elts[pc + 1].longconst); nargs++; tem = 0; if (exp->elts[pc + 4].opcode == OP_LONG && exp->elts[pc + 5].type == builtin_type (exp->gdbarch)->builtin_char && exp->language_defn->la_language == language_c) { /* Attempt to print C character arrays using string syntax. Walk through the args, picking up one character from each of the OP_LONG expression elements. If any array element does not match our expection of what we should find for a simple string, revert back to array printing. Note that the last expression element is an explicit null terminator byte, which doesn't get printed. */ tempstr = alloca (nargs); pc += 4; while (tem < nargs) { if (exp->elts[pc].opcode != OP_LONG || exp->elts[pc + 1].type != builtin_type (exp->gdbarch)->builtin_char) { /* Not a simple array of char, use regular array printing. */ tem = 0; break; } else { tempstr[tem++] = longest_to_int (exp->elts[pc + 2].longconst); pc += 4; } } } if (tem > 0) { struct value_print_options opts; get_user_print_options (&opts); LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, tempstr, nargs - 1, NULL, 0, &opts); (*pos) = pc; } else { fputs_filtered (" {", stream); for (tem = 0; tem < nargs; tem++) { if (tem != 0) { fputs_filtered (", ", stream); } print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } fputs_filtered ("}", stream); } return; case OP_LABELED: tem = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); /* Gcc support both these syntaxes. Unsure which is preferred. */ #if 1 fputs_filtered (&exp->elts[pc + 2].string, stream); fputs_filtered (": ", stream); #else fputs_filtered (".", stream); fputs_filtered (&exp->elts[pc + 2].string, stream); fputs_filtered ("=", stream); #endif print_subexp (exp, pos, stream, PREC_SUFFIX); return; case TERNOP_COND: if ((int) prec > (int) PREC_COMMA) fputs_filtered ("(", stream); /* Print the subexpressions, forcing parentheses around any binary operations within them. This is more parentheses than are strictly necessary, but it looks clearer. */ print_subexp (exp, pos, stream, PREC_HYPER); fputs_filtered (" ? ", stream); print_subexp (exp, pos, stream, PREC_HYPER); fputs_filtered (" : ", stream); print_subexp (exp, pos, stream, PREC_HYPER); if ((int) prec > (int) PREC_COMMA) fputs_filtered (")", stream); return; case TERNOP_SLICE: case TERNOP_SLICE_COUNT: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("(", stream); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); fputs_filtered (opcode == TERNOP_SLICE ? " : " : " UP ", stream); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); fputs_filtered (")", stream); return; case STRUCTOP_STRUCT: tem = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered (".", stream); fputs_filtered (&exp->elts[pc + 2].string, stream); return; /* Will not occur for Modula-2. */ case STRUCTOP_PTR: tem = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("->", stream); fputs_filtered (&exp->elts[pc + 2].string, stream); return; case STRUCTOP_MEMBER: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered (".*", stream); print_subexp (exp, pos, stream, PREC_SUFFIX); return; case STRUCTOP_MPTR: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("->*", stream); print_subexp (exp, pos, stream, PREC_SUFFIX); return; case BINOP_SUBSCRIPT: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("[", stream); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); fputs_filtered ("]", stream); return; case UNOP_POSTINCREMENT: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("++", stream); return; case UNOP_POSTDECREMENT: print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("--", stream); return; case UNOP_CAST: (*pos) += 2; if ((int) prec > (int) PREC_PREFIX) fputs_filtered ("(", stream); fputs_filtered ("(", stream); type_print (exp->elts[pc + 1].type, "", stream, 0); fputs_filtered (") ", stream); print_subexp (exp, pos, stream, PREC_PREFIX); if ((int) prec > (int) PREC_PREFIX) fputs_filtered (")", stream); return; case UNOP_DYNAMIC_CAST: case UNOP_REINTERPRET_CAST: fputs_filtered (opcode == UNOP_DYNAMIC_CAST ? "dynamic_cast" : "reinterpret_cast", stream); fputs_filtered ("<", stream); (*pos) += 2; type_print (exp->elts[pc + 1].type, "", stream, 0); fputs_filtered ("> (", stream); print_subexp (exp, pos, stream, PREC_PREFIX); fputs_filtered (")", stream); return; case UNOP_MEMVAL: (*pos) += 2; if ((int) prec > (int) PREC_PREFIX) fputs_filtered ("(", stream); if (TYPE_CODE (exp->elts[pc + 1].type) == TYPE_CODE_FUNC && exp->elts[pc + 3].opcode == OP_LONG) { struct value_print_options opts; /* We have a minimal symbol fn, probably. It's encoded as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address). Swallow the OP_LONG (including both its opcodes); ignore its type; print the value in the type of the MEMVAL. */ (*pos) += 4; val = value_at_lazy (exp->elts[pc + 1].type, (CORE_ADDR) exp->elts[pc + 5].longconst); get_raw_print_options (&opts); value_print (val, stream, &opts); } else { fputs_filtered ("{", stream); type_print (exp->elts[pc + 1].type, "", stream, 0); fputs_filtered ("} ", stream); print_subexp (exp, pos, stream, PREC_PREFIX); } if ((int) prec > (int) PREC_PREFIX) fputs_filtered (")", stream); return; case UNOP_MEMVAL_TLS: (*pos) += 3; if ((int) prec > (int) PREC_PREFIX) fputs_filtered ("(", stream); fputs_filtered ("{", stream); type_print (exp->elts[pc + 2].type, "", stream, 0); fputs_filtered ("} ", stream); print_subexp (exp, pos, stream, PREC_PREFIX); if ((int) prec > (int) PREC_PREFIX) fputs_filtered (")", stream); return; case BINOP_ASSIGN_MODIFY: opcode = exp->elts[pc + 1].opcode; (*pos) += 2; myprec = PREC_ASSIGN; assoc = 1; assign_modify = 1; op_str = "???"; for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++) if (op_print_tab[tem].opcode == opcode) { op_str = op_print_tab[tem].string; break; } if (op_print_tab[tem].opcode != opcode) /* Not found; don't try to keep going because we don't know how to interpret further elements. */ error (_("Invalid expression")); break; /* C++ ops */ case OP_THIS: ++(*pos); fputs_filtered ("this", stream); return; /* Objective-C ops */ case OP_OBJC_SELF: ++(*pos); fputs_filtered ("self", stream); /* The ObjC equivalent of "this". */ return; /* Modula-2 ops */ case MULTI_SUBSCRIPT: (*pos) += 2; nargs = longest_to_int (exp->elts[pc + 1].longconst); print_subexp (exp, pos, stream, PREC_SUFFIX); fprintf_unfiltered (stream, " ["); for (tem = 0; tem < nargs; tem++) { if (tem != 0) fprintf_unfiltered (stream, ", "); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } fprintf_unfiltered (stream, "]"); return; case BINOP_VAL: (*pos) += 2; fprintf_unfiltered (stream, "VAL("); type_print (exp->elts[pc + 1].type, "", stream, 0); fprintf_unfiltered (stream, ","); print_subexp (exp, pos, stream, PREC_PREFIX); fprintf_unfiltered (stream, ")"); return; case TYPE_INSTANCE: { LONGEST count = exp->elts[pc + 1].longconst; /* The COUNT. */ (*pos)++; fputs_unfiltered ("TypesInstance(", stream); while (count-- > 0) { type_print (exp->elts[(*pos)++].type, "", stream, 0); if (count > 0) fputs_unfiltered (",", stream); } fputs_unfiltered (",", stream); /* Ending COUNT and ending TYPE_INSTANCE. */ (*pos) += 2; print_subexp (exp, pos, stream, PREC_PREFIX); fputs_unfiltered (")", stream); return; } /* Default ops */ default: op_str = "???"; for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++) if (op_print_tab[tem].opcode == opcode) { op_str = op_print_tab[tem].string; myprec = op_print_tab[tem].precedence; assoc = op_print_tab[tem].right_assoc; break; } if (op_print_tab[tem].opcode != opcode) /* Not found; don't try to keep going because we don't know how to interpret further elements. For example, this happens if opcode is OP_TYPE. */ error (_("Invalid expression")); } /* Note that PREC_BUILTIN will always emit parentheses. */ if ((int) myprec < (int) prec) fputs_filtered ("(", stream); if ((int) opcode > (int) BINOP_END) { if (assoc) { /* Unary postfix operator. */ print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered (op_str, stream); } else { /* Unary prefix operator. */ fputs_filtered (op_str, stream); if (myprec == PREC_BUILTIN_FUNCTION) fputs_filtered ("(", stream); print_subexp (exp, pos, stream, PREC_PREFIX); if (myprec == PREC_BUILTIN_FUNCTION) fputs_filtered (")", stream); } } else { /* Binary operator. */ /* Print left operand. If operator is right-associative, increment precedence for this operand. */ print_subexp (exp, pos, stream, (enum precedence) ((int) myprec + assoc)); /* Print the operator itself. */ if (assign_modify) fprintf_filtered (stream, " %s= ", op_str); else if (op_str[0] == ',') fprintf_filtered (stream, "%s ", op_str); else fprintf_filtered (stream, " %s ", op_str); /* Print right operand. If operator is left-associative, increment precedence for this operand. */ print_subexp (exp, pos, stream, (enum precedence) ((int) myprec + !assoc)); } if ((int) myprec < (int) prec) fputs_filtered (")", stream); }
static void mi_on_resume (ptid_t ptid) { struct thread_info *tp = NULL; if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) tp = inferior_thread (); else tp = find_thread_ptid (ptid); /* Suppress output while calling an inferior function. */ if (tp->control.in_infcall) return; /* To cater for older frontends, emit ^running, but do it only once per each command. We do it here, since at this point we know that the target was successfully resumed, and in non-async mode, we won't return back to MI interpreter code until the target is done running, so delaying the output of "^running" until then will make it impossible for frontend to know what's going on. In future (MI3), we'll be outputting "^done" here. */ if (!running_result_record_printed && mi_proceeded) { fprintf_unfiltered (raw_stdout, "%s^running\n", current_token ? current_token : ""); } if (PIDGET (ptid) == -1) fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n"); else if (ptid_is_pid (ptid)) { int count = 0; /* Backwards compatibility. If there's only one inferior, output "all", otherwise, output each resumed thread individually. */ iterate_over_inferiors (mi_inferior_count, &count); if (count == 1) fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n"); else iterate_over_threads (mi_output_running_pid, &ptid); } else { struct thread_info *ti = find_thread_ptid (ptid); gdb_assert (ti); fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num); } if (!running_result_record_printed && mi_proceeded) { running_result_record_printed = 1; /* This is what gdb used to do historically -- printing prompt even if it cannot actually accept any input. This will be surely removed for MI3, and may be removed even earler. */ /* FIXME: review the use of target_is_async_p here -- is that what we want? */ if (!target_is_async_p ()) fputs_unfiltered ("(gdb) \n", raw_stdout); } gdb_flush (raw_stdout); }