1214082Sdim/* dwarf.c -- display DWARF contents of a BFD binary file
2214634Sdim   Copyright 2005, 2006, 2007
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
22214634Sdim#include "sysdep.h"
23214634Sdim#include "libiberty.h"
24214634Sdim#include "bfd.h"
25214634Sdim#include "bucomm.h"
26214634Sdim#include "elf/dwarf2.h"
27214082Sdim#include "dwarf.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";
560248802Sdim    case DW_FORM_flag_present:	return "DW_FORM_flag_present";
561214082Sdim    default:
562214082Sdim      {
563214082Sdim	static char buffer[100];
564214082Sdim
565214082Sdim	snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
566214082Sdim	return buffer;
567214082Sdim      }
568214082Sdim    }
569214082Sdim}
570214082Sdim
571214082Sdimstatic unsigned char *
572214082Sdimdisplay_block (unsigned char *data, unsigned long length)
573214082Sdim{
574214082Sdim  printf (_(" %lu byte block: "), length);
575214082Sdim
576214082Sdim  while (length --)
577214082Sdim    printf ("%lx ", (unsigned long) byte_get (data++, 1));
578214082Sdim
579214082Sdim  return data;
580214082Sdim}
581214082Sdim
582214082Sdimstatic int
583214082Sdimdecode_location_expression (unsigned char * data,
584214082Sdim			    unsigned int pointer_size,
585214082Sdim			    unsigned long length,
586214082Sdim			    unsigned long cu_offset)
587214082Sdim{
588214082Sdim  unsigned op;
589214082Sdim  unsigned int bytes_read;
590214082Sdim  unsigned long uvalue;
591214082Sdim  unsigned char *end = data + length;
592214082Sdim  int need_frame_base = 0;
593214082Sdim
594214082Sdim  while (data < end)
595214082Sdim    {
596214082Sdim      op = *data++;
597214082Sdim
598214082Sdim      switch (op)
599214082Sdim	{
600214082Sdim	case DW_OP_addr:
601214082Sdim	  printf ("DW_OP_addr: %lx",
602214082Sdim		  (unsigned long) byte_get (data, pointer_size));
603214082Sdim	  data += pointer_size;
604214082Sdim	  break;
605214082Sdim	case DW_OP_deref:
606214082Sdim	  printf ("DW_OP_deref");
607214082Sdim	  break;
608214082Sdim	case DW_OP_const1u:
609214082Sdim	  printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1));
610214082Sdim	  break;
611214082Sdim	case DW_OP_const1s:
612214082Sdim	  printf ("DW_OP_const1s: %ld", (long) byte_get_signed (data++, 1));
613214082Sdim	  break;
614214082Sdim	case DW_OP_const2u:
615214082Sdim	  printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2));
616214082Sdim	  data += 2;
617214082Sdim	  break;
618214082Sdim	case DW_OP_const2s:
619214082Sdim	  printf ("DW_OP_const2s: %ld", (long) byte_get_signed (data, 2));
620214082Sdim	  data += 2;
621214082Sdim	  break;
622214082Sdim	case DW_OP_const4u:
623214082Sdim	  printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4));
624214082Sdim	  data += 4;
625214082Sdim	  break;
626214082Sdim	case DW_OP_const4s:
627214082Sdim	  printf ("DW_OP_const4s: %ld", (long) byte_get_signed (data, 4));
628214082Sdim	  data += 4;
629214082Sdim	  break;
630214082Sdim	case DW_OP_const8u:
631214082Sdim	  printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4),
632214082Sdim		  (unsigned long) byte_get (data + 4, 4));
633214082Sdim	  data += 8;
634214082Sdim	  break;
635214082Sdim	case DW_OP_const8s:
636214082Sdim	  printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4),
637214082Sdim		  (long) byte_get (data + 4, 4));
638214082Sdim	  data += 8;
639214082Sdim	  break;
640214082Sdim	case DW_OP_constu:
641214082Sdim	  printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0));
642214082Sdim	  data += bytes_read;
643214082Sdim	  break;
644214082Sdim	case DW_OP_consts:
645214082Sdim	  printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1));
646214082Sdim	  data += bytes_read;
647214082Sdim	  break;
648214082Sdim	case DW_OP_dup:
649214082Sdim	  printf ("DW_OP_dup");
650214082Sdim	  break;
651214082Sdim	case DW_OP_drop:
652214082Sdim	  printf ("DW_OP_drop");
653214082Sdim	  break;
654214082Sdim	case DW_OP_over:
655214082Sdim	  printf ("DW_OP_over");
656214082Sdim	  break;
657214082Sdim	case DW_OP_pick:
658214082Sdim	  printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1));
659214082Sdim	  break;
660214082Sdim	case DW_OP_swap:
661214082Sdim	  printf ("DW_OP_swap");
662214082Sdim	  break;
663214082Sdim	case DW_OP_rot:
664214082Sdim	  printf ("DW_OP_rot");
665214082Sdim	  break;
666214082Sdim	case DW_OP_xderef:
667214082Sdim	  printf ("DW_OP_xderef");
668214082Sdim	  break;
669214082Sdim	case DW_OP_abs:
670214082Sdim	  printf ("DW_OP_abs");
671214082Sdim	  break;
672214082Sdim	case DW_OP_and:
673214082Sdim	  printf ("DW_OP_and");
674214082Sdim	  break;
675214082Sdim	case DW_OP_div:
676214082Sdim	  printf ("DW_OP_div");
677214082Sdim	  break;
678214082Sdim	case DW_OP_minus:
679214082Sdim	  printf ("DW_OP_minus");
680214082Sdim	  break;
681214082Sdim	case DW_OP_mod:
682214082Sdim	  printf ("DW_OP_mod");
683214082Sdim	  break;
684214082Sdim	case DW_OP_mul:
685214082Sdim	  printf ("DW_OP_mul");
686214082Sdim	  break;
687214082Sdim	case DW_OP_neg:
688214082Sdim	  printf ("DW_OP_neg");
689214082Sdim	  break;
690214082Sdim	case DW_OP_not:
691214082Sdim	  printf ("DW_OP_not");
692214082Sdim	  break;
693214082Sdim	case DW_OP_or:
694214082Sdim	  printf ("DW_OP_or");
695214082Sdim	  break;
696214082Sdim	case DW_OP_plus:
697214082Sdim	  printf ("DW_OP_plus");
698214082Sdim	  break;
699214082Sdim	case DW_OP_plus_uconst:
700214082Sdim	  printf ("DW_OP_plus_uconst: %lu",
701214082Sdim		  read_leb128 (data, &bytes_read, 0));
702214082Sdim	  data += bytes_read;
703214082Sdim	  break;
704214082Sdim	case DW_OP_shl:
705214082Sdim	  printf ("DW_OP_shl");
706214082Sdim	  break;
707214082Sdim	case DW_OP_shr:
708214082Sdim	  printf ("DW_OP_shr");
709214082Sdim	  break;
710214082Sdim	case DW_OP_shra:
711214082Sdim	  printf ("DW_OP_shra");
712214082Sdim	  break;
713214082Sdim	case DW_OP_xor:
714214082Sdim	  printf ("DW_OP_xor");
715214082Sdim	  break;
716214082Sdim	case DW_OP_bra:
717214082Sdim	  printf ("DW_OP_bra: %ld", (long) byte_get_signed (data, 2));
718214082Sdim	  data += 2;
719214082Sdim	  break;
720214082Sdim	case DW_OP_eq:
721214082Sdim	  printf ("DW_OP_eq");
722214082Sdim	  break;
723214082Sdim	case DW_OP_ge:
724214082Sdim	  printf ("DW_OP_ge");
725214082Sdim	  break;
726214082Sdim	case DW_OP_gt:
727214082Sdim	  printf ("DW_OP_gt");
728214082Sdim	  break;
729214082Sdim	case DW_OP_le:
730214082Sdim	  printf ("DW_OP_le");
731214082Sdim	  break;
732214082Sdim	case DW_OP_lt:
733214082Sdim	  printf ("DW_OP_lt");
734214082Sdim	  break;
735214082Sdim	case DW_OP_ne:
736214082Sdim	  printf ("DW_OP_ne");
737214082Sdim	  break;
738214082Sdim	case DW_OP_skip:
739214082Sdim	  printf ("DW_OP_skip: %ld", (long) byte_get_signed (data, 2));
740214082Sdim	  data += 2;
741214082Sdim	  break;
742214082Sdim
743214082Sdim	case DW_OP_lit0:
744214082Sdim	case DW_OP_lit1:
745214082Sdim	case DW_OP_lit2:
746214082Sdim	case DW_OP_lit3:
747214082Sdim	case DW_OP_lit4:
748214082Sdim	case DW_OP_lit5:
749214082Sdim	case DW_OP_lit6:
750214082Sdim	case DW_OP_lit7:
751214082Sdim	case DW_OP_lit8:
752214082Sdim	case DW_OP_lit9:
753214082Sdim	case DW_OP_lit10:
754214082Sdim	case DW_OP_lit11:
755214082Sdim	case DW_OP_lit12:
756214082Sdim	case DW_OP_lit13:
757214082Sdim	case DW_OP_lit14:
758214082Sdim	case DW_OP_lit15:
759214082Sdim	case DW_OP_lit16:
760214082Sdim	case DW_OP_lit17:
761214082Sdim	case DW_OP_lit18:
762214082Sdim	case DW_OP_lit19:
763214082Sdim	case DW_OP_lit20:
764214082Sdim	case DW_OP_lit21:
765214082Sdim	case DW_OP_lit22:
766214082Sdim	case DW_OP_lit23:
767214082Sdim	case DW_OP_lit24:
768214082Sdim	case DW_OP_lit25:
769214082Sdim	case DW_OP_lit26:
770214082Sdim	case DW_OP_lit27:
771214082Sdim	case DW_OP_lit28:
772214082Sdim	case DW_OP_lit29:
773214082Sdim	case DW_OP_lit30:
774214082Sdim	case DW_OP_lit31:
775214082Sdim	  printf ("DW_OP_lit%d", op - DW_OP_lit0);
776214082Sdim	  break;
777214082Sdim
778214082Sdim	case DW_OP_reg0:
779214082Sdim	case DW_OP_reg1:
780214082Sdim	case DW_OP_reg2:
781214082Sdim	case DW_OP_reg3:
782214082Sdim	case DW_OP_reg4:
783214082Sdim	case DW_OP_reg5:
784214082Sdim	case DW_OP_reg6:
785214082Sdim	case DW_OP_reg7:
786214082Sdim	case DW_OP_reg8:
787214082Sdim	case DW_OP_reg9:
788214082Sdim	case DW_OP_reg10:
789214082Sdim	case DW_OP_reg11:
790214082Sdim	case DW_OP_reg12:
791214082Sdim	case DW_OP_reg13:
792214082Sdim	case DW_OP_reg14:
793214082Sdim	case DW_OP_reg15:
794214082Sdim	case DW_OP_reg16:
795214082Sdim	case DW_OP_reg17:
796214082Sdim	case DW_OP_reg18:
797214082Sdim	case DW_OP_reg19:
798214082Sdim	case DW_OP_reg20:
799214082Sdim	case DW_OP_reg21:
800214082Sdim	case DW_OP_reg22:
801214082Sdim	case DW_OP_reg23:
802214082Sdim	case DW_OP_reg24:
803214082Sdim	case DW_OP_reg25:
804214082Sdim	case DW_OP_reg26:
805214082Sdim	case DW_OP_reg27:
806214082Sdim	case DW_OP_reg28:
807214082Sdim	case DW_OP_reg29:
808214082Sdim	case DW_OP_reg30:
809214082Sdim	case DW_OP_reg31:
810214082Sdim	  printf ("DW_OP_reg%d", op - DW_OP_reg0);
811214082Sdim	  break;
812214082Sdim
813214082Sdim	case DW_OP_breg0:
814214082Sdim	case DW_OP_breg1:
815214082Sdim	case DW_OP_breg2:
816214082Sdim	case DW_OP_breg3:
817214082Sdim	case DW_OP_breg4:
818214082Sdim	case DW_OP_breg5:
819214082Sdim	case DW_OP_breg6:
820214082Sdim	case DW_OP_breg7:
821214082Sdim	case DW_OP_breg8:
822214082Sdim	case DW_OP_breg9:
823214082Sdim	case DW_OP_breg10:
824214082Sdim	case DW_OP_breg11:
825214082Sdim	case DW_OP_breg12:
826214082Sdim	case DW_OP_breg13:
827214082Sdim	case DW_OP_breg14:
828214082Sdim	case DW_OP_breg15:
829214082Sdim	case DW_OP_breg16:
830214082Sdim	case DW_OP_breg17:
831214082Sdim	case DW_OP_breg18:
832214082Sdim	case DW_OP_breg19:
833214082Sdim	case DW_OP_breg20:
834214082Sdim	case DW_OP_breg21:
835214082Sdim	case DW_OP_breg22:
836214082Sdim	case DW_OP_breg23:
837214082Sdim	case DW_OP_breg24:
838214082Sdim	case DW_OP_breg25:
839214082Sdim	case DW_OP_breg26:
840214082Sdim	case DW_OP_breg27:
841214082Sdim	case DW_OP_breg28:
842214082Sdim	case DW_OP_breg29:
843214082Sdim	case DW_OP_breg30:
844214082Sdim	case DW_OP_breg31:
845214082Sdim	  printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0,
846214082Sdim		  read_leb128 (data, &bytes_read, 1));
847214082Sdim	  data += bytes_read;
848214082Sdim	  break;
849214082Sdim
850214082Sdim	case DW_OP_regx:
851214082Sdim	  printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0));
852214082Sdim	  data += bytes_read;
853214082Sdim	  break;
854214082Sdim	case DW_OP_fbreg:
855214082Sdim	  need_frame_base = 1;
856214082Sdim	  printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1));
857214082Sdim	  data += bytes_read;
858214082Sdim	  break;
859214082Sdim	case DW_OP_bregx:
860214082Sdim	  uvalue = read_leb128 (data, &bytes_read, 0);
861214082Sdim	  data += bytes_read;
862214082Sdim	  printf ("DW_OP_bregx: %lu %ld", uvalue,
863214082Sdim		  read_leb128 (data, &bytes_read, 1));
864214082Sdim	  data += bytes_read;
865214082Sdim	  break;
866214082Sdim	case DW_OP_piece:
867214082Sdim	  printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0));
868214082Sdim	  data += bytes_read;
869214082Sdim	  break;
870214082Sdim	case DW_OP_deref_size:
871214082Sdim	  printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1));
872214082Sdim	  break;
873214082Sdim	case DW_OP_xderef_size:
874214082Sdim	  printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1));
875214082Sdim	  break;
876214082Sdim	case DW_OP_nop:
877214082Sdim	  printf ("DW_OP_nop");
878214082Sdim	  break;
879214082Sdim
880214082Sdim	  /* DWARF 3 extensions.  */
881214082Sdim	case DW_OP_push_object_address:
882214082Sdim	  printf ("DW_OP_push_object_address");
883214082Sdim	  break;
884214082Sdim	case DW_OP_call2:
885214082Sdim	  /* XXX: Strictly speaking for 64-bit DWARF3 files
886214082Sdim	     this ought to be an 8-byte wide computation.  */
887214082Sdim	  printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2) + cu_offset);
888214082Sdim	  data += 2;
889214082Sdim	  break;
890214082Sdim	case DW_OP_call4:
891214082Sdim	  /* XXX: Strictly speaking for 64-bit DWARF3 files
892214082Sdim	     this ought to be an 8-byte wide computation.  */
893214082Sdim	  printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4) + cu_offset);
894214082Sdim	  data += 4;
895214082Sdim	  break;
896214082Sdim	case DW_OP_call_ref:
897214082Sdim	  printf ("DW_OP_call_ref");
898214082Sdim	  break;
899214634Sdim	case DW_OP_form_tls_address:
900214634Sdim	  printf ("DW_OP_form_tls_address");
901214634Sdim	  break;
902214082Sdim
903214082Sdim	  /* GNU extensions.  */
904214082Sdim	case DW_OP_GNU_push_tls_address:
905214082Sdim	  printf ("DW_OP_GNU_push_tls_address");
906214082Sdim	  break;
907214082Sdim
908214082Sdim	default:
909214082Sdim	  if (op >= DW_OP_lo_user
910214082Sdim	      && op <= DW_OP_hi_user)
911214082Sdim	    printf (_("(User defined location op)"));
912214082Sdim	  else
913214082Sdim	    printf (_("(Unknown location op)"));
914214082Sdim	  /* No way to tell where the next op is, so just bail.  */
915214082Sdim	  return need_frame_base;
916214082Sdim	}
917214082Sdim
918214082Sdim      /* Separate the ops.  */
919214082Sdim      if (data < end)
920214082Sdim	printf ("; ");
921214082Sdim    }
922214082Sdim
923214082Sdim  return need_frame_base;
924214082Sdim}
925214082Sdim
926214082Sdimstatic unsigned char *
927214082Sdimread_and_display_attr_value (unsigned long attribute,
928214082Sdim			     unsigned long form,
929214082Sdim			     unsigned char *data,
930214082Sdim			     unsigned long cu_offset,
931214082Sdim			     unsigned long pointer_size,
932214082Sdim			     unsigned long offset_size,
933214082Sdim			     int dwarf_version,
934214082Sdim			     debug_info *debug_info_p,
935214082Sdim			     int do_loc)
936214082Sdim{
937214082Sdim  unsigned long uvalue = 0;
938214082Sdim  unsigned char *block_start = NULL;
939214082Sdim  unsigned int bytes_read;
940214082Sdim
941214082Sdim  switch (form)
942214082Sdim    {
943214082Sdim    default:
944214082Sdim      break;
945214082Sdim
946214082Sdim    case DW_FORM_ref_addr:
947214082Sdim      if (dwarf_version == 2)
948214082Sdim	{
949214082Sdim	  uvalue = byte_get (data, pointer_size);
950214082Sdim	  data += pointer_size;
951214082Sdim	}
952214082Sdim      else if (dwarf_version == 3)
953214082Sdim	{
954214082Sdim	  uvalue = byte_get (data, offset_size);
955214082Sdim	  data += offset_size;
956214082Sdim	}
957214082Sdim      else
958214082Sdim	{
959214082Sdim	  error (_("Internal error: DWARF version is not 2 or 3.\n"));
960214082Sdim	}
961214082Sdim      break;
962214082Sdim
963214082Sdim    case DW_FORM_addr:
964214082Sdim      uvalue = byte_get (data, pointer_size);
965214082Sdim      data += pointer_size;
966214082Sdim      break;
967214082Sdim
968214082Sdim    case DW_FORM_strp:
969214082Sdim      uvalue = byte_get (data, offset_size);
970214082Sdim      data += offset_size;
971214082Sdim      break;
972214082Sdim
973248802Sdim    case DW_FORM_flag_present:
974248802Sdim      uvalue = 1;
975248802Sdim      break;
976248802Sdim
977214082Sdim    case DW_FORM_ref1:
978214082Sdim    case DW_FORM_flag:
979214082Sdim    case DW_FORM_data1:
980214082Sdim      uvalue = byte_get (data++, 1);
981214082Sdim      break;
982214082Sdim
983214082Sdim    case DW_FORM_ref2:
984214082Sdim    case DW_FORM_data2:
985214082Sdim      uvalue = byte_get (data, 2);
986214082Sdim      data += 2;
987214082Sdim      break;
988214082Sdim
989214082Sdim    case DW_FORM_ref4:
990214082Sdim    case DW_FORM_data4:
991214082Sdim      uvalue = byte_get (data, 4);
992214082Sdim      data += 4;
993214082Sdim      break;
994214082Sdim
995214082Sdim    case DW_FORM_sdata:
996214082Sdim      uvalue = read_leb128 (data, & bytes_read, 1);
997214082Sdim      data += bytes_read;
998214082Sdim      break;
999214082Sdim
1000214082Sdim    case DW_FORM_ref_udata:
1001214082Sdim    case DW_FORM_udata:
1002214082Sdim      uvalue = read_leb128 (data, & bytes_read, 0);
1003214082Sdim      data += bytes_read;
1004214082Sdim      break;
1005214082Sdim
1006214082Sdim    case DW_FORM_indirect:
1007214082Sdim      form = read_leb128 (data, & bytes_read, 0);
1008214082Sdim      data += bytes_read;
1009214082Sdim      if (!do_loc)
1010214082Sdim	printf (" %s", get_FORM_name (form));
1011214082Sdim      return read_and_display_attr_value (attribute, form, data,
1012214082Sdim					  cu_offset, pointer_size,
1013214082Sdim					  offset_size, dwarf_version,
1014214082Sdim					  debug_info_p, do_loc);
1015214082Sdim    }
1016214082Sdim
1017214082Sdim  switch (form)
1018214082Sdim    {
1019214082Sdim    case DW_FORM_ref_addr:
1020214082Sdim      if (!do_loc)
1021214082Sdim	printf (" <#%lx>", uvalue);
1022214082Sdim      break;
1023214082Sdim
1024214082Sdim    case DW_FORM_ref1:
1025214082Sdim    case DW_FORM_ref2:
1026214082Sdim    case DW_FORM_ref4:
1027214082Sdim    case DW_FORM_ref_udata:
1028214082Sdim      if (!do_loc)
1029214082Sdim	printf (" <%lx>", uvalue + cu_offset);
1030214082Sdim      break;
1031214082Sdim
1032214082Sdim    case DW_FORM_data4:
1033214082Sdim    case DW_FORM_addr:
1034214082Sdim      if (!do_loc)
1035214082Sdim	printf (" %#lx", uvalue);
1036214082Sdim      break;
1037214082Sdim
1038248802Sdim    case DW_FORM_flag_present:
1039214082Sdim    case DW_FORM_flag:
1040214082Sdim    case DW_FORM_data1:
1041214082Sdim    case DW_FORM_data2:
1042214082Sdim    case DW_FORM_sdata:
1043214082Sdim    case DW_FORM_udata:
1044214082Sdim      if (!do_loc)
1045214082Sdim	printf (" %ld", uvalue);
1046214082Sdim      break;
1047214082Sdim
1048214082Sdim    case DW_FORM_ref8:
1049214082Sdim    case DW_FORM_data8:
1050214082Sdim      if (!do_loc)
1051214082Sdim	{
1052214082Sdim	  uvalue = byte_get (data, 4);
1053214082Sdim	  printf (" %lx", uvalue);
1054214082Sdim	  printf (" %lx", (unsigned long) byte_get (data + 4, 4));
1055214082Sdim	}
1056214082Sdim      if ((do_loc || do_debug_loc || do_debug_ranges)
1057214082Sdim	  && num_debug_info_entries == 0)
1058214082Sdim	{
1059214082Sdim	  if (sizeof (uvalue) == 8)
1060214082Sdim	    uvalue = byte_get (data, 8);
1061214082Sdim	  else
1062214082Sdim	    error (_("DW_FORM_data8 is unsupported when sizeof (unsigned long) != 8\n"));
1063214082Sdim	}
1064214082Sdim      data += 8;
1065214082Sdim      break;
1066214082Sdim
1067214082Sdim    case DW_FORM_string:
1068214082Sdim      if (!do_loc)
1069214082Sdim	printf (" %s", data);
1070214082Sdim      data += strlen ((char *) data) + 1;
1071214082Sdim      break;
1072214082Sdim
1073214082Sdim    case DW_FORM_block:
1074214082Sdim      uvalue = read_leb128 (data, & bytes_read, 0);
1075214082Sdim      block_start = data + bytes_read;
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_block1:
1083214082Sdim      uvalue = byte_get (data, 1);
1084214082Sdim      block_start = data + 1;
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_block2:
1092214082Sdim      uvalue = byte_get (data, 2);
1093214082Sdim      block_start = data + 2;
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_block4:
1101214082Sdim      uvalue = byte_get (data, 4);
1102214082Sdim      block_start = data + 4;
1103214082Sdim      if (do_loc)
1104214082Sdim	data = block_start + uvalue;
1105214082Sdim      else
1106214082Sdim	data = display_block (block_start, uvalue);
1107214082Sdim      break;
1108214082Sdim
1109214082Sdim    case DW_FORM_strp:
1110214082Sdim      if (!do_loc)
1111214082Sdim	printf (_(" (indirect string, offset: 0x%lx): %s"),
1112214082Sdim		uvalue, fetch_indirect_string (uvalue));
1113214082Sdim      break;
1114214082Sdim
1115214082Sdim    case DW_FORM_indirect:
1116214082Sdim      /* Handled above.  */
1117214082Sdim      break;
1118214082Sdim
1119214082Sdim    default:
1120214082Sdim      warn (_("Unrecognized form: %lu\n"), form);
1121214082Sdim      break;
1122214082Sdim    }
1123214082Sdim
1124214082Sdim  /* For some attributes we can display further information.  */
1125214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1126214082Sdim      && num_debug_info_entries == 0)
1127214082Sdim    {
1128214082Sdim      switch (attribute)
1129214082Sdim	{
1130214082Sdim	case DW_AT_frame_base:
1131214082Sdim	  have_frame_base = 1;
1132214082Sdim	case DW_AT_location:
1133214082Sdim	case DW_AT_data_member_location:
1134214082Sdim	case DW_AT_vtable_elem_location:
1135214082Sdim	case DW_AT_allocated:
1136214082Sdim	case DW_AT_associated:
1137214082Sdim	case DW_AT_data_location:
1138214082Sdim	case DW_AT_stride:
1139214082Sdim	case DW_AT_upper_bound:
1140214082Sdim	case DW_AT_lower_bound:
1141214082Sdim	  if (form == DW_FORM_data4 || form == DW_FORM_data8)
1142214082Sdim	    {
1143214082Sdim	      /* Process location list.  */
1144214082Sdim	      unsigned int max = debug_info_p->max_loc_offsets;
1145214082Sdim	      unsigned int num = debug_info_p->num_loc_offsets;
1146214082Sdim
1147214082Sdim	      if (max == 0 || num >= max)
1148214082Sdim		{
1149214082Sdim		  max += 1024;
1150214082Sdim		  debug_info_p->loc_offsets
1151214082Sdim		    = xcrealloc (debug_info_p->loc_offsets,
1152214082Sdim				 max, sizeof (*debug_info_p->loc_offsets));
1153214082Sdim		  debug_info_p->have_frame_base
1154214082Sdim		    = xcrealloc (debug_info_p->have_frame_base,
1155214082Sdim				 max, sizeof (*debug_info_p->have_frame_base));
1156214082Sdim		  debug_info_p->max_loc_offsets = max;
1157214082Sdim		}
1158214082Sdim	      debug_info_p->loc_offsets [num] = uvalue;
1159214082Sdim	      debug_info_p->have_frame_base [num] = have_frame_base;
1160214082Sdim	      debug_info_p->num_loc_offsets++;
1161214082Sdim	    }
1162214082Sdim	  break;
1163214082Sdim
1164214082Sdim	case DW_AT_low_pc:
1165214082Sdim	  if (need_base_address)
1166214082Sdim	    debug_info_p->base_address = uvalue;
1167214082Sdim	  break;
1168214082Sdim
1169214082Sdim	case DW_AT_ranges:
1170214082Sdim	  if (form == DW_FORM_data4 || form == DW_FORM_data8)
1171214082Sdim	    {
1172214082Sdim	      /* Process range list.  */
1173214082Sdim	      unsigned int max = debug_info_p->max_range_lists;
1174214082Sdim	      unsigned int num = debug_info_p->num_range_lists;
1175214082Sdim
1176214082Sdim	      if (max == 0 || num >= max)
1177214082Sdim		{
1178214082Sdim		  max += 1024;
1179214082Sdim		  debug_info_p->range_lists
1180214082Sdim		    = xcrealloc (debug_info_p->range_lists,
1181214082Sdim				 max, sizeof (*debug_info_p->range_lists));
1182214082Sdim		  debug_info_p->max_range_lists = max;
1183214082Sdim		}
1184214082Sdim	      debug_info_p->range_lists [num] = uvalue;
1185214082Sdim	      debug_info_p->num_range_lists++;
1186214082Sdim	    }
1187214082Sdim	  break;
1188214082Sdim
1189214082Sdim	default:
1190214082Sdim	  break;
1191214082Sdim	}
1192214082Sdim    }
1193214082Sdim
1194214082Sdim  if (do_loc)
1195214082Sdim    return data;
1196214082Sdim
1197214082Sdim  printf ("\t");
1198214082Sdim
1199214082Sdim  switch (attribute)
1200214082Sdim    {
1201214082Sdim    case DW_AT_inline:
1202214082Sdim      switch (uvalue)
1203214082Sdim	{
1204214082Sdim	case DW_INL_not_inlined:
1205214082Sdim	  printf (_("(not inlined)"));
1206214082Sdim	  break;
1207214082Sdim	case DW_INL_inlined:
1208214082Sdim	  printf (_("(inlined)"));
1209214082Sdim	  break;
1210214082Sdim	case DW_INL_declared_not_inlined:
1211214082Sdim	  printf (_("(declared as inline but ignored)"));
1212214082Sdim	  break;
1213214082Sdim	case DW_INL_declared_inlined:
1214214082Sdim	  printf (_("(declared as inline and inlined)"));
1215214082Sdim	  break;
1216214082Sdim	default:
1217214082Sdim	  printf (_("  (Unknown inline attribute value: %lx)"), uvalue);
1218214082Sdim	  break;
1219214082Sdim	}
1220214082Sdim      break;
1221214082Sdim
1222214082Sdim    case DW_AT_language:
1223214082Sdim      switch (uvalue)
1224214082Sdim	{
1225214634Sdim	  /* Ordered by the numeric value of these constants.  */
1226214634Sdim	case DW_LANG_C89:		printf ("(ANSI C)"); break;
1227214082Sdim	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
1228214634Sdim	case DW_LANG_Ada83:		printf ("(Ada)"); break;
1229214082Sdim	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
1230214634Sdim	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
1231214634Sdim	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
1232214082Sdim	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
1233214082Sdim	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
1234214634Sdim	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
1235214082Sdim	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
1236214082Sdim	  /* DWARF 2.1 values.	*/
1237214634Sdim	case DW_LANG_Java:		printf ("(Java)"); break;
1238214082Sdim	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
1239214082Sdim	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
1240214082Sdim	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
1241214634Sdim	  /* DWARF 3 values.  */
1242214634Sdim	case DW_LANG_PLI:		printf ("(PLI)"); break;
1243214634Sdim	case DW_LANG_ObjC:		printf ("(Objective C)"); break;
1244214634Sdim	case DW_LANG_ObjC_plus_plus:	printf ("(Objective C++)"); break;
1245214634Sdim	case DW_LANG_UPC:		printf ("(Unified Parallel C)"); break;
1246214634Sdim	case DW_LANG_D:			printf ("(D)"); break;
1247214082Sdim	  /* MIPS extension.  */
1248214082Sdim	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
1249214082Sdim	  /* UPC extension.  */
1250214082Sdim	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
1251214082Sdim	default:
1252214634Sdim	  if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
1253214634Sdim	    printf ("(implementation defined: %lx)", uvalue);
1254214634Sdim	  else
1255214634Sdim	    printf ("(Unknown: %lx)", uvalue);
1256214082Sdim	  break;
1257214082Sdim	}
1258214082Sdim      break;
1259214082Sdim
1260214082Sdim    case DW_AT_encoding:
1261214082Sdim      switch (uvalue)
1262214082Sdim	{
1263214082Sdim	case DW_ATE_void:		printf ("(void)"); break;
1264214082Sdim	case DW_ATE_address:		printf ("(machine address)"); break;
1265214082Sdim	case DW_ATE_boolean:		printf ("(boolean)"); break;
1266214082Sdim	case DW_ATE_complex_float:	printf ("(complex float)"); break;
1267214082Sdim	case DW_ATE_float:		printf ("(float)"); break;
1268214082Sdim	case DW_ATE_signed:		printf ("(signed)"); break;
1269214082Sdim	case DW_ATE_signed_char:	printf ("(signed char)"); break;
1270214082Sdim	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
1271214082Sdim	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
1272214082Sdim	  /* DWARF 2.1 value.  */
1273214082Sdim	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
1274214082Sdim	case DW_ATE_decimal_float:	printf ("(decimal float)"); break;
1275214082Sdim	default:
1276214082Sdim	  if (uvalue >= DW_ATE_lo_user
1277214082Sdim	      && uvalue <= DW_ATE_hi_user)
1278214082Sdim	    printf ("(user defined type)");
1279214082Sdim	  else
1280214082Sdim	    printf ("(unknown type)");
1281214082Sdim	  break;
1282214082Sdim	}
1283214082Sdim      break;
1284214082Sdim
1285214082Sdim    case DW_AT_accessibility:
1286214082Sdim      switch (uvalue)
1287214082Sdim	{
1288214082Sdim	case DW_ACCESS_public:		printf ("(public)"); break;
1289214082Sdim	case DW_ACCESS_protected:	printf ("(protected)"); break;
1290214082Sdim	case DW_ACCESS_private:		printf ("(private)"); break;
1291214082Sdim	default:
1292214082Sdim	  printf ("(unknown accessibility)");
1293214082Sdim	  break;
1294214082Sdim	}
1295214082Sdim      break;
1296214082Sdim
1297214082Sdim    case DW_AT_visibility:
1298214082Sdim      switch (uvalue)
1299214082Sdim	{
1300214082Sdim	case DW_VIS_local:		printf ("(local)"); break;
1301214082Sdim	case DW_VIS_exported:		printf ("(exported)"); break;
1302214082Sdim	case DW_VIS_qualified:		printf ("(qualified)"); break;
1303214082Sdim	default:			printf ("(unknown visibility)"); break;
1304214082Sdim	}
1305214082Sdim      break;
1306214082Sdim
1307214082Sdim    case DW_AT_virtuality:
1308214082Sdim      switch (uvalue)
1309214082Sdim	{
1310214082Sdim	case DW_VIRTUALITY_none:	printf ("(none)"); break;
1311214082Sdim	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
1312214082Sdim	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
1313214082Sdim	default:			printf ("(unknown virtuality)"); break;
1314214082Sdim	}
1315214082Sdim      break;
1316214082Sdim
1317214082Sdim    case DW_AT_identifier_case:
1318214082Sdim      switch (uvalue)
1319214082Sdim	{
1320214082Sdim	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
1321214082Sdim	case DW_ID_up_case:		printf ("(up_case)"); break;
1322214082Sdim	case DW_ID_down_case:		printf ("(down_case)"); break;
1323214082Sdim	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
1324214082Sdim	default:			printf ("(unknown case)"); break;
1325214082Sdim	}
1326214082Sdim      break;
1327214082Sdim
1328214082Sdim    case DW_AT_calling_convention:
1329214082Sdim      switch (uvalue)
1330214082Sdim	{
1331214082Sdim	case DW_CC_normal:	printf ("(normal)"); break;
1332214082Sdim	case DW_CC_program:	printf ("(program)"); break;
1333214082Sdim	case DW_CC_nocall:	printf ("(nocall)"); break;
1334214082Sdim	default:
1335214082Sdim	  if (uvalue >= DW_CC_lo_user
1336214082Sdim	      && uvalue <= DW_CC_hi_user)
1337214082Sdim	    printf ("(user defined)");
1338214082Sdim	  else
1339214082Sdim	    printf ("(unknown convention)");
1340214082Sdim	}
1341214082Sdim      break;
1342214082Sdim
1343214082Sdim    case DW_AT_ordering:
1344214082Sdim      switch (uvalue)
1345214082Sdim	{
1346214082Sdim	case -1: printf ("(undefined)"); break;
1347214082Sdim	case 0:  printf ("(row major)"); break;
1348214082Sdim	case 1:  printf ("(column major)"); break;
1349214082Sdim	}
1350214082Sdim      break;
1351214082Sdim
1352214082Sdim    case DW_AT_frame_base:
1353214082Sdim      have_frame_base = 1;
1354214082Sdim    case DW_AT_location:
1355214082Sdim    case DW_AT_data_member_location:
1356214082Sdim    case DW_AT_vtable_elem_location:
1357214082Sdim    case DW_AT_allocated:
1358214082Sdim    case DW_AT_associated:
1359214082Sdim    case DW_AT_data_location:
1360214082Sdim    case DW_AT_stride:
1361214082Sdim    case DW_AT_upper_bound:
1362214082Sdim    case DW_AT_lower_bound:
1363214082Sdim      if (block_start)
1364214082Sdim	{
1365214082Sdim	  int need_frame_base;
1366214082Sdim
1367214082Sdim	  printf ("(");
1368214082Sdim	  need_frame_base = decode_location_expression (block_start,
1369214082Sdim							pointer_size,
1370214082Sdim							uvalue,
1371214082Sdim							cu_offset);
1372214082Sdim	  printf (")");
1373214082Sdim	  if (need_frame_base && !have_frame_base)
1374214082Sdim	    printf (_(" [without DW_AT_frame_base]"));
1375214082Sdim	}
1376214082Sdim      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
1377214082Sdim	printf (_("(location list)"));
1378214082Sdim
1379214082Sdim      break;
1380214082Sdim
1381214082Sdim    default:
1382214082Sdim      break;
1383214082Sdim    }
1384214082Sdim
1385214082Sdim  return data;
1386214082Sdim}
1387214082Sdim
1388214082Sdimstatic char *
1389214082Sdimget_AT_name (unsigned long attribute)
1390214082Sdim{
1391214082Sdim  switch (attribute)
1392214082Sdim    {
1393214082Sdim    case DW_AT_sibling:			return "DW_AT_sibling";
1394214082Sdim    case DW_AT_location:		return "DW_AT_location";
1395214082Sdim    case DW_AT_name:			return "DW_AT_name";
1396214082Sdim    case DW_AT_ordering:		return "DW_AT_ordering";
1397214082Sdim    case DW_AT_subscr_data:		return "DW_AT_subscr_data";
1398214082Sdim    case DW_AT_byte_size:		return "DW_AT_byte_size";
1399214082Sdim    case DW_AT_bit_offset:		return "DW_AT_bit_offset";
1400214082Sdim    case DW_AT_bit_size:		return "DW_AT_bit_size";
1401214082Sdim    case DW_AT_element_list:		return "DW_AT_element_list";
1402214082Sdim    case DW_AT_stmt_list:		return "DW_AT_stmt_list";
1403214082Sdim    case DW_AT_low_pc:			return "DW_AT_low_pc";
1404214082Sdim    case DW_AT_high_pc:			return "DW_AT_high_pc";
1405214082Sdim    case DW_AT_language:		return "DW_AT_language";
1406214082Sdim    case DW_AT_member:			return "DW_AT_member";
1407214082Sdim    case DW_AT_discr:			return "DW_AT_discr";
1408214082Sdim    case DW_AT_discr_value:		return "DW_AT_discr_value";
1409214082Sdim    case DW_AT_visibility:		return "DW_AT_visibility";
1410214082Sdim    case DW_AT_import:			return "DW_AT_import";
1411214082Sdim    case DW_AT_string_length:		return "DW_AT_string_length";
1412214082Sdim    case DW_AT_common_reference:	return "DW_AT_common_reference";
1413214082Sdim    case DW_AT_comp_dir:		return "DW_AT_comp_dir";
1414214082Sdim    case DW_AT_const_value:		return "DW_AT_const_value";
1415214082Sdim    case DW_AT_containing_type:		return "DW_AT_containing_type";
1416214082Sdim    case DW_AT_default_value:		return "DW_AT_default_value";
1417214082Sdim    case DW_AT_inline:			return "DW_AT_inline";
1418214082Sdim    case DW_AT_is_optional:		return "DW_AT_is_optional";
1419214082Sdim    case DW_AT_lower_bound:		return "DW_AT_lower_bound";
1420214082Sdim    case DW_AT_producer:		return "DW_AT_producer";
1421214082Sdim    case DW_AT_prototyped:		return "DW_AT_prototyped";
1422214082Sdim    case DW_AT_return_addr:		return "DW_AT_return_addr";
1423214082Sdim    case DW_AT_start_scope:		return "DW_AT_start_scope";
1424214082Sdim    case DW_AT_stride_size:		return "DW_AT_stride_size";
1425214082Sdim    case DW_AT_upper_bound:		return "DW_AT_upper_bound";
1426214082Sdim    case DW_AT_abstract_origin:		return "DW_AT_abstract_origin";
1427214082Sdim    case DW_AT_accessibility:		return "DW_AT_accessibility";
1428214082Sdim    case DW_AT_address_class:		return "DW_AT_address_class";
1429214082Sdim    case DW_AT_artificial:		return "DW_AT_artificial";
1430214082Sdim    case DW_AT_base_types:		return "DW_AT_base_types";
1431214082Sdim    case DW_AT_calling_convention:	return "DW_AT_calling_convention";
1432214082Sdim    case DW_AT_count:			return "DW_AT_count";
1433214082Sdim    case DW_AT_data_member_location:	return "DW_AT_data_member_location";
1434214082Sdim    case DW_AT_decl_column:		return "DW_AT_decl_column";
1435214082Sdim    case DW_AT_decl_file:		return "DW_AT_decl_file";
1436214082Sdim    case DW_AT_decl_line:		return "DW_AT_decl_line";
1437214082Sdim    case DW_AT_declaration:		return "DW_AT_declaration";
1438214082Sdim    case DW_AT_discr_list:		return "DW_AT_discr_list";
1439214082Sdim    case DW_AT_encoding:		return "DW_AT_encoding";
1440214082Sdim    case DW_AT_external:		return "DW_AT_external";
1441214082Sdim    case DW_AT_frame_base:		return "DW_AT_frame_base";
1442214082Sdim    case DW_AT_friend:			return "DW_AT_friend";
1443214082Sdim    case DW_AT_identifier_case:		return "DW_AT_identifier_case";
1444214082Sdim    case DW_AT_macro_info:		return "DW_AT_macro_info";
1445214082Sdim    case DW_AT_namelist_items:		return "DW_AT_namelist_items";
1446214082Sdim    case DW_AT_priority:		return "DW_AT_priority";
1447214082Sdim    case DW_AT_segment:			return "DW_AT_segment";
1448214082Sdim    case DW_AT_specification:		return "DW_AT_specification";
1449214082Sdim    case DW_AT_static_link:		return "DW_AT_static_link";
1450214082Sdim    case DW_AT_type:			return "DW_AT_type";
1451214082Sdim    case DW_AT_use_location:		return "DW_AT_use_location";
1452214082Sdim    case DW_AT_variable_parameter:	return "DW_AT_variable_parameter";
1453214082Sdim    case DW_AT_virtuality:		return "DW_AT_virtuality";
1454214082Sdim    case DW_AT_vtable_elem_location:	return "DW_AT_vtable_elem_location";
1455214082Sdim      /* DWARF 2.1 values.  */
1456214082Sdim    case DW_AT_allocated:		return "DW_AT_allocated";
1457214082Sdim    case DW_AT_associated:		return "DW_AT_associated";
1458214082Sdim    case DW_AT_data_location:		return "DW_AT_data_location";
1459214082Sdim    case DW_AT_stride:			return "DW_AT_stride";
1460214082Sdim    case DW_AT_entry_pc:		return "DW_AT_entry_pc";
1461214082Sdim    case DW_AT_use_UTF8:		return "DW_AT_use_UTF8";
1462214082Sdim    case DW_AT_extension:		return "DW_AT_extension";
1463214082Sdim    case DW_AT_ranges:			return "DW_AT_ranges";
1464214082Sdim    case DW_AT_trampoline:		return "DW_AT_trampoline";
1465214082Sdim    case DW_AT_call_column:		return "DW_AT_call_column";
1466214082Sdim    case DW_AT_call_file:		return "DW_AT_call_file";
1467214082Sdim    case DW_AT_call_line:		return "DW_AT_call_line";
1468214082Sdim      /* SGI/MIPS extensions.  */
1469214082Sdim    case DW_AT_MIPS_fde:		return "DW_AT_MIPS_fde";
1470214082Sdim    case DW_AT_MIPS_loop_begin:		return "DW_AT_MIPS_loop_begin";
1471214082Sdim    case DW_AT_MIPS_tail_loop_begin:	return "DW_AT_MIPS_tail_loop_begin";
1472214082Sdim    case DW_AT_MIPS_epilog_begin:	return "DW_AT_MIPS_epilog_begin";
1473214082Sdim    case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
1474214082Sdim    case DW_AT_MIPS_software_pipeline_depth:
1475214082Sdim      return "DW_AT_MIPS_software_pipeline_depth";
1476214082Sdim    case DW_AT_MIPS_linkage_name:	return "DW_AT_MIPS_linkage_name";
1477214082Sdim    case DW_AT_MIPS_stride:		return "DW_AT_MIPS_stride";
1478214082Sdim    case DW_AT_MIPS_abstract_name:	return "DW_AT_MIPS_abstract_name";
1479214082Sdim    case DW_AT_MIPS_clone_origin:	return "DW_AT_MIPS_clone_origin";
1480214082Sdim    case DW_AT_MIPS_has_inlines:	return "DW_AT_MIPS_has_inlines";
1481214082Sdim      /* GNU extensions.  */
1482214082Sdim    case DW_AT_sf_names:		return "DW_AT_sf_names";
1483214082Sdim    case DW_AT_src_info:		return "DW_AT_src_info";
1484214082Sdim    case DW_AT_mac_info:		return "DW_AT_mac_info";
1485214082Sdim    case DW_AT_src_coords:		return "DW_AT_src_coords";
1486214082Sdim    case DW_AT_body_begin:		return "DW_AT_body_begin";
1487214082Sdim    case DW_AT_body_end:		return "DW_AT_body_end";
1488214082Sdim    case DW_AT_GNU_vector:		return "DW_AT_GNU_vector";
1489214082Sdim      /* UPC extension.  */
1490214082Sdim    case DW_AT_upc_threads_scaled:	return "DW_AT_upc_threads_scaled";
1491214082Sdim    default:
1492214082Sdim      {
1493214082Sdim	static char buffer[100];
1494214082Sdim
1495214082Sdim	snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
1496214082Sdim		  attribute);
1497214082Sdim	return buffer;
1498214082Sdim      }
1499214082Sdim    }
1500214082Sdim}
1501214082Sdim
1502214082Sdimstatic unsigned char *
1503214082Sdimread_and_display_attr (unsigned long attribute,
1504214082Sdim		       unsigned long form,
1505214082Sdim		       unsigned char *data,
1506214082Sdim		       unsigned long cu_offset,
1507214082Sdim		       unsigned long pointer_size,
1508214082Sdim		       unsigned long offset_size,
1509214082Sdim		       int dwarf_version,
1510214082Sdim		       debug_info *debug_info_p,
1511214082Sdim		       int do_loc)
1512214082Sdim{
1513214082Sdim  if (!do_loc)
1514214082Sdim    printf ("     %-18s:", get_AT_name (attribute));
1515214082Sdim  data = read_and_display_attr_value (attribute, form, data, cu_offset,
1516214082Sdim				      pointer_size, offset_size,
1517214082Sdim				      dwarf_version, debug_info_p,
1518214082Sdim				      do_loc);
1519214082Sdim  if (!do_loc)
1520214082Sdim    printf ("\n");
1521214082Sdim  return data;
1522214082Sdim}
1523214082Sdim
1524214082Sdim
1525214082Sdim/* Process the contents of a .debug_info section.  If do_loc is non-zero
1526214082Sdim   then we are scanning for location lists and we do not want to display
1527214082Sdim   anything to the user.  */
1528214082Sdim
1529214082Sdimstatic int
1530214082Sdimprocess_debug_info (struct dwarf_section *section, void *file,
1531214082Sdim		    int do_loc)
1532214082Sdim{
1533214082Sdim  unsigned char *start = section->start;
1534214082Sdim  unsigned char *end = start + section->size;
1535214082Sdim  unsigned char *section_begin;
1536214082Sdim  unsigned int unit;
1537214082Sdim  unsigned int num_units = 0;
1538214082Sdim
1539214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1540214082Sdim      && num_debug_info_entries == 0)
1541214082Sdim    {
1542214082Sdim      unsigned long length;
1543214082Sdim
1544214082Sdim      /* First scan the section to get the number of comp units.  */
1545214082Sdim      for (section_begin = start, num_units = 0; section_begin < end;
1546214082Sdim	   num_units ++)
1547214082Sdim	{
1548214082Sdim	  /* Read the first 4 bytes.  For a 32-bit DWARF section, this
1549214082Sdim	     will be the length.  For a 64-bit DWARF section, it'll be
1550214082Sdim	     the escape code 0xffffffff followed by an 8 byte length.  */
1551214082Sdim	  length = byte_get (section_begin, 4);
1552214082Sdim
1553214082Sdim	  if (length == 0xffffffff)
1554214082Sdim	    {
1555214082Sdim	      length = byte_get (section_begin + 4, 8);
1556214082Sdim	      section_begin += length + 12;
1557214082Sdim	    }
1558214082Sdim	  else
1559214082Sdim	    section_begin += length + 4;
1560214082Sdim	}
1561214082Sdim
1562214082Sdim      if (num_units == 0)
1563214082Sdim	{
1564214082Sdim	  error (_("No comp units in %s section ?"), section->name);
1565214082Sdim	  return 0;
1566214082Sdim	}
1567214082Sdim
1568214082Sdim      /* Then allocate an array to hold the information.  */
1569214082Sdim      debug_information = cmalloc (num_units,
1570214082Sdim				   sizeof (* debug_information));
1571214082Sdim      if (debug_information == NULL)
1572214082Sdim	{
1573214082Sdim	  error (_("Not enough memory for a debug info array of %u entries"),
1574214082Sdim		 num_units);
1575214082Sdim	  return 0;
1576214082Sdim	}
1577214082Sdim    }
1578214082Sdim
1579214082Sdim  if (!do_loc)
1580214082Sdim    {
1581214082Sdim      printf (_("The section %s contains:\n\n"), section->name);
1582214082Sdim
1583214082Sdim      load_debug_section (str, file);
1584214082Sdim    }
1585214082Sdim
1586214082Sdim  load_debug_section (abbrev, file);
1587214082Sdim  if (debug_displays [abbrev].section.start == NULL)
1588214082Sdim    {
1589214082Sdim      warn (_("Unable to locate %s section!\n"),
1590214082Sdim	    debug_displays [abbrev].section.name);
1591214082Sdim      return 0;
1592214082Sdim    }
1593214082Sdim
1594214082Sdim  for (section_begin = start, unit = 0; start < end; unit++)
1595214082Sdim    {
1596214082Sdim      DWARF2_Internal_CompUnit compunit;
1597214082Sdim      unsigned char *hdrptr;
1598214082Sdim      unsigned char *cu_abbrev_offset_ptr;
1599214082Sdim      unsigned char *tags;
1600214082Sdim      int level;
1601214082Sdim      unsigned long cu_offset;
1602214082Sdim      int offset_size;
1603214082Sdim      int initial_length_size;
1604214082Sdim
1605214082Sdim      hdrptr = start;
1606214082Sdim
1607214082Sdim      compunit.cu_length = byte_get (hdrptr, 4);
1608214082Sdim      hdrptr += 4;
1609214082Sdim
1610214082Sdim      if (compunit.cu_length == 0xffffffff)
1611214082Sdim	{
1612214082Sdim	  compunit.cu_length = byte_get (hdrptr, 8);
1613214082Sdim	  hdrptr += 8;
1614214082Sdim	  offset_size = 8;
1615214082Sdim	  initial_length_size = 12;
1616214082Sdim	}
1617214082Sdim      else
1618214082Sdim	{
1619214082Sdim	  offset_size = 4;
1620214082Sdim	  initial_length_size = 4;
1621214082Sdim	}
1622214082Sdim
1623214082Sdim      compunit.cu_version = byte_get (hdrptr, 2);
1624214082Sdim      hdrptr += 2;
1625214082Sdim
1626214082Sdim      cu_offset = start - section_begin;
1627214082Sdim
1628214082Sdim      cu_abbrev_offset_ptr = hdrptr;
1629214082Sdim      compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
1630214082Sdim      hdrptr += offset_size;
1631214082Sdim
1632214082Sdim      compunit.cu_pointer_size = byte_get (hdrptr, 1);
1633214082Sdim      hdrptr += 1;
1634214082Sdim      if ((do_loc || do_debug_loc || do_debug_ranges)
1635214082Sdim	  && num_debug_info_entries == 0)
1636214082Sdim	{
1637214082Sdim	  debug_information [unit].cu_offset = cu_offset;
1638214082Sdim	  debug_information [unit].pointer_size
1639214082Sdim	    = compunit.cu_pointer_size;
1640214082Sdim	  debug_information [unit].base_address = 0;
1641214082Sdim	  debug_information [unit].loc_offsets = NULL;
1642214082Sdim	  debug_information [unit].have_frame_base = NULL;
1643214082Sdim	  debug_information [unit].max_loc_offsets = 0;
1644214082Sdim	  debug_information [unit].num_loc_offsets = 0;
1645214082Sdim	  debug_information [unit].range_lists = NULL;
1646214082Sdim	  debug_information [unit].max_range_lists= 0;
1647214082Sdim	  debug_information [unit].num_range_lists = 0;
1648214082Sdim	}
1649214082Sdim
1650214082Sdim      if (!do_loc)
1651214082Sdim	{
1652214082Sdim	  printf (_("  Compilation Unit @ offset 0x%lx:\n"), cu_offset);
1653214082Sdim	  printf (_("   Length:        %ld\n"), compunit.cu_length);
1654214082Sdim	  printf (_("   Version:       %d\n"), compunit.cu_version);
1655214082Sdim	  printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
1656214082Sdim	  printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
1657214082Sdim	}
1658214082Sdim
1659214634Sdim      if (cu_offset + compunit.cu_length + initial_length_size
1660214634Sdim	  > section->size)
1661214634Sdim	{
1662214634Sdim	  warn (_("Debug info is corrupted, length is invalid (section is %lu bytes)\n"),
1663214634Sdim		(unsigned long)section->size);
1664214634Sdim	  break;
1665214634Sdim	}
1666214634Sdim      tags = hdrptr;
1667214634Sdim      start += compunit.cu_length + initial_length_size;
1668214634Sdim
1669214082Sdim      if (compunit.cu_version != 2 && compunit.cu_version != 3)
1670214082Sdim	{
1671214082Sdim	  warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
1672214082Sdim	  continue;
1673214082Sdim	}
1674214082Sdim
1675214082Sdim      free_abbrevs ();
1676214082Sdim
1677214082Sdim      /* Process the abbrevs used by this compilation unit. DWARF
1678214082Sdim	 sections under Mach-O have non-zero addresses.  */
1679214634Sdim      if (compunit.cu_abbrev_offset >= debug_displays [abbrev].section.size)
1680214634Sdim	warn (_("Debug info is corrupted, abbrev offset is invalid (section is %lu bytes)\n"),
1681214634Sdim	      (unsigned long)debug_displays [abbrev].section.size);
1682214634Sdim      else
1683214634Sdim	process_abbrev_section
1684214634Sdim	  ((unsigned char *) debug_displays [abbrev].section.start
1685214634Sdim	   + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
1686214634Sdim	   (unsigned char *) debug_displays [abbrev].section.start
1687214634Sdim	   + debug_displays [abbrev].section.size);
1688214082Sdim
1689214082Sdim      level = 0;
1690214082Sdim      while (tags < start)
1691214082Sdim	{
1692214082Sdim	  unsigned int bytes_read;
1693214082Sdim	  unsigned long abbrev_number;
1694214082Sdim	  abbrev_entry *entry;
1695214082Sdim	  abbrev_attr *attr;
1696214082Sdim
1697214082Sdim	  abbrev_number = read_leb128 (tags, & bytes_read, 0);
1698214082Sdim	  tags += bytes_read;
1699214082Sdim
1700214082Sdim	  /* A null DIE marks the end of a list of children.  */
1701214082Sdim	  if (abbrev_number == 0)
1702214082Sdim	    {
1703214082Sdim	      --level;
1704214082Sdim	      continue;
1705214082Sdim	    }
1706214082Sdim
1707214634Sdim	  if (!do_loc)
1708214634Sdim	    printf (_(" <%d><%lx>: Abbrev Number: %lu"),
1709214634Sdim		    level,
1710214634Sdim		    (unsigned long) (tags - section_begin
1711214634Sdim				     - bytes_read),
1712214634Sdim		    abbrev_number);
1713214634Sdim
1714214082Sdim	  /* Scan through the abbreviation list until we reach the
1715214082Sdim	     correct entry.  */
1716214082Sdim	  for (entry = first_abbrev;
1717214082Sdim	       entry && entry->entry != abbrev_number;
1718214082Sdim	       entry = entry->next)
1719214082Sdim	    continue;
1720214082Sdim
1721214082Sdim	  if (entry == NULL)
1722214082Sdim	    {
1723214634Sdim	      if (!do_loc)
1724214634Sdim		{
1725214634Sdim		  printf ("\n");
1726214634Sdim		  fflush (stdout);
1727214634Sdim		}
1728214082Sdim	      warn (_("Unable to locate entry %lu in the abbreviation table\n"),
1729214082Sdim		    abbrev_number);
1730214082Sdim	      return 0;
1731214082Sdim	    }
1732214082Sdim
1733214082Sdim	  if (!do_loc)
1734214634Sdim	    printf (_(" (%s)\n"), get_TAG_name (entry->tag));
1735214082Sdim
1736214082Sdim	  switch (entry->tag)
1737214082Sdim	    {
1738214082Sdim	    default:
1739214082Sdim	      need_base_address = 0;
1740214082Sdim	      break;
1741214082Sdim	    case DW_TAG_compile_unit:
1742214082Sdim	      need_base_address = 1;
1743214082Sdim	      break;
1744214082Sdim	    case DW_TAG_entry_point:
1745214082Sdim	    case DW_TAG_subprogram:
1746214082Sdim	      need_base_address = 0;
1747214082Sdim	      /* Assuming that there is no DW_AT_frame_base.  */
1748214082Sdim	      have_frame_base = 0;
1749214082Sdim	      break;
1750214082Sdim	    }
1751214082Sdim
1752214082Sdim	  for (attr = entry->first_attr; attr; attr = attr->next)
1753214634Sdim	    {
1754214634Sdim	      if (! do_loc)
1755214634Sdim		/* Show the offset from where the tag was extracted.  */
1756214634Sdim		printf ("  <%2lx>", (unsigned long)(tags - section_begin));
1757214634Sdim
1758214634Sdim	      tags = read_and_display_attr (attr->attribute,
1759214634Sdim					    attr->form,
1760214634Sdim					    tags, cu_offset,
1761214634Sdim					    compunit.cu_pointer_size,
1762214634Sdim					    offset_size,
1763214634Sdim					    compunit.cu_version,
1764214634Sdim					    &debug_information [unit],
1765214634Sdim					    do_loc);
1766214634Sdim	    }
1767214082Sdim
1768214082Sdim 	  if (entry->children)
1769214082Sdim 	    ++level;
1770214082Sdim 	}
1771214082Sdim    }
1772214082Sdim
1773214082Sdim  /* Set num_debug_info_entries here so that it can be used to check if
1774214082Sdim     we need to process .debug_loc and .debug_ranges sections.  */
1775214082Sdim  if ((do_loc || do_debug_loc || do_debug_ranges)
1776214082Sdim      && num_debug_info_entries == 0)
1777214082Sdim    num_debug_info_entries = num_units;
1778214082Sdim
1779214082Sdim  if (!do_loc)
1780214082Sdim    {
1781214082Sdim      printf ("\n");
1782214082Sdim    }
1783214082Sdim
1784214082Sdim  return 1;
1785214082Sdim}
1786214082Sdim
1787214082Sdim/* Locate and scan the .debug_info section in the file and record the pointer
1788214082Sdim   sizes and offsets for the compilation units in it.  Usually an executable
1789214082Sdim   will have just one pointer size, but this is not guaranteed, and so we try
1790214082Sdim   not to make any assumptions.  Returns zero upon failure, or the number of
1791214082Sdim   compilation units upon success.  */
1792214082Sdim
1793214082Sdimstatic unsigned int
1794214082Sdimload_debug_info (void * file)
1795214082Sdim{
1796214082Sdim  /* Reset the last pointer size so that we can issue correct error
1797214082Sdim     messages if we are displaying the contents of more than one section.  */
1798214082Sdim  last_pointer_size = 0;
1799214082Sdim  warned_about_missing_comp_units = FALSE;
1800214082Sdim
1801214082Sdim  /* If we already have the information there is nothing else to do.  */
1802214082Sdim  if (num_debug_info_entries > 0)
1803214082Sdim    return num_debug_info_entries;
1804214082Sdim
1805214082Sdim  if (load_debug_section (info, file)
1806214082Sdim      && process_debug_info (&debug_displays [info].section, file, 1))
1807214082Sdim    return num_debug_info_entries;
1808214082Sdim  else
1809214082Sdim    return 0;
1810214082Sdim}
1811214082Sdim
1812214082Sdimstatic int
1813214082Sdimdisplay_debug_lines (struct dwarf_section *section, void *file)
1814214082Sdim{
1815214082Sdim  unsigned char *start = section->start;
1816214082Sdim  unsigned char *data = start;
1817214082Sdim  unsigned char *end = start + section->size;
1818214082Sdim
1819214082Sdim  printf (_("\nDump of debug contents of section %s:\n\n"),
1820214082Sdim	  section->name);
1821214082Sdim
1822214082Sdim  load_debug_info (file);
1823214082Sdim
1824214082Sdim  while (data < end)
1825214082Sdim    {
1826214082Sdim      DWARF2_Internal_LineInfo info;
1827214082Sdim      unsigned char *standard_opcodes;
1828214082Sdim      unsigned char *end_of_sequence;
1829214082Sdim      unsigned char *hdrptr;
1830214082Sdim      int initial_length_size;
1831214082Sdim      int offset_size;
1832214082Sdim      int i;
1833214082Sdim
1834214082Sdim      hdrptr = data;
1835214082Sdim
1836214082Sdim      /* Check the length of the block.  */
1837214082Sdim      info.li_length = byte_get (hdrptr, 4);
1838214082Sdim      hdrptr += 4;
1839214082Sdim
1840214082Sdim      if (info.li_length == 0xffffffff)
1841214082Sdim	{
1842214082Sdim	  /* This section is 64-bit DWARF 3.  */
1843214082Sdim	  info.li_length = byte_get (hdrptr, 8);
1844214082Sdim	  hdrptr += 8;
1845214082Sdim	  offset_size = 8;
1846214082Sdim	  initial_length_size = 12;
1847214082Sdim	}
1848214082Sdim      else
1849214082Sdim	{
1850214082Sdim	  offset_size = 4;
1851214082Sdim	  initial_length_size = 4;
1852214082Sdim	}
1853214082Sdim
1854214082Sdim      if (info.li_length + initial_length_size > section->size)
1855214082Sdim	{
1856214082Sdim	  warn
1857214082Sdim	    (_("The line info appears to be corrupt - the section is too small\n"));
1858214082Sdim	  return 0;
1859214082Sdim	}
1860214082Sdim
1861214082Sdim      /* Check its version number.  */
1862214082Sdim      info.li_version = byte_get (hdrptr, 2);
1863214082Sdim      hdrptr += 2;
1864214082Sdim      if (info.li_version != 2 && info.li_version != 3)
1865214082Sdim	{
1866214082Sdim	  warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
1867214082Sdim	  return 0;
1868214082Sdim	}
1869214082Sdim
1870214082Sdim      info.li_prologue_length = byte_get (hdrptr, offset_size);
1871214082Sdim      hdrptr += offset_size;
1872214082Sdim      info.li_min_insn_length = byte_get (hdrptr, 1);
1873214082Sdim      hdrptr++;
1874214082Sdim      info.li_default_is_stmt = byte_get (hdrptr, 1);
1875214082Sdim      hdrptr++;
1876214082Sdim      info.li_line_base = byte_get (hdrptr, 1);
1877214082Sdim      hdrptr++;
1878214082Sdim      info.li_line_range = byte_get (hdrptr, 1);
1879214082Sdim      hdrptr++;
1880214082Sdim      info.li_opcode_base = byte_get (hdrptr, 1);
1881214082Sdim      hdrptr++;
1882214082Sdim
1883214082Sdim      /* Sign extend the line base field.  */
1884214082Sdim      info.li_line_base <<= 24;
1885214082Sdim      info.li_line_base >>= 24;
1886214082Sdim
1887214082Sdim      printf (_("  Length:                      %ld\n"), info.li_length);
1888214082Sdim      printf (_("  DWARF Version:               %d\n"), info.li_version);
1889214082Sdim      printf (_("  Prologue Length:             %d\n"), info.li_prologue_length);
1890214082Sdim      printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
1891214082Sdim      printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
1892214082Sdim      printf (_("  Line Base:                   %d\n"), info.li_line_base);
1893214082Sdim      printf (_("  Line Range:                  %d\n"), info.li_line_range);
1894214082Sdim      printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
1895214082Sdim
1896214082Sdim      end_of_sequence = data + info.li_length + initial_length_size;
1897214082Sdim
1898214082Sdim      reset_state_machine (info.li_default_is_stmt);
1899214082Sdim
1900214082Sdim      /* Display the contents of the Opcodes table.  */
1901214082Sdim      standard_opcodes = hdrptr;
1902214082Sdim
1903214082Sdim      printf (_("\n Opcodes:\n"));
1904214082Sdim
1905214082Sdim      for (i = 1; i < info.li_opcode_base; i++)
1906214082Sdim	printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
1907214082Sdim
1908214082Sdim      /* Display the contents of the Directory table.  */
1909214082Sdim      data = standard_opcodes + info.li_opcode_base - 1;
1910214082Sdim
1911214082Sdim      if (*data == 0)
1912214082Sdim	printf (_("\n The Directory Table is empty.\n"));
1913214082Sdim      else
1914214082Sdim	{
1915214082Sdim	  printf (_("\n The Directory Table:\n"));
1916214082Sdim
1917214082Sdim	  while (*data != 0)
1918214082Sdim	    {
1919214082Sdim	      printf (_("  %s\n"), data);
1920214082Sdim
1921214082Sdim	      data += strlen ((char *) data) + 1;
1922214082Sdim	    }
1923214082Sdim	}
1924214082Sdim
1925214082Sdim      /* Skip the NUL at the end of the table.  */
1926214082Sdim      data++;
1927214082Sdim
1928214082Sdim      /* Display the contents of the File Name table.  */
1929214082Sdim      if (*data == 0)
1930214082Sdim	printf (_("\n The File Name Table is empty.\n"));
1931214082Sdim      else
1932214082Sdim	{
1933214082Sdim	  printf (_("\n The File Name Table:\n"));
1934214082Sdim	  printf (_("  Entry\tDir\tTime\tSize\tName\n"));
1935214082Sdim
1936214082Sdim	  while (*data != 0)
1937214082Sdim	    {
1938214082Sdim	      unsigned char *name;
1939214082Sdim	      unsigned int bytes_read;
1940214082Sdim
1941214082Sdim	      printf (_("  %d\t"), ++state_machine_regs.last_file_entry);
1942214082Sdim	      name = data;
1943214082Sdim
1944214082Sdim	      data += strlen ((char *) data) + 1;
1945214082Sdim
1946214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1947214082Sdim	      data += bytes_read;
1948214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1949214082Sdim	      data += bytes_read;
1950214082Sdim	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
1951214082Sdim	      data += bytes_read;
1952214082Sdim	      printf (_("%s\n"), name);
1953214082Sdim	    }
1954214082Sdim	}
1955214082Sdim
1956214082Sdim      /* Skip the NUL at the end of the table.  */
1957214082Sdim      data++;
1958214082Sdim
1959214082Sdim      /* Now display the statements.  */
1960214082Sdim      printf (_("\n Line Number Statements:\n"));
1961214082Sdim
1962214082Sdim      while (data < end_of_sequence)
1963214082Sdim	{
1964214082Sdim	  unsigned char op_code;
1965214082Sdim	  int adv;
1966214082Sdim	  unsigned long int uladv;
1967214082Sdim	  unsigned int bytes_read;
1968214082Sdim
1969214082Sdim	  op_code = *data++;
1970214082Sdim
1971214082Sdim	  if (op_code >= info.li_opcode_base)
1972214082Sdim	    {
1973214082Sdim	      op_code -= info.li_opcode_base;
1974214082Sdim	      uladv = (op_code / info.li_line_range) * info.li_min_insn_length;
1975214082Sdim	      state_machine_regs.address += uladv;
1976214082Sdim	      printf (_("  Special opcode %d: advance Address by %lu to 0x%lx"),
1977214082Sdim		      op_code, uladv, state_machine_regs.address);
1978214082Sdim	      adv = (op_code % info.li_line_range) + info.li_line_base;
1979214082Sdim	      state_machine_regs.line += adv;
1980214082Sdim	      printf (_(" and Line by %d to %d\n"),
1981214082Sdim		      adv, state_machine_regs.line);
1982214082Sdim	    }
1983214082Sdim	  else switch (op_code)
1984214082Sdim	    {
1985214082Sdim	    case DW_LNS_extended_op:
1986214082Sdim	      data += process_extended_line_op (data, info.li_default_is_stmt);
1987214082Sdim	      break;
1988214082Sdim
1989214082Sdim	    case DW_LNS_copy:
1990214082Sdim	      printf (_("  Copy\n"));
1991214082Sdim	      break;
1992214082Sdim
1993214082Sdim	    case DW_LNS_advance_pc:
1994214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
1995214082Sdim	      uladv *= info.li_min_insn_length;
1996214082Sdim	      data += bytes_read;
1997214082Sdim	      state_machine_regs.address += uladv;
1998214082Sdim	      printf (_("  Advance PC by %lu to 0x%lx\n"), uladv,
1999214082Sdim		      state_machine_regs.address);
2000214082Sdim	      break;
2001214082Sdim
2002214082Sdim	    case DW_LNS_advance_line:
2003214082Sdim	      adv = read_leb128 (data, & bytes_read, 1);
2004214082Sdim	      data += bytes_read;
2005214082Sdim	      state_machine_regs.line += adv;
2006214082Sdim	      printf (_("  Advance Line by %d to %d\n"), adv,
2007214082Sdim		      state_machine_regs.line);
2008214082Sdim	      break;
2009214082Sdim
2010214082Sdim	    case DW_LNS_set_file:
2011214082Sdim	      adv = read_leb128 (data, & bytes_read, 0);
2012214082Sdim	      data += bytes_read;
2013214082Sdim	      printf (_("  Set File Name to entry %d in the File Name Table\n"),
2014214082Sdim		      adv);
2015214082Sdim	      state_machine_regs.file = adv;
2016214082Sdim	      break;
2017214082Sdim
2018214082Sdim	    case DW_LNS_set_column:
2019214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
2020214082Sdim	      data += bytes_read;
2021214082Sdim	      printf (_("  Set column to %lu\n"), uladv);
2022214082Sdim	      state_machine_regs.column = uladv;
2023214082Sdim	      break;
2024214082Sdim
2025214082Sdim	    case DW_LNS_negate_stmt:
2026214082Sdim	      adv = state_machine_regs.is_stmt;
2027214082Sdim	      adv = ! adv;
2028214082Sdim	      printf (_("  Set is_stmt to %d\n"), adv);
2029214082Sdim	      state_machine_regs.is_stmt = adv;
2030214082Sdim	      break;
2031214082Sdim
2032214082Sdim	    case DW_LNS_set_basic_block:
2033214082Sdim	      printf (_("  Set basic block\n"));
2034214082Sdim	      state_machine_regs.basic_block = 1;
2035214082Sdim	      break;
2036214082Sdim
2037214082Sdim	    case DW_LNS_const_add_pc:
2038214082Sdim	      uladv = (((255 - info.li_opcode_base) / info.li_line_range)
2039214082Sdim		      * info.li_min_insn_length);
2040214082Sdim	      state_machine_regs.address += uladv;
2041214082Sdim	      printf (_("  Advance PC by constant %lu to 0x%lx\n"), uladv,
2042214082Sdim		      state_machine_regs.address);
2043214082Sdim	      break;
2044214082Sdim
2045214082Sdim	    case DW_LNS_fixed_advance_pc:
2046214082Sdim	      uladv = byte_get (data, 2);
2047214082Sdim	      data += 2;
2048214082Sdim	      state_machine_regs.address += uladv;
2049214082Sdim	      printf (_("  Advance PC by fixed size amount %lu to 0x%lx\n"),
2050214082Sdim		      uladv, state_machine_regs.address);
2051214082Sdim	      break;
2052214082Sdim
2053214082Sdim	    case DW_LNS_set_prologue_end:
2054214082Sdim	      printf (_("  Set prologue_end to true\n"));
2055214082Sdim	      break;
2056214082Sdim
2057214082Sdim	    case DW_LNS_set_epilogue_begin:
2058214082Sdim	      printf (_("  Set epilogue_begin to true\n"));
2059214082Sdim	      break;
2060214082Sdim
2061214082Sdim	    case DW_LNS_set_isa:
2062214082Sdim	      uladv = read_leb128 (data, & bytes_read, 0);
2063214082Sdim	      data += bytes_read;
2064214082Sdim	      printf (_("  Set ISA to %lu\n"), uladv);
2065214082Sdim	      break;
2066214082Sdim
2067214082Sdim	    default:
2068214082Sdim	      printf (_("  Unknown opcode %d with operands: "), op_code);
2069214082Sdim
2070214082Sdim	      for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
2071214082Sdim		{
2072214082Sdim		  printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
2073214082Sdim			  i == 1 ? "" : ", ");
2074214082Sdim		  data += bytes_read;
2075214082Sdim		}
2076214082Sdim	      putchar ('\n');
2077214082Sdim	      break;
2078214082Sdim	    }
2079214082Sdim	}
2080214082Sdim      putchar ('\n');
2081214082Sdim    }
2082214082Sdim
2083214082Sdim  return 1;
2084214082Sdim}
2085214082Sdim
2086214082Sdimstatic int
2087214082Sdimdisplay_debug_pubnames (struct dwarf_section *section,
2088214082Sdim			void *file ATTRIBUTE_UNUSED)
2089214082Sdim{
2090214082Sdim  DWARF2_Internal_PubNames pubnames;
2091214082Sdim  unsigned char *start = section->start;
2092214082Sdim  unsigned char *end = start + section->size;
2093214082Sdim
2094214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2095214082Sdim
2096214082Sdim  while (start < end)
2097214082Sdim    {
2098214082Sdim      unsigned char *data;
2099214082Sdim      unsigned long offset;
2100214082Sdim      int offset_size, initial_length_size;
2101214082Sdim
2102214082Sdim      data = start;
2103214082Sdim
2104214082Sdim      pubnames.pn_length = byte_get (data, 4);
2105214082Sdim      data += 4;
2106214082Sdim      if (pubnames.pn_length == 0xffffffff)
2107214082Sdim	{
2108214082Sdim	  pubnames.pn_length = byte_get (data, 8);
2109214082Sdim	  data += 8;
2110214082Sdim	  offset_size = 8;
2111214082Sdim	  initial_length_size = 12;
2112214082Sdim	}
2113214082Sdim      else
2114214082Sdim	{
2115214082Sdim	  offset_size = 4;
2116214082Sdim	  initial_length_size = 4;
2117214082Sdim	}
2118214082Sdim
2119214082Sdim      pubnames.pn_version = byte_get (data, 2);
2120214082Sdim      data += 2;
2121214082Sdim      pubnames.pn_offset = byte_get (data, offset_size);
2122214082Sdim      data += offset_size;
2123214082Sdim      pubnames.pn_size = byte_get (data, offset_size);
2124214082Sdim      data += offset_size;
2125214082Sdim
2126214082Sdim      start += pubnames.pn_length + initial_length_size;
2127214082Sdim
2128214082Sdim      if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
2129214082Sdim	{
2130214082Sdim	  static int warned = 0;
2131214082Sdim
2132214082Sdim	  if (! warned)
2133214082Sdim	    {
2134214082Sdim	      warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
2135214082Sdim	      warned = 1;
2136214082Sdim	    }
2137214082Sdim
2138214082Sdim	  continue;
2139214082Sdim	}
2140214082Sdim
2141214082Sdim      printf (_("  Length:                              %ld\n"),
2142214082Sdim	      pubnames.pn_length);
2143214082Sdim      printf (_("  Version:                             %d\n"),
2144214082Sdim	      pubnames.pn_version);
2145214082Sdim      printf (_("  Offset into .debug_info section:     %ld\n"),
2146214082Sdim	      pubnames.pn_offset);
2147214082Sdim      printf (_("  Size of area in .debug_info section: %ld\n"),
2148214082Sdim	      pubnames.pn_size);
2149214082Sdim
2150214082Sdim      printf (_("\n    Offset\tName\n"));
2151214082Sdim
2152214082Sdim      do
2153214082Sdim	{
2154214082Sdim	  offset = byte_get (data, offset_size);
2155214082Sdim
2156214082Sdim	  if (offset != 0)
2157214082Sdim	    {
2158214082Sdim	      data += offset_size;
2159214082Sdim	      printf ("    %-6ld\t\t%s\n", offset, data);
2160214082Sdim	      data += strlen ((char *) data) + 1;
2161214082Sdim	    }
2162214082Sdim	}
2163214082Sdim      while (offset != 0);
2164214082Sdim    }
2165214082Sdim
2166214082Sdim  printf ("\n");
2167214082Sdim  return 1;
2168214082Sdim}
2169214082Sdim
2170214082Sdimstatic int
2171214082Sdimdisplay_debug_macinfo (struct dwarf_section *section,
2172214082Sdim		       void *file ATTRIBUTE_UNUSED)
2173214082Sdim{
2174214082Sdim  unsigned char *start = section->start;
2175214082Sdim  unsigned char *end = start + section->size;
2176214082Sdim  unsigned char *curr = start;
2177214082Sdim  unsigned int bytes_read;
2178214082Sdim  enum dwarf_macinfo_record_type op;
2179214082Sdim
2180214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2181214082Sdim
2182214082Sdim  while (curr < end)
2183214082Sdim    {
2184214082Sdim      unsigned int lineno;
2185214082Sdim      const char *string;
2186214082Sdim
2187214082Sdim      op = *curr;
2188214082Sdim      curr++;
2189214082Sdim
2190214082Sdim      switch (op)
2191214082Sdim	{
2192214082Sdim	case DW_MACINFO_start_file:
2193214082Sdim	  {
2194214082Sdim	    unsigned int filenum;
2195214082Sdim
2196214082Sdim	    lineno = read_leb128 (curr, & bytes_read, 0);
2197214082Sdim	    curr += bytes_read;
2198214082Sdim	    filenum = read_leb128 (curr, & bytes_read, 0);
2199214082Sdim	    curr += bytes_read;
2200214082Sdim
2201214082Sdim	    printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
2202214082Sdim		    lineno, filenum);
2203214082Sdim	  }
2204214082Sdim	  break;
2205214082Sdim
2206214082Sdim	case DW_MACINFO_end_file:
2207214082Sdim	  printf (_(" DW_MACINFO_end_file\n"));
2208214082Sdim	  break;
2209214082Sdim
2210214082Sdim	case DW_MACINFO_define:
2211214082Sdim	  lineno = read_leb128 (curr, & bytes_read, 0);
2212214082Sdim	  curr += bytes_read;
2213214082Sdim	  string = (char *) curr;
2214214082Sdim	  curr += strlen (string) + 1;
2215214082Sdim	  printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
2216214082Sdim		  lineno, string);
2217214082Sdim	  break;
2218214082Sdim
2219214082Sdim	case DW_MACINFO_undef:
2220214082Sdim	  lineno = read_leb128 (curr, & bytes_read, 0);
2221214082Sdim	  curr += bytes_read;
2222214082Sdim	  string = (char *) curr;
2223214082Sdim	  curr += strlen (string) + 1;
2224214082Sdim	  printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
2225214082Sdim		  lineno, string);
2226214082Sdim	  break;
2227214082Sdim
2228214082Sdim	case DW_MACINFO_vendor_ext:
2229214082Sdim	  {
2230214082Sdim	    unsigned int constant;
2231214082Sdim
2232214082Sdim	    constant = read_leb128 (curr, & bytes_read, 0);
2233214082Sdim	    curr += bytes_read;
2234214082Sdim	    string = (char *) curr;
2235214082Sdim	    curr += strlen (string) + 1;
2236214082Sdim	    printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
2237214082Sdim		    constant, string);
2238214082Sdim	  }
2239214082Sdim	  break;
2240214082Sdim	}
2241214082Sdim    }
2242214082Sdim
2243214082Sdim  return 1;
2244214082Sdim}
2245214082Sdim
2246214082Sdimstatic int
2247214082Sdimdisplay_debug_abbrev (struct dwarf_section *section,
2248214082Sdim		      void *file ATTRIBUTE_UNUSED)
2249214082Sdim{
2250214082Sdim  abbrev_entry *entry;
2251214082Sdim  unsigned char *start = section->start;
2252214082Sdim  unsigned char *end = start + section->size;
2253214082Sdim
2254214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2255214082Sdim
2256214082Sdim  do
2257214082Sdim    {
2258214082Sdim      free_abbrevs ();
2259214082Sdim
2260214082Sdim      start = process_abbrev_section (start, end);
2261214082Sdim
2262214082Sdim      if (first_abbrev == NULL)
2263214082Sdim	continue;
2264214082Sdim
2265214082Sdim      printf (_("  Number TAG\n"));
2266214082Sdim
2267214082Sdim      for (entry = first_abbrev; entry; entry = entry->next)
2268214082Sdim	{
2269214082Sdim	  abbrev_attr *attr;
2270214082Sdim
2271214082Sdim	  printf (_("   %ld      %s    [%s]\n"),
2272214082Sdim		  entry->entry,
2273214082Sdim		  get_TAG_name (entry->tag),
2274214082Sdim		  entry->children ? _("has children") : _("no children"));
2275214082Sdim
2276214082Sdim	  for (attr = entry->first_attr; attr; attr = attr->next)
2277214082Sdim	    printf (_("    %-18s %s\n"),
2278214082Sdim		    get_AT_name (attr->attribute),
2279214082Sdim		    get_FORM_name (attr->form));
2280214082Sdim	}
2281214082Sdim    }
2282214082Sdim  while (start);
2283214082Sdim
2284214082Sdim  printf ("\n");
2285214082Sdim
2286214082Sdim  return 1;
2287214082Sdim}
2288214082Sdim
2289214082Sdimstatic int
2290214082Sdimdisplay_debug_loc (struct dwarf_section *section, void *file)
2291214082Sdim{
2292214082Sdim  unsigned char *start = section->start;
2293214082Sdim  unsigned char *section_end;
2294214082Sdim  unsigned long bytes;
2295214082Sdim  unsigned char *section_begin = start;
2296214082Sdim  unsigned int num_loc_list = 0;
2297214082Sdim  unsigned long last_offset = 0;
2298214082Sdim  unsigned int first = 0;
2299214082Sdim  unsigned int i;
2300214082Sdim  unsigned int j;
2301214082Sdim  int seen_first_offset = 0;
2302214082Sdim  int use_debug_info = 1;
2303214082Sdim  unsigned char *next;
2304214082Sdim
2305214082Sdim  bytes = section->size;
2306214082Sdim  section_end = start + bytes;
2307214082Sdim
2308214082Sdim  if (bytes == 0)
2309214082Sdim    {
2310214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2311214082Sdim      return 0;
2312214082Sdim    }
2313214082Sdim
2314214082Sdim  load_debug_info (file);
2315214082Sdim
2316214082Sdim  /* Check the order of location list in .debug_info section. If
2317214082Sdim     offsets of location lists are in the ascending order, we can
2318214082Sdim     use `debug_information' directly.  */
2319214082Sdim  for (i = 0; i < num_debug_info_entries; i++)
2320214082Sdim    {
2321214082Sdim      unsigned int num;
2322214082Sdim
2323214082Sdim      num = debug_information [i].num_loc_offsets;
2324214082Sdim      num_loc_list += num;
2325214082Sdim
2326214082Sdim      /* Check if we can use `debug_information' directly.  */
2327214082Sdim      if (use_debug_info && num != 0)
2328214082Sdim	{
2329214082Sdim	  if (!seen_first_offset)
2330214082Sdim	    {
2331214082Sdim	      /* This is the first location list.  */
2332214082Sdim	      last_offset = debug_information [i].loc_offsets [0];
2333214082Sdim	      first = i;
2334214082Sdim	      seen_first_offset = 1;
2335214082Sdim	      j = 1;
2336214082Sdim	    }
2337214082Sdim	  else
2338214082Sdim	    j = 0;
2339214082Sdim
2340214082Sdim	  for (; j < num; j++)
2341214082Sdim	    {
2342214082Sdim	      if (last_offset >
2343214082Sdim		  debug_information [i].loc_offsets [j])
2344214082Sdim		{
2345214082Sdim		  use_debug_info = 0;
2346214082Sdim		  break;
2347214082Sdim		}
2348214082Sdim	      last_offset = debug_information [i].loc_offsets [j];
2349214082Sdim	    }
2350214082Sdim	}
2351214082Sdim    }
2352214082Sdim
2353214082Sdim  if (!use_debug_info)
2354214082Sdim    /* FIXME: Should we handle this case?  */
2355214082Sdim    error (_("Location lists in .debug_info section aren't in ascending order!\n"));
2356214082Sdim
2357214082Sdim  if (!seen_first_offset)
2358214082Sdim    error (_("No location lists in .debug_info section!\n"));
2359214082Sdim
2360214082Sdim  /* DWARF sections under Mach-O have non-zero addresses.  */
2361214634Sdim  if (debug_information [first].num_loc_offsets > 0
2362214634Sdim      && debug_information [first].loc_offsets [0] != section->address)
2363214082Sdim    warn (_("Location lists in %s section start at 0x%lx\n"),
2364214082Sdim	  section->name, debug_information [first].loc_offsets [0]);
2365214082Sdim
2366214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2367214082Sdim  printf (_("    Offset   Begin    End      Expression\n"));
2368214082Sdim
2369214082Sdim  seen_first_offset = 0;
2370214082Sdim  for (i = first; i < num_debug_info_entries; i++)
2371214082Sdim    {
2372214082Sdim      unsigned long begin;
2373214082Sdim      unsigned long end;
2374214082Sdim      unsigned short length;
2375214082Sdim      unsigned long offset;
2376214082Sdim      unsigned int pointer_size;
2377214082Sdim      unsigned long cu_offset;
2378214082Sdim      unsigned long base_address;
2379214082Sdim      int need_frame_base;
2380214082Sdim      int has_frame_base;
2381214082Sdim
2382214082Sdim      pointer_size = debug_information [i].pointer_size;
2383214082Sdim      cu_offset = debug_information [i].cu_offset;
2384214082Sdim
2385214082Sdim      for (j = 0; j < debug_information [i].num_loc_offsets; j++)
2386214082Sdim	{
2387214082Sdim	  has_frame_base = debug_information [i].have_frame_base [j];
2388214082Sdim	  /* DWARF sections under Mach-O have non-zero addresses.  */
2389214082Sdim	  offset = debug_information [i].loc_offsets [j] - section->address;
2390214082Sdim	  next = section_begin + offset;
2391214082Sdim	  base_address = debug_information [i].base_address;
2392214082Sdim
2393214082Sdim	  if (!seen_first_offset)
2394214082Sdim	    seen_first_offset = 1;
2395214082Sdim	  else
2396214082Sdim	    {
2397214082Sdim	      if (start < next)
2398214082Sdim		warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
2399214082Sdim		      (long)(start - section_begin), (long)(next - section_begin));
2400214082Sdim	      else if (start > next)
2401214082Sdim		warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
2402214082Sdim		      (long)(start - section_begin), (long)(next - section_begin));
2403214082Sdim	    }
2404214082Sdim	  start = next;
2405214082Sdim
2406214082Sdim	  if (offset >= bytes)
2407214082Sdim	    {
2408214082Sdim	      warn (_("Offset 0x%lx is bigger than .debug_loc section size.\n"),
2409214082Sdim		    offset);
2410214082Sdim	      continue;
2411214082Sdim	    }
2412214082Sdim
2413214082Sdim	  while (1)
2414214082Sdim	    {
2415214082Sdim	      if (start + 2 * pointer_size > section_end)
2416214082Sdim		{
2417214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2418214082Sdim			offset);
2419214082Sdim		  break;
2420214082Sdim		}
2421214082Sdim
2422214082Sdim	      begin = byte_get (start, pointer_size);
2423214082Sdim	      start += pointer_size;
2424214082Sdim	      end = byte_get (start, pointer_size);
2425214082Sdim	      start += pointer_size;
2426214082Sdim
2427214082Sdim	      if (begin == 0 && end == 0)
2428214082Sdim		{
2429214082Sdim		  printf (_("    %8.8lx <End of list>\n"), offset);
2430214082Sdim		  break;
2431214082Sdim		}
2432214082Sdim
2433214082Sdim	      /* Check base address specifiers.  */
2434214082Sdim	      if (begin == -1UL && end != -1UL)
2435214082Sdim		{
2436214082Sdim		  base_address = end;
2437214082Sdim		  printf (_("    %8.8lx %8.8lx %8.8lx (base address)\n"),
2438214082Sdim			  offset, begin, end);
2439214082Sdim		  continue;
2440214082Sdim		}
2441214082Sdim
2442214082Sdim	      if (start + 2 > section_end)
2443214082Sdim		{
2444214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2445214082Sdim			offset);
2446214082Sdim		  break;
2447214082Sdim		}
2448214082Sdim
2449214082Sdim	      length = byte_get (start, 2);
2450214082Sdim	      start += 2;
2451214082Sdim
2452214082Sdim	      if (start + length > section_end)
2453214082Sdim		{
2454214082Sdim		  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
2455214082Sdim			offset);
2456214082Sdim		  break;
2457214082Sdim		}
2458214082Sdim
2459214082Sdim	      printf ("    %8.8lx %8.8lx %8.8lx (",
2460214082Sdim		      offset, begin + base_address, end + base_address);
2461214082Sdim	      need_frame_base = decode_location_expression (start,
2462214082Sdim							    pointer_size,
2463214082Sdim							    length,
2464214082Sdim							    cu_offset);
2465214082Sdim	      putchar (')');
2466214082Sdim
2467214082Sdim	      if (need_frame_base && !has_frame_base)
2468214082Sdim		printf (_(" [without DW_AT_frame_base]"));
2469214082Sdim
2470214082Sdim	      if (begin == end)
2471214082Sdim		fputs (_(" (start == end)"), stdout);
2472214082Sdim	      else if (begin > end)
2473214082Sdim		fputs (_(" (start > end)"), stdout);
2474214082Sdim
2475214082Sdim	      putchar ('\n');
2476214082Sdim
2477214082Sdim	      start += length;
2478214082Sdim	    }
2479214082Sdim	}
2480214082Sdim    }
2481214082Sdim  return 1;
2482214082Sdim}
2483214082Sdim
2484214082Sdimstatic int
2485214082Sdimdisplay_debug_str (struct dwarf_section *section,
2486214082Sdim		   void *file ATTRIBUTE_UNUSED)
2487214082Sdim{
2488214082Sdim  unsigned char *start = section->start;
2489214082Sdim  unsigned long bytes = section->size;
2490214082Sdim  dwarf_vma addr = section->address;
2491214082Sdim
2492214082Sdim  if (bytes == 0)
2493214082Sdim    {
2494214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2495214082Sdim      return 0;
2496214082Sdim    }
2497214082Sdim
2498214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2499214082Sdim
2500214082Sdim  while (bytes)
2501214082Sdim    {
2502214082Sdim      int j;
2503214082Sdim      int k;
2504214082Sdim      int lbytes;
2505214082Sdim
2506214082Sdim      lbytes = (bytes > 16 ? 16 : bytes);
2507214082Sdim
2508214082Sdim      printf ("  0x%8.8lx ", (unsigned long) addr);
2509214082Sdim
2510214082Sdim      for (j = 0; j < 16; j++)
2511214082Sdim	{
2512214082Sdim	  if (j < lbytes)
2513214082Sdim	    printf ("%2.2x", start[j]);
2514214082Sdim	  else
2515214082Sdim	    printf ("  ");
2516214082Sdim
2517214082Sdim	  if ((j & 3) == 3)
2518214082Sdim	    printf (" ");
2519214082Sdim	}
2520214082Sdim
2521214082Sdim      for (j = 0; j < lbytes; j++)
2522214082Sdim	{
2523214082Sdim	  k = start[j];
2524214082Sdim	  if (k >= ' ' && k < 0x80)
2525214082Sdim	    printf ("%c", k);
2526214082Sdim	  else
2527214082Sdim	    printf (".");
2528214082Sdim	}
2529214082Sdim
2530214082Sdim      putchar ('\n');
2531214082Sdim
2532214082Sdim      start += lbytes;
2533214082Sdim      addr  += lbytes;
2534214082Sdim      bytes -= lbytes;
2535214082Sdim    }
2536214082Sdim
2537214082Sdim  putchar ('\n');
2538214082Sdim
2539214082Sdim  return 1;
2540214082Sdim}
2541214082Sdim
2542214082Sdimstatic int
2543214082Sdimdisplay_debug_info (struct dwarf_section *section, void *file)
2544214082Sdim{
2545214082Sdim  return process_debug_info (section, file, 0);
2546214082Sdim}
2547214082Sdim
2548214082Sdim
2549214082Sdimstatic int
2550214082Sdimdisplay_debug_aranges (struct dwarf_section *section,
2551214082Sdim		       void *file ATTRIBUTE_UNUSED)
2552214082Sdim{
2553214082Sdim  unsigned char *start = section->start;
2554214082Sdim  unsigned char *end = start + section->size;
2555214082Sdim
2556214082Sdim  printf (_("The section %s contains:\n\n"), section->name);
2557214082Sdim
2558214082Sdim  while (start < end)
2559214082Sdim    {
2560214082Sdim      unsigned char *hdrptr;
2561214082Sdim      DWARF2_Internal_ARange arange;
2562214082Sdim      unsigned char *ranges;
2563214082Sdim      unsigned long length;
2564214082Sdim      unsigned long address;
2565214634Sdim      unsigned char address_size;
2566214082Sdim      int excess;
2567214082Sdim      int offset_size;
2568214082Sdim      int initial_length_size;
2569214082Sdim
2570214082Sdim      hdrptr = start;
2571214082Sdim
2572214082Sdim      arange.ar_length = byte_get (hdrptr, 4);
2573214082Sdim      hdrptr += 4;
2574214082Sdim
2575214082Sdim      if (arange.ar_length == 0xffffffff)
2576214082Sdim	{
2577214082Sdim	  arange.ar_length = byte_get (hdrptr, 8);
2578214082Sdim	  hdrptr += 8;
2579214082Sdim	  offset_size = 8;
2580214082Sdim	  initial_length_size = 12;
2581214082Sdim	}
2582214082Sdim      else
2583214082Sdim	{
2584214082Sdim	  offset_size = 4;
2585214082Sdim	  initial_length_size = 4;
2586214082Sdim	}
2587214082Sdim
2588214082Sdim      arange.ar_version = byte_get (hdrptr, 2);
2589214082Sdim      hdrptr += 2;
2590214082Sdim
2591214082Sdim      arange.ar_info_offset = byte_get (hdrptr, offset_size);
2592214082Sdim      hdrptr += offset_size;
2593214082Sdim
2594214082Sdim      arange.ar_pointer_size = byte_get (hdrptr, 1);
2595214082Sdim      hdrptr += 1;
2596214082Sdim
2597214082Sdim      arange.ar_segment_size = byte_get (hdrptr, 1);
2598214082Sdim      hdrptr += 1;
2599214082Sdim
2600214082Sdim      if (arange.ar_version != 2 && arange.ar_version != 3)
2601214082Sdim	{
2602214082Sdim	  warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
2603214082Sdim	  break;
2604214082Sdim	}
2605214082Sdim
2606214082Sdim      printf (_("  Length:                   %ld\n"), arange.ar_length);
2607214082Sdim      printf (_("  Version:                  %d\n"), arange.ar_version);
2608214082Sdim      printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
2609214082Sdim      printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
2610214082Sdim      printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
2611214082Sdim
2612214634Sdim      address_size = arange.ar_pointer_size + arange.ar_segment_size;
2613214082Sdim
2614214634Sdim      /* The DWARF spec does not require that the address size be a power
2615214634Sdim	 of two, but we do.  This will have to change if we ever encounter
2616214634Sdim	 an uneven architecture.  */
2617214634Sdim      if ((address_size & (address_size - 1)) != 0)
2618214634Sdim	{
2619214634Sdim	  warn (_("Pointer size + Segment size is not a power of two.\n"));
2620214634Sdim	  break;
2621214634Sdim	}
2622214634Sdim
2623214634Sdim      if (address_size > 4)
2624214634Sdim	printf (_("\n    Address            Length\n"));
2625214634Sdim      else
2626214634Sdim	printf (_("\n    Address    Length\n"));
2627214634Sdim
2628214082Sdim      ranges = hdrptr;
2629214082Sdim
2630214634Sdim      /* Must pad to an alignment boundary that is twice the address size.  */
2631214634Sdim      excess = (hdrptr - start) % (2 * address_size);
2632214082Sdim      if (excess)
2633214634Sdim	ranges += (2 * address_size) - excess;
2634214082Sdim
2635214082Sdim      start += arange.ar_length + initial_length_size;
2636214082Sdim
2637214634Sdim      while (ranges + 2 * address_size <= start)
2638214082Sdim	{
2639214634Sdim	  address = byte_get (ranges, address_size);
2640214082Sdim
2641214634Sdim	  ranges += address_size;
2642214082Sdim
2643214634Sdim	  length  = byte_get (ranges, address_size);
2644214082Sdim
2645214634Sdim	  ranges += address_size;
2646214082Sdim
2647214634Sdim	  if (address_size > 4)
2648214634Sdim	    printf ("    0x%16.16lx 0x%lx\n", address, length);
2649214634Sdim	  else
2650214634Sdim	    printf ("    0x%8.8lx 0x%lx\n", address, length);
2651214082Sdim	}
2652214082Sdim    }
2653214082Sdim
2654214082Sdim  printf ("\n");
2655214082Sdim
2656214082Sdim  return 1;
2657214082Sdim}
2658214082Sdim
2659214082Sdimstatic int
2660214082Sdimdisplay_debug_ranges (struct dwarf_section *section,
2661214082Sdim		      void *file ATTRIBUTE_UNUSED)
2662214082Sdim{
2663214082Sdim  unsigned char *start = section->start;
2664214082Sdim  unsigned char *section_end;
2665214082Sdim  unsigned long bytes;
2666214082Sdim  unsigned char *section_begin = start;
2667214082Sdim  unsigned int num_range_list = 0;
2668214082Sdim  unsigned long last_offset = 0;
2669214082Sdim  unsigned int first = 0;
2670214082Sdim  unsigned int i;
2671214082Sdim  unsigned int j;
2672214082Sdim  int seen_first_offset = 0;
2673214082Sdim  int use_debug_info = 1;
2674214082Sdim  unsigned char *next;
2675214082Sdim
2676214082Sdim  bytes = section->size;
2677214082Sdim  section_end = start + bytes;
2678214082Sdim
2679214082Sdim  if (bytes == 0)
2680214082Sdim    {
2681214082Sdim      printf (_("\nThe %s section is empty.\n"), section->name);
2682214082Sdim      return 0;
2683214082Sdim    }
2684214082Sdim
2685214082Sdim  load_debug_info (file);
2686214082Sdim
2687214082Sdim  /* Check the order of range list in .debug_info section. If
2688214082Sdim     offsets of range lists are in the ascending order, we can
2689214082Sdim     use `debug_information' directly.  */
2690214082Sdim  for (i = 0; i < num_debug_info_entries; i++)
2691214082Sdim    {
2692214082Sdim      unsigned int num;
2693214082Sdim
2694214082Sdim      num = debug_information [i].num_range_lists;
2695214082Sdim      num_range_list += num;
2696214082Sdim
2697214082Sdim      /* Check if we can use `debug_information' directly.  */
2698214082Sdim      if (use_debug_info && num != 0)
2699214082Sdim	{
2700214082Sdim	  if (!seen_first_offset)
2701214082Sdim	    {
2702214082Sdim	      /* This is the first range list.  */
2703214082Sdim	      last_offset = debug_information [i].range_lists [0];
2704214082Sdim	      first = i;
2705214082Sdim	      seen_first_offset = 1;
2706214082Sdim	      j = 1;
2707214082Sdim	    }
2708214082Sdim	  else
2709214082Sdim	    j = 0;
2710214082Sdim
2711214082Sdim	  for (; j < num; j++)
2712214082Sdim	    {
2713214082Sdim	      if (last_offset >
2714214082Sdim		  debug_information [i].range_lists [j])
2715214082Sdim		{
2716214082Sdim		  use_debug_info = 0;
2717214082Sdim		  break;
2718214082Sdim		}
2719214082Sdim	      last_offset = debug_information [i].range_lists [j];
2720214082Sdim	    }
2721214082Sdim	}
2722214082Sdim    }
2723214082Sdim
2724214082Sdim  if (!use_debug_info)
2725214082Sdim    /* FIXME: Should we handle this case?  */
2726214082Sdim    error (_("Range lists in .debug_info section aren't in ascending order!\n"));
2727214082Sdim
2728214082Sdim  if (!seen_first_offset)
2729214082Sdim    error (_("No range lists in .debug_info section!\n"));
2730214082Sdim
2731214082Sdim  /* DWARF sections under Mach-O have non-zero addresses.  */
2732214634Sdim  if (debug_information [first].num_range_lists > 0
2733214634Sdim      && debug_information [first].range_lists [0] != section->address)
2734214082Sdim    warn (_("Range lists in %s section start at 0x%lx\n"),
2735214082Sdim	  section->name, debug_information [first].range_lists [0]);
2736214082Sdim
2737214082Sdim  printf (_("Contents of the %s section:\n\n"), section->name);
2738214082Sdim  printf (_("    Offset   Begin    End\n"));
2739214082Sdim
2740214082Sdim  seen_first_offset = 0;
2741214082Sdim  for (i = first; i < num_debug_info_entries; i++)
2742214082Sdim    {
2743214082Sdim      unsigned long begin;
2744214082Sdim      unsigned long end;
2745214082Sdim      unsigned long offset;
2746214082Sdim      unsigned int pointer_size;
2747214082Sdim      unsigned long base_address;
2748214082Sdim
2749214082Sdim      pointer_size = debug_information [i].pointer_size;
2750214082Sdim
2751214082Sdim      for (j = 0; j < debug_information [i].num_range_lists; j++)
2752214082Sdim	{
2753214082Sdim	  /* DWARF sections under Mach-O have non-zero addresses.  */
2754214082Sdim	  offset = debug_information [i].range_lists [j] - section->address;
2755214082Sdim	  next = section_begin + offset;
2756214082Sdim	  base_address = debug_information [i].base_address;
2757214082Sdim
2758214082Sdim	  if (!seen_first_offset)
2759214082Sdim	    seen_first_offset = 1;
2760214082Sdim	  else
2761214082Sdim	    {
2762214082Sdim	      if (start < next)
2763214082Sdim		warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
2764214082Sdim		      (long)(start - section_begin),
2765214082Sdim		      (long)(next - section_begin), section->name);
2766214082Sdim	      else if (start > next)
2767214082Sdim		warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
2768214082Sdim		      (long)(start - section_begin),
2769214082Sdim		      (long)(next - section_begin), section->name);
2770214082Sdim	    }
2771214082Sdim	  start = next;
2772214082Sdim
2773214082Sdim	  while (1)
2774214082Sdim	    {
2775214082Sdim	      begin = byte_get (start, pointer_size);
2776214082Sdim	      start += pointer_size;
2777214082Sdim	      end = byte_get (start, pointer_size);
2778214082Sdim	      start += pointer_size;
2779214082Sdim
2780214082Sdim	      if (begin == 0 && end == 0)
2781214082Sdim		{
2782214082Sdim		  printf (_("    %8.8lx <End of list>\n"), offset);
2783214082Sdim		  break;
2784214082Sdim		}
2785214082Sdim
2786214082Sdim	      /* Check base address specifiers.  */
2787214082Sdim	      if (begin == -1UL && end != -1UL)
2788214082Sdim		{
2789214082Sdim		  base_address = end;
2790214082Sdim		  printf ("    %8.8lx %8.8lx %8.8lx (base address)\n",
2791214082Sdim			  offset, begin, end);
2792214082Sdim		  continue;
2793214082Sdim		}
2794214082Sdim
2795214082Sdim	      printf ("    %8.8lx %8.8lx %8.8lx",
2796214082Sdim		      offset, begin + base_address, end + base_address);
2797214082Sdim
2798214082Sdim	      if (begin == end)
2799214082Sdim		fputs (_(" (start == end)"), stdout);
2800214082Sdim	      else if (begin > end)
2801214082Sdim		fputs (_(" (start > end)"), stdout);
2802214082Sdim
2803214082Sdim	      putchar ('\n');
2804214082Sdim	    }
2805214082Sdim	}
2806214082Sdim    }
2807214082Sdim  putchar ('\n');
2808214082Sdim  return 1;
2809214082Sdim}
2810214082Sdim
2811214082Sdimtypedef struct Frame_Chunk
2812214082Sdim{
2813214082Sdim  struct Frame_Chunk *next;
2814214082Sdim  unsigned char *chunk_start;
2815214082Sdim  int ncols;
2816214082Sdim  /* DW_CFA_{undefined,same_value,offset,register,unreferenced}  */
2817214082Sdim  short int *col_type;
2818214082Sdim  int *col_offset;
2819214082Sdim  char *augmentation;
2820214082Sdim  unsigned int code_factor;
2821214082Sdim  int data_factor;
2822214082Sdim  unsigned long pc_begin;
2823214082Sdim  unsigned long pc_range;
2824214082Sdim  int cfa_reg;
2825214082Sdim  int cfa_offset;
2826214082Sdim  int ra;
2827214082Sdim  unsigned char fde_encoding;
2828214082Sdim  unsigned char cfa_exp;
2829214082Sdim}
2830214082SdimFrame_Chunk;
2831214082Sdim
2832214082Sdim/* A marker for a col_type that means this column was never referenced
2833214082Sdim   in the frame info.  */
2834214082Sdim#define DW_CFA_unreferenced (-1)
2835214082Sdim
2836214082Sdimstatic void
2837214082Sdimframe_need_space (Frame_Chunk *fc, int reg)
2838214082Sdim{
2839214082Sdim  int prev = fc->ncols;
2840214082Sdim
2841214082Sdim  if (reg < fc->ncols)
2842214082Sdim    return;
2843214082Sdim
2844214082Sdim  fc->ncols = reg + 1;
2845214082Sdim  fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
2846214082Sdim  fc->col_offset = xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
2847214082Sdim
2848214082Sdim  while (prev < fc->ncols)
2849214082Sdim    {
2850214082Sdim      fc->col_type[prev] = DW_CFA_unreferenced;
2851214082Sdim      fc->col_offset[prev] = 0;
2852214082Sdim      prev++;
2853214082Sdim    }
2854214082Sdim}
2855214082Sdim
2856214082Sdimstatic void
2857214082Sdimframe_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs)
2858214082Sdim{
2859214082Sdim  int r;
2860214082Sdim  char tmp[100];
2861214082Sdim
2862214082Sdim  if (*max_regs < fc->ncols)
2863214082Sdim    *max_regs = fc->ncols;
2864214082Sdim
2865214082Sdim  if (*need_col_headers)
2866214082Sdim    {
2867214082Sdim      *need_col_headers = 0;
2868214082Sdim
2869214082Sdim      printf ("   LOC   CFA      ");
2870214082Sdim
2871214082Sdim      for (r = 0; r < *max_regs; r++)
2872214082Sdim	if (fc->col_type[r] != DW_CFA_unreferenced)
2873214082Sdim	  {
2874214082Sdim	    if (r == fc->ra)
2875214082Sdim	      printf ("ra   ");
2876214082Sdim	    else
2877214082Sdim	      printf ("r%-4d", r);
2878214082Sdim	  }
2879214082Sdim
2880214082Sdim      printf ("\n");
2881214082Sdim    }
2882214082Sdim
2883214082Sdim  printf ("%08lx ", fc->pc_begin);
2884214082Sdim  if (fc->cfa_exp)
2885214082Sdim    strcpy (tmp, "exp");
2886214082Sdim  else
2887214082Sdim    sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
2888214082Sdim  printf ("%-8s ", tmp);
2889214082Sdim
2890214082Sdim  for (r = 0; r < fc->ncols; r++)
2891214082Sdim    {
2892214082Sdim      if (fc->col_type[r] != DW_CFA_unreferenced)
2893214082Sdim	{
2894214082Sdim	  switch (fc->col_type[r])
2895214082Sdim	    {
2896214082Sdim	    case DW_CFA_undefined:
2897214082Sdim	      strcpy (tmp, "u");
2898214082Sdim	      break;
2899214082Sdim	    case DW_CFA_same_value:
2900214082Sdim	      strcpy (tmp, "s");
2901214082Sdim	      break;
2902214082Sdim	    case DW_CFA_offset:
2903214082Sdim	      sprintf (tmp, "c%+d", fc->col_offset[r]);
2904214082Sdim	      break;
2905214082Sdim	    case DW_CFA_val_offset:
2906214082Sdim	      sprintf (tmp, "v%+d", fc->col_offset[r]);
2907214082Sdim	      break;
2908214082Sdim	    case DW_CFA_register:
2909214082Sdim	      sprintf (tmp, "r%d", fc->col_offset[r]);
2910214082Sdim	      break;
2911214082Sdim	    case DW_CFA_expression:
2912214082Sdim	      strcpy (tmp, "exp");
2913214082Sdim	      break;
2914214082Sdim	    case DW_CFA_val_expression:
2915214082Sdim	      strcpy (tmp, "vexp");
2916214082Sdim	      break;
2917214082Sdim	    default:
2918214082Sdim	      strcpy (tmp, "n/a");
2919214082Sdim	      break;
2920214082Sdim	    }
2921214082Sdim	  printf ("%-5s", tmp);
2922214082Sdim	}
2923214082Sdim    }
2924214082Sdim  printf ("\n");
2925214082Sdim}
2926214082Sdim
2927214082Sdimstatic int
2928214082Sdimsize_of_encoded_value (int encoding)
2929214082Sdim{
2930214082Sdim  switch (encoding & 0x7)
2931214082Sdim    {
2932214082Sdim    default:	/* ??? */
2933214082Sdim    case 0:	return eh_addr_size;
2934214082Sdim    case 2:	return 2;
2935214082Sdim    case 3:	return 4;
2936214082Sdim    case 4:	return 8;
2937214082Sdim    }
2938214082Sdim}
2939214082Sdim
2940214082Sdimstatic dwarf_vma
2941214082Sdimget_encoded_value (unsigned char *data, int encoding)
2942214082Sdim{
2943214082Sdim  int size = size_of_encoded_value (encoding);
2944214634Sdim
2945214082Sdim  if (encoding & DW_EH_PE_signed)
2946214082Sdim    return byte_get_signed (data, size);
2947214082Sdim  else
2948214082Sdim    return byte_get (data, size);
2949214082Sdim}
2950214082Sdim
2951214082Sdim#define GET(N)	byte_get (start, N); start += N
2952214082Sdim#define LEB()	read_leb128 (start, & length_return, 0); start += length_return
2953214082Sdim#define SLEB()	read_leb128 (start, & length_return, 1); start += length_return
2954214082Sdim
2955214082Sdimstatic int
2956214082Sdimdisplay_debug_frames (struct dwarf_section *section,
2957214082Sdim		      void *file ATTRIBUTE_UNUSED)
2958214082Sdim{
2959214082Sdim  unsigned char *start = section->start;
2960214082Sdim  unsigned char *end = start + section->size;
2961214082Sdim  unsigned char *section_start = start;
2962214082Sdim  Frame_Chunk *chunks = 0;
2963214082Sdim  Frame_Chunk *remembered_state = 0;
2964214082Sdim  Frame_Chunk *rs;
2965214082Sdim  int is_eh = strcmp (section->name, ".eh_frame") == 0;
2966214082Sdim  unsigned int length_return;
2967214082Sdim  int max_regs = 0;
2968214082Sdim
2969214082Sdim  printf (_("The section %s contains:\n"), section->name);
2970214082Sdim
2971214082Sdim  while (start < end)
2972214082Sdim    {
2973214082Sdim      unsigned char *saved_start;
2974214082Sdim      unsigned char *block_end;
2975214082Sdim      unsigned long length;
2976214082Sdim      unsigned long cie_id;
2977214082Sdim      Frame_Chunk *fc;
2978214082Sdim      Frame_Chunk *cie;
2979214082Sdim      int need_col_headers = 1;
2980214082Sdim      unsigned char *augmentation_data = NULL;
2981214082Sdim      unsigned long augmentation_data_len = 0;
2982214082Sdim      int encoded_ptr_size = eh_addr_size;
2983214082Sdim      int offset_size;
2984214082Sdim      int initial_length_size;
2985214082Sdim
2986214082Sdim      saved_start = start;
2987214082Sdim      length = byte_get (start, 4); start += 4;
2988214082Sdim
2989214082Sdim      if (length == 0)
2990214082Sdim	{
2991214082Sdim	  printf ("\n%08lx ZERO terminator\n\n",
2992214082Sdim		    (unsigned long)(saved_start - section_start));
2993214634Sdim	  continue;
2994214082Sdim	}
2995214082Sdim
2996214082Sdim      if (length == 0xffffffff)
2997214082Sdim	{
2998214082Sdim	  length = byte_get (start, 8);
2999214082Sdim	  start += 8;
3000214082Sdim	  offset_size = 8;
3001214082Sdim	  initial_length_size = 12;
3002214082Sdim	}
3003214082Sdim      else
3004214082Sdim	{
3005214082Sdim	  offset_size = 4;
3006214082Sdim	  initial_length_size = 4;
3007214082Sdim	}
3008214082Sdim
3009214082Sdim      block_end = saved_start + length + initial_length_size;
3010214634Sdim      if (block_end > end)
3011214634Sdim	{
3012214634Sdim	  warn ("Invalid length %#08lx in FDE at %#08lx\n",
3013214634Sdim		length, (unsigned long)(saved_start - section_start));
3014214634Sdim	  block_end = end;
3015214634Sdim	}
3016214082Sdim      cie_id = byte_get (start, offset_size); start += offset_size;
3017214082Sdim
3018214082Sdim      if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
3019214082Sdim	{
3020214082Sdim	  int version;
3021214082Sdim
3022214082Sdim	  fc = xmalloc (sizeof (Frame_Chunk));
3023214082Sdim	  memset (fc, 0, sizeof (Frame_Chunk));
3024214082Sdim
3025214082Sdim	  fc->next = chunks;
3026214082Sdim	  chunks = fc;
3027214082Sdim	  fc->chunk_start = saved_start;
3028214082Sdim	  fc->ncols = 0;
3029214082Sdim	  fc->col_type = xmalloc (sizeof (short int));
3030214082Sdim	  fc->col_offset = xmalloc (sizeof (int));
3031214082Sdim	  frame_need_space (fc, max_regs-1);
3032214082Sdim
3033214082Sdim	  version = *start++;
3034214082Sdim
3035214082Sdim	  fc->augmentation = (char *) start;
3036214082Sdim	  start = (unsigned char *) strchr ((char *) start, '\0') + 1;
3037214082Sdim
3038214082Sdim	  if (fc->augmentation[0] == 'z')
3039214082Sdim	    {
3040214082Sdim	      fc->code_factor = LEB ();
3041214082Sdim	      fc->data_factor = SLEB ();
3042214082Sdim	      if (version == 1)
3043214082Sdim		{
3044214082Sdim		  fc->ra = GET (1);
3045214082Sdim		}
3046214082Sdim	      else
3047214082Sdim		{
3048214082Sdim		  fc->ra = LEB ();
3049214082Sdim		}
3050214082Sdim	      augmentation_data_len = LEB ();
3051214082Sdim	      augmentation_data = start;
3052214082Sdim	      start += augmentation_data_len;
3053214082Sdim	    }
3054214082Sdim	  else if (strcmp (fc->augmentation, "eh") == 0)
3055214082Sdim	    {
3056214082Sdim	      start += eh_addr_size;
3057214082Sdim	      fc->code_factor = LEB ();
3058214082Sdim	      fc->data_factor = SLEB ();
3059214082Sdim	      if (version == 1)
3060214082Sdim		{
3061214082Sdim		  fc->ra = GET (1);
3062214082Sdim		}
3063214082Sdim	      else
3064214082Sdim		{
3065214082Sdim		  fc->ra = LEB ();
3066214082Sdim		}
3067214082Sdim	    }
3068214082Sdim	  else
3069214082Sdim	    {
3070214082Sdim	      fc->code_factor = LEB ();
3071214082Sdim	      fc->data_factor = SLEB ();
3072214082Sdim	      if (version == 1)
3073214082Sdim		{
3074214082Sdim		  fc->ra = GET (1);
3075214082Sdim		}
3076214082Sdim	      else
3077214082Sdim		{
3078214082Sdim		  fc->ra = LEB ();
3079214082Sdim		}
3080214082Sdim	    }
3081214082Sdim	  cie = fc;
3082214082Sdim
3083214082Sdim	  if (do_debug_frames_interp)
3084214082Sdim	    printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n",
3085214082Sdim		    (unsigned long)(saved_start - section_start), length, cie_id,
3086214082Sdim		    fc->augmentation, fc->code_factor, fc->data_factor,
3087214082Sdim		    fc->ra);
3088214082Sdim	  else
3089214082Sdim	    {
3090214082Sdim	      printf ("\n%08lx %08lx %08lx CIE\n",
3091214082Sdim		      (unsigned long)(saved_start - section_start), length, cie_id);
3092214082Sdim	      printf ("  Version:               %d\n", version);
3093214082Sdim	      printf ("  Augmentation:          \"%s\"\n", fc->augmentation);
3094214082Sdim	      printf ("  Code alignment factor: %u\n", fc->code_factor);
3095214082Sdim	      printf ("  Data alignment factor: %d\n", fc->data_factor);
3096214082Sdim	      printf ("  Return address column: %d\n", fc->ra);
3097214082Sdim
3098214082Sdim	      if (augmentation_data_len)
3099214082Sdim		{
3100214082Sdim		  unsigned long i;
3101214082Sdim		  printf ("  Augmentation data:    ");
3102214082Sdim		  for (i = 0; i < augmentation_data_len; ++i)
3103214082Sdim		    printf (" %02x", augmentation_data[i]);
3104214082Sdim		  putchar ('\n');
3105214082Sdim		}
3106214082Sdim	      putchar ('\n');
3107214082Sdim	    }
3108214082Sdim
3109214082Sdim	  if (augmentation_data_len)
3110214082Sdim	    {
3111214082Sdim	      unsigned char *p, *q;
3112214082Sdim	      p = (unsigned char *) fc->augmentation + 1;
3113214082Sdim	      q = augmentation_data;
3114214082Sdim
3115214082Sdim	      while (1)
3116214082Sdim		{
3117214082Sdim		  if (*p == 'L')
3118214082Sdim		    q++;
3119214082Sdim		  else if (*p == 'P')
3120214082Sdim		    q += 1 + size_of_encoded_value (*q);
3121214082Sdim		  else if (*p == 'R')
3122214082Sdim		    fc->fde_encoding = *q++;
3123214082Sdim		  else
3124214082Sdim		    break;
3125214082Sdim		  p++;
3126214082Sdim		}
3127214082Sdim
3128214082Sdim	      if (fc->fde_encoding)
3129214082Sdim		encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
3130214082Sdim	    }
3131214082Sdim
3132214082Sdim	  frame_need_space (fc, fc->ra);
3133214082Sdim	}
3134214082Sdim      else
3135214082Sdim	{
3136214082Sdim	  unsigned char *look_for;
3137214082Sdim	  static Frame_Chunk fde_fc;
3138214082Sdim
3139214082Sdim	  fc = & fde_fc;
3140214082Sdim	  memset (fc, 0, sizeof (Frame_Chunk));
3141214082Sdim
3142214082Sdim	  look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
3143214082Sdim
3144214082Sdim	  for (cie = chunks; cie ; cie = cie->next)
3145214082Sdim	    if (cie->chunk_start == look_for)
3146214082Sdim	      break;
3147214082Sdim
3148214082Sdim	  if (!cie)
3149214082Sdim	    {
3150214634Sdim	      warn ("Invalid CIE pointer %#08lx in FDE at %#08lx\n",
3151214082Sdim		    cie_id, (unsigned long)(saved_start - section_start));
3152214082Sdim	      fc->ncols = 0;
3153214082Sdim	      fc->col_type = xmalloc (sizeof (short int));
3154214082Sdim	      fc->col_offset = xmalloc (sizeof (int));
3155214082Sdim	      frame_need_space (fc, max_regs - 1);
3156214082Sdim	      cie = fc;
3157214082Sdim	      fc->augmentation = "";
3158214082Sdim	      fc->fde_encoding = 0;
3159214082Sdim	    }
3160214082Sdim	  else
3161214082Sdim	    {
3162214082Sdim	      fc->ncols = cie->ncols;
3163214082Sdim	      fc->col_type = xcmalloc (fc->ncols, sizeof (short int));
3164214082Sdim	      fc->col_offset = xcmalloc (fc->ncols, sizeof (int));
3165214082Sdim	      memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
3166214082Sdim	      memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
3167214082Sdim	      fc->augmentation = cie->augmentation;
3168214082Sdim	      fc->code_factor = cie->code_factor;
3169214082Sdim	      fc->data_factor = cie->data_factor;
3170214082Sdim	      fc->cfa_reg = cie->cfa_reg;
3171214082Sdim	      fc->cfa_offset = cie->cfa_offset;
3172214082Sdim	      fc->ra = cie->ra;
3173214082Sdim	      frame_need_space (fc, max_regs-1);
3174214082Sdim	      fc->fde_encoding = cie->fde_encoding;
3175214082Sdim	    }
3176214082Sdim
3177214082Sdim	  if (fc->fde_encoding)
3178214082Sdim	    encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
3179214082Sdim
3180214082Sdim	  fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
3181214082Sdim	  if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
3182214082Sdim	      /* Don't adjust for relocatable file since there's
3183214082Sdim		 invariably a pcrel reloc here, which we haven't
3184214082Sdim		 applied.  */
3185214082Sdim	      && !is_relocatable)
3186214082Sdim	    fc->pc_begin += section->address + (start - section_start);
3187214082Sdim	  start += encoded_ptr_size;
3188214082Sdim	  fc->pc_range = byte_get (start, encoded_ptr_size);
3189214082Sdim	  start += encoded_ptr_size;
3190214082Sdim
3191214082Sdim	  if (cie->augmentation[0] == 'z')
3192214082Sdim	    {
3193214082Sdim	      augmentation_data_len = LEB ();
3194214082Sdim	      augmentation_data = start;
3195214082Sdim	      start += augmentation_data_len;
3196214082Sdim	    }
3197214082Sdim
3198214082Sdim	  printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
3199214082Sdim		  (unsigned long)(saved_start - section_start), length, cie_id,
3200214082Sdim		  (unsigned long)(cie->chunk_start - section_start),
3201214082Sdim		  fc->pc_begin, fc->pc_begin + fc->pc_range);
3202214082Sdim	  if (! do_debug_frames_interp && augmentation_data_len)
3203214082Sdim	    {
3204214082Sdim	      unsigned long i;
3205214082Sdim
3206214082Sdim	      printf ("  Augmentation data:    ");
3207214082Sdim	      for (i = 0; i < augmentation_data_len; ++i)
3208214082Sdim		printf (" %02x", augmentation_data[i]);
3209214082Sdim	      putchar ('\n');
3210214082Sdim	      putchar ('\n');
3211214082Sdim	    }
3212214082Sdim	}
3213214082Sdim
3214214082Sdim      /* At this point, fc is the current chunk, cie (if any) is set, and
3215214082Sdim	 we're about to interpret instructions for the chunk.  */
3216214082Sdim      /* ??? At present we need to do this always, since this sizes the
3217214082Sdim	 fc->col_type and fc->col_offset arrays, which we write into always.
3218214082Sdim	 We should probably split the interpreted and non-interpreted bits
3219214082Sdim	 into two different routines, since there's so much that doesn't
3220214082Sdim	 really overlap between them.  */
3221214082Sdim      if (1 || do_debug_frames_interp)
3222214082Sdim	{
3223214082Sdim	  /* Start by making a pass over the chunk, allocating storage
3224214082Sdim	     and taking note of what registers are used.  */
3225214082Sdim	  unsigned char *tmp = start;
3226214082Sdim
3227214082Sdim	  while (start < block_end)
3228214082Sdim	    {
3229214082Sdim	      unsigned op, opa;
3230214082Sdim	      unsigned long reg, tmp;
3231214082Sdim
3232214082Sdim	      op = *start++;
3233214082Sdim	      opa = op & 0x3f;
3234214082Sdim	      if (op & 0xc0)
3235214082Sdim		op &= 0xc0;
3236214082Sdim
3237214082Sdim	      /* Warning: if you add any more cases to this switch, be
3238214082Sdim		 sure to add them to the corresponding switch below.  */
3239214082Sdim	      switch (op)
3240214082Sdim		{
3241214082Sdim		case DW_CFA_advance_loc:
3242214082Sdim		  break;
3243214082Sdim		case DW_CFA_offset:
3244214082Sdim		  LEB ();
3245214082Sdim		  frame_need_space (fc, opa);
3246214082Sdim		  fc->col_type[opa] = DW_CFA_undefined;
3247214082Sdim		  break;
3248214082Sdim		case DW_CFA_restore:
3249214082Sdim		  frame_need_space (fc, opa);
3250214082Sdim		  fc->col_type[opa] = DW_CFA_undefined;
3251214082Sdim		  break;
3252214082Sdim		case DW_CFA_set_loc:
3253214082Sdim		  start += encoded_ptr_size;
3254214082Sdim		  break;
3255214082Sdim		case DW_CFA_advance_loc1:
3256214082Sdim		  start += 1;
3257214082Sdim		  break;
3258214082Sdim		case DW_CFA_advance_loc2:
3259214082Sdim		  start += 2;
3260214082Sdim		  break;
3261214082Sdim		case DW_CFA_advance_loc4:
3262214082Sdim		  start += 4;
3263214082Sdim		  break;
3264214082Sdim		case DW_CFA_offset_extended:
3265214082Sdim		case DW_CFA_val_offset:
3266214082Sdim		  reg = LEB (); LEB ();
3267214082Sdim		  frame_need_space (fc, reg);
3268214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3269214082Sdim		  break;
3270214082Sdim		case DW_CFA_restore_extended:
3271214082Sdim		  reg = LEB ();
3272214082Sdim		  frame_need_space (fc, reg);
3273214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3274214082Sdim		  break;
3275214082Sdim		case DW_CFA_undefined:
3276214082Sdim		  reg = LEB ();
3277214082Sdim		  frame_need_space (fc, reg);
3278214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3279214082Sdim		  break;
3280214082Sdim		case DW_CFA_same_value:
3281214082Sdim		  reg = LEB ();
3282214082Sdim		  frame_need_space (fc, reg);
3283214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3284214082Sdim		  break;
3285214082Sdim		case DW_CFA_register:
3286214082Sdim		  reg = LEB (); LEB ();
3287214082Sdim		  frame_need_space (fc, reg);
3288214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3289214082Sdim		  break;
3290214082Sdim		case DW_CFA_def_cfa:
3291214082Sdim		  LEB (); LEB ();
3292214082Sdim		  break;
3293214082Sdim		case DW_CFA_def_cfa_register:
3294214082Sdim		  LEB ();
3295214082Sdim		  break;
3296214082Sdim		case DW_CFA_def_cfa_offset:
3297214082Sdim		  LEB ();
3298214082Sdim		  break;
3299214082Sdim		case DW_CFA_def_cfa_expression:
3300214082Sdim		  tmp = LEB ();
3301214082Sdim		  start += tmp;
3302214082Sdim		  break;
3303214082Sdim		case DW_CFA_expression:
3304214082Sdim		case DW_CFA_val_expression:
3305214082Sdim		  reg = LEB ();
3306214082Sdim		  tmp = LEB ();
3307214082Sdim		  start += tmp;
3308214082Sdim		  frame_need_space (fc, reg);
3309214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3310214082Sdim		  break;
3311214082Sdim		case DW_CFA_offset_extended_sf:
3312214082Sdim		case DW_CFA_val_offset_sf:
3313214082Sdim		  reg = LEB (); SLEB ();
3314214082Sdim		  frame_need_space (fc, reg);
3315214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3316214082Sdim		  break;
3317214082Sdim		case DW_CFA_def_cfa_sf:
3318214082Sdim		  LEB (); SLEB ();
3319214082Sdim		  break;
3320214082Sdim		case DW_CFA_def_cfa_offset_sf:
3321214082Sdim		  SLEB ();
3322214082Sdim		  break;
3323214082Sdim		case DW_CFA_MIPS_advance_loc8:
3324214082Sdim		  start += 8;
3325214082Sdim		  break;
3326214082Sdim		case DW_CFA_GNU_args_size:
3327214082Sdim		  LEB ();
3328214082Sdim		  break;
3329214082Sdim		case DW_CFA_GNU_negative_offset_extended:
3330214082Sdim		  reg = LEB (); LEB ();
3331214082Sdim		  frame_need_space (fc, reg);
3332214082Sdim		  fc->col_type[reg] = DW_CFA_undefined;
3333214082Sdim
3334214082Sdim		default:
3335214082Sdim		  break;
3336214082Sdim		}
3337214082Sdim	    }
3338214082Sdim	  start = tmp;
3339214082Sdim	}
3340214082Sdim
3341214082Sdim      /* Now we know what registers are used, make a second pass over
3342214082Sdim	 the chunk, this time actually printing out the info.  */
3343214082Sdim
3344214082Sdim      while (start < block_end)
3345214082Sdim	{
3346214082Sdim	  unsigned op, opa;
3347214082Sdim	  unsigned long ul, reg, roffs;
3348214082Sdim	  long l, ofs;
3349214082Sdim	  dwarf_vma vma;
3350214082Sdim
3351214082Sdim	  op = *start++;
3352214082Sdim	  opa = op & 0x3f;
3353214082Sdim	  if (op & 0xc0)
3354214082Sdim	    op &= 0xc0;
3355214082Sdim
3356214082Sdim	  /* Warning: if you add any more cases to this switch, be
3357214082Sdim	     sure to add them to the corresponding switch above.  */
3358214082Sdim	  switch (op)
3359214082Sdim	    {
3360214082Sdim	    case DW_CFA_advance_loc:
3361214082Sdim	      if (do_debug_frames_interp)
3362214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3363214082Sdim	      else
3364214082Sdim		printf ("  DW_CFA_advance_loc: %d to %08lx\n",
3365214082Sdim			opa * fc->code_factor,
3366214082Sdim			fc->pc_begin + opa * fc->code_factor);
3367214082Sdim	      fc->pc_begin += opa * fc->code_factor;
3368214082Sdim	      break;
3369214082Sdim
3370214082Sdim	    case DW_CFA_offset:
3371214082Sdim	      roffs = LEB ();
3372214082Sdim	      if (! do_debug_frames_interp)
3373214082Sdim		printf ("  DW_CFA_offset: r%d at cfa%+ld\n",
3374214082Sdim			opa, roffs * fc->data_factor);
3375214082Sdim	      fc->col_type[opa] = DW_CFA_offset;
3376214082Sdim	      fc->col_offset[opa] = roffs * fc->data_factor;
3377214082Sdim	      break;
3378214082Sdim
3379214082Sdim	    case DW_CFA_restore:
3380214082Sdim	      if (! do_debug_frames_interp)
3381214082Sdim		printf ("  DW_CFA_restore: r%d\n", opa);
3382214082Sdim	      fc->col_type[opa] = cie->col_type[opa];
3383214082Sdim	      fc->col_offset[opa] = cie->col_offset[opa];
3384214082Sdim	      break;
3385214082Sdim
3386214082Sdim	    case DW_CFA_set_loc:
3387214082Sdim	      vma = get_encoded_value (start, fc->fde_encoding);
3388214082Sdim	      if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
3389214082Sdim		  && !is_relocatable)
3390214082Sdim		vma += section->address + (start - section_start);
3391214082Sdim	      start += encoded_ptr_size;
3392214082Sdim	      if (do_debug_frames_interp)
3393214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3394214082Sdim	      else
3395214082Sdim		printf ("  DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
3396214082Sdim	      fc->pc_begin = vma;
3397214082Sdim	      break;
3398214082Sdim
3399214082Sdim	    case DW_CFA_advance_loc1:
3400214082Sdim	      ofs = byte_get (start, 1); start += 1;
3401214082Sdim	      if (do_debug_frames_interp)
3402214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3403214082Sdim	      else
3404214082Sdim		printf ("  DW_CFA_advance_loc1: %ld to %08lx\n",
3405214082Sdim			ofs * fc->code_factor,
3406214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3407214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3408214082Sdim	      break;
3409214082Sdim
3410214082Sdim	    case DW_CFA_advance_loc2:
3411214082Sdim	      ofs = byte_get (start, 2); start += 2;
3412214082Sdim	      if (do_debug_frames_interp)
3413214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3414214082Sdim	      else
3415214082Sdim		printf ("  DW_CFA_advance_loc2: %ld to %08lx\n",
3416214082Sdim			ofs * fc->code_factor,
3417214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3418214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3419214082Sdim	      break;
3420214082Sdim
3421214082Sdim	    case DW_CFA_advance_loc4:
3422214082Sdim	      ofs = byte_get (start, 4); start += 4;
3423214082Sdim	      if (do_debug_frames_interp)
3424214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3425214082Sdim	      else
3426214082Sdim		printf ("  DW_CFA_advance_loc4: %ld to %08lx\n",
3427214082Sdim			ofs * fc->code_factor,
3428214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3429214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3430214082Sdim	      break;
3431214082Sdim
3432214082Sdim	    case DW_CFA_offset_extended:
3433214082Sdim	      reg = LEB ();
3434214082Sdim	      roffs = LEB ();
3435214082Sdim	      if (! do_debug_frames_interp)
3436214082Sdim		printf ("  DW_CFA_offset_extended: r%ld at cfa%+ld\n",
3437214082Sdim			reg, roffs * fc->data_factor);
3438214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3439214082Sdim	      fc->col_offset[reg] = roffs * fc->data_factor;
3440214082Sdim	      break;
3441214082Sdim
3442214082Sdim	    case DW_CFA_val_offset:
3443214082Sdim	      reg = LEB ();
3444214082Sdim	      roffs = LEB ();
3445214082Sdim	      if (! do_debug_frames_interp)
3446214082Sdim		printf ("  DW_CFA_val_offset: r%ld at cfa%+ld\n",
3447214082Sdim			reg, roffs * fc->data_factor);
3448214082Sdim	      fc->col_type[reg] = DW_CFA_val_offset;
3449214082Sdim	      fc->col_offset[reg] = roffs * fc->data_factor;
3450214082Sdim	      break;
3451214082Sdim
3452214082Sdim	    case DW_CFA_restore_extended:
3453214082Sdim	      reg = LEB ();
3454214082Sdim	      if (! do_debug_frames_interp)
3455214082Sdim		printf ("  DW_CFA_restore_extended: r%ld\n", reg);
3456214082Sdim	      fc->col_type[reg] = cie->col_type[reg];
3457214082Sdim	      fc->col_offset[reg] = cie->col_offset[reg];
3458214082Sdim	      break;
3459214082Sdim
3460214082Sdim	    case DW_CFA_undefined:
3461214082Sdim	      reg = LEB ();
3462214082Sdim	      if (! do_debug_frames_interp)
3463214082Sdim		printf ("  DW_CFA_undefined: r%ld\n", reg);
3464214082Sdim	      fc->col_type[reg] = DW_CFA_undefined;
3465214082Sdim	      fc->col_offset[reg] = 0;
3466214082Sdim	      break;
3467214082Sdim
3468214082Sdim	    case DW_CFA_same_value:
3469214082Sdim	      reg = LEB ();
3470214082Sdim	      if (! do_debug_frames_interp)
3471214082Sdim		printf ("  DW_CFA_same_value: r%ld\n", reg);
3472214082Sdim	      fc->col_type[reg] = DW_CFA_same_value;
3473214082Sdim	      fc->col_offset[reg] = 0;
3474214082Sdim	      break;
3475214082Sdim
3476214082Sdim	    case DW_CFA_register:
3477214082Sdim	      reg = LEB ();
3478214082Sdim	      roffs = LEB ();
3479214082Sdim	      if (! do_debug_frames_interp)
3480214082Sdim		printf ("  DW_CFA_register: r%ld in r%ld\n", reg, roffs);
3481214082Sdim	      fc->col_type[reg] = DW_CFA_register;
3482214082Sdim	      fc->col_offset[reg] = roffs;
3483214082Sdim	      break;
3484214082Sdim
3485214082Sdim	    case DW_CFA_remember_state:
3486214082Sdim	      if (! do_debug_frames_interp)
3487214082Sdim		printf ("  DW_CFA_remember_state\n");
3488214082Sdim	      rs = xmalloc (sizeof (Frame_Chunk));
3489214082Sdim	      rs->ncols = fc->ncols;
3490214082Sdim	      rs->col_type = xcmalloc (rs->ncols, sizeof (short int));
3491214082Sdim	      rs->col_offset = xcmalloc (rs->ncols, sizeof (int));
3492214082Sdim	      memcpy (rs->col_type, fc->col_type, rs->ncols);
3493214082Sdim	      memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
3494214082Sdim	      rs->next = remembered_state;
3495214082Sdim	      remembered_state = rs;
3496214082Sdim	      break;
3497214082Sdim
3498214082Sdim	    case DW_CFA_restore_state:
3499214082Sdim	      if (! do_debug_frames_interp)
3500214082Sdim		printf ("  DW_CFA_restore_state\n");
3501214082Sdim	      rs = remembered_state;
3502214082Sdim	      if (rs)
3503214082Sdim		{
3504214082Sdim		  remembered_state = rs->next;
3505214082Sdim		  frame_need_space (fc, rs->ncols-1);
3506214082Sdim		  memcpy (fc->col_type, rs->col_type, rs->ncols);
3507214082Sdim		  memcpy (fc->col_offset, rs->col_offset,
3508214082Sdim			  rs->ncols * sizeof (int));
3509214082Sdim		  free (rs->col_type);
3510214082Sdim		  free (rs->col_offset);
3511214082Sdim		  free (rs);
3512214082Sdim		}
3513214082Sdim	      else if (do_debug_frames_interp)
3514214082Sdim		printf ("Mismatched DW_CFA_restore_state\n");
3515214082Sdim	      break;
3516214082Sdim
3517214082Sdim	    case DW_CFA_def_cfa:
3518214082Sdim	      fc->cfa_reg = LEB ();
3519214082Sdim	      fc->cfa_offset = LEB ();
3520214082Sdim	      fc->cfa_exp = 0;
3521214082Sdim	      if (! do_debug_frames_interp)
3522214082Sdim		printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
3523214082Sdim			fc->cfa_reg, fc->cfa_offset);
3524214082Sdim	      break;
3525214082Sdim
3526214082Sdim	    case DW_CFA_def_cfa_register:
3527214082Sdim	      fc->cfa_reg = LEB ();
3528214082Sdim	      fc->cfa_exp = 0;
3529214082Sdim	      if (! do_debug_frames_interp)
3530214082Sdim		printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
3531214082Sdim	      break;
3532214082Sdim
3533214082Sdim	    case DW_CFA_def_cfa_offset:
3534214082Sdim	      fc->cfa_offset = LEB ();
3535214082Sdim	      if (! do_debug_frames_interp)
3536214082Sdim		printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
3537214082Sdim	      break;
3538214082Sdim
3539214082Sdim	    case DW_CFA_nop:
3540214082Sdim	      if (! do_debug_frames_interp)
3541214082Sdim		printf ("  DW_CFA_nop\n");
3542214082Sdim	      break;
3543214082Sdim
3544214082Sdim	    case DW_CFA_def_cfa_expression:
3545214082Sdim	      ul = LEB ();
3546214082Sdim	      if (! do_debug_frames_interp)
3547214082Sdim		{
3548214082Sdim		  printf ("  DW_CFA_def_cfa_expression (");
3549214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3550214082Sdim		  printf (")\n");
3551214082Sdim		}
3552214082Sdim	      fc->cfa_exp = 1;
3553214082Sdim	      start += ul;
3554214082Sdim	      break;
3555214082Sdim
3556214082Sdim	    case DW_CFA_expression:
3557214082Sdim	      reg = LEB ();
3558214082Sdim	      ul = LEB ();
3559214082Sdim	      if (! do_debug_frames_interp)
3560214082Sdim		{
3561214082Sdim		  printf ("  DW_CFA_expression: r%ld (", reg);
3562214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3563214082Sdim		  printf (")\n");
3564214082Sdim		}
3565214082Sdim	      fc->col_type[reg] = DW_CFA_expression;
3566214082Sdim	      start += ul;
3567214082Sdim	      break;
3568214082Sdim
3569214082Sdim	    case DW_CFA_val_expression:
3570214082Sdim	      reg = LEB ();
3571214082Sdim	      ul = LEB ();
3572214082Sdim	      if (! do_debug_frames_interp)
3573214082Sdim		{
3574214082Sdim		  printf ("  DW_CFA_val_expression: r%ld (", reg);
3575214082Sdim		  decode_location_expression (start, eh_addr_size, ul, 0);
3576214082Sdim		  printf (")\n");
3577214082Sdim		}
3578214082Sdim	      fc->col_type[reg] = DW_CFA_val_expression;
3579214082Sdim	      start += ul;
3580214082Sdim	      break;
3581214082Sdim
3582214082Sdim	    case DW_CFA_offset_extended_sf:
3583214082Sdim	      reg = LEB ();
3584214082Sdim	      l = SLEB ();
3585214082Sdim	      frame_need_space (fc, reg);
3586214082Sdim	      if (! do_debug_frames_interp)
3587214082Sdim		printf ("  DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n",
3588214082Sdim			reg, l * fc->data_factor);
3589214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3590214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3591214082Sdim	      break;
3592214082Sdim
3593214082Sdim	    case DW_CFA_val_offset_sf:
3594214082Sdim	      reg = LEB ();
3595214082Sdim	      l = SLEB ();
3596214082Sdim	      frame_need_space (fc, reg);
3597214082Sdim	      if (! do_debug_frames_interp)
3598214082Sdim		printf ("  DW_CFA_val_offset_sf: r%ld at cfa%+ld\n",
3599214082Sdim			reg, l * fc->data_factor);
3600214082Sdim	      fc->col_type[reg] = DW_CFA_val_offset;
3601214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3602214082Sdim	      break;
3603214082Sdim
3604214082Sdim	    case DW_CFA_def_cfa_sf:
3605214082Sdim	      fc->cfa_reg = LEB ();
3606214082Sdim	      fc->cfa_offset = SLEB ();
3607214082Sdim	      fc->cfa_offset = fc->cfa_offset * fc->data_factor;
3608214082Sdim	      fc->cfa_exp = 0;
3609214082Sdim	      if (! do_debug_frames_interp)
3610214082Sdim		printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
3611214082Sdim			fc->cfa_reg, fc->cfa_offset);
3612214082Sdim	      break;
3613214082Sdim
3614214082Sdim	    case DW_CFA_def_cfa_offset_sf:
3615214082Sdim	      fc->cfa_offset = SLEB ();
3616214082Sdim	      fc->cfa_offset = fc->cfa_offset * fc->data_factor;
3617214082Sdim	      if (! do_debug_frames_interp)
3618214082Sdim		printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
3619214082Sdim	      break;
3620214082Sdim
3621214082Sdim	    case DW_CFA_MIPS_advance_loc8:
3622214082Sdim	      ofs = byte_get (start, 8); start += 8;
3623214082Sdim	      if (do_debug_frames_interp)
3624214082Sdim		frame_display_row (fc, &need_col_headers, &max_regs);
3625214082Sdim	      else
3626214082Sdim		printf ("  DW_CFA_MIPS_advance_loc8: %ld to %08lx\n",
3627214082Sdim			ofs * fc->code_factor,
3628214082Sdim			fc->pc_begin + ofs * fc->code_factor);
3629214082Sdim	      fc->pc_begin += ofs * fc->code_factor;
3630214082Sdim	      break;
3631214082Sdim
3632214082Sdim	    case DW_CFA_GNU_window_save:
3633214082Sdim	      if (! do_debug_frames_interp)
3634214082Sdim		printf ("  DW_CFA_GNU_window_save\n");
3635214082Sdim	      break;
3636214082Sdim
3637214082Sdim	    case DW_CFA_GNU_args_size:
3638214082Sdim	      ul = LEB ();
3639214082Sdim	      if (! do_debug_frames_interp)
3640214082Sdim		printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
3641214082Sdim	      break;
3642214082Sdim
3643214082Sdim	    case DW_CFA_GNU_negative_offset_extended:
3644214082Sdim	      reg = LEB ();
3645214082Sdim	      l = - LEB ();
3646214082Sdim	      frame_need_space (fc, reg);
3647214082Sdim	      if (! do_debug_frames_interp)
3648214082Sdim		printf ("  DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
3649214082Sdim			reg, l * fc->data_factor);
3650214082Sdim	      fc->col_type[reg] = DW_CFA_offset;
3651214082Sdim	      fc->col_offset[reg] = l * fc->data_factor;
3652214082Sdim	      break;
3653214082Sdim
3654214082Sdim	    default:
3655214634Sdim	      if (op >= DW_CFA_lo_user && op <= DW_CFA_hi_user)
3656214634Sdim		printf (_("  DW_CFA_??? (User defined call frame op: %#x)\n"), op);
3657214634Sdim	      else
3658214634Sdim		warn (_("unsupported or unknown Dwarf Call Frame Instruction number: %#x\n"), op);
3659214082Sdim	      start = block_end;
3660214082Sdim	    }
3661214082Sdim	}
3662214082Sdim
3663214082Sdim      if (do_debug_frames_interp)
3664214082Sdim	frame_display_row (fc, &need_col_headers, &max_regs);
3665214082Sdim
3666214082Sdim      start = block_end;
3667214082Sdim    }
3668214082Sdim
3669214082Sdim  printf ("\n");
3670214082Sdim
3671214082Sdim  return 1;
3672214082Sdim}
3673214082Sdim
3674214082Sdim#undef GET
3675214082Sdim#undef LEB
3676214082Sdim#undef SLEB
3677214082Sdim
3678214082Sdimstatic int
3679214082Sdimdisplay_debug_not_supported (struct dwarf_section *section,
3680214082Sdim			     void *file ATTRIBUTE_UNUSED)
3681214082Sdim{
3682214082Sdim  printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
3683214082Sdim	    section->name);
3684214082Sdim
3685214082Sdim  return 1;
3686214082Sdim}
3687214082Sdim
3688214082Sdimvoid *
3689214082Sdimcmalloc (size_t nmemb, size_t size)
3690214082Sdim{
3691214082Sdim  /* Check for overflow.  */
3692214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3693214082Sdim    return NULL;
3694214082Sdim  else
3695214082Sdim    return malloc (nmemb * size);
3696214082Sdim}
3697214082Sdim
3698214082Sdimvoid *
3699214082Sdimxcmalloc (size_t nmemb, size_t size)
3700214082Sdim{
3701214082Sdim  /* Check for overflow.  */
3702214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3703214082Sdim    return NULL;
3704214082Sdim  else
3705214082Sdim    return xmalloc (nmemb * size);
3706214082Sdim}
3707214082Sdim
3708214082Sdimvoid *
3709214082Sdimxcrealloc (void *ptr, size_t nmemb, size_t size)
3710214082Sdim{
3711214082Sdim  /* Check for overflow.  */
3712214082Sdim  if (nmemb >= ~(size_t) 0 / size)
3713214082Sdim    return NULL;
3714214082Sdim  else
3715214082Sdim    return xrealloc (ptr, nmemb * size);
3716214082Sdim}
3717214082Sdim
3718214082Sdimvoid
3719214082Sdimerror (const char *message, ...)
3720214082Sdim{
3721214082Sdim  va_list args;
3722214082Sdim
3723214082Sdim  va_start (args, message);
3724214082Sdim  fprintf (stderr, _("%s: Error: "), program_name);
3725214082Sdim  vfprintf (stderr, message, args);
3726214082Sdim  va_end (args);
3727214082Sdim}
3728214082Sdim
3729214082Sdimvoid
3730214082Sdimwarn (const char *message, ...)
3731214082Sdim{
3732214082Sdim  va_list args;
3733214082Sdim
3734214082Sdim  va_start (args, message);
3735214082Sdim  fprintf (stderr, _("%s: Warning: "), program_name);
3736214082Sdim  vfprintf (stderr, message, args);
3737214082Sdim  va_end (args);
3738214082Sdim}
3739214082Sdim
3740214082Sdimvoid
3741214082Sdimfree_debug_memory (void)
3742214082Sdim{
3743214082Sdim  enum dwarf_section_display_enum i;
3744214082Sdim
3745214082Sdim  free_abbrevs ();
3746214082Sdim
3747214082Sdim  for (i = 0; i < max; i++)
3748214082Sdim    free_debug_section (i);
3749214082Sdim
3750214082Sdim  if (debug_information)
3751214082Sdim    {
3752214082Sdim      for (i = 0; i < num_debug_info_entries; i++)
3753214082Sdim	{
3754214082Sdim	  if (!debug_information [i].max_loc_offsets)
3755214082Sdim	    {
3756214082Sdim	      free (debug_information [i].loc_offsets);
3757214082Sdim	      free (debug_information [i].have_frame_base);
3758214082Sdim	    }
3759214082Sdim	  if (!debug_information [i].max_range_lists)
3760214082Sdim	    free (debug_information [i].range_lists);
3761214082Sdim	}
3762214082Sdim      free (debug_information);
3763214082Sdim      debug_information = NULL;
3764214082Sdim      num_debug_info_entries = 0;
3765214082Sdim    }
3766214082Sdim
3767214082Sdim}
3768214082Sdim
3769214082Sdimstruct dwarf_section_display debug_displays[] =
3770214082Sdim{
3771214082Sdim  { { ".debug_abbrev",		NULL,	0,	0 },
3772214082Sdim    display_debug_abbrev,		0,	0 },
3773214082Sdim  { { ".debug_aranges",		NULL,	0,	0 },
3774214082Sdim    display_debug_aranges,		0,	0 },
3775214082Sdim  { { ".debug_frame",		NULL,	0,	0 },
3776214082Sdim    display_debug_frames,		1,	0 },
3777214082Sdim  { { ".debug_info",		NULL,	0,	0 },
3778214082Sdim    display_debug_info,			1,	0 },
3779214082Sdim  { { ".debug_line",		NULL,	0,	0 },
3780214082Sdim    display_debug_lines,		0,	0 },
3781214082Sdim  { { ".debug_pubnames",	NULL,	0,	0 },
3782214082Sdim    display_debug_pubnames,		0,	0 },
3783214082Sdim  { { ".eh_frame",		NULL,	0,	0 },
3784214082Sdim    display_debug_frames,		1,	1 },
3785214082Sdim  { { ".debug_macinfo",		NULL,	0,	0 },
3786214082Sdim    display_debug_macinfo,		0,	0 },
3787214082Sdim  { { ".debug_str",		NULL,	0,	0 },
3788214082Sdim    display_debug_str,			0,	0 },
3789214082Sdim  { { ".debug_loc",		NULL,	0,	0 },
3790214082Sdim    display_debug_loc,			0,	0 },
3791214082Sdim  { { ".debug_pubtypes",	NULL,	0,	0 },
3792214082Sdim    display_debug_pubnames,		0,	0 },
3793214082Sdim  { { ".debug_ranges",		NULL,	0,	0 },
3794214082Sdim    display_debug_ranges,		0,	0 },
3795214082Sdim  { { ".debug_static_func",	NULL,	0,	0 },
3796214082Sdim    display_debug_not_supported,	0,	0 },
3797214082Sdim  { { ".debug_static_vars",	NULL,	0,	0 },
3798214082Sdim    display_debug_not_supported,	0,	0 },
3799214082Sdim  { { ".debug_types",		NULL,	0,	0 },
3800214082Sdim    display_debug_not_supported,	0,	0 },
3801214082Sdim  { { ".debug_weaknames",	NULL,	0,	0 },
3802214082Sdim    display_debug_not_supported,	0,	0 }
3803214082Sdim};
3804