+ debug_apply_relocations (file, sec, section->start);
+
+ return section->start != NULL;
+}
+
+void
+free_debug_section (enum dwarf_section_display_enum debug)
+{
+ struct dwarf_section *section = &debug_displays [debug].section;
+
+ if (section->start == NULL)
+ return;
+
+ free ((char *) section->start);
+ section->start = NULL;
+ section->address = 0;
+ section->size = 0;
+}
+
+static int
+display_debug_section (Elf_Internal_Shdr *section, FILE *file)
+{
+ char *name = SECTION_NAME (section);
+ bfd_size_type length;
+ int result = 1;
+ enum dwarf_section_display_enum i;
+
+ length = section->sh_size;
+ if (length == 0)
+ {
+ printf (_("\nSection '%s' has no debugging data.\n"), name);
+ return 0;
+ }
+
+ if (const_strneq (name, ".gnu.linkonce.wi."))
+ name = ".debug_info";
+
+ /* See if we know how to display the contents of this section. */
+ for (i = 0; i < max; i++)
+ if (streq (debug_displays[i].section.name, name))
+ {
+ struct dwarf_section *sec = &debug_displays [i].section;
+
+ if (load_debug_section (i, file))
+ {
+ result &= debug_displays[i].display (sec, file);
+
+ if (i != info && i != abbrev)
+ free_debug_section (i);
+ }
+
+ break;
+ }
+
+ if (i == max)
+ {
+ printf (_("Unrecognized debug section: %s\n"), name);
+ result = 0;
+ }
+
+ return result;
+}
+
+/* Set DUMP_SECTS for all sections where dumps were requested
+ based on section name. */
+
+static void
+initialise_dumps_byname (void)
+{
+ struct dump_list_entry *cur;
+
+ for (cur = dump_sects_byname; cur; cur = cur->next)
+ {
+ unsigned int i;
+ int any;
+
+ for (i = 0, any = 0; i < elf_header.e_shnum; i++)
+ if (streq (SECTION_NAME (section_headers + i), cur->name))
+ {
+ request_dump_bynumber (i, cur->type);
+ any = 1;
+ }
+
+ if (!any)
+ warn (_("Section '%s' was not dumped because it does not exist!\n"),
+ cur->name);
+ }
+}
+
+static void
+process_section_contents (FILE *file)
+{
+ Elf_Internal_Shdr *section;
+ unsigned int i;
+
+ if (! do_dump)
+ return;
+
+ initialise_dumps_byname ();
+
+ for (i = 0, section = section_headers;
+ i < elf_header.e_shnum && i < num_dump_sects;
+ i++, section++)
+ {
+#ifdef SUPPORT_DISASSEMBLY
+ if (dump_sects[i] & DISASS_DUMP)
+ disassemble_section (section, file);
+#endif
+ if (dump_sects[i] & HEX_DUMP)
+ dump_section_as_bytes (section, file);
+
+ if (dump_sects[i] & DEBUG_DUMP)
+ display_debug_section (section, file);
+
+ if (dump_sects[i] & STRING_DUMP)
+ dump_section_as_strings (section, file);
+ }
+
+ /* Check to see if the user requested a
+ dump of a section that does not exist. */
+ while (i++ < num_dump_sects)
+ if (dump_sects[i])
+ warn (_("Section %d was not dumped because it does not exist!\n"), i);
+}
+
+static void
+process_mips_fpe_exception (int mask)
+{
+ if (mask)
+ {
+ int first = 1;
+ if (mask & OEX_FPU_INEX)
+ fputs ("INEX", stdout), first = 0;
+ if (mask & OEX_FPU_UFLO)
+ printf ("%sUFLO", first ? "" : "|"), first = 0;
+ if (mask & OEX_FPU_OFLO)
+ printf ("%sOFLO", first ? "" : "|"), first = 0;
+ if (mask & OEX_FPU_DIV0)
+ printf ("%sDIV0", first ? "" : "|"), first = 0;
+ if (mask & OEX_FPU_INVAL)
+ printf ("%sINVAL", first ? "" : "|");
+ }
+ else
+ fputs ("0", stdout);
+}
+
+/* ARM EABI attributes section. */
+typedef struct
+{
+ int tag;
+ const char *name;
+ /* 0 = special, 1 = string, 2 = uleb123, > 0x80 == table lookup. */
+ int type;
+ const char **table;
+} arm_attr_public_tag;
+
+static const char *arm_attr_tag_CPU_arch[] =
+ {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
+ "v6K", "v7"};
+static const char *arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
+static const char *arm_attr_tag_THUMB_ISA_use[] =
+ {"No", "Thumb-1", "Thumb-2"};
+/* FIXME: VFPv3 encoding was extrapolated! */
+static const char *arm_attr_tag_VFP_arch[] = {"No", "VFPv1", "VFPv2", "VFPv3"};
+static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1"};
+static const char *arm_attr_tag_NEON_arch[] = {"No", "NEONv1"};
+static const char *arm_attr_tag_ABI_PCS_config[] =
+ {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
+ "PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"};
+static const char *arm_attr_tag_ABI_PCS_R9_use[] =
+ {"V6", "SB", "TLS", "Unused"};
+static const char *arm_attr_tag_ABI_PCS_RW_data[] =
+ {"Absolute", "PC-relative", "SB-relative", "None"};
+static const char *arm_attr_tag_ABI_PCS_RO_DATA[] =
+ {"Absolute", "PC-relative", "None"};
+static const char *arm_attr_tag_ABI_PCS_GOT_use[] =
+ {"None", "direct", "GOT-indirect"};
+static const char *arm_attr_tag_ABI_PCS_wchar_t[] =
+ {"None", "??? 1", "2", "??? 3", "4"};
+static const char *arm_attr_tag_ABI_FP_rounding[] = {"Unused", "Needed"};
+static const char *arm_attr_tag_ABI_FP_denormal[] = {"Unused", "Needed"};
+static const char *arm_attr_tag_ABI_FP_exceptions[] = {"Unused", "Needed"};
+static const char *arm_attr_tag_ABI_FP_user_exceptions[] = {"Unused", "Needed"};
+static const char *arm_attr_tag_ABI_FP_number_model[] =
+ {"Unused", "Finite", "RTABI", "IEEE 754"};
+static const char *arm_attr_tag_ABI_align8_needed[] = {"No", "Yes", "4-byte"};
+static const char *arm_attr_tag_ABI_align8_preserved[] =
+ {"No", "Yes, except leaf SP", "Yes"};
+static const char *arm_attr_tag_ABI_enum_size[] =
+ {"Unused", "small", "int", "forced to int"};
+static const char *arm_attr_tag_ABI_HardFP_use[] =
+ {"As Tag_VFP_arch", "SP only", "DP only", "SP and DP"};
+static const char *arm_attr_tag_ABI_VFP_args[] =
+ {"AAPCS", "VFP registers", "custom"};
+static const char *arm_attr_tag_ABI_WMMX_args[] =
+ {"AAPCS", "WMMX registers", "custom"};
+static const char *arm_attr_tag_ABI_optimization_goals[] =
+ {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
+ "Aggressive Size", "Prefer Debug", "Aggressive Debug"};
+static const char *arm_attr_tag_ABI_FP_optimization_goals[] =
+ {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
+ "Aggressive Size", "Prefer Accuracy", "Aggressive Accuracy"};
+
+#define LOOKUP(id, name) \
+ {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
+static arm_attr_public_tag arm_attr_public_tags[] =
+{
+ {4, "CPU_raw_name", 1, NULL},
+ {5, "CPU_name", 1, NULL},
+ LOOKUP(6, CPU_arch),
+ {7, "CPU_arch_profile", 0, NULL},
+ LOOKUP(8, ARM_ISA_use),
+ LOOKUP(9, THUMB_ISA_use),
+ LOOKUP(10, VFP_arch),
+ LOOKUP(11, WMMX_arch),
+ LOOKUP(12, NEON_arch),
+ LOOKUP(13, ABI_PCS_config),
+ LOOKUP(14, ABI_PCS_R9_use),
+ LOOKUP(15, ABI_PCS_RW_data),
+ LOOKUP(16, ABI_PCS_RO_DATA),
+ LOOKUP(17, ABI_PCS_GOT_use),
+ LOOKUP(18, ABI_PCS_wchar_t),
+ LOOKUP(19, ABI_FP_rounding),
+ LOOKUP(20, ABI_FP_denormal),
+ LOOKUP(21, ABI_FP_exceptions),
+ LOOKUP(22, ABI_FP_user_exceptions),
+ LOOKUP(23, ABI_FP_number_model),
+ LOOKUP(24, ABI_align8_needed),
+ LOOKUP(25, ABI_align8_preserved),
+ LOOKUP(26, ABI_enum_size),
+ LOOKUP(27, ABI_HardFP_use),
+ LOOKUP(28, ABI_VFP_args),
+ LOOKUP(29, ABI_WMMX_args),
+ LOOKUP(30, ABI_optimization_goals),
+ LOOKUP(31, ABI_FP_optimization_goals),
+ {32, "compatibility", 0, NULL}
+};
+#undef LOOKUP
+
+/* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of
+ bytes read. */
+static unsigned int
+read_uleb128 (unsigned char *p, unsigned int *plen)
+{
+ unsigned char c;
+ unsigned int val;
+ int shift;
+ int len;
+
+ val = 0;
+ shift = 0;
+ len = 0;
+ do
+ {
+ c = *(p++);
+ len++;
+ val |= ((unsigned int)c & 0x7f) << shift;
+ shift += 7;
+ }
+ while (c & 0x80);
+
+ *plen = len;
+ return val;
+}
+
+static unsigned char *
+display_arm_attribute (unsigned char *p)
+{
+ int tag;
+ unsigned int len;
+ int val;
+ arm_attr_public_tag *attr;
+ unsigned i;
+ int type;
+
+ tag = read_uleb128 (p, &len);
+ p += len;
+ attr = NULL;
+ for (i = 0; i < ARRAY_SIZE(arm_attr_public_tags); i++)
+ {
+ if (arm_attr_public_tags[i].tag == tag)
+ {
+ attr = &arm_attr_public_tags[i];
+ break;
+ }
+ }
+
+ if (attr)
+ {
+ printf (" Tag_%s: ", attr->name);
+ switch (attr->type)
+ {
+ case 0:
+ switch (tag)
+ {
+ case 7: /* Tag_CPU_arch_profile. */
+ val = read_uleb128 (p, &len);
+ p += len;
+ switch (val)
+ {
+ case 0: printf ("None\n"); break;
+ case 'A': printf ("Application\n"); break;
+ case 'R': printf ("Realtime\n"); break;
+ case 'M': printf ("Microcontroller\n"); break;
+ default: printf ("??? (%d)\n", val); break;
+ }
+ break;
+
+ case 32: /* Tag_compatibility. */
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf ("flag = %d, vendor = %s\n", val, p);
+ p += strlen((char *)p) + 1;
+ break;
+
+ default:
+ abort();
+ }
+ return p;
+
+ case 1:
+ case 2:
+ type = attr->type;
+ break;
+
+ default:
+ assert (attr->type & 0x80);
+ val = read_uleb128 (p, &len);
+ p += len;
+ type = attr->type & 0x7f;
+ if (val >= type)
+ printf ("??? (%d)\n", val);
+ else
+ printf ("%s\n", attr->table[val]);
+ return p;
+ }
+ }
+ else
+ {
+ if (tag & 1)
+ type = 1; /* String. */
+ else
+ type = 2; /* uleb128. */
+ printf (" Tag_unknown_%d: ", tag);
+ }
+
+ if (type == 1)
+ {
+ printf ("\"%s\"\n", p);
+ p += strlen((char *)p) + 1;
+ }
+ else
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf ("%d (0x%x)\n", val, val);
+ }
+
+ return p;
+}
+
+static unsigned char *
+display_gnu_attribute (unsigned char * p,
+ unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int))
+{
+ int tag;
+ unsigned int len;
+ int val;
+ int type;
+
+ tag = read_uleb128 (p, &len);
+ p += len;
+
+ /* Tag_compatibility is the only generic GNU attribute defined at
+ present. */
+ if (tag == 32)
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf ("flag = %d, vendor = %s\n", val, p);
+ p += strlen ((char *) p) + 1;
+ return p;
+ }
+
+ if ((tag & 2) == 0 && display_proc_gnu_attribute)
+ return display_proc_gnu_attribute (p, tag);
+
+ if (tag & 1)
+ type = 1; /* String. */
+ else
+ type = 2; /* uleb128. */
+ printf (" Tag_unknown_%d: ", tag);
+
+ if (type == 1)
+ {
+ printf ("\"%s\"\n", p);
+ p += strlen ((char *) p) + 1;
+ }
+ else
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf ("%d (0x%x)\n", val, val);
+ }
+
+ return p;
+}
+
+static unsigned char *
+display_power_gnu_attribute (unsigned char *p, int tag)
+{
+ int type;
+ unsigned int len;
+ int val;
+
+ if (tag == Tag_GNU_Power_ABI_FP)
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf (" Tag_GNU_Power_ABI_FP: ");
+
+ switch (val)
+ {
+ case 0:
+ printf ("Hard or soft float\n");
+ break;
+ case 1:
+ printf ("Hard float\n");
+ break;
+ case 2:
+ printf ("Soft float\n");
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+ return p;
+ }
+
+ if (tag == Tag_GNU_Power_ABI_Vector)
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf (" Tag_GNU_Power_ABI_Vector: ");
+ switch (val)
+ {
+ case 0:
+ printf ("Any\n");
+ break;
+ case 1:
+ printf ("Generic\n");
+ break;
+ case 2:
+ printf ("AltiVec\n");
+ break;
+ case 3:
+ printf ("SPE\n");
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+ return p;
+ }
+
+ if (tag & 1)
+ type = 1; /* String. */
+ else
+ type = 2; /* uleb128. */
+ printf (" Tag_unknown_%d: ", tag);
+
+ if (type == 1)
+ {
+ printf ("\"%s\"\n", p);
+ p += strlen ((char *) p) + 1;
+ }
+ else
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf ("%d (0x%x)\n", val, val);
+ }