Commit | Line | Data |
---|---|---|
1a8da44d AC |
1 | /* Target-dependent code for the MDEBUG MIPS architecture, for GDB, |
2 | the GNU Debugger. | |
3 | ||
197e01b6 | 4 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, |
3e5af19e DJ |
5 | 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 |
6 | Free Software Foundation, Inc. | |
1a8da44d AC |
7 | |
8 | This file is part of GDB. | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2 of the License, or | |
13 | (at your option) any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
197e01b6 EZ |
22 | Foundation, Inc., 51 Franklin Street, Fifth Floor, |
23 | Boston, MA 02110-1301, USA. */ | |
1a8da44d AC |
24 | |
25 | #include "defs.h" | |
26 | #include "frame.h" | |
27 | #include "mips-tdep.h" | |
28 | #include "trad-frame.h" | |
29 | #include "block.h" | |
30 | #include "symtab.h" | |
31 | #include "objfiles.h" | |
32 | #include "elf/mips.h" | |
33 | #include "elf-bfd.h" | |
34 | #include "gdb_assert.h" | |
35 | #include "frame-unwind.h" | |
36 | #include "frame-base.h" | |
37 | #include "mips-mdebug-tdep.h" | |
36b8628e | 38 | #include "mdebugread.h" |
1a8da44d AC |
39 | |
40 | #define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */ | |
1a8da44d AC |
41 | #define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset) |
42 | #define PROC_FRAME_REG(proc) ((proc)->pdr.framereg) | |
1a8da44d AC |
43 | #define PROC_REG_MASK(proc) ((proc)->pdr.regmask) |
44 | #define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask) | |
45 | #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset) | |
46 | #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset) | |
47 | #define PROC_PC_REG(proc) ((proc)->pdr.pcreg) | |
48 | /* FIXME drow/2002-06-10: If a pointer on the host is bigger than a long, | |
49 | this will corrupt pdr.iline. Fortunately we don't use it. */ | |
50 | #define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym) | |
51 | #define _PROC_MAGIC_ 0x0F0F0F0F | |
52 | ||
53 | struct mips_objfile_private | |
54 | { | |
55 | bfd_size_type size; | |
56 | char *contents; | |
57 | }; | |
58 | ||
59 | /* Global used to communicate between non_heuristic_proc_desc and | |
60 | compare_pdr_entries within qsort (). */ | |
61 | static bfd *the_bfd; | |
62 | ||
63 | static int | |
64 | compare_pdr_entries (const void *a, const void *b) | |
65 | { | |
3e5af19e DJ |
66 | CORE_ADDR lhs = bfd_get_signed_32 (the_bfd, (bfd_byte *) a); |
67 | CORE_ADDR rhs = bfd_get_signed_32 (the_bfd, (bfd_byte *) b); | |
1a8da44d AC |
68 | |
69 | if (lhs < rhs) | |
70 | return -1; | |
71 | else if (lhs == rhs) | |
72 | return 0; | |
73 | else | |
74 | return 1; | |
75 | } | |
76 | ||
77 | static const struct objfile_data *mips_pdr_data; | |
78 | ||
f92761ec | 79 | static struct mdebug_extra_func_info * |
1a8da44d AC |
80 | non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) |
81 | { | |
82 | CORE_ADDR startaddr; | |
f92761ec | 83 | struct mdebug_extra_func_info *proc_desc; |
1a8da44d AC |
84 | struct block *b = block_for_pc (pc); |
85 | struct symbol *sym; | |
86 | struct obj_section *sec; | |
87 | struct mips_objfile_private *priv; | |
88 | ||
89 | find_pc_partial_function (pc, NULL, &startaddr, NULL); | |
90 | if (addrptr) | |
91 | *addrptr = startaddr; | |
92 | ||
93 | priv = NULL; | |
94 | ||
95 | sec = find_pc_section (pc); | |
96 | if (sec != NULL) | |
97 | { | |
98 | priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data); | |
99 | ||
100 | /* Search the ".pdr" section generated by GAS. This includes most of | |
101 | the information normally found in ECOFF PDRs. */ | |
102 | ||
103 | the_bfd = sec->objfile->obfd; | |
104 | if (priv == NULL | |
105 | && (the_bfd->format == bfd_object | |
106 | && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour | |
107 | && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64)) | |
108 | { | |
109 | /* Right now GAS only outputs the address as a four-byte sequence. | |
110 | This means that we should not bother with this method on 64-bit | |
111 | targets (until that is fixed). */ | |
112 | ||
113 | priv = obstack_alloc (&sec->objfile->objfile_obstack, | |
114 | sizeof (struct mips_objfile_private)); | |
115 | priv->size = 0; | |
116 | set_objfile_data (sec->objfile, mips_pdr_data, priv); | |
117 | } | |
118 | else if (priv == NULL) | |
119 | { | |
120 | asection *bfdsec; | |
121 | ||
122 | priv = obstack_alloc (&sec->objfile->objfile_obstack, | |
123 | sizeof (struct mips_objfile_private)); | |
124 | ||
125 | bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"); | |
126 | if (bfdsec != NULL) | |
127 | { | |
128 | priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); | |
129 | priv->contents = obstack_alloc (&sec->objfile->objfile_obstack, | |
130 | priv->size); | |
131 | bfd_get_section_contents (sec->objfile->obfd, bfdsec, | |
132 | priv->contents, 0, priv->size); | |
133 | ||
134 | /* In general, the .pdr section is sorted. However, in the | |
135 | presence of multiple code sections (and other corner cases) | |
136 | it can become unsorted. Sort it so that we can use a faster | |
137 | binary search. */ | |
138 | qsort (priv->contents, priv->size / 32, 32, | |
139 | compare_pdr_entries); | |
140 | } | |
141 | else | |
142 | priv->size = 0; | |
143 | ||
144 | set_objfile_data (sec->objfile, mips_pdr_data, priv); | |
145 | } | |
146 | the_bfd = NULL; | |
147 | ||
148 | if (priv->size != 0) | |
149 | { | |
150 | int low, mid, high; | |
151 | char *ptr; | |
152 | CORE_ADDR pdr_pc; | |
153 | ||
154 | low = 0; | |
155 | high = priv->size / 32; | |
156 | ||
157 | /* We've found a .pdr section describing this objfile. We want to | |
158 | find the entry which describes this code address. The .pdr | |
159 | information is not very descriptive; we have only a function | |
160 | start address. We have to look for the closest entry, because | |
161 | the local symbol at the beginning of this function may have | |
162 | been stripped - so if we ask the symbol table for the start | |
163 | address we may get a preceding global function. */ | |
164 | ||
165 | /* First, find the last .pdr entry starting at or before PC. */ | |
166 | do | |
167 | { | |
168 | mid = (low + high) / 2; | |
169 | ||
170 | ptr = priv->contents + mid * 32; | |
171 | pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); | |
172 | pdr_pc += ANOFFSET (sec->objfile->section_offsets, | |
173 | SECT_OFF_TEXT (sec->objfile)); | |
174 | ||
175 | if (pdr_pc > pc) | |
176 | high = mid; | |
177 | else | |
178 | low = mid + 1; | |
179 | } | |
180 | while (low != high); | |
181 | ||
182 | /* Both low and high point one past the PDR of interest. If | |
183 | both are zero, that means this PC is before any region | |
184 | covered by a PDR, i.e. pdr_pc for the first PDR entry is | |
185 | greater than PC. */ | |
186 | if (low > 0) | |
187 | { | |
188 | ptr = priv->contents + (low - 1) * 32; | |
189 | pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); | |
190 | pdr_pc += ANOFFSET (sec->objfile->section_offsets, | |
191 | SECT_OFF_TEXT (sec->objfile)); | |
192 | } | |
193 | ||
194 | /* We don't have a range, so we have no way to know for sure | |
195 | whether we're in the correct PDR or a PDR for a preceding | |
196 | function and the current function was a stripped local | |
197 | symbol. But if the PDR's PC is at least as great as the | |
198 | best guess from the symbol table, assume that it does cover | |
199 | the right area; if a .pdr section is present at all then | |
200 | nearly every function will have an entry. The biggest exception | |
201 | will be the dynamic linker stubs; conveniently these are | |
202 | placed before .text instead of after. */ | |
203 | ||
204 | if (pc >= pdr_pc && pdr_pc >= startaddr) | |
205 | { | |
206 | struct symbol *sym = find_pc_function (pc); | |
207 | ||
208 | if (addrptr) | |
209 | *addrptr = pdr_pc; | |
210 | ||
211 | /* Fill in what we need of the proc_desc. */ | |
f92761ec | 212 | proc_desc = (struct mdebug_extra_func_info *) |
1a8da44d | 213 | obstack_alloc (&sec->objfile->objfile_obstack, |
f92761ec | 214 | sizeof (struct mdebug_extra_func_info)); |
1a8da44d AC |
215 | PROC_LOW_ADDR (proc_desc) = pdr_pc; |
216 | ||
1a8da44d | 217 | PROC_FRAME_OFFSET (proc_desc) |
3e5af19e | 218 | = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20); |
1a8da44d AC |
219 | PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, |
220 | ptr + 24); | |
1a8da44d AC |
221 | PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, |
222 | ptr + 4); | |
223 | PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, | |
224 | ptr + 12); | |
3e5af19e DJ |
225 | PROC_REG_OFFSET (proc_desc) |
226 | = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8); | |
1a8da44d | 227 | PROC_FREG_OFFSET (proc_desc) |
3e5af19e | 228 | = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16); |
1a8da44d AC |
229 | PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, |
230 | ptr + 28); | |
231 | proc_desc->pdr.isym = (long) sym; | |
232 | ||
233 | return proc_desc; | |
234 | } | |
235 | } | |
236 | } | |
237 | ||
238 | if (b == NULL) | |
239 | return NULL; | |
240 | ||
241 | if (startaddr > BLOCK_START (b)) | |
242 | { | |
243 | /* This is the "pathological" case referred to in a comment in | |
244 | print_frame_info. It might be better to move this check into | |
245 | symbol reading. */ | |
246 | return NULL; | |
247 | } | |
248 | ||
f92761ec | 249 | sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL); |
1a8da44d AC |
250 | |
251 | /* If we never found a PDR for this function in symbol reading, then | |
252 | examine prologues to find the information. */ | |
253 | if (sym) | |
254 | { | |
f92761ec | 255 | proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); |
1a8da44d AC |
256 | if (PROC_FRAME_REG (proc_desc) == -1) |
257 | return NULL; | |
258 | else | |
259 | return proc_desc; | |
260 | } | |
261 | else | |
262 | return NULL; | |
263 | } | |
264 | ||
265 | struct mips_frame_cache | |
266 | { | |
267 | CORE_ADDR base; | |
268 | struct trad_frame_saved_reg *saved_regs; | |
269 | }; | |
270 | ||
271 | static struct mips_frame_cache * | |
272 | mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache) | |
273 | { | |
274 | CORE_ADDR startaddr = 0; | |
f92761ec | 275 | struct mdebug_extra_func_info *proc_desc; |
1a8da44d AC |
276 | struct mips_frame_cache *cache; |
277 | struct gdbarch *gdbarch = get_frame_arch (next_frame); | |
278 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
279 | /* r0 bit means kernel trap */ | |
280 | int kernel_trap; | |
281 | /* What registers have been saved? Bitmasks. */ | |
282 | unsigned long gen_mask, float_mask; | |
283 | ||
284 | if ((*this_cache) != NULL) | |
285 | return (*this_cache); | |
286 | cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache); | |
287 | (*this_cache) = cache; | |
288 | cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); | |
289 | ||
290 | /* Get the mdebug proc descriptor. */ | |
291 | proc_desc = non_heuristic_proc_desc (frame_pc_unwind (next_frame), | |
292 | &startaddr); | |
293 | /* Must be true. This is only called when the sniffer detected a | |
294 | proc descriptor. */ | |
295 | gdb_assert (proc_desc != NULL); | |
296 | ||
297 | /* Extract the frame's base. */ | |
298 | cache->base = (frame_unwind_register_signed (next_frame, NUM_REGS + PROC_FRAME_REG (proc_desc)) | |
0bb57b31 | 299 | + PROC_FRAME_OFFSET (proc_desc)); |
1a8da44d AC |
300 | |
301 | kernel_trap = PROC_REG_MASK (proc_desc) & 1; | |
302 | gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK (proc_desc); | |
303 | float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK (proc_desc); | |
304 | ||
305 | /* Must be true. The in_prologue case is left for the heuristic | |
306 | unwinder. This is always used on kernel traps. */ | |
307 | gdb_assert (!in_prologue (frame_pc_unwind (next_frame), PROC_LOW_ADDR (proc_desc)) | |
308 | || kernel_trap); | |
309 | ||
310 | /* Fill in the offsets for the registers which gen_mask says were | |
311 | saved. */ | |
312 | { | |
313 | CORE_ADDR reg_position = (cache->base + PROC_REG_OFFSET (proc_desc)); | |
314 | int ireg; | |
315 | ||
316 | for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1) | |
317 | if (gen_mask & 0x80000000) | |
318 | { | |
319 | cache->saved_regs[NUM_REGS + ireg].addr = reg_position; | |
320 | reg_position -= mips_abi_regsize (gdbarch); | |
321 | } | |
322 | } | |
323 | ||
324 | /* Fill in the offsets for the registers which float_mask says were | |
325 | saved. */ | |
326 | { | |
327 | CORE_ADDR reg_position = (cache->base | |
328 | + PROC_FREG_OFFSET (proc_desc)); | |
329 | int ireg; | |
330 | /* Fill in the offsets for the float registers which float_mask | |
331 | says were saved. */ | |
332 | for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1) | |
333 | if (float_mask & 0x80000000) | |
334 | { | |
335 | if (mips_abi_regsize (gdbarch) == 4 | |
336 | && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) | |
337 | { | |
338 | /* On a big endian 32 bit ABI, floating point registers | |
339 | are paired to form doubles such that the most | |
340 | significant part is in $f[N+1] and the least | |
341 | significant in $f[N] vis: $f[N+1] ||| $f[N]. The | |
342 | registers are also spilled as a pair and stored as a | |
343 | double. | |
344 | ||
345 | When little-endian the least significant part is | |
346 | stored first leading to the memory order $f[N] and | |
347 | then $f[N+1]. | |
348 | ||
349 | Unfortunately, when big-endian the most significant | |
350 | part of the double is stored first, and the least | |
351 | significant is stored second. This leads to the | |
352 | registers being ordered in memory as firt $f[N+1] and | |
353 | then $f[N]. | |
354 | ||
355 | For the big-endian case make certain that the | |
356 | addresses point at the correct (swapped) locations | |
357 | $f[N] and $f[N+1] pair (keep in mind that | |
358 | reg_position is decremented each time through the | |
359 | loop). */ | |
360 | if ((ireg & 1)) | |
361 | cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg] | |
362 | .addr = reg_position - mips_abi_regsize (gdbarch); | |
363 | else | |
364 | cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg] | |
365 | .addr = reg_position + mips_abi_regsize (gdbarch); | |
366 | } | |
367 | else | |
368 | cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg] | |
369 | .addr = reg_position; | |
370 | reg_position -= mips_abi_regsize (gdbarch); | |
371 | } | |
372 | ||
373 | cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc] | |
374 | = cache->saved_regs[NUM_REGS + MIPS_RA_REGNUM]; | |
375 | } | |
376 | ||
377 | /* SP_REGNUM, contains the value and not the address. */ | |
378 | trad_frame_set_value (cache->saved_regs, NUM_REGS + MIPS_SP_REGNUM, cache->base); | |
379 | ||
380 | return (*this_cache); | |
381 | } | |
382 | ||
383 | static void | |
384 | mips_mdebug_frame_this_id (struct frame_info *next_frame, void **this_cache, | |
385 | struct frame_id *this_id) | |
386 | { | |
387 | struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, | |
388 | this_cache); | |
389 | (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); | |
390 | } | |
391 | ||
392 | static void | |
393 | mips_mdebug_frame_prev_register (struct frame_info *next_frame, | |
394 | void **this_cache, | |
395 | int regnum, int *optimizedp, | |
396 | enum lval_type *lvalp, CORE_ADDR *addrp, | |
bc0c849e | 397 | int *realnump, gdb_byte *valuep) |
1a8da44d AC |
398 | { |
399 | struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, | |
400 | this_cache); | |
401 | trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, | |
402 | optimizedp, lvalp, addrp, realnump, valuep); | |
403 | } | |
404 | ||
405 | static const struct frame_unwind mips_mdebug_frame_unwind = | |
406 | { | |
407 | NORMAL_FRAME, | |
408 | mips_mdebug_frame_this_id, | |
409 | mips_mdebug_frame_prev_register | |
410 | }; | |
411 | ||
412 | static const struct frame_unwind * | |
413 | mips_mdebug_frame_sniffer (struct frame_info *next_frame) | |
414 | { | |
415 | CORE_ADDR pc = frame_pc_unwind (next_frame); | |
416 | CORE_ADDR startaddr = 0; | |
f92761ec | 417 | struct mdebug_extra_func_info *proc_desc; |
1a8da44d AC |
418 | int kernel_trap; |
419 | ||
420 | /* Don't use this on MIPS16. */ | |
421 | if (mips_pc_is_mips16 (pc)) | |
422 | return NULL; | |
423 | ||
424 | /* Only use the mdebug frame unwinder on mdebug frames where all the | |
425 | registers have been saved. Leave hard cases such as no mdebug or | |
426 | in prologue for the heuristic unwinders. */ | |
427 | ||
428 | proc_desc = non_heuristic_proc_desc (pc, &startaddr); | |
429 | if (proc_desc == NULL) | |
430 | return NULL; | |
431 | ||
432 | /* Not sure exactly what kernel_trap means, but if it means the | |
433 | kernel saves the registers without a prologue doing it, we better | |
434 | not examine the prologue to see whether registers have been saved | |
435 | yet. */ | |
436 | kernel_trap = PROC_REG_MASK (proc_desc) & 1; | |
437 | if (kernel_trap) | |
438 | return &mips_mdebug_frame_unwind; | |
439 | ||
440 | /* In any frame other than the innermost or a frame interrupted by a | |
441 | signal, we assume that all registers have been saved. This | |
442 | assumes that all register saves in a function happen before the | |
443 | first function call. */ | |
444 | if (!in_prologue (pc, PROC_LOW_ADDR (proc_desc))) | |
445 | return &mips_mdebug_frame_unwind; | |
446 | ||
447 | return NULL; | |
448 | } | |
449 | ||
450 | static CORE_ADDR | |
451 | mips_mdebug_frame_base_address (struct frame_info *next_frame, | |
452 | void **this_cache) | |
453 | { | |
454 | struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, | |
455 | this_cache); | |
456 | return info->base; | |
457 | } | |
458 | ||
459 | static const struct frame_base mips_mdebug_frame_base = { | |
460 | &mips_mdebug_frame_unwind, | |
461 | mips_mdebug_frame_base_address, | |
462 | mips_mdebug_frame_base_address, | |
463 | mips_mdebug_frame_base_address | |
464 | }; | |
465 | ||
466 | static const struct frame_base * | |
467 | mips_mdebug_frame_base_sniffer (struct frame_info *next_frame) | |
468 | { | |
469 | if (mips_mdebug_frame_sniffer (next_frame) != NULL) | |
470 | return &mips_mdebug_frame_base; | |
471 | else | |
472 | return NULL; | |
473 | } | |
474 | ||
475 | void | |
476 | mips_mdebug_append_sniffers (struct gdbarch *gdbarch) | |
477 | { | |
478 | frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer); | |
479 | frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer); | |
480 | } | |
481 | ||
482 | ||
483 | extern void _initialize_mips_mdebug_tdep (void); | |
484 | void | |
485 | _initialize_mips_mdebug_tdep (void) | |
486 | { | |
487 | mips_pdr_data = register_objfile_data (); | |
488 | } |