Commit | Line | Data |
---|---|---|
03b93bdc DT |
1 | /* |
2 | ** tuiDisassem.c | |
3 | ** This module contains functions for handling disassembly display. | |
4 | */ | |
5 | ||
6 | ||
7 | #include "defs.h" | |
8 | #include "symtab.h" | |
9 | #include "breakpoint.h" | |
10 | #include "frame.h" | |
11 | ||
12 | #include "tui.h" | |
13 | #include "tuiData.h" | |
14 | #include "tuiLayout.h" | |
15 | #include "tuiSourceWin.h" | |
16 | #include "tuiStack.h" | |
17 | ||
18 | ||
19 | /***************************************** | |
20 | ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** | |
21 | ******************************************/ | |
22 | ||
23 | static struct breakpoint *_hasBreak PARAMS ((CORE_ADDR)); | |
24 | ||
25 | ||
26 | /***************************************** | |
27 | ** PUBLIC FUNCTIONS ** | |
28 | ******************************************/ | |
29 | ||
30 | /* | |
31 | ** tuiSetDisassemContent(). | |
32 | ** Function to set the disassembly window's content. | |
33 | */ | |
34 | TuiStatus | |
35 | #ifdef __STDC__ | |
36 | tuiSetDisassemContent ( | |
37 | struct symtab *s, | |
38 | Opaque startAddr) | |
39 | #else | |
40 | tuiSetDisassemContent (s, startAddr) | |
41 | struct symtab *s; | |
42 | Opaque startAddr; | |
43 | #endif | |
44 | { | |
45 | TuiStatus ret = TUI_FAILURE; | |
46 | GDB_FILE *gdb_dis_out; | |
47 | ||
48 | if (startAddr != (Opaque) NULL) | |
49 | { | |
50 | register int i, desc; | |
51 | ||
52 | if ((ret = tuiAllocSourceBuffer (disassemWin)) == TUI_SUCCESS) | |
53 | { | |
54 | register int offset = disassemWin->detail.sourceInfo.horizontalOffset; | |
55 | register int threshold, curLine = 0, lineWidth, maxLines; | |
56 | CORE_ADDR newpc, pc; | |
57 | disassemble_info asmInfo; | |
58 | TuiGenWinInfoPtr locator = locatorWinInfoPtr (); | |
59 | extern void strcat_address PARAMS ((CORE_ADDR, char *, int)); | |
60 | extern void strcat_address_numeric PARAMS ((CORE_ADDR, int, char *, int)); | |
61 | int curLen = 0; | |
62 | int tab_len = tuiDefaultTabLen (); | |
63 | ||
64 | maxLines = disassemWin->generic.height - 2; /* account for hilite */ | |
65 | lineWidth = disassemWin->generic.width - 1; | |
66 | threshold = (lineWidth - 1) + offset; | |
67 | ||
68 | /* now init the gdb_file structure */ | |
69 | gdb_dis_out = gdb_file_init_astring (threshold); | |
70 | ||
71 | INIT_DISASSEMBLE_INFO_NO_ARCH (asmInfo, gdb_dis_out, (fprintf_ftype) fprintf_filtered); | |
72 | asmInfo.read_memory_func = dis_asm_read_memory; | |
73 | asmInfo.memory_error_func = dis_asm_memory_error; | |
74 | ||
75 | disassemWin->detail.sourceInfo.startLineOrAddr.addr = startAddr; | |
76 | ||
77 | /* Now construct each line */ | |
78 | for (curLine = 0, pc = (CORE_ADDR) startAddr; (curLine < maxLines);) | |
79 | { | |
80 | TuiWinElementPtr element = (TuiWinElementPtr)disassemWin->generic.content[curLine]; | |
81 | struct breakpoint *bp; | |
82 | ||
83 | print_address (pc, gdb_dis_out); | |
84 | ||
85 | curLen = strlen (gdb_file_get_strbuf (gdb_dis_out)); | |
86 | i = curLen - ((curLen / tab_len) * tab_len); | |
87 | ||
88 | /* adjust buffer length if necessary */ | |
89 | gdb_file_adjust_strbuf ((tab_len - i > 0) ? (tab_len - i ) : 0, gdb_dis_out); | |
90 | ||
91 | /* Add spaces to make the instructions start onthe same column */ | |
92 | while (i < tab_len) | |
93 | { | |
94 | gdb_file_get_strbuf (gdb_dis_out)[curLen] = ' '; | |
95 | i++; | |
96 | curLen++; | |
97 | } | |
98 | gdb_file_get_strbuf (gdb_dis_out)[curLen] = '\0'; | |
99 | ||
100 | newpc = pc + ((*tm_print_insn) (pc, &asmInfo)); | |
101 | ||
102 | /* Now copy the line taking the offset into account */ | |
103 | if (strlen (gdb_file_get_strbuf (gdb_dis_out)) > offset) | |
104 | strcpy (element->whichElement.source.line, | |
105 | &(gdb_file_get_strbuf (gdb_dis_out)[offset])); | |
106 | else | |
107 | element->whichElement.source.line[0] = '\0'; | |
108 | element->whichElement.source.lineOrAddr.addr = (Opaque) pc; | |
109 | element->whichElement.source.isExecPoint = | |
110 | (pc == (CORE_ADDR) ((TuiWinElementPtr)locator->content[0])->whichElement.locator.addr); | |
111 | bp = _hasBreak (pc); | |
112 | element->whichElement.source.hasBreak = | |
113 | (bp != (struct breakpoint *) NULL && | |
114 | (!element->whichElement.source.isExecPoint || | |
115 | (bp->disposition != del || bp->hit_count <= 0))); | |
116 | curLine++; | |
117 | pc = newpc; | |
118 | /* reset the buffer to empty */ | |
119 | gdb_file_get_strbuf (gdb_dis_out)[0] = '\0'; | |
120 | } | |
121 | gdb_file_deallocate (&gdb_dis_out); | |
122 | disassemWin->generic.contentSize = curLine; | |
123 | ret = TUI_SUCCESS; | |
124 | } | |
125 | } | |
126 | ||
127 | return ret; | |
128 | } /* tuiSetDisassemContent */ | |
129 | ||
130 | ||
131 | /* | |
132 | ** tuiShowDisassem(). | |
133 | ** Function to display the disassembly window with disassembled code. | |
134 | */ | |
135 | void | |
136 | #ifdef __STDC__ | |
137 | tuiShowDisassem ( | |
138 | Opaque startAddr) | |
139 | #else | |
140 | tuiShowDisassem (startAddr) | |
141 | Opaque startAddr; | |
142 | #endif | |
143 | { | |
144 | struct symtab *s = find_pc_symtab ((CORE_ADDR) startAddr); | |
145 | TuiWinInfoPtr winWithFocus = tuiWinWithFocus (); | |
146 | ||
147 | tuiAddWinToLayout (DISASSEM_WIN); | |
148 | tuiUpdateSourceWindow (disassemWin, s, startAddr, FALSE); | |
149 | /* | |
150 | ** if the focus was in the src win, put it in the asm win, if the | |
151 | ** source view isn't split | |
152 | */ | |
153 | if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin) | |
154 | tuiSetWinFocusTo (disassemWin); | |
155 | ||
156 | return; | |
157 | } /* tuiShowDisassem */ | |
158 | ||
159 | ||
160 | /* | |
161 | ** tuiShowDisassemAndUpdateSource(). | |
162 | ** Function to display the disassembly window. | |
163 | */ | |
164 | void | |
165 | #ifdef __STDC__ | |
166 | tuiShowDisassemAndUpdateSource ( | |
167 | Opaque startAddr) | |
168 | #else | |
169 | tuiShowDisassemAndUpdateSource (startAddr) | |
170 | Opaque startAddr; | |
171 | #endif | |
172 | { | |
173 | struct symtab_and_line sal; | |
174 | ||
175 | tuiShowDisassem (startAddr); | |
176 | if (currentLayout () == SRC_DISASSEM_COMMAND) | |
177 | { | |
178 | TuiGenWinInfoPtr locator = locatorWinInfoPtr (); | |
179 | /* | |
180 | ** Update what is in the source window if it is displayed too, | |
181 | ** note that it follows what is in the disassembly window and visa-versa | |
182 | */ | |
183 | sal = find_pc_line ((CORE_ADDR) startAddr, 0); | |
184 | current_source_symtab = sal.symtab; | |
185 | tuiUpdateSourceWindow (srcWin, sal.symtab, (Opaque) sal.line, TRUE); | |
186 | tuiUpdateLocatorFilename (sal.symtab->filename); | |
187 | } | |
188 | ||
189 | return; | |
190 | } /* tuiShowDisassemAndUpdateSource */ | |
191 | ||
192 | ||
193 | /* | |
194 | ** tuiShowDisassemAsIs(). | |
195 | ** Function to display the disassembly window. This function shows | |
196 | ** the disassembly as specified by the horizontal offset. | |
197 | */ | |
198 | void | |
199 | #ifdef __STDC__ | |
200 | tuiShowDisassemAsIs ( | |
201 | Opaque addr) | |
202 | #else | |
203 | tuiShowDisassemAsIs (addr) | |
204 | Opaque addr; | |
205 | #endif | |
206 | { | |
207 | tuiAddWinToLayout (DISASSEM_WIN); | |
208 | tuiUpdateSourceWindowAsIs (disassemWin, (struct symtab *) NULL, addr, FALSE); | |
209 | /* | |
210 | ** Update what is in the source window if it is displayed too, not that it | |
211 | ** follows what is in the disassembly window and visa-versa | |
212 | */ | |
213 | if (currentLayout () == SRC_DISASSEM_COMMAND) | |
214 | tuiShowSourceContent (srcWin); /*???? Need to do more? */ | |
215 | ||
216 | return; | |
217 | } /* tuiShowDisassem */ | |
218 | ||
219 | ||
220 | /* | |
221 | ** tuiGetBeginAsmAddress(). | |
222 | */ | |
223 | Opaque | |
224 | #ifdef __STDC__ | |
225 | tuiGetBeginAsmAddress (void) | |
226 | #else | |
227 | tuiGetBeginAsmAddress () | |
228 | #endif | |
229 | { | |
230 | TuiGenWinInfoPtr locator; | |
231 | TuiLocatorElementPtr element; | |
232 | Opaque addr; | |
233 | ||
234 | locator = locatorWinInfoPtr (); | |
235 | element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator; | |
236 | ||
237 | if (element->addr == (Opaque) 0) | |
238 | { | |
239 | /*the target is not executing, because the pc is 0*/ | |
240 | ||
241 | addr = (Opaque) parse_and_eval_address ("main"); | |
242 | ||
243 | if (addr == (Opaque) 0) | |
244 | addr = (Opaque) parse_and_eval_address ("MAIN"); | |
245 | ||
246 | } | |
247 | else /* the target is executing */ | |
248 | addr = element->addr; | |
249 | ||
250 | return addr; | |
251 | } /* tuiGetBeginAsmAddress */ | |
252 | ||
253 | ||
254 | /* | |
255 | ** tuiVerticalDisassemScroll(). | |
256 | ** Scroll the disassembly forward or backward vertically | |
257 | */ | |
258 | void | |
259 | #ifdef __STDC__ | |
260 | tuiVerticalDisassemScroll ( | |
261 | TuiScrollDirection scrollDirection, | |
262 | int numToScroll) | |
263 | #else | |
264 | tuiVerticalDisassemScroll (scrollDirection, numToScroll) | |
265 | TuiScrollDirection scrollDirection; | |
266 | int numToScroll; | |
267 | #endif | |
268 | { | |
269 | if (disassemWin->generic.content != (OpaquePtr) NULL) | |
270 | { | |
271 | Opaque pc, lowAddr; | |
272 | TuiWinContent content; | |
273 | struct symtab *s; | |
274 | ||
275 | content = (TuiWinContent) disassemWin->generic.content; | |
276 | if (current_source_symtab == (struct symtab *) NULL) | |
277 | s = find_pc_symtab (selected_frame->pc); | |
278 | else | |
279 | s = current_source_symtab; | |
280 | ||
281 | pc = content[0]->whichElement.source.lineOrAddr.addr; | |
282 | if (find_pc_partial_function ((CORE_ADDR) pc, | |
283 | (char **) NULL, | |
284 | (CORE_ADDR *) & lowAddr, | |
285 | (CORE_ADDR) NULL) == 0) | |
286 | error ("No function contains prgram counter for selected frame.\n"); | |
287 | else | |
288 | { | |
289 | register int line = 0; | |
290 | register Opaque newLow; | |
291 | bfd_byte buffer[4]; | |
292 | ||
293 | newLow = pc; | |
294 | if (scrollDirection == FORWARD_SCROLL) | |
295 | { | |
296 | for (; line < numToScroll; line++) | |
297 | newLow += sizeof (bfd_getb32 (buffer)); | |
298 | } | |
299 | else | |
300 | { | |
301 | for (; newLow >= (Opaque) 0 && line < numToScroll; line++) | |
302 | newLow -= sizeof (bfd_getb32 (buffer)); | |
303 | } | |
304 | tuiUpdateSourceWindowAsIs (disassemWin, s, newLow, FALSE); | |
305 | } | |
306 | } | |
307 | ||
308 | return; | |
309 | } /* tuiVerticalDisassemScroll */ | |
310 | ||
311 | ||
312 | ||
313 | /***************************************** | |
314 | ** STATIC LOCAL FUNCTIONS ** | |
315 | ******************************************/ | |
316 | /* | |
317 | ** _hasBreak(). | |
318 | ** Answer whether there is a break point at the input line in the | |
319 | ** source file indicated | |
320 | */ | |
321 | static struct breakpoint * | |
322 | #ifdef __STDC__ | |
323 | _hasBreak ( | |
324 | CORE_ADDR addr) | |
325 | #else | |
326 | _hasBreak (addr) | |
327 | CORE_ADDR addr; | |
328 | #endif | |
329 | { | |
330 | struct breakpoint *bpWithBreak = (struct breakpoint *) NULL; | |
331 | struct breakpoint *bp; | |
332 | extern struct breakpoint *breakpoint_chain; | |
333 | ||
334 | ||
335 | for (bp = breakpoint_chain; | |
336 | (bp != (struct breakpoint *) NULL && | |
337 | bpWithBreak == (struct breakpoint *) NULL); | |
338 | bp = bp->next) | |
339 | if (addr == bp->address) | |
340 | bpWithBreak = bp; | |
341 | ||
342 | return bpWithBreak; | |
343 | } /* _hasBreak */ |