static void signal_catchpoint_print_one (struct breakpoint *b, struct bp_location **last_loc) { struct signal_catchpoint *c = (void *) b; struct value_print_options opts; struct ui_out *uiout = current_uiout; get_user_print_options (&opts); /* Field 4, the address, is omitted (which makes the columns not line up too nicely with the headers, but the effect is relatively readable). */ if (opts.addressprint) ui_out_field_skip (uiout, "addr"); annotate_field (5); if (c->signals_to_be_caught && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1) ui_out_text (uiout, "signals \""); else ui_out_text (uiout, "signal \""); if (c->signals_to_be_caught) { int i; gdb_signal_type iter; struct obstack text; struct cleanup *cleanup; obstack_init (&text); cleanup = make_cleanup_obstack_free (&text); for (i = 0; VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter); i++) { const char *name = signal_to_name_or_int (iter); if (i > 0) obstack_grow (&text, " ", 1); obstack_grow (&text, name, strlen (name)); } obstack_grow (&text, "", 1); ui_out_field_string (uiout, "what", obstack_base (&text)); do_cleanups (cleanup); } else ui_out_field_string (uiout, "what", c->catch_all ? "<any signal>" : "<standard signals>"); ui_out_text (uiout, "\" "); if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "catch-type", "signal"); }
static void btrace_insn_history (struct ui_out *uiout, const struct btrace_insn_iterator *begin, const struct btrace_insn_iterator *end, int flags) { struct gdbarch *gdbarch; struct btrace_insn_iterator it; DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin), btrace_insn_number (end)); gdbarch = target_gdbarch (); for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1)) { const struct btrace_insn *insn; insn = btrace_insn_get (&it); /* Print the instruction index. */ ui_out_field_uint (uiout, "index", btrace_insn_number (&it)); ui_out_text (uiout, "\t"); /* Disassembly with '/m' flag may not produce the expected result. See PR gdb/11833. */ gdb_disassembly (gdbarch, uiout, NULL, flags, 1, insn->pc, insn->pc + 1); } }
void cmd_show_list (struct cmd_list_element *list, int from_tty, const char *prefix) { struct cleanup *showlist_chain; struct ui_out *uiout = current_uiout; showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist"); for (; list != NULL; list = list->next) { /* If we find a prefix, run its list, prefixing our output by its prefix (with "show " skipped). */ if (list->prefixlist && !list->abbrev_flag) { struct cleanup *optionlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "optionlist"); char *new_prefix = strstr (list->prefixname, "show ") + 5; if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "prefix", new_prefix); cmd_show_list (*list->prefixlist, from_tty, new_prefix); /* Close the tuple. */ do_cleanups (optionlist_chain); } else { if (list->theclass != no_set_class) { struct cleanup *option_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); ui_out_text (uiout, prefix); ui_out_field_string (uiout, "name", list->name); ui_out_text (uiout, ": "); if (list->type == show_cmd) do_show_command ((char *) NULL, from_tty, list); else cmd_func (list, NULL, from_tty); /* Close the tuple. */ do_cleanups (option_chain); } } } /* Close the tuple. */ do_cleanups (showlist_chain); }
char* hsail_dbginfo_get_source_buffer(void) { struct ui_out *uiout = current_uiout; if (gs_hsail_source == NULL) { ui_out_text(uiout, "HSAIL source buffer not available\n"); } return gs_hsail_source; }
static void btrace_func_history_insn_range (struct ui_out *uiout, struct btrace_func *bfun) { ui_out_field_uint (uiout, "insn begin", bfun->ibegin); if (bfun->ibegin == bfun->iend) return; ui_out_text (uiout, "-"); ui_out_field_uint (uiout, "insn end", bfun->iend); }
int gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream) { struct ui_stream *stb = ui_out_stream_new (uiout); struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream); // struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); struct disassemble_info * di2 = &di; struct cleanup *ui_out_chain; ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); int i; CORE_ADDR old_pc = memaddr; CORE_ADDR oldmemaddr = memaddr; bfd_byte data; int status; ui_file_rewind (stb->stream); memaddr = TARGET_PRINT_INSN (memaddr, &di); oldmemaddr += memaddr; for (; old_pc < oldmemaddr; old_pc ++) { status = (*di2->read_memory_func) (old_pc, &data, 1, di2); if (status != 0) (*di2->memory_error_func) (status, old_pc, di2); ui_out_message (uiout, 0, " %02x", (unsigned)data); } i = memaddr; for (; i<10; i++) ui_out_text(uiout, " "); ui_out_text (uiout, " "); ui_out_field_stream(uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); return memaddr; // return TARGET_PRINT_INSN (memaddr, &di); }
static void btrace_func_history (struct btrace_thread_info *btinfo, struct ui_out *uiout, unsigned int begin, unsigned int end, enum record_print_flag flags) { struct btrace_func *bfun; unsigned int idx; DEBUG ("ftrace (0x%x): [%u; %u[", flags, begin, end); for (idx = begin; VEC_iterate (btrace_func_s, btinfo->ftrace, idx, bfun) && idx < end; ++idx) { /* Print the function index. */ ui_out_field_uint (uiout, "index", idx); ui_out_text (uiout, "\t"); if ((flags & record_print_insn_range) != 0) { btrace_func_history_insn_range (uiout, bfun); ui_out_text (uiout, "\t"); } if ((flags & record_print_src_line) != 0) { btrace_func_history_src_line (uiout, bfun); ui_out_text (uiout, "\t"); } if (bfun->sym != NULL) ui_out_field_string (uiout, "function", SYMBOL_PRINT_NAME (bfun->sym)); else if (bfun->msym != NULL) ui_out_field_string (uiout, "function", SYMBOL_PRINT_NAME (bfun->msym)); ui_out_text (uiout, "\n"); } }
static void btrace_func_history_src_line (struct ui_out *uiout, struct btrace_func *bfun) { struct symbol *sym; sym = bfun->sym; if (sym == NULL) return; ui_out_field_string (uiout, "file", symtab_to_filename_for_display (sym->symtab)); if (bfun->lend == 0) return; ui_out_text (uiout, ":"); ui_out_field_int (uiout, "min line", bfun->lbegin); if (bfun->lend == bfun->lbegin) return; ui_out_text (uiout, "-"); ui_out_field_int (uiout, "max line", bfun->lend); }
static void btrace_call_history_insn_range (struct ui_out *uiout, const struct btrace_function *bfun) { unsigned int begin, end, size; size = VEC_length (btrace_insn_s, bfun->insn); gdb_assert (size > 0); begin = bfun->insn_offset; end = begin + size - 1; ui_out_field_uint (uiout, "insn begin", begin); ui_out_text (uiout, ","); ui_out_field_uint (uiout, "insn end", end); }
static void btrace_insn_history (struct btrace_thread_info *btinfo, struct ui_out *uiout, unsigned int begin, unsigned int end, int flags) { struct gdbarch *gdbarch; struct btrace_inst *inst; unsigned int idx; DEBUG ("itrace (0x%x): [%u; %u[", flags, begin, end); gdbarch = target_gdbarch (); for (idx = begin; VEC_iterate (btrace_inst_s, btinfo->itrace, idx, inst) && idx < end; ++idx) { /* Print the instruction index. */ ui_out_field_uint (uiout, "index", idx); ui_out_text (uiout, "\t"); /* Disassembly with '/m' flag may not produce the expected result. See PR gdb/11833. */ gdb_disassembly (gdbarch, uiout, NULL, flags, 1, inst->pc, inst->pc + 1); } }
int hsail_utils_command_index(char* arg, struct ui_out *uiout) { char index_buffer[256] = { 0 }; int buffer_length = 0; int arg_length = 0; int ret_val = -1; gdb_assert(NULL != arg); gdb_assert(NULL != uiout); arg_length = strlen(arg); memset(index_buffer, '\0', sizeof(index_buffer)); SKIP_LEADING_SPACES(arg,arg_length); while((buffer_length < arg_length) && isdigit(arg[buffer_length]) && buffer_length < 256) { index_buffer[buffer_length] = arg[buffer_length]; buffer_length++; } /* validate the that index termiates in end of line of space, not alpha so it is valid (spaces)*/ if (buffer_length >= arg_length || arg[buffer_length] == ' ' || arg[buffer_length] == '\t' || arg[buffer_length] == '\r' || arg[buffer_length] == '\n') { /* convert the buffer to value */ index_buffer[buffer_length] = 0; ret_val = atoi(index_buffer); } /* if no conversion was made or fo some reason we got a negative value */ if (ret_val < 0) { ui_out_text(uiout,"Invalid index provided for info command\n"); } return ret_val; }
static int dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, struct disassemble_info * di, CORE_ADDR low, CORE_ADDR high, int how_many, int flags, struct ui_stream *stb) { int num_displayed = 0; CORE_ADDR pc; /* parts of the symbolic representation of the address */ int unmapped; int offset; int line; struct cleanup *ui_out_chain; for (pc = low; pc < high;) { char *filename = NULL; char *name = NULL; QUIT; if (how_many >= 0) { if (num_displayed >= how_many) break; else num_displayed++; } ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_core_addr (uiout, "address", gdbarch, pc); if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped)) { /* We don't care now about line, filename and unmapped. But we might in the future. */ ui_out_text (uiout, " <"); ui_out_field_string (uiout, "func-name", name); ui_out_text (uiout, "+"); ui_out_field_int (uiout, "offset", offset); ui_out_text (uiout, ">:\t"); } else ui_out_text (uiout, ":\t"); if (filename != NULL) xfree (filename); if (name != NULL) xfree (name); ui_file_rewind (stb->stream); if (flags & DISASSEMBLY_RAW_INSN) { CORE_ADDR old_pc = pc; bfd_byte data; int status; pc += gdbarch_print_insn (gdbarch, pc, di); for (;old_pc < pc; old_pc++) { status = (*di->read_memory_func) (old_pc, &data, 1, di); if (status != 0) (*di->memory_error_func) (status, old_pc, di); ui_out_message (uiout, 0, " %02x", (unsigned)data); } ui_out_text (uiout, "\t"); } else pc += gdbarch_print_insn (gdbarch, pc, di); ui_out_field_stream (uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); ui_out_text (uiout, "\n"); } return num_displayed; }
/* The idea here is to present a source-O-centric view of a function to the user. This means that things are presented in source order, with (possibly) out of order assembly immediately following. */ static void do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, struct disassemble_info *di, int nlines, struct linetable_entry *le, CORE_ADDR low, CORE_ADDR high, struct symtab *symtab, int how_many, int flags, struct ui_stream *stb) { int newlines = 0; struct dis_line_entry *mle; struct symtab_and_line sal; int i; int out_of_order = 0; int next_line = 0; CORE_ADDR pc; int num_displayed = 0; struct cleanup *ui_out_chain; struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0); struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0); mle = (struct dis_line_entry *) alloca (nlines * sizeof (struct dis_line_entry)); /* Copy linetable entries for this function into our data structure, creating end_pc's and setting out_of_order as appropriate. */ /* First, skip all the preceding functions. */ for (i = 0; i < nlines - 1 && le[i].pc < low; i++); /* Now, copy all entries before the end of this function. */ for (; i < nlines - 1 && le[i].pc < high; i++) { if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) continue; /* Ignore duplicates */ /* Skip any end-of-function markers. */ if (le[i].line == 0) continue; mle[newlines].line = le[i].line; if (le[i].line > le[i + 1].line) out_of_order = 1; mle[newlines].start_pc = le[i].pc; mle[newlines].end_pc = le[i + 1].pc; newlines++; } /* If we're on the last line, and it's part of the function, then we need to get the end pc in a special way. */ if (i == nlines - 1 && le[i].pc < high) { mle[newlines].line = le[i].line; mle[newlines].start_pc = le[i].pc; sal = find_pc_line (le[i].pc, 0); mle[newlines].end_pc = sal.end; newlines++; } /* Now, sort mle by line #s (and, then by addresses within lines). */ if (out_of_order) qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); /* Now, for each line entry, emit the specified lines (unless they have been emitted before), followed by the assembly code for that line. */ ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); for (i = 0; i < newlines; i++) { /* Print out everything from next_line to the current line. */ if (mle[i].line >= next_line) { if (next_line != 0) { /* Just one line to print. */ if (next_line == mle[i].line) { ui_out_tuple_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); print_source_lines (symtab, next_line, mle[i].line + 1, 0); } else { /* Several source lines w/o asm instructions associated. */ for (; next_line < mle[i].line; next_line++) { struct cleanup *ui_out_list_chain_line; struct cleanup *ui_out_tuple_chain_line; ui_out_tuple_chain_line = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); print_source_lines (symtab, next_line, next_line + 1, 0); ui_out_list_chain_line = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); do_cleanups (ui_out_list_chain_line); do_cleanups (ui_out_tuple_chain_line); } /* Print the last line and leave list open for asm instructions to be added. */ ui_out_tuple_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); print_source_lines (symtab, next_line, mle[i].line + 1, 0); } } else { ui_out_tuple_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); } next_line = mle[i].line + 1; ui_out_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); } num_displayed += dump_insns (gdbarch, uiout, di, mle[i].start_pc, mle[i].end_pc, how_many, flags, stb); /* When we've reached the end of the mle array, or we've seen the last assembly range for this source line, close out the list/tuple. */ if (i == (newlines - 1) || mle[i + 1].line > mle[i].line) { do_cleanups (ui_out_list_chain); do_cleanups (ui_out_tuple_chain); ui_out_tuple_chain = make_cleanup (null_cleanup, 0); ui_out_list_chain = make_cleanup (null_cleanup, 0); ui_out_text (uiout, "\n"); } if (how_many >= 0 && num_displayed >= how_many) break; } do_cleanups (ui_out_chain); }
static void darwin_debug_regions_recurse (task_t task) { mach_vm_address_t r_addr; mach_vm_address_t r_start; mach_vm_size_t r_size; natural_t r_depth; mach_msg_type_number_t r_info_size; vm_region_submap_short_info_data_64_t r_info; kern_return_t kret; int ret; struct cleanup *table_chain; struct ui_out *uiout = current_uiout; table_chain = make_cleanup_ui_out_table_begin_end (uiout, 9, -1, "regions"); if (gdbarch_addr_bit (target_gdbarch ()) <= 32) { ui_out_table_header (uiout, 10, ui_left, "start", "Start"); ui_out_table_header (uiout, 10, ui_left, "end", "End"); } else { ui_out_table_header (uiout, 18, ui_left, "start", "Start"); ui_out_table_header (uiout, 18, ui_left, "end", "End"); } ui_out_table_header (uiout, 3, ui_left, "min-prot", "Min"); ui_out_table_header (uiout, 3, ui_left, "max-prot", "Max"); ui_out_table_header (uiout, 5, ui_left, "inheritence", "Inh"); ui_out_table_header (uiout, 9, ui_left, "share-mode", "Shr"); ui_out_table_header (uiout, 1, ui_left, "depth", "D"); ui_out_table_header (uiout, 3, ui_left, "submap", "Sm"); ui_out_table_header (uiout, 0, ui_noalign, "tag", "Tag"); ui_out_table_body (uiout); r_start = 0; r_depth = 0; while (1) { const char *tag; struct cleanup *row_chain; r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; r_size = -1; kret = mach_vm_region_recurse (task, &r_start, &r_size, &r_depth, (vm_region_recurse_info_t) &r_info, &r_info_size); if (kret != KERN_SUCCESS) break; row_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "regions-row"); ui_out_field_core_addr (uiout, "start", target_gdbarch (), r_start); ui_out_field_core_addr (uiout, "end", target_gdbarch (), r_start + r_size); ui_out_field_string (uiout, "min-prot", unparse_protection (r_info.protection)); ui_out_field_string (uiout, "max-prot", unparse_protection (r_info.max_protection)); ui_out_field_string (uiout, "inheritence", unparse_inheritance (r_info.inheritance)); ui_out_field_string (uiout, "share-mode", unparse_share_mode (r_info.share_mode)); ui_out_field_int (uiout, "depth", r_depth); ui_out_field_string (uiout, "submap", r_info.is_submap ? _("sm ") : _("obj")); tag = unparse_user_tag (r_info.user_tag); if (tag) ui_out_field_string (uiout, "tag", tag); else ui_out_field_int (uiout, "tag", r_info.user_tag); do_cleanups (row_chain); if (!ui_out_is_mi_like_p (uiout)) ui_out_text (uiout, "\n"); if (r_info.is_submap) r_depth++; else r_start += r_size; } do_cleanups (table_chain); }
HwDbgInfo_debug hsail_init_hwdbginfo(HsailNotificationPayload* payload) { struct ui_out *uiout = NULL; /* pointer to shared memory*/ void* pShm = NULL; /* HwDbgFacilities objects */ HwDbgInfo_err errout_twolevel= HWDBGINFO_E_UNEXPECTED; HwDbgInfo_err errout_onelevel= HWDBGINFO_E_UNEXPECTED; HwDbgInfo_debug dbg_op = NULL; const int max_shared_mem_size = hsail_get_agent_binary_shmem_max_size(); if (payload == NULL) { /* return the cached dbgInfo there exists */ return gs_DbgInfo; } gdb_assert(payload->m_Notification == HSAIL_NOTIFY_NEW_BINARY); uiout = current_uiout; /* Shared memory buffer pointer*/ dbg_op = NULL; if(hsail_is_debug_facilities_loaded()) { /* A copy of the shared memory segment )*/ void* dbe_binary = NULL; size_t dbe_binary_size = 0; int shmid = -1; hsail_segment_update_loadmap(); /*1M used is hard wired for now*/ shmid = shmget(hsail_get_agent_binary_shmem_key(), max_shared_mem_size, 0666); if (shmid <= 0) { ui_out_text(uiout, "GDB: HwDbgFacilities init: shmid is invalid\n"); } gdb_assert(shmid > 0); /* Get shm pointer */ pShm = (int*)shmat(shmid, NULL, 0); if (pShm == NULL) { ui_out_text(uiout, "GDB: HwDbgFacilities init: pShm is NULL\n"); } gdb_assert(pShm != NULL); dbe_binary_size = ((size_t*)pShm)[0]; gdb_assert(dbe_binary_size > 0 && dbe_binary_size < max_shared_mem_size); dbe_binary = xmalloc(dbe_binary_size); gdb_assert(dbe_binary != NULL); memcpy(dbe_binary,(size_t*)pShm+1,dbe_binary_size); /* Uncomment this call if you need to save the binary to the file hsail_breakpoint_save_binary_to_file(dbe_binary_size, dbe_binary); */ /* Attempt to initialize as a HSAIL backend binary*/ dbg_op = hwdbginfo_init_with_hsa_1_0_binary(dbe_binary, dbe_binary_size, &errout_twolevel); /* Keep this printf here as a reminder for a * quick way to check that the IPC happened correctly*/ /* int i = 0; for(i = 0; i<10;i++) { printf("%d \t %d\n",i,*((int*)dbe_binary + i)); } */ /* If we get a no HL binary, return code, we try to initialize as a single level binary */ if (errout_twolevel == HWDBGINFO_E_NOHLBINARY) { /* dbg_op = hwdbginfo_init_with_single_level_binary(dbe_binary, dbe_binary_size, &errout_onelevel); */ dbg_op = NULL; } /* * In the near future, debug facilities needs to be able to tell the difference * between an incomplete 2 level code object and a complete 1 level code object. * Since we dont support debugging LC for 1.3, this is not a big issue. * */ /* If we have a single level binary, thats good, we dont need to check the * two level return code */ if (errout_twolevel == HWDBGINFO_E_NOHLBINARY && errout_onelevel == HWDBGINFO_E_SUCCESS) { fflush(stdout); } else if (errout_twolevel != HWDBGINFO_E_SUCCESS ) { /* HwDbgFacilities init: Called DebugFacilities Incorrectly. * We can add more detailed messages such as low-level dwarf or high level dwarf missing in the future * */ ui_out_text(uiout, "[ROCm-gdb]: The code object for the current dispatch does not contain debug information\n"); fflush(stdout); dbg_op = NULL; } /* Test function to print all the mapped addresses and line numbers */ /* hsail_dbginfo_test_all_mapped_addrs(dbg_op); */ /* We can clear the dbe_binary buffer once we have initialized HWDbgFacilities */ if (dbe_binary != NULL) { free_current_contents(&dbe_binary); } /* Get the kernel source, only if the 2 level initialization was good*/ if (errout_twolevel == HWDBGINFO_E_SUCCESS) { if (!hsail_dbginfo_init_source_buffer(dbg_op)) { ui_out_text(uiout, "[ROCm-gdb]: HwDbgFacilities get hsail text error\n"); } } /* Detach shared memory */ if (shmdt(pShm) == -1) { ui_out_text(uiout, "GDB: HwDbgFacilities init: Error detaching shm\n"); } } /* cache the dgbInfo */ gs_DbgInfo = dbg_op; return gs_DbgInfo; /* * This function's caller will use the returned context to query the * Debug Facilities API */ }
void print_command_lines (struct ui_out *uiout, struct command_line *cmd, unsigned int depth) { struct command_line *list; list = cmd; while (list) { if (depth) ui_out_spaces (uiout, 2 * depth); /* A simple command, print it and continue. */ if (list->control_type == simple_control) { ui_out_field_string (uiout, NULL, list->line); ui_out_text (uiout, "\n"); list = list->next; continue; } /* loop_continue to jump to the start of a while loop, print it and continue. */ if (list->control_type == continue_control) { ui_out_field_string (uiout, NULL, "loop_continue"); ui_out_text (uiout, "\n"); list = list->next; continue; } /* loop_break to break out of a while loop, print it and continue. */ if (list->control_type == break_control) { ui_out_field_string (uiout, NULL, "loop_break"); ui_out_text (uiout, "\n"); list = list->next; continue; } /* A while command. Recursively print its subcommands and continue. */ if (list->control_type == while_control || list->control_type == while_stepping_control) { /* For while-stepping, the line includes the 'while-stepping' token. See comment in process_next_line for explanation. Here, take care not print 'while-stepping' twice. */ if (list->control_type == while_control) ui_out_field_fmt (uiout, NULL, "while %s", list->line); else ui_out_field_string (uiout, NULL, list->line); ui_out_text (uiout, "\n"); print_command_lines (uiout, *list->body_list, depth + 1); if (depth) ui_out_spaces (uiout, 2 * depth); ui_out_field_string (uiout, NULL, "end"); ui_out_text (uiout, "\n"); list = list->next; continue; } /* An if command. Recursively print both arms before continueing. */ if (list->control_type == if_control) { ui_out_field_fmt (uiout, NULL, "if %s", list->line); ui_out_text (uiout, "\n"); /* The true arm. */ print_command_lines (uiout, list->body_list[0], depth + 1); /* Show the false arm if it exists. */ if (list->body_count == 2) { if (depth) ui_out_spaces (uiout, 2 * depth); ui_out_field_string (uiout, NULL, "else"); ui_out_text (uiout, "\n"); print_command_lines (uiout, list->body_list[1], depth + 1); } if (depth) ui_out_spaces (uiout, 2 * depth); ui_out_field_string (uiout, NULL, "end"); ui_out_text (uiout, "\n"); list = list->next; continue; } /* A commands command. Print the breakpoint commands and continue. */ if (list->control_type == commands_control) { if (*(list->line)) ui_out_field_fmt (uiout, NULL, "commands %s", list->line); else ui_out_field_string (uiout, NULL, "commands"); ui_out_text (uiout, "\n"); print_command_lines (uiout, *list->body_list, depth + 1); if (depth) ui_out_spaces (uiout, 2 * depth); ui_out_field_string (uiout, NULL, "end"); ui_out_text (uiout, "\n"); list = list->next; continue; } if (list->control_type == python_control) { ui_out_field_string (uiout, NULL, "python"); ui_out_text (uiout, "\n"); /* Don't indent python code at all. */ print_command_lines (uiout, *list->body_list, 0); if (depth) ui_out_spaces (uiout, 2 * depth); ui_out_field_string (uiout, NULL, "end"); ui_out_text (uiout, "\n"); list = list->next; continue; } /* Ignore illegal command type and try next. */ list = list->next; } /* while (list) */ }
void hsail_set_step_breakpoints(int step_type, int count) { struct ui_out* uiout = current_uiout; HwDbgInfo_debug dbg = hsail_init_hwdbginfo(NULL); HwDbgInfo_err err = HWDBGINFO_E_SUCCESS; uint64_t addr = hsail_tdep_get_current_pc(); HwDbgInfo_addr* step_addrs = NULL; size_t step_addr_count = 0; /* At the initial breakpoint, we are emulating the behavior of having the PC at the * opening brace. Thus, a "step over" should behave like a "step in". * */ if ((0 == addr) && (HSAIL_STEP_OVER == step_type)) step_type = HSAIL_STEP_IN; gdb_assert(NULL != dbg); gdb_assert((HSAIL_STEP_IN == step_type) || 0 != addr); /* Allow "step in" even if we don't have an address yet (i.e. in the pre-dispatch) */ if (NULL == dbg || ((HSAIL_STEP_IN != step_type) && (0 == addr))) { ui_out_text(uiout, "[ROCm-gdb]: could not perform GPU step\nContinuing execution...\n"); return; } /* TODO: support step "n" command */ if (1 != count) { ui_out_text(uiout, "[ROCm-gdb]: Only single steps are currently supported in hsail\nConverting to single step\n"); count = 1; } if (HSAIL_STEP_IN == step_type) { err = hwdbginfo_all_mapped_addrs(dbg, 0, NULL, &step_addr_count); gdb_assert(HWDBGINFO_E_SUCCESS == err); gdb_assert(0 != step_addr_count); step_addrs = step_addr_count > 0 ? (HwDbgInfo_addr*)malloc(step_addr_count * sizeof(HwDbgInfo_addr)) : NULL; gdb_assert(NULL != step_addrs); if ((HWDBGINFO_E_SUCCESS != err) || 0 == step_addr_count || NULL == step_addrs) { ui_out_text(uiout, "[ROCm-gdb]: Could not perform GPU step-in\nContinuing execution...\n"); return; } memset(step_addrs, 0, step_addr_count * sizeof(HwDbgInfo_addr)); err = hwdbginfo_all_mapped_addrs(dbg, step_addr_count, step_addrs, NULL); gdb_assert(HWDBGINFO_E_SUCCESS == err); if (HWDBGINFO_E_SUCCESS != err) { ui_out_text(uiout, "[ROCm-gdb]: Could not perform GPU step-in\nContinuing execution...\n"); free(step_addrs); return; } } else { /* Get the number of step addresses */ err = hwdbginfo_step_addresses(dbg, addr, (HSAIL_STEP_OUT == step_type), 0, NULL, &step_addr_count); gdb_assert(HWDBGINFO_E_SUCCESS == err); gdb_assert(0 != step_addr_count); step_addrs = step_addr_count > 0 ? (HwDbgInfo_addr*)malloc(step_addr_count * sizeof(HwDbgInfo_addr)) : NULL; gdb_assert(NULL != step_addrs); if ((HWDBGINFO_E_SUCCESS != err) || 0 == step_addr_count || NULL == step_addrs) { ui_out_text(uiout, "[ROCm-GDB]: Could not perform GPU step-over\nContinuing execution...\n"); return; } memset(step_addrs, 0, step_addr_count * sizeof(HwDbgInfo_addr)); /* Get the step addresses */ err = hwdbginfo_step_addresses(dbg, addr, (HSAIL_STEP_OUT == step_type), step_addr_count, step_addrs, NULL); gdb_assert(HWDBGINFO_E_SUCCESS == err); if (HWDBGINFO_E_SUCCESS != err) { ui_out_text(uiout, "[ROCm-gdb]: Could not perform GPU step-over\nContinuing execution...\n"); free(step_addrs); return; } } /* Write momentary breakpoints to shared memory */ hsail_step_write_momentary_breakpoints(dbg, step_addr_count,step_addrs); /* Notify the agent */ hsail_enqueue_momentary_breakpoint_packet(step_addr_count); /* Prepare the agent to have the "continue" issued: */ hsail_set_continue_dispatch(); }
static int dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, struct disassemble_info * di, CORE_ADDR low, CORE_ADDR high, int how_many, int flags, struct ui_stream *stb) { int num_displayed = 0; CORE_ADDR pc; /* parts of the symbolic representation of the address */ int unmapped; int offset; int line; struct cleanup *ui_out_chain; for (pc = low; pc < high;) { char *filename = NULL; char *name = NULL; QUIT; if (how_many >= 0) { if (num_displayed >= how_many) break; else num_displayed++; } ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_text (uiout, pc_prefix (pc)); ui_out_field_core_addr (uiout, "address", gdbarch, pc); if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename, &line, &unmapped)) { /* We don't care now about line, filename and unmapped. But we might in the future. */ ui_out_text (uiout, " <"); if ((flags & DISASSEMBLY_OMIT_FNAME) == 0) ui_out_field_string (uiout, "func-name", name); ui_out_text (uiout, "+"); ui_out_field_int (uiout, "offset", offset); ui_out_text (uiout, ">:\t"); } else ui_out_text (uiout, ":\t"); if (filename != NULL) xfree (filename); if (name != NULL) xfree (name); ui_file_rewind (stb->stream); if (flags & DISASSEMBLY_RAW_INSN) { CORE_ADDR old_pc = pc; bfd_byte data; int status; const char *spacer = ""; /* Build the opcodes using a temporary stream so we can write them out in a single go for the MI. */ struct ui_stream *opcode_stream = ui_out_stream_new (uiout); struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (opcode_stream); pc += gdbarch_print_insn (gdbarch, pc, di); for (;old_pc < pc; old_pc++) { status = (*di->read_memory_func) (old_pc, &data, 1, di); if (status != 0) (*di->memory_error_func) (status, old_pc, di); fprintf_filtered (opcode_stream->stream, "%s%02x", spacer, (unsigned) data); spacer = " "; } ui_out_field_stream (uiout, "opcodes", opcode_stream); ui_out_text (uiout, "\t"); do_cleanups (cleanups); } else pc += gdbarch_print_insn (gdbarch, pc, di); ui_out_field_stream (uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); ui_out_text (uiout, "\n"); } return num_displayed; }
static int dump_insns (struct ui_out *uiout, struct disassemble_info * di, CORE_ADDR low, CORE_ADDR high, int how_many, struct ui_stream *stb) { int num_displayed = 0; CORE_ADDR pc; /* parts of the symbolic representation of the address */ int unmapped; int offset; int line; struct cleanup *ui_out_chain; struct cleanup *table_chain; struct cleanup *tuple_chain; for (pc = low; pc < high;) { char *filename = NULL; char *name = NULL; QUIT; if (how_many >= 0) { if (num_displayed >= how_many) break; else num_displayed++; } ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_core_addr (uiout, "address", pc); if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped)) { /* We don't care now about line, filename and unmapped. But we might in the future. */ ui_out_text (uiout, " <"); ui_out_field_string (uiout, "func-name", name); ui_out_text (uiout, "+"); ui_out_field_int (uiout, "offset", offset); ui_out_text (uiout, ">: "); } else ui_out_text (uiout, ": "); if (filename != NULL) xfree (filename); if (name != NULL) xfree (name); ui_file_rewind (stb->stream); // dump the disassembly raw bytes - ripped from gnu gdb latest cvs version // fG! - 12/08/2009 // save the initial disassembly address CORE_ADDR old_pc = pc; bfd_byte data; int status; int i; // this will return the disassembled instructions, but it will be buffered into the stream // pc will hold the final address after the disassembly, so we can compute the length of the instruction // the macro returns the number of bytes disassembled pc += TARGET_PRINT_INSN (pc, di); i = pc - old_pc; // read the bytes from the initial address to the final address for (; old_pc < pc; old_pc++) { status = (*di->read_memory_func) (old_pc, &data, 1, di); if (status != 0) (*di->memory_error_func) (status, old_pc, di); // print the raw bytes ui_out_message (uiout, 0, " %02x", (unsigned)data); } // to align the output... gdb tables don't work correctly :( for (; i < 10 ; i++) ui_out_text(uiout, " "); ui_out_text(uiout, " "); // now we can finally print the buffered stream ui_out_field_stream (uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); ui_out_text (uiout, "\n"); } return num_displayed; }
/* * Display a disassembled instruction with annotation */ static void print_one_insn(struct ca_dis_insn* insn, struct ui_out* uiout) { int i, pos; struct ca_operand* dst_op; ui_out_text(uiout, insn->dis_string); pos = strlen(insn->dis_string); if (pos < MAX_SPACING) ui_out_spaces(uiout, MAX_SPACING - pos); ui_out_text(uiout, " ## "); if (insn->num_operand == 0) { ui_out_text(uiout, "\n"); return; } // special case /*if (insn->call) { // reminder that $rax is set to return value after a "call" instruction // if the called function has an integer return value // (unfortunately return type is not known for a function) ui_out_text(uiout, "(%rax=? on return) "); }*/ dst_op = &insn->operands[0]; // annotation of object context if (insn->annotate) { size_t ptr_sz = g_ptr_bit >> 3; int has_value = 0; size_t val = 0xcdcdcdcd; int op_size = insn->op_size; const char* symname = NULL; struct win_type type = {0,0}; int is_vptr = 0; char* name_to_free = NULL; // update register context by "pc" set_current_reg_pointers(insn); // Get the instruction's destination value/symbol/type if (dst_op->type == CA_OP_MEMORY) { // if the destination is a known local variable if (is_stack_address(dst_op)) { address_t addr = get_address(dst_op); struct ca_stack_var* sval = get_stack_var(addr); if (sval) { symname = sval->sym_name; type = sval->type; } else { /*struct symbol* sym; struct object_reference aref; memset(&aref, 0, sizeof(aref)); aref.vaddr = addr; aref.value = 0; aref.target_index = -1; sym = get_stack_sym(&aref, NULL, NULL); if (sym) { symname = SYMBOL_PRINT_NAME (sym); type = SYMBOL_TYPE(sym); }*/ get_stack_sym_and_type(addr, &symname, &type); } } // could it be a known heap object if (!symname && !type.mod_base) { // this function will allocate buffer for the symbol name if any, remember to free it get_op_symbol_type(dst_op, 0, &name_to_free, &type, NULL); symname = name_to_free; } // Since flag insn->annotate is set, dst_op's value should be calculated val = get_op_value(dst_op, op_size); has_value = 1; } else if (dst_op->type == CA_OP_REGISTER) { struct ca_reg_value* dst_reg = get_reg_at_pc(dst_op->reg.index, insn->pc); if (dst_reg) { symname = dst_reg->sym_name; type = dst_reg->type; is_vptr = dst_reg->vptr; if (dst_reg->has_value) { has_value = 1; val = dst_reg->value; } } } else if (dst_op->type == CA_OP_IMMEDIATE) { val = get_op_value(dst_op, op_size); has_value = 1; } if (dst_op->type != CA_OP_IMMEDIATE) { // Name and value (if known) of destination print_one_operand(uiout, dst_op, op_size); if (has_value) ui_out_message(uiout, 0, "="PRINT_FORMAT_POINTER, val); else ui_out_text(uiout, "=?"); } // Symbol or type of destination if (dst_op->type == CA_OP_REGISTER && dst_op->reg.index == RSP) { if (val == g_debug_context.sp) ui_out_text(uiout, " End of function prologue"); ui_out_text(uiout, "\n"); } else { // symbol or type is known if (symname || type.mod_base) { ui_out_text(uiout, "("); if (symname) { ui_out_message(uiout, 0, "symbol=\"%s\"", symname); } if (type.mod_base) { //CHECK_TYPEDEF(type); if (symname) ui_out_text(uiout, " "); ui_out_text(uiout, "type=\""); /*if (is_vptr) { const char * type_name = type_name_no_tag(type); if (type_name) ui_out_message(uiout, 0, "vtable for %s", type_name); else { ui_out_text(uiout, "vtable for "); print_type_name (type); } } else*/ print_type_name (type); ui_out_text(uiout, "\""); } ui_out_text(uiout, ")\n"); } // whatever we can get form the value else { address_t location = 0; int offset = 0; //if (insn->num_operand > 1) //{ // struct ca_operand* src_op = &insn->operands[1]; // get_location(src_op, &location, &offset); //} print_op_value_context (val, op_size > 0 ? op_size : ptr_sz, location, offset, insn->lea); } } if (name_to_free) free (name_to_free); }
/* * First, disassemble all instructions of the function and store them in buffer * Second, follow and calculate register values at each instruction * Finally, display all disassembled instruction with annotation of object context */ int decode_insns(struct decode_control_block* decode_cb) { unsigned int insn_index, i; int num_insns = 0; struct gdbarch *gdbarch = decode_cb->gdbarch; struct ui_out *uiout = decode_cb->uiout; // Disassemble the whole function even if user chooses // only a subset of it num_insns += dump_insns(decode_cb); // copy known function parameters init_reg_table(decode_cb->param_regs); init_stack_vars(); g_reg_table.cur_regs[RIP]->has_value = 1; // Annotate the context of each instruction for (insn_index = 0; insn_index < g_num_insns; insn_index++) { int cur_insn = 0; struct ca_dis_insn* insn = &g_insns_buffer[insn_index]; // update program counter for RIP-relative instruction // RIP points to the address of the next instruction before executing current one if (insn_index + 1 < g_num_insns) set_reg_value_at_pc(RIP, (insn+1)->pc, insn->pc); // user may set some register values deliberately if (decode_cb->user_regs) { if (insn->pc == decode_cb->low || (insn_index + 1 < g_num_insns && g_insns_buffer[insn_index + 1].pc > decode_cb->low) ) { if (insn->pc == decode_cb->func_start) set_reg_table_at_pc(decode_cb->user_regs, 0); else set_reg_table_at_pc(decode_cb->user_regs, insn->pc); } } // analyze and update register context affected by this instruction if (decode_cb->innermost_frame) { if (insn->pc == decode_cb->current) cur_insn = 1; } else if (insn_index + 1 < g_num_insns && g_insns_buffer[insn_index + 1].pc == decode_cb->current) cur_insn = 1; process_one_insn(insn, cur_insn); if (cur_insn) { // return the register context back to caller for (i = 0; i < TOTAL_REGS; i++) { struct ca_reg_value* reg = g_reg_table.cur_regs[i]; if (reg->has_value) { // only pass on values, symbol may be out of context in another function struct ca_reg_value* dst = &decode_cb->param_regs[i]; memcpy(dst, reg, sizeof(struct ca_reg_value)); dst->sym_name = NULL; } } } } if (decode_cb->verbose) validate_reg_table(); // display disassembled insns for (insn_index = 0; insn_index < g_num_insns; insn_index++) { struct ca_dis_insn* insn = &g_insns_buffer[insn_index]; // parts of the symbolic representation of the address int unmapped; int offset; int line; char *filename = NULL; char *name = NULL; if (insn->pc >= decode_cb->high) break; else if (insn->pc >= decode_cb->low) { // instruction address + offset ui_out_text(uiout, pc_prefix(insn->pc)); ui_out_field_core_addr(uiout, "address", gdbarch, insn->pc); if (!build_address_symbolic(gdbarch, insn->pc, 0, &name, &offset, &filename, &line, &unmapped)) { ui_out_text(uiout, " <"); //if (decode_cb->verbose) // ui_out_field_string(uiout, "func-name", name); ui_out_text(uiout, "+"); ui_out_field_int(uiout, "offset", offset); ui_out_text(uiout, ">:\t"); } else ui_out_message(uiout, 0, "<+%ld>:\t", insn->pc - decode_cb->func_start); // disassembled instruction with annotation print_one_insn(insn, uiout); if (filename != NULL) free(filename); if (name != NULL) free(name); } } reset_reg_table(); reset_stack_vars(); return num_insns; }