+ printf (_("Key to Flags:\n\
+ W (write), A (alloc), X (execute), M (merge), S (strings)\n\
+ I (info), L (link order), G (group), x (unknown)\n\
+ O (extra OS processing required) o (OS specific), p (processor specific)\n"));
+
+ return 1;
+}
+
+/* Process the reloc section. */
+static int
+process_relocs (file)
+ FILE * file;
+{
+ unsigned long rel_size;
+ unsigned long rel_offset;
+
+
+ if (!do_reloc)
+ return 1;
+
+ if (do_using_dynamic)
+ {
+ int is_rela = FALSE;
+
+ rel_size = 0;
+ rel_offset = 0;
+
+ if (dynamic_info[DT_REL])
+ {
+ rel_offset = dynamic_info[DT_REL];
+ rel_size = dynamic_info[DT_RELSZ];
+ is_rela = FALSE;
+ }
+ else if (dynamic_info [DT_RELA])
+ {
+ rel_offset = dynamic_info[DT_RELA];
+ rel_size = dynamic_info[DT_RELASZ];
+ is_rela = TRUE;
+ }
+ else if (dynamic_info[DT_JMPREL])
+ {
+ rel_offset = dynamic_info[DT_JMPREL];
+ rel_size = dynamic_info[DT_PLTRELSZ];
+
+ switch (dynamic_info[DT_PLTREL])
+ {
+ case DT_REL:
+ is_rela = FALSE;
+ break;
+ case DT_RELA:
+ is_rela = TRUE;
+ break;
+ default:
+ is_rela = UNKNOWN;
+ break;
+ }
+ }
+
+ if (rel_size)
+ {
+ printf
+ (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
+ rel_offset, rel_size);
+
+ dump_relocations (file, rel_offset - loadaddr, rel_size,
+ dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela);
+ }
+ else
+ printf (_("\nThere are no dynamic relocations in this file.\n"));
+ }
+ else
+ {
+ Elf32_Internal_Shdr * section;
+ unsigned long i;
+ int found = 0;
+
+ for (i = 0, section = section_headers;
+ i < elf_header.e_shnum;
+ i++, section ++)
+ {
+ if ( section->sh_type != SHT_RELA
+ && section->sh_type != SHT_REL)
+ continue;
+
+ rel_offset = section->sh_offset;
+ rel_size = section->sh_size;
+
+ if (rel_size)
+ {
+ Elf32_Internal_Shdr * strsec;
+ Elf_Internal_Sym * symtab;
+ char * strtab;
+ int is_rela;
+ unsigned long nsyms;
+
+ printf (_("\nRelocation section "));
+
+ if (string_table == NULL)
+ printf ("%d", section->sh_name);
+ else
+ printf ("'%s'", SECTION_NAME (section));
+
+ printf (_(" at offset 0x%lx contains %lu entries:\n"),
+ rel_offset, (unsigned long) (rel_size / section->sh_entsize));
+
+ symtab = NULL;
+ strtab = NULL;
+ nsyms = 0;
+ if (section->sh_link)
+ {
+ Elf32_Internal_Shdr * symsec;
+
+ symsec = SECTION_HEADER (section->sh_link);
+ nsyms = symsec->sh_size / symsec->sh_entsize;
+ symtab = GET_ELF_SYMBOLS (file, symsec);
+
+ if (symtab == NULL)
+ continue;
+
+ strsec = SECTION_HEADER (symsec->sh_link);
+
+ strtab = (char *) get_data (NULL, file, strsec->sh_offset,
+ strsec->sh_size,
+ _("string table"));
+ }
+ is_rela = section->sh_type == SHT_RELA;
+
+ dump_relocations (file, rel_offset, rel_size,
+ symtab, nsyms, strtab, is_rela);
+
+ if (strtab)
+ free (strtab);
+ if (symtab)
+ free (symtab);
+
+ found = 1;
+ }
+ }
+
+ if (! found)
+ printf (_("\nThere are no relocations in this file.\n"));
+ }
+
+ return 1;
+}
+
+#include "unwind-ia64.h"
+
+/* An absolute address consists of a section and an offset. If the
+ section is NULL, the offset itself is the address, otherwise, the
+ address equals to LOAD_ADDRESS(section) + offset. */
+
+struct absaddr
+ {
+ unsigned short section;
+ bfd_vma offset;
+ };
+
+struct unw_aux_info
+ {
+ struct unw_table_entry
+ {
+ struct absaddr start;
+ struct absaddr end;
+ struct absaddr info;
+ }
+ *table; /* Unwind table. */
+ unsigned long table_len; /* Length of unwind table. */
+ unsigned char * info; /* Unwind info. */
+ unsigned long info_size; /* Size of unwind info. */
+ bfd_vma info_addr; /* starting address of unwind info. */
+ bfd_vma seg_base; /* Starting address of segment. */
+ Elf_Internal_Sym * symtab; /* The symbol table. */
+ unsigned long nsyms; /* Number of symbols. */
+ char * strtab; /* The string table. */
+ unsigned long strtab_size; /* Size of string table. */
+ };
+
+static void find_symbol_for_address PARAMS ((struct unw_aux_info *,
+ struct absaddr, const char **,
+ bfd_vma *));
+static void dump_ia64_unwind PARAMS ((struct unw_aux_info *));
+static int slurp_ia64_unwind_table PARAMS ((FILE *, struct unw_aux_info *,
+ Elf32_Internal_Shdr *));
+
+static void
+find_symbol_for_address (aux, addr, symname, offset)
+ struct unw_aux_info *aux;
+ struct absaddr addr;
+ const char **symname;
+ bfd_vma *offset;
+{
+ bfd_vma dist = (bfd_vma) 0x100000;
+ Elf_Internal_Sym *sym, *best = NULL;
+ unsigned long i;
+
+ for (i = 0, sym = aux->symtab; i < aux->nsyms; ++i, ++sym)
+ {
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC
+ && sym->st_name != 0
+ && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx)
+ && addr.offset >= sym->st_value
+ && addr.offset - sym->st_value < dist)
+ {
+ best = sym;
+ dist = addr.offset - sym->st_value;
+ if (!dist)
+ break;
+ }
+ }
+ if (best)
+ {
+ *symname = (best->st_name >= aux->strtab_size
+ ? "<corrupt>" : aux->strtab + best->st_name);
+ *offset = dist;
+ return;
+ }
+ *symname = NULL;
+ *offset = addr.offset;
+}
+
+static void
+dump_ia64_unwind (aux)
+ struct unw_aux_info *aux;
+{
+ bfd_vma addr_size;
+ struct unw_table_entry * tp;
+ int in_body;
+
+ addr_size = is_32bit_elf ? 4 : 8;
+
+ for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
+ {
+ bfd_vma stamp;
+ bfd_vma offset;
+ const unsigned char * dp;
+ const unsigned char * head;
+ const char * procname;
+
+ find_symbol_for_address (aux, tp->start, &procname, &offset);
+
+ fputs ("\n<", stdout);
+
+ if (procname)
+ {
+ fputs (procname, stdout);
+
+ if (offset)
+ printf ("+%lx", (unsigned long) offset);
+ }
+
+ fputs (">: [", stdout);
+ print_vma (tp->start.offset, PREFIX_HEX);
+ fputc ('-', stdout);
+ print_vma (tp->end.offset, PREFIX_HEX);
+ printf ("), info at +0x%lx\n",
+ (unsigned long) (tp->info.offset - aux->seg_base));
+
+ head = aux->info + (tp->info.offset - aux->info_addr);
+ stamp = BYTE_GET8 ((unsigned char *) head);
+
+ printf (" v%u, flags=0x%lx (%s%s ), len=%lu bytes\n",
+ (unsigned) UNW_VER (stamp),
+ (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
+ UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
+ UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "",
+ (unsigned long) (addr_size * UNW_LENGTH (stamp)));
+
+ if (UNW_VER (stamp) != 1)
+ {
+ printf ("\tUnknown version.\n");
+ continue;
+ }