+static const char * debug_loc_contents;
+static bfd_vma debug_loc_size;
+
+static void
+load_debug_loc (file)
+ FILE * file;
+{
+ Elf32_Internal_Shdr * sec;
+ unsigned int i;
+
+ /* If it is already loaded, do nothing. */
+ if (debug_loc_contents != NULL)
+ return;
+
+ /* Locate the .debug_loc section. */
+ for (i = 0, sec = section_headers;
+ i < elf_header.e_shnum;
+ i ++, sec ++)
+ if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
+ break;
+
+ if (i == elf_header.e_shnum || sec->sh_size == 0)
+ return;
+
+ debug_loc_size = sec->sh_size;
+
+ debug_loc_contents = ((char *)
+ get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_loc section data")));
+}
+
+static void
+free_debug_loc ()
+{
+ if (debug_loc_contents == NULL)
+ return;
+
+ free ((char *) debug_loc_contents);
+ debug_loc_contents = NULL;
+ debug_loc_size = 0;
+}
+
+
+static int
+display_debug_loc (section, start, file)
+ Elf32_Internal_Shdr * section;
+ unsigned char * start;
+ FILE * file ATTRIBUTE_UNUSED;
+{
+ unsigned char *section_end;
+ unsigned long bytes;
+ unsigned char *section_begin = start;
+ bfd_vma addr;
+
+ addr = section->sh_addr;
+ bytes = section->sh_size;
+ section_end = start + bytes;
+ if (bytes == 0)
+ {
+ printf (_("\nThe .debug_loc section is empty.\n"));
+ return 0;
+ }
+ printf (_("Contents of the .debug_loc section:\n\n"));
+ printf (_("\n Offset Begin End Expression\n"));
+ while (start < section_end)
+ {
+ unsigned long begin;
+ unsigned long end;
+ unsigned short length;
+ unsigned long offset;
+
+ offset = start - section_begin;
+
+ while (1)
+ {
+ /* Normally, the lists in the debug_loc section are related to a
+ given compilation unit, and thus, we would use the
+ pointer size of that compilation unit. However, since we are
+ displaying it seperately here, we either have to store
+ pointer sizes of all compilation units, or assume they don't
+ change. We assume, like the debug_line display, that
+ it doesn't change. */
+ begin = byte_get (start, debug_line_pointer_size);
+ start += debug_line_pointer_size;
+ end = byte_get (start, debug_line_pointer_size);
+ start += debug_line_pointer_size;
+
+ if (begin == 0 && end == 0)
+ break;
+
+ begin += addr;
+ end += addr;
+
+ length = byte_get (start, 2);
+ start += 2;
+
+ printf (" %8.8lx %8.8lx %8.8lx (", offset, begin, end);
+ decode_location_expression (start, debug_line_pointer_size, length);
+ printf (")\n");
+
+ start += length;
+ }
+ printf ("\n");
+ }
+ return 1;
+}
+
+static const char * debug_str_contents;
+static bfd_vma debug_str_size;
+
+static void
+load_debug_str (file)
+ FILE * file;
+{
+ Elf32_Internal_Shdr * sec;
+ unsigned int i;
+
+ /* If it is already loaded, do nothing. */
+ if (debug_str_contents != NULL)
+ return;
+
+ /* Locate the .debug_str section. */
+ for (i = 0, sec = section_headers;
+ i < elf_header.e_shnum;
+ i ++, sec ++)
+ if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
+ break;
+
+ if (i == elf_header.e_shnum || sec->sh_size == 0)
+ return;
+
+ debug_str_size = sec->sh_size;
+
+ debug_str_contents = ((char *)
+ get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_str section data")));
+}
+
+static void
+free_debug_str ()
+{
+ if (debug_str_contents == NULL)
+ return;
+
+ free ((char *) debug_str_contents);
+ debug_str_contents = NULL;
+ debug_str_size = 0;
+}
+
+static const char *
+fetch_indirect_string (offset)
+ unsigned long offset;
+{
+ if (debug_str_contents == NULL)
+ return _("<no .debug_str section>");
+
+ if (offset > debug_str_size)
+ return _("<offset is too big>");
+
+ return debug_str_contents + offset;
+}
+
+
+static int
+display_debug_str (section, start, file)
+ Elf32_Internal_Shdr * section;
+ unsigned char * start;
+ FILE * file ATTRIBUTE_UNUSED;
+{
+ unsigned long bytes;
+ bfd_vma addr;
+
+ addr = section->sh_addr;
+ bytes = section->sh_size;
+
+ if (bytes == 0)
+ {
+ printf (_("\nThe .debug_str section is empty.\n"));
+ return 0;
+ }
+
+ printf (_("Contents of the .debug_str section:\n\n"));
+
+ while (bytes)
+ {
+ int j;
+ int k;
+ int lbytes;
+
+ lbytes = (bytes > 16 ? 16 : bytes);
+
+ printf (" 0x%8.8lx ", (unsigned long) addr);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (j < lbytes)
+ printf ("%2.2x", start [j]);
+ else
+ printf (" ");
+
+ if ((j & 3) == 3)
+ printf (" ");
+ }
+
+ for (j = 0; j < lbytes; j++)
+ {
+ k = start [j];
+ if (k >= ' ' && k < 0x80)
+ printf ("%c", k);
+ else
+ printf (".");
+ }
+
+ putchar ('\n');
+
+ start += lbytes;
+ addr += lbytes;
+ bytes -= lbytes;
+ }
+
+ return 1;
+}
+