| /* |
| ** tuiDisassem.c |
| ** This module contains functions for handling disassembly display. |
| */ |
| |
| |
| #include "defs.h" |
| #include "symtab.h" |
| #include "breakpoint.h" |
| #include "frame.h" |
| |
| #include "tui.h" |
| #include "tuiData.h" |
| #include "tuiLayout.h" |
| #include "tuiSourceWin.h" |
| #include "tuiStack.h" |
| |
| |
| /***************************************** |
| ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** |
| ******************************************/ |
| |
| static struct breakpoint *_hasBreak (CORE_ADDR); |
| |
| |
| /***************************************** |
| ** PUBLIC FUNCTIONS ** |
| ******************************************/ |
| |
| /* |
| ** tuiSetDisassemContent(). |
| ** Function to set the disassembly window's content. |
| */ |
| TuiStatus |
| #ifdef __STDC__ |
| tuiSetDisassemContent ( |
| struct symtab *s, |
| Opaque startAddr) |
| #else |
| tuiSetDisassemContent (s, startAddr) |
| struct symtab *s; |
| Opaque startAddr; |
| #endif |
| { |
| TuiStatus ret = TUI_FAILURE; |
| struct ui_file *gdb_dis_out; |
| |
| if (startAddr != (Opaque) NULL) |
| { |
| register int i, desc; |
| |
| if ((ret = tuiAllocSourceBuffer (disassemWin)) == TUI_SUCCESS) |
| { |
| register int offset = disassemWin->detail.sourceInfo.horizontalOffset; |
| register int threshold, curLine = 0, lineWidth, maxLines; |
| CORE_ADDR newpc, pc; |
| disassemble_info asmInfo; |
| TuiGenWinInfoPtr locator = locatorWinInfoPtr (); |
| extern void strcat_address (CORE_ADDR, char *, int); |
| extern void strcat_address_numeric (CORE_ADDR, int, char *, int); |
| int curLen = 0; |
| int tab_len = tuiDefaultTabLen (); |
| |
| maxLines = disassemWin->generic.height - 2; /* account for hilite */ |
| lineWidth = disassemWin->generic.width - 1; |
| threshold = (lineWidth - 1) + offset; |
| |
| /* now init the ui_file structure */ |
| gdb_dis_out = tui_sfileopen (threshold); |
| |
| INIT_DISASSEMBLE_INFO_NO_ARCH (asmInfo, gdb_dis_out, (fprintf_ftype) fprintf_filtered); |
| asmInfo.read_memory_func = dis_asm_read_memory; |
| asmInfo.memory_error_func = dis_asm_memory_error; |
| |
| disassemWin->detail.sourceInfo.startLineOrAddr.addr = startAddr; |
| |
| /* Now construct each line */ |
| for (curLine = 0, pc = (CORE_ADDR) startAddr; (curLine < maxLines);) |
| { |
| TuiWinElementPtr element = (TuiWinElementPtr) disassemWin->generic.content[curLine]; |
| struct breakpoint *bp; |
| |
| print_address (pc, gdb_dis_out); |
| |
| curLen = strlen (tui_file_get_strbuf (gdb_dis_out)); |
| i = curLen - ((curLen / tab_len) * tab_len); |
| |
| /* adjust buffer length if necessary */ |
| tui_file_adjust_strbuf ((tab_len - i > 0) ? (tab_len - i) : 0, gdb_dis_out); |
| |
| /* Add spaces to make the instructions start onthe same column */ |
| while (i < tab_len) |
| { |
| tui_file_get_strbuf (gdb_dis_out)[curLen] = ' '; |
| i++; |
| curLen++; |
| } |
| tui_file_get_strbuf (gdb_dis_out)[curLen] = '\0'; |
| |
| newpc = pc + ((*tm_print_insn) (pc, &asmInfo)); |
| |
| /* Now copy the line taking the offset into account */ |
| if (strlen (tui_file_get_strbuf (gdb_dis_out)) > offset) |
| strcpy (element->whichElement.source.line, |
| &(tui_file_get_strbuf (gdb_dis_out)[offset])); |
| else |
| element->whichElement.source.line[0] = '\0'; |
| element->whichElement.source.lineOrAddr.addr = (Opaque) pc; |
| element->whichElement.source.isExecPoint = |
| (pc == (CORE_ADDR) ((TuiWinElementPtr) locator->content[0])->whichElement.locator.addr); |
| bp = _hasBreak (pc); |
| element->whichElement.source.hasBreak = |
| (bp != (struct breakpoint *) NULL && |
| (!element->whichElement.source.isExecPoint || |
| (bp->disposition != del || bp->hit_count <= 0))); |
| curLine++; |
| pc = newpc; |
| /* reset the buffer to empty */ |
| tui_file_get_strbuf (gdb_dis_out)[0] = '\0'; |
| } |
| ui_file_delete (gdb_dis_out); |
| gdb_dis_out = NULL; |
| disassemWin->generic.contentSize = curLine; |
| ret = TUI_SUCCESS; |
| } |
| } |
| |
| return ret; |
| } /* tuiSetDisassemContent */ |
| |
| |
| /* |
| ** tuiShowDisassem(). |
| ** Function to display the disassembly window with disassembled code. |
| */ |
| void |
| #ifdef __STDC__ |
| tuiShowDisassem ( |
| Opaque startAddr) |
| #else |
| tuiShowDisassem (startAddr) |
| Opaque startAddr; |
| #endif |
| { |
| struct symtab *s = find_pc_symtab ((CORE_ADDR) startAddr); |
| TuiWinInfoPtr winWithFocus = tuiWinWithFocus (); |
| |
| tuiAddWinToLayout (DISASSEM_WIN); |
| tuiUpdateSourceWindow (disassemWin, s, startAddr, FALSE); |
| /* |
| ** if the focus was in the src win, put it in the asm win, if the |
| ** source view isn't split |
| */ |
| if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin) |
| tuiSetWinFocusTo (disassemWin); |
| |
| return; |
| } /* tuiShowDisassem */ |
| |
| |
| /* |
| ** tuiShowDisassemAndUpdateSource(). |
| ** Function to display the disassembly window. |
| */ |
| void |
| #ifdef __STDC__ |
| tuiShowDisassemAndUpdateSource ( |
| Opaque startAddr) |
| #else |
| tuiShowDisassemAndUpdateSource (startAddr) |
| Opaque startAddr; |
| #endif |
| { |
| struct symtab_and_line sal; |
| |
| tuiShowDisassem (startAddr); |
| if (currentLayout () == SRC_DISASSEM_COMMAND) |
| { |
| TuiGenWinInfoPtr locator = locatorWinInfoPtr (); |
| /* |
| ** Update what is in the source window if it is displayed too, |
| ** note that it follows what is in the disassembly window and visa-versa |
| */ |
| sal = find_pc_line ((CORE_ADDR) startAddr, 0); |
| current_source_symtab = sal.symtab; |
| tuiUpdateSourceWindow (srcWin, sal.symtab, (Opaque) sal.line, TRUE); |
| tuiUpdateLocatorFilename (sal.symtab->filename); |
| } |
| |
| return; |
| } /* tuiShowDisassemAndUpdateSource */ |
| |
| |
| /* |
| ** tuiShowDisassemAsIs(). |
| ** Function to display the disassembly window. This function shows |
| ** the disassembly as specified by the horizontal offset. |
| */ |
| void |
| #ifdef __STDC__ |
| tuiShowDisassemAsIs ( |
| Opaque addr) |
| #else |
| tuiShowDisassemAsIs (addr) |
| Opaque addr; |
| #endif |
| { |
| tuiAddWinToLayout (DISASSEM_WIN); |
| tuiUpdateSourceWindowAsIs (disassemWin, (struct symtab *) NULL, addr, FALSE); |
| /* |
| ** Update what is in the source window if it is displayed too, not that it |
| ** follows what is in the disassembly window and visa-versa |
| */ |
| if (currentLayout () == SRC_DISASSEM_COMMAND) |
| tuiShowSourceContent (srcWin); /*???? Need to do more? */ |
| |
| return; |
| } /* tuiShowDisassem */ |
| |
| |
| /* |
| ** tuiGetBeginAsmAddress(). |
| */ |
| Opaque |
| #ifdef __STDC__ |
| tuiGetBeginAsmAddress (void) |
| #else |
| tuiGetBeginAsmAddress () |
| #endif |
| { |
| TuiGenWinInfoPtr locator; |
| TuiLocatorElementPtr element; |
| Opaque addr; |
| |
| locator = locatorWinInfoPtr (); |
| element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator; |
| |
| if (element->addr == (Opaque) 0) |
| { |
| /*the target is not executing, because the pc is 0 */ |
| |
| addr = (Opaque) parse_and_eval_address ("main"); |
| |
| if (addr == (Opaque) 0) |
| addr = (Opaque) parse_and_eval_address ("MAIN"); |
| |
| } |
| else /* the target is executing */ |
| addr = element->addr; |
| |
| return addr; |
| } /* tuiGetBeginAsmAddress */ |
| |
| |
| /* |
| ** tuiVerticalDisassemScroll(). |
| ** Scroll the disassembly forward or backward vertically |
| */ |
| void |
| #ifdef __STDC__ |
| tuiVerticalDisassemScroll ( |
| TuiScrollDirection scrollDirection, |
| int numToScroll) |
| #else |
| tuiVerticalDisassemScroll (scrollDirection, numToScroll) |
| TuiScrollDirection scrollDirection; |
| int numToScroll; |
| #endif |
| { |
| if (disassemWin->generic.content != (OpaquePtr) NULL) |
| { |
| Opaque pc, lowAddr; |
| TuiWinContent content; |
| struct symtab *s; |
| |
| content = (TuiWinContent) disassemWin->generic.content; |
| if (current_source_symtab == (struct symtab *) NULL) |
| s = find_pc_symtab (selected_frame->pc); |
| else |
| s = current_source_symtab; |
| |
| pc = content[0]->whichElement.source.lineOrAddr.addr; |
| if (find_pc_partial_function ((CORE_ADDR) pc, |
| (char **) NULL, |
| (CORE_ADDR *) & lowAddr, |
| (CORE_ADDR) NULL) == 0) |
| error ("No function contains prgram counter for selected frame.\n"); |
| else |
| { |
| register int line = 0; |
| register Opaque newLow; |
| bfd_byte buffer[4]; |
| |
| newLow = pc; |
| if (scrollDirection == FORWARD_SCROLL) |
| { |
| for (; line < numToScroll; line++) |
| newLow += sizeof (bfd_getb32 (buffer)); |
| } |
| else |
| { |
| for (; newLow >= (Opaque) 0 && line < numToScroll; line++) |
| newLow -= sizeof (bfd_getb32 (buffer)); |
| } |
| tuiUpdateSourceWindowAsIs (disassemWin, s, newLow, FALSE); |
| } |
| } |
| |
| return; |
| } /* tuiVerticalDisassemScroll */ |
| |
| |
| |
| /***************************************** |
| ** STATIC LOCAL FUNCTIONS ** |
| ******************************************/ |
| /* |
| ** _hasBreak(). |
| ** Answer whether there is a break point at the input line in the |
| ** source file indicated |
| */ |
| static struct breakpoint * |
| #ifdef __STDC__ |
| _hasBreak ( |
| CORE_ADDR addr) |
| #else |
| _hasBreak (addr) |
| CORE_ADDR addr; |
| #endif |
| { |
| struct breakpoint *bpWithBreak = (struct breakpoint *) NULL; |
| struct breakpoint *bp; |
| extern struct breakpoint *breakpoint_chain; |
| |
| |
| for (bp = breakpoint_chain; |
| (bp != (struct breakpoint *) NULL && |
| bpWithBreak == (struct breakpoint *) NULL); |
| bp = bp->next) |
| if (addr == bp->address) |
| bpWithBreak = bp; |
| |
| return bpWithBreak; |
| } /* _hasBreak */ |