dwarf.c revision 214082
1214082Sdim/* dwarf.c -- display DWARF contents of a BFD binary file
2214082Sdim   Copyright 2005, 2006
3214082Sdim   Free Software Foundation, Inc.
4214082Sdim
5214082Sdim   This file is part of GNU Binutils.
6214082Sdim
7214082Sdim   This program is free software; you can redistribute it and/or modify
8214082Sdim   it under the terms of the GNU General Public License as published by
9214082Sdim   the Free Software Foundation; either version 2 of the License, or
10214082Sdim   (at your option) any later version.
11214082Sdim
12214082Sdim   This program is distributed in the hope that it will be useful,
13214082Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
14214082Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15214082Sdim   GNU General Public License for more details.
16214082Sdim
17214082Sdim   You should have received a copy of the GNU General Public License
18214082Sdim   along with this program; if not, write to the Free Software
19214082Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20214082Sdim   02110-1301, USA.  */
21214082Sdim
22214082Sdim#include <stdio.h>
23214082Sdim
24214082Sdim#include "dwarf.h"
25214082Sdim
26214082Sdim#include "bucomm.h"
27214082Sdim#include "libiberty.h"
28214082Sdim
29214082Sdimstatic int have_frame_base;
30214082Sdimstatic int need_base_address;
31214082Sdim
32214082Sdimstatic unsigned int last_pointer_size = 0;
33214082Sdimstatic int warned_about_missing_comp_units = FALSE;
34214082Sdim
35214082Sdimstatic unsigned int num_debug_info_entries = 0;
36214082Sdimstatic debug_info *debug_information = NULL;
37214082Sdim
38214082Sdimdwarf_vma eh_addr_size;
39214082Sdimint is_relocatable;
40214082Sdim
41214082Sdimint do_debug_info;
42214082Sdimint do_debug_abbrevs;
43214082Sdimint do_debug_lines;
44214082Sdimint do_debug_pubnames;
45214082Sdimint do_debug_aranges;
46214082Sdimint do_debug_ranges;
47214082Sdimint do_debug_frames;
48214082Sdimint do_debug_frames_interp;
49214082Sdimint do_debug_macinfo;
50214082Sdimint do_debug_str;
51214082Sdimint do_debug_loc;
52214082Sdim
53214082Sdimdwarf_vma (*byte_get) (unsigned char *, int);
54214082Sdim
55214082Sdimdwarf_vma
56214082Sdimbyte_get_little_endian (unsigned char *field, int size)
57214082Sdim{
58214082Sdim  switch (size)
59214082Sdim    {
60214082Sdim    case 1:
61214082Sdim      return *field;
62214082Sdim
63214082Sdim    case 2:
64214082Sdim      return  ((unsigned int) (field[0]))
65214082Sdim	|    (((unsigned int) (field[1])) << 8);
66214082Sdim
67214082Sdim    case 4:
68214082Sdim      return  ((unsigned long) (field[0]))
69214082Sdim	|    (((unsigned long) (field[1])) << 8)
70214082Sdim	|    (((unsigned long) (field[2])) << 16)
71214082Sdim	|    (((unsigned long) (field[3])) << 24);
72214082Sdim
73214082Sdim    case 8:
74214082Sdim      if (sizeof (dwarf_vma) == 8)
75214082Sdim	return  ((dwarf_vma) (field[0]))
76214082Sdim	  |    (((dwarf_vma) (field[1])) << 8)
77214082Sdim	  |    (((dwarf_vma) (field[2])) << 16)
78214082Sdim	  |    (((dwarf_vma) (field[3])) << 24)
79214082Sdim	  |    (((dwarf_vma) (field[4])) << 32)
80214082Sdim	  |    (((dwarf_vma) (field[5])) << 40)
81214082Sdim	  |    (((dwarf_vma) (field[6])) << 48)
82214082Sdim	  |    (((dwarf_vma) (field[7])) << 56);
83214082Sdim      else if (sizeof (dwarf_vma) == 4)
84214082Sdim	/* We want to extract data from an 8 byte wide field and
85214082Sdim	   place it into a 4 byte wide field.  Since this is a little
86214082Sdim	   endian source we can just use the 4 byte extraction code.  */
87214082Sdim	return  ((unsigned long) (field[0]))
88214082Sdim	  |    (((unsigned long) (field[1])) << 8)
89214082Sdim	  |    (((unsigned long) (field[2])) << 16)
90214082Sdim	  |    (((unsigned long) (field[3])) << 24);
91214082Sdim
92214082Sdim    default:
93214082Sdim      error (_("Unhandled data length: %d\n"), size);
94214082Sdim      abort ();
95214082Sdim    }
96214082Sdim}
97214082Sdim
98214082Sdimdwarf_vma
99214082Sdimbyte_get_big_endian (unsigned char *field, int size)
100214082Sdim{
101214082Sdim  switch (size)
102214082Sdim    {
103214082Sdim    case 1:
104214082Sdim      return *field;
105214082Sdim
106214082Sdim    case 2:
107214082Sdim      return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
108214082Sdim
109214082Sdim    case 4:
110214082Sdim      return ((unsigned long) (field[3]))
111214082Sdim	|   (((unsigned long) (field[2])) << 8)
112214082Sdim	|   (((unsigned long) (field[1])) << 16)
113214082Sdim	|   (((unsigned long) (field[0])) << 24);
114214082Sdim
115214082Sdim    case 8:
116214082Sdim      if (sizeof (dwarf_vma) == 8)
117214082Sdim	return ((dwarf_vma) (field[7]))
118214082Sdim	  |   (((dwarf_vma) (field[6])) << 8)
119214082Sdim	  |   (((dwarf_vma) (field[5])) << 16)
120214082Sdim	  |   (((dwarf_vma) (field[4])) << 24)
121214082Sdim	  |   (((dwarf_vma) (field[3])) << 32)
122214082Sdim	  |   (((dwarf_vma) (field[2])) << 40)
123214082Sdim	  |   (((dwarf_vma) (field[1])) << 48)
124214082Sdim	  |   (((dwarf_vma) (field[0])) << 56);
125214082Sdim      else if (sizeof (dwarf_vma) == 4)
126214082Sdim	{
127214082Sdim	  /* Although we are extracing data from an 8 byte wide field,
128214082Sdim	     we are returning only 4 bytes of data.  */
129214082Sdim	  field += 4;
130214082Sdim	  return ((unsigned long) (field[3]))
131214082Sdim	    |   (((unsigned long) (field[2])) << 8)
132214082Sdim	    |   (((unsigned long) (field[1])) << 16)
133214082Sdim	    |   (((unsigned long) (field[0])) << 24);
134214082Sdim	}
135214082Sdim
136214082Sdim    default:
137214082Sdim      error (_("Unhandled data length: %d\n"), size);
138214082Sdim      abort ();
139214082Sdim    }
140214082Sdim}
141214082Sdim
142214082Sdimstatic dwarf_vma
143214082Sdimbyte_get_signed (unsigned char *field, int size)
144214082Sdim{
145214082Sdim  dwarf_vma x = byte_get (field, size);
146214082Sdim
147214082Sdim  switch (size)
148214082Sdim    {
149214082Sdim    case 1:
150214082Sdim      return (x ^ 0x80) - 0x80;
151214082Sdim    case 2:
152214082Sdim      return (x ^ 0x8000) - 0x8000;
153214082Sdim    case 4:
154214082Sdim      return (x ^ 0x80000000) - 0x80000000;
155214082Sdim    case 8:
156214082Sdim      return x;
157214082Sdim    default:
158214082Sdim      abort ();
159214082Sdim    }
160214082Sdim}
161214082Sdim
162214082Sdimstatic unsigned long int
163214082Sdimread_leb128 (unsigned char *data, unsigned int *length_return, int sign)
164214082Sdim{
165214082Sdim  unsigned long int result = 0;
166214082Sdim  unsigned int num_read = 0;
167214082Sdim  unsigned int shift = 0;
168214082Sdim  unsigned char byte;
169214082Sdim
170214082Sdim  do
171214082Sdim    {
172214082Sdim      byte = *data++;
173214082Sdim      num_read++;
174214082Sdim
175214082Sdim      result |= ((unsigned long int) (byte & 0x7f)) << shift;
176214082Sdim
177214082Sdim      shift += 7;
178214082Sdim
179214082Sdim    }
180214082Sdim  while (byte & 0x80);
181214082Sdim
182214082Sdim  if (length_return != NULL)
183214082Sdim    *length_return = num_read;
184214082Sdim
185214082Sdim  if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
186214082Sdim    result |= -1L << shift;
187214082Sdim
188214082Sdim  return result;
189214082Sdim}
190214082Sdim
191214082Sdimtypedef struct State_Machine_Registers
192214082Sdim{
193214082Sdim  unsigned long address;
194214082Sdim  unsigned int file;
195214082Sdim  unsigned int line;
196214082Sdim  unsigned int column;
197214082Sdim  int is_stmt;
198214082Sdim  int basic_block;
199214082Sdim  int end_sequence;
200214082Sdim/* This variable hold the number of the last entry seen
201214082Sdim   in the File Table.  */
202214082Sdim  unsigned int last_file_entry;
203214082Sdim} SMR;
204214082Sdim
205214082Sdimstatic SMR state_machine_regs;
206214082Sdim
207214082Sdimstatic void
208214082Sdimreset_state_machine (int is_stmt)
209214082Sdim{
210214082Sdim  state_machine_regs.address = 0;
211214082Sdim  state_machine_regs.file = 1;
212214082Sdim  state_machine_regs.line = 1;
213214082Sdim  state_machine_regs.column = 0;
214214082Sdim  state_machine_regs.is_stmt = is_stmt;
215214082Sdim  state_machine_regs.basic_block = 0;
216214082Sdim  state_machine_regs.end_sequence = 0;
217214082Sdim  state_machine_regs.last_file_entry = 0;
218214082Sdim}
219214082Sdim
220214082Sdim/* Handled an extend line op.
221214082Sdim   Returns the number of bytes read.  */
222214082Sdim
223214082Sdimstatic int
224214082Sdimprocess_extended_line_op (unsigned char *data, int is_stmt)
225214082Sdim{
226214082Sdim  unsigned char op_code;
227214082Sdim  unsigned int bytes_read;
228214082Sdim  unsigned int len;
229214082Sdim  unsigned char *name;
230214082Sdim  unsigned long adr;
231214082Sdim
232214082Sdim  len = read_leb128 (data, & bytes_read, 0);
233214082Sdim  data += bytes_read;
234214082Sdim
235214082Sdim  if (len == 0)
236214082Sdim    {
237214082Sdim      warn (_("badly formed extended line op encountered!\n"));
238214082Sdim      return bytes_read;
239214082Sdim    }
240214082Sdim
241214082Sdim  len += bytes_read;
242214082Sdim  op_code = *data++;
243214082Sdim
244214082Sdim  printf (_("  Extended opcode %d: "), op_code);
245214082Sdim
246214082Sdim  switch (op_code)
247214082Sdim    {
248214082Sdim    case DW_LNE_end_sequence:
249214082Sdim      printf (_("End of Sequence\n\n"));
250214082Sdim      reset_state_machine (is_stmt);
251214082Sdim      break;
252214082Sdim
253214082Sdim    case DW_LNE_set_address:
254214082Sdim      adr = byte_get (data, len - bytes_read - 1);
255214082Sdim      printf (_("set Address to 0x%lx\n"), adr);
256214082Sdim      state_machine_regs.address = adr;
257214082Sdim      break;
258214082Sdim
259214082Sdim    case DW_LNE_define_file:
260214082Sdim      printf (_("  define new File Table entry\n"));
261214082Sdim      printf (_("  Entry\tDir\tTime\tSize\tName\n"));
262214082Sdim
263214082Sdim      printf (_("   %d\t"), ++state_machine_regs.last_file_entry);
264214082Sdim      name = data;
265214082Sdim      data += strlen ((char *) data) + 1;
266214082Sdim      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
267214082Sdim      data += bytes_read;
268214082Sdim      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
269214082Sdim      data += bytes_read;
270214082Sdim      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
271214082Sdim      printf (_("%s\n\n"), name);
272214082Sdim      break;
273214082Sdim
274214082Sdim    default:
275214082Sdim      printf (_("UNKNOWN: length %d\n"), len - bytes_read);
276214082Sdim      break;
277214082Sdim    }
278214082Sdim
279214082Sdim  return len;
280214082Sdim}
281214082Sdim
282214082Sdimstatic const char *
283214082Sdimfetch_indirect_string (unsigned long offset)
284214082Sdim{
285214082Sdim  struct dwarf_section *section = &debug_displays [str].section;
286214082Sdim
287214082Sdim  if (section->start == NULL)
288214082Sdim    return _("<no .debug_str section>");
289214082Sdim
290214082Sdim  /* DWARF sections under Mach-O have non-zero addresses.  */
291214082Sdim  offset -= section->address;
292214082Sdim  if (offset > section->size)
293214082Sdim    {
294214082Sdim      warn (_("DW_FORM_strp offset too big: %lx\n"), offset);
295214082Sdim      return _("<offset is too big>");
296214082Sdim    }
297214082Sdim
298214082Sdim  return (const char *) section->start + offset;
299214082Sdim}
300214082Sdim
301214082Sdim/* FIXME:  There are better and more efficient ways to handle
302214082Sdim   these structures.  For now though, I just want something that
303214082Sdim   is simple to implement.  */
304214082Sdimtypedef struct abbrev_attr
305214082Sdim{
306214082Sdim  unsigned long attribute;
307214082Sdim  unsigned long form;
308214082Sdim  struct abbrev_attr *next;
309214082Sdim}
310214082Sdimabbrev_attr;
311214082Sdim
312214082Sdimtypedef struct abbrev_entry
313214082Sdim{
314214082Sdim  unsigned long entry;
315214082Sdim  unsigned long tag;
316214082Sdim  int children;
317214082Sdim  struct abbrev_attr *first_attr;
318214082Sdim  struct abbrev_attr *last_attr;
319214082Sdim  struct abbrev_entry *next;
320214082Sdim}
321214082Sdimabbrev_entry;
322214082Sdim
323214082Sdimstatic abbrev_entry *first_abbrev = NULL;
324214082Sdimstatic abbrev_entry *last_abbrev = NULL;
325214082Sdim
326214082Sdimstatic void
327214082Sdimfree_abbrevs (void)
328214082Sdim{
329214082Sdim  abbrev_entry *abbrev;
330214082Sdim
331214082Sdim  for (abbrev = first_abbrev; abbrev;)
332214082Sdim    {
333214082Sdim      abbrev_entry *next = abbrev->next;
334214082Sdim      abbrev_attr *attr;
335214082Sdim
336214082Sdim      for (attr = abbrev->first_attr; attr;)
337214082Sdim	{
338214082Sdim	  abbrev_attr *next = attr->next;
339214082Sdim
340214082Sdim	  free (attr);
341214082Sdim	  attr = next;
342214082Sdim	}
343214082Sdim
344214082Sdim      free (abbrev);
345214082Sdim      abbrev = next;
346214082Sdim    }
347214082Sdim
348214082Sdim  last_abbrev = first_abbrev = NULL;
349214082Sdim}
350214082Sdim
351214082Sdimstatic void
352214082Sdimadd_abbrev (unsigned long number, unsigned long tag, int children)
353214082Sdim{
354214082Sdim  abbrev_entry *entry;
355214082Sdim
356214082Sdim  entry = malloc (sizeof (*entry));
357214082Sdim
358214082Sdim  if (entry == NULL)
359214082Sdim    /* ugg */
360214082Sdim    return;
361214082Sdim
362214082Sdim  entry->entry      = number;
363214082Sdim  entry->tag        = tag;
364214082Sdim  entry->children   = children;
365214082Sdim  entry->first_attr = NULL;
366214082Sdim  entry->last_attr  = NULL;
367214082Sdim  entry->next       = NULL;
368214082Sdim
369214082Sdim  if (first_abbrev == NULL)
370214082Sdim    first_abbrev = entry;
371214082Sdim  else
372214082Sdim    last_abbrev->next = entry;
373214082Sdim
374214082Sdim  last_abbrev = entry;
375214082Sdim}
376214082Sdim
377214082Sdimstatic void
378214082Sdimadd_abbrev_attr (unsigned long attribute, unsigned long form)
379214082Sdim{
380214082Sdim  abbrev_attr *attr;
381214082Sdim
382214082Sdim  attr = malloc (sizeof (*attr));
383214082Sdim
384214082Sdim  if (attr == NULL)
385214082Sdim    /* ugg */
386214082Sdim    return;
387214082Sdim
388214082Sdim  attr->attribute = attribute;
389214082Sdim  attr->form      = form;
390214082Sdim  attr->next      = NULL;
391214082Sdim
392214082Sdim  if (last_abbrev->first_attr == NULL)
393214082Sdim    last_abbrev->first_attr = attr;
394214082Sdim  else
395214082Sdim    last_abbrev->last_attr->next = attr;
396214082Sdim
397214082Sdim  last_abbrev->last_attr = attr;
398214082Sdim}
399214082Sdim
400214082Sdim/* Processes the (partial) contents of a .debug_abbrev section.
401214082Sdim   Returns NULL if the end of the section was encountered.
402214082Sdim   Returns the address after the last byte read if the end of
403214082Sdim   an abbreviation set was found.  */
404214082Sdim
405214082Sdimstatic unsigned char *
406214082Sdimprocess_abbrev_section (unsigned char *start, unsigned char *end)
407214082Sdim{
408214082Sdim  if (first_abbrev != NULL)
409214082Sdim    return NULL;
410214082Sdim
411214082Sdim  while (start < end)
412214082Sdim    {
413214082Sdim      unsigned int bytes_read;
414214082Sdim      unsigned long entry;
415214082Sdim      unsigned long tag;
416214082Sdim      unsigned long attribute;
417214082Sdim      int children;
418214082Sdim
419214082Sdim      entry = read_leb128 (start, & bytes_read, 0);
420214082Sdim      start += bytes_read;
421214082Sdim
422214082Sdim      /* A single zero is supposed to end the section according
423214082Sdim	 to the standard.  If there's more, then signal that to
424214082Sdim	 the caller.  */
425214082Sdim      if (entry == 0)
426214082Sdim	return start == end ? NULL : start;
427214082Sdim
428214082Sdim      tag = read_leb128 (start, & bytes_read, 0);
429214082Sdim      start += bytes_read;
430214082Sdim
431214082Sdim      children = *start++;
432214082Sdim
433214082Sdim      add_abbrev (entry, tag, children);
434214082Sdim
435214082Sdim      do
436214082Sdim	{
437214082Sdim	  unsigned long form;
438214082Sdim
439214082Sdim	  attribute = read_leb128 (start, & bytes_read, 0);
440214082Sdim	  start += bytes_read;
441214082Sdim
442214082Sdim	  form = read_leb128 (start, & bytes_read, 0);
443214082Sdim	  start += bytes_read;
444214082Sdim
445214082Sdim	  if (attribute != 0)
446214082Sdim	    add_abbrev_attr (attribute, form);
447214082Sdim	}
448214082Sdim      while (attribute != 0);
449214082Sdim    }
450214082Sdim
451214082Sdim  return NULL;
452214082Sdim}
453214082Sdim
454214082Sdimstatic char *
455214082Sdimget_TAG_name (unsigned long tag)
456214082Sdim{
457214082Sdim  switch (tag)
458214082Sdim    {
459214082Sdim    case DW_TAG_padding:		return "DW_TAG_padding";
460214082Sdim    case DW_TAG_array_type:		return "DW_TAG_array_type";
461214082Sdim    case DW_TAG_class_type:		return "DW_TAG_class_type";
462214082Sdim    case DW_TAG_entry_point:		return "DW_TAG_entry_point";
463214082Sdim    case DW_TAG_enumeration_type:	return "DW_TAG_enumeration_type";
464214082Sdim    case DW_TAG_formal_parameter:	return "DW_TAG_formal_parameter";
465214082Sdim    case DW_TAG_imported_declaration:	return "DW_TAG_imported_declaration";
466214082Sdim    case DW_TAG_label:			return "DW_TAG_label";
467214082Sdim    case DW_TAG_lexical_block:		return "DW_TAG_lexical_block";
468214082Sdim    case DW_TAG_member:			return "DW_TAG_member";
469214082Sdim    case DW_TAG_pointer_type:		return "DW_TAG_pointer_type";
470214082Sdim    case DW_TAG_reference_type:		return "DW_TAG_reference_type";
471214082Sdim    case DW_TAG_compile_unit:		return "DW_TAG_compile_unit";
472214082Sdim    case DW_TAG_string_type:		return "DW_TAG_string_type";
473214082Sdim    case DW_TAG_structure_type:		return "DW_TAG_structure_type";
474214082Sdim    case DW_TAG_subroutine_type:	return "DW_TAG_subroutine_type";
475214082Sdim    case DW_TAG_typedef:		return "DW_TAG_typedef";
476214082Sdim    case DW_TAG_union_type:		return "DW_TAG_union_type";
477214082Sdim    case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
478214082Sdim    case DW_TAG_variant:		return "DW_TAG_variant";
479214082Sdim    case DW_TAG_common_block:		return "DW_TAG_common_block";
480214082Sdim    case DW_TAG_common_inclusion:	return "DW_TAG_common_inclusion";
481214082Sdim    case DW_TAG_inheritance:		return "DW_TAG_inheritance";
482214082Sdim    case DW_TAG_inlined_subroutine:	return "DW_TAG_inlined_subroutine";
483214082Sdim    case DW_TAG_module:			return "DW_TAG_module";
484214082Sdim    case DW_TAG_ptr_to_member_type:	return "DW_TAG_ptr_to_member_type";
485214082Sdim    case DW_TAG_set_type:		return "DW_TAG_set_type";
486214082Sdim    case DW_TAG_subrange_type:		return "DW_TAG_subrange_type";
487214082Sdim    case DW_TAG_with_stmt:		return "DW_TAG_with_stmt";
488214082Sdim    case DW_TAG_access_declaration:	return "DW_TAG_access_declaration";
489214082Sdim    case DW_TAG_base_type:		return "DW_TAG_base_type";
490214082Sdim    case DW_TAG_catch_block:		return "DW_TAG_catch_block";
491214082Sdim    case DW_TAG_const_type:		return "DW_TAG_const_type";
492214082Sdim    case DW_TAG_constant:		return "DW_TAG_constant";
493214082Sdim    case DW_TAG_enumerator:		return "DW_TAG_enumerator";
494214082Sdim    case DW_TAG_file_type:		return "DW_TAG_file_type";
495214082Sdim    case DW_TAG_friend:			return "DW_TAG_friend";
496214082Sdim    case DW_TAG_namelist:		return "DW_TAG_namelist";
497214082Sdim    case DW_TAG_namelist_item:		return "DW_TAG_namelist_item";
498214082Sdim    case DW_TAG_packed_type:		return "DW_TAG_packed_type";
499214082Sdim    case DW_TAG_subprogram:		return "DW_TAG_subprogram";
500214082Sdim    case DW_TAG_template_type_param:	return "DW_TAG_template_type_param";
501214082Sdim    case DW_TAG_template_value_param:	return "DW_TAG_template_value_param";
502214082Sdim    case DW_TAG_thrown_type:		return "DW_TAG_thrown_type";
503214082Sdim    case DW_TAG_try_block:		return "DW_TAG_try_block";
504214082Sdim    case DW_TAG_variant_part:		return "DW_TAG_variant_part";
505214082Sdim    case DW_TAG_variable:		return "DW_TAG_variable";
506214082Sdim    case DW_TAG_volatile_type:		return "DW_TAG_volatile_type";
507214082Sdim    case DW_TAG_MIPS_loop:		return "DW_TAG_MIPS_loop";
508214082Sdim    case DW_TAG_format_label:		return "DW_TAG_format_label";
509214082Sdim    case DW_TAG_function_template:	return "DW_TAG_function_template";
510214082Sdim    case DW_TAG_class_template:		return "DW_TAG_class_template";
511214082Sdim      /* DWARF 2.1 values.  */
512214082Sdim    case DW_TAG_dwarf_procedure:	return "DW_TAG_dwarf_procedure";
513214082Sdim    case DW_TAG_restrict_type:		return "DW_TAG_restrict_type";
514214082Sdim    case DW_TAG_interface_type:		return "DW_TAG_interface_type";
515214082Sdim    case DW_TAG_namespace:		return "DW_TAG_namespace";
516214082Sdim    case DW_TAG_imported_module:	return "DW_TAG_imported_module";
517214082Sdim    case DW_TAG_unspecified_type:	return "DW_TAG_unspecified_type";
518214082Sdim    case DW_TAG_partial_unit:		return "DW_TAG_partial_unit";
519214082Sdim    case DW_TAG_imported_unit:		return "DW_TAG_imported_unit";
520214082Sdim      /* UPC values.  */
521214082Sdim    case DW_TAG_upc_shared_type:	return "DW_TAG_upc_shared_type";
522214082Sdim    case DW_TAG_upc_strict_type:	return "DW_TAG_upc_strict_type";
523214082Sdim    case DW_TAG_upc_relaxed_type:	return "DW_TAG_upc_relaxed_type";
524214082Sdim    default:
525214082Sdim      {
526214082Sdim	static char buffer[100];
527214082Sdim
528214082Sdim	snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag);
529214082Sdim	return buffer;
530214082Sdim      }
531214082Sdim    }
532214082Sdim}
533214082Sdim
534214082Sdimstatic char *
535214082Sdimget_FORM_name (unsigned long form)
536214082Sdim{
537214082Sdim  switch (form)
538214082Sdim    {
539214082Sdim    case DW_FORM_addr:		return "DW_FORM_addr";
540214082Sdim    case DW_FORM_block2:	return "DW_FORM_block2";
541214082Sdim    case DW_FORM_block4:	return "DW_FORM_block4";
542214082Sdim    case DW_FORM_data2:		return "DW_FORM_data2";
543214082Sdim    case DW_FORM_data4:		return "DW_FORM_data4";
544214082Sdim    case DW_FORM_data8:		return "DW_FORM_data8";
545214082Sdim    case DW_FORM_string:	return "DW_FORM_string";
546214082Sdim    case DW_FORM_block:		return "DW_FORM_block";
547214082Sdim    case DW_FORM_block1:	return "DW_FORM_block1";
548214082Sdim    case DW_FORM_data1:		return "DW_FORM_data1";
549214082Sdim    case DW_FORM_flag:		return "DW_FORM_flag";
550214082Sdim    case DW_FORM_sdata:		return "DW_FORM_sdata";
551214082Sdim    case DW_FORM_strp:		return "DW_FORM_strp";
552214082Sdim    case DW_FORM_udata:		return "DW_FORM_udata";
553214082Sdim    case DW_FORM_ref_addr:	return "DW_FORM_ref_addr";
554214082Sdim    case DW_FORM_ref1:		return "DW_FORM_ref1";
555214082Sdim    case DW_FORM_ref2:		return "DW_FORM_ref2";
556214082Sdim    case DW_FORM_ref4:		return "DW_FORM_ref4";
557214082Sdim    case DW_FORM_ref8:		return "DW_FORM_ref8";
558214082Sdim    case DW_FORM_ref_udata:	return "DW_FORM_ref_udata";
559214082Sdim    case DW_FORM_indirect:	return "DW_FORM_indirect";
560214082Sdim    default:
561214082Sdim      {
562214082Sdim	static char buffer[100];
563214082Sdim
564214082Sdim	snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
565214082Sdim	return buffer;
566214082Sdim      }
567214082Sdim    }
568214082Sdim}
569214082Sdim
570214082Sdimstatic unsigned char *
571214082Sdimdisplay_block (unsigned char *data, unsigned long length)
572214082Sdim{
573214082Sdim  printf (_(" %lu byte block: "), length);
574214082Sdim
575214082Sdim  while (length --)
576214082Sdim    printf ("%lx ", (unsigned long) byte_get (data++, 1));
577214082Sdim
578214082Sdim  return data;
579214082Sdim}
580214082Sdim
581214082Sdimstatic int
582214082Sdimdecode_location_expression (unsigned char * data,
583214082Sdim			    unsigned int pointer_size,
584214082Sdim			    unsigned long length,
585214082Sdim			    unsigned long cu_offset)
586214082Sdim{
587214082Sdim  unsigned op;
588214082Sdim  unsigned int bytes_read;
589214082Sdim  unsigned long uvalue;
590214082Sdim  unsigned char *end = data + length;
591214082Sdim  int need_frame_base = 0;
592214082Sdim
593214082Sdim  while (data < end)
594214082Sdim    {
595214082Sdim      op = *data++;
596214082Sdim
597214082Sdim      switch (op)
598214082Sdim	{
599214082Sdim	case DW_OP_addr:
600214082Sdim	  printf ("DW_OP_addr: %lx",
601214082Sdim		  (unsigned long) byte_get (data, pointer_size));
602214082Sdim	  data += pointer_size;
603214082Sdim	  break;
604214082Sdim	case DW_OP_deref:
605214082Sdim	  printf ("DW_OP_deref");
606214082Sdim	  break;
607214082Sdim	case DW_OP_const1u:
608214082Sdim	  printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1));
609214082Sdim	  break;
610214082Sdim	case DW_OP_const1s:
611214082Sdim	  printf ("DW_OP_const1s: %ld", (long) byte_get_signed (data++, 1));
612214082Sdim	  break;
613214082Sdim	case DW_OP_const2u:
614214082Sdim	  printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2));
615214082Sdim	  data += 2;
616214082Sdim	  break;
617214082Sdim	case DW_OP_const2s:
618214082Sdim	  printf ("DW_OP_const2s: %ld", (long) byte_get_signed (data, 2));
619214082Sdim	  data += 2;
620214082Sdim	  break;
621214082Sdim	case DW_OP_const4u:
622214082Sdim	  printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4));
623214082Sdim	  data += 4;
624214082Sdim	  break;
625214082Sdim	case DW_OP_const4s:
626214082Sdim	  printf ("DW_OP_const4s: %ld", (long) byte_get_signed (data, 4));
627214082Sdim	  data += 4;
628214082Sdim	  break;
629214082Sdim	case DW_OP_const8u:
630214082Sdim	  printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4),
631214082Sdim		  (unsigned long) byte_get (data + 4, 4));
632214082Sdim	  data += 8;
633214082Sdim	  break;
634214082Sdim	case DW_OP_const8s:
635214082Sdim	  printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4),
636214082Sdim		  (long) byte_get (data + 4, 4));
637214082Sdim	  data += 8;
638214082Sdim	  break;
639214082Sdim	case DW_OP_constu:
640214082Sdim	  printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0));
641214082Sdim	  data += bytes_read;
642214082Sdim	  break;
643214082Sdim	case DW_OP_consts:
644214082Sdim	  printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1));
645214082Sdim	  data += bytes_read;
646214082Sdim	  break;
647214082Sdim	case DW_OP_dup:
648214082Sdim	  printf ("DW_OP_dup");
649214082Sdim	  break;
650214082Sdim	case DW_OP_drop:
651214082Sdim	  printf ("DW_OP_drop");
652214082Sdim	  break;
653214082Sdim	case DW_OP_over:
654214082Sdim	  printf ("DW_OP_over");
655214082Sdim	  break;
656214082Sdim	case DW_OP_pick:
657214082Sdim	  printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1));
658214082Sdim	  break;
659214082Sdim	case DW_OP_swap:
660214082Sdim	  printf ("DW_OP_swap");
661214082Sdim	  break;
662214082Sdim	case DW_OP_rot:
663214082Sdim	  printf ("DW_OP_rot");
664214082Sdim	  break;
665214082Sdim	case DW_OP_xderef:
666214082Sdim	  printf ("DW_OP_xderef");
667214082Sdim	  break;
668214082Sdim	case DW_OP_abs:
669214082Sdim	  printf ("DW_OP_abs");
670214082Sdim	  break;
671214082Sdim	case DW_OP_and:
672214082Sdim	  printf ("DW_OP_and");
673214082Sdim	  break;
674214082Sdim	case DW_OP_div:
675214082Sdim	  printf ("DW_OP_div");
676214082Sdim	  break;
677214082Sdim	case DW_OP_minus:
678214082Sdim	  printf ("DW_OP_minus");
679214082Sdim	  break;
680214082Sdim	case DW_OP_mod:
681214082Sdim	  printf ("DW_OP_mod");
682214082Sdim	  break;
683214082Sdim	case DW_OP_mul:
684214082Sdim	  printf ("DW_OP_mul");
685214082Sdim	  break;
686214082Sdim	case DW_OP_neg:
687214082Sdim	  printf ("DW_OP_neg");
688214082Sdim	  break;
689214082Sdim	case DW_OP_not:
690214082Sdim	  printf ("DW_OP_not");
691214082Sdim	  break;
692214082Sdim	case DW_OP_or:
693214082Sdim	  printf ("DW_OP_or");
694214082Sdim	  break;
695214082Sdim	case DW_OP_plus:
696214082Sdim	  printf ("DW_OP_plus");
697214082Sdim	  break;
698214082Sdim	case DW_OP_plus_uconst:
699214082Sdim	  printf ("DW_OP_plus_uconst: %lu",
700214082Sdim		  read_leb128 (data, &bytes_read, 0));
701214082Sdim	  data += bytes_read;
702214082Sdim	  break;
703214082Sdim	case DW_OP_shl:
704214082Sdim	  printf ("DW_OP_shl");
705214082Sdim	  break;
706214082Sdim	case DW_OP_shr:
707214082Sdim	  printf ("DW_OP_shr");
708214082Sdim	  break;
709214082Sdim	case DW_OP_shra:
710214082Sdim	  printf ("DW_OP_shra");
711214082Sdim	  break;
712214082Sdim	case DW_OP_xor:
713214082Sdim	  printf ("DW_OP_xor");
714214082Sdim	  break;
715214082Sdim	case DW_OP_bra:
716214082Sdim	  printf ("DW_OP_bra: %ld", (long) byte_get_signed (data, 2));
717214082Sdim	  data += 2;
718214082Sdim	  break;
719214082Sdim	case DW_OP_eq:
720214082Sdim	  printf ("DW_OP_eq");
721214082Sdim	  break;
722214082Sdim	case DW_OP_ge:
723214082Sdim	  printf ("DW_OP_ge");
724214082Sdim	  break;
725214082Sdim	case DW_OP_gt:
726214082Sdim	  printf ("DW_OP_gt");
727214082Sdim	  break;
728214082Sdim	case DW_OP_le:
729214082Sdim	  printf ("DW_OP_le");
730214082Sdim	  break;
731214082Sdim	case DW_OP_lt:
732214082Sdim	  printf ("DW_OP_lt");
733214082Sdim	  break;
734214082Sdim	case DW_OP_ne:
735214082Sdim	  printf ("DW_OP_ne");
736214082Sdim	  break;
737214082Sdim	case DW_OP_skip:
738214082Sdim	  printf ("DW_OP_skip: %ld", (long) byte_get_signed (data, 2));
739214082Sdim	  data += 2;
740214082Sdim	  break;
741214082Sdim
742214082Sdim	case DW_OP_lit0:
743214082Sdim	case DW_OP_lit1:
744214082Sdim	case DW_OP_lit2:
745214082Sdim	case DW_OP_lit3:
746214082Sdim	case DW_OP_lit4:
747214082Sdim	case DW_OP_lit5:
748214082Sdim	case DW_OP_lit6:
749214082Sdim	case DW_OP_lit7:
750214082Sdim	case DW_OP_lit8:
751214082Sdim	case DW_OP_lit9:
752214082Sdim	case DW_OP_lit10:
753214082Sdim	case DW_OP_lit11:
754214082Sdim	case DW_OP_lit12:
755214082Sdim	case DW_OP_lit13:
756214082Sdim	case DW_OP_lit14:
757214082Sdim	case DW_OP_lit15:
758214082Sdim	case DW_OP_lit16:
759214082Sdim	case DW_OP_lit17:
760214082Sdim	case DW_OP_lit18:
761214082Sdim	case DW_OP_lit19:
762214082Sdim	case DW_OP_lit20:
763214082Sdim	case DW_OP_lit21:
764214082Sdim	case DW_OP_lit22:
765214082Sdim	case DW_OP_lit23:
766214082Sdim	case DW_OP_lit24:
767214082Sdim	case DW_OP_lit25:
768214082Sdim	case DW_OP_lit26:
769214082Sdim	case DW_OP_lit27:
770214082Sdim	case DW_OP_lit28:
771214082Sdim	case DW_OP_lit29:
772214082Sdim	case DW_OP_lit30:
773214082Sdim	case DW_OP_lit31:
774214082Sdim	  printf ("DW_OP_lit%d", op - DW_OP_lit0);
775214082Sdim	  break;
776214082Sdim
777214082Sdim	case DW_OP_reg0:
778214082Sdim	case DW_OP_reg1:
779214082Sdim	case DW_OP_reg2:
780214082Sdim	case DW_OP_reg3:
781214082Sdim	case DW_OP_reg4:
782214082Sdim	case DW_OP_reg5:
783214082Sdim	case DW_OP_reg6:
784214082Sdim	case DW_OP_reg7:
785214082Sdim	case DW_OP_reg8:
786214082Sdim	case DW_OP_reg9:
787214082Sdim	case DW_OP_reg10:
788214082Sdim	case DW_OP_reg11:
789214082Sdim	case DW_OP_reg12:
790214082Sdim	case DW_OP_reg13:
791214082Sdim	case DW_OP_reg14:
792214082Sdim	case DW_OP_reg15:
793214082Sdim	case DW_OP_reg16:
794214082Sdim	case DW_OP_reg17:
795214082Sdim	case DW_OP_reg18:
796214082Sdim	case DW_OP_reg19:
797214082Sdim	case DW_OP_reg20:
798214082Sdim	case DW_OP_reg21:
799214082Sdim	case DW_OP_reg22:
800214082Sdim	case DW_OP_reg23:
801214082Sdim	case DW_OP_reg24:
802214082Sdim	case DW_OP_reg25:
803214082Sdim	case DW_OP_reg26:
804214082Sdim	case DW_OP_reg27:
805214082Sdim	case DW_OP_reg28:
806214082Sdim	case DW_OP_reg29:
807214082Sdim	case DW_OP_reg30:
808214082Sdim	case DW_OP_reg31:
809214082Sdim	  printf ("DW_OP_reg%d", op - DW_OP_reg0);
810214082Sdim	  break;
811214082Sdim
812214082Sdim	case DW_OP_breg0:
813214082Sdim	case DW_OP_breg1:
814214082Sdim	case DW_OP_breg2:
815214082Sdim	case DW_OP_breg3:
816214082Sdim	case DW_OP_breg4:
817214082Sdim	case DW_OP_breg5:
818214082Sdim	case DW_OP_breg6:
819214082Sdim	case DW_OP_breg7:
820214082Sdim	case DW_OP_breg8:
821214082Sdim	case DW_OP_breg9:
822214082Sdim	case DW_OP_breg10:
823214082Sdim	case DW_OP_breg11:
824214082Sdim	case DW_OP_breg12:
825214082Sdim	case DW_OP_breg13:
826214082Sdim	case DW_OP_breg14:
827214082Sdim	case DW_OP_breg15:
828214082Sdim	case DW_OP_breg16:
829214082Sdim	case DW_OP_breg17:
830214082Sdim	case DW_OP_breg18:
831214082Sdim	case DW_OP_breg19:
832214082Sdim	case DW_OP_breg20:
833214082Sdim	case DW_OP_breg21:
834214082Sdim	case DW_OP_breg22:
835214082Sdim	case DW_OP_breg23:
836214082Sdim	case DW_OP_breg24:
837214082Sdim	case DW_OP_breg25:
838214082Sdim	case DW_OP_breg26:
839214082Sdim	case DW_OP_breg27:
840214082Sdim	case DW_OP_breg28:
841214082Sdim	case DW_OP_breg29:
842214082Sdim	case DW_OP_breg30:
843214082Sdim	case DW_OP_breg31:
844214082Sdim	  printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0,
845214082Sdim		  read_leb128 (data, &bytes_read, 1));
846214082Sdim	  data += bytes_read;
847214082Sdim	  break;
848214082Sdim
849214082Sdim	case DW_OP_regx:
850214082Sdim	  printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0));
851214082Sdim	  data += bytes_read;
852214082Sdim	  break;
853214082Sdim	case DW_OP_fbreg:
854214082Sdim	  need_frame_base = 1;
855214082Sdim	  printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1));
856214082Sdim	  data += bytes_read;
857214082Sdim	  break;
858214082Sdim	case DW_OP_bregx:
859214082Sdim	  uvalue = read_leb128 (data, &bytes_read, 0);
860214082Sdim	  data += bytes_read;
861214082Sdim	  printf ("DW_OP_bregx: %lu %ld", uvalue,
862214082Sdim		  read_leb128 (data, &bytes_read, 1));
863214082Sdim	  data += bytes_read;
864214082Sdim	  break;
865214082Sdim	case DW_OP_piece:
866214082Sdim	  printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0));
867214082Sdim	  data += bytes_read;
868214082Sdim	  break;
869214082Sdim	case DW_OP_deref_size:
870214082Sdim	  printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1));
871214082Sdim	  break;
872214082Sdim	case DW_OP_xderef_size:
873214082Sdim	  printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1));
874214082Sdim	  break;
875214082Sdim	case DW_OP_nop:
876214082Sdim	  printf ("DW_OP_nop");
877214082Sdim	  break;
878214082Sdim
879214082Sdim	  /* DWARF 3 extensions.  */
880214082Sdim	case DW_OP_push_object_address:
881214082Sdim	  printf ("DW_OP_push_object_address");
882214082Sdim	  break;
883214082Sdim	case DW_OP_call2:
884214082Sdim	  /* XXX: Strictly speaking for 64-bit DWARF3 files
885214082Sdim	     this ought to be an 8-byte wide computation.  */
886214082Sdim	  printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2) + cu_offset);
887214082Sdim	  data += 2;
888214082Sdim	  break;
889214082Sdim	case DW_OP_call4:
890214082Sdim	  /* XXX: Strictly speaking for 64-bit DWARF3 files
891214082Sdim	     this ought to be an 8-byte wide computation.  */
892214082Sdim	  printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4) + cu_offset);
893214082Sdim	  data += 4;
894214082Sdim	  break;
895214082Sdim	case DW_OP_call_ref:
896214082Sdim	  printf ("DW_OP_call_ref");
897214082Sdim	  break;
898214082Sdim
899214082Sdim	  /* GNU extensions.  */
900214082Sdim	case DW_OP_GNU_push_tls_address:
901214082Sdim	  printf ("DW_OP_GNU_push_tls_address");
902214082Sdim	  break;
903214082Sdim
904214082Sdim	default:
905214082Sdim	  if (op >= DW_OP_lo_user
906214082Sdim	      && op <= DW_OP_hi_user)
907214082Sdim	    printf (_("(User defined location op)"));
908214082Sdim	  else
909214082Sdim	    printf (_("(Unknown location op)"));
910214082Sdim	  /* No way to tell where the next op is, so just bail.  */
911214082Sdim	  return need_frame_base;
912214082Sdim	}
913214082Sdim
914214082Sdim      /* Separate the ops.  */
915214082Sdim      if (data < end)
916214082Sdim	printf ("; ");
917214082Sdim    }
918214082Sdim
919214082Sdim  return need_frame_base;
920214082Sdim}
921214082Sdim
922214082Sdimstatic unsigned char *
923214082Sdimread_and_display_attr_value (unsigned long attribute,
924214082Sdim			     unsigned long form,
925214082Sdim			     unsigned char *data,
926214082Sdim			     unsigned long cu_offset,
927214082Sdim			     unsigned long pointer_size,
928214082Sdim			     unsigned long offset_size,
929214082Sdim			     int dwarf_version,
930214082Sdim			     debug_info *debug_info_p,
931214082Sdim			     int do_loc)
932214082Sdim{
933214082Sdim  unsigned long uvalue = 0;
934214082Sdim  unsigned char *block_start = NULL;
935214082Sdim  unsigned int bytes_read;
936214082Sdim
937214082Sdim  switch (form)
938214082Sdim    {
939214082Sdim    default:
940214082Sdim      break;
941214082Sdim
942214082Sdim    case DW_FORM_ref_addr:
943214082Sdim      if (dwarf_version == 2)
944214082Sdim	{
945214082Sdim	  uvalue = byte_get (data, pointer_size);
946214082Sdim	  data += pointer_size;
947214082Sdim	}
948214082Sdim      else if (dwarf_version == 3)
949214082Sdim	{
950214082Sdim	  uvalue = byte_get (data, offset_size);
951214082Sdim	  data += offset_size;
952214082Sdim	}
953214082Sdim      else
954214082Sdim	{
955214082Sdim	  error (_("Internal error: DWARF version is not 2 or 3.\n"));
956214082Sdim	}
957214082Sdim      break;
958214082Sdim
959214082Sdim    case DW_FORM_addr:
960214082Sdim      uvalue = byte_get (data, pointer_size);
961214082Sdim      data += pointer_size;
962214082Sdim      break;
963214082Sdim
964214082Sdim    case DW_FORM_strp:
965214082Sdim      uvalue = byte_get (data, offset_size);
966214082Sdim      data += offset_size;
967214082Sdim      break;
968214082Sdim
969214082Sdim    case DW_FORM_ref1:
970214082Sdim    case DW_FORM_flag:
971214082Sdim    case DW_FORM_data1:
972214082Sdim      uvalue = byte_get (data++, 1);
973214082Sdim      break;
974214082Sdim
975214082Sdim    case DW_FORM_ref2:
976214082Sdim    case DW_FORM_data2:
977214082Sdim      uvalue = byte_get (data, 2);
978214082Sdim      data += 2;
979214082Sdim      break;
980214082Sdim
981214082Sdim    case DW_FORM_ref4:
982214082Sdim    case DW_FORM_data4:
983214082Sdim      uvalue = byte_get (data, 4);
984214082Sdim      data += 4;
985214082Sdim      break;
986214082Sdim
987214082Sdim    case DW_FORM_sdata:
988214082Sdim      uvalue = read_leb128 (data, & bytes_read, 1);
989214082Sdim      data += bytes_read;
990214082Sdim      break;
991214082Sdim
992214082Sdim    case DW_FORM_ref_udata:
993214082Sdim    case DW_FORM_udata:
994214082Sdim      uvalue = read_leb128 (data, & bytes_read, 0);
995214082Sdim      data += bytes_read;
996214082Sdim      break;
997214082Sdim
998214082Sdim    case DW_FORM_indirect:
999214082Sdim      form = read_leb128 (data, & bytes_read, 0);
1000214082Sdim      data += bytes_read;
1001214082Sdim      if (!do_loc)
1002214082Sdim	printf (" %s", get_FORM_name (form));
1003214082Sdim      return read_and_display_attr_value (attribute, form, data,
1004214082Sdim					  cu_offset, pointer_size,
1005214082Sdim					  offset_size, dwarf_version,
1006214082Sdim					  debug_info_p, do_loc);
1007214082Sdim    }
1008214082Sdim
1009214082Sdim  switch (form)
1010214082Sdim    {
1011214082Sdim    case DW_FORM_ref_addr:
1012214082Sdim      if (!do_loc)
1013214082Sdim	printf (" <#%lx>", uvalue);
1014214082Sdim      break;
1015214082Sdim
1016214082Sdim    case DW_FORM_ref1:
1017214082Sdim    case DW_FORM_ref2:
1018214082Sdim    case DW_FORM_ref4:
1019214082Sdim    case DW_FORM_ref_udata:
1020214082Sdim      if (!do_loc)
1021214082Sdim	printf (" <%lx>", uvalue + cu_offset);
1022214082Sdim      break;
1023214082Sdim
1024214082Sdim    case DW_FORM_data4:
1025214082Sdim    case DW_FORM_addr:
1026214082Sdim      if (!do_loc)
1027214082Sdim	printf (" %#lx", uvalue);
1028214082Sdim      break;
1029214082Sdim
1030214082Sdim    case DW_FORM_flag:
1031214082Sdim    case DW_FORM_data1:
1032214082Sdim    case DW_FORM_data2:
1033214082Sdim    case DW_FORM_sdata:
1034214082Sdim    case DW_FORM_udata:
1035214082Sdim      if (!do_loc)
1036214082Sdim	printf (" %ld", uvalue);
1037214082Sdim      break;
1038214082Sdim
1039214082Sdim    case DW_FORM_ref8:
1040214082Sdim    case DW_FORM_data8:
1041214082Sdim      if (!do_loc)
1042214082Sdim	{
1043214082Sdim	  uvalue = byte_get (data, 4);
1044214082Sdim	  printf (" %lx", uvalue);
1045214082Sdim	  printf (" %lx", (unsigned long) byte_get (data + 4, 4));
1046214082Sdim	}
1047214082Sdim      if ((do_loc || do_debug_loc || do_debug_ranges)
1048214082Sdim	  && num_debug_info_entries == 0)
1049214082Sdim	{
1050214082Sdim	  if (sizeof (uvalue) == 8)
1051214082Sdim	    uvalue = byte_get (data, 8);
1052214082Sdim	  else
1053214082Sdim	    error (_("DW_FORM_data8 is unsupported when sizeof (unsigned long) != 8\n"));
1054214082Sdim	}
1055214082Sdim      data += 8;
1056214082Sdim      break;
1057214082Sdim
1058214082Sdim    case DW_FORM_string:
1059214082Sdim      if (!do_loc)
1060214082Sdim	printf (" %s", data);
1061214082Sdim      data += strlen ((char *) data) + 1;
1062214082Sdim      break;
1063214082Sdim
1064214082Sdim    case DW_FORM_block:
1065214082Sdim      uvalue = read_leb128 (data, & bytes_read, 0);
1066214082Sdim      block_start = data + bytes_read;
1067214082Sdim      if (do_loc)
1068214082Sdim	data = block_start + uvalue;
1069214082Sdim      else
1070214082Sdim	data = display_block (block_start, uvalue);
1071214082Sdim      break;
1072214082Sdim
1073214082Sdim    case DW_FORM_block1:
1074214082Sdim      uvalue = byte_get (data, 1);
1075214082Sdim      block_start = data + 1;
1076214082Sdim      if (do_loc)
1077214082Sdim	data = block_start + uvalue;
1078214082Sdim      else
1079214082Sdim	data = display_block (block_start, uvalue);
1080214082Sdim      break;
1081214082Sdim
1082214082Sdim    case DW_FORM_block2:
1083214082Sdim      uvalue = byte_get (data, 2);
1084214082Sdim      block_start = data + 2;
1085214082Sdim      if (do_loc)
1086214082Sdim	data = block_start + uvalue;
1087214082Sdim      else
1088214082Sdim	data = display_block (block_start, uvalue);
1089214082Sdim      break;
1090214082Sdim
1091214082Sdim    case DW_FORM_block4:
1092214082Sdim      uvalue = byte_get (data, 4);
1093214082Sdim      block_start = data + 4;
1094214082Sdim      if (do_loc)
1095214082Sdim	data = block_start + uvalue;
1096214082Sdim      else
1097214082Sdim	data = display_block (block_start, uvalue);
1098214082Sdim      break;
1099214082Sdim
1100214082Sdim    case DW_FORM_strp:
1101214082Sdim      if (!do_loc)
1102214082Sdim	printf (_(" (indirect string, offset: 0x%lx): %s"),
1103214082Sdim		uvalue, fetch_indirect_string (uvalue));
1104214082Sdim      break;
1105214082Sdim
1106214082Sdim    case DW_FORM_indirect:
1107214082Sdim      /* Handled above.  */
1108214082Sdim      break;
1109214082Sdim
1110214082Sdim    default:
1111214082Sdim      warn (_("Unrecognized form: %lu\n"), form);
1112214082Sdim      break;
1113214082Sdim    }
1114214082Sdim
1115214082Sdim  /* For some attributes we can display further information.  */
1116214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1117214082Sdim      && num_debug_info_entries == 0)
1118214082Sdim    {
1119214082Sdim      switch (attribute)
1120214082Sdim	{
1121214082Sdim	case DW_AT_frame_base:
1122214082Sdim	  have_frame_base = 1;
1123214082Sdim	case DW_AT_location:
1124214082Sdim	case DW_AT_data_member_location:
1125214082Sdim	case DW_AT_vtable_elem_location:
1126214082Sdim	case DW_AT_allocated:
1127214082Sdim	case DW_AT_associated:
1128214082Sdim	case DW_AT_data_location:
1129214082Sdim	case DW_AT_stride:
1130214082Sdim	case DW_AT_upper_bound:
1131214082Sdim	case DW_AT_lower_bound:
1132214082Sdim	  if (form == DW_FORM_data4 || form == DW_FORM_data8)
1133214082Sdim	    {
1134214082Sdim	      /* Process location list.  */
1135214082Sdim	      unsigned int max = debug_info_p->max_loc_offsets;
1136214082Sdim	      unsigned int num = debug_info_p->num_loc_offsets;
1137214082Sdim
1138214082Sdim	      if (max == 0 || num >= max)
1139214082Sdim		{
1140214082Sdim		  max += 1024;
1141214082Sdim		  debug_info_p->loc_offsets
1142214082Sdim		    = xcrealloc (debug_info_p->loc_offsets,
1143214082Sdim				 max, sizeof (*debug_info_p->loc_offsets));
1144214082Sdim		  debug_info_p->have_frame_base
1145214082Sdim		    = xcrealloc (debug_info_p->have_frame_base,
1146214082Sdim				 max, sizeof (*debug_info_p->have_frame_base));
1147214082Sdim		  debug_info_p->max_loc_offsets = max;
1148214082Sdim		}
1149214082Sdim	      debug_info_p->loc_offsets [num] = uvalue;
1150214082Sdim	      debug_info_p->have_frame_base [num] = have_frame_base;
1151214082Sdim	      debug_info_p->num_loc_offsets++;
1152214082Sdim	    }
1153214082Sdim	  break;
1154214082Sdim
1155214082Sdim	case DW_AT_low_pc:
1156214082Sdim	  if (need_base_address)
1157214082Sdim	    debug_info_p->base_address = uvalue;
1158214082Sdim	  break;
1159214082Sdim
1160214082Sdim	case DW_AT_ranges:
1161214082Sdim	  if (form == DW_FORM_data4 || form == DW_FORM_data8)
1162214082Sdim	    {
1163214082Sdim	      /* Process range list.  */
1164214082Sdim	      unsigned int max = debug_info_p->max_range_lists;
1165214082Sdim	      unsigned int num = debug_info_p->num_range_lists;
1166214082Sdim
1167214082Sdim	      if (max == 0 || num >= max)
1168214082Sdim		{
1169214082Sdim		  max += 1024;
1170214082Sdim		  debug_info_p->range_lists
1171214082Sdim		    = xcrealloc (debug_info_p->range_lists,
1172214082Sdim				 max, sizeof (*debug_info_p->range_lists));
1173214082Sdim		  debug_info_p->max_range_lists = max;
1174214082Sdim		}
1175214082Sdim	      debug_info_p->range_lists [num] = uvalue;
1176214082Sdim	      debug_info_p->num_range_lists++;
1177214082Sdim	    }
1178214082Sdim	  break;
1179214082Sdim
1180214082Sdim	default:
1181214082Sdim	  break;
1182214082Sdim	}
1183214082Sdim    }
1184214082Sdim
1185214082Sdim  if (do_loc)
1186214082Sdim    return data;
1187214082Sdim
1188214082Sdim  printf ("\t");
1189214082Sdim
1190214082Sdim  switch (attribute)
1191214082Sdim    {
1192214082Sdim    case DW_AT_inline:
1193214082Sdim      switch (uvalue)
1194214082Sdim	{
1195214082Sdim	case DW_INL_not_inlined:
1196214082Sdim	  printf (_("(not inlined)"));
1197214082Sdim	  break;
1198214082Sdim	case DW_INL_inlined:
1199214082Sdim	  printf (_("(inlined)"));
1200214082Sdim	  break;
1201214082Sdim	case DW_INL_declared_not_inlined:
1202214082Sdim	  printf (_("(declared as inline but ignored)"));
1203214082Sdim	  break;
1204214082Sdim	case DW_INL_declared_inlined:
1205214082Sdim	  printf (_("(declared as inline and inlined)"));
1206214082Sdim	  break;
1207214082Sdim	default:
1208214082Sdim	  printf (_("  (Unknown inline attribute value: %lx)"), uvalue);
1209214082Sdim	  break;
1210214082Sdim	}
1211214082Sdim      break;
1212214082Sdim
1213214082Sdim    case DW_AT_language:
1214214082Sdim      switch (uvalue)
1215214082Sdim	{
1216214082Sdim	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
1217214082Sdim	case DW_LANG_C89:		printf ("(ANSI C)"); break;
1218214082Sdim	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
1219214082Sdim	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
1220214082Sdim	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
1221214082Sdim	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
1222214082Sdim	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
1223214082Sdim	case DW_LANG_Ada83:		printf ("(Ada)"); break;
1224214082Sdim	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
1225214082Sdim	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
1226214082Sdim	  /* DWARF 2.1 values.	*/
1227214082Sdim	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
1228214082Sdim	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
1229214082Sdim	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
1230214082Sdim	  /* MIPS extension.  */
1231214082Sdim	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
1232214082Sdim	  /* UPC extension.  */
1233214082Sdim	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
1234214082Sdim	default:
1235214082Sdim	  printf ("(Unknown: %lx)", uvalue);
1236214082Sdim	  break;
1237214082Sdim	}
1238214082Sdim      break;
1239214082Sdim
1240214082Sdim    case DW_AT_encoding:
1241214082Sdim      switch (uvalue)
1242214082Sdim	{
1243214082Sdim	case DW_ATE_void:		printf ("(void)"); break;
1244214082Sdim	case DW_ATE_address:		printf ("(machine address)"); break;
1245214082Sdim	case DW_ATE_boolean:		printf ("(boolean)"); break;
1246214082Sdim	case DW_ATE_complex_float:	printf ("(complex float)"); break;
1247214082Sdim	case DW_ATE_float:		printf ("(float)"); break;
1248214082Sdim	case DW_ATE_signed:		printf ("(signed)"); break;
1249214082Sdim	case DW_ATE_signed_char:	printf ("(signed char)"); break;
1250214082Sdim	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
1251214082Sdim	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
1252214082Sdim	  /* DWARF 2.1 value.  */
1253214082Sdim	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
1254214082Sdim	case DW_ATE_decimal_float:	printf ("(decimal float)"); break;
1255214082Sdim	default:
1256214082Sdim	  if (uvalue >= DW_ATE_lo_user
1257214082Sdim	      && uvalue <= DW_ATE_hi_user)
1258214082Sdim	    printf ("(user defined type)");
1259214082Sdim	  else
1260214082Sdim	    printf ("(unknown type)");
1261214082Sdim	  break;
1262214082Sdim	}
1263214082Sdim      break;
1264214082Sdim
1265214082Sdim    case DW_AT_accessibility:
1266214082Sdim      switch (uvalue)
1267214082Sdim	{
1268214082Sdim	case DW_ACCESS_public:		printf ("(public)"); break;
1269214082Sdim	case DW_ACCESS_protected:	printf ("(protected)"); break;
1270214082Sdim	case DW_ACCESS_private:		printf ("(private)"); break;
1271214082Sdim	default:
1272214082Sdim	  printf ("(unknown accessibility)");
1273214082Sdim	  break;
1274214082Sdim	}
1275214082Sdim      break;
1276214082Sdim
1277214082Sdim    case DW_AT_visibility:
1278214082Sdim      switch (uvalue)
1279214082Sdim	{
1280214082Sdim	case DW_VIS_local:		printf ("(local)"); break;
1281214082Sdim	case DW_VIS_exported:		printf ("(exported)"); break;
1282214082Sdim	case DW_VIS_qualified:		printf ("(qualified)"); break;
1283214082Sdim	default:			printf ("(unknown visibility)"); break;
1284214082Sdim	}
1285214082Sdim      break;
1286214082Sdim
1287214082Sdim    case DW_AT_virtuality:
1288214082Sdim      switch (uvalue)
1289214082Sdim	{
1290214082Sdim	case DW_VIRTUALITY_none:	printf ("(none)"); break;
1291214082Sdim	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
1292214082Sdim	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
1293214082Sdim	default:			printf ("(unknown virtuality)"); break;
1294214082Sdim	}
1295214082Sdim      break;
1296214082Sdim
1297214082Sdim    case DW_AT_identifier_case:
1298214082Sdim      switch (uvalue)
1299214082Sdim	{
1300214082Sdim	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
1301214082Sdim	case DW_ID_up_case:		printf ("(up_case)"); break;
1302214082Sdim	case DW_ID_down_case:		printf ("(down_case)"); break;
1303214082Sdim	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
1304214082Sdim	default:			printf ("(unknown case)"); break;
1305214082Sdim	}
1306214082Sdim      break;
1307214082Sdim
1308214082Sdim    case DW_AT_calling_convention:
1309214082Sdim      switch (uvalue)
1310214082Sdim	{
1311214082Sdim	case DW_CC_normal:	printf ("(normal)"); break;
1312214082Sdim	case DW_CC_program:	printf ("(program)"); break;
1313214082Sdim	case DW_CC_nocall:	printf ("(nocall)"); break;
1314214082Sdim	default:
1315214082Sdim	  if (uvalue >= DW_CC_lo_user
1316214082Sdim	      && uvalue <= DW_CC_hi_user)
1317214082Sdim	    printf ("(user defined)");
1318214082Sdim	  else
1319214082Sdim	    printf ("(unknown convention)");
1320214082Sdim	}
1321214082Sdim      break;
1322214082Sdim
1323214082Sdim    case DW_AT_ordering:
1324214082Sdim      switch (uvalue)
1325214082Sdim	{
1326214082Sdim	case -1: printf ("(undefined)"); break;
1327214082Sdim	case 0:  printf ("(row major)"); break;
1328214082Sdim	case 1:  printf ("(column major)"); break;
1329214082Sdim	}
1330214082Sdim      break;
1331214082Sdim
1332214082Sdim    case DW_AT_frame_base:
1333214082Sdim      have_frame_base = 1;
1334214082Sdim    case DW_AT_location:
1335214082Sdim    case DW_AT_data_member_location:
1336214082Sdim    case DW_AT_vtable_elem_location:
1337214082Sdim    case DW_AT_allocated:
1338214082Sdim    case DW_AT_associated:
1339214082Sdim    case DW_AT_data_location:
1340214082Sdim    case DW_AT_stride:
1341214082Sdim    case DW_AT_upper_bound:
1342214082Sdim    case DW_AT_lower_bound:
1343214082Sdim      if (block_start)
1344214082Sdim	{
1345214082Sdim	  int need_frame_base;
1346214082Sdim
1347214082Sdim	  printf ("(");
1348214082Sdim	  need_frame_base = decode_location_expression (block_start,
1349214082Sdim							pointer_size,
1350214082Sdim							uvalue,
1351214082Sdim							cu_offset);
1352214082Sdim	  printf (")");
1353214082Sdim	  if (need_frame_base && !have_frame_base)
1354214082Sdim	    printf (_(" [without DW_AT_frame_base]"));
1355214082Sdim	}
1356214082Sdim      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
1357214082Sdim	printf (_("(location list)"));
1358214082Sdim
1359214082Sdim      break;
1360214082Sdim
1361214082Sdim    default:
1362214082Sdim      break;
1363214082Sdim    }
1364214082Sdim
1365214082Sdim  return data;
1366214082Sdim}
1367214082Sdim
1368214082Sdimstatic char *
1369214082Sdimget_AT_name (unsigned long attribute)
1370214082Sdim{
1371214082Sdim  switch (attribute)
1372214082Sdim    {
1373214082Sdim    case DW_AT_sibling:			return "DW_AT_sibling";
1374214082Sdim    case DW_AT_location:		return "DW_AT_location";
1375214082Sdim    case DW_AT_name:			return "DW_AT_name";
1376214082Sdim    case DW_AT_ordering:		return "DW_AT_ordering";
1377214082Sdim    case DW_AT_subscr_data:		return "DW_AT_subscr_data";
1378214082Sdim    case DW_AT_byte_size:		return "DW_AT_byte_size";
1379214082Sdim    case DW_AT_bit_offset:		return "DW_AT_bit_offset";
1380214082Sdim    case DW_AT_bit_size:		return "DW_AT_bit_size";
1381214082Sdim    case DW_AT_element_list:		return "DW_AT_element_list";
1382214082Sdim    case DW_AT_stmt_list:		return "DW_AT_stmt_list";
1383214082Sdim    case DW_AT_low_pc:			return "DW_AT_low_pc";
1384214082Sdim    case DW_AT_high_pc:			return "DW_AT_high_pc";
1385214082Sdim    case DW_AT_language:		return "DW_AT_language";
1386214082Sdim    case DW_AT_member:			return "DW_AT_member";
1387214082Sdim    case DW_AT_discr:			return "DW_AT_discr";
1388214082Sdim    case DW_AT_discr_value:		return "DW_AT_discr_value";
1389214082Sdim    case DW_AT_visibility:		return "DW_AT_visibility";
1390214082Sdim    case DW_AT_import:			return "DW_AT_import";
1391214082Sdim    case DW_AT_string_length:		return "DW_AT_string_length";
1392214082Sdim    case DW_AT_common_reference:	return "DW_AT_common_reference";
1393214082Sdim    case DW_AT_comp_dir:		return "DW_AT_comp_dir";
1394214082Sdim    case DW_AT_const_value:		return "DW_AT_const_value";
1395214082Sdim    case DW_AT_containing_type:		return "DW_AT_containing_type";
1396214082Sdim    case DW_AT_default_value:		return "DW_AT_default_value";
1397214082Sdim    case DW_AT_inline:			return "DW_AT_inline";
1398214082Sdim    case DW_AT_is_optional:		return "DW_AT_is_optional";
1399214082Sdim    case DW_AT_lower_bound:		return "DW_AT_lower_bound";
1400214082Sdim    case DW_AT_producer:		return "DW_AT_producer";
1401214082Sdim    case DW_AT_prototyped:		return "DW_AT_prototyped";
1402214082Sdim    case DW_AT_return_addr:		return "DW_AT_return_addr";
1403214082Sdim    case DW_AT_start_scope:		return "DW_AT_start_scope";
1404214082Sdim    case DW_AT_stride_size:		return "DW_AT_stride_size";
1405214082Sdim    case DW_AT_upper_bound:		return "DW_AT_upper_bound";
1406214082Sdim    case DW_AT_abstract_origin:		return "DW_AT_abstract_origin";
1407214082Sdim    case DW_AT_accessibility:		return "DW_AT_accessibility";
1408214082Sdim    case DW_AT_address_class:		return "DW_AT_address_class";
1409214082Sdim    case DW_AT_artificial:		return "DW_AT_artificial";
1410214082Sdim    case DW_AT_base_types:		return "DW_AT_base_types";
1411214082Sdim    case DW_AT_calling_convention:	return "DW_AT_calling_convention";
1412214082Sdim    case DW_AT_count:			return "DW_AT_count";
1413214082Sdim    case DW_AT_data_member_location:	return "DW_AT_data_member_location";
1414214082Sdim    case DW_AT_decl_column:		return "DW_AT_decl_column";
1415214082Sdim    case DW_AT_decl_file:		return "DW_AT_decl_file";
1416214082Sdim    case DW_AT_decl_line:		return "DW_AT_decl_line";
1417214082Sdim    case DW_AT_declaration:		return "DW_AT_declaration";
1418214082Sdim    case DW_AT_discr_list:		return "DW_AT_discr_list";
1419214082Sdim    case DW_AT_encoding:		return "DW_AT_encoding";
1420214082Sdim    case DW_AT_external:		return "DW_AT_external";
1421214082Sdim    case DW_AT_frame_base:		return "DW_AT_frame_base";
1422214082Sdim    case DW_AT_friend:			return "DW_AT_friend";
1423214082Sdim    case DW_AT_identifier_case:		return "DW_AT_identifier_case";
1424214082Sdim    case DW_AT_macro_info:		return "DW_AT_macro_info";
1425214082Sdim    case DW_AT_namelist_items:		return "DW_AT_namelist_items";
1426214082Sdim    case DW_AT_priority:		return "DW_AT_priority";
1427214082Sdim    case DW_AT_segment:			return "DW_AT_segment";
1428214082Sdim    case DW_AT_specification:		return "DW_AT_specification";
1429214082Sdim    case DW_AT_static_link:		return "DW_AT_static_link";
1430214082Sdim    case DW_AT_type:			return "DW_AT_type";
1431214082Sdim    case DW_AT_use_location:		return "DW_AT_use_location";
1432214082Sdim    case DW_AT_variable_parameter:	return "DW_AT_variable_parameter";
1433214082Sdim    case DW_AT_virtuality:		return "DW_AT_virtuality";
1434214082Sdim    case DW_AT_vtable_elem_location:	return "DW_AT_vtable_elem_location";
1435214082Sdim      /* DWARF 2.1 values.  */
1436214082Sdim    case DW_AT_allocated:		return "DW_AT_allocated";
1437214082Sdim    case DW_AT_associated:		return "DW_AT_associated";
1438214082Sdim    case DW_AT_data_location:		return "DW_AT_data_location";
1439214082Sdim    case DW_AT_stride:			return "DW_AT_stride";
1440214082Sdim    case DW_AT_entry_pc:		return "DW_AT_entry_pc";
1441214082Sdim    case DW_AT_use_UTF8:		return "DW_AT_use_UTF8";
1442214082Sdim    case DW_AT_extension:		return "DW_AT_extension";
1443214082Sdim    case DW_AT_ranges:			return "DW_AT_ranges";
1444214082Sdim    case DW_AT_trampoline:		return "DW_AT_trampoline";
1445214082Sdim    case DW_AT_call_column:		return "DW_AT_call_column";
1446214082Sdim    case DW_AT_call_file:		return "DW_AT_call_file";
1447214082Sdim    case DW_AT_call_line:		return "DW_AT_call_line";
1448214082Sdim      /* SGI/MIPS extensions.  */
1449214082Sdim    case DW_AT_MIPS_fde:		return "DW_AT_MIPS_fde";
1450214082Sdim    case DW_AT_MIPS_loop_begin:		return "DW_AT_MIPS_loop_begin";
1451214082Sdim    case DW_AT_MIPS_tail_loop_begin:	return "DW_AT_MIPS_tail_loop_begin";
1452214082Sdim    case DW_AT_MIPS_epilog_begin:	return "DW_AT_MIPS_epilog_begin";
1453214082Sdim    case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
1454214082Sdim    case DW_AT_MIPS_software_pipeline_depth:
1455214082Sdim      return "DW_AT_MIPS_software_pipeline_depth";
1456214082Sdim    case DW_AT_MIPS_linkage_name:	return "DW_AT_MIPS_linkage_name";
1457214082Sdim    case DW_AT_MIPS_stride:		return "DW_AT_MIPS_stride";
1458214082Sdim    case DW_AT_MIPS_abstract_name:	return "DW_AT_MIPS_abstract_name";
1459214082Sdim    case DW_AT_MIPS_clone_origin:	return "DW_AT_MIPS_clone_origin";
1460214082Sdim    case DW_AT_MIPS_has_inlines:	return "DW_AT_MIPS_has_inlines";
1461214082Sdim      /* GNU extensions.  */
1462214082Sdim    case DW_AT_sf_names:		return "DW_AT_sf_names";
1463214082Sdim    case DW_AT_src_info:		return "DW_AT_src_info";
1464214082Sdim    case DW_AT_mac_info:		return "DW_AT_mac_info";
1465214082Sdim    case DW_AT_src_coords:		return "DW_AT_src_coords";
1466214082Sdim    case DW_AT_body_begin:		return "DW_AT_body_begin";
1467214082Sdim    case DW_AT_body_end:		return "DW_AT_body_end";
1468214082Sdim    case DW_AT_GNU_vector:		return "DW_AT_GNU_vector";
1469214082Sdim      /* UPC extension.  */
1470214082Sdim    case DW_AT_upc_threads_scaled:	return "DW_AT_upc_threads_scaled";
1471214082Sdim    default:
1472214082Sdim      {
1473214082Sdim	static char buffer[100];
1474214082Sdim
1475214082Sdim	snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
1476214082Sdim		  attribute);
1477214082Sdim	return buffer;
1478214082Sdim      }
1479214082Sdim    }
1480214082Sdim}
1481214082Sdim
1482214082Sdimstatic unsigned char *
1483214082Sdimread_and_display_attr (unsigned long attribute,
1484214082Sdim		       unsigned long form,
1485214082Sdim		       unsigned char *data,
1486214082Sdim		       unsigned long cu_offset,
1487214082Sdim		       unsigned long pointer_size,
1488214082Sdim		       unsigned long offset_size,
1489214082Sdim		       int dwarf_version,
1490214082Sdim		       debug_info *debug_info_p,
1491214082Sdim		       int do_loc)
1492214082Sdim{
1493214082Sdim  if (!do_loc)
1494214082Sdim    printf ("     %-18s:", get_AT_name (attribute));
1495214082Sdim  data = read_and_display_attr_value (attribute, form, data, cu_offset,
1496214082Sdim				      pointer_size, offset_size,
1497214082Sdim				      dwarf_version, debug_info_p,
1498214082Sdim				      do_loc);
1499214082Sdim  if (!do_loc)
1500214082Sdim    printf ("\n");
1501214082Sdim  return data;
1502214082Sdim}
1503214082Sdim
1504214082Sdim
1505214082Sdim/* Process the contents of a .debug_info section.  If do_loc is non-zero
1506214082Sdim   then we are scanning for location lists and we do not want to display
1507214082Sdim   anything to the user.  */
1508214082Sdim
1509214082Sdimstatic int
1510214082Sdimprocess_debug_info (struct dwarf_section *section, void *file,
1511214082Sdim		    int do_loc)
1512214082Sdim{
1513214082Sdim  unsigned char *start = section->start;
1514214082Sdim  unsigned char *end = start + section->size;
1515214082Sdim  unsigned char *section_begin;
1516214082Sdim  unsigned int unit;
1517214082Sdim  unsigned int num_units = 0;
1518214082Sdim
1519214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1520214082Sdim      && num_debug_info_entries == 0)
1521214082Sdim    {
1522214082Sdim      unsigned long length;
1523214082Sdim
1524214082Sdim      /* First scan the section to get the number of comp units.  */
1525214082Sdim      for (section_begin = start, num_units = 0; section_begin < end;
1526214082Sdim	   num_units ++)
1527214082Sdim	{
1528214082Sdim	  /* Read the first 4 bytes.  For a 32-bit DWARF section, this
1529214082Sdim	     will be the length.  For a 64-bit DWARF section, it'll be
1530214082Sdim	     the escape code 0xffffffff followed by an 8 byte length.  */
1531214082Sdim	  length = byte_get (section_begin, 4);
1532214082Sdim
1533214082Sdim	  if (length == 0xffffffff)
1534214082Sdim	    {
1535214082Sdim	      length = byte_get (section_begin + 4, 8);
1536214082Sdim	      section_begin += length + 12;
1537214082Sdim	    }
1538214082Sdim	  else
1539214082Sdim	    section_begin += length + 4;
1540214082Sdim	}
1541214082Sdim
1542214082Sdim      if (num_units == 0)
1543214082Sdim	{
1544214082Sdim	  error (_("No comp units in %s section ?"), section->name);
1545214082Sdim	  return 0;
1546214082Sdim	}
1547214082Sdim
1548214082Sdim      /* Then allocate an array to hold the information.  */
1549214082Sdim      debug_information = cmalloc (num_units,
1550214082Sdim				   sizeof (* debug_information));
1551214082Sdim      if (debug_information == NULL)
1552214082Sdim	{
1553214082Sdim	  error (_("Not enough memory for a debug info array of %u entries"),
1554214082Sdim		 num_units);
1555214082Sdim	  return 0;
1556214082Sdim	}
1557214082Sdim    }
1558214082Sdim
1559214082Sdim  if (!do_loc)
1560214082Sdim    {
1561214082Sdim      printf (_("The section %s contains:\n\n"), section->name);
1562214082Sdim
1563214082Sdim      load_debug_section (str, file);
1564214082Sdim    }
1565214082Sdim
1566214082Sdim  load_debug_section (abbrev, file);
1567214082Sdim  if (debug_displays [abbrev].section.start == NULL)
1568214082Sdim    {
1569214082Sdim      warn (_("Unable to locate %s section!\n"),
1570214082Sdim	    debug_displays [abbrev].section.name);
1571214082Sdim      return 0;
1572214082Sdim    }
1573214082Sdim
1574214082Sdim  for (section_begin = start, unit = 0; start < end; unit++)
1575214082Sdim    {
1576214082Sdim      DWARF2_Internal_CompUnit compunit;
1577214082Sdim      unsigned char *hdrptr;
1578214082Sdim      unsigned char *cu_abbrev_offset_ptr;
1579214082Sdim      unsigned char *tags;
1580214082Sdim      int level;
1581214082Sdim      unsigned long cu_offset;
1582214082Sdim      int offset_size;
1583214082Sdim      int initial_length_size;
1584214082Sdim
1585214082Sdim      hdrptr = start;
1586214082Sdim
1587214082Sdim      compunit.cu_length = byte_get (hdrptr, 4);
1588214082Sdim      hdrptr += 4;
1589214082Sdim
1590214082Sdim      if (compunit.cu_length == 0xffffffff)
1591214082Sdim	{
1592214082Sdim	  compunit.cu_length = byte_get (hdrptr, 8);
1593214082Sdim	  hdrptr += 8;
1594214082Sdim	  offset_size = 8;
1595214082Sdim	  initial_length_size = 12;
1596214082Sdim	}
1597214082Sdim      else
1598214082Sdim	{
1599214082Sdim	  offset_size = 4;
1600214082Sdim	  initial_length_size = 4;
1601214082Sdim	}
1602214082Sdim
1603214082Sdim      compunit.cu_version = byte_get (hdrptr, 2);
1604214082Sdim      hdrptr += 2;
1605214082Sdim
1606214082Sdim      cu_offset = start - section_begin;
1607214082Sdim      start += compunit.cu_length + initial_length_size;
1608214082Sdim
1609214082Sdim      cu_abbrev_offset_ptr = hdrptr;
1610214082Sdim      compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
1611214082Sdim      hdrptr += offset_size;
1612214082Sdim
1613214082Sdim      compunit.cu_pointer_size = byte_get (hdrptr, 1);
1614214082Sdim      hdrptr += 1;
1615214082Sdim      if ((do_loc || do_debug_loc || do_debug_ranges)
1616214082Sdim	  && num_debug_info_entries == 0)
1617214082Sdim	{
1618214082Sdim	  debug_information [unit].cu_offset = cu_offset;
1619214082Sdim	  debug_information [unit].pointer_size
1620214082Sdim	    = compunit.cu_pointer_size;
1621214082Sdim	  debug_information [unit].base_address = 0;
1622214082Sdim	  debug_information [unit].loc_offsets = NULL;
1623214082Sdim	  debug_information [unit].have_frame_base = NULL;
1624214082Sdim	  debug_information [unit].max_loc_offsets = 0;
1625214082Sdim	  debug_information [unit].num_loc_offsets = 0;
1626214082Sdim	  debug_information [unit].range_lists = NULL;
1627214082Sdim	  debug_information [unit].max_range_lists= 0;
1628214082Sdim	  debug_information [unit].num_range_lists = 0;
1629214082Sdim	}
1630214082Sdim
1631214082Sdim      tags = hdrptr;
1632214082Sdim
1633214082Sdim      if (!do_loc)
1634214082Sdim	{
1635214082Sdim	  printf (_("  Compilation Unit @ offset 0x%lx:\n"), cu_offset);
1636214082Sdim	  printf (_("   Length:        %ld\n"), compunit.cu_length);
1637214082Sdim	  printf (_("   Version:       %d\n"), compunit.cu_version);
1638214082Sdim	  printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
1639214082Sdim	  printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
1640214082Sdim	}
1641214082Sdim
1642214082Sdim      if (compunit.cu_version != 2 && compunit.cu_version != 3)
1643214082Sdim	{
1644214082Sdim	  warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
1645214082Sdim	  continue;
1646214082Sdim	}
1647214082Sdim
1648214082Sdim      free_abbrevs ();
1649214082Sdim
1650214082Sdim      /* Process the abbrevs used by this compilation unit. DWARF
1651214082Sdim	 sections under Mach-O have non-zero addresses.  */
1652214082Sdim      process_abbrev_section
1653214082Sdim	((unsigned char *) debug_displays [abbrev].section.start
1654214082Sdim	 + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
1655214082Sdim	 (unsigned char *) debug_displays [abbrev].section.start
1656214082Sdim	 + debug_displays [abbrev].section.size);
1657214082Sdim
1658214082Sdim      level = 0;
1659214082Sdim      while (tags < start)
1660214082Sdim	{
1661214082Sdim	  unsigned int bytes_read;
1662214082Sdim	  unsigned long abbrev_number;
1663214082Sdim	  abbrev_entry *entry;
1664214082Sdim	  abbrev_attr *attr;
1665214082Sdim
1666214082Sdim	  abbrev_number = read_leb128 (tags, & bytes_read, 0);
1667214082Sdim	  tags += bytes_read;
1668214082Sdim
1669214082Sdim	  /* A null DIE marks the end of a list of children.  */
1670214082Sdim	  if (abbrev_number == 0)
1671214082Sdim	    {
1672214082Sdim	      --level;
1673214082Sdim	      continue;
1674214082Sdim	    }
1675214082Sdim
1676214082Sdim	  /* Scan through the abbreviation list until we reach the
1677214082Sdim	     correct entry.  */
1678214082Sdim	  for (entry = first_abbrev;
1679214082Sdim	       entry && entry->entry != abbrev_number;
1680214082Sdim	       entry = entry->next)
1681214082Sdim	    continue;
1682214082Sdim
1683214082Sdim	  if (entry == NULL)
1684214082Sdim	    {
1685214082Sdim	      warn (_("Unable to locate entry %lu in the abbreviation table\n"),
1686214082Sdim		    abbrev_number);
1687214082Sdim	      return 0;
1688214082Sdim	    }
1689214082Sdim
1690214082Sdim	  if (!do_loc)
1691214082Sdim	    printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
1692214082Sdim		    level,
1693214082Sdim		    (unsigned long) (tags - section_begin
1694214082Sdim				     - bytes_read),
1695214082Sdim		    abbrev_number,
1696214082Sdim		    get_TAG_name (entry->tag));
1697214082Sdim
1698214082Sdim	  switch (entry->tag)
1699214082Sdim	    {
1700214082Sdim	    default:
1701214082Sdim	      need_base_address = 0;
1702214082Sdim	      break;
1703214082Sdim	    case DW_TAG_compile_unit:
1704214082Sdim	      need_base_address = 1;
1705214082Sdim	      break;
1706214082Sdim	    case DW_TAG_entry_point:
1707214082Sdim	    case DW_TAG_inlined_subroutine:
1708214082Sdim	    case DW_TAG_subprogram:
1709214082Sdim	      need_base_address = 0;
1710214082Sdim	      /* Assuming that there is no DW_AT_frame_base.  */
1711214082Sdim	      have_frame_base = 0;
1712214082Sdim	      break;
1713214082Sdim	    }
1714214082Sdim
1715214082Sdim	  for (attr = entry->first_attr; attr; attr = attr->next)
1716214082Sdim	    tags = read_and_display_attr (attr->attribute,
1717214082Sdim					  attr->form,
1718214082Sdim					  tags, cu_offset,
1719214082Sdim					  compunit.cu_pointer_size,
1720214082Sdim					  offset_size,
1721214082Sdim					  compunit.cu_version,
1722214082Sdim					  &debug_information [unit],
1723214082Sdim					  do_loc);
1724214082Sdim
1725214082Sdim 	  if (entry->children)
1726214082Sdim 	    ++level;
1727214082Sdim 	}
1728214082Sdim    }
1729214082Sdim
1730214082Sdim  /* Set num_debug_info_entries here so that it can be used to check if
1731214082Sdim     we need to process .debug_loc and .debug_ranges sections.  */
1732214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1733214082Sdim      && num_debug_info_entries == 0)
1734214082Sdim    num_debug_info_entries = num_units;
1735214082Sdim
1736214082Sdim  if (!do_loc)
1737214082Sdim    {
1738214082Sdim      printf ("\n");
1739214082Sdim    }
1740214082Sdim
1741214082Sdim  return 1;
1742214082Sdim}
1743214082Sdim
1744214082Sdim/* Locate and scan the .debug_info section in the file and record the pointer
1745214082Sdim   sizes and offsets for the compilation units in it.  Usually an executable
1746214082Sdim   will have just one pointer size, but this is not guaranteed, and so we try
1747214082Sdim   not to make any assumptions.  Returns zero upon failure, or the number of
1748214082Sdim   compilation units upon success.  */
1749214082Sdim
1750214082Sdimstatic unsigned int
1751214082Sdimload_debug_info (void * file)
1752214082Sdim{
1753214082Sdim  /* Reset the last pointer size so that we can issue correct error
1754214082Sdim     messages if we are displaying the contents of more than one section.  */
1755214082Sdim  last_pointer_size = 0;
1756214082Sdim  warned_about_missing_comp_units = FALSE;
1757214082Sdim
1758214082Sdim  /* If we already have the information there is nothing else to do.  */
1759214082Sdim  if (num_debug_info_entries > 0)
1760214082Sdim    return num_debug_info_entries;
1761214082Sdim
1762214082Sdim  if (load_debug_section (info, file)
1763214082Sdim      && process_debug_info (&debug_displays [info].section, file, 1))
1764214082Sdim    return num_debug_info_entries;
1765214082Sdim  else
1766214082Sdim    return 0;
1767214082Sdim}
1768214082Sdim
1769214082Sdimstatic int
1770214082Sdimdisplay_debug_lines (struct dwarf_section *section, void *file)
1771214082Sdim{
1772214082Sdim  unsigned char *start = section->start;
1773214082Sdim  unsigned char *data = start;
1774214082Sdim  unsigned char *end = start + section->size;
1775214082Sdim
1776214082Sdim  printf (_("\nDump of debug contents of section %s:\n\n"),
1777214082Sdim	  section->name);
1778214082Sdim
1779214082Sdim  load_debug_info (file);
1780214082Sdim
1781214082Sdim  while (data < end)
1782214082Sdim    {
1783214082Sdim      DWARF2_Internal_LineInfo info;
1784214082Sdim      unsigned char *standard_opcodes;
1785214082Sdim      unsigned char *end_of_sequence;
1786214082Sdim      unsigned char *hdrptr;
1787214082Sdim      int initial_length_size;
1788214082Sdim      int offset_size;
1789214082Sdim      int i;
1790214082Sdim
1791214082Sdim      hdrptr = data;
1792214082Sdim
1793214082Sdim      /* Check the length of the block.  */
1794214082Sdim      info.li_length = byte_get (hdrptr, 4);
1795214082Sdim      hdrptr += 4;
1796214082Sdim
1797214082Sdim      if (info.li_length == 0xffffffff)
1798214082Sdim	{
1799214082Sdim	  /* This section is 64-bit DWARF 3.  */
1800214082Sdim	  info.li_length = byte_get (hdrptr, 8);
1801214082Sdim	  hdrptr += 8;
1802214082Sdim	  offset_size = 8;
1803214082Sdim	  initial_length_size = 12;
1804214082Sdim	}
1805214082Sdim      else
1806214082Sdim	{
1807214082Sdim	  offset_size = 4;
1808214082Sdim	  initial_length_size = 4;
1809214082Sdim	}
1810214082Sdim
1811214082Sdim      if (info.li_length + initial_length_size > section->size)
1812214082Sdim	{
1813214082Sdim	  warn
1814214082Sdim	    (_("The line info appears to be corrupt - the section is too small\n"));
1815214082Sdim	  return 0;
1816214082Sdim	}
1817214082Sdim
1818214082Sdim      /* Check its version number.  */
1819214082Sdim      info.li_version = byte_get (hdrptr, 2);
1820214082Sdim      hdrptr += 2;
1821214082Sdim      if (info.li_version != 2 && info.li_version != 3)
1822214082Sdim	{
1823214082Sdim	  warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
1824214082Sdim	  return 0;
1825214082Sdim	}
1826214082Sdim
1827214082Sdim      info.li_prologue_length = byte_get (hdrptr, offset_size);
1828214082Sdim      hdrptr += offset_size;
1829214082Sdim      info.li_min_insn_length = byte_get (hdrptr, 1);
1830214082Sdim      hdrptr++;
1831214082Sdim      info.li_default_is_stmt = byte_get (hdrptr, 1);
1832214082Sdim      hdrptr++;
1833214082Sdim      info.li_line_base = byte_get (hdrptr, 1);
1834214082Sdim      hdrptr++;
1835214082Sdim      info.li_line_range = byte_get (hdrptr, 1);
1836214082Sdim      hdrptr++;
1837214082Sdim      info.li_opcode_base = byte_get (hdrptr, 1);
1838214082Sdim      hdrptr++;
1839214082Sdim
1840214082Sdim      /* Sign extend the line base field.  */
1841214082Sdim      info.li_line_base <<= 24;
1842214082Sdim      info.li_line_base >>= 24;
1843214082Sdim
1844214082Sdim      printf (_("  Length:                      %ld\n"), info.li_length);
1845214082Sdim      printf (_("  DWARF Version:               %d\n"), info.li_version);
1846214082Sdim      printf (_("  Prologue Length:             %d\n"), info.li_prologue_length);
1847214082Sdim      printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
1848214082Sdim      printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
1849214082Sdim      printf (_("  Line Base:                   %d\n"), info.li_line_base);
1850214082Sdim      printf (_("  Line Range:                  %d\n"), info.li_line_range);
1851214082Sdim      printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
1852214082Sdim
1853214082Sdim      end_of_sequence = data + info.li_length + initial_length_size;
1854214082Sdim
1855214082Sdim      reset_state_machine (info.li_default_is_stmt);
1856214082Sdim
1857214082Sdim      /* Display the contents of the Opcodes table.  */
1858214082Sdim      standard_opcodes = hdrptr;
1859214082Sdim
1860214082Sdim      printf (_("\n Opcodes:\n"));
1861214082Sdim
1862214082Sdim      for (i = 1; i < info.li_opcode_base; i++)
1863214082Sdim	printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
1864214082Sdim
1865214082Sdim      /* Display the contents of the Directory table.  */
1866214082Sdim      data = standard_opcodes + info.li_opcode_base - 1;
1867214082Sdim
1868214082Sdim      if (*data == 0)
1869214082Sdim	printf (_("\n The Directory Table is empty.\n"));
1870214082Sdim      else
1871214082Sdim	{
1872214082Sdim	  printf (_("\n The Directory Table:\n"));
1873214082Sdim
1874214082Sdim	  while (*data != 0)
1875214082Sdim	    {
1876214082Sdim	      printf (_("  %s\n"), data);
1877214082Sdim
1878214082Sdim	      data += strlen ((char *) data) + 1;
1879214082Sdim	    }
1880214082Sdim	}
1881214082Sdim
1882214082Sdim      /* Skip the NUL at the end of the table.  */
1883214082Sdim      data++;
1884214082Sdim
1885214082Sdim      /* Display the contents of the File Name table.  */
1886214082Sdim      if (*data == 0)
1887214082Sdim	printf (_("\n The File Name Table is empty.\n"));
1888214082Sdim      else
1889214082Sdim	{
1890214082Sdim	  printf (_("\n The File Name Table:\n"));
1891214082Sdim	  printf (_("  Entry\tDir\tTime\tSize\tName\n"));
1892214082Sdim
1893214082Sdim	  while (*data != 0)
1894214082Sdim	    {
1895214082Sdim	      unsigned char *name;
1896214082Sdim	      unsigned int bytes_read;
1897214082Sdim
1898214082Sdim	      printf (_("  %d\t"), ++state_machine_regs.last_file_entry);
1899214082Sdim	      name = data;
1900214082Sdim
1901214082Sdim	      data += strlen ((char *) data) + 1;
1902214082Sdim
1903214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1904214082Sdim	      data += bytes_read;
1905214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1906214082Sdim	      data += bytes_read;
1907214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1908214082Sdim	      data += bytes_read;
1909214082Sdim	      printf (_("%s\n"), name);
1910214082Sdim	    }
1911214082Sdim	}
1912214082Sdim
1913214082Sdim      /* Skip the NUL at the end of the table.  */
1914214082Sdim      data++;
1915214082Sdim
1916214082Sdim      /* Now display the statements.  */
1917214082Sdim      printf (_("\n Line Number Statements:\n"));
1918214082Sdim
1919214082Sdim      while (data < end_of_sequence)
1920214082Sdim	{
1921214082Sdim	  unsigned char op_code;
1922214082Sdim	  int adv;
1923214082Sdim	  unsigned long int uladv;
1924214082Sdim	  unsigned int bytes_read;
1925214082Sdim
1926214082Sdim	  op_code = *data++;
1927214082Sdim
1928214082Sdim	  if (op_code >= info.li_opcode_base)
1929214082Sdim	    {
1930214082Sdim	      op_code -= info.li_opcode_base;
1931214082Sdim	      uladv = (op_code / info.li_line_range) * info.li_min_insn_length;
1932214082Sdim	      state_machine_regs.address += uladv;
1933214082Sdim	      printf (_("  Special opcode %d: advance Address by %lu to 0x%lx"),
1934214082Sdim		      op_code, uladv, state_machine_regs.address);
1935214082Sdim	      adv = (op_code % info.li_line_range) + info.li_line_base;
1936214082Sdim	      state_machine_regs.line += adv;
1937214082Sdim	      printf (_(" and Line by %d to %d\n"),
1938214082Sdim		      adv, state_machine_regs.line);
1939214082Sdim	    }
1940214082Sdim	  else switch (op_code)
1941214082Sdim	    {
1942214082Sdim	    case DW_LNS_extended_op:
1943214082Sdim	      data += process_extended_line_op (data, info.li_default_is_stmt);
1944214082Sdim	      break;
1945214082Sdim
1946214082Sdim	    case DW_LNS_copy:
1947214082Sdim	      printf (_("  Copy\n"));
1948214082Sdim	      break;
1949214082Sdim
1950214082Sdim	    case DW_LNS_advance_pc:
1951214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
1952214082Sdim	      uladv *= info.li_min_insn_length;
1953214082Sdim	      data += bytes_read;
1954214082Sdim	      state_machine_regs.address += uladv;
1955214082Sdim	      printf (_("  Advance PC by %lu to 0x%lx\n"), uladv,
1956214082Sdim		      state_machine_regs.address);
1957214082Sdim	      break;
1958214082Sdim
1959214082Sdim	    case DW_LNS_advance_line:
1960214082Sdim	      adv = read_leb128 (data, & bytes_read, 1);
1961214082Sdim	      data += bytes_read;
1962214082Sdim	      state_machine_regs.line += adv;
1963214082Sdim	      printf (_("  Advance Line by %d to %d\n"), adv,
1964214082Sdim		      state_machine_regs.line);
1965214082Sdim	      break;
1966214082Sdim
1967214082Sdim	    case DW_LNS_set_file:
1968214082Sdim	      adv = read_leb128 (data, & bytes_read, 0);
1969214082Sdim	      data += bytes_read;
1970214082Sdim	      printf (_("  Set File Name to entry %d in the File Name Table\n"),
1971214082Sdim		      adv);
1972214082Sdim	      state_machine_regs.file = adv;
1973214082Sdim	      break;
1974214082Sdim
1975214082Sdim	    case DW_LNS_set_column:
1976214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
1977214082Sdim	      data += bytes_read;
1978214082Sdim	      printf (_("  Set column to %lu\n"), uladv);
1979214082Sdim	      state_machine_regs.column = uladv;
1980214082Sdim	      break;
1981214082Sdim
1982214082Sdim	    case DW_LNS_negate_stmt:
1983214082Sdim	      adv = state_machine_regs.is_stmt;
1984214082Sdim	      adv = ! adv;
1985214082Sdim	      printf (_("  Set is_stmt to %d\n"), adv);
1986214082Sdim	      state_machine_regs.is_stmt = adv;
1987214082Sdim	      break;
1988214082Sdim
1989214082Sdim	    case DW_LNS_set_basic_block:
1990214082Sdim	      printf (_("  Set basic block\n"));
1991214082Sdim	      state_machine_regs.basic_block = 1;
1992214082Sdim	      break;
1993214082Sdim
1994214082Sdim	    case DW_LNS_const_add_pc:
1995214082Sdim	      uladv = (((255 - info.li_opcode_base) / info.li_line_range)
1996214082Sdim		      * info.li_min_insn_length);
1997214082Sdim	      state_machine_regs.address += uladv;
1998214082Sdim	      printf (_("  Advance PC by constant %lu to 0x%lx\n"), uladv,
1999214082Sdim		      state_machine_regs.address);
2000214082Sdim	      break;
2001214082Sdim
2002214082Sdim	    case DW_LNS_fixed_advance_pc:
2003214082Sdim	      uladv = byte_get (data, 2);
2004214082Sdim	      data += 2;
2005214082Sdim	      state_machine_regs.address += uladv;
2006214082Sdim	      printf (_("  Advance PC by fixed size amount %lu to 0x%lx\n"),
2007214082Sdim		      uladv, state_machine_regs.address);
2008214082Sdim	      break;
2009214082Sdim
2010214082Sdim	    case DW_LNS_set_prologue_end:
2011214082Sdim	      printf (_("  Set prologue_end to true\n"));
2012214082Sdim	      break;
2013214082Sdim
2014214082Sdim	    case DW_LNS_set_epilogue_begin:
2015214082Sdim	      printf (_("  Set epilogue_begin to true\n"));
2016214082Sdim	      break;
2017214082Sdim
2018214082Sdim	    case DW_LNS_set_isa:
2019214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
2020214082Sdim	      data += bytes_read;
2021214082Sdim	      printf (_("  Set ISA to %lu\n"), uladv);
2022214082Sdim	      break;
2023214082Sdim
2024214082Sdim	    default:
2025214082Sdim	      printf (_("  Unknown opcode %d with operands: "), op_code);
2026214082Sdim
2027214082Sdim	      for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
2028214082Sdim		{
2029214082Sdim		  printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
2030214082Sdim			  i == 1 ? "" : ", ");
2031214082Sdim		  data += bytes_read;
2032214082Sdim		}
2033214082Sdim	      putchar ('\n');
2034214082Sdim	      break;
2035214082Sdim	    }
2036214082Sdim	}
2037214082Sdim      putchar ('\n');
2038214082Sdim    }
2039214082Sdim
2040214082Sdim  return 1;
2041214082Sdim}
2042214082Sdim
2043214082Sdimstatic int
2044214082Sdimdisplay_debug_pubnames (struct dwarf_section *section,
2045214082Sdim			void *file ATTRIBUTE_UNUSED)
2046214082Sdim{
2047214082Sdim  DWARF2_Internal_PubNames pubnames;
2048214082Sdim  unsigned char *start = section->start;
2049214082Sdim  unsigned char *end = start + section->size;
2050214082Sdim
2051214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2052214082Sdim
2053214082Sdim  while (start < end)
2054214082Sdim    {
2055214082Sdim      unsigned char *data;
2056214082Sdim      unsigned long offset;
2057214082Sdim      int offset_size, initial_length_size;
2058214082Sdim
2059214082Sdim      data = start;
2060214082Sdim
2061214082Sdim      pubnames.pn_length = byte_get (data, 4);
2062214082Sdim      data += 4;
2063214082Sdim      if (pubnames.pn_length == 0xffffffff)
2064214082Sdim	{
2065214082Sdim	  pubnames.pn_length = byte_get (data, 8);
2066214082Sdim	  data += 8;
2067214082Sdim	  offset_size = 8;
2068214082Sdim	  initial_length_size = 12;
2069214082Sdim	}
2070214082Sdim      else
2071214082Sdim	{
2072214082Sdim	  offset_size = 4;
2073214082Sdim	  initial_length_size = 4;
2074214082Sdim	}
2075214082Sdim
2076214082Sdim      pubnames.pn_version = byte_get (data, 2);
2077214082Sdim      data += 2;
2078214082Sdim      pubnames.pn_offset = byte_get (data, offset_size);
2079214082Sdim      data += offset_size;
2080214082Sdim      pubnames.pn_size = byte_get (data, offset_size);
2081214082Sdim      data += offset_size;
2082214082Sdim
2083214082Sdim      start += pubnames.pn_length + initial_length_size;
2084214082Sdim
2085214082Sdim      if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
2086214082Sdim	{
2087214082Sdim	  static int warned = 0;
2088214082Sdim
2089214082Sdim	  if (! warned)
2090214082Sdim	    {
2091214082Sdim	      warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
2092214082Sdim	      warned = 1;
2093214082Sdim	    }
2094214082Sdim
2095214082Sdim	  continue;
2096214082Sdim	}
2097214082Sdim
2098214082Sdim      printf (_("  Length:                              %ld\n"),
2099214082Sdim	      pubnames.pn_length);
2100214082Sdim      printf (_("  Version:                             %d\n"),
2101214082Sdim	      pubnames.pn_version);
2102214082Sdim      printf (_("  Offset into .debug_info section:     %ld\n"),
2103214082Sdim	      pubnames.pn_offset);
2104214082Sdim      printf (_("  Size of area in .debug_info section: %ld\n"),
2105214082Sdim	      pubnames.pn_size);
2106214082Sdim
2107214082Sdim      printf (_("\n    Offset\tName\n"));
2108214082Sdim
2109214082Sdim      do
2110214082Sdim	{
2111214082Sdim	  offset = byte_get (data, offset_size);
2112214082Sdim
2113214082Sdim	  if (offset != 0)
2114214082Sdim	    {
2115214082Sdim	      data += offset_size;
2116214082Sdim	      printf ("    %-6ld\t\t%s\n", offset, data);
2117214082Sdim	      data += strlen ((char *) data) + 1;
2118214082Sdim	    }
2119214082Sdim	}
2120214082Sdim      while (offset != 0);
2121214082Sdim    }
2122214082Sdim
2123214082Sdim  printf ("\n");
2124214082Sdim  return 1;
2125214082Sdim}
2126214082Sdim
2127214082Sdimstatic int
2128214082Sdimdisplay_debug_macinfo (struct dwarf_section *section,
2129214082Sdim		       void *file ATTRIBUTE_UNUSED)
2130214082Sdim{
2131214082Sdim  unsigned char *start = section->start;
2132214082Sdim  unsigned char *end = start + section->size;
2133214082Sdim  unsigned char *curr = start;
2134214082Sdim  unsigned int bytes_read;
2135214082Sdim  enum dwarf_macinfo_record_type op;
2136214082Sdim
2137214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2138214082Sdim
2139214082Sdim  while (curr < end)
2140214082Sdim    {
2141214082Sdim      unsigned int lineno;
2142214082Sdim      const char *string;
2143214082Sdim
2144214082Sdim      op = *curr;
2145214082Sdim      curr++;
2146214082Sdim
2147214082Sdim      switch (op)
2148214082Sdim	{
2149214082Sdim	case DW_MACINFO_start_file:
2150214082Sdim	  {
2151214082Sdim	    unsigned int filenum;
2152214082Sdim
2153214082Sdim	    lineno = read_leb128 (curr, & bytes_read, 0);
2154214082Sdim	    curr += bytes_read;
2155214082Sdim	    filenum = read_leb128 (curr, & bytes_read, 0);
2156214082Sdim	    curr += bytes_read;
2157214082Sdim
2158214082Sdim	    printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
2159214082Sdim		    lineno, filenum);
2160214082Sdim	  }
2161214082Sdim	  break;
2162214082Sdim
2163214082Sdim	case DW_MACINFO_end_file:
2164214082Sdim	  printf (_(" DW_MACINFO_end_file\n"));
2165214082Sdim	  break;
2166214082Sdim
2167214082Sdim	case DW_MACINFO_define:
2168214082Sdim	  lineno = read_leb128 (curr, & bytes_read, 0);
2169214082Sdim	  curr += bytes_read;
2170214082Sdim	  string = (char *) curr;
2171214082Sdim	  curr += strlen (string) + 1;
2172214082Sdim	  printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
2173214082Sdim		  lineno, string);
2174214082Sdim	  break;
2175214082Sdim
2176214082Sdim	case DW_MACINFO_undef:
2177214082Sdim	  lineno = read_leb128 (curr, & bytes_read, 0);
2178214082Sdim	  curr += bytes_read;
2179214082Sdim	  string = (char *) curr;
2180214082Sdim	  curr += strlen (string) + 1;
2181214082Sdim	  printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
2182214082Sdim		  lineno, string);
2183214082Sdim	  break;
2184214082Sdim
2185214082Sdim	case DW_MACINFO_vendor_ext:
2186214082Sdim	  {
2187214082Sdim	    unsigned int constant;
2188214082Sdim
2189214082Sdim	    constant = read_leb128 (curr, & bytes_read, 0);
2190214082Sdim	    curr += bytes_read;
2191214082Sdim	    string = (char *) curr;
2192214082Sdim	    curr += strlen (string) + 1;
2193214082Sdim	    printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
2194214082Sdim		    constant, string);
2195214082Sdim	  }
2196214082Sdim	  break;
2197214082Sdim	}
2198214082Sdim    }
2199214082Sdim
2200214082Sdim  return 1;
2201214082Sdim}
2202214082Sdim
2203214082Sdimstatic int
2204214082Sdimdisplay_debug_abbrev (struct dwarf_section *section,
2205214082Sdim		      void *file ATTRIBUTE_UNUSED)
2206214082Sdim{
2207214082Sdim  abbrev_entry *entry;
2208214082Sdim  unsigned char *start = section->start;
2209214082Sdim  unsigned char *end = start + section->size;
2210214082Sdim
2211214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2212214082Sdim
2213214082Sdim  do
2214214082Sdim    {
2215214082Sdim      free_abbrevs ();
2216214082Sdim
2217214082Sdim      start = process_abbrev_section (start, end);
2218214082Sdim
2219214082Sdim      if (first_abbrev == NULL)
2220214082Sdim	continue;
2221214082Sdim
2222214082Sdim      printf (_("  Number TAG\n"));
2223214082Sdim
2224214082Sdim      for (entry = first_abbrev; entry; entry = entry->next)
2225214082Sdim	{
2226214082Sdim	  abbrev_attr *attr;
2227214082Sdim
2228214082Sdim	  printf (_("   %ld      %s    [%s]\n"),
2229214082Sdim		  entry->entry,
2230214082Sdim		  get_TAG_name (entry->tag),
2231214082Sdim		  entry->children ? _("has children") : _("no children"));
2232214082Sdim
2233214082Sdim	  for (attr = entry->first_attr; attr; attr = attr->next)
2234214082Sdim	    printf (_("    %-18s %s\n"),
2235214082Sdim		    get_AT_name (attr->attribute),
2236214082Sdim		    get_FORM_name (attr->form));
2237214082Sdim	}
2238214082Sdim    }
2239214082Sdim  while (start);
2240214082Sdim
2241214082Sdim  printf ("\n");
2242214082Sdim
2243214082Sdim  return 1;
2244214082Sdim}
2245214082Sdim
2246214082Sdimstatic int
2247214082Sdimdisplay_debug_loc (struct dwarf_section *section, void *file)
2248214082Sdim{
2249214082Sdim  unsigned char *start = section->start;
2250214082Sdim  unsigned char *section_end;
2251214082Sdim  unsigned long bytes;
2252214082Sdim  unsigned char *section_begin = start;
2253214082Sdim  unsigned int num_loc_list = 0;
2254214082Sdim  unsigned long last_offset = 0;
2255214082Sdim  unsigned int first = 0;
2256214082Sdim  unsigned int i;
2257214082Sdim  unsigned int j;
2258214082Sdim  int seen_first_offset = 0;
2259214082Sdim  int use_debug_info = 1;
2260214082Sdim  unsigned char *next;
2261214082Sdim
2262214082Sdim  bytes = section->size;
2263214082Sdim  section_end = start + bytes;
2264214082Sdim
2265214082Sdim  if (bytes == 0)
2266214082Sdim    {
2267214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2268214082Sdim      return 0;
2269214082Sdim    }
2270214082Sdim
2271214082Sdim  load_debug_info (file);
2272214082Sdim
2273214082Sdim  /* Check the order of location list in .debug_info section. If
2274214082Sdim     offsets of location lists are in the ascending order, we can
2275214082Sdim     use `debug_information' directly.  */
2276214082Sdim  for (i = 0; i < num_debug_info_entries; i++)
2277214082Sdim    {
2278214082Sdim      unsigned int num;
2279214082Sdim
2280214082Sdim      num = debug_information [i].num_loc_offsets;
2281214082Sdim      num_loc_list += num;
2282214082Sdim
2283214082Sdim      /* Check if we can use `debug_information' directly.  */
2284214082Sdim      if (use_debug_info && num != 0)
2285214082Sdim	{
2286214082Sdim	  if (!seen_first_offset)
2287214082Sdim	    {
2288214082Sdim	      /* This is the first location list.  */
2289214082Sdim	      last_offset = debug_information [i].loc_offsets [0];
2290214082Sdim	      first = i;
2291214082Sdim	      seen_first_offset = 1;
2292214082Sdim	      j = 1;
2293214082Sdim	    }
2294214082Sdim	  else
2295214082Sdim	    j = 0;
2296214082Sdim
2297214082Sdim	  for (; j < num; j++)
2298214082Sdim	    {
2299214082Sdim	      if (last_offset >
2300214082Sdim		  debug_information [i].loc_offsets [j])
2301214082Sdim		{
2302214082Sdim		  use_debug_info = 0;
2303214082Sdim		  break;
2304214082Sdim		}
2305214082Sdim	      last_offset = debug_information [i].loc_offsets [j];
2306214082Sdim	    }
2307214082Sdim	}
2308214082Sdim    }
2309214082Sdim
2310214082Sdim  if (!use_debug_info)
2311214082Sdim    /* FIXME: Should we handle this case?  */
2312214082Sdim    error (_("Location lists in .debug_info section aren't in ascending order!\n"));
2313214082Sdim
2314214082Sdim  if (!seen_first_offset)
2315214082Sdim    error (_("No location lists in .debug_info section!\n"));
2316214082Sdim
2317214082Sdim  /* DWARF sections under Mach-O have non-zero addresses.  */
2318214082Sdim  if (debug_information [first].loc_offsets [0] != section->address)
2319214082Sdim    warn (_("Location lists in %s section start at 0x%lx\n"),
2320214082Sdim	  section->name, debug_information [first].loc_offsets [0]);
2321214082Sdim
2322214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2323214082Sdim  printf (_("    Offset   Begin    End      Expression\n"));
2324214082Sdim
2325214082Sdim  seen_first_offset = 0;
2326214082Sdim  for (i = first; i < num_debug_info_entries; i++)
2327214082Sdim    {
2328214082Sdim      unsigned long begin;
2329214082Sdim      unsigned long end;
2330214082Sdim      unsigned short length;
2331214082Sdim      unsigned long offset;
2332214082Sdim      unsigned int pointer_size;
2333214082Sdim      unsigned long cu_offset;
2334214082Sdim      unsigned long base_address;
2335214082Sdim      int need_frame_base;
2336214082Sdim      int has_frame_base;
2337214082Sdim
2338214082Sdim      pointer_size = debug_information [i].pointer_size;
2339214082Sdim      cu_offset = debug_information [i].cu_offset;
2340214082Sdim
2341214082Sdim      for (j = 0; j < debug_information [i].num_loc_offsets; j++)
2342214082Sdim	{
2343214082Sdim	  has_frame_base = debug_information [i].have_frame_base [j];
2344214082Sdim	  /* DWARF sections under Mach-O have non-zero addresses.  */
2345214082Sdim	  offset = debug_information [i].loc_offsets [j] - section->address;
2346214082Sdim	  next = section_begin + offset;
2347214082Sdim	  base_address = debug_information [i].base_address;
2348214082Sdim
2349214082Sdim	  if (!seen_first_offset)
2350214082Sdim	    seen_first_offset = 1;
2351214082Sdim	  else
2352214082Sdim	    {
2353214082Sdim	      if (start < next)
2354214082Sdim		warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
2355214082Sdim		      (long)(start - section_begin), (long)(next - section_begin));
2356214082Sdim	      else if (start > next)
2357214082Sdim		warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
2358214082Sdim		      (long)(start - section_begin), (long)(next - section_begin));
2359214082Sdim	    }
2360214082Sdim	  start = next;
2361214082Sdim
2362214082Sdim	  if (offset >= bytes)
2363214082Sdim	    {
2364214082Sdim	      warn (_("Offset 0x%lx is bigger than .debug_loc section size.\n"),
2365214082Sdim		    offset);
2366214082Sdim	      continue;
2367214082Sdim	    }
2368214082Sdim
2369214082Sdim	  while (1)
2370214082Sdim	    {
2371214082Sdim	      if (start + 2 * pointer_size > section_end)
2372214082Sdim		{
2373214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2374214082Sdim			offset);
2375214082Sdim		  break;
2376214082Sdim		}
2377214082Sdim
2378214082Sdim	      begin = byte_get (start, pointer_size);
2379214082Sdim	      start += pointer_size;
2380214082Sdim	      end = byte_get (start, pointer_size);
2381214082Sdim	      start += pointer_size;
2382214082Sdim
2383214082Sdim	      if (begin == 0 && end == 0)
2384214082Sdim		{
2385214082Sdim		  printf (_("    %8.8lx <End of list>\n"), offset);
2386214082Sdim		  break;
2387214082Sdim		}
2388214082Sdim
2389214082Sdim	      /* Check base address specifiers.  */
2390214082Sdim	      if (begin == -1UL && end != -1UL)
2391214082Sdim		{
2392214082Sdim		  base_address = end;
2393214082Sdim		  printf (_("    %8.8lx %8.8lx %8.8lx (base address)\n"),
2394214082Sdim			  offset, begin, end);
2395214082Sdim		  continue;
2396214082Sdim		}
2397214082Sdim
2398214082Sdim	      if (start + 2 > section_end)
2399214082Sdim		{
2400214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2401214082Sdim			offset);
2402214082Sdim		  break;
2403214082Sdim		}
2404214082Sdim
2405214082Sdim	      length = byte_get (start, 2);
2406214082Sdim	      start += 2;
2407214082Sdim
2408214082Sdim	      if (start + length > section_end)
2409214082Sdim		{
2410214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2411214082Sdim			offset);
2412214082Sdim		  break;
2413214082Sdim		}
2414214082Sdim
2415214082Sdim	      printf ("    %8.8lx %8.8lx %8.8lx (",
2416214082Sdim		      offset, begin + base_address, end + base_address);
2417214082Sdim	      need_frame_base = decode_location_expression (start,
2418214082Sdim							    pointer_size,
2419214082Sdim							    length,
2420214082Sdim							    cu_offset);
2421214082Sdim	      putchar (')');
2422214082Sdim
2423214082Sdim	      if (need_frame_base && !has_frame_base)
2424214082Sdim		printf (_(" [without DW_AT_frame_base]"));
2425214082Sdim
2426214082Sdim	      if (begin == end)
2427214082Sdim		fputs (_(" (start == end)"), stdout);
2428214082Sdim	      else if (begin > end)
2429214082Sdim		fputs (_(" (start > end)"), stdout);
2430214082Sdim
2431214082Sdim	      putchar ('\n');
2432214082Sdim
2433214082Sdim	      start += length;
2434214082Sdim	    }
2435214082Sdim	}
2436214082Sdim    }
2437214082Sdim  return 1;
2438214082Sdim}
2439214082Sdim
2440214082Sdimstatic int
2441214082Sdimdisplay_debug_str (struct dwarf_section *section,
2442214082Sdim		   void *file ATTRIBUTE_UNUSED)
2443214082Sdim{
2444214082Sdim  unsigned char *start = section->start;
2445214082Sdim  unsigned long bytes = section->size;
2446214082Sdim  dwarf_vma addr = section->address;
2447214082Sdim
2448214082Sdim  if (bytes == 0)
2449214082Sdim    {
2450214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2451214082Sdim      return 0;
2452214082Sdim    }
2453214082Sdim
2454214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2455214082Sdim
2456214082Sdim  while (bytes)
2457214082Sdim    {
2458214082Sdim      int j;
2459214082Sdim      int k;
2460214082Sdim      int lbytes;
2461214082Sdim
2462214082Sdim      lbytes = (bytes > 16 ? 16 : bytes);
2463214082Sdim
2464214082Sdim      printf ("  0x%8.8lx ", (unsigned long) addr);
2465214082Sdim
2466214082Sdim      for (j = 0; j < 16; j++)
2467214082Sdim	{
2468214082Sdim	  if (j < lbytes)
2469214082Sdim	    printf ("%2.2x", start[j]);
2470214082Sdim	  else
2471214082Sdim	    printf ("  ");
2472214082Sdim
2473214082Sdim	  if ((j & 3) == 3)
2474214082Sdim	    printf (" ");
2475214082Sdim	}
2476214082Sdim
2477214082Sdim      for (j = 0; j < lbytes; j++)
2478214082Sdim	{
2479214082Sdim	  k = start[j];
2480214082Sdim	  if (k >= ' ' && k < 0x80)
2481214082Sdim	    printf ("%c", k);
2482214082Sdim	  else
2483214082Sdim	    printf (".");
2484214082Sdim	}
2485214082Sdim
2486214082Sdim      putchar ('\n');
2487214082Sdim
2488214082Sdim      start += lbytes;
2489214082Sdim      addr  += lbytes;
2490214082Sdim      bytes -= lbytes;
2491214082Sdim    }
2492214082Sdim
2493214082Sdim  putchar ('\n');
2494214082Sdim
2495214082Sdim  return 1;
2496214082Sdim}
2497214082Sdim
2498214082Sdim
2499214082Sdimstatic int
2500214082Sdimdisplay_debug_info (struct dwarf_section *section, void *file)
2501214082Sdim{
2502214082Sdim  return process_debug_info (section, file, 0);
2503214082Sdim}
2504214082Sdim
2505214082Sdim
2506214082Sdimstatic int
2507214082Sdimdisplay_debug_aranges (struct dwarf_section *section,
2508214082Sdim		       void *file ATTRIBUTE_UNUSED)
2509214082Sdim{
2510214082Sdim  unsigned char *start = section->start;
2511214082Sdim  unsigned char *end = start + section->size;
2512214082Sdim
2513214082Sdim  printf (_("The section %s contains:\n\n"), section->name);
2514214082Sdim
2515214082Sdim  while (start < end)
2516214082Sdim    {
2517214082Sdim      unsigned char *hdrptr;
2518214082Sdim      DWARF2_Internal_ARange arange;
2519214082Sdim      unsigned char *ranges;
2520214082Sdim      unsigned long length;
2521214082Sdim      unsigned long address;
2522214082Sdim      int excess;
2523214082Sdim      int offset_size;
2524214082Sdim      int initial_length_size;
2525214082Sdim
2526214082Sdim      hdrptr = start;
2527214082Sdim
2528214082Sdim      arange.ar_length = byte_get (hdrptr, 4);
2529214082Sdim      hdrptr += 4;
2530214082Sdim
2531214082Sdim      if (arange.ar_length == 0xffffffff)
2532214082Sdim	{
2533214082Sdim	  arange.ar_length = byte_get (hdrptr, 8);
2534214082Sdim	  hdrptr += 8;
2535214082Sdim	  offset_size = 8;
2536214082Sdim	  initial_length_size = 12;
2537214082Sdim	}
2538214082Sdim      else
2539214082Sdim	{
2540214082Sdim	  offset_size = 4;
2541214082Sdim	  initial_length_size = 4;
2542214082Sdim	}
2543214082Sdim
2544214082Sdim      arange.ar_version = byte_get (hdrptr, 2);
2545214082Sdim      hdrptr += 2;
2546214082Sdim
2547214082Sdim      arange.ar_info_offset = byte_get (hdrptr, offset_size);
2548214082Sdim      hdrptr += offset_size;
2549214082Sdim
2550214082Sdim      arange.ar_pointer_size = byte_get (hdrptr, 1);
2551214082Sdim      hdrptr += 1;
2552214082Sdim
2553214082Sdim      arange.ar_segment_size = byte_get (hdrptr, 1);
2554214082Sdim      hdrptr += 1;
2555214082Sdim
2556214082Sdim      if (arange.ar_version != 2 && arange.ar_version != 3)
2557214082Sdim	{
2558214082Sdim	  warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
2559214082Sdim	  break;
2560214082Sdim	}
2561214082Sdim
2562214082Sdim      printf (_("  Length:                   %ld\n"), arange.ar_length);
2563214082Sdim      printf (_("  Version:                  %d\n"), arange.ar_version);
2564214082Sdim      printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
2565214082Sdim      printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
2566214082Sdim      printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
2567214082Sdim
2568214082Sdim      printf (_("\n    Address  Length\n"));
2569214082Sdim
2570214082Sdim      ranges = hdrptr;
2571214082Sdim
2572214082Sdim      /* Must pad to an alignment boundary that is twice the pointer size.  */
2573214082Sdim      excess = (hdrptr - start) % (2 * arange.ar_pointer_size);
2574214082Sdim      if (excess)
2575214082Sdim	ranges += (2 * arange.ar_pointer_size) - excess;
2576214082Sdim
2577214082Sdim      start += arange.ar_length + initial_length_size;
2578214082Sdim
2579214082Sdim      while (ranges + 2 * arange.ar_pointer_size <= start)
2580214082Sdim	{
2581214082Sdim	  address = byte_get (ranges, arange.ar_pointer_size);
2582214082Sdim
2583214082Sdim	  ranges += arange.ar_pointer_size;
2584214082Sdim
2585214082Sdim	  length  = byte_get (ranges, arange.ar_pointer_size);
2586214082Sdim
2587214082Sdim	  ranges += arange.ar_pointer_size;
2588214082Sdim
2589214082Sdim	  printf ("    %8.8lx %lu\n", address, length);
2590214082Sdim	}
2591214082Sdim    }
2592214082Sdim
2593214082Sdim  printf ("\n");
2594214082Sdim
2595214082Sdim  return 1;
2596214082Sdim}
2597214082Sdim
2598214082Sdimstatic int
2599214082Sdimdisplay_debug_ranges (struct dwarf_section *section,
2600214082Sdim		      void *file ATTRIBUTE_UNUSED)
2601214082Sdim{
2602214082Sdim  unsigned char *start = section->start;
2603214082Sdim  unsigned char *section_end;
2604214082Sdim  unsigned long bytes;
2605214082Sdim  unsigned char *section_begin = start;
2606214082Sdim  unsigned int num_range_list = 0;
2607214082Sdim  unsigned long last_offset = 0;
2608214082Sdim  unsigned int first = 0;
2609214082Sdim  unsigned int i;
2610214082Sdim  unsigned int j;
2611214082Sdim  int seen_first_offset = 0;
2612214082Sdim  int use_debug_info = 1;
2613214082Sdim  unsigned char *next;
2614214082Sdim
2615214082Sdim  bytes = section->size;
2616214082Sdim  section_end = start + bytes;
2617214082Sdim
2618214082Sdim  if (bytes == 0)
2619214082Sdim    {
2620214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2621214082Sdim      return 0;
2622214082Sdim    }
2623214082Sdim
2624214082Sdim  load_debug_info (file);
2625214082Sdim
2626214082Sdim  /* Check the order of range list in .debug_info section. If
2627214082Sdim     offsets of range lists are in the ascending order, we can
2628214082Sdim     use `debug_information' directly.  */
2629214082Sdim  for (i = 0; i < num_debug_info_entries; i++)
2630214082Sdim    {
2631214082Sdim      unsigned int num;
2632214082Sdim
2633214082Sdim      num = debug_information [i].num_range_lists;
2634214082Sdim      num_range_list += num;
2635214082Sdim
2636214082Sdim      /* Check if we can use `debug_information' directly.  */
2637214082Sdim      if (use_debug_info && num != 0)
2638214082Sdim	{
2639214082Sdim	  if (!seen_first_offset)
2640214082Sdim	    {
2641214082Sdim	      /* This is the first range list.  */
2642214082Sdim	      last_offset = debug_information [i].range_lists [0];
2643214082Sdim	      first = i;
2644214082Sdim	      seen_first_offset = 1;
2645214082Sdim	      j = 1;
2646214082Sdim	    }
2647214082Sdim	  else
2648214082Sdim	    j = 0;
2649214082Sdim
2650214082Sdim	  for (; j < num; j++)
2651214082Sdim	    {
2652214082Sdim	      if (last_offset >
2653214082Sdim		  debug_information [i].range_lists [j])
2654214082Sdim		{
2655214082Sdim		  use_debug_info = 0;
2656214082Sdim		  break;
2657214082Sdim		}
2658214082Sdim	      last_offset = debug_information [i].range_lists [j];
2659214082Sdim	    }
2660214082Sdim	}
2661214082Sdim    }
2662214082Sdim
2663214082Sdim  if (!use_debug_info)
2664214082Sdim    /* FIXME: Should we handle this case?  */
2665214082Sdim    error (_("Range lists in .debug_info section aren't in ascending order!\n"));
2666214082Sdim
2667214082Sdim  if (!seen_first_offset)
2668214082Sdim    error (_("No range lists in .debug_info section!\n"));
2669214082Sdim
2670214082Sdim  /* DWARF sections under Mach-O have non-zero addresses.  */
2671214082Sdim  if (debug_information [first].range_lists [0] != section->address)
2672214082Sdim    warn (_("Range lists in %s section start at 0x%lx\n"),
2673214082Sdim	  section->name, debug_information [first].range_lists [0]);
2674214082Sdim
2675214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2676214082Sdim  printf (_("    Offset   Begin    End\n"));
2677214082Sdim
2678214082Sdim  seen_first_offset = 0;
2679214082Sdim  for (i = first; i < num_debug_info_entries; i++)
2680214082Sdim    {
2681214082Sdim      unsigned long begin;
2682214082Sdim      unsigned long end;
2683214082Sdim      unsigned long offset;
2684214082Sdim      unsigned int pointer_size;
2685214082Sdim      unsigned long base_address;
2686214082Sdim
2687214082Sdim      pointer_size = debug_information [i].pointer_size;
2688214082Sdim
2689214082Sdim      for (j = 0; j < debug_information [i].num_range_lists; j++)
2690214082Sdim	{
2691214082Sdim	  /* DWARF sections under Mach-O have non-zero addresses.  */
2692214082Sdim	  offset = debug_information [i].range_lists [j] - section->address;
2693214082Sdim	  next = section_begin + offset;
2694214082Sdim	  base_address = debug_information [i].base_address;
2695214082Sdim
2696214082Sdim	  if (!seen_first_offset)
2697214082Sdim	    seen_first_offset = 1;
2698214082Sdim	  else
2699214082Sdim	    {
2700214082Sdim	      if (start < next)
2701214082Sdim		warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
2702214082Sdim		      (long)(start - section_begin),
2703214082Sdim		      (long)(next - section_begin), section->name);
2704214082Sdim	      else if (start > next)
2705214082Sdim		warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
2706214082Sdim		      (long)(start - section_begin),
2707214082Sdim		      (long)(next - section_begin), section->name);
2708214082Sdim	    }
2709214082Sdim	  start = next;
2710214082Sdim
2711214082Sdim	  while (1)
2712214082Sdim	    {
2713214082Sdim	      begin = byte_get (start, pointer_size);
2714214082Sdim	      start += pointer_size;
2715214082Sdim	      end = byte_get (start, pointer_size);
2716214082Sdim	      start += pointer_size;
2717214082Sdim
2718214082Sdim	      if (begin == 0 && end == 0)
2719214082Sdim		{
2720214082Sdim		  printf (_("    %8.8lx <End of list>\n"), offset);
2721214082Sdim		  break;
2722214082Sdim		}
2723214082Sdim
2724214082Sdim	      /* Check base address specifiers.  */
2725214082Sdim	      if (begin == -1UL && end != -1UL)
2726214082Sdim		{
2727214082Sdim		  base_address = end;
2728214082Sdim		  printf ("    %8.8lx %8.8lx %8.8lx (base address)\n",
2729214082Sdim			  offset, begin, end);
2730214082Sdim		  continue;
2731214082Sdim		}
2732214082Sdim
2733214082Sdim	      printf ("    %8.8lx %8.8lx %8.8lx",
2734214082Sdim		      offset, begin + base_address, end + base_address);
2735214082Sdim
2736214082Sdim	      if (begin == end)
2737214082Sdim		fputs (_(" (start == end)"), stdout);
2738214082Sdim	      else if (begin > end)
2739214082Sdim		fputs (_(" (start > end)"), stdout);
2740214082Sdim
2741214082Sdim	      putchar ('\n');
2742214082Sdim	    }
2743214082Sdim	}
2744214082Sdim    }
2745214082Sdim  putchar ('\n');
2746214082Sdim  return 1;
2747214082Sdim}
2748214082Sdim
2749214082Sdimtypedef struct Frame_Chunk
2750214082Sdim{
2751214082Sdim  struct Frame_Chunk *next;
2752214082Sdim  unsigned char *chunk_start;
2753214082Sdim  int ncols;
2754214082Sdim  /* DW_CFA_{undefined,same_value,offset,register,unreferenced}  */
2755214082Sdim  short int *col_type;
2756214082Sdim  int *col_offset;
2757214082Sdim  char *augmentation;
2758214082Sdim  unsigned int code_factor;
2759214082Sdim  int data_factor;
2760214082Sdim  unsigned long pc_begin;
2761214082Sdim  unsigned long pc_range;
2762214082Sdim  int cfa_reg;
2763214082Sdim  int cfa_offset;
2764214082Sdim  int ra;
2765214082Sdim  unsigned char fde_encoding;
2766214082Sdim  unsigned char cfa_exp;
2767214082Sdim}
2768214082SdimFrame_Chunk;
2769214082Sdim
2770214082Sdim/* A marker for a col_type that means this column was never referenced
2771214082Sdim   in the frame info.  */
2772214082Sdim#define DW_CFA_unreferenced (-1)
2773214082Sdim
2774214082Sdimstatic void
2775214082Sdimframe_need_space (Frame_Chunk *fc, int reg)
2776214082Sdim{
2777214082Sdim  int prev = fc->ncols;
2778214082Sdim
2779214082Sdim  if (reg < fc->ncols)
2780214082Sdim    return;
2781214082Sdim
2782214082Sdim  fc->ncols = reg + 1;
2783214082Sdim  fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
2784214082Sdim  fc->col_offset = xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
2785214082Sdim
2786214082Sdim  while (prev < fc->ncols)
2787214082Sdim    {
2788214082Sdim      fc->col_type[prev] = DW_CFA_unreferenced;
2789214082Sdim      fc->col_offset[prev] = 0;
2790214082Sdim      prev++;
2791214082Sdim    }
2792214082Sdim}
2793214082Sdim
2794214082Sdimstatic void
2795214082Sdimframe_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs)
2796214082Sdim{
2797214082Sdim  int r;
2798214082Sdim  char tmp[100];
2799214082Sdim
2800214082Sdim  if (*max_regs < fc->ncols)
2801214082Sdim    *max_regs = fc->ncols;
2802214082Sdim
2803214082Sdim  if (*need_col_headers)
2804214082Sdim    {
2805214082Sdim      *need_col_headers = 0;
2806214082Sdim
2807214082Sdim      printf ("   LOC   CFA      ");
2808214082Sdim
2809214082Sdim      for (r = 0; r < *max_regs; r++)
2810214082Sdim	if (fc->col_type[r] != DW_CFA_unreferenced)
2811214082Sdim	  {
2812214082Sdim	    if (r == fc->ra)
2813214082Sdim	      printf ("ra   ");
2814214082Sdim	    else
2815214082Sdim	      printf ("r%-4d", r);
2816214082Sdim	  }
2817214082Sdim
2818214082Sdim      printf ("\n");
2819214082Sdim    }
2820214082Sdim
2821214082Sdim  printf ("%08lx ", fc->pc_begin);
2822214082Sdim  if (fc->cfa_exp)
2823214082Sdim    strcpy (tmp, "exp");
2824214082Sdim  else
2825214082Sdim    sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
2826214082Sdim  printf ("%-8s ", tmp);
2827214082Sdim
2828214082Sdim  for (r = 0; r < fc->ncols; r++)
2829214082Sdim    {
2830214082Sdim      if (fc->col_type[r] != DW_CFA_unreferenced)
2831214082Sdim	{
2832214082Sdim	  switch (fc->col_type[r])
2833214082Sdim	    {
2834214082Sdim	    case DW_CFA_undefined:
2835214082Sdim	      strcpy (tmp, "u");
2836214082Sdim	      break;
2837214082Sdim	    case DW_CFA_same_value:
2838214082Sdim	      strcpy (tmp, "s");
2839214082Sdim	      break;
2840214082Sdim	    case DW_CFA_offset:
2841214082Sdim	      sprintf (tmp, "c%+d", fc->col_offset[r]);
2842214082Sdim	      break;
2843214082Sdim	    case DW_CFA_val_offset:
2844214082Sdim	      sprintf (tmp, "v%+d", fc->col_offset[r]);
2845214082Sdim	      break;
2846214082Sdim	    case DW_CFA_register:
2847214082Sdim	      sprintf (tmp, "r%d", fc->col_offset[r]);
2848214082Sdim	      break;
2849214082Sdim	    case DW_CFA_expression:
2850214082Sdim	      strcpy (tmp, "exp");
2851214082Sdim	      break;
2852214082Sdim	    case DW_CFA_val_expression:
2853214082Sdim	      strcpy (tmp, "vexp");
2854214082Sdim	      break;
2855214082Sdim	    default:
2856214082Sdim	      strcpy (tmp, "n/a");
2857214082Sdim	      break;
2858214082Sdim	    }
2859214082Sdim	  printf ("%-5s", tmp);
2860214082Sdim	}
2861214082Sdim    }
2862214082Sdim  printf ("\n");
2863214082Sdim}
2864214082Sdim
2865214082Sdimstatic int
2866214082Sdimsize_of_encoded_value (int encoding)
2867214082Sdim{
2868214082Sdim  switch (encoding & 0x7)
2869214082Sdim    {
2870214082Sdim    default:	/* ??? */
2871214082Sdim    case 0:	return eh_addr_size;
2872214082Sdim    case 2:	return 2;
2873214082Sdim    case 3:	return 4;
2874214082Sdim    case 4:	return 8;
2875214082Sdim    }
2876214082Sdim}
2877214082Sdim
2878214082Sdimstatic dwarf_vma
2879214082Sdimget_encoded_value (unsigned char *data, int encoding)
2880214082Sdim{
2881214082Sdim  int size = size_of_encoded_value (encoding);
2882214082Sdim  if (encoding & DW_EH_PE_signed)
2883214082Sdim    return byte_get_signed (data, size);
2884214082Sdim  else
2885214082Sdim    return byte_get (data, size);
2886214082Sdim}
2887214082Sdim
2888214082Sdim#define GET(N)	byte_get (start, N); start += N
2889214082Sdim#define LEB()	read_leb128 (start, & length_return, 0); start += length_return
2890214082Sdim#define SLEB()	read_leb128 (start, & length_return, 1); start += length_return
2891214082Sdim
2892214082Sdimstatic int
2893214082Sdimdisplay_debug_frames (struct dwarf_section *section,
2894214082Sdim		      void *file ATTRIBUTE_UNUSED)
2895214082Sdim{
2896214082Sdim  unsigned char *start = section->start;
2897214082Sdim  unsigned char *end = start + section->size;
2898214082Sdim  unsigned char *section_start = start;
2899214082Sdim  Frame_Chunk *chunks = 0;
2900214082Sdim  Frame_Chunk *remembered_state = 0;
2901214082Sdim  Frame_Chunk *rs;
2902214082Sdim  int is_eh = strcmp (section->name, ".eh_frame") == 0;
2903214082Sdim  unsigned int length_return;
2904214082Sdim  int max_regs = 0;
2905214082Sdim
2906214082Sdim  printf (_("The section %s contains:\n"), section->name);
2907214082Sdim
2908214082Sdim  while (start < end)
2909214082Sdim    {
2910214082Sdim      unsigned char *saved_start;
2911214082Sdim      unsigned char *block_end;
2912214082Sdim      unsigned long length;
2913214082Sdim      unsigned long cie_id;
2914214082Sdim      Frame_Chunk *fc;
2915214082Sdim      Frame_Chunk *cie;
2916214082Sdim      int need_col_headers = 1;
2917214082Sdim      unsigned char *augmentation_data = NULL;
2918214082Sdim      unsigned long augmentation_data_len = 0;
2919214082Sdim      int encoded_ptr_size = eh_addr_size;
2920214082Sdim      int offset_size;
2921214082Sdim      int initial_length_size;
2922214082Sdim
2923214082Sdim      saved_start = start;
2924214082Sdim      length = byte_get (start, 4); start += 4;
2925214082Sdim
2926214082Sdim      if (length == 0)
2927214082Sdim	{
2928214082Sdim	  printf ("\n%08lx ZERO terminator\n\n",
2929214082Sdim		    (unsigned long)(saved_start - section_start));
2930214082Sdim	  return 1;
2931214082Sdim	}
2932214082Sdim
2933214082Sdim      if (length == 0xffffffff)
2934214082Sdim	{
2935214082Sdim	  length = byte_get (start, 8);
2936214082Sdim	  start += 8;
2937214082Sdim	  offset_size = 8;
2938214082Sdim	  initial_length_size = 12;
2939214082Sdim	}
2940214082Sdim      else
2941214082Sdim	{
2942214082Sdim	  offset_size = 4;
2943214082Sdim	  initial_length_size = 4;
2944214082Sdim	}
2945214082Sdim
2946214082Sdim      block_end = saved_start + length + initial_length_size;
2947214082Sdim      cie_id = byte_get (start, offset_size); start += offset_size;
2948214082Sdim
2949214082Sdim      if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
2950214082Sdim	{
2951214082Sdim	  int version;
2952214082Sdim
2953214082Sdim	  fc = xmalloc (sizeof (Frame_Chunk));
2954214082Sdim	  memset (fc, 0, sizeof (Frame_Chunk));
2955214082Sdim
2956214082Sdim	  fc->next = chunks;
2957214082Sdim	  chunks = fc;
2958214082Sdim	  fc->chunk_start = saved_start;
2959214082Sdim	  fc->ncols = 0;
2960214082Sdim	  fc->col_type = xmalloc (sizeof (short int));
2961214082Sdim	  fc->col_offset = xmalloc (sizeof (int));
2962214082Sdim	  frame_need_space (fc, max_regs-1);
2963214082Sdim
2964214082Sdim	  version = *start++;
2965214082Sdim
2966214082Sdim	  fc->augmentation = (char *) start;
2967214082Sdim	  start = (unsigned char *) strchr ((char *) start, '\0') + 1;
2968214082Sdim
2969214082Sdim	  if (fc->augmentation[0] == 'z')
2970214082Sdim	    {
2971214082Sdim	      fc->code_factor = LEB ();
2972214082Sdim	      fc->data_factor = SLEB ();
2973214082Sdim	      if (version == 1)
2974214082Sdim		{
2975214082Sdim		  fc->ra = GET (1);
2976214082Sdim		}
2977214082Sdim	      else
2978214082Sdim		{
2979214082Sdim		  fc->ra = LEB ();
2980214082Sdim		}
2981214082Sdim	      augmentation_data_len = LEB ();
2982214082Sdim	      augmentation_data = start;
2983214082Sdim	      start += augmentation_data_len;
2984214082Sdim	    }
2985214082Sdim	  else if (strcmp (fc->augmentation, "eh") == 0)
2986214082Sdim	    {
2987214082Sdim	      start += eh_addr_size;
2988214082Sdim	      fc->code_factor = LEB ();
2989214082Sdim	      fc->data_factor = SLEB ();
2990214082Sdim	      if (version == 1)
2991214082Sdim		{
2992214082Sdim		  fc->ra = GET (1);
2993214082Sdim		}
2994214082Sdim	      else
2995214082Sdim		{
2996214082Sdim		  fc->ra = LEB ();
2997214082Sdim		}
2998214082Sdim	    }
2999214082Sdim	  else
3000214082Sdim	    {
3001214082Sdim	      fc->code_factor = LEB ();
3002214082Sdim	      fc->data_factor = SLEB ();
3003214082Sdim	      if (version == 1)
3004214082Sdim		{
3005214082Sdim		  fc->ra = GET (1);
3006214082Sdim		}
3007214082Sdim	      else
3008214082Sdim		{
3009214082Sdim		  fc->ra = LEB ();
3010214082Sdim		}
3011214082Sdim	    }
3012214082Sdim	  cie = fc;
3013214082Sdim
3014214082Sdim	  if (do_debug_frames_interp)
3015214082Sdim	    printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n",
3016214082Sdim		    (unsigned long)(saved_start - section_start), length, cie_id,
3017214082Sdim		    fc->augmentation, fc->code_factor, fc->data_factor,
3018214082Sdim		    fc->ra);
3019214082Sdim	  else
3020214082Sdim	    {
3021214082Sdim	      printf ("\n%08lx %08lx %08lx CIE\n",
3022214082Sdim		      (unsigned long)(saved_start - section_start), length, cie_id);
3023214082Sdim	      printf ("  Version:               %d\n", version);
3024214082Sdim	      printf ("  Augmentation:          \"%s\"\n", fc->augmentation);
3025214082Sdim	      printf ("  Code alignment factor: %u\n", fc->code_factor);
3026214082Sdim	      printf ("  Data alignment factor: %d\n", fc->data_factor);
3027214082Sdim	      printf ("  Return address column: %d\n", fc->ra);
3028214082Sdim
3029214082Sdim	      if (augmentation_data_len)
3030214082Sdim		{
3031214082Sdim		  unsigned long i;
3032214082Sdim		  printf ("  Augmentation data:    ");
3033214082Sdim		  for (i = 0; i < augmentation_data_len; ++i)
3034214082Sdim		    printf (" %02x", augmentation_data[i]);
3035214082Sdim		  putchar ('\n');
3036214082Sdim		}
3037214082Sdim	      putchar ('\n');
3038214082Sdim	    }
3039214082Sdim
3040214082Sdim	  if (augmentation_data_len)
3041214082Sdim	    {
3042214082Sdim	      unsigned char *p, *q;
3043214082Sdim	      p = (unsigned char *) fc->augmentation + 1;
3044214082Sdim	      q = augmentation_data;
3045214082Sdim
3046214082Sdim	      while (1)
3047214082Sdim		{
3048214082Sdim		  if (*p == 'L')
3049214082Sdim		    q++;
3050214082Sdim		  else if (*p == 'P')
3051214082Sdim		    q += 1 + size_of_encoded_value (*q);
3052214082Sdim		  else if (*p == 'R')
3053214082Sdim		    fc->fde_encoding = *q++;
3054214082Sdim		  else
3055214082Sdim		    break;
3056214082Sdim		  p++;
3057214082Sdim		}
3058214082Sdim
3059214082Sdim	      if (fc->fde_encoding)
3060214082Sdim		encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
3061214082Sdim	    }
3062214082Sdim
3063214082Sdim	  frame_need_space (fc, fc->ra);
3064214082Sdim	}
3065214082Sdim      else
3066214082Sdim	{
3067214082Sdim	  unsigned char *look_for;
3068214082Sdim	  static Frame_Chunk fde_fc;
3069214082Sdim
3070214082Sdim	  fc = & fde_fc;
3071214082Sdim	  memset (fc, 0, sizeof (Frame_Chunk));
3072214082Sdim
3073214082Sdim	  look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
3074214082Sdim
3075214082Sdim	  for (cie = chunks; cie ; cie = cie->next)
3076214082Sdim	    if (cie->chunk_start == look_for)
3077214082Sdim	      break;
3078214082Sdim
3079214082Sdim	  if (!cie)
3080214082Sdim	    {
3081214082Sdim	      warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
3082214082Sdim		    cie_id, (unsigned long)(saved_start - section_start));
3083214082Sdim	      start = block_end;
3084214082Sdim	      fc->ncols = 0;
3085214082Sdim	      fc->col_type = xmalloc (sizeof (short int));
3086214082Sdim	      fc->col_offset = xmalloc (sizeof (int));
3087214082Sdim	      frame_need_space (fc, max_regs - 1);
3088214082Sdim	      cie = fc;
3089214082Sdim	      fc->augmentation = "";
3090214082Sdim	      fc->fde_encoding = 0;
3091214082Sdim	    }
3092214082Sdim	  else
3093214082Sdim	    {
3094214082Sdim	      fc->ncols = cie->ncols;
3095214082Sdim	      fc->col_type = xcmalloc (fc->ncols, sizeof (short int));
3096214082Sdim	      fc->col_offset = xcmalloc (fc->ncols, sizeof (int));
3097214082Sdim	      memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
3098214082Sdim	      memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
3099214082Sdim	      fc->augmentation = cie->augmentation;
3100214082Sdim	      fc->code_factor = cie->code_factor;
3101214082Sdim	      fc->data_factor = cie->data_factor;
3102214082Sdim	      fc->cfa_reg = cie->cfa_reg;
3103214082Sdim	      fc->cfa_offset = cie->cfa_offset;
3104214082Sdim	      fc->ra = cie->ra;
3105214082Sdim	      frame_need_space (fc, max_regs-1);
3106214082Sdim	      fc->fde_encoding = cie->fde_encoding;
3107214082Sdim	    }
3108214082Sdim
3109214082Sdim	  if (fc->fde_encoding)
3110214082Sdim	    encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
3111214082Sdim
3112214082Sdim	  fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
3113214082Sdim	  if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
3114214082Sdim	      /* Don't adjust for relocatable file since there's
3115214082Sdim		 invariably a pcrel reloc here, which we haven't
3116214082Sdim		 applied.  */
3117214082Sdim	      && !is_relocatable)
3118214082Sdim	    fc->pc_begin += section->address + (start - section_start);
3119214082Sdim	  start += encoded_ptr_size;
3120214082Sdim	  fc->pc_range = byte_get (start, encoded_ptr_size);
3121214082Sdim	  start += encoded_ptr_size;
3122214082Sdim
3123214082Sdim	  if (cie->augmentation[0] == 'z')
3124214082Sdim	    {
3125214082Sdim	      augmentation_data_len = LEB ();
3126214082Sdim	      augmentation_data = start;
3127214082Sdim	      start += augmentation_data_len;
3128214082Sdim	    }
3129214082Sdim
3130214082Sdim	  printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
3131214082Sdim		  (unsigned long)(saved_start - section_start), length, cie_id,
3132214082Sdim		  (unsigned long)(cie->chunk_start - section_start),
3133214082Sdim		  fc->pc_begin, fc->pc_begin + fc->pc_range);
3134214082Sdim	  if (! do_debug_frames_interp && augmentation_data_len)
3135214082Sdim	    {
3136214082Sdim	      unsigned long i;
3137214082Sdim
3138214082Sdim	      printf ("  Augmentation data:    ");
3139214082Sdim	      for (i = 0; i < augmentation_data_len; ++i)
3140214082Sdim		printf (" %02x", augmentation_data[i]);
3141214082Sdim	      putchar ('\n');
3142214082Sdim	      putchar ('\n');
3143214082Sdim	    }
3144214082Sdim	}
3145214082Sdim
3146214082Sdim      /* At this point, fc is the current chunk, cie (if any) is set, and
3147214082Sdim	 we're about to interpret instructions for the chunk.  */
3148214082Sdim      /* ??? At present we need to do this always, since this sizes the
3149214082Sdim	 fc->col_type and fc->col_offset arrays, which we write into always.
3150214082Sdim	 We should probably split the interpreted and non-interpreted bits
3151214082Sdim	 into two different routines, since there's so much that doesn't
3152214082Sdim	 really overlap between them.  */
3153214082Sdim      if (1 || do_debug_frames_interp)
3154214082Sdim	{
3155214082Sdim	  /* Start by making a pass over the chunk, allocating storage
3156214082Sdim	     and taking note of what registers are used.  */
3157214082Sdim	  unsigned char *tmp = start;
3158214082Sdim
3159214082Sdim	  while (start < block_end)
3160214082Sdim	    {
3161214082Sdim	      unsigned op, opa;
3162214082Sdim	      unsigned long reg, tmp;
3163214082Sdim
3164214082Sdim	      op = *start++;
3165214082Sdim	      opa = op & 0x3f;
3166214082Sdim	      if (op & 0xc0)
3167214082Sdim		op &= 0xc0;
3168214082Sdim
3169214082Sdim	      /* Warning: if you add any more cases to this switch, be
3170214082Sdim		 sure to add them to the corresponding switch below.  */
3171214082Sdim	      switch (op)
3172214082Sdim		{
3173214082Sdim		case DW_CFA_advance_loc:
3174214082Sdim		  break;
3175214082Sdim		case DW_CFA_offset:
3176214082Sdim		  LEB ();
3177214082Sdim		  frame_need_space (fc, opa);
3178214082Sdim		  fc->col_type[opa] = DW_CFA_undefined;
3179214082Sdim		  break;
3180214082Sdim		case DW_CFA_restore:
3181214082Sdim		  frame_need_space (fc, opa);
3182214082Sdim		  fc->col_type[opa] = DW_CFA_undefined;
3183214082Sdim		  break;
3184214082Sdim		case DW_CFA_set_loc:
3185214082Sdim		  start += encoded_ptr_size;
3186214082Sdim		  break;
3187214082Sdim		case DW_CFA_advance_loc1:
3188214082Sdim		  start += 1;
3189214082Sdim		  break;
3190214082Sdim		case DW_CFA_advance_loc2:
3191214082Sdim		  start += 2;
3192214082Sdim		  break;
3193214082Sdim		case DW_CFA_advance_loc4:
3194214082Sdim		  start += 4;
3195214082Sdim		  break;
3196214082Sdim		case DW_CFA_offset_extended:
3197214082Sdim		case DW_CFA_val_offset:
3198214082Sdim		  reg = LEB (); LEB ();
3199214082Sdim		  frame_need_space (fc, reg);
3200214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3201214082Sdim		  break;
3202214082Sdim		case DW_CFA_restore_extended:
3203214082Sdim		  reg = LEB ();
3204214082Sdim		  frame_need_space (fc, reg);
3205214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3206214082Sdim		  break;
3207214082Sdim		case DW_CFA_undefined:
3208214082Sdim		  reg = LEB ();
3209214082Sdim		  frame_need_space (fc, reg);
3210214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3211214082Sdim		  break;
3212214082Sdim		case DW_CFA_same_value:
3213214082Sdim		  reg = LEB ();
3214214082Sdim		  frame_need_space (fc, reg);
3215214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3216214082Sdim		  break;
3217214082Sdim		case DW_CFA_register:
3218214082Sdim		  reg = LEB (); LEB ();
3219214082Sdim		  frame_need_space (fc, reg);
3220214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3221214082Sdim		  break;
3222214082Sdim		case DW_CFA_def_cfa:
3223214082Sdim		  LEB (); LEB ();
3224214082Sdim		  break;
3225214082Sdim		case DW_CFA_def_cfa_register:
3226214082Sdim		  LEB ();
3227214082Sdim		  break;
3228214082Sdim		case DW_CFA_def_cfa_offset:
3229214082Sdim		  LEB ();
3230214082Sdim		  break;
3231214082Sdim		case DW_CFA_def_cfa_expression:
3232214082Sdim		  tmp = LEB ();
3233214082Sdim		  start += tmp;
3234214082Sdim		  break;
3235214082Sdim		case DW_CFA_expression:
3236214082Sdim		case DW_CFA_val_expression:
3237214082Sdim		  reg = LEB ();
3238214082Sdim		  tmp = LEB ();
3239214082Sdim		  start += tmp;
3240214082Sdim		  frame_need_space (fc, reg);
3241214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3242214082Sdim		  break;
3243214082Sdim		case DW_CFA_offset_extended_sf:
3244214082Sdim		case DW_CFA_val_offset_sf:
3245214082Sdim		  reg = LEB (); SLEB ();
3246214082Sdim		  frame_need_space (fc, reg);
3247214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3248214082Sdim		  break;
3249214082Sdim		case DW_CFA_def_cfa_sf:
3250214082Sdim		  LEB (); SLEB ();
3251214082Sdim		  break;
3252214082Sdim		case DW_CFA_def_cfa_offset_sf:
3253214082Sdim		  SLEB ();
3254214082Sdim		  break;
3255214082Sdim		case DW_CFA_MIPS_advance_loc8:
3256214082Sdim		  start += 8;
3257214082Sdim		  break;
3258214082Sdim		case DW_CFA_GNU_args_size:
3259214082Sdim		  LEB ();
3260214082Sdim		  break;
3261214082Sdim		case DW_CFA_GNU_negative_offset_extended:
3262214082Sdim		  reg = LEB (); LEB ();
3263214082Sdim		  frame_need_space (fc, reg);
3264214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3265214082Sdim
3266214082Sdim		default:
3267214082Sdim		  break;
3268214082Sdim		}
3269214082Sdim	    }
3270214082Sdim	  start = tmp;
3271214082Sdim	}
3272214082Sdim
3273214082Sdim      /* Now we know what registers are used, make a second pass over
3274214082Sdim	 the chunk, this time actually printing out the info.  */
3275214082Sdim
3276214082Sdim      while (start < block_end)
3277214082Sdim	{
3278214082Sdim	  unsigned op, opa;
3279214082Sdim	  unsigned long ul, reg, roffs;
3280214082Sdim	  long l, ofs;
3281214082Sdim	  dwarf_vma vma;
3282214082Sdim
3283214082Sdim	  op = *start++;
3284214082Sdim	  opa = op & 0x3f;
3285214082Sdim	  if (op & 0xc0)
3286214082Sdim	    op &= 0xc0;
3287214082Sdim
3288214082Sdim	  /* Warning: if you add any more cases to this switch, be
3289214082Sdim	     sure to add them to the corresponding switch above.  */
3290214082Sdim	  switch (op)
3291214082Sdim	    {
3292214082Sdim	    case DW_CFA_advance_loc:
3293214082Sdim	      if (do_debug_frames_interp)
3294214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3295214082Sdim	      else
3296214082Sdim		printf ("  DW_CFA_advance_loc: %d to %08lx\n",
3297214082Sdim			opa * fc->code_factor,
3298214082Sdim			fc->pc_begin + opa * fc->code_factor);
3299214082Sdim	      fc->pc_begin += opa * fc->code_factor;
3300214082Sdim	      break;
3301214082Sdim
3302214082Sdim	    case DW_CFA_offset:
3303214082Sdim	      roffs = LEB ();
3304214082Sdim	      if (! do_debug_frames_interp)
3305214082Sdim		printf ("  DW_CFA_offset: r%d at cfa%+ld\n",
3306214082Sdim			opa, roffs * fc->data_factor);
3307214082Sdim	      fc->col_type[opa] = DW_CFA_offset;
3308214082Sdim	      fc->col_offset[opa] = roffs * fc->data_factor;
3309214082Sdim	      break;
3310214082Sdim
3311214082Sdim	    case DW_CFA_restore:
3312214082Sdim	      if (! do_debug_frames_interp)
3313214082Sdim		printf ("  DW_CFA_restore: r%d\n", opa);
3314214082Sdim	      fc->col_type[opa] = cie->col_type[opa];
3315214082Sdim	      fc->col_offset[opa] = cie->col_offset[opa];
3316214082Sdim	      break;
3317214082Sdim
3318214082Sdim	    case DW_CFA_set_loc:
3319214082Sdim	      vma = get_encoded_value (start, fc->fde_encoding);
3320214082Sdim	      if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
3321214082Sdim		  && !is_relocatable)
3322214082Sdim		vma += section->address + (start - section_start);
3323214082Sdim	      start += encoded_ptr_size;
3324214082Sdim	      if (do_debug_frames_interp)
3325214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3326214082Sdim	      else
3327214082Sdim		printf ("  DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
3328214082Sdim	      fc->pc_begin = vma;
3329214082Sdim	      break;
3330214082Sdim
3331214082Sdim	    case DW_CFA_advance_loc1:
3332214082Sdim	      ofs = byte_get (start, 1); start += 1;
3333214082Sdim	      if (do_debug_frames_interp)
3334214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3335214082Sdim	      else
3336214082Sdim		printf ("  DW_CFA_advance_loc1: %ld to %08lx\n",
3337214082Sdim			ofs * fc->code_factor,
3338214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3339214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3340214082Sdim	      break;
3341214082Sdim
3342214082Sdim	    case DW_CFA_advance_loc2:
3343214082Sdim	      ofs = byte_get (start, 2); start += 2;
3344214082Sdim	      if (do_debug_frames_interp)
3345214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3346214082Sdim	      else
3347214082Sdim		printf ("  DW_CFA_advance_loc2: %ld to %08lx\n",
3348214082Sdim			ofs * fc->code_factor,
3349214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3350214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3351214082Sdim	      break;
3352214082Sdim
3353214082Sdim	    case DW_CFA_advance_loc4:
3354214082Sdim	      ofs = byte_get (start, 4); start += 4;
3355214082Sdim	      if (do_debug_frames_interp)
3356214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3357214082Sdim	      else
3358214082Sdim		printf ("  DW_CFA_advance_loc4: %ld to %08lx\n",
3359214082Sdim			ofs * fc->code_factor,
3360214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3361214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3362214082Sdim	      break;
3363214082Sdim
3364214082Sdim	    case DW_CFA_offset_extended:
3365214082Sdim	      reg = LEB ();
3366214082Sdim	      roffs = LEB ();
3367214082Sdim	      if (! do_debug_frames_interp)
3368214082Sdim		printf ("  DW_CFA_offset_extended: r%ld at cfa%+ld\n",
3369214082Sdim			reg, roffs * fc->data_factor);
3370214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3371214082Sdim	      fc->col_offset[reg] = roffs * fc->data_factor;
3372214082Sdim	      break;
3373214082Sdim
3374214082Sdim	    case DW_CFA_val_offset:
3375214082Sdim	      reg = LEB ();
3376214082Sdim	      roffs = LEB ();
3377214082Sdim	      if (! do_debug_frames_interp)
3378214082Sdim		printf ("  DW_CFA_val_offset: r%ld at cfa%+ld\n",
3379214082Sdim			reg, roffs * fc->data_factor);
3380214082Sdim	      fc->col_type[reg] = DW_CFA_val_offset;
3381214082Sdim	      fc->col_offset[reg] = roffs * fc->data_factor;
3382214082Sdim	      break;
3383214082Sdim
3384214082Sdim	    case DW_CFA_restore_extended:
3385214082Sdim	      reg = LEB ();
3386214082Sdim	      if (! do_debug_frames_interp)
3387214082Sdim		printf ("  DW_CFA_restore_extended: r%ld\n", reg);
3388214082Sdim	      fc->col_type[reg] = cie->col_type[reg];
3389214082Sdim	      fc->col_offset[reg] = cie->col_offset[reg];
3390214082Sdim	      break;
3391214082Sdim
3392214082Sdim	    case DW_CFA_undefined:
3393214082Sdim	      reg = LEB ();
3394214082Sdim	      if (! do_debug_frames_interp)
3395214082Sdim		printf ("  DW_CFA_undefined: r%ld\n", reg);
3396214082Sdim	      fc->col_type[reg] = DW_CFA_undefined;
3397214082Sdim	      fc->col_offset[reg] = 0;
3398214082Sdim	      break;
3399214082Sdim
3400214082Sdim	    case DW_CFA_same_value:
3401214082Sdim	      reg = LEB ();
3402214082Sdim	      if (! do_debug_frames_interp)
3403214082Sdim		printf ("  DW_CFA_same_value: r%ld\n", reg);
3404214082Sdim	      fc->col_type[reg] = DW_CFA_same_value;
3405214082Sdim	      fc->col_offset[reg] = 0;
3406214082Sdim	      break;
3407214082Sdim
3408214082Sdim	    case DW_CFA_register:
3409214082Sdim	      reg = LEB ();
3410214082Sdim	      roffs = LEB ();
3411214082Sdim	      if (! do_debug_frames_interp)
3412214082Sdim		printf ("  DW_CFA_register: r%ld in r%ld\n", reg, roffs);
3413214082Sdim	      fc->col_type[reg] = DW_CFA_register;
3414214082Sdim	      fc->col_offset[reg] = roffs;
3415214082Sdim	      break;
3416214082Sdim
3417214082Sdim	    case DW_CFA_remember_state:
3418214082Sdim	      if (! do_debug_frames_interp)
3419214082Sdim		printf ("  DW_CFA_remember_state\n");
3420214082Sdim	      rs = xmalloc (sizeof (Frame_Chunk));
3421214082Sdim	      rs->ncols = fc->ncols;
3422214082Sdim	      rs->col_type = xcmalloc (rs->ncols, sizeof (short int));
3423214082Sdim	      rs->col_offset = xcmalloc (rs->ncols, sizeof (int));
3424214082Sdim	      memcpy (rs->col_type, fc->col_type, rs->ncols);
3425214082Sdim	      memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
3426214082Sdim	      rs->next = remembered_state;
3427214082Sdim	      remembered_state = rs;
3428214082Sdim	      break;
3429214082Sdim
3430214082Sdim	    case DW_CFA_restore_state:
3431214082Sdim	      if (! do_debug_frames_interp)
3432214082Sdim		printf ("  DW_CFA_restore_state\n");
3433214082Sdim	      rs = remembered_state;
3434214082Sdim	      if (rs)
3435214082Sdim		{
3436214082Sdim		  remembered_state = rs->next;
3437214082Sdim		  frame_need_space (fc, rs->ncols-1);
3438214082Sdim		  memcpy (fc->col_type, rs->col_type, rs->ncols);
3439214082Sdim		  memcpy (fc->col_offset, rs->col_offset,
3440214082Sdim			  rs->ncols * sizeof (int));
3441214082Sdim		  free (rs->col_type);
3442214082Sdim		  free (rs->col_offset);
3443214082Sdim		  free (rs);
3444214082Sdim		}
3445214082Sdim	      else if (do_debug_frames_interp)
3446214082Sdim		printf ("Mismatched DW_CFA_restore_state\n");
3447214082Sdim	      break;
3448214082Sdim
3449214082Sdim	    case DW_CFA_def_cfa:
3450214082Sdim	      fc->cfa_reg = LEB ();
3451214082Sdim	      fc->cfa_offset = LEB ();
3452214082Sdim	      fc->cfa_exp = 0;
3453214082Sdim	      if (! do_debug_frames_interp)
3454214082Sdim		printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
3455214082Sdim			fc->cfa_reg, fc->cfa_offset);
3456214082Sdim	      break;
3457214082Sdim
3458214082Sdim	    case DW_CFA_def_cfa_register:
3459214082Sdim	      fc->cfa_reg = LEB ();
3460214082Sdim	      fc->cfa_exp = 0;
3461214082Sdim	      if (! do_debug_frames_interp)
3462214082Sdim		printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
3463214082Sdim	      break;
3464214082Sdim
3465214082Sdim	    case DW_CFA_def_cfa_offset:
3466214082Sdim	      fc->cfa_offset = LEB ();
3467214082Sdim	      if (! do_debug_frames_interp)
3468214082Sdim		printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
3469214082Sdim	      break;
3470214082Sdim
3471214082Sdim	    case DW_CFA_nop:
3472214082Sdim	      if (! do_debug_frames_interp)
3473214082Sdim		printf ("  DW_CFA_nop\n");
3474214082Sdim	      break;
3475214082Sdim
3476214082Sdim	    case DW_CFA_def_cfa_expression:
3477214082Sdim	      ul = LEB ();
3478214082Sdim	      if (! do_debug_frames_interp)
3479214082Sdim		{
3480214082Sdim		  printf ("  DW_CFA_def_cfa_expression (");
3481214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3482214082Sdim		  printf (")\n");
3483214082Sdim		}
3484214082Sdim	      fc->cfa_exp = 1;
3485214082Sdim	      start += ul;
3486214082Sdim	      break;
3487214082Sdim
3488214082Sdim	    case DW_CFA_expression:
3489214082Sdim	      reg = LEB ();
3490214082Sdim	      ul = LEB ();
3491214082Sdim	      if (! do_debug_frames_interp)
3492214082Sdim		{
3493214082Sdim		  printf ("  DW_CFA_expression: r%ld (", reg);
3494214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3495214082Sdim		  printf (")\n");
3496214082Sdim		}
3497214082Sdim	      fc->col_type[reg] = DW_CFA_expression;
3498214082Sdim	      start += ul;
3499214082Sdim	      break;
3500214082Sdim
3501214082Sdim	    case DW_CFA_val_expression:
3502214082Sdim	      reg = LEB ();
3503214082Sdim	      ul = LEB ();
3504214082Sdim	      if (! do_debug_frames_interp)
3505214082Sdim		{
3506214082Sdim		  printf ("  DW_CFA_val_expression: r%ld (", reg);
3507214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3508214082Sdim		  printf (")\n");
3509214082Sdim		}
3510214082Sdim	      fc->col_type[reg] = DW_CFA_val_expression;
3511214082Sdim	      start += ul;
3512214082Sdim	      break;
3513214082Sdim
3514214082Sdim	    case DW_CFA_offset_extended_sf:
3515214082Sdim	      reg = LEB ();
3516214082Sdim	      l = SLEB ();
3517214082Sdim	      frame_need_space (fc, reg);
3518214082Sdim	      if (! do_debug_frames_interp)
3519214082Sdim		printf ("  DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n",
3520214082Sdim			reg, l * fc->data_factor);
3521214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3522214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3523214082Sdim	      break;
3524214082Sdim
3525214082Sdim	    case DW_CFA_val_offset_sf:
3526214082Sdim	      reg = LEB ();
3527214082Sdim	      l = SLEB ();
3528214082Sdim	      frame_need_space (fc, reg);
3529214082Sdim	      if (! do_debug_frames_interp)
3530214082Sdim		printf ("  DW_CFA_val_offset_sf: r%ld at cfa%+ld\n",
3531214082Sdim			reg, l * fc->data_factor);
3532214082Sdim	      fc->col_type[reg] = DW_CFA_val_offset;
3533214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3534214082Sdim	      break;
3535214082Sdim
3536214082Sdim	    case DW_CFA_def_cfa_sf:
3537214082Sdim	      fc->cfa_reg = LEB ();
3538214082Sdim	      fc->cfa_offset = SLEB ();
3539214082Sdim	      fc->cfa_offset = fc->cfa_offset * fc->data_factor;
3540214082Sdim	      fc->cfa_exp = 0;
3541214082Sdim	      if (! do_debug_frames_interp)
3542214082Sdim		printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
3543214082Sdim			fc->cfa_reg, fc->cfa_offset);
3544214082Sdim	      break;
3545214082Sdim
3546214082Sdim	    case DW_CFA_def_cfa_offset_sf:
3547214082Sdim	      fc->cfa_offset = SLEB ();
3548214082Sdim	      fc->cfa_offset = fc->cfa_offset * fc->data_factor;
3549214082Sdim	      if (! do_debug_frames_interp)
3550214082Sdim		printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
3551214082Sdim	      break;
3552214082Sdim
3553214082Sdim	    case DW_CFA_MIPS_advance_loc8:
3554214082Sdim	      ofs = byte_get (start, 8); start += 8;
3555214082Sdim	      if (do_debug_frames_interp)
3556214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3557214082Sdim	      else
3558214082Sdim		printf ("  DW_CFA_MIPS_advance_loc8: %ld to %08lx\n",
3559214082Sdim			ofs * fc->code_factor,
3560214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3561214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3562214082Sdim	      break;
3563214082Sdim
3564214082Sdim	    case DW_CFA_GNU_window_save:
3565214082Sdim	      if (! do_debug_frames_interp)
3566214082Sdim		printf ("  DW_CFA_GNU_window_save\n");
3567214082Sdim	      break;
3568214082Sdim
3569214082Sdim	    case DW_CFA_GNU_args_size:
3570214082Sdim	      ul = LEB ();
3571214082Sdim	      if (! do_debug_frames_interp)
3572214082Sdim		printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
3573214082Sdim	      break;
3574214082Sdim
3575214082Sdim	    case DW_CFA_GNU_negative_offset_extended:
3576214082Sdim	      reg = LEB ();
3577214082Sdim	      l = - LEB ();
3578214082Sdim	      frame_need_space (fc, reg);
3579214082Sdim	      if (! do_debug_frames_interp)
3580214082Sdim		printf ("  DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
3581214082Sdim			reg, l * fc->data_factor);
3582214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3583214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3584214082Sdim	      break;
3585214082Sdim
3586214082Sdim	    default:
3587214082Sdim	      warn (_("unsupported or unknown DW_CFA_%d\n"), op);
3588214082Sdim	      start = block_end;
3589214082Sdim	    }
3590214082Sdim	}
3591214082Sdim
3592214082Sdim      if (do_debug_frames_interp)
3593214082Sdim	frame_display_row (fc, &need_col_headers, &max_regs);
3594214082Sdim
3595214082Sdim      start = block_end;
3596214082Sdim    }
3597214082Sdim
3598214082Sdim  printf ("\n");
3599214082Sdim
3600214082Sdim  return 1;
3601214082Sdim}
3602214082Sdim
3603214082Sdim#undef GET
3604214082Sdim#undef LEB
3605214082Sdim#undef SLEB
3606214082Sdim
3607214082Sdimstatic int
3608214082Sdimdisplay_debug_not_supported (struct dwarf_section *section,
3609214082Sdim			     void *file ATTRIBUTE_UNUSED)
3610214082Sdim{
3611214082Sdim  printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
3612214082Sdim	    section->name);
3613214082Sdim
3614214082Sdim  return 1;
3615214082Sdim}
3616214082Sdim
3617214082Sdimvoid *
3618214082Sdimcmalloc (size_t nmemb, size_t size)
3619214082Sdim{
3620214082Sdim  /* Check for overflow.  */
3621214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3622214082Sdim    return NULL;
3623214082Sdim  else
3624214082Sdim    return malloc (nmemb * size);
3625214082Sdim}
3626214082Sdim
3627214082Sdimvoid *
3628214082Sdimxcmalloc (size_t nmemb, size_t size)
3629214082Sdim{
3630214082Sdim  /* Check for overflow.  */
3631214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3632214082Sdim    return NULL;
3633214082Sdim  else
3634214082Sdim    return xmalloc (nmemb * size);
3635214082Sdim}
3636214082Sdim
3637214082Sdimvoid *
3638214082Sdimxcrealloc (void *ptr, size_t nmemb, size_t size)
3639214082Sdim{
3640214082Sdim  /* Check for overflow.  */
3641214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3642214082Sdim    return NULL;
3643214082Sdim  else
3644214082Sdim    return xrealloc (ptr, nmemb * size);
3645214082Sdim}
3646214082Sdim
3647214082Sdimvoid
3648214082Sdimerror (const char *message, ...)
3649214082Sdim{
3650214082Sdim  va_list args;
3651214082Sdim
3652214082Sdim  va_start (args, message);
3653214082Sdim  fprintf (stderr, _("%s: Error: "), program_name);
3654214082Sdim  vfprintf (stderr, message, args);
3655214082Sdim  va_end (args);
3656214082Sdim}
3657214082Sdim
3658214082Sdimvoid
3659214082Sdimwarn (const char *message, ...)
3660214082Sdim{
3661214082Sdim  va_list args;
3662214082Sdim
3663214082Sdim  va_start (args, message);
3664214082Sdim  fprintf (stderr, _("%s: Warning: "), program_name);
3665214082Sdim  vfprintf (stderr, message, args);
3666214082Sdim  va_end (args);
3667214082Sdim}
3668214082Sdim
3669214082Sdimvoid
3670214082Sdimfree_debug_memory (void)
3671214082Sdim{
3672214082Sdim  enum dwarf_section_display_enum i;
3673214082Sdim
3674214082Sdim  free_abbrevs ();
3675214082Sdim
3676214082Sdim  for (i = 0; i < max; i++)
3677214082Sdim    free_debug_section (i);
3678214082Sdim
3679214082Sdim  if (debug_information)
3680214082Sdim    {
3681214082Sdim      for (i = 0; i < num_debug_info_entries; i++)
3682214082Sdim	{
3683214082Sdim	  if (!debug_information [i].max_loc_offsets)
3684214082Sdim	    {
3685214082Sdim	      free (debug_information [i].loc_offsets);
3686214082Sdim	      free (debug_information [i].have_frame_base);
3687214082Sdim	    }
3688214082Sdim	  if (!debug_information [i].max_range_lists)
3689214082Sdim	    free (debug_information [i].range_lists);
3690214082Sdim	}
3691214082Sdim      free (debug_information);
3692214082Sdim      debug_information = NULL;
3693214082Sdim      num_debug_info_entries = 0;
3694214082Sdim    }
3695214082Sdim
3696214082Sdim}
3697214082Sdim
3698214082Sdimstruct dwarf_section_display debug_displays[] =
3699214082Sdim{
3700214082Sdim  { { ".debug_abbrev",		NULL,	0,	0 },
3701214082Sdim    display_debug_abbrev,		0,	0 },
3702214082Sdim  { { ".debug_aranges",		NULL,	0,	0 },
3703214082Sdim    display_debug_aranges,		0,	0 },
3704214082Sdim  { { ".debug_frame",		NULL,	0,	0 },
3705214082Sdim    display_debug_frames,		1,	0 },
3706214082Sdim  { { ".debug_info",		NULL,	0,	0 },
3707214082Sdim    display_debug_info,			1,	0 },
3708214082Sdim  { { ".debug_line",		NULL,	0,	0 },
3709214082Sdim    display_debug_lines,		0,	0 },
3710214082Sdim  { { ".debug_pubnames",	NULL,	0,	0 },
3711214082Sdim    display_debug_pubnames,		0,	0 },
3712214082Sdim  { { ".eh_frame",		NULL,	0,	0 },
3713214082Sdim    display_debug_frames,		1,	1 },
3714214082Sdim  { { ".debug_macinfo",		NULL,	0,	0 },
3715214082Sdim    display_debug_macinfo,		0,	0 },
3716214082Sdim  { { ".debug_str",		NULL,	0,	0 },
3717214082Sdim    display_debug_str,			0,	0 },
3718214082Sdim  { { ".debug_loc",		NULL,	0,	0 },
3719214082Sdim    display_debug_loc,			0,	0 },
3720214082Sdim  { { ".debug_pubtypes",	NULL,	0,	0 },
3721214082Sdim    display_debug_pubnames,		0,	0 },
3722214082Sdim  { { ".debug_ranges",		NULL,	0,	0 },
3723214082Sdim    display_debug_ranges,		0,	0 },
3724214082Sdim  { { ".debug_static_func",	NULL,	0,	0 },
3725214082Sdim    display_debug_not_supported,	0,	0 },
3726214082Sdim  { { ".debug_static_vars",	NULL,	0,	0 },
3727214082Sdim    display_debug_not_supported,	0,	0 },
3728214082Sdim  { { ".debug_types",		NULL,	0,	0 },
3729214082Sdim    display_debug_not_supported,	0,	0 },
3730214082Sdim  { { ".debug_weaknames",	NULL,	0,	0 },
3731214082Sdim    display_debug_not_supported,	0,	0 }
3732214082Sdim};
3733