+ return data == data_end;
+}
+
+static const char *
+get_ia64_vms_note_type (unsigned e_type)
+{
+ static char buff[64];
+
+ switch (e_type)
+ {
+ case NT_VMS_MHD:
+ return _("NT_VMS_MHD (module header)");
+ case NT_VMS_LNM:
+ return _("NT_VMS_LNM (language name)");
+ case NT_VMS_SRC:
+ return _("NT_VMS_SRC (source files)");
+ case NT_VMS_TITLE:
+ return "NT_VMS_TITLE";
+ case NT_VMS_EIDC:
+ return _("NT_VMS_EIDC (consistency check)");
+ case NT_VMS_FPMODE:
+ return _("NT_VMS_FPMODE (FP mode)");
+ case NT_VMS_LINKTIME:
+ return "NT_VMS_LINKTIME";
+ case NT_VMS_IMGNAM:
+ return _("NT_VMS_IMGNAM (image name)");
+ case NT_VMS_IMGID:
+ return _("NT_VMS_IMGID (image id)");
+ case NT_VMS_LINKID:
+ return _("NT_VMS_LINKID (link id)");
+ case NT_VMS_IMGBID:
+ return _("NT_VMS_IMGBID (build id)");
+ case NT_VMS_GSTNAM:
+ return _("NT_VMS_GSTNAM (sym table name)");
+ case NT_VMS_ORIG_DYN:
+ return "NT_VMS_ORIG_DYN";
+ case NT_VMS_PATCHTIME:
+ return "NT_VMS_PATCHTIME";
+ default:
+ snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+ return buff;
+ }
+}
+
+static bfd_boolean
+print_ia64_vms_note (Elf_Internal_Note * pnote)
+{
+ switch (pnote->type)
+ {
+ case NT_VMS_MHD:
+ if (pnote->descsz > 36)
+ {
+ size_t l = strlen (pnote->descdata + 34);
+ printf (_(" Creation date : %.17s\n"), pnote->descdata);
+ printf (_(" Last patch date: %.17s\n"), pnote->descdata + 17);
+ printf (_(" Module name : %s\n"), pnote->descdata + 34);
+ printf (_(" Module version : %s\n"), pnote->descdata + 34 + l + 1);
+ }
+ else
+ printf (_(" Invalid size\n"));
+ break;
+ case NT_VMS_LNM:
+ printf (_(" Language: %s\n"), pnote->descdata);
+ break;
+#ifdef BFD64
+ case NT_VMS_FPMODE:
+ printf (_(" Floating Point mode: "));
+ printf ("0x%016" BFD_VMA_FMT "x\n",
+ (bfd_vma) byte_get ((unsigned char *)pnote->descdata, 8));
+ break;
+ case NT_VMS_LINKTIME:
+ printf (_(" Link time: "));
+ print_vms_time
+ ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+ printf ("\n");
+ break;
+ case NT_VMS_PATCHTIME:
+ printf (_(" Patch time: "));
+ print_vms_time
+ ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+ printf ("\n");
+ break;
+ case NT_VMS_ORIG_DYN:
+ printf (_(" Major id: %u, minor id: %u\n"),
+ (unsigned) byte_get ((unsigned char *)pnote->descdata, 4),
+ (unsigned) byte_get ((unsigned char *)pnote->descdata + 4, 4));
+ printf (_(" Last modified : "));
+ print_vms_time
+ ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata + 8, 8));
+ printf (_("\n Link flags : "));
+ printf ("0x%016" BFD_VMA_FMT "x\n",
+ (bfd_vma) byte_get ((unsigned char *)pnote->descdata + 16, 8));
+ printf (_(" Header flags: 0x%08x\n"),
+ (unsigned) byte_get ((unsigned char *)pnote->descdata + 24, 4));
+ printf (_(" Image id : %s\n"), pnote->descdata + 32);
+ break;
+#endif
+ case NT_VMS_IMGNAM:
+ printf (_(" Image name: %s\n"), pnote->descdata);
+ break;
+ case NT_VMS_GSTNAM:
+ printf (_(" Global symbol table name: %s\n"), pnote->descdata);
+ break;
+ case NT_VMS_IMGID:
+ printf (_(" Image id: %s\n"), pnote->descdata);
+ break;
+ case NT_VMS_LINKID:
+ printf (_(" Linker id: %s\n"), pnote->descdata);
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Print the name of the symbol associated with a build attribute
+ that is attached to address OFFSET. */
+
+static bfd_boolean
+print_symbol_for_build_attribute (FILE * file,
+ unsigned long offset,
+ bfd_boolean is_open_attr)
+{
+ static FILE * saved_file = NULL;
+ static char * strtab;
+ static unsigned long strtablen;
+ static Elf_Internal_Sym * symtab;
+ static unsigned long nsyms;
+ Elf_Internal_Sym * saved_sym = NULL;
+ Elf_Internal_Sym * sym;
+
+ if (section_headers != NULL
+ && (saved_file == NULL || file != saved_file))
+ {
+ Elf_Internal_Shdr * symsec;
+
+ /* Load the symbol and string sections. */
+ for (symsec = section_headers;
+ symsec < section_headers + elf_header.e_shnum;
+ symsec ++)
+ {
+ if (symsec->sh_type == SHT_SYMTAB)
+ {
+ symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
+
+ if (symsec->sh_link < elf_header.e_shnum)
+ {
+ Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+
+ strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
+ 1, strtab_sec->sh_size,
+ _("string table"));
+ strtablen = strtab != NULL ? strtab_sec->sh_size : 0;
+ }
+ }
+ }
+ saved_file = file;
+ }
+
+ if (symtab == NULL || strtab == NULL)
+ {
+ printf ("\n");
+ return FALSE;
+ }
+
+ /* Find a symbol whose value matches offset. */
+ for (sym = symtab; sym < symtab + nsyms; sym ++)
+ if (sym->st_value == offset)
+ {
+ if (sym->st_name >= strtablen)
+ /* Huh ? This should not happen. */
+ continue;
+
+ if (strtab[sym->st_name] == 0)
+ continue;
+
+ if (is_open_attr)
+ {
+ /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
+ and FILE or OBJECT symbols over NOTYPE symbols. We skip
+ FUNC symbols entirely. */
+ switch (ELF_ST_TYPE (sym->st_info))
+ {
+ case STT_FILE:
+ saved_sym = sym;
+ /* We can stop searching now. */
+ sym = symtab + nsyms;
+ continue;
+
+ case STT_OBJECT:
+ saved_sym = sym;
+ continue;
+
+ case STT_FUNC:
+ /* Ignore function symbols. */
+ continue;
+
+ default:
+ break;
+ }
+
+ switch (ELF_ST_BIND (sym->st_info))
+ {
+ case STB_GLOBAL:
+ if (saved_sym == NULL
+ || ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
+ saved_sym = sym;
+ break;
+
+ case STB_LOCAL:
+ if (saved_sym == NULL)
+ saved_sym = sym;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+ continue;
+
+ saved_sym = sym;
+ break;
+ }
+ }
+
+ printf (" (%s: %s)\n",
+ is_open_attr ? _("file") : _("func"),
+ saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
+ return TRUE;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
+ FILE * file)
+{
+ static unsigned long global_offset = 0;
+ unsigned long offset;
+ unsigned int desc_size = is_32bit_elf ? 4 : 8;
+ bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
+
+ if (pnote->descsz == 0)
+ {
+ if (is_open_attr)
+ {
+ printf (_(" Applies from offset %#lx\n"), global_offset);
+ return TRUE;
+ }
+ else
+ {
+ printf (_(" Applies to func at %#lx"), global_offset);
+ return print_symbol_for_build_attribute (file, global_offset, is_open_attr);
+ }
+ }
+
+ if (pnote->descsz != desc_size)
+ {
+ error (_(" <invalid description size: %lx>\n"), pnote->descsz);
+ printf (_(" <invalid descsz>"));
+ return FALSE;
+ }
+
+ offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
+
+ if (is_open_attr)
+ {
+ printf (_(" Applies from offset %#lx"), offset);
+ global_offset = offset;
+ }
+ else
+ {
+ printf (_(" Applies to func at %#lx"), offset);
+ }
+
+ return print_symbol_for_build_attribute (file, offset, is_open_attr);