diff -ruN binutils-2.16-orig/VMSNOTES binutils/VMSNOTES --- binutils-2.16-orig/VMSNOTES Thu Jan 1 01:00:00 1970 +++ binutils/VMSNOTES Wed May 25 09:08:05 2005 @@ -0,0 +1,32 @@ +removed X nisse-i386.c is based on elf32-i386.c +removed X nisse.c is elf.c copied. +X i386vms.sc is elf.sc copied, and .init #-out +X i386vms.sh is probably based on elf_i386.sh +? nisse.sc is handcrafted? is not currently used. (ref from i386vms.sh) +? readnisse.c is loosely based on readelf +nisse2 is based on vms.c? + final_link based on _bfd_generic_final_link from linker.c + need more? +nisse2.c is now named nisse.c + +bfd/: Makefile.in config.bfd configure.in configure targets.c +binutils: Makefile.in +.: configure configure.in +ld/: Makefile.in configure.tgt + +#if 0 +/* +Notes about the vms.h file: + +TIR/EITR definitions seems to be based on starlet tirdef.h and etirdef.h, +with ETIR$ changed to ETIR_S_ + +The same with GSD GPS GSY LSY ENV etc. + +Of the struct eom is the same, but hdr is emh$ + +We will not use these structs or defines, +but $-proper ones + +*/ +#endif diff -ruN binutils-2.16-orig/bfd/Makefile.in binutils/bfd/Makefile.in --- binutils-2.16-orig/bfd/Makefile.in Mon May 2 21:45:46 2005 +++ binutils/bfd/Makefile.in Wed May 25 09:08:05 2005 @@ -1721,6 +1721,9 @@ elf.lo: elf.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/libiberty.h +nisse.lo: nisse.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ + elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/external.h $(INCDIR)/libiberty.h elf32-am33lin.lo: elf32-am33lin.c elf-m10300.c $(INCDIR)/filenames.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mn10300.h \ diff -ruN binutils-2.16-orig/bfd/config.bfd binutils/bfd/config.bfd --- binutils-2.16-orig/bfd/config.bfd Mon Jan 31 18:18:47 2005 +++ binutils/bfd/config.bfd Wed May 25 09:08:05 2005 @@ -534,6 +534,10 @@ targ_selvecs="i386linux_vec bfd_efi_app_ia32_vec" targ64_selvecs=bfd_elf64_x86_64_vec ;; + i386-*-vms) + targ_defvec=bfd_nisse_i386_vec + targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec" + ;; #ifdef BFD64 x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) targ_defvec=bfd_elf64_x86_64_vec diff -ruN binutils-2.16-orig/bfd/configure binutils/bfd/configure --- binutils-2.16-orig/bfd/configure Mon May 2 21:43:54 2005 +++ binutils/bfd/configure Wed May 25 09:08:05 2005 @@ -11556,6 +11556,7 @@ bfd_elf32_i370_vec) tb="$tb elf32-i370.lo elf32.lo $elf" ;; bfd_elf32_i386_freebsd_vec) tb="$tb elf32-i386.lo elf32.lo $elf" ;; bfd_elf32_i386_vec) tb="$tb elf32-i386.lo elf32.lo $elf" ;; + bfd_nisse_i386_vec) tb="$tb nisse.lo elf32-i386.lo elf32.lo $elf" ;; bfd_elf32_i860_little_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; bfd_elf32_i860_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; bfd_elf32_i960_vec) tb="$tb elf32-i960.lo elf32.lo $elf" ;; diff -ruN binutils-2.16-orig/bfd/configure.in binutils/bfd/configure.in --- binutils-2.16-orig/bfd/configure.in Mon May 2 21:43:51 2005 +++ binutils/bfd/configure.in Wed May 25 09:08:05 2005 @@ -603,6 +603,7 @@ bfd_elf32_i370_vec) tb="$tb elf32-i370.lo elf32.lo $elf" ;; bfd_elf32_i386_freebsd_vec) tb="$tb elf32-i386.lo elf32.lo $elf" ;; bfd_elf32_i386_vec) tb="$tb elf32-i386.lo elf32.lo $elf" ;; + bfd_nisse_i386_vec) tb="$tb nisse.lo elf32-i386.lo elf32.lo $elf" ;; bfd_elf32_i860_little_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; bfd_elf32_i860_vec) tb="$tb elf32-i860.lo elf32.lo $elf" ;; bfd_elf32_i960_vec) tb="$tb elf32-i960.lo elf32.lo $elf" ;; diff -ruN binutils-2.16-orig/bfd/nisse.c binutils/bfd/nisse.c --- binutils-2.16-orig/bfd/nisse.c Thu Jan 1 01:00:00 1970 +++ binutils/bfd/nisse.c Mon Jun 13 11:03:39 2005 @@ -0,0 +1,2417 @@ +#include "bfd.h" +#include "bfdver.h" +#include "sysdep.h" +#include "libiberty.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "genlink.h" + +#include"nisse/iafdef.h" +#include"nisse/ihadef.h" +#include"nisse/ihddef.h" +#include"nisse/ihidef.h" +#include"nisse/ihpdef.h" +#include"nisse/ihsdef.h" +#include"nisse/ihvndef.h" +#include"nisse/isddef.h" +#include"nisse/shldef.h" + +#include "elf-bfd.h" // temp extra + +#include "vms.h" + +struct vms_core_data { + char * buffer; + // rest can be derived, and is just shortcuts; + int symtab_size; + char * symtab; + char * symstr; + void * iaf; + int debvbn1; + int debvbn2; + struct _isd * mysection; + struct _isd * mysectionstart; + int fixup_vector_start; + int start_addr; + int fixup_size; +}; + +static char * sections[] = { ".none", ".text", ".data", ".bss", ".comment", ".rodata", ".symstr", ".symtab", ".fix", 0 }; + +static int search_sect(char * s) { + int i; + for(i=0;sections[i];i++) { + if (0==strncmp(s,sections[i],strlen(sections[i]))) + return i; + } + return 0; +} + +int is_abfd_sect(bfd * abfd,asection * sect) { + asection * s; + for(s=abfd->sections; s; s=s->next) { + if (sect==s) + return 1; + } + return 0; +} + +#define VMS_DEBUG 1 + +#define Elf_External_Sym Elf32_External_Sym +#define H_GET_32(x, y) bfd_getl32(y) +#define H_GET_WORD(x, y) bfd_getl32(y) +#define H_GET_SIGNED_WORD(x, y) bfd_getl32(y) +#define H_PUT_32(x, y, z) bfd_putl32(y, z) +#define H_PUT_WORD(x, y, z) bfd_putl32(y, z) +#define H_PUT_SIGNED_WORD(x, y, z) bfd_putl32(y ,z) + +/* Translate an ELF symbol in external format into an ELF symbol in internal + format. */ + +void +nisse_swap_symbol_in (bfd *abfd, + const void *psrc, + const void *pshn, + asymbol /*Elf_Internal_Sym*/ *dst) +{ + const Elf_External_Sym *src = psrc; + const Elf_External_Sym_Shndx *shndx = pshn; + // int signed_vma = get_nisse_backend_data (abfd)->sign_extend_vma; + int signed_vma = 0; // check. added this to be sure. + + dst->name = H_GET_32 (abfd, src->st_name); + if (signed_vma) + dst->value = H_GET_SIGNED_WORD (abfd, src->st_value); + else + dst->value = H_GET_WORD (abfd, src->st_value); + dst->flags = H_GET_WORD (abfd, src->st_size); +#if 0 + dst->st_size = H_GET_WORD (abfd, src->st_size); + dst->st_info = H_GET_8 (abfd, src->st_info); + dst->st_other = H_GET_8 (abfd, src->st_other); + dst->st_shndx = H_GET_16 (abfd, src->st_shndx); + if (dst->st_shndx == SHN_XINDEX) + { + if (shndx == NULL) + abort (); + dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx); + } +#else + { + int i=H_GET_16 (abfd, src->st_shndx); +#if 0 + printf("ii %x %x %x\n",i,src->st_shndx,H_GET_16 (abfd, src->st_shndx)); +#endif + asection * a=abfd->sections; + if (i==255) { + dst->section=&bfd_und_section; + } else { + for (;i && a;i--,a=a->next) ; + if (a) + dst->section = a; + else + dst->section = &bfd_und_section; + } +#if 0 + printf("iii %x %x %x %x\n",i,src->st_shndx,dst->section,dst->section->index); +#endif + } +#endif +} + +/* Translate an ELF symbol in internal format into an ELF symbol in external + format. */ + +void +nisse_swap_symbol_out (bfd *abfd, + asymbol /*const Elf_Internal_Sym*/ *src, + void *cdst, + void *shndx) +{ + unsigned int tmp; + Elf_External_Sym *dst = cdst; + H_PUT_32 (abfd, src->name, dst->st_name); + H_PUT_WORD (abfd, src->value, dst->st_value); + H_PUT_WORD (abfd, src->flags, dst->st_size); +#if 0 + H_PUT_WORD (abfd, src->st_size, dst->st_size); + H_PUT_8 (abfd, src->st_info, dst->st_info); + H_PUT_8 (abfd, src->st_other, dst->st_other); + tmp = src->st_shndx; + if (tmp > SHN_HIRESERVE) + { + if (shndx == NULL) + abort (); + H_PUT_32 (abfd, tmp, shndx); + tmp = SHN_XINDEX; + } + H_PUT_16 (abfd, tmp, dst->st_shndx); +#else + H_PUT_16 (abfd, (short) shndx, dst->st_shndx); +#if 0 + printf("oo %x %x\n",shndx,dst->st_shndx); +#endif +#endif +} + +int section_flags_isd_to_as(int flags) { + int retval=0; + if ((flags&ISD$M_WRT)==0) + retval|= SEC_READONLY; + return retval; +} + +int section_flags_as_to_isd(int flags) { + int retval=0; + if ((flags&SEC_READONLY)==0) + retval|=ISD$M_WRT; + return retval; +} + +int section_type_isd_to_as(int flags) { + int retval=0; + if (flags==ISD$K_NORMAL) + retval|=SEC_CODE; + if (flags==ISD$K_PRVFXD) + retval|=SEC_DATA; + return retval; +} + +int section_type_as_to_isd(int flags) { + int retval=0; + if (flags&SEC_CODE) + retval=ISD$K_NORMAL; + if (flags&SEC_DATA) + retval=ISD$K_PRVFXD; + return retval; +} + +/* Add an output symbol to the output BFD. */ + +static bfd_boolean +generic_add_output_symbol (bfd *output_bfd, size_t *psymalloc, asymbol *sym) +{ + if (bfd_get_symcount (output_bfd) >= *psymalloc) + { + asymbol **newsyms; + bfd_size_type amt; + + if (*psymalloc == 0) + *psymalloc = 124; + else + *psymalloc *= 2; + amt = *psymalloc; + amt *= sizeof (asymbol *); + newsyms = bfd_realloc (bfd_get_outsymbols (output_bfd), amt); + if (newsyms == NULL) + return FALSE; + bfd_get_outsymbols (output_bfd) = newsyms; + } + + bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym; + if (sym != NULL) + ++ bfd_get_symcount (output_bfd); + + return TRUE; +} + +/*-- Part 4.8, linker -------------------------------------------------------*/ + +bfd_boolean +nisse_set_arch_mach (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; +{ + /* If this isn't the right architecture for this backend, and this + isn't the generic backend, fail. */ +#if 0 + if (arch != get_elf_backend_data (abfd)->arch + && arch != bfd_arch_unknown + /* && get_elf_backend_data (abfd)->arch != bfd_arch_unknown*/) + return FALSE; +#endif + + return bfd_default_set_arch_mach (abfd, arch, machine); +} + +bfd_boolean +nisse_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; +{ + // Elf_Internal_Shdr *hdr; + bfd_signed_vma pos; + +#if 0 + if (! abfd->output_has_begun + && ! (_bfd_elf_compute_section_file_positions + (abfd, (struct bfd_link_info *) NULL))) + return FALSE; +#endif + +#if 0 + hdr = &elf_section_data (section)->this_hdr; + pos = hdr->sh_offset + offset; +#endif + if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 + || bfd_bwrite (location, count, abfd) != count) + return FALSE; + + return TRUE; +} + +int find_symtab_int(void * abfd, asymbol ** symbol, char * s) { + int i=0; + while (1) { +#if 0 + if (symbol[i]==0) + return 0; +#endif + if (0==strcmp((*symbol[i]).name,s/*,strlen(routine)*/)) { + return &symbol[i]; + } + i++; + } + return 0; +} + +int find_symtab(void * abfd, void * symtab, long symstr, char * s) { + while (1) { + Elf_External_Sym * src = symtab; + if (src->st_name[0]==0 && src->st_name[1]==0) break; + asymbol dst; + nisse_swap_symbol_in(abfd, src, 0, &dst); + symtab += sizeof(Elf_External_Sym); + if (0==strcmp(symstr+dst.name,s/*,strlen(routine)*/)) { + return dst.name; + } + src++; + } + return 0; +} + +int find_symtab_val(void * abfd, void * symtab, long symstr, char * s) { + while (1) { + Elf_External_Sym * src = symtab; + if (src->st_name[0]==0 && src->st_name[1]==0) break; + asymbol dst; + nisse_swap_symbol_in(abfd, src, 0, &dst); + symtab += sizeof(Elf_External_Sym); + if (0==strcmp(symstr+dst.name,s/*,strlen(routine)*/)) { + return dst.value; + } + src++; + } + return 0; +} + +int search_bfd(bfd * b, char * c) { + int i; + asection * s; + for (s=b->sections; s; s=s->next) { + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = s->orelocation[i]; + if (0==strcmp((*(r->sym_ptr_ptr))->name,c)) + return r; + } + } + return 0; +} + +int search_ibfd(struct bfd_link_info *info, char * c) { + int i, j; + asection * s; + bfd * b; + for (b=info->input_bfds,i=1; b; b=b->link_next) { + if (b->flags & DYNAMIC) { +#if 0 + for (s=b->sections; s; s=s->next) { + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = s->orelocation[i]; + if (0==strcmp((*(r->sym_ptr_ptr))->name,c)) +#endif + for (j=0; jsymcount; j++) { + asymbol * r = b->outsymbols[j]; + if (0==strcmp(r->name,c)) + return i; + } +#if 0 + } +#endif + i++; + } + } + return 0; +} + +int get_new_index(bfd * b, asection * s) { + int i; + asection * o; + for (o=b->sections, i=0; o; o=o->next, i++) { + if (0==strcmp(o->name,s->name)) + return i; + } + return 255; +} + +bfd_boolean +nisse_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + struct vms_core_data * data = abfd->tdata.any; + if (data==0) { + data = bfd_malloc(sizeof(struct vms_core_data)); + abfd->tdata.any=data; + } + bfd *sub; + asection *o; + struct bfd_link_order *p; + size_t outsymalloc; + struct generic_write_global_symbol_info wginfo; + char * readsyms; + struct _isd * mysection; + + if (info->shared) + abfd->flags |= DYNAMIC; + info->relocatable = info->shared; + + bfd * ibfd; + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + if (ibfd->flags & DYNAMIC) { + info->relocatable = 1; //info->shared; + } + + bfd_get_outsymbols (abfd) = NULL; + bfd_get_symcount (abfd) = 0; + outsymalloc = 0; + + int fixup_vector = bfd_malloc(10000000); + int fixup_vector_size = 512; + + memset(fixup_vector, 0, 1000000); + + /* Mark all sections which will be included in the output file. */ + for (o = abfd->sections; o != NULL; o = o->next) + for (p = o->link_order_head; p != NULL; p = p->next) + if (p->type == bfd_indirect_link_order) + p->u.indirect.section->linker_mark = TRUE; + + /* Build the output symbol table. */ + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc)) + return FALSE; + + /* Accumulate the global symbols. */ + wginfo.info = info; + wginfo.output_bfd = abfd; + wginfo.psymalloc = &outsymalloc; + _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info), + _bfd_generic_link_write_global_symbol, + &wginfo); + + /* Make sure we have a trailing NULL pointer on OUTSYMBOLS. We + shouldn't really need one, since we have SYMCOUNT, but some old + code still expects one. */ + if (! generic_add_output_symbol (abfd, &outsymalloc, NULL)) + return FALSE; + + data->mysectionstart=mysection=bfd_malloc(512); + bzero(mysection,512); + + int startaddr=0x10000; + int vbn=8; + + int newaddr=bfd_get_start_address(abfd)-abfd->sections->vma+startaddr; +#if 0 + int j; + for (j=0;jsymcount;j++) { + if (4==strlen(abfd->outsymbols[j]->name) && 0==strncmp("main",abfd->outsymbols[j]->name,4)) newaddr=abfd->outsymbols[j]->value+startaddr; + } +#endif + data->start_addr=newaddr; + bfd_set_start_address(abfd, newaddr); + + for (o = abfd->sections; o != NULL; o = o->next) + { + if (0==strncmp(o->name,".debug",6)) + continue; + if (0==strncmp(o->name,".gnu",4)) + continue; + if (search_sect(o->name)>5) + continue; + //printf("name %s %x %x %x %x\n",o->output_section->name,o->output_section->flags,o->output_section->filepos,o->output_section->output_offset,o->output_section->rawsize); + mysection->isd$w_size=0x10; + mysection->isd$v_vpn=startaddr>>12; + mysection->isd$v_pfc=search_sect(o->name); // borrowed field + mysection->isd$l_vbn=vbn; + mysection->isd$w_pagcnt=1+(bfd_section_size(abfd, o)>>12); + + bfd_set_section_vma(abfd, o->output_section, startaddr); + o->filepos=vbn*512; + o->output_section->filepos=vbn*512; + + vbn+=8*mysection->isd$w_pagcnt; + startaddr+=mysection->isd$w_pagcnt<<12; + + mysection->isd$l_flags=section_flags_as_to_isd(bfd_get_section_flags(abfd, o)); + mysection->isd$b_type=section_type_as_to_isd(bfd_get_section_flags(abfd, o)); + + mysection=(unsigned long)mysection+mysection->isd$w_size; + mysection->isd$w_size=0x0; + + printf("name %s %x %x %x %x %x %x %x %x %x\n",o->output_section->name,o->output_section->flags,o->output_section->filepos,o->output_section->output_offset,o->output_section->rawsize,o->vma,o->output_section->vma,o->filepos,o->output_section->filepos); + + } + + int gbl_sects=0; + + int ibfds; + for (ibfd = info->input_bfds, ibfds=0; ibfd != NULL; ibfd = ibfd->link_next,ibfds++) + if (ibfd->flags & DYNAMIC) { + char * filename = basename(ibfd->filename); + mysection->isd$w_size=0x14+1+strlen(filename); + mysection->isd$v_vpn=startaddr>>12; + //mysection->isd$v_pfc=0; search_sect(o->name); // borrowed field + mysection->isd$l_vbn=vbn; + mysection->isd$w_pagcnt=0; //1+(bfd_section_size(abfd, o)>>12); + + mysection->isd$l_flags=ISD$M_GBL; +#if 0 + mysection->isd$b_type=section_type_as_to_isd(bfd_get_section_flags(abfd, o)); +#endif + memcpy(&mysection->isd$t_gblnam,filename,strlen(filename)); + mysection=(unsigned long)mysection+mysection->isd$w_size; + mysection->isd$w_size=0x0; + gbl_sects++; + } + + if (info->relocatable) + { + /* Allocate space for the output relocs for each section. */ + for (o = abfd->sections; o != NULL; o = o->next) + { + o->reloc_count = 0; + for (p = o->link_order_head; p != NULL; p = p->next) + { + if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + ++o->reloc_count; + else if (p->type == bfd_indirect_link_order) + { + asection *input_section; + bfd *input_bfd; + long relsize; + arelent **relocs; + asymbol **symbols; + long reloc_count; + + input_section = p->u.indirect.section; + input_bfd = input_section->owner; + relsize = bfd_get_reloc_upper_bound (input_bfd, + input_section); + if (relsize < 0) + return FALSE; + relocs = bfd_malloc (relsize); + if (!relocs && relsize != 0) + return FALSE; + symbols = _bfd_generic_link_get_symbols (input_bfd); + reloc_count = bfd_canonicalize_reloc (input_bfd, + input_section, + relocs, + symbols); +#if 0 + free (relocs); +#endif + if (reloc_count < 0) + return FALSE; + BFD_ASSERT ((unsigned long) reloc_count + == input_section->reloc_count); + o->reloc_count += reloc_count; + } + } + if (o->reloc_count > 0) + { + bfd_size_type amt; + + amt = o->reloc_count; + amt *= sizeof (arelent *); + o->orelocation = (arelent **) bfd_alloc (abfd, amt); + if (!o->orelocation) + return FALSE; + o->flags |= SEC_RELOC; + /* Reset the count so that it can be used as an index + when putting in the output relocs. */ + o->reloc_count = 0; + } + } + } + + /* Handle all the link order information for the sections. */ + for (o = abfd->sections; o != NULL; o = o->next) + { + if (0==strncmp(o->name,".debug",6)) + continue; + if (0==strncmp(o->name,".gnu",4)) + continue; +#if 0 + if (o->flags&SEC_DEBUGGING) + continue; +#endif + for (p = o->link_order_head; p != NULL; p = p->next) + { + switch (p->type) + { + case bfd_section_reloc_link_order: + case bfd_symbol_reloc_link_order: + if (! _bfd_generic_reloc_link_order (abfd, info, o, p)) + return FALSE; + break; + case bfd_indirect_link_order: + // if rawsize is workaround because with gnu.warning it segfaults +#if 0 + if (p->u.indirect.section->rawsize) +#endif + if (! _bfd_default_link_order (abfd, info, o, p)) + return FALSE; + break; + default: + if (! _bfd_default_link_order (abfd, info, o, p)) + return FALSE; + break; + } + } + } + + // nisse_write_object_contents(abfd); + + int symtab_size = bfd_get_symcount(abfd) * sizeof(Elf_Internal_Sym); + void * symtab = bfd_malloc(symtab_size); + memset(symtab, 0, symtab_size); + + int i; + + int symstr_size; + + struct bfd_strtab_hash * symstrtab = _bfd_elf_stringtab_init (); // borrowed an independent routine from elf + + void * dest = symtab; + + for (i=0;iname, TRUE, FALSE); + if (index==0) continue; + asymbol as = *abfd->outsymbols[i]; +#if 0 + if (as.section->flags&SEC_DEBUGGING) + continue; +#endif + if (as.flags&0x4000) + continue; + if (as.flags&0x100) + continue; +#if 1 + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + if ((ibfd->flags & DYNAMIC)==0) { + int j; + for(j=0;jsymcount;j++) { + if (0==strcmp(ibfd->outsymbols[j]->name,as.name)) { + if (bfd_is_und_section(ibfd->outsymbols[j]->section)) + as.section=&bfd_und_section; + goto do_it; + } + } + } +#endif +#if 0 + if (as.flags&0x8000) + continue; +#endif + do_it: + if (as.flags&0x8000) + as.section=&bfd_und_section; + if (0==strcmp("_GLOBAL_OFFSET_TABLE_",bfd_get_outsymbols (abfd)[i]->name)) + continue; +#if 0 + if (!is_abfd_sect(abfd,as.section)) + continue; +#endif + printf("symo %s %x %x %x\n",bfd_get_outsymbols (abfd)[i]->name,bfd_get_outsymbols (abfd)[i]->value,bfd_get_outsymbols (abfd)[i]->flags, j=bfd_get_outsymbols (abfd)[i]->section->index); + as.name=index; + as.value+=as.section->output_offset; + if (bfd_is_und_section(as.section)) + nisse_swap_symbol_out (abfd, &as, dest, 255); + else + nisse_swap_symbol_out (abfd, &as, dest, get_new_index(abfd,as.section)); + ((Elf_External_Sym*)dest)->st_other[0]=as.flags&0xff; + dest = dest + sizeof(Elf_External_Sym); + symstr_size=index+1+sizeof(bfd_get_outsymbols (abfd)[i]->name); + } + + //symtab_size=(long)dest-symtab; + + // now assign filepos + + if (bfd_seek (abfd, vbn*512, SEEK_SET) != 0 + || bfd_bwrite (symtab, symtab_size, abfd) != symtab_size) + return FALSE; + data->debvbn1=vbn; + + mysection->isd$w_size=0x10; + mysection->isd$v_vpn=startaddr>>12; + mysection->isd$v_pfc=search_sect(".symtab"); // borrowed field + mysection->isd$l_vbn=vbn; + mysection->isd$w_pagcnt=1+(symtab_size>>12); + + vbn+=8*mysection->isd$w_pagcnt; + startaddr+=mysection->isd$w_pagcnt<<12; + + mysection->isd$l_flags=0; + mysection->isd$b_type=0; + + mysection=(unsigned long)mysection+mysection->isd$w_size; + mysection->isd$w_size=0x0; + + if (bfd_get_symcount (abfd) > 0) + { + if (bfd_seek (abfd, vbn*512, SEEK_SET) != 0 + || ! _bfd_stringtab_emit (abfd, symstrtab)) + return FALSE; + bfd_seek (abfd, vbn*512, SEEK_SET); + readsyms=malloc(symstr_size); + bfd_bread(readsyms, symstr_size, abfd); + } + data->debvbn2=vbn; + + //symstr_size = (long) - symstr; + + mysection->isd$w_size=0x10; + mysection->isd$v_vpn=startaddr>>12; + mysection->isd$v_pfc=search_sect(".symstr"); // borrowed field + mysection->isd$l_vbn=vbn; + mysection->isd$w_pagcnt=1+(symstr_size>>12); + + vbn+=8*mysection->isd$w_pagcnt; + startaddr+=mysection->isd$w_pagcnt<<12; + + mysection->isd$l_flags=0; + mysection->isd$b_type=0; + + mysection=(unsigned long)mysection+mysection->isd$w_size; + mysection->isd$w_size=0x0; + + data->fixup_vector_start = startaddr >> 9; + + struct _iaf * iaf = fixup_vector; + iaf->iaf$l_g_fixoff = 512; + + int * addr_g; + int * addr_d; + + int globals = 0; + int locals = 0; + int dots=0; + + asection * b; + + int secno; + int ibfd_no; + + printf("bfd_count_sections(abfd) %x\n",bfd_count_sections(abfd)); + long glbs[bfd_count_sections(abfd)]; // or bfd_count_sections(abfd) + long locs[bfd_count_sections(abfd)]; // or bfd_count_sections(abfd) + long glba[bfd_count_sections(abfd)]; // or bfd_count_sections(abfd) + long loca[bfd_count_sections(abfd)]; // or bfd_count_sections(abfd) + long wth_g=0; + long wth_l=0; + memset(glbs,0,4*bfd_count_sections(abfd)); + memset(locs,0,4*bfd_count_sections(abfd)); + memset(glba,0,4*bfd_count_sections(abfd)); + memset(loca,0,4*bfd_count_sections(abfd)); + +#if 0 + for (ibfd = info->input_bfds, i=1; ibfd != NULL; ibfd = ibfd->link_next,ibfds++) + if (ibfd->flags & DYNAMIC) { + glbs[i]=0; + locs[i]=0; + for (b=ibfd->sections, secno=0; b; b=b->next) { + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = b->orelocation[i]; + int ret=search_bfd(abfd, (*(r->sym_ptr_ptr))->name); + if (ret) { + if (r->howto->pc_relative==0) { + glbs[i]++; + } else { + locs[i]++; + } + break; + } + } + } // for b=ibfd->sect + if (glbs[i]) + wth_g++; + if (locs[i]) + wth_l++; + i++; + } +#endif + + for (o = abfd->sections, secno=0; o != NULL; o = o->next, secno++) { + if (o->flags&SEC_DEBUGGING) + continue; + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = o->orelocation[i]; + int symtab_offset=(find_symtab(abfd,symtab,readsyms,(*(r->sym_ptr_ptr))->name)<<8); + if (symtab_offset==0) + continue; + int ret=search_ibfd(info, (*(r->sym_ptr_ptr))->name); + if (r->howto->pc_relative==0) { + globals++; + glbs[secno]++; + } else { + locals++; + locs[secno]++; + } + } + } + + for(i=0;iiaf$l_dotadroff = 512 + 4*2*2*wth_g + globals*sizeof(Elf32_External_Rela)+ 4*2; + iaf->iaf$l_shlstoff = iaf->iaf$l_dotadroff + 4*2*2*wth_l + locals*sizeof(Elf32_External_Rela); + +#if 0 + for (b=abfd->sections; b; b=b->next) { + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = b->orelocation[i]; + if (r->howto->pc_relative==0) { + globals++; + } else { + locals++; + } + } + } +#endif + + addr_g = fixup_vector+iaf->iaf$l_g_fixoff; + addr_d = fixup_vector+iaf->iaf$l_dotadroff; + + for(i=0;iiaf$l_shlstoff; + data->fixup_size=iaf->iaf$l_shlstoff+sizeof(struct _shl)*(1+gbl_sects); + + char * filename = basename(abfd->filename); + memcpy(&shlst[0].shl$t_imgnam,filename,strlen(filename)); + shlst[0].shl$l_permctx=abfd; + for (ibfd = info->input_bfds, i=1; ibfd != NULL; ibfd = ibfd->link_next) + if (ibfd->flags & DYNAMIC) { + char * filename = basename(ibfd->filename); + memcpy(&shlst[i].shl$t_imgnam,filename,strlen(filename)); + shlst[i].shl$l_permctx=ibfd; // zero later? + i++; + } + + addr_g = fixup_vector+iaf->iaf$l_g_fixoff; + addr_d = fixup_vector+iaf->iaf$l_dotadroff; + + for (b=abfd->sections, secno=0; b; b=b->next,secno++) { +#if 0 + if (glbs[secno]) { + *addr_g++=glbs[secno]; + *addr_g++=secno; + } + if (locs[secno]) { + *addr_d++=locs[secno]; + *addr_d++=secno; + } + + Elf32_External_Rela * r_g=addr_g; + Elf32_External_Rela * r_d=addr_d; +#endif + + asection * o=b; + if (o->flags&SEC_DEBUGGING) + continue; + for (i=0; ireloc_count; i++) { + struct reloc_cache_entry * r = b->orelocation[i]; + int ret=search_ibfd(info, (*(r->sym_ptr_ptr))->name); + ret=secno; + if (r->howto->pc_relative==0) { + int symtab_offset=(find_symtab(abfd,symtab,readsyms,(*(r->sym_ptr_ptr))->name)<<8); + if (symtab_offset==0) { + continue; + } + Elf32_External_Rela * r_g=glba[ret]; + int * tmp=&r_g->r_offset; + *tmp=r->address; + tmp=&r_g->r_info; + int tmp2=r->howto->type|symtab_offset; + *tmp=tmp2; + glba[ret]+=sizeof(Elf32_External_Rela); + r_g++; + } else { + int symtab_offset=(find_symtab(abfd,symtab,readsyms,(*(r->sym_ptr_ptr))->name)<<8); + if (symtab_offset==0) { + continue; + } + Elf32_External_Rela * r_d=loca[ret]; + int * tmp=&r_d->r_offset; + *tmp=r->address; + tmp=&r_d->r_info; + int tmp2=r->howto->type|symtab_offset; + *tmp=tmp2; + loca[ret]+=sizeof(Elf32_External_Rela); + r_d++; + } + } +#if 0 + addr_g=r_g; + addr_d=r_d; + if (glbs[secno]) { + *addr_g++=0; + *addr_g++=0; + } + if (locs[secno]) { + *addr_d++=0; + *addr_d++=0; + } +#endif + } + + if (bfd_seek (abfd, vbn*512, SEEK_SET) != 0 + || bfd_bwrite (fixup_vector, data->fixup_size, abfd) != data->fixup_size) + return FALSE; + + mysection->isd$w_size=0x10; + mysection->isd$v_vpn=startaddr>>12; + mysection->isd$v_pfc=search_sect(".fix"); // borrowed field + mysection->isd$l_vbn=vbn; + mysection->isd$w_pagcnt=1+(data->fixup_size>>12); + + vbn+=8*mysection->isd$w_pagcnt; + startaddr+=mysection->isd$w_pagcnt<<12; + + mysection->isd$l_flags=ISD$M_FIXUPVEC; + mysection->isd$b_type=0; + + mysection=(unsigned long)mysection+mysection->isd$w_size; + mysection->isd$w_size=0x0; + + data->mysection=mysection; + + return TRUE; +} + +/* Get the size of the section headers. */ + +static int +nisse_sizeof_headers (abfd, reloc) + bfd *abfd ATTRIBUTE_UNUSED; + bfd_boolean reloc ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_sizeof_headers(%p, %s)\n", abfd, (reloc)?"True":"False"); +#endif + return 512; +} + +/* Provides default handling of relocation effort for back ends + which can't be bothered to do it efficiently. */ + +static bfd_byte * +not_nisse_bfd_get_relocated_section_contents (abfd, link_info, link_order, data, + relocateable, symbols) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; + struct bfd_link_order *link_order ATTRIBUTE_UNUSED; + bfd_byte *data ATTRIBUTE_UNUSED; + bfd_boolean relocateable ATTRIBUTE_UNUSED; + asymbol **symbols ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_get_relocated_section_contents(%p, %p, %p, %p, %s, %p)\n", + abfd, link_info, link_order, data, (relocateable)?"True":"False", symbols); +#endif + exit(46); + return 0; +} + +/* ??? */ + +static bfd_boolean +nisse_bfd_relax_section (abfd, section, link_info, again) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; + bfd_boolean *again ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_relax_section(%p, %s, %p, )\n", + abfd, section->name, link_info); +#endif + return TRUE; +} + +static bfd_boolean +nisse_bfd_gc_sections (abfd, link_info) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_gc_sections(%p, %p)\n", abfd, link_info); +#endif + return TRUE; +} + +static bfd_boolean +nisse_bfd_merge_sections2 (abfd, link_info) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_merge_sections(%p, %p)\n", abfd, link_info); +#endif + return TRUE; +} + +/* Create a hash table for the linker. Different backends store + different information in this table. */ + +static struct bfd_link_hash_table * +nisse_bfd_link_hash_table_create2 (abfd) + bfd *abfd ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_link_hash_table_create(%p)\n", abfd); +#endif + return 0; +} + +/* Free a linker hash table. */ + +static void +nisse_bfd_link_hash_table_free2 (hash) + struct bfd_link_hash_table *hash ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_link_hash_table_free(%p)\n", abfd); +#endif +} + +/* Add symbols from this object file into the hash table. */ + +static bfd_boolean +nisse_bfd_link_add_symbols_not (abfd, link_info) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_link_add_symbols(%p, %p)\n", abfd, link_info); +#endif + return FALSE; +} + +/* Do a link based on the link_order structures attached to each + section of the BFD. */ + +static bfd_boolean +nisse_bfd_final_link2 (abfd, link_info) + bfd *abfd ATTRIBUTE_UNUSED; + struct bfd_link_info *link_info ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_final_link(%p, %p)\n", abfd, link_info); +#endif + return _bfd_generic_final_link(abfd,link_info); +} + +/* Should this section be split up into smaller pieces during linking. */ + +static bfd_boolean +nisse_bfd_link_split_section (abfd, section) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section ATTRIBUTE_UNUSED; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_bfd_link_split_section(%p, %s)\n", abfd, section->name); +#endif + return FALSE; +} +//================================= + +static bfd_boolean +nisse_mkobject (abfd) + bfd *abfd; +{ +#if NISSE_DEBUG + nisse_debug (1, "nisse_mkobject(%p)\n", abfd); +#endif + +#if 0 + if (!vms_initialize (abfd)) + return 0; +#endif + + { + const bfd_arch_info_type *arch = bfd_scan_arch ("i386"); + if (arch == 0) + { + bfd_set_error(bfd_error_wrong_format); + return 0; + } + abfd->arch_info = arch; + } + + return TRUE; +} + +/* Write cached information into a file being written, at bfd_close. */ + +static bfd_boolean +nisse_write_object_contents (abfd) + bfd *abfd; +{ + struct vms_core_data * data=abfd->tdata.any; + char s[10] = BFD_VERSION_STRING; + struct _ihd * header; + struct _iha * active; + struct _isd * section; + struct _ihi * name; + struct _ihvn * vers; + struct _ihs * debug; +#if NISSE_DEBUG + nisse_debug (1, "nisse_write_object_contents(%p)\n", abfd); +#endif + + char * buffer = bfd_malloc(512*10); + + header=bfd_malloc(512); + bzero(header,512); + + header->ihd$w_activoff=0x30; + header->ihd$w_symdbgoff=header->ihd$w_activoff+sizeof(struct _ihs); + header->ihd$w_imgidoff=header->ihd$w_symdbgoff+sizeof(struct _iha); + header->ihd$w_size=header->ihd$w_imgidoff+sizeof(struct _ihi); + + header->ihd$w_patchoff=0; + header->ihd$w_version_array_off=0; + header->ihd$w_majorid=IHD$K_MAJORID; + header->ihd$w_minorid=IHD$K_MINORID; + header->ihd$b_hdrblkcnt=1; + if (abfd->flags&DYNAMIC==0) + header->ihd$b_imgtype=IHD$K_EXE; + else + header->ihd$b_imgtype=IHD$K_LIM; + + header->ihd$l_iafva=data->fixup_vector_start; + + active=(unsigned long)header+header->ihd$w_activoff; + section=(unsigned long)header+header->ihd$w_size; + name=(unsigned long)header+header->ihd$w_imgidoff; + vers=(unsigned long)header+header->ihd$w_version_array_off; + debug=(unsigned long)header+header->ihd$w_symdbgoff; + + active->iha$l_tfradr1=data->start_addr; // do not forget this + + char * filename = basename(abfd->filename); + name->ihi$t_imgnam [0]=strlen(filename); + strncpy(&name->ihi$t_imgnam [1], filename, name->ihi$t_imgnam [0]); + name->ihi$t_imgid [0]=1; + name->ihi$t_imgid [1]=32; + name->ihi$t_linkid [0]=strlen(BFD_VERSION_STRING); + strncpy(&name->ihi$t_linkid[1],s,name->ihi$t_linkid [0]); + + debug->ihs$l_dstvbn=data->debvbn1; + debug->ihs$l_dmtvbn=data->debvbn2; // borrowing this + + if (((long)section+(long)(data->mysection)-(long)(data->mysectionstart))>=((long)header+512)) + { + printf("section overflow\n"); + exit(42); + } + + bcopy(data->mysectionstart,section,(unsigned long)(data->mysection)-(unsigned long)(data->mysectionstart)); + + if (abfd->section_count > 0) /* we have sections */ + { +#if 0 + if (section->isd$w_size==0) + break; + if (section->isd$w_size==0xffffffff) { + int no=((unsigned long)section-(unsigned long)buffer)>>9; + section=buffer+512*(no+1); + continue; + } + nisse_section[i].eisd$l_eisdsize=section->isd$w_size; + nisse_section[i].eisd$l_secsize=section->isd$w_pagcnt; + nisse_section[i].eisd$l_virt_addr=section->isd$l_vpnpfc; + nisse_section[i].eisd$l_flags=section->isd$l_flags; + nisse_section[i].eisd$l_vbn=section->isd$l_vbn; + nisse_section[i].eisd$l_ident=section->isd$l_ident; + bcopy(section->isd$t_gblnam,nisse_section[i].eisd$t_gblnam,44); + section=(unsigned long)section+section->isd$w_size; + i++; +#endif + } + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 + || bfd_bwrite ((PTR) header, 512, abfd) != 512) + return FALSE; + + return TRUE; +} + +//================================= + +#if 1 +static vms_debug() {} +#else +#define vms_debug fprintf +#endif + +static long nisse_get_symtab_upper_bound + PARAMS ((bfd *abfd)); +static long nisse_canonicalize_symtab + PARAMS ((bfd *abfd, asymbol **symbols)); +static void nisse_print_symbol + PARAMS ((bfd *abfd, PTR file, asymbol *symbol, bfd_print_symbol_type how)); +static void nisse_get_symbol_info + PARAMS ((bfd *abfd, asymbol *symbol, symbol_info *ret)); +static asymbol *nisse_bfd_make_debug_symbol + PARAMS ((bfd *abfd, void *ptr, unsigned long size)); +static long nisse_read_minisymbols + PARAMS ((bfd *abfd, bfd_boolean dynamic, PTR *minisymsp, + unsigned int *sizep)); +static asymbol *nisse_minisymbol_to_symbol + PARAMS ((bfd *abfd, bfd_boolean dynamic, const PTR minisym, asymbol *sym)); +static long nisse_get_reloc_upper_bound + PARAMS ((bfd *abfd, asection *sect)); +static long nisse_canonicalize_reloc + PARAMS ((bfd *abfd, asection *srcsec, arelent **location, + asymbol **symbols)); +static bfd_boolean nisse_bfd_is_local_label_name + PARAMS ((bfd *abfd, const char *)); +static bfd_boolean nisse_bfd_is_target_special_symbol + PARAMS ((bfd *abfd, asymbol *)); +static alent *nisse_get_lineno + PARAMS ((bfd *abfd, asymbol *symbol)); +static bfd_boolean nisse_find_nearest_line + PARAMS ((bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, + const char **file, const char **func, unsigned int *line)); + +#define nisse_make_empty_symbol _bfd_generic_make_empty_symbol +#define nisse_bfd_link_just_syms _bfd_generic_link_just_syms +#define nisse_bfd_is_group_section bfd_generic_is_group_section +#define nisse_bfd_discard_group bfd_generic_discard_group +#define nisse_section_already_linked _bfd_generic_section_already_linked +#define nisse_bfd_link_add_symbols _bfd_generic_link_add_symbols + +static const struct reloc_howto_struct * nisse_bfd_reloc_type_lookup(bfd *, bfd_reloc_code_real_type); +static long nisse_get_dynamic_symtab_upper_bound (bfd *); +static long nisse_canonicalize_dynamic_symtab (bfd *, asymbol **); +#define nisse_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab +static long nisse_get_dynamic_reloc_upper_bound (bfd *); +static long nisse_canonicalize_dynamic_reloc (bfd *, arelent **, asymbol **); + +#define nisse_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define nisse_bfd_link_hash_table_free _bfd_generic_link_hash_table_free +#define nisse_bfd_merge_sections bfd_generic_merge_sections +#define nisse_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents + +extern const bfd_target * bfd_elf32_object_p PARAMS ((bfd *)); +extern const bfd_target *bfd_generic_archive_p PARAMS ((bfd *abfd)); + +static const struct bfd_target * _bfd_nisse_target PARAMS ((bfd * )); + +const bfd_target bfd_nisse_i386_vec = +{ + "nisse-i386", /* name */ + bfd_target_unknown_flavour, + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ + + (HAS_RELOC | HAS_SYMS + | DYNAMIC | WP_TEXT | D_PAGED), /* object flags */ + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY + | SEC_CODE | SEC_DATA | SEC_EXCLUDE + | SEC_IN_MEMORY), /* sect flags */ + 0, /* symbol_leading_char */ + ' ', /* ar_pad_char */ + 15, /* ar_max_namelen */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, + + {_bfd_dummy_target, _bfd_nisse_target, /* bfd_check_format */ + _bfd_dummy_target, _bfd_dummy_target}, + {bfd_false, nisse_mkobject, /* bfd_set_format */ + bfd_false, bfd_false}, + {bfd_false, nisse_write_object_contents, /* bfd_write_contents */ + bfd_false, bfd_false}, + + BFD_JUMP_TABLE_GENERIC (_bfd_generic), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (nisse), + BFD_JUMP_TABLE_RELOCS (nisse), + BFD_JUMP_TABLE_WRITE (nisse), + BFD_JUMP_TABLE_LINK (nisse), + BFD_JUMP_TABLE_DYNAMIC (nisse), + + NULL, + + (PTR) 0 +}; + +/* Check the format for a file being read. + Return a (bfd_target *) if it's an object file or zero if not. */ + +static const struct bfd_target * +_bfd_nisse_target (abfd) + bfd *abfd; +{ + int err = 0; + int prev_type; + const struct bfd_target *target_vector = 0; + const bfd_arch_info_type *arch = 0; + PTR tdata_save = abfd->tdata.any; + bfd_vma saddr_save = bfd_get_start_address (abfd); + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) + goto err_wrong_format; + + prev_type = -1; + + /* set arch_info to i386 */ + + arch = bfd_scan_arch ("i386"); + + abfd->arch_info = arch; + + target_vector = &bfd_nisse_i386_vec; + + char buf[512]; + bfd_bread(buf, 512, abfd); + + struct _ihd * ehdr32 = buf; + + if (ehdr32->ihd$w_majorid!=IHD$K_MAJORID) + goto err_wrong_format; + + if (ehdr32->ihd$b_imgtype==IHD$K_LIM) + abfd->flags|=DYNAMIC; + + abfd->flags |= D_PAGED; + abfd->flags|=HAS_SYMS; + + struct _iha * active; + struct _isd * section; + struct _ihi * name; + struct _ihvn * vers; + struct _ihs * debug; + struct _iaf * iaf; + int i; + char * buffer = bfd_malloc(512*ehdr32->ihd$b_hdrblkcnt+5120000); + + struct vms_core_data * data = bfd_malloc(sizeof(struct vms_core_data)); + data->buffer=buffer; + abfd->tdata.any=data; + + active=(unsigned long)ehdr32+ehdr32->ihd$w_activoff; + // section=(unsigned long)ehdr32+ehdr32->ihd$w_isdoff; + section=(void*)active; + section=(unsigned long)buffer+ehdr32->ihd$w_size; + name=(unsigned long)ehdr32+ehdr32->ihd$w_imgidoff; + vers=(unsigned long)ehdr32+ehdr32->ihd$w_version_array_off; + debug=(unsigned long)ehdr32+ehdr32->ihd$w_symdbgoff; + iaf=(unsigned long)ehdr32+ehdr32->ihd$l_iafva; + +#if 0 + // only for object files... + set_start_address(abfd, active->iha$l_tfradr1); + // not yet? adr2,3 iha$l_inishr + bfd_set_start_address (abfd, active->iha$l_tfradr1); +#endif + + // nisse_section=malloc(sizeof(struct _isd)); +#if 0 + nisse_name=malloc(sizeof(struct _ihi)); + nisse_vers=malloc(sizeof(struct _img_version_array)); + nisse_debug=malloc(sizeof(struct _ihs)); + + bzero(nisse_header,512); + + nisse_header->eihd$l_size=ehdr32->ihd$w_size; + nisse_header->eihd$l_activoff=ehdr32->ihd$w_activoff; + nisse_header->eihd$l_symdbgoff=ehdr32->ihd$w_symdbgoff; + nisse_header->eihd$l_imgidoff=ehdr32->ihd$w_imgidoff; + nisse_header->eihd$l_patchoff=ehdr32->ihd$w_patchoff; + nisse_header->eihd$l_version_array_off=ehdr32->ihd$w_version_array_off; + nisse_header->eihd$l_majorid=ehdr32->ihd$w_majorid; + nisse_header->eihd$l_minorid=ehdr32->ihd$w_minorid; + nisse_header->eihd$l_hdrblkcnt=ehdr32->ihd$b_hdrblkcnt; + nisse_header->eihd$l_imgtype=ehdr32->ihd$b_imgtype; + nisse_header->eihd$q_privreqs=ehdr32->ihd$q_privreqs; + nisse_header->eihd$l_iochancnt=ehdr32->ihd$w_iochancnt; + nisse_header->eihd$l_imgiocnt=ehdr32->ihd$w_imgiocnt; + nisse_header->eihd$l_lnkflags=ehdr32->ihd$l_lnkflags; + nisse_header->eihd$l_ident=ehdr32->ihd$l_ident; + nisse_header->eihd$l_sysver=ehdr32->ihd$l_sysver; + nisse_header->eihd$w_alias=ehdr32->ihd$w_alias; +#endif + +#if 0 + nisse_active->eiha$l_tfradr1=active->iha$l_tfradr1; + nisse_active->eiha$l_tfradr2=active->iha$l_tfradr2; + nisse_active->eiha$l_tfradr3=active->iha$l_tfradr3; + nisse_active->eiha$l_inishr=active->iha$l_inishr; +#endif + +#if 0 + bcopy(name->ihi$t_imgnam,nisse_name->eihi$t_imgnam,40); + bcopy(name->ihi$t_imgnam,nisse_name->eihi$t_imgnam,16); + bcopy(name->ihi$t_imgid,nisse_name->eihi$t_imgid,16); + nisse_name->eihi$q_linktime=name->ihi$q_linktime; + bcopy(name->ihi$t_linkid,nisse_name->eihi$t_linkid,16); +#endif + +#if 0 + nisse_debug->eihs$l_dstvbn=debug->ihs$l_dstvbn; + nisse_debug->eihs$l_gstvbn=debug->ihs$l_gstvbn; + nisse_debug->eihs$l_dstsize=debug->ihs$w_dstblks; + nisse_debug->eihs$l_gstsize=debug->ihs$w_gstrecs; + nisse_debug->eihs$l_dmtvbn=debug->ihs$l_dmtvbn; + nisse_debug->eihs$l_dmtbytes=debug->ihs$l_dmtbytes; + // nisse_debug->eihs$l_dstblks=debug->ihs$l_dstblks; + // nisse_debug->eihs$l_gstrecs=debug->ihs$l_gstrecs; +#endif + + bfd_seek (abfd, (file_ptr) 0, SEEK_SET); + bfd_bread(buffer, 512*ehdr32->ihd$b_hdrblkcnt+5120000, abfd); + + char * symtab = 0; + int symtab_size; + char * symstr = 0; + int symstr_size; + + i=0; + + section=(unsigned long)buffer+ehdr32->ihd$w_size; + + char done[32]; + memset(done, 0, 32); + + while (section<(buffer+512*ehdr32->ihd$b_hdrblkcnt)) { + asection * as; + if (section->isd$w_size==0) + break; +#if 0 + if (done[section->isd$v_pfc]) + goto do_next; + done[section->isd$v_pfc]=1; +#endif + if (section->isd$v_gbl) + as = bfd_make_section(abfd, §ion->isd$t_gblnam); + else + as = bfd_make_section(abfd, sections[section->isd$v_pfc]); //_malloc(sizeof(asection)); +#if 0 + asection * as=bfd_malloc(sizeof(asection)); + memset(as,0,sizeof(asection)); + bfd_section_list_insert(abfd, abfd->section_tail, as); + bfd_count_sections(abfd)++; + as->index=i; +#endif + i++; + if (section->isd$w_size==0xffffffff) { + int no=((unsigned long)section-(unsigned long)buffer)>>9; + section=buffer+512*(no+1); + continue; + } +#if 0 + nisse_section[i].eisd$l_eisdsize=section->isd$w_size; +#endif + +#if 0 + nisse_section[i].eisd$l_secsize=section->isd$w_pagcnt; +#endif + bfd_section_size(abfd, as) = 8*512*section->isd$w_pagcnt; + +#if 0 + nisse_section[i].eisd$l_virt_addr=section->isd$l_vpnpfc; +#endif + bfd_set_section_vma(abfd, as, section->isd$l_vpnpfc*4096); + // bfd_set_section_lma(abfd, as, section->isd$l_vpnpfc*4096); // check? + +#if 0 + nisse_section[i].eisd$l_flags=section->isd$l_flags; +#endif + int excl=0; + if (abfd->flags&DYNAMIC) + excl=SEC_EXCLUDE; + int more_flags=0; + if (abfd->flags&DYNAMIC) + more_flags=SEC_ALLOC|SEC_LOAD; + + bfd_set_section_flags(abfd, as, SEC_HAS_CONTENTS|section_type_isd_to_as(section->isd$b_type)|section_flags_isd_to_as(section->isd$l_flags)|excl|more_flags); + +#if 0 + nisse_section[i].eisd$l_vbn=section->isd$l_vbn; +#endif + as->filepos=512*section->isd$l_vbn; + +#if 0 + nisse_section[i].eisd$l_ident=section->isd$l_ident; +#endif + +#if 0 + bcopy(section->isd$t_gblnam,nisse_section[i].eisd$t_gblnam,44); +#endif + + if (debug->ihs$l_dstvbn==section->isd$l_vbn) { + symtab=buffer+debug->ihs$l_dstvbn*512; + data->symtab=symtab; + data->symtab_size=section->isd$w_pagcnt<<12; // gross + } + + if (debug->ihs$l_dmtvbn==section->isd$l_vbn) { + symstr=buffer+debug->ihs$l_dmtvbn*512; + data->symstr=symstr; + } + + if (section->isd$l_flags&ISD$M_FIXUPVEC) { + // whynot? iaf=(int)buffer+(section->isd$v_vpn<<12); + iaf=buffer+section->isd$l_vbn*512; + data->iaf=iaf; + } + + do_next: + section=(unsigned long)section+section->isd$w_size; + } + + return target_vector; + + err_wrong_format: + bfd_set_error (bfd_error_wrong_format); + error_ret: + if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) + bfd_release (abfd, abfd->tdata.any); + abfd->tdata.any = tdata_save; + bfd_set_start_address (abfd, saddr_save); + + return NULL; +} + +int +bfd_nisse_get_nisse_syms(bfd * abfd, asymbol **allocation, char * symtab, char * symstr, bfd_boolean dynamic) { + if (symtab && symstr) +#if 0 + bfd_set_file_flags(abfd, HAS_SYMS); +#else + abfd->flags|=HAS_SYMS; +#endif + + symstr; + + int outsymalloc=0; + + int j; + + int count=0; + + char * symtmp=symtab; + for (j=0;1;j++,count++) { + Elf_External_Sym * src = symtmp; + if (src->st_name[0]==0 && src->st_name[1]==0) break; + symtmp += sizeof(Elf_External_Sym); + } + + asymbol * symbase = bfd_zalloc(abfd, count * sizeof (asymbol)); + + for (j=0;1;j++) { + Elf_External_Sym * src = symtab; + if (src->st_name[0]==0 && src->st_name[1]==0) break; +#if 0 + asymbol * sym = bfd_malloc(sizeof(asymbol)); +#else + asymbol * sym = &symbase[j]; +#endif + asymbol dst; + nisse_swap_symbol_in(abfd, src, 0, &dst); + sym->flags=src->st_other[0]; + if (abfd->flags & DYNAMIC) + sym->flags|=BSF_DYNAMIC; + sym->value=dst.value; + { +#if 0 + int i=dst.section->index; + asection * a=abfd->sections; + for (;i;i--,a=a->next) ; +#endif + // sym->value+=a->vma; + } + symtab += sizeof(Elf_External_Sym); + src++; + sym->the_bfd = abfd; +#if 0 + sym->section = abfd->sections; +#else + sym->section = dst.section; +#endif + sym->name = (long)symstr+dst.name; + printf("symi %s %x %x %x\n",sym->name,sym->value,sym->flags, sym->section->index); +#if 0 + symstr += strlen(symstr); + symstr++; + if (strlen(symstr)==0) break; +#endif +#if 0 + if (! generic_add_output_symbol (abfd, &outsymalloc, sym)) + return FALSE; +#endif + } + printf("%x symbols read\n",j); + + long l = j; + + asymbol ** symbols = allocation; + //asymbol ** sym = abfd->outsymbols; // was: symbase; + asymbol * sym = symbase; + while (l-- > 0) + { + *symbols++ = sym; // was: &sym->symbol; and without *sym + sym++; + } + *symbols = 0; /* Final null pointer */ + + return j; +} + +/*-- Part 4.6, relocations --------------------------------------------------*/ + +/* Return the number of bytes required to store the relocation information + associated with section sect attached to bfd abfd. + If an error occurs, return -1. */ + +static long +nisse_get_reloc_upper_bound (abfd, section) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_get_reloc_upper_bound(%p, %s)\n", abfd, section->name); +#endif + struct vms_core_data * data = abfd->tdata.any; + printf("reloc size %x\n",data->fixup_size); + return data->fixup_size; //check +} + +/* Call the back end associated with the open BFD abfd and translate the + external form of the relocation information attached to sec into the + internal canonical form. Place the table into memory at loc, which has + been preallocated, usually by a call to bfd_get_reloc_upper_bound. + Returns the number of relocs, or -1 on error. */ + +static long +nisse_canonicalize_reloc (abfd, section, location, symbols) + bfd *abfd; + asection *section; + arelent **location; + asymbol **symbols; +{ +#if VMS_DEBUG + vms_debug (1, "vms_canonicalize_reloc(%p, %s, , )\n", abfd, section->name); +#endif + return bfd_nisse_get_nisse_relocs(abfd, location, symbols, FALSE); + exit(44); + return FALSE; +} + +/*---------------------------------------------------------------------------*/ +/* this is just copied from ecoff-alpha, needs to be fixed probably */ + +/* How to process the various reloc types. */ + +static bfd_reloc_status_type +reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc ATTRIBUTE_UNUSED; + asymbol *sym ATTRIBUTE_UNUSED; + PTR data ATTRIBUTE_UNUSED; + asection *sec ATTRIBUTE_UNUSED; + bfd *output_bfd ATTRIBUTE_UNUSED; + char **error_message ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "reloc_nil(abfd %p, output_bfd %p)\n", abfd, output_bfd); + vms_debug (2, "In section %s, symbol %s\n", + sec->name, sym->name); + vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n", + reloc->sym_ptr_ptr[0]->name, + (unsigned long)reloc->address, + (unsigned long)reloc->addend, reloc->howto->name); + vms_debug (2, "data at %p\n", data); +/* _bfd_hexdump (2, data, bfd_get_reloc_size(reloc->howto),0); */ +#endif + + return bfd_reloc_ok; +} + +#define R_386_32 1 +#define R_386_PC32 2 + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value + from smaller values. Start with zero, widen, *then* decrement. */ +#define MINUS_ONE (((bfd_vma)0) - 1) + +static reloc_howto_type alpha_howto_table[] = +{ + HOWTO (ALPHA_R_IGNORE, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "IGNORE", /* name */ + TRUE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_386_32", + TRUE, 0xffffffff, 0xffffffff, FALSE), + HOWTO(R_386_PC32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_386_PC32", + TRUE, 0xffffffff, 0xffffffff, TRUE), + + /* A 64 bit reference to a symbol. */ + HOWTO (ALPHA_R_REFQUAD, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "REFQUAD", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 21 bit branch. The native assembler generates these for + branches within the text segment, and also fills in the PC + relative offset in the instruction. */ + HOWTO (ALPHA_R_BRADDR, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "BRADDR", /* name */ + TRUE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A hint for a jump to a register. */ + HOWTO (ALPHA_R_HINT, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "HINT", /* name */ + TRUE, /* partial_inplace */ + 0x3fff, /* src_mask */ + 0x3fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 16 bit PC relative offset. */ + HOWTO (ALPHA_R_SREL16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "SREL16", /* name */ + TRUE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 32 bit PC relative offset. */ + HOWTO (ALPHA_R_SREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "SREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 64 bit PC relative offset. */ + HOWTO (ALPHA_R_SREL64, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "SREL64", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Push a value on the reloc evaluation stack. */ + HOWTO (ALPHA_R_OP_PUSH, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "OP_PUSH", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Store the value from the stack at the given address. Store it in + a bitfield of size r_size starting at bit position r_offset. */ + HOWTO (ALPHA_R_OP_STORE, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "OP_STORE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Subtract the reloc address from the value on the top of the + relocation stack. */ + HOWTO (ALPHA_R_OP_PSUB, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "OP_PSUB", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Shift the value on the top of the relocation stack right by the + given value. */ + HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "OP_PRSHIFT", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Hack. Linkage is done by linker. */ + HOWTO (ALPHA_R_LINKAGE, /* type */ + 0, /* rightshift */ + 8, /* size (0 = byte, 1 = short, 2 = long) */ + 256, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "LINKAGE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 32 bit reference to a symbol. */ + HOWTO (ALPHA_R_REFLONG, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "REFLONG", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 64 bit reference to a procedure, written as 32 bit value. */ + HOWTO (ALPHA_R_CODEADDR, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + reloc_nil, /* special_function */ + "CODEADDR", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + +}; + +/* Return a pointer to a howto structure which, when invoked, will perform + the relocation code on data from the architecture noted. */ + +static const struct reloc_howto_struct * +nisse_bfd_reloc_type_lookup (abfd, code) + bfd *abfd ATTRIBUTE_UNUSED; + bfd_reloc_code_real_type code; +{ + int alpha_type; + exit(42); + +#if VMS_DEBUG + vms_debug (1, "vms_bfd_reloc_type_lookup(%p, %d)\t", abfd, code); +#endif + + switch (code) + { + case BFD_RELOC_16: alpha_type = ALPHA_R_SREL16; break; + case BFD_RELOC_32: alpha_type = ALPHA_R_REFLONG; break; + case BFD_RELOC_64: alpha_type = ALPHA_R_REFQUAD; break; + case BFD_RELOC_CTOR: alpha_type = ALPHA_R_REFQUAD; break; + case BFD_RELOC_23_PCREL_S2: alpha_type = ALPHA_R_BRADDR; break; + case BFD_RELOC_ALPHA_HINT: alpha_type = ALPHA_R_HINT; break; + case BFD_RELOC_16_PCREL: alpha_type = ALPHA_R_SREL16; break; + case BFD_RELOC_32_PCREL: alpha_type = ALPHA_R_SREL32; break; + case BFD_RELOC_64_PCREL: alpha_type = ALPHA_R_SREL64; break; + case BFD_RELOC_ALPHA_LINKAGE: alpha_type = ALPHA_R_LINKAGE; break; + case BFD_RELOC_ALPHA_CODEADDR: alpha_type = ALPHA_R_CODEADDR; break; + default: + (*_bfd_error_handler) ("reloc (%d) is *UNKNOWN*", code); + return (const struct reloc_howto_struct *) NULL; + } +#if VMS_DEBUG + vms_debug (2, "reloc is %s\n", alpha_howto_table[alpha_type].name); +#endif + return &alpha_howto_table[alpha_type]; +} + +void * +bfd_nisse_get_nisse_relocs(bfd * abfd, arelent **storage, asymbol **syms, bfd_boolean dynamic) +{ + arelent *p; + struct vms_core_data * data=abfd->tdata.any; + struct _iaf * iaf=data->iaf; + + int fixup_vector = iaf; + + int * addr_g; + int * addr_d; + struct _shl * shlst; + + addr_g = fixup_vector+iaf->iaf$l_g_fixoff; + addr_d = fixup_vector+iaf->iaf$l_dotadroff; + shlst = fixup_vector + iaf->iaf$l_shlstoff; + + int count=calc_size(addr_g)+calc_size(addr_d); + printf("count %x %x\n",calc_size(addr_g),calc_size(addr_d)); + abfd->sections->relocation=bfd_alloc(abfd, count*sizeof(arelent)); + p=abfd->sections->relocation; + + int i=0; + + int * addr; + addr=addr_g; + int again=2; + int alpha=R_386_32; + while (again) { + int refc=*addr++; + int shli=*addr++; + long base=shlst[shli].shl$l_baseva; + Elf32_External_Rela * adr = addr; + if (refc==0) + goto norefc; + while (refc--) { + int * tmp = &adr->r_info; + char type=(*tmp)&0xff; + int symo=(*tmp)>>8; + tmp=&adr->r_offset; + p->address=*tmp; + if (symo) + p->sym_ptr_ptr=find_symtab_int(abfd, syms, data->symstr + symo); + if (p->sym_ptr_ptr==0) + printf("problem finding %x %s\n",data->symstr + symo,data->symstr + symo); + if (p->sym_ptr_ptr==0) + goto skip_me; + + if (type==1) + p->howto=&alpha_howto_table[R_386_32]; + if (type==2) + p->howto=&alpha_howto_table[R_386_PC32]; + if (type>2) // temp workaround + exit(2); + if (type>2) // temp workaround + p->howto=&alpha_howto_table[R_386_32]; + p++; + skip_me: + adr++; + } + addr=adr; + norefc: + if (*addr==0) + addr+=2; + if (*addr==0) { + addr+=2; + again--; + } + } + + p=abfd->sections->relocation; + for (i = 0; i < count; i++) + *storage++ = p++; + *storage = NULL; + + return count; +} + +/* Back-door to allow format-aware applications to create debug symbols + while using BFD for everything else. Currently used by the assembler + when creating COFF files. */ + +static asymbol * +nisse_bfd_make_debug_symbol (abfd, ptr, size) + bfd *abfd ATTRIBUTE_UNUSED; + void *ptr ATTRIBUTE_UNUSED; + unsigned long size ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_bfd_make_debug_symbol(%p, %p, %ld)\n", abfd, ptr, size); +#endif + return 0; +} + +/* Read minisymbols. For minisymbols, we use the unmodified a.out + symbols. The minisymbol_to_symbol function translates these into + BFD asymbol structures. */ + +static long +nisse_read_minisymbols (abfd, dynamic, minisymsp, sizep) + bfd *abfd; + bfd_boolean dynamic; + PTR *minisymsp; + unsigned int *sizep; +{ +#if VMS_DEBUG + vms_debug (1, "vms_read_minisymbols(%p, %d, %p, %d)\n", abfd, dynamic, minisymsp, *sizep); +#endif + return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); +} + +/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an + unmodified a.out symbol. The SYM argument is a structure returned + by bfd_make_empty_symbol, which we fill in here. */ + +/* Print symbol to file according to how. how is one of + bfd_print_symbol_name just print the name + bfd_print_symbol_more print more (???) + bfd_print_symbol_all print all we know, which is not much right now :-) */ + +static void +nisse_print_symbol (abfd, file, symbol, how) + bfd *abfd; + PTR file; + asymbol *symbol; + bfd_print_symbol_type how; +{ +#if VMS_DEBUG + vms_debug (1, "vms_print_symbol(%p, %p, %p, %d)\n", abfd, file, symbol, how); +#endif + + switch (how) + { + case bfd_print_symbol_name: + case bfd_print_symbol_more: + fprintf ((FILE *)file," %s", symbol->name); + break; + + case bfd_print_symbol_all: + { + const char *section_name = symbol->section->name; + + bfd_print_symbol_vandf (abfd, (PTR)file, symbol); + + fprintf ((FILE *)file," %-8s %s", section_name, symbol->name); + } + break; + } + return; +} + +/* Return information about symbol in ret. + + fill type, value and name + type: + A absolute + B bss segment symbol + C common symbol + D data segment symbol + f filename + t a static function symbol + T text segment symbol + U undefined + - debug */ + +static void +nisse_get_symbol_info (abfd, symbol, ret) + bfd *abfd ATTRIBUTE_UNUSED; + asymbol *symbol; + symbol_info *ret; +{ + asection *sec; + +#if VMS_DEBUG + vms_debug (1, "vms_get_symbol_info(%p, %p, %p)\n", abfd, symbol, ret); +#endif + + sec = symbol->section; + + if (ret == 0) + return; + + if (bfd_is_com_section (sec)) + ret->type = 'C'; + else if (bfd_is_abs_section (sec)) + ret->type = 'A'; + else if (bfd_is_und_section (sec)) + ret->type = 'U'; + else if (bfd_is_ind_section (sec)) + ret->type = 'I'; + else if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + ret->type = 'T'; + else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) + ret->type = 'D'; + else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) + ret->type = 'B'; + else + ret->type = '-'; + + if (ret->type != 'U') + ret->value = symbol->value + symbol->section->vma; + else + ret->value = 0; + ret->name = symbol->name; + + return; +} + +/* Return TRUE if the given symbol sym in the BFD abfd is + a compiler generated local label, else return FALSE. */ + +/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an + unmodified a.out symbol. The SYM argument is a structure returned + by bfd_make_empty_symbol, which we fill in here. */ + +static asymbol * +nisse_minisymbol_to_symbol (abfd, dynamic, minisym, sym) + bfd *abfd; + bfd_boolean dynamic; + const PTR minisym; + asymbol *sym; +{ +#if VMS_DEBUG + vms_debug (1, "vms_minisymbol_to_symbol(%p, %d, %p, %p)\n", abfd, dynamic, minisym, sym); +#endif + return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym); +} + +/* Return TRUE if the given symbol sym in the BFD abfd is + a compiler generated local label, else return FALSE. */ + +static bfd_boolean +nisse_bfd_is_local_label_name (abfd, name) + bfd *abfd ATTRIBUTE_UNUSED; + const char *name; +{ +#if VMS_DEBUG + vms_debug (1, "vms_bfd_is_local_label_name(%p, %s)\n", abfd, name); +#endif + return name[0] == '$'; +} + +static bfd_boolean +nisse_bfd_is_target_special_symbol (abfd, symbol) + bfd *abfd ATTRIBUTE_UNUSED; + asymbol * symbol; +{ + return 0; +} + +/* Get source line number for symbol */ + +static alent * +nisse_get_lineno (abfd, symbol) + bfd *abfd ATTRIBUTE_UNUSED; + asymbol *symbol ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_get_lineno(%p, %p)\n", abfd, symbol); +#endif + return 0; +} + +/* Provided a BFD, a section and an offset into the section, calculate and + return the name of the source file and the line nearest to the wanted + location. */ + +static bfd_boolean +nisse_find_nearest_line (abfd, section, symbols, offset, file, func, line) + bfd *abfd ATTRIBUTE_UNUSED; + asection *section ATTRIBUTE_UNUSED; + asymbol **symbols ATTRIBUTE_UNUSED; + bfd_vma offset ATTRIBUTE_UNUSED; + const char **file ATTRIBUTE_UNUSED; + const char **func ATTRIBUTE_UNUSED; + unsigned int *line ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_find_nearest_line(%p, %s, %p, %ld, , , )\n", + abfd, section->name, symbols, (long int)offset); +#endif + return FALSE; +} + +/* Read the symbols from the BFD abfd, and fills in the vector + location with pointers to the symbols and a trailing NULL. + + return # of symbols read */ + +static long +nisse_canonicalize_symtab (abfd, symbols) + bfd *abfd; + asymbol **symbols; +{ +#if VMS_DEBUG + vms_debug (1, "vms_canonicalize_symtab(%p, )\n", abfd); +#endif + +#if 0 + /* init counter */ + (void)copy_symbols((struct bfd_hash_entry *)0, abfd); + + /* traverse table and fill symbols vector */ + + PRIV (symcache) = symbols; + bfd_hash_traverse(PRIV (vms_symbol_table), copy_symbols, (PTR)abfd); +#endif + +#if 0 + symbols[PRIV (gsd_sym_count)] = NULL; + + return PRIV (gsd_sym_count); +#endif + int i=0; + struct vms_core_data * data = abfd->tdata.any; + char * symtab=data->symtab; + char * symstr=data->symstr; + int cnt = bfd_nisse_get_nisse_syms(abfd,symbols,symtab,symstr, FALSE); + int symcount = cnt; + if (symcount >= 0) + bfd_get_symcount (abfd) = symcount; + return symcount; + + if (bfd_get_symcount(abfd)==0) { + // temp workaround + + } + for(i=0;ioutsymbols[i]; + return bfd_get_symcount(abfd); +} + +/*-- Part 4.5, symbols --------------------------------------------------------*/ + +/* Return the number of bytes required to store a vector of pointers + to asymbols for all the symbols in the BFD abfd, including a + terminal NULL pointer. If there are no symbols in the BFD, + then return 0. If an error occurs, return -1. */ + +static long +nisse_get_symtab_upper_bound (abfd) + bfd *abfd; +{ +#if 0 +#if VMS_DEBUG + vms_debug (1, "vms_get_symtab_upper_bound(%p), %d symbols\n", abfd, PRIV (gsd_sym_count)); +#endif + return (PRIV (gsd_sym_count)+1) * sizeof (asymbol *); +#else + struct vms_core_data * data = abfd->tdata.any; + return data->symtab_size; +#endif +} + +/*-- Part 4.9, dynamic symbols and relocations ------------------------------*/ + +/* Get the amount of memory required to hold the dynamic symbols. */ + +static long +nisse_get_dynamic_symtab_upper_bound (abfd) + bfd *abfd; +{ +#if VMS_DEBUG + vms_debug (1, "vms_get_dynamic_symtab_upper_bound(%p)\n", abfd); +#endif + struct vms_core_data * data = abfd->tdata.any; + return data->symtab_size; +} + +static bfd_boolean +nisse_bfd_print_private_bfd_data (abfd, file) + bfd *abfd ATTRIBUTE_UNUSED; + void *file ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_bfd_print_private_bfd_data(%p)\n", abfd); +#endif + return 0; +} + +/* Read in the dynamic symbols. */ + +static long +nisse_canonicalize_dynamic_symtab (abfd, symbols) + bfd *abfd; + asymbol **symbols; +{ +#if VMS_DEBUG + vms_debug (1, "vms_canonicalize_dynamic_symtab(%p, )\n", abfd); +#endif + struct vms_core_data * data = abfd->tdata.any; + char * symtab=data->symtab; + char * symstr=data->symstr; + int cnt = bfd_nisse_get_nisse_syms(abfd,symbols,symtab,symstr, TRUE); + int symcount = cnt; + if (symcount >= 0) + bfd_get_dynamic_symcount (abfd) = symcount; + return symcount; + if (symbols) { + long l = symcount; + + asymbol ** sym = abfd->outsymbols; // was: symbase; + while (l-- > 0) + { + *symbols++ = *sym; // was: &sym->symbol; and without *sym + sym++; + } + *symbols = 0; /* Final null pointer */ + } + return cnt; +} + +/* Get the amount of memory required to hold the dynamic relocs. */ + +int calc_size(long * l) { + int ret=0; + while (*l) { + int add=*l; + ret+=add; + l=((int)l)+2*4*2+add*sizeof(Elf32_External_Rela); + } + return ret; +} + +static long +nisse_get_dynamic_reloc_upper_bound (abfd) + bfd *abfd ATTRIBUTE_UNUSED; +{ +#if VMS_DEBUG + vms_debug (1, "vms_get_dynamic_reloc_upper_bound(%p)\n", abfd); +#endif + struct vms_core_data * data=abfd->tdata.any; + struct _iaf * iaf=data->iaf; + int * addr_g=(int)iaf+iaf->iaf$l_g_fixoff; + int * addr_d=(int)iaf+iaf->iaf$l_dotadroff; + int ret=calc_size(addr_g)+calc_size(addr_d); + printf("ret %x\n",ret); + if (ret==0) + ret++; + return ret*sizeof(arelent *); +} + +/* Read in the dynamic relocs. */ + +static long +nisse_canonicalize_dynamic_reloc (abfd, arel, symbols) + bfd *abfd; + arelent **arel; + asymbol **symbols; +{ +#if VMS_DEBUG + vms_debug (1, "vms_canonicalize_dynamic_reloc(%p)\n", abfd); +#endif + return bfd_nisse_get_nisse_relocs(abfd, arel, symbols, TRUE); +} diff -ruN binutils-2.16-orig/bfd/targets.c binutils/bfd/targets.c --- binutils-2.16-orig/bfd/targets.c Tue Mar 1 02:56:27 2005 +++ binutils/bfd/targets.c Wed May 25 09:08:06 2005 @@ -562,6 +562,7 @@ extern const bfd_target bfd_elf32_i370_vec; extern const bfd_target bfd_elf32_i386_freebsd_vec; extern const bfd_target bfd_elf32_i386_vec; +extern const bfd_target bfd_nisse_i386_vec; extern const bfd_target bfd_elf32_i860_little_vec; extern const bfd_target bfd_elf32_i860_vec; extern const bfd_target bfd_elf32_i960_vec; @@ -861,6 +862,7 @@ &bfd_elf32_i370_vec, &bfd_elf32_i386_freebsd_vec, &bfd_elf32_i386_vec, + &bfd_nisse_i386_vec, &bfd_elf32_i860_little_vec, &bfd_elf32_i860_vec, &bfd_elf32_i960_vec, diff -ruN binutils-2.16-orig/binutils/Makefile.in binutils/binutils/Makefile.in --- binutils-2.16-orig/binutils/Makefile.in Tue Feb 22 13:57:27 2005 +++ binutils/binutils/Makefile.in Wed May 25 09:08:06 2005 @@ -157,6 +157,8 @@ READELF_PROG = readelf +READNISSE_PROG = readnisse + # These should all be the same program too. SIZE_PROG = size NM_PROG = nm-new @@ -175,9 +177,9 @@ SRCONV_PROG = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) -PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ +PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) $(READNISSE_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ -bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ +bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) $(READNISSE_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG) $(DEMANGLER_PROG) @@ -215,7 +217,7 @@ ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \ nlmconv.c nm.c not-ranlib.c not-strip.c \ objcopy.c objdump.c prdbg.c \ - rdcoff.c rddbg.c readelf.c rename.c \ + rdcoff.c rddbg.c readelf.c readnisse.c rename.c \ resbin.c rescoff.c resrc.c resres.c \ size.c srconv.c stabs.c strings.c sysdump.c version.c \ windres.c winduni.c wrstabs.c @@ -276,6 +278,9 @@ readelf_SOURCES = readelf.c version.c unwind-ia64.c readelf_LDADD = $(INTLLIBS) $(LIBIBERTY) +readnisse_SOURCES = readnisse.c version.c unwind-ia64.c +readnisse_LDADD = $(INTLLIBS) $(LIBIBERTY) + strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) nm_new_SOURCES = nm.c budemang.c $(BULIBS) @@ -336,7 +341,7 @@ bin_PROGRAMS = size$(EXEEXT) objdump$(EXEEXT) ar$(EXEEXT) \ strings$(EXEEXT) ranlib$(EXEEXT) objcopy$(EXEEXT) @BUILD_NLMCONV@ \ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ addr2line$(EXEEXT) \ -readelf$(EXEEXT) @BUILD_DLLWRAP@ @BUILD_MISC@ +readelf$(EXEEXT) readnisse$(EXEEXT) @BUILD_DLLWRAP@ @BUILD_MISC@ noinst_PROGRAMS = nm-new$(EXEEXT) strip-new$(EXEEXT) cxxfilt$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) @@ -419,8 +424,12 @@ addr2line_LDFLAGS = readelf_OBJECTS = readelf.$(OBJEXT) version.$(OBJEXT) \ unwind-ia64.$(OBJEXT) +readnisse_OBJECTS = readnisse.$(OBJEXT) version.$(OBJEXT) \ +unwind-ia64.$(OBJEXT) readelf_DEPENDENCIES = ../libiberty/libiberty.a readelf_LDFLAGS = +readnisse_DEPENDENCIES = ../libiberty/libiberty.a +readnisse_LDFLAGS = nm_new_OBJECTS = nm.$(OBJEXT) budemang.$(OBJEXT) bucomm.$(OBJEXT) \ version.$(OBJEXT) filemode.$(OBJEXT) nm_new_LDADD = $(LDADD) @@ -455,8 +464,8 @@ TAR = tar GZIP_ENV = --best -SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(dllwrap_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(readelf_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES) $(cxxfilt_SOURCES) -OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(dllwrap_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(readelf_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS) $(cxxfilt_OBJECTS) +SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(dllwrap_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(readelf_SOURCES) $(readnisse_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES) $(cxxfilt_SOURCES) +OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(dllwrap_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(readelf_OBJECTS) $(readnisse_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS) $(cxxfilt_OBJECTS) all: all-redirect .SUFFIXES: @@ -642,6 +651,10 @@ @rm -f readelf$(EXEEXT) $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS) +readnisse$(EXEEXT): $(readnisse_OBJECTS) $(readnisse_DEPENDENCIES) + @rm -f readnisse$(EXEEXT) + $(LINK) $(readnisse_LDFLAGS) $(readnisse_OBJECTS) $(readnisse_LDADD) $(LIBS) + nm-new$(EXEEXT): $(nm_new_OBJECTS) $(nm_new_DEPENDENCIES) @rm -f nm-new$(EXEEXT) $(LINK) $(nm_new_LDFLAGS) $(nm_new_OBJECTS) $(nm_new_LDADD) $(LIBS) @@ -1202,6 +1215,22 @@ $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h debug.h \ budbg.h readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/symcat.h $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h \ + $(INCDIR)/elf/internal.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/alpha.h \ + $(INCDIR)/elf/reloc-macros.h $(INCDIR)/elf/arc.h $(INCDIR)/elf/arm.h \ + $(INCDIR)/elf/avr.h $(INCDIR)/elf/cris.h $(INCDIR)/elf/d10v.h \ + $(INCDIR)/elf/d30v.h $(INCDIR)/elf/dlx.h $(INCDIR)/elf/fr30.h \ + $(INCDIR)/elf/frv.h $(INCDIR)/elf/h8.h $(INCDIR)/elf/hppa.h \ + $(INCDIR)/elf/i386.h $(INCDIR)/elf/i860.h $(INCDIR)/elf/i960.h \ + $(INCDIR)/elf/ia64.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/m68k.h \ + $(INCDIR)/elf/m68hc11.h $(INCDIR)/elf/mcore.h $(INCDIR)/elf/mips.h \ + $(INCDIR)/elf/mmix.h $(INCDIR)/elf/mn10200.h $(INCDIR)/elf/mn10300.h \ + $(INCDIR)/elf/or32.h $(INCDIR)/elf/pj.h $(INCDIR)/elf/ppc.h \ + $(INCDIR)/elf/s390.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/sparc.h \ + $(INCDIR)/elf/v850.h $(INCDIR)/elf/vax.h $(INCDIR)/elf/x86-64.h \ + $(INCDIR)/elf/xstormy16.h bucomm.h config.h $(INCDIR)/bin-bugs.h \ + $(INCDIR)/fopen-same.h unwind-ia64.h +readnisse.o: readnisse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/symcat.h $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/alpha.h \ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/elf/arc.h $(INCDIR)/elf/arm.h \ diff -ruN binutils-2.16-orig/binutils/readnisse.c binutils/binutils/readnisse.c --- binutils-2.16-orig/binutils/readnisse.c Thu Jan 1 01:00:00 1970 +++ binutils/binutils/readnisse.c Wed May 25 09:08:06 2005 @@ -0,0 +1,10274 @@ +/* readelf.c -- display contents of an ELF format file + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + Originally developed by Eric Youngdale + Modifications by Nick Clifton + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +#include +#include +#include +#include +#include + +#if __GNUC__ >= 2 +/* Define BFD64 here, even if our default architecture is 32 bit ELF + as this will allow us to read in and parse 64bit and 32bit ELF files. + Only do this if we belive that the compiler can support a 64 bit + data type. For now we only rely on GCC being able to do this. */ +#define BFD64 +#endif + +#include "bfd.h" + +/* The following headers use the elf/reloc-macros.h file to + automatically generate relocation recognition functions + such as elf_mips_reloc_type() */ + +#define RELOC_MACROS_GEN_FUNC + +#include"nisse/eihadef.h" +#include"nisse/eihddef.h" +#include"nisse/eihidef.h" +#include"nisse/eihpdef.h" +#include"nisse/eihsdef.h" +#include"nisse/eihvndef.h" +#include"nisse/eisddef.h" +#include"nisse/ihadef.h" +#include"nisse/ihddef.h" +#include"nisse/ihidef.h" +#include"nisse/ihpdef.h" +#include"nisse/ihsdef.h" +#include"nisse/ihvndef.h" +#include"nisse/isddef.h" + +#include "bucomm.h" +#include "getopt.h" + +char * program_name = "readelf"; +unsigned int dynamic_addr; +bfd_size_type dynamic_size; +unsigned int rela_addr; +unsigned int rela_size; +char * dynamic_strings; +char * string_table; +unsigned long string_table_length; +unsigned long num_dynamic_syms; +//Elf_Internal_Sym * dynamic_symbols; +//Elf_Internal_Syminfo * dynamic_syminfo; +unsigned long dynamic_syminfo_offset; +unsigned int dynamic_syminfo_nent; +char program_interpreter [64]; +//int dynamic_info[DT_JMPREL + 1]; +int version_info[16]; +int loadaddr = 0; +struct _eihd * nisse_header; +struct _eiha * nisse_active; +struct _eisd nisse_section[100]; +unsigned long nisse_sects=0; +struct _eihi * nisse_name; +struct _eimg_version_array * nisse_vers; +struct _eihs * nisse_debug; +//Elf_Internal_Shdr * section_headers; +//Elf_Internal_Dyn * dynamic_segment; +//Elf_Internal_Shdr * symtab_shndx_hdr; +int show_name; +int do_dynamic; +int do_syms; +int do_reloc; +int do_sections; +int do_segments; +int do_unwind; +int do_using_dynamic; +int do_header; +int do_dump; +int do_version; +int do_wide; +int do_histogram; +int do_debugging; +int do_debug_info; +int do_debug_abbrevs; +int do_debug_lines; +int do_debug_pubnames; +int do_debug_aranges; +int do_debug_frames; +int do_debug_frames_interp; +int do_debug_macinfo; +int do_debug_str; +int do_debug_loc; +int do_arch; +int do_notes; +int is_32bit_elf; + +/* A dynamic array of flags indicating which sections require dumping. */ +char * dump_sects = NULL; +unsigned int num_dump_sects = 0; + +#define HEX_DUMP (1 << 0) +#define DISASS_DUMP (1 << 1) +#define DEBUG_DUMP (1 << 2) + +/* How to rpint a vma value. */ +typedef enum print_mode +{ + HEX, + DEC, + DEC_5, + UNSIGNED, + PREFIX_HEX, + FULL_HEX, + LONG_HEX +} +print_mode; + +#if 0 + +/* Forward declarations for dumb compilers. */ +static void print_vma PARAMS ((bfd_vma, print_mode)); +static void print_symbol PARAMS ((int, char *)); +static bfd_vma (* byte_get) PARAMS ((unsigned char *, int)); +static bfd_vma byte_get_little_endian PARAMS ((unsigned char *, int)); +static bfd_vma byte_get_big_endian PARAMS ((unsigned char *, int)); +static const char * get_mips_dynamic_type PARAMS ((unsigned long)); +static const char * get_sparc64_dynamic_type PARAMS ((unsigned long)); +static const char * get_ppc64_dynamic_type PARAMS ((unsigned long)); +static const char * get_parisc_dynamic_type PARAMS ((unsigned long)); +static const char * get_dynamic_type PARAMS ((unsigned long)); +static int slurp_rela_relocs PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *)); +static int slurp_rel_relocs PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rel **, unsigned long *)); +static int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int)); +static char * get_file_type PARAMS ((unsigned)); +static char * get_machine_name PARAMS ((unsigned)); +static void decode_ARM_machine_flags PARAMS ((unsigned, char [])); +static char * get_machine_flags PARAMS ((unsigned, unsigned)); +static const char * get_mips_segment_type PARAMS ((unsigned long)); +static const char * get_parisc_segment_type PARAMS ((unsigned long)); +static const char * get_ia64_segment_type PARAMS ((unsigned long)); +static const char * get_segment_type PARAMS ((unsigned long)); +static const char * get_mips_section_type_name PARAMS ((unsigned int)); +static const char * get_parisc_section_type_name PARAMS ((unsigned int)); +static const char * get_ia64_section_type_name PARAMS ((unsigned int)); +static const char * get_section_type_name PARAMS ((unsigned int)); +static const char * get_symbol_binding PARAMS ((unsigned int)); +static const char * get_symbol_type PARAMS ((unsigned int)); +static const char * get_symbol_visibility PARAMS ((unsigned int)); +static const char * get_symbol_index_type PARAMS ((unsigned int)); +static const char * get_dynamic_flags PARAMS ((bfd_vma)); +static void usage PARAMS ((void)); +static void parse_args PARAMS ((int, char **)); +static int process_file_header PARAMS ((void)); +static int process_program_headers PARAMS ((FILE *)); +static int process_section_headers PARAMS ((FILE *)); +static int process_unwind PARAMS ((FILE *)); +static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *)); +static void dynamic_segment_parisc_val PARAMS ((Elf_Internal_Dyn *)); +static int process_dynamic_segment PARAMS ((FILE *)); +static int process_symbol_table PARAMS ((FILE *)); +static int process_syminfo PARAMS ((FILE *)); +static int process_section_contents PARAMS ((FILE *)); +static void process_mips_fpe_exception PARAMS ((int)); +static int process_mips_specific PARAMS ((FILE *)); +static int process_file PARAMS ((char *)); +static int process_relocs PARAMS ((FILE *)); +static int process_version_sections PARAMS ((FILE *)); +static char * get_ver_flags PARAMS ((unsigned int)); +static int get_32bit_section_headers PARAMS ((FILE *, unsigned int)); +static int get_64bit_section_headers PARAMS ((FILE *, unsigned int)); +static int get_32bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); +static int get_64bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); +static int get_file_header PARAMS ((FILE *)); +static Elf_Internal_Sym * get_32bit_elf_symbols PARAMS ((FILE *, Elf_Internal_Shdr *)); +static Elf_Internal_Sym * get_64bit_elf_symbols PARAMS ((FILE *, Elf_Internal_Shdr *)); +static const char * get_elf_section_flags PARAMS ((bfd_vma)); +static int * get_dynamic_data PARAMS ((FILE *, unsigned int)); +static int get_32bit_dynamic_segment PARAMS ((FILE *)); +static int get_64bit_dynamic_segment PARAMS ((FILE *)); +#ifdef SUPPORT_DISASSEMBLY +static int disassemble_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +#endif +static int dump_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +static int display_debug_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +static int display_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int prescan_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_lines PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_pubnames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_abbrev PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_aranges PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_frames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_macinfo PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_str PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_loc PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static unsigned char * process_abbrev_section PARAMS ((unsigned char *, unsigned char *)); +static void load_debug_str PARAMS ((FILE *)); +static void free_debug_str PARAMS ((void)); +static const char * fetch_indirect_string PARAMS ((unsigned long)); +static void load_debug_loc PARAMS ((FILE *)); +static void free_debug_loc PARAMS ((void)); +static unsigned long read_leb128 PARAMS ((unsigned char *, int *, int)); +static int process_extended_line_op PARAMS ((unsigned char *, int, int)); +static void reset_state_machine PARAMS ((int)); +static char * get_TAG_name PARAMS ((unsigned long)); +static char * get_AT_name PARAMS ((unsigned long)); +static char * get_FORM_name PARAMS ((unsigned long)); +static void free_abbrevs PARAMS ((void)); +static void add_abbrev PARAMS ((unsigned long, unsigned long, int)); +static void add_abbrev_attr PARAMS ((unsigned long, unsigned long)); +static unsigned char * read_and_display_attr PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long)); +static unsigned char * read_and_display_attr_value PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long)); +static unsigned char * display_block PARAMS ((unsigned char *, unsigned long)); +static void decode_location_expression PARAMS ((unsigned char *, unsigned int, unsigned long)); +static void request_dump PARAMS ((unsigned int, int)); +static const char * get_elf_class PARAMS ((unsigned int)); +static const char * get_data_encoding PARAMS ((unsigned int)); +static const char * get_osabi_name PARAMS ((unsigned int)); +static int guess_is_rela PARAMS ((unsigned long)); +static const char * get_note_type PARAMS ((unsigned int)); +static const char * get_netbsd_elfcore_note_type PARAMS ((unsigned int)); +static int process_note PARAMS ((Elf32_Internal_Note *)); +static int process_corefile_note_segment PARAMS ((FILE *, bfd_vma, bfd_vma)); +static int process_corefile_note_segments PARAMS ((FILE *)); +static int process_corefile_contents PARAMS ((FILE *)); +static int process_arch_specific PARAMS ((FILE *)); +static int process_gnu_liblist PARAMS ((FILE *)); + +#endif + +typedef int Elf32_Word; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#define UNKNOWN -1 + +#define SECTION_NAME(X) ((X) == NULL ? "" : \ + ((X)->sh_name >= string_table_length \ + ? "" : string_table + (X)->sh_name)) + +/* Given st_shndx I, map to section_headers index. */ +#define SECTION_HEADER_INDEX(I) \ + ((I) < SHN_LORESERVE \ + ? (I) \ + : ((I) <= SHN_HIRESERVE \ + ? 0 \ + : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE))) + +/* Reverse of the above. */ +#define SECTION_HEADER_NUM(N) \ + ((N) < SHN_LORESERVE \ + ? (N) \ + : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE)) + +#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I)) + +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ + +#define BYTE_GET(field) byte_get (field, sizeof (field)) + +/* If we can support a 64 bit data type then BFD64 should be defined + and sizeof (bfd_vma) == 8. In this case when translating from an + external 8 byte field to an internal field, we can assume that the + internal field is also 8 bytes wide and so we can extract all the data. + If, however, BFD64 is not defined, then we must assume that the + internal data structure only has 4 byte wide fields that are the + equivalent of the 8 byte wide external counterparts, and so we must + truncate the data. */ +#ifdef BFD64 +#define BYTE_GET8(field) byte_get (field, -8) +#else +#define BYTE_GET8(field) byte_get (field, 8) +#endif + +#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) + +#define GET_ELF_SYMBOLS(file, section) \ + (is_32bit_elf ? get_32bit_elf_symbols (file, section) \ + : get_64bit_elf_symbols (file, section)) + + +static void +error VPARAMS ((const char *message, ...)) +{ + VA_OPEN (args, message); + VA_FIXEDARG (args, const char *, message); + + fprintf (stderr, _("%s: Error: "), program_name); + vfprintf (stderr, message, args); + VA_CLOSE (args); +} + +static void +warn VPARAMS ((const char *message, ...)) +{ + VA_OPEN (args, message); + VA_FIXEDARG (args, const char *, message); + + fprintf (stderr, _("%s: Warning: "), program_name); + vfprintf (stderr, message, args); + VA_CLOSE (args); +} + +static PTR get_data PARAMS ((PTR, FILE *, long, size_t, const char *)); + +static PTR +get_data (var, file, offset, size, reason) + PTR var; + FILE *file; + long offset; + size_t size; + const char *reason; +{ + PTR mvar; + + if (size == 0) + return NULL; + + if (fseek (file, offset, SEEK_SET)) + { + error (_("Unable to seek to %x for %s\n"), offset, reason); + return NULL; + } + + mvar = var; + if (mvar == NULL) + { + mvar = (PTR) malloc (size); + + if (mvar == NULL) + { + error (_("Out of memory allocating %d bytes for %s\n"), + size, reason); + return NULL; + } + } + + if (fread (mvar, size, 1, file) != 1) + { + error (_("Unable to read in %d bytes of %s\n"), size, reason); + if (mvar != var) + free (mvar); + return NULL; + } + + return mvar; +} + +static bfd_vma +byte_get_little_endian (field, size) + unsigned char * field; + int size; +{ + switch (size) + { + case 1: + return * field; + + case 2: + return ((unsigned int) (field [0])) + | (((unsigned int) (field [1])) << 8); + +#ifndef BFD64 + case 8: + /* We want to extract data from an 8 byte wide field and + place it into a 4 byte wide field. Since this is a little + endian source we can juts use the 4 byte extraction code. */ + /* Fall through. */ +#endif + case 4: + return ((unsigned long) (field [0])) + | (((unsigned long) (field [1])) << 8) + | (((unsigned long) (field [2])) << 16) + | (((unsigned long) (field [3])) << 24); + +#ifdef BFD64 + case 8: + case -8: + /* This is a special case, generated by the BYTE_GET8 macro. + It means that we are loading an 8 byte value from a field + in an external structure into an 8 byte value in a field + in an internal strcuture. */ + return ((bfd_vma) (field [0])) + | (((bfd_vma) (field [1])) << 8) + | (((bfd_vma) (field [2])) << 16) + | (((bfd_vma) (field [3])) << 24) + | (((bfd_vma) (field [4])) << 32) + | (((bfd_vma) (field [5])) << 40) + | (((bfd_vma) (field [6])) << 48) + | (((bfd_vma) (field [7])) << 56); +#endif + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +/* Print a VMA value. */ +static void +print_vma (vma, mode) + bfd_vma vma; + print_mode mode; +{ +#ifdef BFD64 + if (is_32bit_elf) +#endif + { + switch (mode) + { + case FULL_HEX: printf ("0x"); /* drop through */ + case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break; + case PREFIX_HEX: printf ("0x"); /* drop through */ + case HEX: printf ("%lx", (unsigned long) vma); break; + case DEC: printf ("%ld", (unsigned long) vma); break; + case DEC_5: printf ("%5ld", (long) vma); break; + case UNSIGNED: printf ("%lu", (unsigned long) vma); break; + } + } +#ifdef BFD64 + else + { + switch (mode) + { + case FULL_HEX: + printf ("0x"); + /* drop through */ + + case LONG_HEX: + printf_vma (vma); + break; + + case PREFIX_HEX: + printf ("0x"); + /* drop through */ + + case HEX: +#if BFD_HOST_64BIT_LONG + printf ("%lx", vma); +#else + if (_bfd_int64_high (vma)) + printf ("%lx%8.8lx", _bfd_int64_high (vma), _bfd_int64_low (vma)); + else + printf ("%lx", _bfd_int64_low (vma)); +#endif + break; + + case DEC: +#if BFD_HOST_64BIT_LONG + printf ("%ld", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%ld", _bfd_int64_low (vma)); + else + printf ("%ld", _bfd_int64_low (vma)); +#endif + break; + + case DEC_5: +#if BFD_HOST_64BIT_LONG + printf ("%5ld", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%ld", _bfd_int64_low (vma)); + else + printf ("%5ld", _bfd_int64_low (vma)); +#endif + break; + + case UNSIGNED: +#if BFD_HOST_64BIT_LONG + printf ("%lu", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%lu", _bfd_int64_low (vma)); + else + printf ("%lu", _bfd_int64_low (vma)); +#endif + break; + } + } +#endif +} + +/* Display a symbol on stdout. If do_wide is not true then + format the symbol to be at most WIDTH characters, + truncating as necessary. If WIDTH is negative then + format the string to be exactly - WIDTH characters, + truncating or padding as necessary. */ + +static void +print_symbol (width, symbol) + int width; + char * symbol; +{ + if (do_wide) + printf (symbol); + else if (width < 0) + printf ("%-*.*s", width, width, symbol); + else + printf ("%-.*s", width, symbol); +} + +static bfd_vma +byte_get_big_endian (field, size) + unsigned char * field; + int size; +{ + switch (size) + { + case 1: + return * field; + + case 2: + return ((unsigned int) (field [1])) | (((int) (field [0])) << 8); + + case 4: + return ((unsigned long) (field [3])) + | (((unsigned long) (field [2])) << 8) + | (((unsigned long) (field [1])) << 16) + | (((unsigned long) (field [0])) << 24); + +#ifndef BFD64 + case 8: + /* Although we are extracing data from an 8 byte wide field, we + are returning only 4 bytes of data. */ + return ((unsigned long) (field [7])) + | (((unsigned long) (field [6])) << 8) + | (((unsigned long) (field [5])) << 16) + | (((unsigned long) (field [4])) << 24); +#else + case 8: + case -8: + /* This is a special case, generated by the BYTE_GET8 macro. + It means that we are loading an 8 byte value from a field + in an external structure into an 8 byte value in a field + in an internal strcuture. */ + return ((bfd_vma) (field [7])) + | (((bfd_vma) (field [6])) << 8) + | (((bfd_vma) (field [5])) << 16) + | (((bfd_vma) (field [4])) << 24) + | (((bfd_vma) (field [3])) << 32) + | (((bfd_vma) (field [2])) << 40) + | (((bfd_vma) (field [1])) << 48) + | (((bfd_vma) (field [0])) << 56); +#endif + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +#if 0 + +/* Guess the relocation size commonly used by the specific machines. */ + +static int +guess_is_rela (e_machine) + unsigned long e_machine; +{ + switch (e_machine) + { + /* Targets that use REL relocations. */ + case EM_ARM: + case EM_386: + case EM_486: + case EM_960: + case EM_DLX: + case EM_OPENRISC: + case EM_OR32: + case EM_M32R: + case EM_CYGNUS_M32R: + case EM_D10V: + case EM_CYGNUS_D10V: + case EM_MIPS: + case EM_MIPS_RS3_LE: + return FALSE; + + /* Targets that use RELA relocations. */ + case EM_68K: + case EM_H8_300: + case EM_H8_300H: + case EM_H8S: + case EM_SPARC32PLUS: + case EM_SPARCV9: + case EM_SPARC: + case EM_PPC: + case EM_PPC64: + case EM_V850: + case EM_CYGNUS_V850: + case EM_D30V: + case EM_CYGNUS_D30V: + case EM_MN10200: + case EM_CYGNUS_MN10200: + case EM_MN10300: + case EM_CYGNUS_MN10300: + case EM_FR30: + case EM_CYGNUS_FR30: + case EM_CYGNUS_FRV: + case EM_SH: + case EM_ALPHA: + case EM_MCORE: + case EM_IA_64: + case EM_AVR: + case EM_AVR_OLD: + case EM_CRIS: + case EM_860: + case EM_X86_64: + case EM_S390: + case EM_S390_OLD: + case EM_MMIX: + case EM_XSTORMY16: + case EM_VAX: + return TRUE; + + case EM_MMA: + case EM_PCP: + case EM_NCPU: + case EM_NDR1: + case EM_STARCORE: + case EM_ME16: + case EM_ST100: + case EM_TINYJ: + case EM_FX66: + case EM_ST9PLUS: + case EM_ST7: + case EM_68HC16: + case EM_68HC11: + case EM_68HC08: + case EM_68HC05: + case EM_SVX: + case EM_ST19: + default: + warn (_("Don't know about relocations on this machine architecture\n")); + return FALSE; + } +} + +static int +slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) + FILE *file; + unsigned long rel_offset; + unsigned long rel_size; + Elf_Internal_Rela **relasp; + unsigned long *nrelasp; +{ + Elf_Internal_Rela *relas; + unsigned long nrelas; + unsigned int i; + + if (is_32bit_elf) + { + Elf32_External_Rela * erelas; + + erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erelas) + return 0; + + nrelas = rel_size / sizeof (Elf32_External_Rela); + + relas = (Elf_Internal_Rela *) + malloc (nrelas * sizeof (Elf_Internal_Rela)); + + if (relas == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } + + for (i = 0; i < nrelas; i++) + { + relas[i].r_offset = BYTE_GET (erelas[i].r_offset); + relas[i].r_info = BYTE_GET (erelas[i].r_info); + relas[i].r_addend = BYTE_GET (erelas[i].r_addend); + } + + free (erelas); + } + else + { + Elf64_External_Rela * erelas; + + erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erelas) + return 0; + + nrelas = rel_size / sizeof (Elf64_External_Rela); + + relas = (Elf_Internal_Rela *) + malloc (nrelas * sizeof (Elf_Internal_Rela)); + + if (relas == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } + + for (i = 0; i < nrelas; i++) + { + relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset); + relas[i].r_info = BYTE_GET8 (erelas[i].r_info); + relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend); + } + + free (erelas); + } + *relasp = relas; + *nrelasp = nrelas; + return 1; +} + +static int +slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) + FILE *file; + unsigned long rel_offset; + unsigned long rel_size; + Elf_Internal_Rel **relsp; + unsigned long *nrelsp; +{ + Elf_Internal_Rel *rels; + unsigned long nrels; + unsigned int i; + + if (is_32bit_elf) + { + Elf32_External_Rel * erels; + + erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erels) + return 0; + + nrels = rel_size / sizeof (Elf32_External_Rel); + + rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); + + if (rels == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } + + for (i = 0; i < nrels; i++) + { + rels[i].r_offset = BYTE_GET (erels[i].r_offset); + rels[i].r_info = BYTE_GET (erels[i].r_info); + } + + free (erels); + } + else + { + Elf64_External_Rel * erels; + + erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erels) + return 0; + + nrels = rel_size / sizeof (Elf64_External_Rel); + + rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); + + if (rels == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } + + for (i = 0; i < nrels; i++) + { + rels[i].r_offset = BYTE_GET8 (erels[i].r_offset); + rels[i].r_info = BYTE_GET8 (erels[i].r_info); + } + + free (erels); + } + *relsp = rels; + *nrelsp = nrels; + return 1; +} + +/* Display the contents of the relocation data found at the specified offset. */ +static int +dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) + FILE * file; + unsigned long rel_offset; + unsigned long rel_size; + Elf_Internal_Sym * symtab; + unsigned long nsyms; + char * strtab; + int is_rela; +{ + unsigned int i; + Elf_Internal_Rel * rels; + Elf_Internal_Rela * relas; + + + if (is_rela == UNKNOWN) + is_rela = guess_is_rela (nisse_header.e_machine); + + if (is_rela) + { + if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size)) + return 0; + } + else + { + if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size)) + return 0; + } + + if (is_32bit_elf) + { + if (is_rela) + { + if (do_wide) + printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n")); + else + printf (_(" Offset Info Type Sym.Value Sym. Name + Addend\n")); + } + else + { + if (do_wide) + printf (_(" Offset Info Type Sym. Value Symbol's Name\n")); + else + printf (_(" Offset Info Type Sym.Value Sym. Name\n")); + } + } + else + { + if (is_rela) + { + if (do_wide) + printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n")); + else + printf (_(" Offset Info Type Sym. Value Sym. Name + Addend\n")); + } + else + { + if (do_wide) + printf (_(" Offset Info Type Symbol's Value Symbol's Name\n")); + else + printf (_(" Offset Info Type Sym. Value Sym. Name\n")); + } + } + + for (i = 0; i < rel_size; i++) + { + const char * rtype; + const char * rtype2 = NULL; + const char * rtype3 = NULL; + bfd_vma offset; + bfd_vma info; + bfd_vma symtab_index; + bfd_vma type; + bfd_vma type2 = (bfd_vma) NULL; + bfd_vma type3 = (bfd_vma) NULL; + + if (is_rela) + { + offset = relas [i].r_offset; + info = relas [i].r_info; + } + else + { + offset = rels [i].r_offset; + info = rels [i].r_info; + } + + if (is_32bit_elf) + { + type = ELF32_R_TYPE (info); + symtab_index = ELF32_R_SYM (info); + } + else + { + if (nisse_header.e_machine == EM_MIPS) + { + type = ELF64_MIPS_R_TYPE (info); + type2 = ELF64_MIPS_R_TYPE2 (info); + type3 = ELF64_MIPS_R_TYPE3 (info); + } + else if (nisse_header.e_machine == EM_SPARCV9) + type = ELF64_R_TYPE_ID (info); + else + type = ELF64_R_TYPE (info); + /* The #ifdef BFD64 below is to prevent a compile time warning. + We know that if we do not have a 64 bit data type that we + will never execute this code anyway. */ +#ifdef BFD64 + symtab_index = ELF64_R_SYM (info); +#endif + } + + if (is_32bit_elf) + { +#ifdef _bfd_int64_low + printf ("%8.8lx %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info)); +#else + printf ("%8.8lx %8.8lx ", offset, info); +#endif + } + else + { +#ifdef _bfd_int64_low + printf (do_wide + ? "%8.8lx%8.8lx %8.8lx%8.8lx " + : "%4.4lx%8.8lx %4.4lx%8.8lx ", + _bfd_int64_high (offset), + _bfd_int64_low (offset), + _bfd_int64_high (info), + _bfd_int64_low (info)); +#else + printf (do_wide + ? "%16.16lx %16.16lx " + : "%12.12lx %12.12lx ", + offset, info); +#endif + } + + switch (nisse_header.e_machine) + { + default: + rtype = NULL; + break; + + case EM_M32R: + case EM_CYGNUS_M32R: + rtype = elf_m32r_reloc_type (type); + break; + + case EM_386: + case EM_486: + rtype = elf_i386_reloc_type (type); + break; + + case EM_68HC11: + case EM_68HC12: + rtype = elf_m68hc11_reloc_type (type); + break; + + case EM_68K: + rtype = elf_m68k_reloc_type (type); + break; + + case EM_960: + rtype = elf_i960_reloc_type (type); + break; + + case EM_AVR: + case EM_AVR_OLD: + rtype = elf_avr_reloc_type (type); + break; + + case EM_OLD_SPARCV9: + case EM_SPARC32PLUS: + case EM_SPARCV9: + case EM_SPARC: + rtype = elf_sparc_reloc_type (type); + break; + + case EM_V850: + case EM_CYGNUS_V850: + rtype = v850_reloc_type (type); + break; + + case EM_D10V: + case EM_CYGNUS_D10V: + rtype = elf_d10v_reloc_type (type); + break; + + case EM_D30V: + case EM_CYGNUS_D30V: + rtype = elf_d30v_reloc_type (type); + break; + + case EM_DLX: + rtype = elf_dlx_reloc_type (type); + break; + + case EM_SH: + rtype = elf_sh_reloc_type (type); + break; + + case EM_MN10300: + case EM_CYGNUS_MN10300: + rtype = elf_mn10300_reloc_type (type); + break; + + case EM_MN10200: + case EM_CYGNUS_MN10200: + rtype = elf_mn10200_reloc_type (type); + break; + + case EM_FR30: + case EM_CYGNUS_FR30: + rtype = elf_fr30_reloc_type (type); + break; + + case EM_CYGNUS_FRV: + rtype = elf_frv_reloc_type (type); + break; + + case EM_MCORE: + rtype = elf_mcore_reloc_type (type); + break; + + case EM_MMIX: + rtype = elf_mmix_reloc_type (type); + break; + + case EM_PPC: + case EM_PPC64: + rtype = elf_ppc_reloc_type (type); + break; + + case EM_MIPS: + case EM_MIPS_RS3_LE: + rtype = elf_mips_reloc_type (type); + if (!is_32bit_elf) + { + rtype2 = elf_mips_reloc_type (type2); + rtype3 = elf_mips_reloc_type (type3); + } + break; + + case EM_ALPHA: + rtype = elf_alpha_reloc_type (type); + break; + + case EM_ARM: + rtype = elf_arm_reloc_type (type); + break; + + case EM_ARC: + rtype = elf_arc_reloc_type (type); + break; + + case EM_PARISC: + rtype = elf_hppa_reloc_type (type); + break; + + case EM_H8_300: + case EM_H8_300H: + case EM_H8S: + rtype = elf_h8_reloc_type (type); + break; + + case EM_OPENRISC: + case EM_OR32: + rtype = elf_or32_reloc_type (type); + break; + + case EM_PJ: + case EM_PJ_OLD: + rtype = elf_pj_reloc_type (type); + break; + case EM_IA_64: + rtype = elf_ia64_reloc_type (type); + break; + + case EM_CRIS: + rtype = elf_cris_reloc_type (type); + break; + + case EM_860: + rtype = elf_i860_reloc_type (type); + break; + + case EM_X86_64: + rtype = elf_x86_64_reloc_type (type); + break; + + case EM_S390_OLD: + case EM_S390: + rtype = elf_s390_reloc_type (type); + break; + + case EM_XSTORMY16: + rtype = elf_xstormy16_reloc_type (type); + break; + + case EM_VAX: + rtype = elf_vax_reloc_type (type); + break; + } + + if (rtype == NULL) +#ifdef _bfd_int64_low + printf (_("unrecognized: %-7lx"), _bfd_int64_low (type)); +#else + printf (_("unrecognized: %-7lx"), type); +#endif + else + printf (do_wide ? "%-21.21s" : "%-17.17s", rtype); + + if (symtab_index) + { + if (symtab == NULL || symtab_index >= nsyms) + printf (" bad symbol index: %08lx", (unsigned long) symtab_index); + else + { + Elf_Internal_Sym * psym; + + psym = symtab + symtab_index; + + printf (" "); + print_vma (psym->st_value, LONG_HEX); + printf (is_32bit_elf ? " " : " "); + + if (psym->st_name == 0) + print_symbol (22, SECTION_NAME (section_headers + psym->st_shndx)); + else if (strtab == NULL) + printf (_(""), psym->st_name); + else + print_symbol (22, strtab + psym->st_name); + + if (is_rela) + printf (" + %lx", (unsigned long) relas [i].r_addend); + } + } + else if (is_rela) + { + printf ("%*c", is_32bit_elf ? (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' '); + print_vma (relas[i].r_addend, LONG_HEX); + } + + if (nisse_header.e_machine == EM_SPARCV9 + && !strcmp (rtype, "R_SPARC_OLO10")) + printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info)); + + putchar ('\n'); + + if (! is_32bit_elf && nisse_header.e_machine == EM_MIPS) + { + printf (" Type2: "); + + if (rtype2 == NULL) +#ifdef _bfd_int64_low + printf (_("unrecognized: %-7lx"), _bfd_int64_low (type2)); +#else + printf (_("unrecognized: %-7lx"), type2); +#endif + else + printf ("%-17.17s", rtype2); + + printf("\n Type3: "); + + if (rtype3 == NULL) +#ifdef _bfd_int64_low + printf (_("unrecognized: %-7lx"), _bfd_int64_low (type3)); +#else + printf (_("unrecognized: %-7lx"), type3); +#endif + else + printf ("%-17.17s", rtype3); + + putchar ('\n'); + } + } + + if (is_rela) + free (relas); + else + free (rels); + + return 1; +} + +static const char * +get_mips_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION"; + case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP"; + case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM"; + case DT_MIPS_IVERSION: return "MIPS_IVERSION"; + case DT_MIPS_FLAGS: return "MIPS_FLAGS"; + case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS"; + case DT_MIPS_MSYM: return "MIPS_MSYM"; + case DT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case DT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO"; + case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO"; + case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO"; + case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO"; + case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO"; + case DT_MIPS_GOTSYM: return "MIPS_GOTSYM"; + case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO"; + case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP"; + case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS"; + case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO"; + case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE"; + case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO"; + case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC"; + case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO"; + case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM"; + case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO"; + case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM"; + case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO"; + case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS"; + case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT"; + case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX"; + case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX"; + case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX"; + case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX"; + case DT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case DT_MIPS_INTERFACE: return "MIPS_INTERFACE"; + case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN"; + case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE"; + case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR"; + case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX"; + case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; + case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; + case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; + default: + return NULL; + } +} + +static const char * +get_sparc64_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_SPARC_REGISTER: return "SPARC_REGISTER"; + default: + return NULL; + } +} + +static const char * +get_ppc64_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_PPC64_GLINK: return "PPC64_GLINK"; + case DT_PPC64_OPD: return "PPC64_OPD"; + case DT_PPC64_OPDSZ: return "PPC64_OPDSZ"; + default: + return NULL; + } +} + +static const char * +get_parisc_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_HP_LOAD_MAP: return "HP_LOAD_MAP"; + case DT_HP_DLD_FLAGS: return "HP_DLD_FLAGS"; + case DT_HP_DLD_HOOK: return "HP_DLD_HOOK"; + case DT_HP_UX10_INIT: return "HP_UX10_INIT"; + case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ"; + case DT_HP_PREINIT: return "HP_PREINIT"; + case DT_HP_PREINITSZ: return "HP_PREINITSZ"; + case DT_HP_NEEDED: return "HP_NEEDED"; + case DT_HP_TIME_STAMP: return "HP_TIME_STAMP"; + case DT_HP_CHECKSUM: return "HP_CHECKSUM"; + case DT_HP_GST_SIZE: return "HP_GST_SIZE"; + case DT_HP_GST_VERSION: return "HP_GST_VERSION"; + case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL"; + default: + return NULL; + } +} + +static const char * +get_dynamic_type (type) + unsigned long type; +{ + static char buff [32]; + + switch (type) + { + case DT_NULL: return "NULL"; + case DT_NEEDED: return "NEEDED"; + case DT_PLTRELSZ: return "PLTRELSZ"; + case DT_PLTGOT: return "PLTGOT"; + case DT_HASH: return "HASH"; + case DT_STRTAB: return "STRTAB"; + case DT_SYMTAB: return "SYMTAB"; + case DT_RELA: return "RELA"; + case DT_RELASZ: return "RELASZ"; + case DT_RELAENT: return "RELAENT"; + case DT_STRSZ: return "STRSZ"; + case DT_SYMENT: return "SYMENT"; + case DT_INIT: return "INIT"; + case DT_FINI: return "FINI"; + case DT_SONAME: return "SONAME"; + case DT_RPATH: return "RPATH"; + case DT_SYMBOLIC: return "SYMBOLIC"; + case DT_REL: return "REL"; + case DT_RELSZ: return "RELSZ"; + case DT_RELENT: return "RELENT"; + case DT_PLTREL: return "PLTREL"; + case DT_DEBUG: return "DEBUG"; + case DT_TEXTREL: return "TEXTREL"; + case DT_JMPREL: return "JMPREL"; + case DT_BIND_NOW: return "BIND_NOW"; + case DT_INIT_ARRAY: return "INIT_ARRAY"; + case DT_FINI_ARRAY: return "FINI_ARRAY"; + case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; + case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; + case DT_RUNPATH: return "RUNPATH"; + case DT_FLAGS: return "FLAGS"; + + case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; + + case DT_CHECKSUM: return "CHECKSUM"; + case DT_PLTPADSZ: return "PLTPADSZ"; + case DT_MOVEENT: return "MOVEENT"; + case DT_MOVESZ: return "MOVESZ"; + case DT_FEATURE: return "FEATURE"; + case DT_POSFLAG_1: return "POSFLAG_1"; + case DT_SYMINSZ: return "SYMINSZ"; + case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */ + + case DT_ADDRRNGLO: return "ADDRRNGLO"; + case DT_CONFIG: return "CONFIG"; + case DT_DEPAUDIT: return "DEPAUDIT"; + case DT_AUDIT: return "AUDIT"; + case DT_PLTPAD: return "PLTPAD"; + case DT_MOVETAB: return "MOVETAB"; + case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ + + case DT_VERSYM: return "VERSYM"; + + case DT_RELACOUNT: return "RELACOUNT"; + case DT_RELCOUNT: return "RELCOUNT"; + case DT_FLAGS_1: return "FLAGS_1"; + case DT_VERDEF: return "VERDEF"; + case DT_VERDEFNUM: return "VERDEFNUM"; + case DT_VERNEED: return "VERNEED"; + case DT_VERNEEDNUM: return "VERNEEDNUM"; + + case DT_AUXILIARY: return "AUXILIARY"; + case DT_USED: return "USED"; + case DT_FILTER: return "FILTER"; + + case DT_GNU_PRELINKED: return "GNU_PRELINKED"; + case DT_GNU_CONFLICT: return "GNU_CONFLICT"; + case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ"; + case DT_GNU_LIBLIST: return "GNU_LIBLIST"; + case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ"; + + default: + if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) + { + const char * result; + + switch (nisse_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + result = get_mips_dynamic_type (type); + break; + case EM_SPARCV9: + result = get_sparc64_dynamic_type (type); + break; + case EM_PPC64: + result = get_ppc64_dynamic_type (type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, _("Processor Specific: %lx"), type); + } + else if ((type >= DT_LOOS) && (type <= DT_HIOS)) + { + const char * result; + + switch (nisse_header.e_machine) + { + case EM_PARISC: + result = get_parisc_dynamic_type (type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, _("Operating System specific: %lx"), type); + } + else + sprintf (buff, _(": %lx"), type); + + return buff; + } +} + +static char * +get_file_type (e_type) + unsigned e_type; +{ + static char buff [32]; + + switch (e_type) + { + case ET_NONE: return _("NONE (None)"); + case ET_REL: return _("REL (Relocatable file)"); + case ET_EXEC: return _("EXEC (Executable file)"); + case ET_DYN: return _("DYN (Shared object file)"); + case ET_CORE: return _("CORE (Core file)"); + + default: + if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC)) + sprintf (buff, _("Processor Specific: (%x)"), e_type); + else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS)) + sprintf (buff, _("OS Specific: (%x)"), e_type); + else + sprintf (buff, _(": %x"), e_type); + return buff; + } +} + +static char * +get_machine_name (e_machine) + unsigned e_machine; +{ + static char buff [64]; /* XXX */ + + switch (e_machine) + { + case EM_NONE: return _("None"); + case EM_M32: return "WE32100"; + case EM_SPARC: return "Sparc"; + case EM_386: return "Intel 80386"; + case EM_68K: return "MC68000"; + case EM_88K: return "MC88000"; + case EM_486: return "Intel 80486"; + case EM_860: return "Intel 80860"; + case EM_MIPS: return "MIPS R3000"; + case EM_S370: return "IBM System/370"; + case EM_MIPS_RS3_LE: return "MIPS R4000 big-endian"; + case EM_OLD_SPARCV9: return "Sparc v9 (old)"; + case EM_PARISC: return "HPPA"; + case EM_PPC_OLD: return "Power PC (old)"; + case EM_SPARC32PLUS: return "Sparc v8+" ; + case EM_960: return "Intel 90860"; + case EM_PPC: return "PowerPC"; + case EM_PPC64: return "PowerPC64"; + case EM_V800: return "NEC V800"; + case EM_FR20: return "Fujitsu FR20"; + case EM_RH32: return "TRW RH32"; + case EM_MCORE: return "MCORE"; + case EM_ARM: return "ARM"; + case EM_OLD_ALPHA: return "Digital Alpha (old)"; + case EM_SH: return "Hitachi SH"; + case EM_SPARCV9: return "Sparc v9"; + case EM_TRICORE: return "Siemens Tricore"; + case EM_ARC: return "ARC"; + case EM_H8_300: return "Hitachi H8/300"; + case EM_H8_300H: return "Hitachi H8/300H"; + case EM_H8S: return "Hitachi H8S"; + case EM_H8_500: return "Hitachi H8/500"; + case EM_IA_64: return "Intel IA-64"; + case EM_MIPS_X: return "Stanford MIPS-X"; + case EM_COLDFIRE: return "Motorola Coldfire"; + case EM_68HC12: return "Motorola M68HC12"; + case EM_ALPHA: return "Alpha"; + case EM_CYGNUS_D10V: + case EM_D10V: return "d10v"; + case EM_CYGNUS_D30V: + case EM_D30V: return "d30v"; + case EM_CYGNUS_M32R: + case EM_M32R: return "Mitsubishi M32r"; + case EM_CYGNUS_V850: + case EM_V850: return "NEC v850"; + case EM_CYGNUS_MN10300: + case EM_MN10300: return "mn10300"; + case EM_CYGNUS_MN10200: + case EM_MN10200: return "mn10200"; + case EM_CYGNUS_FR30: + case EM_FR30: return "Fujitsu FR30"; + case EM_CYGNUS_FRV: return "Fujitsu FR-V"; + case EM_PJ_OLD: + case EM_PJ: return "picoJava"; + case EM_MMA: return "Fujitsu Multimedia Accelerator"; + case EM_PCP: return "Siemens PCP"; + case EM_NCPU: return "Sony nCPU embedded RISC processor"; + case EM_NDR1: return "Denso NDR1 microprocesspr"; + case EM_STARCORE: return "Motorola Star*Core processor"; + case EM_ME16: return "Toyota ME16 processor"; + case EM_ST100: return "STMicroelectronics ST100 processor"; + case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor"; + case EM_FX66: return "Siemens FX66 microcontroller"; + case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller"; + case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller"; + case EM_68HC16: return "Motorola MC68HC16 Microcontroller"; + case EM_68HC11: return "Motorola MC68HC11 Microcontroller"; + case EM_68HC08: return "Motorola MC68HC08 Microcontroller"; + case EM_68HC05: return "Motorola MC68HC05 Microcontroller"; + case EM_SVX: return "Silicon Graphics SVx"; + case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; + case EM_VAX: return "Digital VAX"; + case EM_AVR_OLD: + case EM_AVR: return "Atmel AVR 8-bit microcontroller"; + case EM_CRIS: return "Axis Communications 32-bit embedded processor"; + case EM_JAVELIN: return "Infineon Technologies 32-bit embedded cpu"; + case EM_FIREPATH: return "Element 14 64-bit DSP processor"; + case EM_ZSP: return "LSI Logic's 16-bit DSP processor"; + case EM_MMIX: return "Donald Knuth's educational 64-bit processor"; + case EM_HUANY: return "Harvard Universitys's machine-independent object format"; + case EM_PRISM: return "SiTera Prism"; + case EM_X86_64: return "Advanced Micro Devices X86-64"; + case EM_S390_OLD: + case EM_S390: return "IBM S/390"; + case EM_XSTORMY16: return "Sanyo Xstormy16 CPU core"; + case EM_OPENRISC: + case EM_OR32: return "OpenRISC"; + case EM_DLX: return "OpenDLX"; + default: + sprintf (buff, _(": %x"), e_machine); + return buff; + } +} + +static void +decode_ARM_machine_flags (e_flags, buf) + unsigned e_flags; + char buf[]; +{ + unsigned eabi; + int unknown = 0; + + eabi = EF_ARM_EABI_VERSION (e_flags); + e_flags &= ~ EF_ARM_EABIMASK; + + /* Handle "generic" ARM flags. */ + if (e_flags & EF_ARM_RELEXEC) + { + strcat (buf, ", relocatable executable"); + e_flags &= ~ EF_ARM_RELEXEC; + } + + if (e_flags & EF_ARM_HASENTRY) + { + strcat (buf, ", has entry point"); + e_flags &= ~ EF_ARM_HASENTRY; + } + + /* Now handle EABI specific flags. */ + switch (eabi) + { + default: + strcat (buf, ", "); + if (e_flags) + unknown = 1; + break; + + case EF_ARM_EABI_VER1: + strcat (buf, ", Version1 EABI"); + while (e_flags) + { + unsigned flag; + + /* Process flags one bit at a time. */ + flag = e_flags & - e_flags; + e_flags &= ~ flag; + + switch (flag) + { + case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ + strcat (buf, ", sorted symbol tables"); + break; + + default: + unknown = 1; + break; + } + } + break; + + case EF_ARM_EABI_VER2: + strcat (buf, ", Version2 EABI"); + while (e_flags) + { + unsigned flag; + + /* Process flags one bit at a time. */ + flag = e_flags & - e_flags; + e_flags &= ~ flag; + + switch (flag) + { + case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ + strcat (buf, ", sorted symbol tables"); + break; + + case EF_ARM_DYNSYMSUSESEGIDX: + strcat (buf, ", dynamic symbols use segment index"); + break; + + case EF_ARM_MAPSYMSFIRST: + strcat (buf, ", mapping symbols precede others"); + break; + + default: + unknown = 1; + break; + } + } + break; + + case EF_ARM_EABI_UNKNOWN: + strcat (buf, ", GNU EABI"); + while (e_flags) + { + unsigned flag; + + /* Process flags one bit at a time. */ + flag = e_flags & - e_flags; + e_flags &= ~ flag; + + switch (flag) + { + case EF_ARM_INTERWORK: + strcat (buf, ", interworking enabled"); + break; + + case EF_ARM_APCS_26: + strcat (buf, ", uses APCS/26"); + break; + + case EF_ARM_APCS_FLOAT: + strcat (buf, ", uses APCS/float"); + break; + + case EF_ARM_PIC: + strcat (buf, ", position independent"); + break; + + case EF_ARM_ALIGN8: + strcat (buf, ", 8 bit structure alignment"); + break; + + case EF_ARM_NEW_ABI: + strcat (buf, ", uses new ABI"); + break; + + case EF_ARM_OLD_ABI: + strcat (buf, ", uses old ABI"); + break; + + case EF_ARM_SOFT_FLOAT: + strcat (buf, ", software FP"); + break; + + default: + unknown = 1; + break; + } + } + } + + if (unknown) + strcat (buf,", "); +} + +static char * +get_machine_flags (e_flags, e_machine) + unsigned e_flags; + unsigned e_machine; +{ + static char buf [1024]; + + buf[0] = '\0'; + + if (e_flags) + { + switch (e_machine) + { + default: + break; + + case EM_ARM: + decode_ARM_machine_flags (e_flags, buf); + break; + + case EM_68K: + if (e_flags & EF_CPU32) + strcat (buf, ", cpu32"); + if (e_flags & EF_M68000) + strcat (buf, ", m68000"); + break; + + case EM_PPC: + if (e_flags & EF_PPC_EMB) + strcat (buf, ", emb"); + + if (e_flags & EF_PPC_RELOCATABLE) + strcat (buf, ", relocatable"); + + if (e_flags & EF_PPC_RELOCATABLE_LIB) + strcat (buf, ", relocatable-lib"); + break; + + case EM_V850: + case EM_CYGNUS_V850: + switch (e_flags & EF_V850_ARCH) + { + case E_V850E_ARCH: + strcat (buf, ", v850e"); + break; + case E_V850EA_ARCH: + strcat (buf, ", v850ea"); + break; + case E_V850_ARCH: + strcat (buf, ", v850"); + break; + default: + strcat (buf, ", unknown v850 architecture variant"); + break; + } + break; + + case EM_M32R: + case EM_CYGNUS_M32R: + if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH) + strcat (buf, ", m32r"); + + break; + + case EM_MIPS: + case EM_MIPS_RS3_LE: + if (e_flags & EF_MIPS_NOREORDER) + strcat (buf, ", noreorder"); + + if (e_flags & EF_MIPS_PIC) + strcat (buf, ", pic"); + + if (e_flags & EF_MIPS_CPIC) + strcat (buf, ", cpic"); + + if (e_flags & EF_MIPS_UCODE) + strcat (buf, ", ugen_reserved"); + + if (e_flags & EF_MIPS_ABI2) + strcat (buf, ", abi2"); + + if (e_flags & EF_MIPS_OPTIONS_FIRST) + strcat (buf, ", odk first"); + + if (e_flags & EF_MIPS_32BITMODE) + strcat (buf, ", 32bitmode"); + + switch ((e_flags & EF_MIPS_MACH)) + { + case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break; + case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break; + case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break; + case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break; + case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break; + case E_MIPS_MACH_SB1: strcat (buf, ", sb1"); break; + case 0: + /* We simply ignore the field in this case to avoid confusion: + MIPS ELF does not specify EF_MIPS_MACH, it is a GNU + extension. */ + break; + default: strcat (buf, ", unknown CPU"); break; + } + + switch ((e_flags & EF_MIPS_ABI)) + { + case E_MIPS_ABI_O32: strcat (buf, ", o32"); break; + case E_MIPS_ABI_O64: strcat (buf, ", o64"); break; + case E_MIPS_ABI_EABI32: strcat (buf, ", eabi32"); break; + case E_MIPS_ABI_EABI64: strcat (buf, ", eabi64"); break; + case 0: + /* We simply ignore the field in this case to avoid confusion: + MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension. + This means it is likely to be an o32 file, but not for + sure. */ + break; + default: strcat (buf, ", unknown ABI"); break; + } + + if (e_flags & EF_MIPS_ARCH_ASE_MDMX) + strcat (buf, ", mdmx"); + + if (e_flags & EF_MIPS_ARCH_ASE_M16) + strcat (buf, ", mips16"); + + switch ((e_flags & EF_MIPS_ARCH)) + { + case E_MIPS_ARCH_1: strcat (buf, ", mips1"); break; + case E_MIPS_ARCH_2: strcat (buf, ", mips2"); break; + case E_MIPS_ARCH_3: strcat (buf, ", mips3"); break; + case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break; + case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break; + case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break; + case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break; + default: strcat (buf, ", unknown ISA"); break; + } + + break; + + case EM_SPARCV9: + if (e_flags & EF_SPARC_32PLUS) + strcat (buf, ", v8+"); + + if (e_flags & EF_SPARC_SUN_US1) + strcat (buf, ", ultrasparcI"); + + if (e_flags & EF_SPARC_SUN_US3) + strcat (buf, ", ultrasparcIII"); + + if (e_flags & EF_SPARC_HAL_R1) + strcat (buf, ", halr1"); + + if (e_flags & EF_SPARC_LEDATA) + strcat (buf, ", ledata"); + + if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO) + strcat (buf, ", tso"); + + if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO) + strcat (buf, ", pso"); + + if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO) + strcat (buf, ", rmo"); + break; + + case EM_PARISC: + switch (e_flags & EF_PARISC_ARCH) + { + case EFA_PARISC_1_0: + strcpy (buf, ", PA-RISC 1.0"); + break; + case EFA_PARISC_1_1: + strcpy (buf, ", PA-RISC 1.1"); + break; + case EFA_PARISC_2_0: + strcpy (buf, ", PA-RISC 2.0"); + break; + default: + break; + } + if (e_flags & EF_PARISC_TRAPNIL) + strcat (buf, ", trapnil"); + if (e_flags & EF_PARISC_EXT) + strcat (buf, ", ext"); + if (e_flags & EF_PARISC_LSB) + strcat (buf, ", lsb"); + if (e_flags & EF_PARISC_WIDE) + strcat (buf, ", wide"); + if (e_flags & EF_PARISC_NO_KABP) + strcat (buf, ", no kabp"); + if (e_flags & EF_PARISC_LAZYSWAP) + strcat (buf, ", lazyswap"); + break; + + case EM_PJ: + case EM_PJ_OLD: + if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS) + strcat (buf, ", new calling convention"); + + if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS) + strcat (buf, ", gnu calling convention"); + break; + + case EM_IA_64: + if ((e_flags & EF_IA_64_ABI64)) + strcat (buf, ", 64-bit"); + else + strcat (buf, ", 32-bit"); + if ((e_flags & EF_IA_64_REDUCEDFP)) + strcat (buf, ", reduced fp model"); + if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP)) + strcat (buf, ", no function descriptors, constant gp"); + else if ((e_flags & EF_IA_64_CONS_GP)) + strcat (buf, ", constant gp"); + if ((e_flags & EF_IA_64_ABSOLUTE)) + strcat (buf, ", absolute"); + break; + + case EM_VAX: + if ((e_flags & EF_VAX_NONPIC)) + strcat (buf, ", non-PIC"); + if ((e_flags & EF_VAX_DFLOAT)) + strcat (buf, ", D-Float"); + if ((e_flags & EF_VAX_GFLOAT)) + strcat (buf, ", G-Float"); + break; + } + } + + return buf; +} + +static const char * +get_mips_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_MIPS_REGINFO: + return "REGINFO"; + case PT_MIPS_RTPROC: + return "RTPROC"; + case PT_MIPS_OPTIONS: + return "OPTIONS"; + default: + break; + } + + return NULL; +} + +static const char * +get_parisc_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_HP_CORE_NONE: return "HP_CORE_NONE"; + case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; + case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; + case PT_HP_CORE_COMM: return "HP_CORE_COMM"; + case PT_HP_CORE_PROC: return "HP_CORE_PROC"; + case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; + case PT_HP_CORE_STACK: return "HP_CORE_STACK"; + case PT_HP_CORE_SHM: return "HP_CORE_SHM"; + case PT_HP_CORE_MMF: return "HP_CORE_MMF"; + case PT_HP_PARALLEL: return "HP_PARALLEL"; + case PT_HP_FASTBIND: return "HP_FASTBIND"; + case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT"; + case PT_PARISC_UNWIND: return "PARISC_UNWIND"; + default: + break; + } + + return NULL; +} + +static const char * +get_ia64_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT"; + case PT_IA_64_UNWIND: return "IA_64_UNWIND"; + case PT_HP_TLS: return "HP_TLS"; + case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT"; + case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT"; + case PT_IA_64_HP_STACK: return "HP_STACK"; + default: + break; + } + + return NULL; +} + +static const char * +get_segment_type (p_type) + unsigned long p_type; +{ + static char buff [32]; + + switch (p_type) + { + case PT_NULL: return "NULL"; + case PT_LOAD: return "LOAD"; + case PT_DYNAMIC: return "DYNAMIC"; + case PT_INTERP: return "INTERP"; + case PT_NOTE: return "NOTE"; + case PT_SHLIB: return "SHLIB"; + case PT_PHDR: return "PHDR"; + case PT_TLS: return "TLS"; + + case PT_GNU_EH_FRAME: + return "GNU_EH_FRAME"; + + default: + if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) + { + const char * result; + + switch (nisse_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + result = get_mips_segment_type (p_type); + break; + case EM_PARISC: + result = get_parisc_segment_type (p_type); + break; + case EM_IA_64: + result = get_ia64_segment_type (p_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC); + } + else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) + { + const char * result; + + switch (nisse_header.e_machine) + { + case EM_PARISC: + result = get_parisc_segment_type (p_type); + break; + case EM_IA_64: + result = get_ia64_segment_type (p_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "LOOS+%lx", p_type - PT_LOOS); + } + else + sprintf (buff, _(": %lx"), p_type); + + return buff; + } +} + +static const char * +get_mips_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case SHT_MIPS_MSYM: return "MIPS_MSYM"; + case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; + case SHT_MIPS_UCODE: return "MIPS_UCODE"; + case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; + case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; + case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; + case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; + case SHT_MIPS_RELD: return "MIPS_RELD"; + case SHT_MIPS_IFACE: return "MIPS_IFACE"; + case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; + case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case SHT_MIPS_SHDR: return "MIPS_SHDR"; + case SHT_MIPS_FDESC: return "MIPS_FDESC"; + case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM"; + case SHT_MIPS_DENSE: return "MIPS_DENSE"; + case SHT_MIPS_PDESC: return "MIPS_PDESC"; + case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM"; + case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM"; + case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM"; + case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR"; + case SHT_MIPS_LINE: return "MIPS_LINE"; + case SHT_MIPS_RFDESC: return "MIPS_RFDESC"; + case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; + case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; + case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; + case SHT_MIPS_DWARF: return "MIPS_DWARF"; + case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; + case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; + case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; + case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; + case SHT_MIPS_XLATE: return "MIPS_XLATE"; + case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; + case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; + case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; + case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; + case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; + default: + break; + } + return NULL; +} + +static const char * +get_parisc_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_PARISC_EXT: return "PARISC_EXT"; + case SHT_PARISC_UNWIND: return "PARISC_UNWIND"; + case SHT_PARISC_DOC: return "PARISC_DOC"; + default: + break; + } + return NULL; +} + +static const char * +get_ia64_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_IA_64_EXT: return "IA_64_EXT"; + case SHT_IA_64_UNWIND: return "IA_64_UNWIND"; + default: + break; + } + return NULL; +} + +static const char * +get_section_type_name (sh_type) + unsigned int sh_type; +{ + static char buff [32]; + + switch (sh_type) + { + case SHT_NULL: return "NULL"; + case SHT_PROGBITS: return "PROGBITS"; + case SHT_SYMTAB: return "SYMTAB"; + case SHT_STRTAB: return "STRTAB"; + case SHT_RELA: return "RELA"; + case SHT_HASH: return "HASH"; + case SHT_DYNAMIC: return "DYNAMIC"; + case SHT_NOTE: return "NOTE"; + case SHT_NOBITS: return "NOBITS"; + case SHT_REL: return "REL"; + case SHT_SHLIB: return "SHLIB"; + case SHT_DYNSYM: return "DYNSYM"; + case SHT_INIT_ARRAY: return "INIT_ARRAY"; + case SHT_FINI_ARRAY: return "FINI_ARRAY"; + case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case SHT_GROUP: return "GROUP"; + case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES"; + case SHT_GNU_verdef: return "VERDEF"; + case SHT_GNU_verneed: return "VERNEED"; + case SHT_GNU_versym: return "VERSYM"; + case 0x6ffffff0: return "VERSYM"; + case 0x6ffffffc: return "VERDEF"; + case 0x7ffffffd: return "AUXILIARY"; + case 0x7fffffff: return "FILTER"; + case SHT_GNU_LIBLIST: return "GNU_LIBLIST"; + + default: + if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC)) + { + const char * result; + + switch (nisse_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + result = get_mips_section_type_name (sh_type); + break; + case EM_PARISC: + result = get_parisc_section_type_name (sh_type); + break; + case EM_IA_64: + result = get_ia64_section_type_name (sh_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC); + } + else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS)) + sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS); + else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER)) + sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER); + else + sprintf (buff, _(": %x"), sh_type); + + return buff; + } +} + +#endif + +#define OPTION_DEBUG_DUMP 512 + +struct option options [] = +{ + {"all", no_argument, 0, 'a'}, + {"file-header", no_argument, 0, 'h'}, + {"program-headers", no_argument, 0, 'l'}, + {"headers", no_argument, 0, 'e'}, + {"histogram", no_argument, 0, 'I'}, + {"segments", no_argument, 0, 'l'}, + {"sections", no_argument, 0, 'S'}, + {"section-headers", no_argument, 0, 'S'}, + {"symbols", no_argument, 0, 's'}, + {"syms", no_argument, 0, 's'}, + {"relocs", no_argument, 0, 'r'}, + {"notes", no_argument, 0, 'n'}, + {"dynamic", no_argument, 0, 'd'}, + {"arch-specific", no_argument, 0, 'A'}, + {"version-info", no_argument, 0, 'V'}, + {"use-dynamic", no_argument, 0, 'D'}, + {"hex-dump", required_argument, 0, 'x'}, + {"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP}, + {"unwind", no_argument, 0, 'u'}, +#ifdef SUPPORT_DISASSEMBLY + {"instruction-dump", required_argument, 0, 'i'}, +#endif + + {"version", no_argument, 0, 'v'}, + {"wide", no_argument, 0, 'W'}, + {"help", no_argument, 0, 'H'}, + {0, no_argument, 0, 0} +}; + +static void +usage () +{ + fprintf (stdout, _("Usage: readelf elf-file(s)\n")); + fprintf (stdout, _(" Display information about the contents of ELF format files\n")); + fprintf (stdout, _(" Options are:\n\ + -a --all Equivalent to: -h -l -S -s -r -d -V -A -I\n\ + -h --file-header Display the ELF file header\n\ + -l --program-headers Display the program headers\n\ + --segments An alias for --program-headers\n\ + -S --section-headers Display the sections' header\n\ + --sections An alias for --section-headers\n\ + -e --headers Equivalent to: -h -l -S\n\ + -s --syms Display the symbol table\n\ + --symbols An alias for --syms\n\ + -n --notes Display the core notes (if present)\n\ + -r --relocs Display the relocations (if present)\n\ + -u --unwind Display the unwind info (if present)\n\ + -d --dynamic Display the dynamic segment (if present)\n\ + -V --version-info Display the version sections (if present)\n\ + -A --arch-specific Display architecture specific information (if any).\n\ + -D --use-dynamic Use the dynamic section info when displaying symbols\n\ + -x --hex-dump= Dump the contents of section \n\ + -w[liaprmfFso] or\n\ + --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\ + Display the contents of DWARF2 debug sections\n")); +#ifdef SUPPORT_DISASSEMBLY + fprintf (stdout, _("\ + -i --instruction-dump=\n\ + Disassemble the contents of section \n")); +#endif + fprintf (stdout, _("\ + -I --histogram Display histogram of bucket list lengths\n\ + -W --wide Allow output width to exceed 80 characters\n\ + -H --help Display this information\n\ + -v --version Display the version number of readelf\n")); + fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO); + + exit (0); +} + +static void +request_dump (section, type) + unsigned int section; + int type; +{ + if (section >= num_dump_sects) + { + char * new_dump_sects; + + new_dump_sects = (char *) calloc (section + 1, 1); + + if (new_dump_sects == NULL) + error (_("Out of memory allocating dump request table.")); + else + { + /* Copy current flag settings. */ + memcpy (new_dump_sects, dump_sects, num_dump_sects); + + free (dump_sects); + + dump_sects = new_dump_sects; + num_dump_sects = section + 1; + } + } + + if (dump_sects) + dump_sects [section] |= type; + + return; +} + +static void +parse_args (argc, argv) + int argc; + char ** argv; +{ + int c; + + if (argc < 2) + usage (); + + while ((c = getopt_long + (argc, argv, "ersuahnldSDAIw::x:i:vVW", options, NULL)) != EOF) + { + char * cp; + int section; + + switch (c) + { + case 0: + /* Long options. */ + break; + case 'H': + usage (); + break; + + case 'a': + do_syms ++; + do_reloc ++; + do_unwind ++; + do_dynamic ++; + do_header ++; + do_sections ++; + do_segments ++; + do_version ++; + do_histogram ++; + do_arch ++; + do_notes ++; + break; + case 'e': + do_header ++; + do_sections ++; + do_segments ++; + break; + case 'A': + do_arch ++; + break; + case 'D': + do_using_dynamic ++; + break; + case 'r': + do_reloc ++; + break; + case 'u': + do_unwind ++; + break; + case 'h': + do_header ++; + break; + case 'l': + do_segments ++; + break; + case 's': + do_syms ++; + break; + case 'S': + do_sections ++; + break; + case 'd': + do_dynamic ++; + break; + case 'I': + do_histogram ++; + break; + case 'n': + do_notes ++; + break; + case 'x': + do_dump ++; + section = strtoul (optarg, & cp, 0); + if (! * cp && section >= 0) + { + request_dump (section, HEX_DUMP); + break; + } + goto oops; + case 'w': + do_dump ++; + if (optarg == 0) + do_debugging = 1; + else + { + unsigned int index = 0; + + do_debugging = 0; + + while (optarg[index]) + switch (optarg[index++]) + { + case 'i': + case 'I': + do_debug_info = 1; + break; + + case 'a': + case 'A': + do_debug_abbrevs = 1; + break; + + case 'l': + case 'L': + do_debug_lines = 1; + break; + + case 'p': + case 'P': + do_debug_pubnames = 1; + break; + + case 'r': + case 'R': + do_debug_aranges = 1; + break; + + case 'F': + do_debug_frames_interp = 1; + case 'f': + do_debug_frames = 1; + break; + + case 'm': + case 'M': + do_debug_macinfo = 1; + break; + + case 's': + case 'S': + do_debug_str = 1; + break; + + case 'o': + case 'O': + do_debug_loc = 1; + break; + + default: + warn (_("Unrecognized debug option '%s'\n"), optarg); + break; + } + } + break; + case OPTION_DEBUG_DUMP: + do_dump ++; + if (optarg == 0) + do_debugging = 1; + else + { + const char *debug_dump_opt[] + = { "line", "info", "abbrev", "pubnames", "ranges", + "macro", "frames", "frames-interp", "str", "loc", NULL }; + unsigned int index; + const char *p; + + do_debugging = 0; + + p = optarg; + while (*p) + { + for (index = 0; debug_dump_opt[index]; index++) + { + size_t len = strlen (debug_dump_opt[index]); + + if (strncmp (p, debug_dump_opt[index], len) == 0 + && (p[len] == ',' || p[len] == '\0')) + { + switch (p[0]) + { + case 'i': + do_debug_info = 1; + break; + + case 'a': + do_debug_abbrevs = 1; + break; + + case 'l': + if (p[1] == 'i') + do_debug_lines = 1; + else + do_debug_loc = 1; + break; + + case 'p': + do_debug_pubnames = 1; + break; + + case 'r': + do_debug_aranges = 1; + break; + + case 'f': + if (len > 6) + do_debug_frames_interp = 1; + do_debug_frames = 1; + break; + + case 'm': + do_debug_macinfo = 1; + break; + + case 's': + do_debug_str = 1; + break; + } + + p += len; + break; + } + } + + if (debug_dump_opt[index] == NULL) + { + warn (_("Unrecognized debug option '%s'\n"), p); + p = strchr (p, ','); + if (p == NULL) + break; + } + + if (*p == ',') + p++; + } + } + break; +#ifdef SUPPORT_DISASSEMBLY + case 'i': + do_dump ++; + section = strtoul (optarg, & cp, 0); + if (! * cp && section >= 0) + { + request_dump (section, DISASS_DUMP); + break; + } + goto oops; +#endif + case 'v': + print_version (program_name); + break; + case 'V': + do_version ++; + break; + case 'W': + do_wide ++; + break; + default: + oops: + /* xgettext:c-format */ + error (_("Invalid option '-%c'\n"), c); + /* Drop through. */ + case '?': + usage (); + } + } + + if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections + && !do_segments && !do_header && !do_dump && !do_version + && !do_histogram && !do_debugging && !do_arch && !do_notes) + usage (); + else if (argc < 3) + { + warn (_("Nothing to do.\n")); + usage(); + } +} + +#if 0 + +static const char * +get_elf_class (elf_class) + unsigned int elf_class; +{ + static char buff [32]; + + switch (elf_class) + { + case ELFCLASSNONE: return _("none"); + case ELFCLASS32: return "ELF32"; + case ELFCLASS64: return "ELF64"; + default: + sprintf (buff, _(""), elf_class); + return buff; + } +} + +static const char * +get_data_encoding (encoding) + unsigned int encoding; +{ + static char buff [32]; + + switch (encoding) + { + case ELFDATANONE: return _("none"); + case ELFDATA2LSB: return _("2's complement, little endian"); + case ELFDATA2MSB: return _("2's complement, big endian"); + default: + sprintf (buff, _(""), encoding); + return buff; + } +} + +static const char * +get_osabi_name (osabi) + unsigned int osabi; +{ + static char buff [32]; + + switch (osabi) + { + case ELFOSABI_NONE: return "UNIX - System V"; + case ELFOSABI_HPUX: return "UNIX - HP-UX"; + case ELFOSABI_NETBSD: return "UNIX - NetBSD"; + case ELFOSABI_LINUX: return "UNIX - Linux"; + case ELFOSABI_HURD: return "GNU/Hurd"; + case ELFOSABI_SOLARIS: return "UNIX - Solaris"; + case ELFOSABI_AIX: return "UNIX - AIX"; + case ELFOSABI_IRIX: return "UNIX - IRIX"; + case ELFOSABI_FREEBSD: return "UNIX - FreeBSD"; + case ELFOSABI_TRU64: return "UNIX - TRU64"; + case ELFOSABI_MODESTO: return "Novell - Modesto"; + case ELFOSABI_OPENBSD: return "UNIX - OpenBSD"; + case ELFOSABI_STANDALONE: return _("Standalone App"); + case ELFOSABI_ARM: return "ARM"; + default: + sprintf (buff, _(""), osabi); + return buff; + } +} + +#endif + +/* Decode the data held in 'nisse_header'. */ +static int +process_file_header () +{ +#if 0 + if ( nisse_header.eihd$l_majorid != EIHD$K_MAJORID + || nisse_header.eihd$l_minorid > EIHD$K_MINORID_64) + { + error + (_("Not a NISSE file - it has the wrong magic bytes at the start\n")); + return 0; + } +#endif + + if (do_header) + { + int i; + + if (is_32bit_elf) + printf("This is an OpenVMS VAX image file\n"); + else + printf("This is an OpenVMS Alpha image file\n"); + + printf ("IMAGE HEADER\n"); + + printf ("Fixed Header Information\n"); + printf ("image format major id: %x, minor id: %x\n",nisse_header->eihd$l_majorid,nisse_header->eihd$l_minorid); + printf ("header block count: %x\n",nisse_header->eihd$l_hdrblkcnt); + printf ("image type: %x\n",nisse_header->eihd$l_imgtype); + printf ("linker flags: %x\n",nisse_header->eihd$l_lnkflags); + + printf ("Image Activation Information\n"); + + printf ("first transfer address: %x\n",nisse_active->eiha$l_tfradr1); + printf ("second transfer address: %x\n",nisse_active->eiha$l_tfradr2); + printf ("third transfer address: %x\n",nisse_active->eiha$l_tfradr3); + + printf ("Global Symbol Table & Debug Symbol Table Information\n"); + + printf("debug symbol table VBN: %x, byte count: %x\n",nisse_debug->eihs$l_dstvbn,nisse_debug->eihs$l_dstsize); + printf("global symbol table VBN: %x, record count: %x\n",nisse_debug->eihs$l_gstvbn,nisse_debug->eihs$l_gstsize); + printf("debug module/psect table VBN: %x, byte count: %x\n",nisse_debug->eihs$l_dmtvbn,nisse_debug->eihs$l_dmtbytes); + + printf("Image Identification Information\n"); + + printf("image name: %s\n",nisse_name->eihi$t_imgnam+1); + printf("image file identification: %s\n",nisse_name->eihi$t_imgid+1); + printf("image file build identification: %s\n",nisse_name->eihi$t_imgbid+1); + printf("link date/time: %x\n",nisse_name->eihi$q_linktime); + printf("linker identification: %s\n",nisse_name->eihi$t_linkid+1); + + printf("Image Section Descriptors (ISD)\n"); + + for(i=0;i" + : ""))); + printf (_(" OS/ABI: %s\n"), + get_osabi_name (nisse_header.e_ident [EI_OSABI])); + printf (_(" ABI Version: %d\n"), + nisse_header.e_ident [EI_ABIVERSION]); + printf (_(" Type: %s\n"), + get_file_type (nisse_header.e_type)); + printf (_(" Machine: %s\n"), + get_machine_name (nisse_header.e_machine)); + printf (_(" Version: 0x%lx\n"), + (unsigned long) nisse_header.e_version); + + printf (_(" Entry point address: ")); + print_vma ((bfd_vma) nisse_header.e_entry, PREFIX_HEX); + printf (_("\n Start of program headers: ")); + print_vma ((bfd_vma) nisse_header.e_phoff, DEC); + printf (_(" (bytes into file)\n Start of section headers: ")); + print_vma ((bfd_vma) nisse_header.e_shoff, DEC); + printf (_(" (bytes into file)\n")); + + printf (_(" Flags: 0x%lx%s\n"), + (unsigned long) nisse_header.e_flags, + get_machine_flags (nisse_header.e_flags, nisse_header.e_machine)); + printf (_(" Size of this header: %ld (bytes)\n"), + (long) nisse_header.e_ehsize); + printf (_(" Size of program headers: %ld (bytes)\n"), + (long) nisse_header.e_phentsize); + printf (_(" Number of program headers: %ld\n"), + (long) nisse_header.e_phnum); + printf (_(" Size of section headers: %ld (bytes)\n"), + (long) nisse_header.e_shentsize); + printf (_(" Number of section headers: %ld"), + (long) nisse_header.e_shnum); + if (section_headers != NULL && nisse_header.e_shnum == 0) + printf (" (%ld)", (long) section_headers[0].sh_size); + putc ('\n', stdout); + printf (_(" Section header string table index: %ld"), + (long) nisse_header.e_shstrndx); + if (section_headers != NULL && nisse_header.e_shstrndx == SHN_XINDEX) + printf (" (%ld)", (long) section_headers[0].sh_link); +#endif + putc ('\n', stdout); + } + +#if 0 + if (section_headers != NULL) + { + if (nisse_header.e_shnum == 0) + nisse_header.e_shnum = section_headers[0].sh_size; + if (nisse_header.e_shstrndx == SHN_XINDEX) + nisse_header.e_shstrndx = section_headers[0].sh_link; + free (section_headers); + section_headers = NULL; + } +#endif + + return 1; +} + +#if 0 + +static int +get_32bit_program_headers (file, program_headers) + FILE * file; + Elf_Internal_Phdr * program_headers; +{ + Elf32_External_Phdr * phdrs; + Elf32_External_Phdr * external; + Elf32_Internal_Phdr * internal; + unsigned int i; + + phdrs = ((Elf32_External_Phdr *) + get_data (NULL, file, nisse_header.e_phoff, + nisse_header.e_phentsize * nisse_header.e_phnum, + _("program headers"))); + if (!phdrs) + return 0; + + for (i = 0, internal = program_headers, external = phdrs; + i < nisse_header.e_phnum; + i ++, internal ++, external ++) + { + internal->p_type = BYTE_GET (external->p_type); + internal->p_offset = BYTE_GET (external->p_offset); + internal->p_vaddr = BYTE_GET (external->p_vaddr); + internal->p_paddr = BYTE_GET (external->p_paddr); + internal->p_filesz = BYTE_GET (external->p_filesz); + internal->p_memsz = BYTE_GET (external->p_memsz); + internal->p_flags = BYTE_GET (external->p_flags); + internal->p_align = BYTE_GET (external->p_align); + } + + free (phdrs); + + return 1; +} + +static int +get_64bit_program_headers (file, program_headers) + FILE * file; + Elf_Internal_Phdr * program_headers; +{ + Elf64_External_Phdr * phdrs; + Elf64_External_Phdr * external; + Elf64_Internal_Phdr * internal; + unsigned int i; + + phdrs = ((Elf64_External_Phdr *) + get_data (NULL, file, nisse_header.e_phoff, + nisse_header.e_phentsize * nisse_header.e_phnum, + _("program headers"))); + if (!phdrs) + return 0; + + for (i = 0, internal = program_headers, external = phdrs; + i < nisse_header.e_phnum; + i ++, internal ++, external ++) + { + internal->p_type = BYTE_GET (external->p_type); + internal->p_flags = BYTE_GET (external->p_flags); + internal->p_offset = BYTE_GET8 (external->p_offset); + internal->p_vaddr = BYTE_GET8 (external->p_vaddr); + internal->p_paddr = BYTE_GET8 (external->p_paddr); + internal->p_filesz = BYTE_GET8 (external->p_filesz); + internal->p_memsz = BYTE_GET8 (external->p_memsz); + internal->p_align = BYTE_GET8 (external->p_align); + } + + free (phdrs); + + return 1; +} + +static int +process_program_headers (file) + FILE * file; +{ + Elf_Internal_Phdr * program_headers; + Elf_Internal_Phdr * segment; + unsigned int i; + + if (nisse_header.e_phnum == 0) + { + if (do_segments) + printf (_("\nThere are no program headers in this file.\n")); + return 1; + } + + if (do_segments && !do_header) + { + printf (_("\nElf file type is %s\n"), get_file_type (nisse_header.e_type)); + printf (_("Entry point ")); + print_vma ((bfd_vma) nisse_header.e_entry, PREFIX_HEX); + printf (_("\nThere are %d program headers, starting at offset "), + nisse_header.e_phnum); + print_vma ((bfd_vma) nisse_header.e_phoff, DEC); + printf ("\n"); + } + + program_headers = (Elf_Internal_Phdr *) malloc + (nisse_header.e_phnum * sizeof (Elf_Internal_Phdr)); + + if (program_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + if (is_32bit_elf) + i = get_32bit_program_headers (file, program_headers); + else + i = get_64bit_program_headers (file, program_headers); + + if (i == 0) + { + free (program_headers); + return 0; + } + + if (do_segments) + { + if (nisse_header.e_phnum > 1) + printf (_("\nProgram Headers:\n")); + else + printf (_("\nProgram Headers:\n")); + + if (is_32bit_elf) + printf + (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); + else if (do_wide) + printf + (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); + else + { + printf + (_(" Type Offset VirtAddr PhysAddr\n")); + printf + (_(" FileSiz MemSiz Flags Align\n")); + } + } + + loadaddr = -1; + dynamic_addr = 0; + dynamic_size = 0; + + for (i = 0, segment = program_headers; + i < nisse_header.e_phnum; + i ++, segment ++) + { + if (do_segments) + { + printf (" %-14.14s ", get_segment_type (segment->p_type)); + + if (is_32bit_elf) + { + printf ("0x%6.6lx ", (unsigned long) segment->p_offset); + printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr); + printf ("0x%8.8lx ", (unsigned long) segment->p_paddr); + printf ("0x%5.5lx ", (unsigned long) segment->p_filesz); + printf ("0x%5.5lx ", (unsigned long) segment->p_memsz); + printf ("%c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + printf ("%#lx", (unsigned long) segment->p_align); + } + else if (do_wide) + { + if ((unsigned long) segment->p_offset == segment->p_offset) + printf ("0x%6.6lx ", (unsigned long) segment->p_offset); + else + { + print_vma (segment->p_offset, FULL_HEX); + putchar (' '); + } + + print_vma (segment->p_vaddr, FULL_HEX); + putchar (' '); + print_vma (segment->p_paddr, FULL_HEX); + putchar (' '); + + if ((unsigned long) segment->p_filesz == segment->p_filesz) + printf ("0x%6.6lx ", (unsigned long) segment->p_filesz); + else + { + print_vma (segment->p_filesz, FULL_HEX); + putchar (' '); + } + + if ((unsigned long) segment->p_memsz == segment->p_memsz) + printf ("0x%6.6lx", (unsigned long) segment->p_memsz); + else + { + print_vma (segment->p_offset, FULL_HEX); + } + + printf (" %c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + + if ((unsigned long) segment->p_align == segment->p_align) + printf ("%#lx", (unsigned long) segment->p_align); + else + { + print_vma (segment->p_align, PREFIX_HEX); + } + } + else + { + print_vma (segment->p_offset, FULL_HEX); + putchar (' '); + print_vma (segment->p_vaddr, FULL_HEX); + putchar (' '); + print_vma (segment->p_paddr, FULL_HEX); + printf ("\n "); + print_vma (segment->p_filesz, FULL_HEX); + putchar (' '); + print_vma (segment->p_memsz, FULL_HEX); + printf (" %c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + print_vma (segment->p_align, HEX); + } + } + + switch (segment->p_type) + { + case PT_LOAD: + if (loadaddr == -1) + loadaddr = (segment->p_vaddr & 0xfffff000) + - (segment->p_offset & 0xfffff000); + break; + + case PT_DYNAMIC: + if (dynamic_addr) + error (_("more than one dynamic segment\n")); + + dynamic_addr = segment->p_offset; + dynamic_size = segment->p_filesz; + break; + + case PT_INTERP: + if (fseek (file, (long) segment->p_offset, SEEK_SET)) + error (_("Unable to find program interpreter name\n")); + else + { + program_interpreter[0] = 0; + fscanf (file, "%63s", program_interpreter); + + if (do_segments) + printf (_("\n [Requesting program interpreter: %s]"), + program_interpreter); + } + break; + } + + if (do_segments) + putc ('\n', stdout); + } + + if (loadaddr == -1) + { + /* Very strange. */ + loadaddr = 0; + } + + if (do_segments && section_headers != NULL) + { + printf (_("\n Section to Segment mapping:\n")); + printf (_(" Segment Sections...\n")); + + assert (string_table != NULL); + + for (i = 0; i < nisse_header.e_phnum; i++) + { + unsigned int j; + Elf_Internal_Shdr * section; + + segment = program_headers + i; + section = section_headers; + + printf (" %2.2d ", i); + + for (j = 1; j < nisse_header.e_shnum; j++, section ++) + { + if (section->sh_size > 0 + /* Compare allocated sections by VMA, unallocated + sections by file offset. */ + && (section->sh_flags & SHF_ALLOC + ? (section->sh_addr >= segment->p_vaddr + && section->sh_addr + section->sh_size + <= segment->p_vaddr + segment->p_memsz) + : ((bfd_vma) section->sh_offset >= segment->p_offset + && (section->sh_offset + section->sh_size + <= segment->p_offset + segment->p_filesz)))) + printf ("%s ", SECTION_NAME (section)); + } + + putc ('\n',stdout); + } + } + + free (program_headers); + + return 1; +} + + +static int +get_32bit_section_headers (file, num) + FILE * file; + unsigned int num; +{ + Elf32_External_Shdr * shdrs; + Elf32_Internal_Shdr * internal; + unsigned int i; + + shdrs = ((Elf32_External_Shdr *) + get_data (NULL, file, nisse_header.e_shoff, + nisse_header.e_shentsize * num, + _("section headers"))); + if (!shdrs) + return 0; + + section_headers = ((Elf_Internal_Shdr *) + malloc (num * sizeof (Elf_Internal_Shdr))); + + if (section_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + for (i = 0, internal = section_headers; + i < num; + i ++, internal ++) + { + internal->sh_name = BYTE_GET (shdrs[i].sh_name); + internal->sh_type = BYTE_GET (shdrs[i].sh_type); + internal->sh_flags = BYTE_GET (shdrs[i].sh_flags); + internal->sh_addr = BYTE_GET (shdrs[i].sh_addr); + internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); + internal->sh_size = BYTE_GET (shdrs[i].sh_size); + internal->sh_link = BYTE_GET (shdrs[i].sh_link); + internal->sh_info = BYTE_GET (shdrs[i].sh_info); + internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); + } + + free (shdrs); + + return 1; +} + +static int +get_64bit_section_headers (file, num) + FILE * file; + unsigned int num; +{ + Elf64_External_Shdr * shdrs; + Elf64_Internal_Shdr * internal; + unsigned int i; + + shdrs = ((Elf64_External_Shdr *) + get_data (NULL, file, nisse_header.e_shoff, + nisse_header.e_shentsize * num, + _("section headers"))); + if (!shdrs) + return 0; + + section_headers = ((Elf_Internal_Shdr *) + malloc (num * sizeof (Elf_Internal_Shdr))); + + if (section_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + for (i = 0, internal = section_headers; + i < num; + i ++, internal ++) + { + internal->sh_name = BYTE_GET (shdrs[i].sh_name); + internal->sh_type = BYTE_GET (shdrs[i].sh_type); + internal->sh_flags = BYTE_GET8 (shdrs[i].sh_flags); + internal->sh_addr = BYTE_GET8 (shdrs[i].sh_addr); + internal->sh_size = BYTE_GET8 (shdrs[i].sh_size); + internal->sh_entsize = BYTE_GET8 (shdrs[i].sh_entsize); + internal->sh_link = BYTE_GET (shdrs[i].sh_link); + internal->sh_info = BYTE_GET (shdrs[i].sh_info); + internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); + internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + } + + free (shdrs); + + return 1; +} + +static Elf_Internal_Sym * +get_32bit_elf_symbols (file, section) + FILE * file; + Elf_Internal_Shdr *section; +{ + unsigned long number; + Elf32_External_Sym * esyms; + Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym * isyms; + Elf_Internal_Sym * psym; + unsigned int j; + + esyms = ((Elf32_External_Sym *) + get_data (NULL, file, section->sh_offset, + section->sh_size, _("symbols"))); + if (!esyms) + return NULL; + + shndx = NULL; + if (symtab_shndx_hdr != NULL + && (symtab_shndx_hdr->sh_link + == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) + { + shndx = ((Elf_External_Sym_Shndx *) + get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx"))); + if (!shndx) + { + free (esyms); + return NULL; + } + } + + number = section->sh_size / section->sh_entsize; + isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); + + if (isyms == NULL) + { + error (_("Out of memory\n")); + if (shndx) + free (shndx); + free (esyms); + return NULL; + } + + for (j = 0, psym = isyms; + j < number; + j ++, psym ++) + { + psym->st_name = BYTE_GET (esyms[j].st_name); + psym->st_value = BYTE_GET (esyms[j].st_value); + psym->st_size = BYTE_GET (esyms[j].st_size); + psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + if (psym->st_shndx == SHN_XINDEX && shndx != NULL) + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + psym->st_info = BYTE_GET (esyms[j].st_info); + psym->st_other = BYTE_GET (esyms[j].st_other); + } + + if (shndx) + free (shndx); + free (esyms); + + return isyms; +} + +static Elf_Internal_Sym * +get_64bit_elf_symbols (file, section) + FILE * file; + Elf_Internal_Shdr *section; +{ + unsigned long number; + Elf64_External_Sym * esyms; + Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym * isyms; + Elf_Internal_Sym * psym; + unsigned int j; + + esyms = ((Elf64_External_Sym *) + get_data (NULL, file, section->sh_offset, + section->sh_size, _("symbols"))); + if (!esyms) + return NULL; + + shndx = NULL; + if (symtab_shndx_hdr != NULL + && (symtab_shndx_hdr->sh_link + == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) + { + shndx = ((Elf_External_Sym_Shndx *) + get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx"))); + if (!shndx) + { + free (esyms); + return NULL; + } + } + + number = section->sh_size / section->sh_entsize; + isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); + + if (isyms == NULL) + { + error (_("Out of memory\n")); + if (shndx) + free (shndx); + free (esyms); + return NULL; + } + + for (j = 0, psym = isyms; + j < number; + j ++, psym ++) + { + psym->st_name = BYTE_GET (esyms[j].st_name); + psym->st_info = BYTE_GET (esyms[j].st_info); + psym->st_other = BYTE_GET (esyms[j].st_other); + psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + if (psym->st_shndx == SHN_XINDEX && shndx != NULL) + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + psym->st_value = BYTE_GET8 (esyms[j].st_value); + psym->st_size = BYTE_GET8 (esyms[j].st_size); + } + + if (shndx) + free (shndx); + free (esyms); + + return isyms; +} + +static const char * +get_elf_section_flags (sh_flags) + bfd_vma sh_flags; +{ + static char buff [32]; + + * buff = 0; + + while (sh_flags) + { + bfd_vma flag; + + flag = sh_flags & - sh_flags; + sh_flags &= ~ flag; + + switch (flag) + { + case SHF_WRITE: strcat (buff, "W"); break; + case SHF_ALLOC: strcat (buff, "A"); break; + case SHF_EXECINSTR: strcat (buff, "X"); break; + case SHF_MERGE: strcat (buff, "M"); break; + case SHF_STRINGS: strcat (buff, "S"); break; + case SHF_INFO_LINK: strcat (buff, "I"); break; + case SHF_LINK_ORDER: strcat (buff, "L"); break; + case SHF_OS_NONCONFORMING: strcat (buff, "O"); break; + case SHF_GROUP: strcat (buff, "G"); break; + case SHF_TLS: strcat (buff, "T"); break; + + default: + if (flag & SHF_MASKOS) + { + strcat (buff, "o"); + sh_flags &= ~ SHF_MASKOS; + } + else if (flag & SHF_MASKPROC) + { + strcat (buff, "p"); + sh_flags &= ~ SHF_MASKPROC; + } + else + strcat (buff, "x"); + break; + } + } + + return buff; +} + +static int +process_section_headers (file) + FILE * file; +{ + Elf_Internal_Shdr * section; + unsigned int i; + + section_headers = NULL; + + if (nisse_header.e_shnum == 0) + { + if (do_sections) + printf (_("\nThere are no sections in this file.\n")); + + return 1; + } + + if (do_sections && !do_header) + printf (_("There are %d section headers, starting at offset 0x%lx:\n"), + nisse_header.e_shnum, (unsigned long) nisse_header.e_shoff); + + if (is_32bit_elf) + { + if (! get_32bit_section_headers (file, nisse_header.e_shnum)) + return 0; + } + else if (! get_64bit_section_headers (file, nisse_header.e_shnum)) + return 0; + + /* Read in the string table, so that we have names to display. */ + section = SECTION_HEADER (nisse_header.e_shstrndx); + + if (section->sh_size != 0) + { + string_table = (char *) get_data (NULL, file, section->sh_offset, + section->sh_size, _("string table")); + + string_table_length = section->sh_size; + } + + /* Scan the sections for the dynamic symbol table + and dynamic string table and debug sections. */ + dynamic_symbols = NULL; + dynamic_strings = NULL; + dynamic_syminfo = NULL; + + for (i = 0, section = section_headers; + i < nisse_header.e_shnum; + i ++, section ++) + { + char * name = SECTION_NAME (section); + + if (section->sh_type == SHT_DYNSYM) + { + if (dynamic_symbols != NULL) + { + error (_("File contains multiple dynamic symbol tables\n")); + continue; + } + + num_dynamic_syms = section->sh_size / section->sh_entsize; + dynamic_symbols = GET_ELF_SYMBOLS (file, section); + } + else if (section->sh_type == SHT_STRTAB + && strcmp (name, ".dynstr") == 0) + { + if (dynamic_strings != NULL) + { + error (_("File contains multiple dynamic string tables\n")); + continue; + } + + dynamic_strings = (char *) get_data (NULL, file, section->sh_offset, + section->sh_size, + _("dynamic strings")); + } + else if (section->sh_type == SHT_SYMTAB_SHNDX) + { + if (symtab_shndx_hdr != NULL) + { + error (_("File contains multiple symtab shndx tables\n")); + continue; + } + symtab_shndx_hdr = section; + } + else if ((do_debugging || do_debug_info || do_debug_abbrevs + || do_debug_lines || do_debug_pubnames || do_debug_aranges + || do_debug_frames || do_debug_macinfo || do_debug_str + || do_debug_loc) + && strncmp (name, ".debug_", 7) == 0) + { + name += 7; + + if (do_debugging + || (do_debug_info && (strcmp (name, "info") == 0)) + || (do_debug_abbrevs && (strcmp (name, "abbrev") == 0)) + || (do_debug_lines && (strcmp (name, "line") == 0)) + || (do_debug_pubnames && (strcmp (name, "pubnames") == 0)) + || (do_debug_aranges && (strcmp (name, "aranges") == 0)) + || (do_debug_frames && (strcmp (name, "frame") == 0)) + || (do_debug_macinfo && (strcmp (name, "macinfo") == 0)) + || (do_debug_str && (strcmp (name, "str") == 0)) + || (do_debug_loc && (strcmp (name, "loc") == 0)) + ) + request_dump (i, DEBUG_DUMP); + } + /* linkonce section to be combined with .debug_info at link time. */ + else if ((do_debugging || do_debug_info) + && strncmp (name, ".gnu.linkonce.wi.", 17) == 0) + request_dump (i, DEBUG_DUMP); + else if (do_debug_frames && strcmp (name, ".eh_frame") == 0) + request_dump (i, DEBUG_DUMP); + } + + if (! do_sections) + return 1; + + if (nisse_header.e_shnum > 1) + printf (_("\nSection Headers:\n")); + else + printf (_("\nSection Header:\n")); + + if (is_32bit_elf) + printf + (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); + else if (do_wide) + printf + (_(" [Nr] Name Type Address Off Size ES Flg Lk Inf Al\n")); + else + { + printf (_(" [Nr] Name Type Address Offset\n")); + printf (_(" Size EntSize Flags Link Info Align\n")); + } + + for (i = 0, section = section_headers; + i < nisse_header.e_shnum; + i ++, section ++) + { + printf (" [%2u] %-17.17s %-15.15s ", + SECTION_HEADER_NUM (i), + SECTION_NAME (section), + get_section_type_name (section->sh_type)); + + if (is_32bit_elf) + { + print_vma (section->sh_addr, LONG_HEX); + + printf ( " %6.6lx %6.6lx %2.2lx", + (unsigned long) section->sh_offset, + (unsigned long) section->sh_size, + (unsigned long) section->sh_entsize); + + printf (" %3s ", get_elf_section_flags (section->sh_flags)); + + printf ("%2ld %3lx %2ld\n", + (unsigned long) section->sh_link, + (unsigned long) section->sh_info, + (unsigned long) section->sh_addralign); + } + else if (do_wide) + { + print_vma (section->sh_addr, LONG_HEX); + + if ((long) section->sh_offset == section->sh_offset) + printf (" %6.6lx", (unsigned long) section->sh_offset); + else + { + putchar (' '); + print_vma (section->sh_offset, LONG_HEX); + } + + if ((unsigned long) section->sh_size == section->sh_size) + printf (" %6.6lx", (unsigned long) section->sh_size); + else + { + putchar (' '); + print_vma (section->sh_size, LONG_HEX); + } + + if ((unsigned long) section->sh_entsize == section->sh_entsize) + printf (" %2.2lx", (unsigned long) section->sh_entsize); + else + { + putchar (' '); + print_vma (section->sh_entsize, LONG_HEX); + } + + printf (" %3s ", get_elf_section_flags (section->sh_flags)); + + printf ("%2ld %3lx ", + (unsigned long) section->sh_link, + (unsigned long) section->sh_info); + + if ((unsigned long) section->sh_addralign == section->sh_addralign) + printf ("%2ld\n", (unsigned long) section->sh_addralign); + else + { + print_vma (section->sh_addralign, DEC); + putchar ('\n'); + } + } + else + { + putchar (' '); + print_vma (section->sh_addr, LONG_HEX); + if ((long) section->sh_offset == section->sh_offset) + printf (" %8.8lx", (unsigned long) section->sh_offset); + else + { + printf (" "); + print_vma (section->sh_offset, LONG_HEX); + } + printf ("\n "); + print_vma (section->sh_size, LONG_HEX); + printf (" "); + print_vma (section->sh_entsize, LONG_HEX); + + printf (" %3s ", get_elf_section_flags (section->sh_flags)); + + printf (" %2ld %3lx %ld\n", + (unsigned long) section->sh_link, + (unsigned long) section->sh_info, + (unsigned long) section->sh_addralign); + } + } + + 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 < nisse_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 + ? "" : 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; + } + + in_body = 0; + for (dp = head + 8; dp < head + 8 + addr_size * UNW_LENGTH (stamp);) + dp = unw_decode (dp, in_body, & in_body); + } +} + +static int +slurp_ia64_unwind_table (file, aux, sec) + FILE *file; + struct unw_aux_info *aux; + Elf32_Internal_Shdr *sec; +{ + unsigned long size, addr_size, nrelas, i; + Elf_Internal_Phdr *prog_hdrs, *seg; + struct unw_table_entry *tep; + Elf32_Internal_Shdr *relsec; + Elf_Internal_Rela *rela, *rp; + unsigned char *table, *tp; + Elf_Internal_Sym *sym; + const char *relname; + int result; + + addr_size = is_32bit_elf ? 4 : 8; + + /* First, find the starting address of the segment that includes + this section: */ + + if (nisse_header.e_phnum) + { + prog_hdrs = (Elf_Internal_Phdr *) + xmalloc (nisse_header.e_phnum * sizeof (Elf_Internal_Phdr)); + + if (is_32bit_elf) + result = get_32bit_program_headers (file, prog_hdrs); + else + result = get_64bit_program_headers (file, prog_hdrs); + + if (!result) + { + free (prog_hdrs); + return 0; + } + + for (seg = prog_hdrs; seg < prog_hdrs + nisse_header.e_phnum; ++seg) + { + if (seg->p_type != PT_LOAD) + continue; + + if (sec->sh_addr >= seg->p_vaddr + && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz)) + { + aux->seg_base = seg->p_vaddr; + break; + } + } + + free (prog_hdrs); + } + + /* Second, build the unwind table from the contents of the unwind section: */ + size = sec->sh_size; + table = (char *) get_data (NULL, file, sec->sh_offset, + size, _("unwind table")); + if (!table) + return 0; + + tep = aux->table = xmalloc (size / (3 * addr_size) * sizeof (aux->table[0])); + for (tp = table; tp < table + size; tp += 3 * addr_size, ++ tep) + { + tep->start.section = SHN_UNDEF; + tep->end.section = SHN_UNDEF; + tep->info.section = SHN_UNDEF; + if (is_32bit_elf) + { + tep->start.offset = byte_get ((unsigned char *) tp + 0, 4); + tep->end.offset = byte_get ((unsigned char *) tp + 4, 4); + tep->info.offset = byte_get ((unsigned char *) tp + 8, 4); + } + else + { + tep->start.offset = BYTE_GET8 ((unsigned char *) tp + 0); + tep->end.offset = BYTE_GET8 ((unsigned char *) tp + 8); + tep->info.offset = BYTE_GET8 ((unsigned char *) tp + 16); + } + tep->start.offset += aux->seg_base; + tep->end.offset += aux->seg_base; + tep->info.offset += aux->seg_base; + } + free (table); + + /* Third, apply any relocations to the unwind table: */ + + for (relsec = section_headers; + relsec < section_headers + nisse_header.e_shnum; + ++relsec) + { + if (relsec->sh_type != SHT_RELA + || SECTION_HEADER (relsec->sh_info) != sec) + continue; + + if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, + & rela, & nrelas)) + return 0; + + for (rp = rela; rp < rela + nrelas; ++rp) + { + if (is_32bit_elf) + { + relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info)); + sym = aux->symtab + ELF32_R_SYM (rp->r_info); + + if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u\n"), + ELF32_ST_TYPE (sym->st_info)); + continue; + } + } + else + { + relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info)); + sym = aux->symtab + ELF64_R_SYM (rp->r_info); + + if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u\n"), + ELF64_ST_TYPE (sym->st_info)); + continue; + } + } + + if (strncmp (relname, "R_IA64_SEGREL", 13) != 0) + { + warn (_("Skipping unexpected relocation type %s\n"), relname); + continue; + } + + i = rp->r_offset / (3 * addr_size); + + switch (rp->r_offset/addr_size % 3) + { + case 0: + aux->table[i].start.section = sym->st_shndx; + aux->table[i].start.offset += rp->r_addend; + break; + case 1: + aux->table[i].end.section = sym->st_shndx; + aux->table[i].end.offset += rp->r_addend; + break; + case 2: + aux->table[i].info.section = sym->st_shndx; + aux->table[i].info.offset += rp->r_addend; + break; + default: + break; + } + } + + free (rela); + } + + aux->table_len = size / (3 * addr_size); + return 1; +} + +static int +process_unwind (file) + FILE * file; +{ + Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec; + unsigned long i, addr_size, unwcount = 0, unwstart = 0; + struct unw_aux_info aux; + + if (!do_unwind) + return 1; + + if (nisse_header.e_machine != EM_IA_64) + { + printf (_("\nThere are no unwind sections in this file.\n")); + return 1; + } + + memset (& aux, 0, sizeof (aux)); + + addr_size = is_32bit_elf ? 4 : 8; + + for (i = 0, sec = section_headers; i < nisse_header.e_shnum; ++i, ++sec) + { + if (sec->sh_type == SHT_SYMTAB) + { + aux.nsyms = sec->sh_size / sec->sh_entsize; + aux.symtab = GET_ELF_SYMBOLS (file, sec); + + strsec = SECTION_HEADER (sec->sh_link); + aux.strtab_size = strsec->sh_size; + aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, + aux.strtab_size, _("string table")); + } + else if (sec->sh_type == SHT_IA_64_UNWIND) + unwcount++; + } + + if (!unwcount) + printf (_("\nThere are no unwind sections in this file.\n")); + + while (unwcount-- > 0) + { + char *suffix; + size_t len, len2; + + for (i = unwstart, sec = section_headers + unwstart; + i < nisse_header.e_shnum; ++i, ++sec) + if (sec->sh_type == SHT_IA_64_UNWIND) + { + unwsec = sec; + break; + } + + unwstart = i + 1; + len = sizeof (ELF_STRING_ia64_unwind_once) - 1; + + if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, + len) == 0) + { + /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */ + len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1; + suffix = SECTION_NAME (unwsec) + len; + for (i = 0, sec = section_headers; i < nisse_header.e_shnum; + ++i, ++sec) + if (strncmp (SECTION_NAME (sec), + ELF_STRING_ia64_unwind_info_once, len2) == 0 + && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) + break; + } + else + { + /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO + .IA_64.unwind or BAR -> .IA_64.unwind_info */ + len = sizeof (ELF_STRING_ia64_unwind) - 1; + len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1; + suffix = ""; + if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, + len) == 0) + suffix = SECTION_NAME (unwsec) + len; + for (i = 0, sec = section_headers; i < nisse_header.e_shnum; + ++i, ++sec) + if (strncmp (SECTION_NAME (sec), + ELF_STRING_ia64_unwind_info, len2) == 0 + && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) + break; + } + + if (i == nisse_header.e_shnum) + { + printf (_("\nCould not find unwind info section for ")); + + if (string_table == NULL) + printf ("%d", unwsec->sh_name); + else + printf (_("'%s'"), SECTION_NAME (unwsec)); + } + else + { + aux.info_size = sec->sh_size; + aux.info_addr = sec->sh_addr; + aux.info = (char *) get_data (NULL, file, sec->sh_offset, + aux.info_size, _("unwind info")); + + printf (_("\nUnwind section ")); + + if (string_table == NULL) + printf ("%d", unwsec->sh_name); + else + printf (_("'%s'"), SECTION_NAME (unwsec)); + + printf (_(" at offset 0x%lx contains %lu entries:\n"), + (unsigned long) unwsec->sh_offset, + (unsigned long) (unwsec->sh_size / (3 * addr_size))); + + (void) slurp_ia64_unwind_table (file, & aux, unwsec); + + if (aux.table_len > 0) + dump_ia64_unwind (& aux); + + if (aux.table) + free ((char *) aux.table); + if (aux.info) + free ((char *) aux.info); + aux.table = NULL; + aux.info = NULL; + } + } + + if (aux.symtab) + free (aux.symtab); + if (aux.strtab) + free ((char *) aux.strtab); + + return 1; +} + +static void +dynamic_segment_mips_val (entry) + Elf_Internal_Dyn * entry; +{ + switch (entry->d_tag) + { + case DT_MIPS_FLAGS: + if (entry->d_un.d_val == 0) + printf ("NONE\n"); + else + { + static const char * opts[] = + { + "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT", + "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS", + "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD", + "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF", + "RLD_ORDER_SAFE" + }; + unsigned int cnt; + int first = 1; + for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt) + if (entry->d_un.d_val & (1 << cnt)) + { + printf ("%s%s", first ? "" : " ", opts[cnt]); + first = 0; + } + puts (""); + } + break; + + case DT_MIPS_IVERSION: + if (dynamic_strings != NULL) + printf ("Interface Version: %s\n", + dynamic_strings + entry->d_un.d_val); + else + printf ("%ld\n", (long) entry->d_un.d_ptr); + break; + + case DT_MIPS_TIME_STAMP: + { + char timebuf[20]; + struct tm * tmp; + + time_t time = entry->d_un.d_val; + tmp = gmtime (&time); + sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + printf ("Time Stamp: %s\n", timebuf); + } + break; + + case DT_MIPS_RLD_VERSION: + case DT_MIPS_LOCAL_GOTNO: + case DT_MIPS_CONFLICTNO: + case DT_MIPS_LIBLISTNO: + case DT_MIPS_SYMTABNO: + case DT_MIPS_UNREFEXTNO: + case DT_MIPS_HIPAGENO: + case DT_MIPS_DELTA_CLASS_NO: + case DT_MIPS_DELTA_INSTANCE_NO: + case DT_MIPS_DELTA_RELOC_NO: + case DT_MIPS_DELTA_SYM_NO: + case DT_MIPS_DELTA_CLASSSYM_NO: + case DT_MIPS_COMPACT_SIZE: + printf ("%ld\n", (long) entry->d_un.d_ptr); + break; + + default: + printf ("%#lx\n", (long) entry->d_un.d_ptr); + } +} + + +static void +dynamic_segment_parisc_val (entry) + Elf_Internal_Dyn * entry; +{ + switch (entry->d_tag) + { + case DT_HP_DLD_FLAGS: + { + static struct + { + long int bit; + const char * str; + } + flags[] = + { + { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" }, + { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" }, + { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" }, + { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" }, + { DT_HP_BIND_NOW, "HP_BIND_NOW" }, + { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" }, + { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" }, + { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" }, + { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" }, + { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" }, + { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" } + }; + int first = 1; + size_t cnt; + bfd_vma val = entry->d_un.d_val; + + for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt) + if (val & flags[cnt].bit) + { + if (! first) + putchar (' '); + fputs (flags[cnt].str, stdout); + first = 0; + val ^= flags[cnt].bit; + } + + if (val != 0 || first) + { + if (! first) + putchar (' '); + print_vma (val, HEX); + } + } + break; + + default: + print_vma (entry->d_un.d_ptr, PREFIX_HEX); + break; + } +} + +static int +get_32bit_dynamic_segment (file) + FILE * file; +{ + Elf32_External_Dyn * edyn; + Elf_Internal_Dyn * entry; + bfd_size_type i; + + edyn = (Elf32_External_Dyn *) get_data (NULL, file, dynamic_addr, + dynamic_size, _("dynamic segment")); + if (!edyn) + return 0; + + /* SGI's ELF has more than one section in the DYNAMIC segment. Determine + how large this .dynamic is now. We can do this even before the byte + swapping since the DT_NULL tag is recognizable. */ + dynamic_size = 0; + while (*(Elf32_Word *) edyn [dynamic_size++].d_tag != DT_NULL) + ; + + dynamic_segment = (Elf_Internal_Dyn *) + malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); + + if (dynamic_segment == NULL) + { + error (_("Out of memory\n")); + free (edyn); + return 0; + } + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + i ++, entry ++) + { + entry->d_tag = BYTE_GET (edyn [i].d_tag); + entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val); + } + + free (edyn); + + return 1; +} + +static int +get_64bit_dynamic_segment (file) + FILE * file; +{ + Elf64_External_Dyn * edyn; + Elf_Internal_Dyn * entry; + bfd_size_type i; + + edyn = (Elf64_External_Dyn *) get_data (NULL, file, dynamic_addr, + dynamic_size, _("dynamic segment")); + if (!edyn) + return 0; + + /* SGI's ELF has more than one section in the DYNAMIC segment. Determine + how large this .dynamic is now. We can do this even before the byte + swapping since the DT_NULL tag is recognizable. */ + dynamic_size = 0; + while (*(bfd_vma *) edyn [dynamic_size ++].d_tag != DT_NULL) + ; + + dynamic_segment = (Elf_Internal_Dyn *) + malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); + + if (dynamic_segment == NULL) + { + error (_("Out of memory\n")); + free (edyn); + return 0; + } + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + i ++, entry ++) + { + entry->d_tag = BYTE_GET8 (edyn [i].d_tag); + entry->d_un.d_val = BYTE_GET8 (edyn [i].d_un.d_val); + } + + free (edyn); + + return 1; +} + +static const char * +get_dynamic_flags (flags) + bfd_vma flags; +{ + static char buff [128]; + char *p = buff; + + *p = '\0'; + while (flags) + { + bfd_vma flag; + + flag = flags & - flags; + flags &= ~ flag; + + if (p != buff) + *p++ = ' '; + + switch (flag) + { + case DF_ORIGIN: strcpy (p, "ORIGIN"); break; + case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break; + case DF_TEXTREL: strcpy (p, "TEXTREL"); break; + case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break; + case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break; + default: strcpy (p, "unknown"); break; + } + + p = strchr (p, '\0'); + } + return buff; +} + +/* Parse and display the contents of the dynamic segment. */ +static int +process_dynamic_segment (file) + FILE * file; +{ + Elf_Internal_Dyn * entry; + bfd_size_type i; + + if (dynamic_size == 0) + { + if (do_dynamic) + printf (_("\nThere is no dynamic segment in this file.\n")); + + return 1; + } + + if (is_32bit_elf) + { + if (! get_32bit_dynamic_segment (file)) + return 0; + } + else if (! get_64bit_dynamic_segment (file)) + return 0; + + /* Find the appropriate symbol table. */ + if (dynamic_symbols == NULL) + { + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + Elf32_Internal_Shdr section; + + if (entry->d_tag != DT_SYMTAB) + continue; + + dynamic_info[DT_SYMTAB] = entry->d_un.d_val; + + /* Since we do not know how big the symbol table is, + we default to reading in the entire file (!) and + processing that. This is overkill, I know, but it + should work. */ + section.sh_offset = entry->d_un.d_val - loadaddr; + + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file!")); + + section.sh_size = ftell (file) - section.sh_offset; + if (is_32bit_elf) + section.sh_entsize = sizeof (Elf32_External_Sym); + else + section.sh_entsize = sizeof (Elf64_External_Sym); + + num_dynamic_syms = section.sh_size / section.sh_entsize; + if (num_dynamic_syms < 1) + { + error (_("Unable to determine the number of symbols to load\n")); + continue; + } + + dynamic_symbols = GET_ELF_SYMBOLS (file, §ion); + } + } + + /* Similarly find a string table. */ + if (dynamic_strings == NULL) + { + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + unsigned long offset; + long str_tab_len; + + if (entry->d_tag != DT_STRTAB) + continue; + + dynamic_info[DT_STRTAB] = entry->d_un.d_val; + + /* Since we do not know how big the string table is, + we default to reading in the entire file (!) and + processing that. This is overkill, I know, but it + should work. */ + + offset = entry->d_un.d_val - loadaddr; + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file\n")); + str_tab_len = ftell (file) - offset; + + if (str_tab_len < 1) + { + error + (_("Unable to determine the length of the dynamic string table\n")); + continue; + } + + dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len, + _("dynamic string table")); + break; + } + } + + /* And find the syminfo section if available. */ + if (dynamic_syminfo == NULL) + { + unsigned int syminsz = 0; + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + if (entry->d_tag == DT_SYMINENT) + { + /* Note: these braces are necessary to avoid a syntax + error from the SunOS4 C compiler. */ + assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val); + } + else if (entry->d_tag == DT_SYMINSZ) + syminsz = entry->d_un.d_val; + else if (entry->d_tag == DT_SYMINFO) + dynamic_syminfo_offset = entry->d_un.d_val - loadaddr; + } + + if (dynamic_syminfo_offset != 0 && syminsz != 0) + { + Elf_External_Syminfo * extsyminfo; + Elf_Internal_Syminfo * syminfo; + + /* There is a syminfo section. Read the data. */ + extsyminfo = ((Elf_External_Syminfo *) + get_data (NULL, file, dynamic_syminfo_offset, + syminsz, _("symbol information"))); + if (!extsyminfo) + return 0; + + dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); + if (dynamic_syminfo == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo); + for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent; + ++i, ++syminfo) + { + syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto); + syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags); + } + + free (extsyminfo); + } + } + + if (do_dynamic && dynamic_addr) + printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"), + dynamic_addr, (long) dynamic_size); + if (do_dynamic) + printf (_(" Tag Type Name/Value\n")); + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + i++, entry ++) + { + if (do_dynamic) + { + const char * dtype; + + putchar (' '); + print_vma (entry->d_tag, FULL_HEX); + dtype = get_dynamic_type (entry->d_tag); + printf (" (%s)%*s", dtype, + ((is_32bit_elf ? 27 : 19) + - (int) strlen (dtype)), + " "); + } + + switch (entry->d_tag) + { + case DT_FLAGS: + if (do_dynamic) + puts (get_dynamic_flags (entry->d_un.d_val)); + break; + + case DT_AUXILIARY: + case DT_FILTER: + case DT_CONFIG: + case DT_DEPAUDIT: + case DT_AUDIT: + if (do_dynamic) + { + switch (entry->d_tag) + { + case DT_AUXILIARY: + printf (_("Auxiliary library")); + break; + + case DT_FILTER: + printf (_("Filter library")); + break; + + case DT_CONFIG: + printf (_("Configuration file")); + break; + + case DT_DEPAUDIT: + printf (_("Dependency audit library")); + break; + + case DT_AUDIT: + printf (_("Audit library")); + break; + } + + if (dynamic_strings) + printf (": [%s]\n", dynamic_strings + entry->d_un.d_val); + else + { + printf (": "); + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); + } + } + break; + + case DT_FEATURE: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DTF_1_PARINIT) + { + printf (" PARINIT"); + val ^= DTF_1_PARINIT; + } + if (val & DTF_1_CONFEXP) + { + printf (" CONFEXP"); + val ^= DTF_1_CONFEXP; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_POSFLAG_1: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DF_P1_LAZYLOAD) + { + printf (" LAZYLOAD"); + val ^= DF_P1_LAZYLOAD; + } + if (val & DF_P1_GROUPPERM) + { + printf (" GROUPPERM"); + val ^= DF_P1_GROUPPERM; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_FLAGS_1: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DF_1_NOW) + { + printf (" NOW"); + val ^= DF_1_NOW; + } + if (val & DF_1_GLOBAL) + { + printf (" GLOBAL"); + val ^= DF_1_GLOBAL; + } + if (val & DF_1_GROUP) + { + printf (" GROUP"); + val ^= DF_1_GROUP; + } + if (val & DF_1_NODELETE) + { + printf (" NODELETE"); + val ^= DF_1_NODELETE; + } + if (val & DF_1_LOADFLTR) + { + printf (" LOADFLTR"); + val ^= DF_1_LOADFLTR; + } + if (val & DF_1_INITFIRST) + { + printf (" INITFIRST"); + val ^= DF_1_INITFIRST; + } + if (val & DF_1_NOOPEN) + { + printf (" NOOPEN"); + val ^= DF_1_NOOPEN; + } + if (val & DF_1_ORIGIN) + { + printf (" ORIGIN"); + val ^= DF_1_ORIGIN; + } + if (val & DF_1_DIRECT) + { + printf (" DIRECT"); + val ^= DF_1_DIRECT; + } + if (val & DF_1_TRANS) + { + printf (" TRANS"); + val ^= DF_1_TRANS; + } + if (val & DF_1_INTERPOSE) + { + printf (" INTERPOSE"); + val ^= DF_1_INTERPOSE; + } + if (val & DF_1_NODEFLIB) + { + printf (" NODEFLIB"); + val ^= DF_1_NODEFLIB; + } + if (val & DF_1_NODUMP) + { + printf (" NODUMP"); + val ^= DF_1_NODUMP; + } + if (val & DF_1_CONLFAT) + { + printf (" CONLFAT"); + val ^= DF_1_CONLFAT; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_PLTREL: + if (do_dynamic) + puts (get_dynamic_type (entry->d_un.d_val)); + break; + + case DT_NULL : + case DT_NEEDED : + case DT_PLTGOT : + case DT_HASH : + case DT_STRTAB : + case DT_SYMTAB : + case DT_RELA : + case DT_INIT : + case DT_FINI : + case DT_SONAME : + case DT_RPATH : + case DT_SYMBOLIC: + case DT_REL : + case DT_DEBUG : + case DT_TEXTREL : + case DT_JMPREL : + case DT_RUNPATH : + dynamic_info[entry->d_tag] = entry->d_un.d_val; + + if (do_dynamic) + { + char * name; + + if (dynamic_strings == NULL) + name = NULL; + else + name = dynamic_strings + entry->d_un.d_val; + + if (name) + { + switch (entry->d_tag) + { + case DT_NEEDED: + printf (_("Shared library: [%s]"), name); + + if (strcmp (name, program_interpreter) == 0) + printf (_(" program interpreter")); + break; + + case DT_SONAME: + printf (_("Library soname: [%s]"), name); + break; + + case DT_RPATH: + printf (_("Library rpath: [%s]"), name); + break; + + case DT_RUNPATH: + printf (_("Library runpath: [%s]"), name); + break; + + default: + print_vma (entry->d_un.d_val, PREFIX_HEX); + break; + } + } + else + print_vma (entry->d_un.d_val, PREFIX_HEX); + + putchar ('\n'); + } + break; + + case DT_PLTRELSZ: + case DT_RELASZ : + case DT_STRSZ : + case DT_RELSZ : + case DT_RELAENT : + case DT_SYMENT : + case DT_RELENT : + case DT_PLTPADSZ: + case DT_MOVEENT : + case DT_MOVESZ : + case DT_INIT_ARRAYSZ: + case DT_FINI_ARRAYSZ: + case DT_GNU_CONFLICTSZ: + case DT_GNU_LIBLISTSZ: + if (do_dynamic) + { + print_vma (entry->d_un.d_val, UNSIGNED); + printf (" (bytes)\n"); + } + break; + + case DT_VERDEFNUM: + case DT_VERNEEDNUM: + case DT_RELACOUNT: + case DT_RELCOUNT: + if (do_dynamic) + { + print_vma (entry->d_un.d_val, UNSIGNED); + putchar ('\n'); + } + break; + + case DT_SYMINSZ: + case DT_SYMINENT: + case DT_SYMINFO: + case DT_USED: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + if (do_dynamic) + { + if (dynamic_strings != NULL && entry->d_tag == DT_USED) + { + char * name; + + name = dynamic_strings + entry->d_un.d_val; + + if (* name) + { + printf (_("Not needed object: [%s]\n"), name); + break; + } + } + + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); + } + break; + + case DT_BIND_NOW: + /* The value of this entry is ignored. */ + break; + + case DT_GNU_PRELINKED: + if (do_dynamic) + { + struct tm * tmp; + time_t time = entry->d_un.d_val; + + tmp = gmtime (&time); + printf ("%04u-%02u-%02uT%02u:%02u:%02u\n", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + } + break; + + default: + if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM)) + version_info [DT_VERSIONTAGIDX (entry->d_tag)] = + entry->d_un.d_val; + + if (do_dynamic) + { + switch (nisse_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + dynamic_segment_mips_val (entry); + break; + case EM_PARISC: + dynamic_segment_parisc_val (entry); + break; + default: + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); + } + } + break; + } + } + + return 1; +} + +static char * +get_ver_flags (flags) + unsigned int flags; +{ + static char buff [32]; + + buff[0] = 0; + + if (flags == 0) + return _("none"); + + if (flags & VER_FLG_BASE) + strcat (buff, "BASE "); + + if (flags & VER_FLG_WEAK) + { + if (flags & VER_FLG_BASE) + strcat (buff, "| "); + + strcat (buff, "WEAK "); + } + + if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)) + strcat (buff, "| "); + + return buff; +} + +/* Display the contents of the version sections. */ +static int +process_version_sections (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + unsigned i; + int found = 0; + + if (! do_version) + return 1; + + for (i = 0, section = section_headers; + i < nisse_header.e_shnum; + i++, section ++) + { + switch (section->sh_type) + { + case SHT_GNU_verdef: + { + Elf_External_Verdef * edefs; + unsigned int idx; + unsigned int cnt; + + found = 1; + + printf + (_("\nVersion definition section '%s' contains %ld entries:\n"), + SECTION_NAME (section), section->sh_info); + + printf (_(" Addr: 0x")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link: %lx (%s)\n"), + (unsigned long) section->sh_offset, section->sh_link, + SECTION_NAME (SECTION_HEADER (section->sh_link))); + + edefs = ((Elf_External_Verdef *) + get_data (NULL, file, section->sh_offset, + section->sh_size, + _("version definition section"))); + if (!edefs) + break; + + for (idx = cnt = 0; cnt < section->sh_info; ++ cnt) + { + char * vstart; + Elf_External_Verdef * edef; + Elf_Internal_Verdef ent; + Elf_External_Verdaux * eaux; + Elf_Internal_Verdaux aux; + int j; + int isum; + + vstart = ((char *) edefs) + idx; + + edef = (Elf_External_Verdef *) vstart; + + ent.vd_version = BYTE_GET (edef->vd_version); + ent.vd_flags = BYTE_GET (edef->vd_flags); + ent.vd_ndx = BYTE_GET (edef->vd_ndx); + ent.vd_cnt = BYTE_GET (edef->vd_cnt); + ent.vd_hash = BYTE_GET (edef->vd_hash); + ent.vd_aux = BYTE_GET (edef->vd_aux); + ent.vd_next = BYTE_GET (edef->vd_next); + + printf (_(" %#06x: Rev: %d Flags: %s"), + idx, ent.vd_version, get_ver_flags (ent.vd_flags)); + + printf (_(" Index: %d Cnt: %d "), + ent.vd_ndx, ent.vd_cnt); + + vstart += ent.vd_aux; + + eaux = (Elf_External_Verdaux *) vstart; + + aux.vda_name = BYTE_GET (eaux->vda_name); + aux.vda_next = BYTE_GET (eaux->vda_next); + + if (dynamic_strings) + printf (_("Name: %s\n"), dynamic_strings + aux.vda_name); + else + printf (_("Name index: %ld\n"), aux.vda_name); + + isum = idx + ent.vd_aux; + + for (j = 1; j < ent.vd_cnt; j ++) + { + isum += aux.vda_next; + vstart += aux.vda_next; + + eaux = (Elf_External_Verdaux *) vstart; + + aux.vda_name = BYTE_GET (eaux->vda_name); + aux.vda_next = BYTE_GET (eaux->vda_next); + + if (dynamic_strings) + printf (_(" %#06x: Parent %d: %s\n"), + isum, j, dynamic_strings + aux.vda_name); + else + printf (_(" %#06x: Parent %d, name index: %ld\n"), + isum, j, aux.vda_name); + } + + idx += ent.vd_next; + } + + free (edefs); + } + break; + + case SHT_GNU_verneed: + { + Elf_External_Verneed * eneed; + unsigned int idx; + unsigned int cnt; + + found = 1; + + printf (_("\nVersion needs section '%s' contains %ld entries:\n"), + SECTION_NAME (section), section->sh_info); + + printf (_(" Addr: 0x")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link to section: %ld (%s)\n"), + (unsigned long) section->sh_offset, section->sh_link, + SECTION_NAME (SECTION_HEADER (section->sh_link))); + + eneed = ((Elf_External_Verneed *) + get_data (NULL, file, section->sh_offset, + section->sh_size, _("version need section"))); + if (!eneed) + break; + + for (idx = cnt = 0; cnt < section->sh_info; ++cnt) + { + Elf_External_Verneed * entry; + Elf_Internal_Verneed ent; + int j; + int isum; + char * vstart; + + vstart = ((char *) eneed) + idx; + + entry = (Elf_External_Verneed *) vstart; + + ent.vn_version = BYTE_GET (entry->vn_version); + ent.vn_cnt = BYTE_GET (entry->vn_cnt); + ent.vn_file = BYTE_GET (entry->vn_file); + ent.vn_aux = BYTE_GET (entry->vn_aux); + ent.vn_next = BYTE_GET (entry->vn_next); + + printf (_(" %#06x: Version: %d"), idx, ent.vn_version); + + if (dynamic_strings) + printf (_(" File: %s"), dynamic_strings + ent.vn_file); + else + printf (_(" File: %lx"), ent.vn_file); + + printf (_(" Cnt: %d\n"), ent.vn_cnt); + + vstart += ent.vn_aux; + + for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j) + { + Elf_External_Vernaux * eaux; + Elf_Internal_Vernaux aux; + + eaux = (Elf_External_Vernaux *) vstart; + + aux.vna_hash = BYTE_GET (eaux->vna_hash); + aux.vna_flags = BYTE_GET (eaux->vna_flags); + aux.vna_other = BYTE_GET (eaux->vna_other); + aux.vna_name = BYTE_GET (eaux->vna_name); + aux.vna_next = BYTE_GET (eaux->vna_next); + + if (dynamic_strings) + printf (_(" %#06x: Name: %s"), + isum, dynamic_strings + aux.vna_name); + else + printf (_(" %#06x: Name index: %lx"), + isum, aux.vna_name); + + printf (_(" Flags: %s Version: %d\n"), + get_ver_flags (aux.vna_flags), aux.vna_other); + + isum += aux.vna_next; + vstart += aux.vna_next; + } + + idx += ent.vn_next; + } + + free (eneed); + } + break; + + case SHT_GNU_versym: + { + Elf32_Internal_Shdr * link_section; + int total; + int cnt; + unsigned char * edata; + unsigned short * data; + char * strtab; + Elf_Internal_Sym * symbols; + Elf32_Internal_Shdr * string_sec; + + link_section = SECTION_HEADER (section->sh_link); + total = section->sh_size / section->sh_entsize; + + found = 1; + + symbols = GET_ELF_SYMBOLS (file, link_section); + + string_sec = SECTION_HEADER (link_section->sh_link); + + strtab = (char *) get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, + _("version string table")); + if (!strtab) + break; + + printf (_("\nVersion symbols section '%s' contains %d entries:\n"), + SECTION_NAME (section), total); + + printf (_(" Addr: ")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link: %lx (%s)\n"), + (unsigned long) section->sh_offset, section->sh_link, + SECTION_NAME (link_section)); + + edata = + ((unsigned char *) + get_data (NULL, file, + version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr, + total * sizeof (short), _("version symbol data"))); + if (!edata) + { + free (strtab); + break; + } + + data = (unsigned short *) malloc (total * sizeof (short)); + + for (cnt = total; cnt --;) + data [cnt] = byte_get (edata + cnt * sizeof (short), + sizeof (short)); + + free (edata); + + for (cnt = 0; cnt < total; cnt += 4) + { + int j, nn; + int check_def, check_need; + char * name; + + printf (" %03x:", cnt); + + for (j = 0; (j < 4) && (cnt + j) < total; ++j) + switch (data [cnt + j]) + { + case 0: + fputs (_(" 0 (*local*) "), stdout); + break; + + case 1: + fputs (_(" 1 (*global*) "), stdout); + break; + + default: + nn = printf ("%4x%c", data [cnt + j] & 0x7fff, + data [cnt + j] & 0x8000 ? 'h' : ' '); + + check_def = 1; + check_need = 1; + if (SECTION_HEADER (symbols [cnt + j].st_shndx)->sh_type + != SHT_NOBITS) + { + if (symbols [cnt + j].st_shndx == SHN_UNDEF) + check_def = 0; + else + check_need = 0; + } + + if (check_need + && version_info [DT_VERSIONTAGIDX (DT_VERNEED)]) + { + Elf_Internal_Verneed ivn; + unsigned long offset; + + offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + - loadaddr; + + do + { + Elf_Internal_Vernaux ivna; + Elf_External_Verneed evn; + Elf_External_Vernaux evna; + unsigned long a_off; + + get_data (&evn, file, offset, sizeof (evn), + _("version need")); + + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); + + a_off = offset + ivn.vn_aux; + + do + { + get_data (&evna, file, a_off, sizeof (evna), + _("version need aux (2)")); + + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_other = BYTE_GET (evna.vna_other); + + a_off += ivna.vna_next; + } + while (ivna.vna_other != data [cnt + j] + && ivna.vna_next != 0); + + if (ivna.vna_other == data [cnt + j]) + { + ivna.vna_name = BYTE_GET (evna.vna_name); + + name = strtab + ivna.vna_name; + nn += printf ("(%s%-*s", + name, + 12 - (int) strlen (name), + ")"); + check_def = 0; + break; + } + + offset += ivn.vn_next; + } + while (ivn.vn_next); + } + + if (check_def && data [cnt + j] != 0x8001 + && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) + { + Elf_Internal_Verdef ivd; + Elf_External_Verdef evd; + unsigned long offset; + + offset = version_info + [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr; + + do + { + get_data (&evd, file, offset, sizeof (evd), + _("version def")); + + ivd.vd_next = BYTE_GET (evd.vd_next); + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + + offset += ivd.vd_next; + } + while (ivd.vd_ndx != (data [cnt + j] & 0x7fff) + && ivd.vd_next != 0); + + if (ivd.vd_ndx == (data [cnt + j] & 0x7fff)) + { + Elf_External_Verdaux evda; + Elf_Internal_Verdaux ivda; + + ivd.vd_aux = BYTE_GET (evd.vd_aux); + + get_data (&evda, file, + offset - ivd.vd_next + ivd.vd_aux, + sizeof (evda), _("version def aux")); + + ivda.vda_name = BYTE_GET (evda.vda_name); + + name = strtab + ivda.vda_name; + nn += printf ("(%s%-*s", + name, + 12 - (int) strlen (name), + ")"); + } + } + + if (nn < 18) + printf ("%*c", 18 - nn, ' '); + } + + putchar ('\n'); + } + + free (data); + free (strtab); + free (symbols); + } + break; + + default: + break; + } + } + + if (! found) + printf (_("\nNo version information found in this file.\n")); + + return 1; +} + +static const char * +get_symbol_binding (binding) + unsigned int binding; +{ + static char buff [32]; + + switch (binding) + { + case STB_LOCAL: return "LOCAL"; + case STB_GLOBAL: return "GLOBAL"; + case STB_WEAK: return "WEAK"; + default: + if (binding >= STB_LOPROC && binding <= STB_HIPROC) + sprintf (buff, _(": %d"), binding); + else if (binding >= STB_LOOS && binding <= STB_HIOS) + sprintf (buff, _(": %d"), binding); + else + sprintf (buff, _(": %d"), binding); + return buff; + } +} + +static const char * +get_symbol_type (type) + unsigned int type; +{ + static char buff [32]; + + switch (type) + { + case STT_NOTYPE: return "NOTYPE"; + case STT_OBJECT: return "OBJECT"; + case STT_FUNC: return "FUNC"; + case STT_SECTION: return "SECTION"; + case STT_FILE: return "FILE"; + case STT_COMMON: return "COMMON"; + case STT_TLS: return "TLS"; + default: + if (type >= STT_LOPROC && type <= STT_HIPROC) + { + if (nisse_header.e_machine == EM_ARM && type == STT_ARM_TFUNC) + return "THUMB_FUNC"; + + if (nisse_header.e_machine == EM_SPARCV9 && type == STT_REGISTER) + return "REGISTER"; + + if (nisse_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI) + return "PARISC_MILLI"; + + sprintf (buff, _(": %d"), type); + } + else if (type >= STT_LOOS && type <= STT_HIOS) + { + if (nisse_header.e_machine == EM_PARISC) + { + if (type == STT_HP_OPAQUE) + return "HP_OPAQUE"; + if (type == STT_HP_STUB) + return "HP_STUB"; + } + + sprintf (buff, _(": %d"), type); + } + else + sprintf (buff, _(": %d"), type); + return buff; + } +} + +static const char * +get_symbol_visibility (visibility) + unsigned int visibility; +{ + switch (visibility) + { + case STV_DEFAULT: return "DEFAULT"; + case STV_INTERNAL: return "INTERNAL"; + case STV_HIDDEN: return "HIDDEN"; + case STV_PROTECTED: return "PROTECTED"; + default: abort (); + } +} + +static const char * +get_symbol_index_type (type) + unsigned int type; +{ + switch (type) + { + case SHN_UNDEF: return "UND"; + case SHN_ABS: return "ABS"; + case SHN_COMMON: return "COM"; + default: + if (type >= SHN_LOPROC && type <= SHN_HIPROC) + return "PRC"; + else if (type >= SHN_LOOS && type <= SHN_HIOS) + return "OS "; + else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) + return "RSV"; + else + { + static char buff [32]; + + sprintf (buff, "%3d", type); + return buff; + } + } +} + +static int * +get_dynamic_data (file, number) + FILE * file; + unsigned int number; +{ + unsigned char * e_data; + int * i_data; + + e_data = (unsigned char *) malloc (number * 4); + + if (e_data == NULL) + { + error (_("Out of memory\n")); + return NULL; + } + + if (fread (e_data, 4, number, file) != number) + { + error (_("Unable to read in dynamic data\n")); + return NULL; + } + + i_data = (int *) malloc (number * sizeof (* i_data)); + + if (i_data == NULL) + { + error (_("Out of memory\n")); + free (e_data); + return NULL; + } + + while (number--) + i_data [number] = byte_get (e_data + number * 4, 4); + + free (e_data); + + return i_data; +} + +/* Dump the symbol table. */ +static int +process_symbol_table (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + unsigned char nb [4]; + unsigned char nc [4]; + int nbuckets = 0; + int nchains = 0; + int * buckets = NULL; + int * chains = NULL; + + if (! do_syms && !do_histogram) + return 1; + + if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL) + || do_histogram)) + { + if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET)) + { + error (_("Unable to seek to start of dynamic information")); + return 0; + } + + if (fread (nb, sizeof (nb), 1, file) != 1) + { + error (_("Failed to read in number of buckets\n")); + return 0; + } + + if (fread (nc, sizeof (nc), 1, file) != 1) + { + error (_("Failed to read in number of chains\n")); + return 0; + } + + nbuckets = byte_get (nb, 4); + nchains = byte_get (nc, 4); + + buckets = get_dynamic_data (file, nbuckets); + chains = get_dynamic_data (file, nchains); + + if (buckets == NULL || chains == NULL) + return 0; + } + + if (do_syms + && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL) + { + int hn; + int si; + + printf (_("\nSymbol table for image:\n")); + if (is_32bit_elf) + printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + else + printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + + for (hn = 0; hn < nbuckets; hn++) + { + if (! buckets [hn]) + continue; + + for (si = buckets [hn]; si < nchains && si > 0; si = chains [si]) + { + Elf_Internal_Sym * psym; + + psym = dynamic_symbols + si; + + printf (" %3d %3d: ", si, hn); + print_vma (psym->st_value, LONG_HEX); + putchar (' ' ); + print_vma (psym->st_size, DEC_5); + + printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); + printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); + printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); + printf (" %3.3s ", get_symbol_index_type (psym->st_shndx)); + print_symbol (25, dynamic_strings + psym->st_name); + putchar ('\n'); + } + } + } + else if (do_syms && !do_using_dynamic) + { + unsigned int i; + + for (i = 0, section = section_headers; + i < nisse_header.e_shnum; + i++, section++) + { + unsigned int si; + char * strtab; + Elf_Internal_Sym * symtab; + Elf_Internal_Sym * psym; + + + if ( section->sh_type != SHT_SYMTAB + && section->sh_type != SHT_DYNSYM) + continue; + + printf (_("\nSymbol table '%s' contains %lu entries:\n"), + SECTION_NAME (section), + (unsigned long) (section->sh_size / section->sh_entsize)); + if (is_32bit_elf) + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); + else + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); + + symtab = GET_ELF_SYMBOLS (file, section); + if (symtab == NULL) + continue; + + if (section->sh_link == nisse_header.e_shstrndx) + strtab = string_table; + else + { + Elf32_Internal_Shdr * string_sec; + + string_sec = SECTION_HEADER (section->sh_link); + + strtab = (char *) get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, + _("string table")); + } + + for (si = 0, psym = symtab; + si < section->sh_size / section->sh_entsize; + si ++, psym ++) + { + printf ("%6d: ", si); + print_vma (psym->st_value, LONG_HEX); + putchar (' '); + print_vma (psym->st_size, DEC_5); + printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); + printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); + printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); + printf (" %4s ", get_symbol_index_type (psym->st_shndx)); + print_symbol (25, strtab + psym->st_name); + + if (section->sh_type == SHT_DYNSYM && + version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0) + { + unsigned char data[2]; + unsigned short vers_data; + unsigned long offset; + int is_nobits; + int check_def; + + offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)] + - loadaddr; + + get_data (&data, file, offset + si * sizeof (vers_data), + sizeof (data), _("version data")); + + vers_data = byte_get (data, 2); + + is_nobits = (SECTION_HEADER (psym->st_shndx)->sh_type + == SHT_NOBITS); + + check_def = (psym->st_shndx != SHN_UNDEF); + + if ((vers_data & 0x8000) || vers_data > 1) + { + if (version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + && (is_nobits || ! check_def)) + { + Elf_External_Verneed evn; + Elf_Internal_Verneed ivn; + Elf_Internal_Vernaux ivna; + + /* We must test both. */ + offset = version_info + [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr; + + do + { + unsigned long vna_off; + + get_data (&evn, file, offset, sizeof (evn), + _("version need")); + + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); + + vna_off = offset + ivn.vn_aux; + + do + { + Elf_External_Vernaux evna; + + get_data (&evna, file, vna_off, + sizeof (evna), + _("version need aux (3)")); + + ivna.vna_other = BYTE_GET (evna.vna_other); + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_name = BYTE_GET (evna.vna_name); + + vna_off += ivna.vna_next; + } + while (ivna.vna_other != vers_data + && ivna.vna_next != 0); + + if (ivna.vna_other == vers_data) + break; + + offset += ivn.vn_next; + } + while (ivn.vn_next != 0); + + if (ivna.vna_other == vers_data) + { + printf ("@%s (%d)", + strtab + ivna.vna_name, ivna.vna_other); + check_def = 0; + } + else if (! is_nobits) + error (_("bad dynamic symbol")); + else + check_def = 1; + } + + if (check_def) + { + if (vers_data != 0x8001 + && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) + { + Elf_Internal_Verdef ivd; + Elf_Internal_Verdaux ivda; + Elf_External_Verdaux evda; + unsigned long offset; + + offset = + version_info [DT_VERSIONTAGIDX (DT_VERDEF)] + - loadaddr; + + do + { + Elf_External_Verdef evd; + + get_data (&evd, file, offset, sizeof (evd), + _("version def")); + + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + ivd.vd_aux = BYTE_GET (evd.vd_aux); + ivd.vd_next = BYTE_GET (evd.vd_next); + + offset += ivd.vd_next; + } + while (ivd.vd_ndx != (vers_data & 0x7fff) + && ivd.vd_next != 0); + + offset -= ivd.vd_next; + offset += ivd.vd_aux; + + get_data (&evda, file, offset, sizeof (evda), + _("version def aux")); + + ivda.vda_name = BYTE_GET (evda.vda_name); + + if (psym->st_name != ivda.vda_name) + printf ((vers_data & 0x8000) + ? "@%s" : "@@%s", + strtab + ivda.vda_name); + } + } + } + } + + putchar ('\n'); + } + + free (symtab); + if (strtab != string_table) + free (strtab); + } + } + else if (do_syms) + printf + (_("\nDynamic symbol information is not available for displaying symbols.\n")); + + if (do_histogram && buckets != NULL) + { + int * lengths; + int * counts; + int hn; + int si; + int maxlength = 0; + int nzero_counts = 0; + int nsyms = 0; + + printf (_("\nHistogram for bucket list length (total of %d buckets):\n"), + nbuckets); + printf (_(" Length Number %% of total Coverage\n")); + + lengths = (int *) calloc (nbuckets, sizeof (int)); + if (lengths == NULL) + { + error (_("Out of memory")); + return 0; + } + for (hn = 0; hn < nbuckets; ++hn) + { + if (! buckets [hn]) + continue; + + for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si]) + { + ++ nsyms; + if (maxlength < ++lengths[hn]) + ++ maxlength; + } + } + + counts = (int *) calloc (maxlength + 1, sizeof (int)); + if (counts == NULL) + { + error (_("Out of memory")); + return 0; + } + + for (hn = 0; hn < nbuckets; ++hn) + ++ counts [lengths [hn]]; + + if (nbuckets > 0) + { + printf (" 0 %-10d (%5.1f%%)\n", + counts[0], (counts[0] * 100.0) / nbuckets); + for (si = 1; si <= maxlength; ++si) + { + nzero_counts += counts[si] * si; + printf ("%7d %-10d (%5.1f%%) %5.1f%%\n", + si, counts[si], (counts[si] * 100.0) / nbuckets, + (nzero_counts * 100.0) / nsyms); + } + } + + free (counts); + free (lengths); + } + + if (buckets != NULL) + { + free (buckets); + free (chains); + } + + return 1; +} + +static int +process_syminfo (file) + FILE * file ATTRIBUTE_UNUSED; +{ + unsigned int i; + + if (dynamic_syminfo == NULL + || !do_dynamic) + /* No syminfo, this is ok. */ + return 1; + + /* There better should be a dynamic symbol section. */ + if (dynamic_symbols == NULL || dynamic_strings == NULL) + return 0; + + if (dynamic_addr) + printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"), + dynamic_syminfo_offset, dynamic_syminfo_nent); + + printf (_(" Num: Name BoundTo Flags\n")); + for (i = 0; i < dynamic_syminfo_nent; ++i) + { + unsigned short int flags = dynamic_syminfo[i].si_flags; + + printf ("%4d: ", i); + print_symbol (30, dynamic_strings + dynamic_symbols[i].st_name); + putchar (' '); + + switch (dynamic_syminfo[i].si_boundto) + { + case SYMINFO_BT_SELF: + fputs ("SELF ", stdout); + break; + case SYMINFO_BT_PARENT: + fputs ("PARENT ", stdout); + break; + default: + if (dynamic_syminfo[i].si_boundto > 0 + && dynamic_syminfo[i].si_boundto < dynamic_size) + { + print_symbol (10, dynamic_strings + + dynamic_segment + [dynamic_syminfo[i].si_boundto].d_un.d_val); + putchar (' ' ); + } + else + printf ("%-10d ", dynamic_syminfo[i].si_boundto); + break; + } + + if (flags & SYMINFO_FLG_DIRECT) + printf (" DIRECT"); + if (flags & SYMINFO_FLG_PASSTHRU) + printf (" PASSTHRU"); + if (flags & SYMINFO_FLG_COPY) + printf (" COPY"); + if (flags & SYMINFO_FLG_LAZYLOAD) + printf (" LAZYLOAD"); + + puts (""); + } + + return 1; +} + +#ifdef SUPPORT_DISASSEMBLY +static void +disassemble_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + printf (_("\nAssembly dump of section %s\n"), + SECTION_NAME (section)); + + /* XXX -- to be done --- XXX */ + + return 1; +} +#endif + +static int +dump_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + bfd_size_type bytes; + bfd_vma addr; + unsigned char * data; + unsigned char * start; + + bytes = section->sh_size; + + if (bytes == 0) + { + printf (_("\nSection '%s' has no data to dump.\n"), + SECTION_NAME (section)); + return 0; + } + else + printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section)); + + addr = section->sh_addr; + + start = (unsigned char *) get_data (NULL, file, section->sh_offset, bytes, + _("section data")); + if (!start) + return 0; + + data = start; + + while (bytes) + { + int j; + int k; + int lbytes; + + lbytes = (bytes > 16 ? 16 : bytes); + + printf (" 0x%8.8lx ", (unsigned long) addr); + + switch (nisse_header.e_ident [EI_DATA]) + { + default: + case ELFDATA2LSB: + for (j = 15; j >= 0; j --) + { + if (j < lbytes) + printf ("%2.2x", data [j]); + else + printf (" "); + + if (!(j & 0x3)) + printf (" "); + } + break; + + case ELFDATA2MSB: + for (j = 0; j < 16; j++) + { + if (j < lbytes) + printf ("%2.2x", data [j]); + else + printf (" "); + + if ((j & 3) == 3) + printf (" "); + } + break; + } + + for (j = 0; j < lbytes; j++) + { + k = data [j]; + if (k >= ' ' && k < 0x80) + printf ("%c", k); + else + printf ("."); + } + + putchar ('\n'); + + data += lbytes; + addr += lbytes; + bytes -= lbytes; + } + + free (start); + + return 1; +} + + +static unsigned long int +read_leb128 (data, length_return, sign) + unsigned char * data; + int * length_return; + int sign; +{ + unsigned long int result = 0; + unsigned int num_read = 0; + int shift = 0; + unsigned char byte; + + do + { + byte = * data ++; + num_read ++; + + result |= (byte & 0x7f) << shift; + + shift += 7; + + } + while (byte & 0x80); + + if (length_return != NULL) + * length_return = num_read; + + if (sign && (shift < 32) && (byte & 0x40)) + result |= -1 << shift; + + return result; +} + +typedef struct State_Machine_Registers +{ + unsigned long address; + unsigned int file; + unsigned int line; + unsigned int column; + int is_stmt; + int basic_block; + int end_sequence; +/* This variable hold the number of the last entry seen + in the File Table. */ + unsigned int last_file_entry; +} SMR; + +static SMR state_machine_regs; + +static void +reset_state_machine (is_stmt) + int is_stmt; +{ + state_machine_regs.address = 0; + state_machine_regs.file = 1; + state_machine_regs.line = 1; + state_machine_regs.column = 0; + state_machine_regs.is_stmt = is_stmt; + state_machine_regs.basic_block = 0; + state_machine_regs.end_sequence = 0; + state_machine_regs.last_file_entry = 0; +} + +/* Handled an extend line op. Returns true if this is the end + of sequence. */ +static int +process_extended_line_op (data, is_stmt, pointer_size) + unsigned char * data; + int is_stmt; + int pointer_size; +{ + unsigned char op_code; + int bytes_read; + unsigned int len; + unsigned char * name; + unsigned long adr; + + len = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + + if (len == 0) + { + warn (_("badly formed extended line op encountered!\n")); + return bytes_read; + } + + len += bytes_read; + op_code = * data ++; + + printf (_(" Extended opcode %d: "), op_code); + + switch (op_code) + { + case DW_LNE_end_sequence: + printf (_("End of Sequence\n\n")); + reset_state_machine (is_stmt); + break; + + case DW_LNE_set_address: + adr = byte_get (data, pointer_size); + printf (_("set Address to 0x%lx\n"), adr); + state_machine_regs.address = adr; + break; + + case DW_LNE_define_file: + printf (_(" define new File Table entry\n")); + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + name = data; + data += strlen ((char *) data) + 1; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + printf (_("%s\n\n"), name); + break; + + default: + printf (_("UNKNOWN: length %d\n"), len - bytes_read); + break; + } + + return len; +} + +/* Size of pointers in the .debug_line section. This information is not + really present in that section. It's obtained before dumping the debug + sections by doing some pre-scan of the .debug_info section. */ +static int debug_line_pointer_size = 4; + +static int +display_debug_lines (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + DWARF2_External_LineInfo * external; + DWARF2_Internal_LineInfo info; + unsigned char * standard_opcodes; + unsigned char * data = start; + unsigned char * end = start + section->sh_size; + unsigned char * end_of_sequence; + int i; + + printf (_("\nDump of debug contents of section %s:\n\n"), + SECTION_NAME (section)); + + while (data < end) + { + external = (DWARF2_External_LineInfo *) data; + + /* Check the length of the block. */ + info.li_length = BYTE_GET (external->li_length); + + if (info.li_length == 0xffffffff) + { + warn (_("64-bit DWARF line info is not supported yet.\n")); + break; + } + + if (info.li_length + sizeof (external->li_length) > section->sh_size) + { + warn + (_("The line info appears to be corrupt - the section is too small\n")); + return 0; + } + + /* Check its version number. */ + info.li_version = BYTE_GET (external->li_version); + if (info.li_version != 2) + { + warn (_("Only DWARF version 2 line info is currently supported.\n")); + return 0; + } + + info.li_prologue_length = BYTE_GET (external->li_prologue_length); + info.li_min_insn_length = BYTE_GET (external->li_min_insn_length); + info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt); + info.li_line_base = BYTE_GET (external->li_line_base); + info.li_line_range = BYTE_GET (external->li_line_range); + info.li_opcode_base = BYTE_GET (external->li_opcode_base); + + /* Sign extend the line base field. */ + info.li_line_base <<= 24; + info.li_line_base >>= 24; + + printf (_(" Length: %ld\n"), info.li_length); + printf (_(" DWARF Version: %d\n"), info.li_version); + printf (_(" Prologue Length: %d\n"), info.li_prologue_length); + printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length); + printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt); + printf (_(" Line Base: %d\n"), info.li_line_base); + printf (_(" Line Range: %d\n"), info.li_line_range); + printf (_(" Opcode Base: %d\n"), info.li_opcode_base); + + end_of_sequence = data + info.li_length + sizeof (external->li_length); + + reset_state_machine (info.li_default_is_stmt); + + /* Display the contents of the Opcodes table. */ + standard_opcodes = data + sizeof (* external); + + printf (_("\n Opcodes:\n")); + + for (i = 1; i < info.li_opcode_base; i++) + printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]); + + /* Display the contents of the Directory table. */ + data = standard_opcodes + info.li_opcode_base - 1; + + if (* data == 0) + printf (_("\n The Directory Table is empty.\n")); + else + { + printf (_("\n The Directory Table:\n")); + + while (* data != 0) + { + printf (_(" %s\n"), data); + + data += strlen ((char *) data) + 1; + } + } + + /* Skip the NUL at the end of the table. */ + data ++; + + /* Display the contents of the File Name table. */ + if (* data == 0) + printf (_("\n The File Name Table is empty.\n")); + else + { + printf (_("\n The File Name Table:\n")); + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + + while (* data != 0) + { + unsigned char * name; + int bytes_read; + + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + name = data; + + data += strlen ((char *) data) + 1; + + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%s\n"), name); + } + } + + /* Skip the NUL at the end of the table. */ + data ++; + + /* Now display the statements. */ + printf (_("\n Line Number Statements:\n")); + + + while (data < end_of_sequence) + { + unsigned char op_code; + int adv; + int bytes_read; + + op_code = * data ++; + + if (op_code >= info.li_opcode_base) + { + op_code -= info.li_opcode_base; + adv = (op_code / info.li_line_range) * info.li_min_insn_length; + state_machine_regs.address += adv; + printf (_(" Special opcode %d: advance Address by %d to 0x%lx"), + op_code, adv, state_machine_regs.address); + adv = (op_code % info.li_line_range) + info.li_line_base; + state_machine_regs.line += adv; + printf (_(" and Line by %d to %d\n"), + adv, state_machine_regs.line); + } + else switch (op_code) + { + case DW_LNS_extended_op: + data += process_extended_line_op (data, info.li_default_is_stmt, + debug_line_pointer_size); + break; + + case DW_LNS_copy: + printf (_(" Copy\n")); + break; + + case DW_LNS_advance_pc: + adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0); + data += bytes_read; + state_machine_regs.address += adv; + printf (_(" Advance PC by %d to %lx\n"), adv, + state_machine_regs.address); + break; + + case DW_LNS_advance_line: + adv = read_leb128 (data, & bytes_read, 1); + data += bytes_read; + state_machine_regs.line += adv; + printf (_(" Advance Line by %d to %d\n"), adv, + state_machine_regs.line); + break; + + case DW_LNS_set_file: + adv = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (_(" Set File Name to entry %d in the File Name Table\n"), + adv); + state_machine_regs.file = adv; + break; + + case DW_LNS_set_column: + adv = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (_(" Set column to %d\n"), adv); + state_machine_regs.column = adv; + break; + + case DW_LNS_negate_stmt: + adv = state_machine_regs.is_stmt; + adv = ! adv; + printf (_(" Set is_stmt to %d\n"), adv); + state_machine_regs.is_stmt = adv; + break; + + case DW_LNS_set_basic_block: + printf (_(" Set basic block\n")); + state_machine_regs.basic_block = 1; + break; + + case DW_LNS_const_add_pc: + adv = (((255 - info.li_opcode_base) / info.li_line_range) + * info.li_min_insn_length); + state_machine_regs.address += adv; + printf (_(" Advance PC by constant %d to 0x%lx\n"), adv, + state_machine_regs.address); + break; + + case DW_LNS_fixed_advance_pc: + adv = byte_get (data, 2); + data += 2; + state_machine_regs.address += adv; + printf (_(" Advance PC by fixed size amount %d to 0x%lx\n"), + adv, state_machine_regs.address); + break; + + case DW_LNS_set_prologue_end: + printf (_(" Set prologue_end to true\n")); + break; + + case DW_LNS_set_epilogue_begin: + printf (_(" Set epilogue_begin to true\n")); + break; + + case DW_LNS_set_isa: + adv = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (_(" Set ISA to %d\n"), adv); + break; + + default: + printf (_(" Unknown opcode %d with operands: "), op_code); + { + int i; + for (i = standard_opcodes[op_code - 1]; i > 0 ; --i) + { + printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0), + i == 1 ? "" : ", "); + data += bytes_read; + } + putchar ('\n'); + } + break; + } + } + putchar ('\n'); + } + + return 1; +} + +static int +display_debug_pubnames (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + DWARF2_External_PubNames * external; + DWARF2_Internal_PubNames pubnames; + unsigned char * end; + + end = start + section->sh_size; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + unsigned char * data; + unsigned long offset; + + external = (DWARF2_External_PubNames *) start; + + pubnames.pn_length = BYTE_GET (external->pn_length); + pubnames.pn_version = BYTE_GET (external->pn_version); + pubnames.pn_offset = BYTE_GET (external->pn_offset); + pubnames.pn_size = BYTE_GET (external->pn_size); + + data = start + sizeof (* external); + start += pubnames.pn_length + sizeof (external->pn_length); + + if (pubnames.pn_length == 0xffffffff) + { + warn (_("64-bit DWARF pubnames are not supported yet.\n")); + break; + } + + if (pubnames.pn_version != 2) + { + static int warned = 0; + + if (! warned) + { + warn (_("Only DWARF 2 pubnames are currently supported\n")); + warned = 1; + } + + continue; + } + + printf (_(" Length: %ld\n"), + pubnames.pn_length); + printf (_(" Version: %d\n"), + pubnames.pn_version); + printf (_(" Offset into .debug_info section: %ld\n"), + pubnames.pn_offset); + printf (_(" Size of area in .debug_info section: %ld\n"), + pubnames.pn_size); + + printf (_("\n Offset\tName\n")); + + do + { + offset = byte_get (data, 4); + + if (offset != 0) + { + data += 4; + printf (" %ld\t\t%s\n", offset, data); + data += strlen ((char *) data) + 1; + } + } + while (offset != 0); + } + + printf ("\n"); + return 1; +} + +static char * +get_TAG_name (tag) + unsigned long tag; +{ + switch (tag) + { + case DW_TAG_padding: return "DW_TAG_padding"; + case DW_TAG_array_type: return "DW_TAG_array_type"; + case DW_TAG_class_type: return "DW_TAG_class_type"; + case DW_TAG_entry_point: return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; + case DW_TAG_label: return "DW_TAG_label"; + case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; + case DW_TAG_member: return "DW_TAG_member"; + case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; + case DW_TAG_string_type: return "DW_TAG_string_type"; + case DW_TAG_structure_type: return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: return "DW_TAG_typedef"; + case DW_TAG_union_type: return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: return "DW_TAG_variant"; + case DW_TAG_common_block: return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: return "DW_TAG_set_type"; + case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; + case DW_TAG_base_type: return "DW_TAG_base_type"; + case DW_TAG_catch_block: return "DW_TAG_catch_block"; + case DW_TAG_const_type: return "DW_TAG_const_type"; + case DW_TAG_constant: return "DW_TAG_constant"; + case DW_TAG_enumerator: return "DW_TAG_enumerator"; + case DW_TAG_file_type: return "DW_TAG_file_type"; + case DW_TAG_friend: return "DW_TAG_friend"; + case DW_TAG_namelist: return "DW_TAG_namelist"; + case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: return "DW_TAG_packed_type"; + case DW_TAG_subprogram: return "DW_TAG_subprogram"; + case DW_TAG_template_type_param: return "DW_TAG_template_type_param"; + case DW_TAG_template_value_param: return "DW_TAG_template_value_param"; + case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; + case DW_TAG_try_block: return "DW_TAG_try_block"; + case DW_TAG_variant_part: return "DW_TAG_variant_part"; + case DW_TAG_variable: return "DW_TAG_variable"; + case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; + case DW_TAG_format_label: return "DW_TAG_format_label"; + case DW_TAG_function_template: return "DW_TAG_function_template"; + case DW_TAG_class_template: return "DW_TAG_class_template"; + /* DWARF 2.1 values. */ + case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: return "DW_TAG_interface_type"; + case DW_TAG_namespace: return "DW_TAG_namespace"; + case DW_TAG_imported_module: return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown TAG value: %lx"), tag); + return buffer; + } + } +} + +static char * +get_AT_name (attribute) + unsigned long attribute; +{ + switch (attribute) + { + case DW_AT_sibling: return "DW_AT_sibling"; + case DW_AT_location: return "DW_AT_location"; + case DW_AT_name: return "DW_AT_name"; + case DW_AT_ordering: return "DW_AT_ordering"; + case DW_AT_subscr_data: return "DW_AT_subscr_data"; + case DW_AT_byte_size: return "DW_AT_byte_size"; + case DW_AT_bit_offset: return "DW_AT_bit_offset"; + case DW_AT_bit_size: return "DW_AT_bit_size"; + case DW_AT_element_list: return "DW_AT_element_list"; + case DW_AT_stmt_list: return "DW_AT_stmt_list"; + case DW_AT_low_pc: return "DW_AT_low_pc"; + case DW_AT_high_pc: return "DW_AT_high_pc"; + case DW_AT_language: return "DW_AT_language"; + case DW_AT_member: return "DW_AT_member"; + case DW_AT_discr: return "DW_AT_discr"; + case DW_AT_discr_value: return "DW_AT_discr_value"; + case DW_AT_visibility: return "DW_AT_visibility"; + case DW_AT_import: return "DW_AT_import"; + case DW_AT_string_length: return "DW_AT_string_length"; + case DW_AT_common_reference: return "DW_AT_common_reference"; + case DW_AT_comp_dir: return "DW_AT_comp_dir"; + case DW_AT_const_value: return "DW_AT_const_value"; + case DW_AT_containing_type: return "DW_AT_containing_type"; + case DW_AT_default_value: return "DW_AT_default_value"; + case DW_AT_inline: return "DW_AT_inline"; + case DW_AT_is_optional: return "DW_AT_is_optional"; + case DW_AT_lower_bound: return "DW_AT_lower_bound"; + case DW_AT_producer: return "DW_AT_producer"; + case DW_AT_prototyped: return "DW_AT_prototyped"; + case DW_AT_return_addr: return "DW_AT_return_addr"; + case DW_AT_start_scope: return "DW_AT_start_scope"; + case DW_AT_stride_size: return "DW_AT_stride_size"; + case DW_AT_upper_bound: return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; + case DW_AT_accessibility: return "DW_AT_accessibility"; + case DW_AT_address_class: return "DW_AT_address_class"; + case DW_AT_artificial: return "DW_AT_artificial"; + case DW_AT_base_types: return "DW_AT_base_types"; + case DW_AT_calling_convention: return "DW_AT_calling_convention"; + case DW_AT_count: return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; + case DW_AT_decl_column: return "DW_AT_decl_column"; + case DW_AT_decl_file: return "DW_AT_decl_file"; + case DW_AT_decl_line: return "DW_AT_decl_line"; + case DW_AT_declaration: return "DW_AT_declaration"; + case DW_AT_discr_list: return "DW_AT_discr_list"; + case DW_AT_encoding: return "DW_AT_encoding"; + case DW_AT_external: return "DW_AT_external"; + case DW_AT_frame_base: return "DW_AT_frame_base"; + case DW_AT_friend: return "DW_AT_friend"; + case DW_AT_identifier_case: return "DW_AT_identifier_case"; + case DW_AT_macro_info: return "DW_AT_macro_info"; + case DW_AT_namelist_items: return "DW_AT_namelist_items"; + case DW_AT_priority: return "DW_AT_priority"; + case DW_AT_segment: return "DW_AT_segment"; + case DW_AT_specification: return "DW_AT_specification"; + case DW_AT_static_link: return "DW_AT_static_link"; + case DW_AT_type: return "DW_AT_type"; + case DW_AT_use_location: return "DW_AT_use_location"; + case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; + case DW_AT_virtuality: return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; + /* DWARF 2.1 values. */ + case DW_AT_allocated: return "DW_AT_allocated"; + case DW_AT_associated: return "DW_AT_associated"; + case DW_AT_data_location: return "DW_AT_data_location"; + case DW_AT_stride: return "DW_AT_stride"; + case DW_AT_entry_pc: return "DW_AT_entry_pc"; + case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; + case DW_AT_extension: return "DW_AT_extension"; + case DW_AT_ranges: return "DW_AT_ranges"; + case DW_AT_trampoline: return "DW_AT_trampoline"; + case DW_AT_call_column: return "DW_AT_call_column"; + case DW_AT_call_file: return "DW_AT_call_file"; + case DW_AT_call_line: return "DW_AT_call_line"; + /* SGI/MIPS extensions. */ + case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; + case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; + case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; + case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; + case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; + case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; + case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; + case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; + case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; + case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; + /* GNU extensions. */ + case DW_AT_sf_names: return "DW_AT_sf_names"; + case DW_AT_src_info: return "DW_AT_src_info"; + case DW_AT_mac_info: return "DW_AT_mac_info"; + case DW_AT_src_coords: return "DW_AT_src_coords"; + case DW_AT_body_begin: return "DW_AT_body_begin"; + case DW_AT_body_end: return "DW_AT_body_end"; + case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown AT value: %lx"), attribute); + return buffer; + } + } +} + +static char * +get_FORM_name (form) + unsigned long form; +{ + switch (form) + { + case DW_FORM_addr: return "DW_FORM_addr"; + case DW_FORM_block2: return "DW_FORM_block2"; + case DW_FORM_block4: return "DW_FORM_block4"; + case DW_FORM_data2: return "DW_FORM_data2"; + case DW_FORM_data4: return "DW_FORM_data4"; + case DW_FORM_data8: return "DW_FORM_data8"; + case DW_FORM_string: return "DW_FORM_string"; + case DW_FORM_block: return "DW_FORM_block"; + case DW_FORM_block1: return "DW_FORM_block1"; + case DW_FORM_data1: return "DW_FORM_data1"; + case DW_FORM_flag: return "DW_FORM_flag"; + case DW_FORM_sdata: return "DW_FORM_sdata"; + case DW_FORM_strp: return "DW_FORM_strp"; + case DW_FORM_udata: return "DW_FORM_udata"; + case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; + case DW_FORM_ref1: return "DW_FORM_ref1"; + case DW_FORM_ref2: return "DW_FORM_ref2"; + case DW_FORM_ref4: return "DW_FORM_ref4"; + case DW_FORM_ref8: return "DW_FORM_ref8"; + case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; + case DW_FORM_indirect: return "DW_FORM_indirect"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown FORM value: %lx"), form); + return buffer; + } + } +} + +/* FIXME: There are better and more effiecint ways to handle + these structures. For now though, I just want something that + is simple to implement. */ +typedef struct abbrev_attr +{ + unsigned long attribute; + unsigned long form; + struct abbrev_attr * next; +} +abbrev_attr; + +typedef struct abbrev_entry +{ + unsigned long entry; + unsigned long tag; + int children; + struct abbrev_attr * first_attr; + struct abbrev_attr * last_attr; + struct abbrev_entry * next; +} +abbrev_entry; + +static abbrev_entry * first_abbrev = NULL; +static abbrev_entry * last_abbrev = NULL; + +static void +free_abbrevs PARAMS ((void)) +{ + abbrev_entry * abbrev; + + for (abbrev = first_abbrev; abbrev;) + { + abbrev_entry * next = abbrev->next; + abbrev_attr * attr; + + for (attr = abbrev->first_attr; attr;) + { + abbrev_attr * next = attr->next; + + free (attr); + attr = next; + } + + free (abbrev); + abbrev = next; + } + + last_abbrev = first_abbrev = NULL; +} + +static void +add_abbrev (number, tag, children) + unsigned long number; + unsigned long tag; + int children; +{ + abbrev_entry * entry; + + entry = (abbrev_entry *) malloc (sizeof (* entry)); + + if (entry == NULL) + /* ugg */ + return; + + entry->entry = number; + entry->tag = tag; + entry->children = children; + entry->first_attr = NULL; + entry->last_attr = NULL; + entry->next = NULL; + + if (first_abbrev == NULL) + first_abbrev = entry; + else + last_abbrev->next = entry; + + last_abbrev = entry; +} + +static void +add_abbrev_attr (attribute, form) + unsigned long attribute; + unsigned long form; +{ + abbrev_attr * attr; + + attr = (abbrev_attr *) malloc (sizeof (* attr)); + + if (attr == NULL) + /* ugg */ + return; + + attr->attribute = attribute; + attr->form = form; + attr->next = NULL; + + if (last_abbrev->first_attr == NULL) + last_abbrev->first_attr = attr; + else + last_abbrev->last_attr->next = attr; + + last_abbrev->last_attr = attr; +} + +/* Processes the (partial) contents of a .debug_abbrev section. + Returns NULL if the end of the section was encountered. + Returns the address after the last byte read if the end of + an abbreviation set was found. */ + +static unsigned char * +process_abbrev_section (start, end) + unsigned char * start; + unsigned char * end; +{ + if (first_abbrev != NULL) + return NULL; + + while (start < end) + { + int bytes_read; + unsigned long entry; + unsigned long tag; + unsigned long attribute; + int children; + + entry = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + /* A single zero is supposed to end the section according + to the standard. If there's more, then signal that to + the caller. */ + if (entry == 0) + return start == end ? NULL : start; + + tag = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + children = * start ++; + + add_abbrev (entry, tag, children); + + do + { + unsigned long form; + + attribute = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + form = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + if (attribute != 0) + add_abbrev_attr (attribute, form); + } + while (attribute != 0); + } + + return NULL; +} + + +static int +display_debug_macinfo (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + unsigned char * end = start + section->sh_size; + unsigned char * curr = start; + unsigned int bytes_read; + enum dwarf_macinfo_record_type op; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + while (curr < end) + { + unsigned int lineno; + const char * string; + + op = * curr; + curr ++; + + switch (op) + { + case DW_MACINFO_start_file: + { + unsigned int filenum; + + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + filenum = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + + printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), lineno, filenum); + } + break; + + case DW_MACINFO_end_file: + printf (_(" DW_MACINFO_end_file\n")); + break; + + case DW_MACINFO_define: + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string); + break; + + case DW_MACINFO_undef: + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string); + break; + + case DW_MACINFO_vendor_ext: + { + unsigned int constant; + + constant = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string); + } + break; + } + } + + return 1; +} + + +static int +display_debug_abbrev (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + abbrev_entry * entry; + unsigned char * end = start + section->sh_size; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + do + { + start = process_abbrev_section (start, end); + + if (first_abbrev == NULL) + continue; + + printf (_(" Number TAG\n")); + + for (entry = first_abbrev; entry; entry = entry->next) + { + abbrev_attr * attr; + + printf (_(" %ld %s [%s]\n"), + entry->entry, + get_TAG_name (entry->tag), + entry->children ? _("has children") : _("no children")); + + for (attr = entry->first_attr; attr; attr = attr->next) + { + printf (_(" %-18s %s\n"), + get_AT_name (attr->attribute), + get_FORM_name (attr->form)); + } + } + + free_abbrevs (); + } + while (start); + + printf ("\n"); + + return 1; +} + + +static unsigned char * +display_block (data, length) + unsigned char * data; + unsigned long length; +{ + printf (_(" %lu byte block: "), length); + + while (length --) + printf ("%lx ", (unsigned long) byte_get (data ++, 1)); + + return data; +} + +static void +decode_location_expression (data, pointer_size, length) + unsigned char * data; + unsigned int pointer_size; + unsigned long length; +{ + unsigned op; + int bytes_read; + unsigned long uvalue; + unsigned char * end = data + length; + + while (data < end) + { + op = * data ++; + + switch (op) + { + case DW_OP_addr: + printf ("DW_OP_addr: %lx", + (unsigned long) byte_get (data, pointer_size)); + data += pointer_size; + break; + case DW_OP_deref: + printf ("DW_OP_deref"); + break; + case DW_OP_const1u: + printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1)); + break; + case DW_OP_const1s: + printf ("DW_OP_const1s: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_const2u: + printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_const2s: + printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_const4u: + printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_const4s: + printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_const8u: + printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4), + (unsigned long) byte_get (data + 4, 4)); + data += 8; + break; + case DW_OP_const8s: + printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4), + (long) byte_get (data + 4, 4)); + data += 8; + break; + case DW_OP_constu: + printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_consts: + printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_dup: + printf ("DW_OP_dup"); + break; + case DW_OP_drop: + printf ("DW_OP_drop"); + break; + case DW_OP_over: + printf ("DW_OP_over"); + break; + case DW_OP_pick: + printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1)); + break; + case DW_OP_swap: + printf ("DW_OP_swap"); + break; + case DW_OP_rot: + printf ("DW_OP_rot"); + break; + case DW_OP_xderef: + printf ("DW_OP_xderef"); + break; + case DW_OP_abs: + printf ("DW_OP_abs"); + break; + case DW_OP_and: + printf ("DW_OP_and"); + break; + case DW_OP_div: + printf ("DW_OP_div"); + break; + case DW_OP_minus: + printf ("DW_OP_minus"); + break; + case DW_OP_mod: + printf ("DW_OP_mod"); + break; + case DW_OP_mul: + printf ("DW_OP_mul"); + break; + case DW_OP_neg: + printf ("DW_OP_neg"); + break; + case DW_OP_not: + printf ("DW_OP_not"); + break; + case DW_OP_or: + printf ("DW_OP_or"); + break; + case DW_OP_plus: + printf ("DW_OP_plus"); + break; + case DW_OP_plus_uconst: + printf ("DW_OP_plus_uconst: %lu", + read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_shl: + printf ("DW_OP_shl"); + break; + case DW_OP_shr: + printf ("DW_OP_shr"); + break; + case DW_OP_shra: + printf ("DW_OP_shra"); + break; + case DW_OP_xor: + printf ("DW_OP_xor"); + break; + case DW_OP_bra: + printf ("DW_OP_bra: %ld", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_eq: + printf ("DW_OP_eq"); + break; + case DW_OP_ge: + printf ("DW_OP_ge"); + break; + case DW_OP_gt: + printf ("DW_OP_gt"); + break; + case DW_OP_le: + printf ("DW_OP_le"); + break; + case DW_OP_lt: + printf ("DW_OP_lt"); + break; + case DW_OP_ne: + printf ("DW_OP_ne"); + break; + case DW_OP_skip: + printf ("DW_OP_skip: %ld", (long) byte_get (data, 2)); + data += 2; + break; + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + printf ("DW_OP_lit%d", op - DW_OP_lit0); + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + printf ("DW_OP_reg%d", op - DW_OP_reg0); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0, + read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + + case DW_OP_regx: + printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_fbreg: + printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_bregx: + uvalue = read_leb128 (data, &bytes_read, 0); + data += bytes_read; + printf ("DW_OP_bregx: %lu %ld", uvalue, + read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_piece: + printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_deref_size: + printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_xderef_size: + printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_nop: + printf ("DW_OP_nop"); + break; + + /* DWARF 2.1 extensions. */ + case DW_OP_push_object_address: + printf ("DW_OP_push_object_address"); + break; + case DW_OP_call2: + printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_call4: + printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_calli: + printf ("DW_OP_calli"); + break; + + default: + if (op >= DW_OP_lo_user + && op <= DW_OP_hi_user) + printf (_("(User defined location op)")); + else + printf (_("(Unknown location op)")); + /* No way to tell where the next op is, so just bail. */ + return; + } + + /* Separate the ops. */ + printf ("; "); + } +} + +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 < nisse_header.e_shnum; + i ++, sec ++) + if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0) + break; + + if (i == nisse_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 < nisse_header.e_shnum; + i ++, sec ++) + if (strcmp (SECTION_NAME (sec), ".debug_str") == 0) + break; + + if (i == nisse_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 _(""); + + if (offset > debug_str_size) + return _(""); + + 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; +} + + +static unsigned char * +read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) + unsigned long attribute; + unsigned long form; + unsigned char * data; + unsigned long cu_offset; + unsigned long pointer_size; +{ + unsigned long uvalue = 0; + unsigned char * block_start = NULL; + int bytes_read; + + switch (form) + { + default: + break; + + case DW_FORM_ref_addr: + case DW_FORM_addr: + uvalue = byte_get (data, pointer_size); + data += pointer_size; + break; + + case DW_FORM_strp: + uvalue = byte_get (data, /* offset_size */ 4); + data += /* offset_size */ 4; + break; + + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: + uvalue = byte_get (data ++, 1); + break; + + case DW_FORM_ref2: + case DW_FORM_data2: + uvalue = byte_get (data, 2); + data += 2; + break; + + case DW_FORM_ref4: + case DW_FORM_data4: + uvalue = byte_get (data, 4); + data += 4; + break; + + case DW_FORM_sdata: + uvalue = read_leb128 (data, & bytes_read, 1); + data += bytes_read; + break; + + case DW_FORM_ref_udata: + case DW_FORM_udata: + uvalue = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + break; + + case DW_FORM_indirect: + form = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (" %s", get_FORM_name (form)); + return read_and_display_attr_value (attribute, form, data, cu_offset, + pointer_size); + } + + switch (form) + { + case DW_FORM_ref_addr: + printf (" <#%lx>", uvalue); + break; + + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref_udata: + printf (" <%lx>", uvalue + cu_offset); + break; + + case DW_FORM_addr: + printf (" %#lx", uvalue); + + case DW_FORM_flag: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_sdata: + case DW_FORM_udata: + printf (" %ld", uvalue); + break; + + case DW_FORM_ref8: + case DW_FORM_data8: + uvalue = byte_get (data, 4); + printf (" %lx", uvalue); + printf (" %lx", (unsigned long) byte_get (data + 4, 4)); + data += 8; + break; + + case DW_FORM_string: + printf (" %s", data); + data += strlen ((char *) data) + 1; + break; + + case DW_FORM_block: + uvalue = read_leb128 (data, & bytes_read, 0); + block_start = data + bytes_read; + data = display_block (block_start, uvalue); + break; + + case DW_FORM_block1: + uvalue = byte_get (data, 1); + block_start = data + 1; + data = display_block (block_start, uvalue); + break; + + case DW_FORM_block2: + uvalue = byte_get (data, 2); + block_start = data + 2; + data = display_block (block_start, uvalue); + break; + + case DW_FORM_block4: + uvalue = byte_get (data, 4); + block_start = data + 4; + data = display_block (block_start, uvalue); + break; + + case DW_FORM_strp: + printf (_(" (indirect string, offset: 0x%lx): "), uvalue); + printf (fetch_indirect_string (uvalue)); + break; + + case DW_FORM_indirect: + /* Handled above. */ + break; + + default: + warn (_("Unrecognized form: %d\n"), form); + break; + } + + /* For some attributes we can display futher information. */ + + printf ("\t"); + + switch (attribute) + { + case DW_AT_inline: + switch (uvalue) + { + case DW_INL_not_inlined: printf (_("(not inlined)")); break; + case DW_INL_inlined: printf (_("(inlined)")); break; + case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break; + case DW_INL_declared_inlined: printf (_("(declared as inline and inlined)")); break; + default: printf (_(" (Unknown inline attribute value: %lx)"), uvalue); break; + } + break; + + case DW_AT_language: + switch (uvalue) + { + case DW_LANG_C: printf ("(non-ANSI C)"); break; + case DW_LANG_C89: printf ("(ANSI C)"); break; + case DW_LANG_C_plus_plus: printf ("(C++)"); break; + case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; + case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; + case DW_LANG_Modula2: printf ("(Modula 2)"); break; + case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_Ada83: printf ("(Ada)"); break; + case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; + case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; + /* DWARF 2.1 values. */ + case DW_LANG_C99: printf ("(ANSI C99)"); break; + case DW_LANG_Ada95: printf ("(ADA 95)"); break; + case DW_LANG_Fortran95: printf ("(Fortran 95)"); break; + /* MIPS extension. */ + case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; + default: printf ("(Unknown: %lx)", uvalue); break; + } + break; + + case DW_AT_encoding: + switch (uvalue) + { + case DW_ATE_void: printf ("(void)"); break; + case DW_ATE_address: printf ("(machine address)"); break; + case DW_ATE_boolean: printf ("(boolean)"); break; + case DW_ATE_complex_float: printf ("(complex float)"); break; + case DW_ATE_float: printf ("(float)"); break; + case DW_ATE_signed: printf ("(signed)"); break; + case DW_ATE_signed_char: printf ("(signed char)"); break; + case DW_ATE_unsigned: printf ("(unsigned)"); break; + case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; + /* DWARF 2.1 value. */ + case DW_ATE_imaginary_float: printf ("(imaginary float)"); break; + default: + if (uvalue >= DW_ATE_lo_user + && uvalue <= DW_ATE_hi_user) + printf ("(user defined type)"); + else + printf ("(unknown type)"); + break; + } + break; + + case DW_AT_accessibility: + switch (uvalue) + { + case DW_ACCESS_public: printf ("(public)"); break; + case DW_ACCESS_protected: printf ("(protected)"); break; + case DW_ACCESS_private: printf ("(private)"); break; + default: printf ("(unknown accessibility)"); break; + } + break; + + case DW_AT_visibility: + switch (uvalue) + { + case DW_VIS_local: printf ("(local)"); break; + case DW_VIS_exported: printf ("(exported)"); break; + case DW_VIS_qualified: printf ("(qualified)"); break; + default: printf ("(unknown visibility)"); break; + } + break; + + case DW_AT_virtuality: + switch (uvalue) + { + case DW_VIRTUALITY_none: printf ("(none)"); break; + case DW_VIRTUALITY_virtual: printf ("(virtual)"); break; + case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break; + default: printf ("(unknown virtuality)"); break; + } + break; + + case DW_AT_identifier_case: + switch (uvalue) + { + case DW_ID_case_sensitive: printf ("(case_sensitive)"); break; + case DW_ID_up_case: printf ("(up_case)"); break; + case DW_ID_down_case: printf ("(down_case)"); break; + case DW_ID_case_insensitive: printf ("(case_insensitive)"); break; + default: printf ("(unknown case)"); break; + } + break; + + case DW_AT_calling_convention: + switch (uvalue) + { + case DW_CC_normal: printf ("(normal)"); break; + case DW_CC_program: printf ("(program)"); break; + case DW_CC_nocall: printf ("(nocall)"); break; + default: + if (uvalue >= DW_CC_lo_user + && uvalue <= DW_CC_hi_user) + printf ("(user defined)"); + else + printf ("(unknown convention)"); + } + break; + + case DW_AT_ordering: + switch (uvalue) + { + case -1: printf ("(undefined)"); break; + case 0: printf ("(row major)"); break; + case 1: printf ("(column major)"); break; + } + break; + + case DW_AT_frame_base: + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_stride: + case DW_AT_upper_bound: + case DW_AT_lower_bound: + if (block_start) + { + printf ("("); + decode_location_expression (block_start, pointer_size, uvalue); + printf (")"); + } + else if (form == DW_FORM_data4) + { + printf ("("); + printf ("location list"); + printf (")"); + } + break; + + default: + break; + } + + return data; +} + +static unsigned char * +read_and_display_attr (attribute, form, data, cu_offset, pointer_size) + unsigned long attribute; + unsigned long form; + unsigned char * data; + unsigned long cu_offset; + unsigned long pointer_size; +{ + printf (" %-18s:", get_AT_name (attribute)); + data = read_and_display_attr_value (attribute, form, data, cu_offset, + pointer_size); + printf ("\n"); + return data; +} + +static int +display_debug_info (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + unsigned char * end = start + section->sh_size; + unsigned char * section_begin = start; + + printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + + load_debug_str (file); + load_debug_loc (file); + + while (start < end) + { + DWARF2_External_CompUnit * external; + DWARF2_Internal_CompUnit compunit; + Elf32_Internal_Shdr * relsec; + unsigned char * tags; + unsigned int i; + int level; + unsigned long cu_offset; + + external = (DWARF2_External_CompUnit *) start; + + compunit.cu_length = BYTE_GET (external->cu_length); + compunit.cu_version = BYTE_GET (external->cu_version); + compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset); + compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size); + + if (compunit.cu_length == 0xffffffff) + { + warn (_("64-bit DWARF debug info is not supported yet.\n")); + break; + } + + /* Check for RELA relocations in the abbrev_offset address, and + apply them. */ + for (relsec = section_headers; + relsec < section_headers + nisse_header.e_shnum; + ++relsec) + { + unsigned long nrelas; + Elf_Internal_Rela *rela, *rp; + Elf32_Internal_Shdr *symsec; + Elf_Internal_Sym *symtab; + Elf_Internal_Sym *sym; + + if (relsec->sh_type != SHT_RELA + || SECTION_HEADER (relsec->sh_info) != section + || relsec->sh_size == 0) + continue; + + if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, + & rela, & nrelas)) + return 0; + + symsec = SECTION_HEADER (relsec->sh_link); + symtab = GET_ELF_SYMBOLS (file, symsec); + + for (rp = rela; rp < rela + nrelas; ++rp) + { + if (rp->r_offset + != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset + - section_begin)) + continue; + + if (is_32bit_elf) + { + sym = symtab + ELF32_R_SYM (rp->r_info); + + if (ELF32_R_SYM (rp->r_info) != 0 + && ELF32_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u\n"), + ELF32_ST_TYPE (sym->st_info)); + continue; + } + } + else + { + sym = symtab + ELF64_R_SYM (rp->r_info); + + if (ELF64_R_SYM (rp->r_info) != 0 + && ELF64_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u\n"), + ELF64_ST_TYPE (sym->st_info)); + continue; + } + } + + compunit.cu_abbrev_offset = rp->r_addend; + break; + } + + free (rela); + break; + } + + tags = start + sizeof (* external); + cu_offset = start - section_begin; + start += compunit.cu_length + sizeof (external->cu_length); + + printf (_(" Compilation Unit @ %lx:\n"), cu_offset); + printf (_(" Length: %ld\n"), compunit.cu_length); + printf (_(" Version: %d\n"), compunit.cu_version); + printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); + printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); + + if (compunit.cu_version != 2) + { + warn (_("Only version 2 DWARF debug information is currently supported.\n")); + continue; + } + + free_abbrevs (); + + /* Read in the abbrevs used by this compilation unit. */ + + { + Elf32_Internal_Shdr * sec; + unsigned char * begin; + + /* Locate the .debug_abbrev section and process it. */ + for (i = 0, sec = section_headers; + i < nisse_header.e_shnum; + i ++, sec ++) + if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0) + break; + + if (i == nisse_header.e_shnum || sec->sh_size == 0) + { + warn (_("Unable to locate .debug_abbrev section!\n")); + return 0; + } + + begin = ((unsigned char *) + get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_abbrev section data"))); + if (!begin) + return 0; + + process_abbrev_section (begin + compunit.cu_abbrev_offset, + begin + sec->sh_size); + + free (begin); + } + + level = 0; + while (tags < start) + { + int bytes_read; + unsigned long abbrev_number; + abbrev_entry * entry; + abbrev_attr * attr; + + abbrev_number = read_leb128 (tags, & bytes_read, 0); + tags += bytes_read; + + /* A null DIE marks the end of a list of children. */ + if (abbrev_number == 0) + { + --level; + continue; + } + + /* Scan through the abbreviation list until we reach the + correct entry. */ + for (entry = first_abbrev; + entry && entry->entry != abbrev_number; + entry = entry->next) + continue; + + if (entry == NULL) + { + warn (_("Unable to locate entry %lu in the abbreviation table\n"), + abbrev_number); + return 0; + } + + printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"), + level, + (unsigned long) (tags - section_begin - bytes_read), + abbrev_number, + get_TAG_name (entry->tag)); + + for (attr = entry->first_attr; attr; attr = attr->next) + tags = read_and_display_attr (attr->attribute, + attr->form, + tags, cu_offset, + compunit.cu_pointer_size); + + if (entry->children) + ++level; + } + } + + free_debug_str (); + free_debug_loc (); + + printf ("\n"); + + return 1; +} + +static int +display_debug_aranges (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + unsigned char * end = start + section->sh_size; + + printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + DWARF2_External_ARange * external; + DWARF2_Internal_ARange arange; + unsigned char * ranges; + unsigned long length; + unsigned long address; + int excess; + + external = (DWARF2_External_ARange *) start; + + arange.ar_length = BYTE_GET (external->ar_length); + arange.ar_version = BYTE_GET (external->ar_version); + arange.ar_info_offset = BYTE_GET (external->ar_info_offset); + arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size); + arange.ar_segment_size = BYTE_GET (external->ar_segment_size); + + if (arange.ar_length == 0xffffffff) + { + warn (_("64-bit DWARF aranges are not supported yet.\n")); + break; + } + + if (arange.ar_version != 2) + { + warn (_("Only DWARF 2 aranges are currently supported.\n")); + break; + } + + printf (_(" Length: %ld\n"), arange.ar_length); + printf (_(" Version: %d\n"), arange.ar_version); + printf (_(" Offset into .debug_info: %lx\n"), arange.ar_info_offset); + printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size); + printf (_(" Segment Size: %d\n"), arange.ar_segment_size); + + printf (_("\n Address Length\n")); + + ranges = start + sizeof (* external); + + /* Must pad to an alignment boundary that is twice the pointer size. */ + excess = sizeof (* external) % (2 * arange.ar_pointer_size); + if (excess) + ranges += (2 * arange.ar_pointer_size) - excess; + + for (;;) + { + address = byte_get (ranges, arange.ar_pointer_size); + + ranges += arange.ar_pointer_size; + + length = byte_get (ranges, arange.ar_pointer_size); + + ranges += arange.ar_pointer_size; + + /* A pair of zeros marks the end of the list. */ + if (address == 0 && length == 0) + break; + + printf (" %8.8lx %lu\n", address, length); + } + + start += arange.ar_length + sizeof (external->ar_length); + } + + printf ("\n"); + + return 1; +} + +typedef struct Frame_Chunk +{ + struct Frame_Chunk * next; + unsigned char * chunk_start; + int ncols; + /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */ + short int * col_type; + int * col_offset; + char * augmentation; + unsigned int code_factor; + int data_factor; + unsigned long pc_begin; + unsigned long pc_range; + int cfa_reg; + int cfa_offset; + int ra; + unsigned char fde_encoding; +} +Frame_Chunk; + +/* A marker for a col_type that means this column was never referenced + in the frame info. */ +#define DW_CFA_unreferenced (-1) + +static void frame_need_space PARAMS ((Frame_Chunk *, int)); +static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *)); +static int size_of_encoded_value PARAMS ((int)); + +static void +frame_need_space (fc, reg) + Frame_Chunk * fc; + int reg; +{ + int prev = fc->ncols; + + if (reg < fc->ncols) + return; + + fc->ncols = reg + 1; + fc->col_type = (short int *) xrealloc (fc->col_type, + fc->ncols * sizeof (short int)); + fc->col_offset = (int *) xrealloc (fc->col_offset, + fc->ncols * sizeof (int)); + + while (prev < fc->ncols) + { + fc->col_type[prev] = DW_CFA_unreferenced; + fc->col_offset[prev] = 0; + prev++; + } +} + +static void +frame_display_row (fc, need_col_headers, max_regs) + Frame_Chunk * fc; + int * need_col_headers; + int * max_regs; +{ + int r; + char tmp[100]; + + if (* max_regs < fc->ncols) + * max_regs = fc->ncols; + + if (* need_col_headers) + { + * need_col_headers = 0; + + printf (" LOC CFA "); + + for (r = 0; r < * max_regs; r++) + if (fc->col_type[r] != DW_CFA_unreferenced) + { + if (r == fc->ra) + printf ("ra "); + else + printf ("r%-4d", r); + } + + printf ("\n"); + } + + printf ("%08lx ", fc->pc_begin); + sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset); + printf ("%-8s ", tmp); + + for (r = 0; r < fc->ncols; r++) + { + if (fc->col_type[r] != DW_CFA_unreferenced) + { + switch (fc->col_type[r]) + { + case DW_CFA_undefined: + strcpy (tmp, "u"); + break; + case DW_CFA_same_value: + strcpy (tmp, "s"); + break; + case DW_CFA_offset: + sprintf (tmp, "c%+d", fc->col_offset[r]); + break; + case DW_CFA_register: + sprintf (tmp, "r%d", fc->col_offset[r]); + break; + default: + strcpy (tmp, "n/a"); + break; + } + printf ("%-5s", tmp); + } + } + printf ("\n"); +} + +static int +size_of_encoded_value (encoding) + int encoding; +{ + switch (encoding & 0x7) + { + default: /* ??? */ + case 0: return is_32bit_elf ? 4 : 8; + case 2: return 2; + case 3: return 4; + case 4: return 8; + } +} + +#define GET(N) byte_get (start, N); start += N +#define LEB() read_leb128 (start, & length_return, 0); start += length_return +#define SLEB() read_leb128 (start, & length_return, 1); start += length_return + +static int +display_debug_frames (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + unsigned char * end = start + section->sh_size; + unsigned char * section_start = start; + Frame_Chunk * chunks = 0; + Frame_Chunk * remembered_state = 0; + Frame_Chunk * rs; + int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0); + int length_return; + int max_regs = 0; + int addr_size = is_32bit_elf ? 4 : 8; + + printf (_("The section %s contains:\n"), SECTION_NAME (section)); + + while (start < end) + { + unsigned char * saved_start; + unsigned char * block_end; + unsigned long length; + unsigned long cie_id; + Frame_Chunk * fc; + Frame_Chunk * cie; + int need_col_headers = 1; + unsigned char * augmentation_data = NULL; + unsigned long augmentation_data_len = 0; + int encoded_ptr_size = addr_size; + + saved_start = start; + length = byte_get (start, 4); start += 4; + + if (length == 0) + return 1; + + if (length == 0xffffffff) + { + warn (_("64-bit DWARF format frames are not supported yet.\n")); + break; + } + + block_end = saved_start + length + 4; + cie_id = byte_get (start, 4); start += 4; + + if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) + { + int version; + + fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); + memset (fc, 0, sizeof (Frame_Chunk)); + + fc->next = chunks; + chunks = fc; + fc->chunk_start = saved_start; + fc->ncols = 0; + fc->col_type = (short int *) xmalloc (sizeof (short int)); + fc->col_offset = (int *) xmalloc (sizeof (int)); + frame_need_space (fc, max_regs-1); + + version = *start++; + + fc->augmentation = start; + start = strchr (start, '\0') + 1; + + if (fc->augmentation[0] == 'z') + { + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; + } + else if (strcmp (fc->augmentation, "eh") == 0) + { + start += addr_size; + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + } + else + { + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + } + cie = fc; + + if (do_debug_frames_interp) + printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n", + (unsigned long)(saved_start - section_start), length, cie_id, + fc->augmentation, fc->code_factor, fc->data_factor, + fc->ra); + else + { + printf ("\n%08lx %08lx %08lx CIE\n", + (unsigned long)(saved_start - section_start), length, cie_id); + printf (" Version: %d\n", version); + printf (" Augmentation: \"%s\"\n", fc->augmentation); + printf (" Code alignment factor: %u\n", fc->code_factor); + printf (" Data alignment factor: %d\n", fc->data_factor); + printf (" Return address column: %d\n", fc->ra); + + if (augmentation_data_len) + { + unsigned long i; + printf (" Augmentation data: "); + for (i = 0; i < augmentation_data_len; ++i) + printf (" %02x", augmentation_data[i]); + putchar ('\n'); + } + putchar ('\n'); + } + + if (augmentation_data_len) + { + unsigned char *p, *q; + p = fc->augmentation + 1; + q = augmentation_data; + + while (1) + { + if (*p == 'L') + q++; + else if (*p == 'P') + q += 1 + size_of_encoded_value (*q); + else if (*p == 'R') + fc->fde_encoding = *q++; + else + break; + p++; + } + + if (fc->fde_encoding) + encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + } + + frame_need_space (fc, fc->ra); + } + else + { + unsigned char * look_for; + static Frame_Chunk fde_fc; + + fc = & fde_fc; + memset (fc, 0, sizeof (Frame_Chunk)); + + look_for = is_eh ? start - 4 - cie_id : section_start + cie_id; + + for (cie = chunks; cie ; cie = cie->next) + if (cie->chunk_start == look_for) + break; + + if (!cie) + { + warn ("Invalid CIE pointer %08lx in FDE at %08lx\n", + cie_id, saved_start); + start = block_end; + fc->ncols = 0; + fc->col_type = (short int *) xmalloc (sizeof (short int)); + fc->col_offset = (int *) xmalloc (sizeof (int)); + frame_need_space (fc, max_regs - 1); + cie = fc; + fc->augmentation = ""; + fc->fde_encoding = 0; + } + else + { + fc->ncols = cie->ncols; + fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int)); + fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int)); + memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int)); + memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int)); + fc->augmentation = cie->augmentation; + fc->code_factor = cie->code_factor; + fc->data_factor = cie->data_factor; + fc->cfa_reg = cie->cfa_reg; + fc->cfa_offset = cie->cfa_offset; + fc->ra = cie->ra; + frame_need_space (fc, max_regs-1); + fc->fde_encoding = cie->fde_encoding; + } + + if (fc->fde_encoding) + encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + + fc->pc_begin = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + fc->pc_range = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + + if (cie->augmentation[0] == 'z') + { + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; + } + + printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n", + (unsigned long)(saved_start - section_start), length, cie_id, + (unsigned long)(cie->chunk_start - section_start), + fc->pc_begin, fc->pc_begin + fc->pc_range); + if (! do_debug_frames_interp && augmentation_data_len) + { + unsigned long i; + printf (" Augmentation data: "); + for (i = 0; i < augmentation_data_len; ++i) + printf (" %02x", augmentation_data[i]); + putchar ('\n'); + putchar ('\n'); + } + } + + /* At this point, fc is the current chunk, cie (if any) is set, and we're + about to interpret instructions for the chunk. */ + + if (do_debug_frames_interp) + { + /* Start by making a pass over the chunk, allocating storage + and taking note of what registers are used. */ + unsigned char * tmp = start; + + while (start < block_end) + { + unsigned op, opa; + unsigned long reg; + + op = * start ++; + opa = op & 0x3f; + if (op & 0xc0) + op &= 0xc0; + + /* Warning: if you add any more cases to this switch, be + sure to add them to the corresponding switch below. */ + switch (op) + { + case DW_CFA_advance_loc: + break; + case DW_CFA_offset: + LEB (); + frame_need_space (fc, opa); + fc->col_type[opa] = DW_CFA_undefined; + break; + case DW_CFA_restore: + frame_need_space (fc, opa); + fc->col_type[opa] = DW_CFA_undefined; + break; + case DW_CFA_set_loc: + start += encoded_ptr_size; + break; + case DW_CFA_advance_loc1: + start += 1; + break; + case DW_CFA_advance_loc2: + start += 2; + break; + case DW_CFA_advance_loc4: + start += 4; + break; + case DW_CFA_offset_extended: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_restore_extended: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_undefined: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_same_value: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_register: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_def_cfa: + LEB (); LEB (); + break; + case DW_CFA_def_cfa_register: + LEB (); + break; + case DW_CFA_def_cfa_offset: + LEB (); + break; + case DW_CFA_offset_extended_sf: + reg = LEB (); SLEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_def_cfa_sf: + LEB (); SLEB (); + break; + case DW_CFA_def_cfa_offset_sf: + SLEB (); + break; + case DW_CFA_GNU_args_size: + LEB (); + break; + case DW_CFA_GNU_negative_offset_extended: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + + default: + break; + } + } + start = tmp; + } + + /* Now we know what registers are used, make a second pass over + the chunk, this time actually printing out the info. */ + + while (start < block_end) + { + unsigned op, opa; + unsigned long ul, reg, roffs; + long l, ofs; + bfd_vma vma; + + op = * start ++; + opa = op & 0x3f; + if (op & 0xc0) + op &= 0xc0; + + /* Warning: if you add any more cases to this switch, be + sure to add them to the corresponding switch above. */ + switch (op) + { + case DW_CFA_advance_loc: + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc: %d to %08lx\n", + opa * fc->code_factor, + fc->pc_begin + opa * fc->code_factor); + fc->pc_begin += opa * fc->code_factor; + break; + + case DW_CFA_offset: + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_offset: r%d at cfa%+ld\n", + opa, roffs * fc->data_factor); + fc->col_type[opa] = DW_CFA_offset; + fc->col_offset[opa] = roffs * fc->data_factor; + break; + + case DW_CFA_restore: + if (! do_debug_frames_interp) + printf (" DW_CFA_restore: r%d\n", opa); + fc->col_type[opa] = cie->col_type[opa]; + fc->col_offset[opa] = cie->col_offset[opa]; + break; + + case DW_CFA_set_loc: + vma = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_set_loc: %08lx\n", (unsigned long)vma); + fc->pc_begin = vma; + break; + + case DW_CFA_advance_loc1: + ofs = byte_get (start, 1); start += 1; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc1: %ld to %08lx\n", + ofs * fc->code_factor, + fc->pc_begin + ofs * fc->code_factor); + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_advance_loc2: + ofs = byte_get (start, 2); start += 2; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc2: %ld to %08lx\n", + ofs * fc->code_factor, + fc->pc_begin + ofs * fc->code_factor); + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_advance_loc4: + ofs = byte_get (start, 4); start += 4; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc4: %ld to %08lx\n", + ofs * fc->code_factor, + fc->pc_begin + ofs * fc->code_factor); + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_offset_extended: + reg = LEB (); + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_offset_extended: r%ld at cfa%+ld\n", + reg, roffs * fc->data_factor); + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = roffs * fc->data_factor; + break; + + case DW_CFA_restore_extended: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_restore_extended: r%ld\n", reg); + fc->col_type[reg] = cie->col_type[reg]; + fc->col_offset[reg] = cie->col_offset[reg]; + break; + + case DW_CFA_undefined: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_undefined: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_undefined; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_same_value: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_same_value: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_same_value; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_register: + reg = LEB (); + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_register: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_register; + fc->col_offset[reg] = roffs; + break; + + case DW_CFA_remember_state: + if (! do_debug_frames_interp) + printf (" DW_CFA_remember_state\n"); + rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); + rs->ncols = fc->ncols; + rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int)); + rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int)); + memcpy (rs->col_type, fc->col_type, rs->ncols); + memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int)); + rs->next = remembered_state; + remembered_state = rs; + break; + + case DW_CFA_restore_state: + if (! do_debug_frames_interp) + printf (" DW_CFA_restore_state\n"); + rs = remembered_state; + remembered_state = rs->next; + frame_need_space (fc, rs->ncols-1); + memcpy (fc->col_type, rs->col_type, rs->ncols); + memcpy (fc->col_offset, rs->col_offset, rs->ncols * sizeof (int)); + free (rs->col_type); + free (rs->col_offset); + free (rs); + break; + + case DW_CFA_def_cfa: + fc->cfa_reg = LEB (); + fc->cfa_offset = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa: r%d ofs %d\n", + fc->cfa_reg, fc->cfa_offset); + break; + + case DW_CFA_def_cfa_register: + fc->cfa_reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg); + break; + + case DW_CFA_def_cfa_offset: + fc->cfa_offset = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset); + break; + + case DW_CFA_nop: + if (! do_debug_frames_interp) + printf (" DW_CFA_nop\n"); + break; + + case DW_CFA_offset_extended_sf: + reg = LEB (); + l = SLEB (); + frame_need_space (fc, reg); + if (! do_debug_frames_interp) + printf (" DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n", + reg, l * fc->data_factor); + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = l * fc->data_factor; + break; + + case DW_CFA_def_cfa_sf: + fc->cfa_reg = LEB (); + fc->cfa_offset = SLEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_sf: r%d ofs %d\n", + fc->cfa_reg, fc->cfa_offset); + break; + + case DW_CFA_def_cfa_offset_sf: + fc->cfa_offset = SLEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset); + break; + + case DW_CFA_GNU_window_save: + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_window_save\n"); + break; + + case DW_CFA_GNU_args_size: + ul = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_args_size: %ld\n", ul); + break; + + case DW_CFA_GNU_negative_offset_extended: + reg = LEB (); + l = - LEB (); + frame_need_space (fc, reg); + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n", + reg, l * fc->data_factor); + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = l * fc->data_factor; + break; + + /* FIXME: How do we handle these? */ + case DW_CFA_def_cfa_expression: + fprintf (stderr, "unsupported DW_CFA_def_cfa_expression\n"); + start = block_end; + break; + + case DW_CFA_expression: + fprintf (stderr, "unsupported DW_CFA_expression\n"); + start = block_end; + break; + + default: + fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op); + start = block_end; + } + } + + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + + start = block_end; + } + + printf ("\n"); + + return 1; +} + +#undef GET +#undef LEB +#undef SLEB + +static int +display_debug_not_supported (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start ATTRIBUTE_UNUSED; + FILE * file ATTRIBUTE_UNUSED; +{ + printf (_("Displaying the debug contents of section %s is not yet supported.\n"), + SECTION_NAME (section)); + + return 1; +} + +/* Pre-scan the .debug_info section to record the size of address. + When dumping the .debug_line, we use that size information, assuming + that all compilation units have the same address size. */ +static int +prescan_debug_info (section, start, file) + Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + DWARF2_External_CompUnit * external; + + external = (DWARF2_External_CompUnit *) start; + + debug_line_pointer_size = BYTE_GET (external->cu_pointer_size); + return 0; +} + + /* A structure containing the name of a debug section and a pointer + to a function that can decode it. The third field is a prescan + function to be run over the section before displaying any of the + sections. */ +struct +{ + const char * const name; + int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); + int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +} +debug_displays[] = +{ + { ".debug_abbrev", display_debug_abbrev, NULL }, + { ".debug_aranges", display_debug_aranges, NULL }, + { ".debug_frame", display_debug_frames, NULL }, + { ".debug_info", display_debug_info, prescan_debug_info }, + { ".debug_line", display_debug_lines, NULL }, + { ".debug_pubnames", display_debug_pubnames, NULL }, + { ".eh_frame", display_debug_frames, NULL }, + { ".debug_macinfo", display_debug_macinfo, NULL }, + { ".debug_str", display_debug_str, NULL }, + { ".debug_loc", display_debug_loc, NULL }, + { ".debug_pubtypes", display_debug_not_supported, NULL }, + { ".debug_ranges", display_debug_not_supported, NULL }, + { ".debug_static_func", display_debug_not_supported, NULL }, + { ".debug_static_vars", display_debug_not_supported, NULL }, + { ".debug_types", display_debug_not_supported, NULL }, + { ".debug_weaknames", display_debug_not_supported, NULL } +}; + +static int +display_debug_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + char * name = SECTION_NAME (section); + bfd_size_type length; + unsigned char * start; + int i; + + length = section->sh_size; + if (length == 0) + { + printf (_("\nSection '%s' has no debugging data.\n"), name); + return 0; + } + + start = (unsigned char *) get_data (NULL, file, section->sh_offset, length, + _("debug section data")); + if (!start) + return 0; + + /* See if we know how to display the contents of this section. */ + if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0) + name = ".debug_info"; + + for (i = NUM_ELEM (debug_displays); i--;) + if (strcmp (debug_displays[i].name, name) == 0) + { + debug_displays[i].display (section, start, file); + break; + } + + if (i == -1) + printf (_("Unrecognized debug section: %s\n"), name); + + free (start); + + /* If we loaded in the abbrev section at some point, + we must release it here. */ + free_abbrevs (); + + return 1; +} + +static int +process_section_contents (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + unsigned int i; + + if (! do_dump) + return 1; + + /* Pre-scan the debug sections to find some debug information not + present in some of them. For the .debug_line, we must find out the + size of address (specified in .debug_info and .debug_aranges). */ + for (i = 0, section = section_headers; + i < nisse_header.e_shnum && i < num_dump_sects; + i ++, section ++) + { + char * name = SECTION_NAME (section); + int j; + + if (section->sh_size == 0) + continue; + + /* See if there is some pre-scan operation for this section. */ + for (j = NUM_ELEM (debug_displays); j--;) + if (strcmp (debug_displays[j].name, name) == 0) + { + if (debug_displays[j].prescan != NULL) + { + bfd_size_type length; + unsigned char * start; + + length = section->sh_size; + start = ((unsigned char *) + get_data (NULL, file, section->sh_offset, length, + _("debug section data"))); + if (!start) + return 0; + + debug_displays[j].prescan (section, start, file); + free (start); + } + + break; + } + } + + for (i = 0, section = section_headers; + i < nisse_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 (section, file); + + if (dump_sects[i] & DEBUG_DUMP) + display_debug_section (section, file); + } + + if (i < num_dump_sects) + warn (_("Some sections were not dumped because they do not exist!\n")); + + return 1; +} + +static void +process_mips_fpe_exception (mask) + 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); +} + +static int +process_mips_specific (file) + FILE * file; +{ + Elf_Internal_Dyn * entry; + size_t liblist_offset = 0; + size_t liblistno = 0; + size_t conflictsno = 0; + size_t options_offset = 0; + size_t conflicts_offset = 0; + + /* We have a lot of special sections. Thanks SGI! */ + if (dynamic_segment == NULL) + /* No information available. */ + return 0; + + for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry) + switch (entry->d_tag) + { + case DT_MIPS_LIBLIST: + liblist_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_LIBLISTNO: + liblistno = entry->d_un.d_val; + break; + case DT_MIPS_OPTIONS: + options_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_CONFLICT: + conflicts_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_CONFLICTNO: + conflictsno = entry->d_un.d_val; + break; + default: + break; + } + + if (liblist_offset != 0 && liblistno != 0 && do_dynamic) + { + Elf32_External_Lib * elib; + size_t cnt; + + elib = ((Elf32_External_Lib *) + get_data (NULL, file, liblist_offset, + liblistno * sizeof (Elf32_External_Lib), + _("liblist"))); + if (elib) + { + printf ("\nSection '.liblist' contains %lu entries:\n", + (unsigned long) liblistno); + fputs (" Library Time Stamp Checksum Version Flags\n", + stdout); + + for (cnt = 0; cnt < liblistno; ++cnt) + { + Elf32_Lib liblist; + time_t time; + char timebuf[20]; + struct tm * tmp; + + liblist.l_name = BYTE_GET (elib[cnt].l_name); + time = BYTE_GET (elib[cnt].l_time_stamp); + liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); + liblist.l_version = BYTE_GET (elib[cnt].l_version); + liblist.l_flags = BYTE_GET (elib[cnt].l_flags); + + tmp = gmtime (&time); + sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + printf ("%3lu: ", (unsigned long) cnt); + print_symbol (20, dynamic_strings + liblist.l_name); + printf (" %s %#10lx %-7ld", timebuf, liblist.l_checksum, + liblist.l_version); + + if (liblist.l_flags == 0) + puts (" NONE"); + else + { + static const struct + { + const char * name; + int bit; + } + l_flags_vals[] = + { + { " EXACT_MATCH", LL_EXACT_MATCH }, + { " IGNORE_INT_VER", LL_IGNORE_INT_VER }, + { " REQUIRE_MINOR", LL_REQUIRE_MINOR }, + { " EXPORTS", LL_EXPORTS }, + { " DELAY_LOAD", LL_DELAY_LOAD }, + { " DELTA", LL_DELTA } + }; + int flags = liblist.l_flags; + size_t fcnt; + + for (fcnt = 0; + fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); + ++fcnt) + if ((flags & l_flags_vals[fcnt].bit) != 0) + { + fputs (l_flags_vals[fcnt].name, stdout); + flags ^= l_flags_vals[fcnt].bit; + } + if (flags != 0) + printf (" %#x", (unsigned int) flags); + + puts (""); + } + } + + free (elib); + } + } + + if (options_offset != 0) + { + Elf_External_Options * eopt; + Elf_Internal_Shdr * sect = section_headers; + Elf_Internal_Options * iopt; + Elf_Internal_Options * option; + size_t offset; + int cnt; + + /* Find the section header so that we get the size. */ + while (sect->sh_type != SHT_MIPS_OPTIONS) + ++ sect; + + eopt = (Elf_External_Options *) get_data (NULL, file, options_offset, + sect->sh_size, _("options")); + if (eopt) + { + iopt = ((Elf_Internal_Options *) + malloc ((sect->sh_size / sizeof (eopt)) * sizeof (* iopt))); + if (iopt == NULL) + { + error (_("Out of memory")); + return 0; + } + + offset = cnt = 0; + option = iopt; + + while (offset < sect->sh_size) + { + Elf_External_Options * eoption; + + eoption = (Elf_External_Options *) ((char *) eopt + offset); + + option->kind = BYTE_GET (eoption->kind); + option->size = BYTE_GET (eoption->size); + option->section = BYTE_GET (eoption->section); + option->info = BYTE_GET (eoption->info); + + offset += option->size; + + ++option; + ++cnt; + } + + printf (_("\nSection '%s' contains %d entries:\n"), + SECTION_NAME (sect), cnt); + + option = iopt; + + while (cnt-- > 0) + { + size_t len; + + switch (option->kind) + { + case ODK_NULL: + /* This shouldn't happen. */ + printf (" NULL %d %lx", option->section, option->info); + break; + case ODK_REGINFO: + printf (" REGINFO "); + if (nisse_header.e_machine == EM_MIPS) + { + /* 32bit form. */ + Elf32_External_RegInfo * ereg; + Elf32_RegInfo reginfo; + + ereg = (Elf32_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x%lx\n", + reginfo.ri_gprmask, + (unsigned long) reginfo.ri_gp_value); + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + else + { + /* 64 bit form. */ + Elf64_External_RegInfo * ereg; + Elf64_Internal_RegInfo reginfo; + + ereg = (Elf64_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET8 (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x", + reginfo.ri_gprmask); + printf_vma (reginfo.ri_gp_value); + printf ("\n"); + + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + ++option; + continue; + case ODK_EXCEPTIONS: + fputs (" EXCEPTIONS fpe_min(", stdout); + process_mips_fpe_exception (option->info & OEX_FPU_MIN); + fputs (") fpe_max(", stdout); + process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); + fputs (")", stdout); + + if (option->info & OEX_PAGE0) + fputs (" PAGE0", stdout); + if (option->info & OEX_SMM) + fputs (" SMM", stdout); + if (option->info & OEX_FPDBUG) + fputs (" FPDBUG", stdout); + if (option->info & OEX_DISMISS) + fputs (" DISMISS", stdout); + break; + case ODK_PAD: + fputs (" PAD ", stdout); + if (option->info & OPAD_PREFIX) + fputs (" PREFIX", stdout); + if (option->info & OPAD_POSTFIX) + fputs (" POSTFIX", stdout); + if (option->info & OPAD_SYMBOL) + fputs (" SYMBOL", stdout); + break; + case ODK_HWPATCH: + fputs (" HWPATCH ", stdout); + if (option->info & OHW_R4KEOP) + fputs (" R4KEOP", stdout); + if (option->info & OHW_R8KPFETCH) + fputs (" R8KPFETCH", stdout); + if (option->info & OHW_R5KEOP) + fputs (" R5KEOP", stdout); + if (option->info & OHW_R5KCVTL) + fputs (" R5KCVTL", stdout); + break; + case ODK_FILL: + fputs (" FILL ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_TAGS: + fputs (" TAGS ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_HWAND: + fputs (" HWAND ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_HWOR: + fputs (" HWOR ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_GP_GROUP: + printf (" GP_GROUP %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + case ODK_IDENT: + printf (" IDENT %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + default: + /* This shouldn't happen. */ + printf (" %3d ??? %d %lx", + option->kind, option->section, option->info); + break; + } + + len = sizeof (* eopt); + while (len < option->size) + if (((char *) option)[len] >= ' ' + && ((char *) option)[len] < 0x7f) + printf ("%c", ((char *) option)[len++]); + else + printf ("\\%03o", ((char *) option)[len++]); + + fputs ("\n", stdout); + ++option; + } + + free (eopt); + } + } + + if (conflicts_offset != 0 && conflictsno != 0) + { + Elf32_Conflict * iconf; + size_t cnt; + + if (dynamic_symbols == NULL) + { + error (_("conflict list found without a dynamic symbol table")); + return 0; + } + + iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (* iconf)); + if (iconf == NULL) + { + error (_("Out of memory")); + return 0; + } + + if (is_32bit_elf) + { + Elf32_External_Conflict * econf32; + + econf32 = ((Elf32_External_Conflict *) + get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (* econf32), + _("conflict"))); + if (!econf32) + return 0; + + for (cnt = 0; cnt < conflictsno; ++cnt) + iconf[cnt] = BYTE_GET (econf32[cnt]); + + free (econf32); + } + else + { + Elf64_External_Conflict * econf64; + + econf64 = ((Elf64_External_Conflict *) + get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (* econf64), + _("conflict"))); + if (!econf64) + return 0; + + for (cnt = 0; cnt < conflictsno; ++cnt) + iconf[cnt] = BYTE_GET (econf64[cnt]); + + free (econf64); + } + + printf (_("\nSection '.conflict' contains %ld entries:\n"), + (long) conflictsno); + puts (_(" Num: Index Value Name")); + + for (cnt = 0; cnt < conflictsno; ++cnt) + { + Elf_Internal_Sym * psym = & dynamic_symbols [iconf [cnt]]; + + printf ("%5lu: %8lu ", (unsigned long) cnt, iconf [cnt]); + print_vma (psym->st_value, FULL_HEX); + putchar (' '); + print_symbol (25, dynamic_strings + psym->st_name); + putchar ('\n'); + } + + free (iconf); + } + + return 1; +} + +static int +process_gnu_liblist (file) + FILE * file; +{ + Elf_Internal_Shdr * section, * string_sec; + Elf32_External_Lib * elib; + char * strtab; + size_t cnt; + unsigned i; + + if (! do_arch) + return 0; + + for (i = 0, section = section_headers; + i < nisse_header.e_shnum; + i++, section ++) + { + switch (section->sh_type) + { + case SHT_GNU_LIBLIST: + elib = ((Elf32_External_Lib *) + get_data (NULL, file, section->sh_offset, section->sh_size, + _("liblist"))); + + if (elib == NULL) + break; + string_sec = SECTION_HEADER (section->sh_link); + + strtab = (char *) get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, + _("liblist string table")); + + if (strtab == NULL + || section->sh_entsize != sizeof (Elf32_External_Lib)) + { + free (elib); + break; + } + + printf (_("\nLibrary list section '%s' contains %lu entries:\n"), + SECTION_NAME (section), + (long) (section->sh_size / sizeof (Elf32_External_Lib))); + + puts (" Library Time Stamp Checksum Version Flags"); + + for (cnt = 0; cnt < section->sh_size / sizeof (Elf32_External_Lib); + ++cnt) + { + Elf32_Lib liblist; + time_t time; + char timebuf[20]; + struct tm * tmp; + + liblist.l_name = BYTE_GET (elib[cnt].l_name); + time = BYTE_GET (elib[cnt].l_time_stamp); + liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); + liblist.l_version = BYTE_GET (elib[cnt].l_version); + liblist.l_flags = BYTE_GET (elib[cnt].l_flags); + + tmp = gmtime (&time); + sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + printf ("%3lu: ", (unsigned long) cnt); + if (do_wide) + printf ("%-20s", strtab + liblist.l_name); + else + printf ("%-20.20s", strtab + liblist.l_name); + printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum, + liblist.l_version, liblist.l_flags); + } + + free (elib); + } + } + + return 1; +} + +static const char * +get_note_type (e_type) + unsigned e_type; +{ + static char buff[64]; + + switch (e_type) + { + case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)"); + case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)"); + case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); + case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)"); + case NT_PRXFPREG: return _("NT_PRXFPREG (user_xfpregs structure)"); + case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)"); + case NT_FPREGS: return _("NT_FPREGS (floating point registers)"); + case NT_PSINFO: return _("NT_PSINFO (psinfo structure)"); + case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)"); + case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)"); + case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus structure)"); + default: + sprintf (buff, _("Unknown note type: (0x%08x)"), e_type); + return buff; + } +} + +static const char * +get_netbsd_elfcore_note_type (e_type) + unsigned e_type; +{ + static char buff[64]; + + if (e_type == NT_NETBSDCORE_PROCINFO) + { + /* NetBSD core "procinfo" structure. */ + return _("NetBSD procinfo structure"); + } + + /* As of Jan 2002 there are no other machine-independent notes + defined for NetBSD core files. If the note type is less + than the start of the machine-dependent note types, we don't + understand it. */ + + if (e_type < NT_NETBSDCORE_FIRSTMACH) + { + sprintf (buff, _("Unknown note type: (0x%08x)"), e_type); + return buff; + } + + switch (nisse_header.e_machine) + { + /* On the Alpha, SPARC (32-bit and 64-bit), PT_GETREGS == mach+0 + and PT_GETFPREGS == mach+2. */ + + case EM_OLD_ALPHA: + case EM_ALPHA: + case EM_SPARC: + case EM_SPARC32PLUS: + case EM_SPARCV9: + switch (e_type) + { + case NT_NETBSDCORE_FIRSTMACH+0: + return _("PT_GETREGS (reg structure)"); + case NT_NETBSDCORE_FIRSTMACH+2: + return _("PT_GETFPREGS (fpreg structure)"); + default: + break; + } + break; + + /* On all other arch's, PT_GETREGS == mach+1 and + PT_GETFPREGS == mach+3. */ + default: + switch (e_type) + { + case NT_NETBSDCORE_FIRSTMACH+1: + return _("PT_GETREGS (reg structure)"); + case NT_NETBSDCORE_FIRSTMACH+3: + return _("PT_GETFPREGS (fpreg structure)"); + default: + break; + } + } + + sprintf (buff, _("PT_FIRSTMACH+%d"), e_type - NT_NETBSDCORE_FIRSTMACH); + return buff; +} + +/* Note that by the ELF standard, the name field is already null byte + terminated, and namesz includes the terminating null byte. + I.E. the value of namesz for the name "FSF" is 4. + + If the value of namesz is zero, there is no name present. */ +static int +process_note (pnote) + Elf32_Internal_Note * pnote; +{ + const char *nt; + + if (pnote->namesz == 0) + { + /* If there is no note name, then use the default set of + note type strings. */ + nt = get_note_type (pnote->type); + } + else if (strncmp (pnote->namedata, "NetBSD-CORE", 11) == 0) + { + /* NetBSD-specific core file notes. */ + nt = get_netbsd_elfcore_note_type (pnote->type); + } + else + { + /* Don't recognize this note name; just use the default set of + note type strings. */ + nt = get_note_type (pnote->type); + } + + printf (" %s\t\t0x%08lx\t%s\n", + pnote->namesz ? pnote->namedata : "(NONE)", + pnote->descsz, nt); + return 1; +} + + +static int +process_corefile_note_segment (file, offset, length) + FILE * file; + bfd_vma offset; + bfd_vma length; +{ + Elf_External_Note * pnotes; + Elf_External_Note * external; + int res = 1; + + if (length <= 0) + return 0; + + pnotes = (Elf_External_Note *) get_data (NULL, file, offset, length, + _("notes")); + if (!pnotes) + return 0; + + external = pnotes; + + printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), + (unsigned long) offset, (unsigned long) length); + printf (_(" Owner\t\tData size\tDescription\n")); + + while (external < (Elf_External_Note *)((char *) pnotes + length)) + { + Elf_External_Note * next; + Elf32_Internal_Note inote; + char * temp = NULL; + + inote.type = BYTE_GET (external->type); + inote.namesz = BYTE_GET (external->namesz); + inote.namedata = external->name; + inote.descsz = BYTE_GET (external->descsz); + inote.descdata = inote.namedata + align_power (inote.namesz, 2); + inote.descpos = offset + (inote.descdata - (char *) pnotes); + + next = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2)); + + if (((char *) next) > (((char *) pnotes) + length)) + { + warn (_("corrupt note found at offset %x into core notes\n"), + ((char *) external) - ((char *) pnotes)); + warn (_(" type: %x, namesize: %08lx, descsize: %08lx\n"), + inote.type, inote.namesz, inote.descsz); + break; + } + + external = next; + + /* Verify that name is null terminated. It appears that at least + one version of Linux (RedHat 6.0) generates corefiles that don't + comply with the ELF spec by failing to include the null byte in + namesz. */ + if (inote.namedata[inote.namesz] != '\0') + { + temp = malloc (inote.namesz + 1); + + if (temp == NULL) + { + error (_("Out of memory\n")); + res = 0; + break; + } + + strncpy (temp, inote.namedata, inote.namesz); + temp[inote.namesz] = 0; + + /* warn (_("'%s' NOTE name not properly null terminated\n"), temp); */ + inote.namedata = temp; + } + + res &= process_note (& inote); + + if (temp != NULL) + { + free (temp); + temp = NULL; + } + } + + free (pnotes); + + return res; +} + +static int +process_corefile_note_segments (file) + FILE * file; +{ + Elf_Internal_Phdr * program_headers; + Elf_Internal_Phdr * segment; + unsigned int i; + int res = 1; + + program_headers = (Elf_Internal_Phdr *) malloc + (nisse_header.e_phnum * sizeof (Elf_Internal_Phdr)); + + if (program_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + if (is_32bit_elf) + i = get_32bit_program_headers (file, program_headers); + else + i = get_64bit_program_headers (file, program_headers); + + if (i == 0) + { + free (program_headers); + return 0; + } + + for (i = 0, segment = program_headers; + i < nisse_header.e_phnum; + i ++, segment ++) + { + if (segment->p_type == PT_NOTE) + res &= process_corefile_note_segment (file, + (bfd_vma) segment->p_offset, + (bfd_vma) segment->p_filesz); + } + + free (program_headers); + + return res; +} + +static int +process_corefile_contents (file) + FILE * file; +{ + /* If we have not been asked to display the notes then do nothing. */ + if (! do_notes) + return 1; + + /* If file is not a core file then exit. */ + if (nisse_header.e_type != ET_CORE) + return 1; + + /* No program headers means no NOTE segment. */ + if (nisse_header.e_phnum == 0) + { + printf (_("No note segments present in the core file.\n")); + return 1; + } + + return process_corefile_note_segments (file); +} + +static int +process_arch_specific (file) + FILE * file; +{ + if (! do_arch) + return 1; + + switch (nisse_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + return process_mips_specific (file); + break; + default: + break; + } + return 1; +} + +#endif + +static int +get_file_header (file) + FILE * file; +{ + struct _eisd * section; + nisse_header=malloc(sizeof(struct _eihd)); + /* Read in the identity array. */ + if (fread (nisse_header, 512, 1, file) != 1) + return 0; + + // byte_get = byte_get_little_endian; + + /* Determine how to read the rest of the header. */ + + /* For now we only support 32 bit and 64 bit ELF files. */ + is_32bit_elf = (nisse_header->eihd$l_majorid != EIHD$K_MAJORID); + + /* Read in the rest of the header. */ + if (is_32bit_elf) + { + struct _ihd * ehdr32; + struct _iha * active; + struct _isd * section; + struct _ihi * name; + struct _ihvn * vers; + struct _ihs * debug; + int i; + char * buffer = malloc(512*((struct _ihd*)nisse_header)->ihd$b_hdrblkcnt); + + ehdr32=malloc(512); + bcopy(nisse_header,ehdr32,512); + + active=(unsigned long)ehdr32+ehdr32->ihd$w_activoff; + // section=(unsigned long)ehdr32+ehdr32->ihd$w_isdoff; + section=(void*)active; + section=(unsigned long)buffer+ehdr32->ihd$w_size; + name=(unsigned long)ehdr32+ehdr32->ihd$w_imgidoff; + vers=(unsigned long)ehdr32+ehdr32->ihd$w_version_array_off; + debug=(unsigned long)ehdr32+ehdr32->ihd$w_symdbgoff; + + nisse_active=malloc(sizeof(struct _iha)); + // nisse_section=malloc(sizeof(struct _isd)); + nisse_name=malloc(sizeof(struct _ihi)); + nisse_vers=malloc(sizeof(struct _img_version_array)); + nisse_debug=malloc(sizeof(struct _ihs)); + + bzero(nisse_header,512); + + if (ehdr32->ihd$w_majorid!=IHD$K_MAJORID) + return 0; + + nisse_header->eihd$l_size=ehdr32->ihd$w_size; + nisse_header->eihd$l_activoff=ehdr32->ihd$w_activoff; + nisse_header->eihd$l_symdbgoff=ehdr32->ihd$w_symdbgoff; + nisse_header->eihd$l_imgidoff=ehdr32->ihd$w_imgidoff; + nisse_header->eihd$l_patchoff=ehdr32->ihd$w_patchoff; + nisse_header->eihd$l_version_array_off=ehdr32->ihd$w_version_array_off; + nisse_header->eihd$l_majorid=ehdr32->ihd$w_majorid; + nisse_header->eihd$l_minorid=ehdr32->ihd$w_minorid; + nisse_header->eihd$l_hdrblkcnt=ehdr32->ihd$b_hdrblkcnt; + nisse_header->eihd$l_imgtype=ehdr32->ihd$b_imgtype; + nisse_header->eihd$q_privreqs=ehdr32->ihd$q_privreqs; + nisse_header->eihd$l_iochancnt=ehdr32->ihd$w_iochancnt; + nisse_header->eihd$l_imgiocnt=ehdr32->ihd$w_imgiocnt; + nisse_header->eihd$l_lnkflags=ehdr32->ihd$l_lnkflags; + nisse_header->eihd$l_ident=ehdr32->ihd$l_ident; + nisse_header->eihd$l_sysver=ehdr32->ihd$l_sysver; + nisse_header->eihd$w_alias=ehdr32->ihd$w_alias; + + nisse_active->eiha$l_tfradr1=active->iha$l_tfradr1; + nisse_active->eiha$l_tfradr2=active->iha$l_tfradr2; + nisse_active->eiha$l_tfradr3=active->iha$l_tfradr3; + nisse_active->eiha$l_inishr=active->iha$l_inishr; + + bcopy(name->ihi$t_imgnam,nisse_name->eihi$t_imgnam,40); + bcopy(name->ihi$t_imgnam,nisse_name->eihi$t_imgnam,16); + bcopy(name->ihi$t_imgid,nisse_name->eihi$t_imgid,16); + nisse_name->eihi$q_linktime=name->ihi$q_linktime; + bcopy(name->ihi$t_linkid,nisse_name->eihi$t_linkid,16); + + nisse_debug->eihs$l_dstvbn=debug->ihs$l_dstvbn; + nisse_debug->eihs$l_gstvbn=debug->ihs$l_gstvbn; + nisse_debug->eihs$l_dstsize=debug->ihs$w_dstblks; + nisse_debug->eihs$l_gstsize=debug->ihs$w_gstrecs; + nisse_debug->eihs$l_dmtvbn=debug->ihs$l_dmtvbn; + nisse_debug->eihs$l_dmtbytes=debug->ihs$l_dmtbytes; + // nisse_debug->eihs$l_dstblks=debug->ihs$l_dstblks; + // nisse_debug->eihs$l_gstrecs=debug->ihs$l_gstrecs; + + fseek(file,0,SEEK_SET); + if (fread (buffer, 512*nisse_header->eihd$l_hdrblkcnt, 1, file) != 1) + return 0; + + i=0; + while (section<(buffer+512*ehdr32->ihd$b_hdrblkcnt)) { + if (section->isd$w_size==0) + break; + if (section->isd$w_size==0xffffffff) { + int no=((unsigned long)section-(unsigned long)buffer)>>9; + section=buffer+512*(no+1); + continue; + } + nisse_section[i].eisd$l_eisdsize=section->isd$w_size; + nisse_section[i].eisd$l_secsize=section->isd$w_pagcnt; + nisse_section[i].eisd$l_virt_addr=section->isd$l_vpnpfc; + nisse_section[i].eisd$l_flags=section->isd$l_flags; + nisse_section[i].eisd$l_vbn=section->isd$l_vbn; + nisse_section[i].eisd$l_ident=section->isd$l_ident; + bcopy(section->isd$t_gblnam,nisse_section[i].eisd$t_gblnam,44); + section=(unsigned long)section+section->isd$w_size; + i++; + } + nisse_sects=i; + +#if 0 + if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 1, file) != 1) + return 0; + + nisse_header.e_type = BYTE_GET (ehdr32.e_type); + nisse_header.e_machine = BYTE_GET (ehdr32.e_machine); + nisse_header.e_version = BYTE_GET (ehdr32.e_version); + nisse_header.e_entry = BYTE_GET (ehdr32.e_entry); + nisse_header.e_phoff = BYTE_GET (ehdr32.e_phoff); + nisse_header.e_shoff = BYTE_GET (ehdr32.e_shoff); + nisse_header.e_flags = BYTE_GET (ehdr32.e_flags); + nisse_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize); + nisse_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize); + nisse_header.e_phnum = BYTE_GET (ehdr32.e_phnum); + nisse_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize); + nisse_header.e_shnum = BYTE_GET (ehdr32.e_shnum); + nisse_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx); +#endif + } + else + { +#if 0 + Elf64_External_Ehdr ehdr64; + + /* If we have been compiled with sizeof (bfd_vma) == 4, then + we will not be able to cope with the 64bit data found in + 64 ELF files. Detect this now and abort before we start + overwritting things. */ + if (sizeof (bfd_vma) < 8) + { + error (_("This instance of readelf has been built without support for a\n\ +64 bit data type and so it cannot read 64 bit ELF files.\n")); + return 0; + } + + if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1) + return 0; + + nisse_header.e_type = BYTE_GET (ehdr64.e_type); + nisse_header.e_machine = BYTE_GET (ehdr64.e_machine); + nisse_header.e_version = BYTE_GET (ehdr64.e_version); + nisse_header.e_entry = BYTE_GET8 (ehdr64.e_entry); + nisse_header.e_phoff = BYTE_GET8 (ehdr64.e_phoff); + nisse_header.e_shoff = BYTE_GET8 (ehdr64.e_shoff); + nisse_header.e_flags = BYTE_GET (ehdr64.e_flags); + nisse_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize); + nisse_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize); + nisse_header.e_phnum = BYTE_GET (ehdr64.e_phnum); + nisse_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize); + nisse_header.e_shnum = BYTE_GET (ehdr64.e_shnum); + nisse_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx); +#endif + int i; + char * buffer = malloc(512*nisse_header->eihd$l_hdrblkcnt); + fseek(file,0,SEEK_SET); + if (fread (buffer, 512*nisse_header->eihd$l_hdrblkcnt, 1, file) != 1) + return 0; + + nisse_active=(unsigned long)nisse_header+nisse_header->eihd$l_activoff; + section=(unsigned long)buffer+nisse_header->eihd$l_isdoff; + nisse_name=(unsigned long)nisse_header+nisse_header->eihd$l_imgidoff; + nisse_vers=(unsigned long)nisse_header+nisse_header->eihd$l_version_array_off; + nisse_debug=(unsigned long)nisse_header+nisse_header->eihd$l_symdbgoff; + + i=0; + while (section<(buffer+512*nisse_header->eihd$l_hdrblkcnt)) { + if (section->eisd$l_eisdsize==0) + break; + if (section->eisd$l_eisdsize==0xffffffff) { + int no=((unsigned long)section-(unsigned long)buffer)>>9; + section=buffer+512*(no+1); + continue; + } + bcopy(section,&nisse_section[i],section->eisd$l_eisdsize); + section=(unsigned long)section+section->eisd$l_eisdsize; + i++; + } + nisse_sects=i; + } + +#if 0 + if (nisse_header.e_shoff) + { + /* There may be some extensions in the first section header. Don't + bomb if we can't read it. */ + if (is_32bit_elf) + get_32bit_section_headers (file, 1); + else + get_64bit_section_headers (file, 1); + } +#endif + + return 1; +} + +static int +process_file (file_name) + char * file_name; +{ + FILE * file; + struct stat statbuf; + unsigned int i; + + if (stat (file_name, & statbuf) < 0) + { + error (_("Cannot stat input file %s.\n"), file_name); + return 1; + } + + file = fopen (file_name, "rb"); + if (file == NULL) + { + error (_("Input file %s not found.\n"), file_name); + return 1; + } + + if (! get_file_header (file)) + { + error (_("%s: Failed to read file header\n"), file_name); + fclose (file); + return 1; + } + +#if 0 + /* Initialise per file variables. */ + for (i = NUM_ELEM (version_info); i--;) + version_info[i] = 0; + + for (i = NUM_ELEM (dynamic_info); i--;) + dynamic_info[i] = 0; + +#endif + + /* Process the file. */ + if (show_name) + printf (_("\nFile: %s\n"), file_name); + + if (! process_file_header ()) + { + fclose (file); + return 1; + } + +#if 0 + + process_section_headers (file); + + process_program_headers (file); + + process_dynamic_segment (file); + + process_relocs (file); + + process_unwind (file); + + process_symbol_table (file); + + process_syminfo (file); + + process_version_sections (file); + + process_section_contents (file); + + process_corefile_contents (file); + + process_gnu_liblist (file); + + process_arch_specific (file); + + fclose (file); + + if (section_headers) + { + free (section_headers); + section_headers = NULL; + } + + if (string_table) + { + free (string_table); + string_table = NULL; + string_table_length = 0; + } + + if (dynamic_strings) + { + free (dynamic_strings); + dynamic_strings = NULL; + } + + if (dynamic_symbols) + { + free (dynamic_symbols); + dynamic_symbols = NULL; + num_dynamic_syms = 0; + } + + if (dynamic_syminfo) + { + free (dynamic_syminfo); + dynamic_syminfo = NULL; + } +#endif + + return 0; +} + +#ifdef SUPPORT_DISASSEMBLY +/* Needed by the i386 disassembler. For extra credit, someone could + fix this so that we insert symbolic addresses here, esp for GOT/PLT + symbols. */ + +void +print_address (unsigned int addr, FILE * outfile) +{ + fprintf (outfile,"0x%8.8x", addr); +} + +/* Needed by the i386 disassembler. */ +void +db_task_printsym (unsigned int addr) +{ + print_address (addr, stderr); +} +#endif + +int main PARAMS ((int, char **)); + +int +main (argc, argv) + int argc; + char ** argv; +{ + int err; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif +#if defined (HAVE_SETLOCALE) + setlocale (LC_CTYPE, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + parse_args (argc, argv); + + if (optind < (argc - 1)) + show_name = 1; + + err = 0; + while (optind < argc) + err |= process_file (argv [optind ++]); + + if (dump_sects != NULL) + free (dump_sects); + + return err; +} diff -ruN binutils-2.16-orig/configure binutils/configure --- binutils-2.16-orig/configure Mon Feb 28 15:06:59 2005 +++ binutils/configure Wed May 25 09:08:06 2005 @@ -1227,6 +1227,9 @@ alpha*-*-*vms*) noconfigdirs="$noconfigdirs gdb ld target-newlib target-libgloss ${libgcj}" ;; + i386-*-*vms*) + noconfigdirs="$noconfigdirs gas fileutils target-newlib target-libgloss" + ;; alpha*-*-linux*) # newlib is not 64 bit ready noconfigdirs="$noconfigdirs target-newlib target-libgloss" diff -ruN binutils-2.16-orig/configure.in binutils/configure.in --- binutils-2.16-orig/configure.in Mon May 2 23:19:23 2005 +++ binutils/configure.in Wed May 25 09:08:06 2005 @@ -426,10 +426,13 @@ # ld works, but does not support shared libraries. # newlib is not 64 bit ready. I'm not sure about fileutils. # gas doesn't generate exception information. - noconfigdirs="$noconfigdirs gas ld fileutils target-newlib target-libgloss" + noconfigdirs="$noconfigdirs ld fileutils target-newlib target-libgloss" ;; alpha*-*-*vms*) - noconfigdirs="$noconfigdirs gdb ld target-newlib target-libgloss ${libgcj}" + noconfigdirs="$noconfigdirs gas gdb ld target-newlib target-libgloss ${libgcj}" + ;; + i386-*-*vms*) + noconfigdirs="$noconfigdirs gas fileutils target-newlib target-libgloss" ;; alpha*-*-linux*) # newlib is not 64 bit ready diff -ruN binutils-2.16-orig/include/nisse/eiafdef.h binutils/include/nisse/eiafdef.h --- binutils-2.16-orig/include/nisse/eiafdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eiafdef.h Wed May 25 10:10:40 2005 @@ -0,0 +1,45 @@ +#ifndef eiafdef_h +#define eiafdef_h + +#define EIAF$K_LENGTH 84 +#define EIAF$C_LENGTH 84 +#define EIAF$S_EIAFDEF 84 + +struct _eiaf { + struct { + unsigned int eiaf$l_majorid; + unsigned int eiaf$l_minorid; + }; + union { + int eiaf$l_iaflink; + long long eiaf$q_iaflink; + }; + union { + int eiaf$l_fixuplnk; + long long eiaf$q_fixuplnk; + }; + int eiaf$l_size; + union { + unsigned int eiaf$l_flags; + struct { + unsigned eiaf$v_shr : 1; + unsigned eiaf$v_fill_0_ : 7; + }; + }; + int eiaf$l_qrelfixoff; + int eiaf$l_lrelfixoff; + int eiaf$l_qdotadroff; + int eiaf$l_ldotadroff; + int eiaf$l_codeadroff; + int eiaf$l_lpfixoff; + int eiaf$l_chgprtoff; + int eiaf$l_shlstoff; + int eiaf$l_shrimgcnt; + int eiaf$l_shlextra; + int eiaf$l_permctx; + void *eiaf$l_base_va; + int eiaf$l_lppsbfixoff; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihadef.h binutils/include/nisse/eihadef.h --- binutils-2.16-orig/include/nisse/eihadef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihadef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,46 @@ +#ifndef eihadef_h +#define eihadef_h + +#define EIHA$K_LENGTH 48 +#define EIHA$C_LENGTH 48 +#define EIHA$S_EIHADEF 48 + +struct _eiha { + unsigned int eiha$l_size; + unsigned int eiha$l_spare; + union { + unsigned long long eiha$q_tfradr1; + struct { + unsigned int eiha$l_tfradr1; + unsigned int eiha$l_tfradr1_h; + }; + }; + union { + unsigned long long eiha$q_tfradr2; + struct { + unsigned int eiha$l_tfradr2; + unsigned int eiha$l_tfradr2_h; + }; + }; + union { + unsigned long long eiha$q_tfradr3; + struct { + unsigned int eiha$l_tfradr3; + unsigned int eiha$l_tfradr3_h; + }; + }; + union { + unsigned long long eiha$q_tfradr4; + struct { + unsigned int eiha$l_tfradr4; + unsigned int eiha$l_tfradr4_h; + }; + }; + union { + unsigned int eiha$l_inishr; + unsigned long long eiha$q_inishr; + }; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihddef.h binutils/include/nisse/eihddef.h --- binutils-2.16-orig/include/nisse/eihddef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihddef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,106 @@ +#ifndef eihddef_h +#define eihddef_h + +#define EIHD$K_MAJORID 3 +#define EIHD$K_MINORID 0 +#define EIHD$K_MINORID_64 1 +#define EIHD$K_EXE 1 +#define EIHD$K_LIM 2 +#define EIHD$C_MINCODE 0 +#define EIHD$C_NATIVE 0 +#define EIHD$C_CLI 1 +#define EIHD$C_MAXCODE 1 +#define EIHD$M_LNKDEBUG 0x1 +#define EIHD$M_LNKNOTFR 0x2 +#define EIHD$M_NOP0BUFS 0x4 +#define EIHD$M_PICIMG 0x8 +#define EIHD$M_P0IMAGE 0x10 +#define EIHD$M_DBGDMT 0x20 +#define EIHD$M_INISHR 0x40 +#define EIHD$M_XLATED 0x80 +#define EIHD$M_BIND_CODE_SEC 0x100 +#define EIHD$M_BIND_DATA_SEC 0x200 +#define EIHD$M_MKTHREADS 0x400 +#define EIHD$M_UPCALLS 0x800 +#define EIHD$M_OMV_READY 0x1000 +#define EIHD$M_EXT_BIND_SECT 0x2000 +#define EIHD$K_LENGTH 104 +#define EIHD$C_LENGTH 104 +#define EIHD$K_LENGTH_97 112 +#define EIHD$K_ALIAS_MINCODE -1 + +#define EIHD$K_VAX -1 +#define EIHD$K_RSX 0 +#define EIHD$K_BPA 1 +#define EIHD$K_ALIAS 2 +#define EIHD$K_VAX_CLI 3 +#define EIHD$K_PMAX 4 + +#define EIHD$K_ALPHA 5 +#define EIHD$K_ALIAS_MAXCODE 5 +#define EIHD$S_EIHDDEF 512 + +struct _eihd { + struct { + unsigned int eihd$l_majorid; + unsigned int eihd$l_minorid; + }; + unsigned int eihd$l_size; + unsigned int eihd$l_isdoff; + unsigned int eihd$l_activoff; + unsigned int eihd$l_symdbgoff; + unsigned int eihd$l_imgidoff; + unsigned int eihd$l_patchoff; + union { + void *eihd$l_iafva; + long long eihd$q_iafva; + }; + union { + void *eihd$l_symvva; + long long eihd$q_symvva; + }; + unsigned int eihd$l_version_array_off; + unsigned int eihd$l_imgtype; + unsigned int eihd$l_subtype; + unsigned int eihd$l_imgiocnt; + unsigned int eihd$l_iochancnt; + unsigned long long eihd$q_privreqs; + unsigned int eihd$l_hdrblkcnt; + union { + unsigned int eihd$l_lnkflags; + struct { + unsigned eihd$v_lnkdebug : 1; + unsigned eihd$v_lnknotfr : 1; + unsigned eihd$v_nop0bufs : 1; + unsigned eihd$v_picimg : 1; + unsigned eihd$v_p0image : 1; + unsigned eihd$v_dbgdmt : 1; + unsigned eihd$v_inishr : 1; + unsigned eihd$v_xlated : 1; + unsigned eihd$v_bind_code_sec : 1; + unsigned eihd$v_bind_data_sec : 1; + unsigned eihd$v_mkthreads : 1; + unsigned eihd$v_upcalls : 1; + unsigned eihd$v_omv_ready : 1; + unsigned eihd$v_ext_bind_sect : 1; + unsigned eihd$v_fill_0_ : 2; + }; + }; + unsigned int eihd$l_ident; + unsigned int eihd$l_sysver; + struct { + unsigned char eihd$b_matchctl; + unsigned char eihd$b_fill_1; + unsigned char eihd$b_fill_2; + unsigned char eihd$b_fill_3; + unsigned int eihd$l_symvect_size; + unsigned int eihd$l_virt_mem_block_size; + }; + unsigned int eihd$l_ext_fixup_off; + unsigned int eihd$l_noopt_psect_off; + char eihd$t_skip [398]; + unsigned short int eihd$w_alias; + }; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihidef.h binutils/include/nisse/eihidef.h --- binutils-2.16-orig/include/nisse/eihidef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihidef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,23 @@ +#ifndef eihidef_h +#define eihidef_h + +#define EIHI$K_MAJORID 1 +#define EIHI$K_MINORID 2 +#define EIHI$K_LENGTH 104 +#define EIHI$C_LENGTH 104 +#define EIHI$S_EIHIDEF 104 + +struct _eihi { + struct { + unsigned int eihi$l_majorid; + unsigned int eihi$l_minorid; + }; + unsigned long long eihi$q_linktime; + char eihi$t_imgnam [40]; + char eihi$t_imgid [16]; + char eihi$t_linkid [16]; + char eihi$t_imgbid [16]; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihpdef.h binutils/include/nisse/eihpdef.h --- binutils-2.16-orig/include/nisse/eihpdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihpdef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,32 @@ +#ifndef eihpdef_h +#define eihpdef_h + +#define EIHP$K_LENGTH 60 +#define EIHP$C_LENGTH 60 +#define EIHP$S_EIHPDEF 60 + +struct _eihp { + struct { + unsigned int eihp$l_majorid; + unsigned int eihp$l_minorid; + }; + unsigned int eihp$l_eco1; + unsigned int eihp$l_eco2; + unsigned int eihp$l_eco3; + unsigned int eihp$l_eco4; + unsigned int eihp$l_patcomtxt; + unsigned int eihp$l_rw_patsiz; + union { + unsigned int eihp$l_rw_patadr; + unsigned long long eihp$q_rw_patadr; + }; + unsigned int eihp$l_ro_patsiz; + union { + unsigned int eihp$l_ro_patadr; + unsigned long long eihp$q_ro_patadr; + }; + unsigned long long eihp$q_patdate; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihsdef.h binutils/include/nisse/eihsdef.h --- binutils-2.16-orig/include/nisse/eihsdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihsdef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,24 @@ +#ifndef eihsdef_h +#define eihsdef_h + +#define EIHS$K_MAJORID 1 +#define EIHS$K_MINORID 1 +#define EIHS$K_LENGTH 32 +#define EIHS$C_LENGTH 32 +#define EIHS$S_EIHSDEF 32 + +struct _eihs { + struct { + unsigned int eihs$l_majorid; + unsigned int eihs$l_minorid; + }; + unsigned int eihs$l_dstvbn; + unsigned int eihs$l_dstsize; + unsigned int eihs$l_gstvbn; + unsigned int eihs$l_gstsize; + unsigned int eihs$l_dmtvbn; + unsigned int eihs$l_dmtbytes; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eihvndef.h binutils/include/nisse/eihvndef.h --- binutils-2.16-orig/include/nisse/eihvndef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eihvndef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,35 @@ +#ifndef eihvndef_h +#define eihvndef_h + +#define EIHVN$M_SUBVERSION_MINOR_ID 0xFFFF +#define EIHVN$M_SUBVERSION_MAJOR_ID 0xFFFF0000 + +struct _eimg_version_array { + unsigned int eihvn$l_subsystem_mask; + union { + unsigned int eihvn$l_subversion_array; + struct { + unsigned eihvn$v_subversion_minor_id : 16; + unsigned eihvn$v_subversion_major_id : 16; + }; + }; +}; + +#define EIHVN$M_VERSION_MINOR_ID 0xFFFFFF +#define EIHVN$M_VERSION_MAJOR_ID 0xFF000000 + +struct _eimg_overall_version { + union { + int eihvn$l_version_bits; + struct { + unsigned eihvn$v_version_minor_id : 24; + unsigned eihvn$v_version_major_id : 8; + }; + }; +}; + +#define EIHVN$K_LENGTH 132 +#define EIHVN$C_LENGTH 132 + +#endif + diff -ruN binutils-2.16-orig/include/nisse/eisddef.h binutils/include/nisse/eisddef.h --- binutils-2.16-orig/include/nisse/eisddef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/eisddef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,96 @@ +#ifndef eisddef_h +#define eisddef_h + +#define EISD$K_MAJORID 1 +#define EISD$K_MINORID 1 +#define EISD$M_GBL 0x1 +#define EISD$M_CRF 0x2 +#define EISD$M_DZRO 0x4 +#define EISD$M_WRT 0x8 +#define EISD$M_INITALCODE 0x10 +#define EISD$M_BASED 0x20 +#define EISD$M_FIXUPVEC 0x40 +#define EISD$M_RESIDENT 0x80 +#define EISD$M_VECTOR 0x100 +#define EISD$M_PROTECT 0x200 +#define EISD$M_LASTCLU 0x400 +#define EISD$M_EXE 0x800 +#define EISD$M_NONSHRADR 0x1000 +#define EISD$M_QUAD_LENGTH 0x2000 +#define EISD$M_ALLOC_64BIT 0x4000 +#define EISD$K_LENDZRO 36 +#define EISD$C_LENDZRO 36 +#define EISD$K_LENPRIV 36 +#define EISD$C_LENPRIV 36 +#define EISD$K_LENGLBL 56 +#define EISD$C_LENGLBL 56 +#define EISD$K_MAXLENGLBL 84 +#define EISD$C_MAXLENGLBL 84 + +#define EISD$K_MATALL 0 +#define EISD$K_MATEQU 1 +#define EISD$K_MATLEQ 2 +#define EISD$K_MATNEV 3 + +#define EISD$K_NORMAL 0 + +#define EISD$K_SHRFXD 1 +#define EISD$K_PRVFXD 2 +#define EISD$K_SHRPIC 3 +#define EISD$K_PRVPIC 4 +#define EISD$K_USRSTACK 253 +#define EISD$S_EISDDEF 84 + +struct _eisd { + struct { + unsigned int eisd$l_majorid; + unsigned int eisd$l_minorid; + }; + unsigned int eisd$l_eisdsize; + unsigned int eisd$l_secsize; + union { + unsigned long long eisd$q_virt_addr; + void *eisd$l_virt_addr; + struct { + unsigned eisd$v_vaddr : 30; + unsigned eisd$v_p1 : 1; + unsigned eisd$v_system : 1; + }; + }; + union { + unsigned int eisd$l_flags; + struct { + unsigned eisd$v_gbl : 1; + unsigned eisd$v_crf : 1; + unsigned eisd$v_dzro : 1; + unsigned eisd$v_wrt : 1; + unsigned eisd$v_initalcode : 1; + unsigned eisd$v_based : 1; + unsigned eisd$v_fixupvec : 1; + unsigned eisd$v_resident : 1; + unsigned eisd$v_vector : 1; + unsigned eisd$v_protect : 1; + unsigned eisd$v_lastclu : 1; + unsigned eisd$v_exe : 1; + unsigned eisd$v_nonshradr : 1; + unsigned eisd$v_quad_length : 1; + unsigned eisd$v_alloc_64bit : 1; + unsigned eisd$v_fill_0_ : 1; + }; + }; + unsigned int eisd$l_vbn; + struct { + unsigned char eisd$b_pfc; + unsigned char eisd$b_matchctl; + unsigned char eisd$b_type; + unsigned char eisd$b_fill_1; + }; + unsigned int eisd$l_ident; + union { + char eisd$t_gblnam [44]; + unsigned long long eisd$q_secsize; + }; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/iafdef.h binutils/include/nisse/iafdef.h --- binutils-2.16-orig/include/nisse/iafdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/iafdef.h Wed May 25 10:13:15 2005 @@ -0,0 +1,34 @@ +#ifndef iafdef_h +#define iafdef_h + +#define IAF$K_LENGTH 64 +#define IAF$C_LENGTH 64 +#define IAF$S_IAFDEF 64 + +struct _iaf { + void *iaf$l_iaflink; + void *iaf$l_fixuplnk; + unsigned short int iaf$w_size; + union { + unsigned short int iaf$w_flags; + struct { + unsigned iaf$v_shr : 1; + unsigned iaf$v_fill_0_ : 7; + }; + }; + unsigned int iaf$l_g_fixoff; + unsigned int iaf$l_dotadroff; + unsigned int iaf$l_chgprtoff; + unsigned int iaf$l_shlstoff; + unsigned int iaf$l_shrimgcnt; + unsigned int iaf$l_shlextra; + void *iaf$l_permctx; + int iafdef$$_fill_1; + int iafdef$$_fill_2; + int iafdef$$_fill_3; + int iafdef$$_fill_4; + int iafdef$$_fill_5; + int iafdef$$_fill_6; +}; + +#endif diff -ruN binutils-2.16-orig/include/nisse/ihadef.h binutils/include/nisse/ihadef.h --- binutils-2.16-orig/include/nisse/ihadef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihadef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,17 @@ +#ifndef ihadef_h +#define ihadef_h + +#define IHA$K_LENGTH 20 +#define IHA$C_LENGTH 20 +#define IHA$S_IHADEF 20 + +struct _iha { + unsigned int iha$l_tfradr1; + unsigned int iha$l_tfradr2; + unsigned int iha$l_tfradr3; + int ihadef$$_fill_1; + unsigned int iha$l_inishr; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/ihddef.h binutils/include/nisse/ihddef.h --- binutils-2.16-orig/include/nisse/ihddef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihddef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,79 @@ +#ifndef ihddef_h +#define ihddef_h + +#define IHD$K_MAJORID 12848 +#define IHD$K_MINORID 13616 +#define IHD$K_EXE 1 +#define IHD$K_LIM 2 +#define IHD$M_LNKDEBUG 0x1 +#define IHD$M_LNKNOTFR 0x2 +#define IHD$M_NOP0BUFS 0x4 +#define IHD$M_PICIMG 0x8 +#define IHD$M_P0IMAGE 0x10 +#define IHD$M_DBGDMT 0x20 +#define IHD$M_INISHR 0x40 +#define IHD$M_IHSLONG 0x80 +#define IHD$M_UPCALLS 0x100 +#define IHD$M_MATCHCTL 0x7000000 +#define IHD$K_LENGTH 48 +#define IHD$C_LENGTH 48 +#define IHD$C_MINCODE -1 +#define IHD$C_NATIVE -1 +#define IHD$C_RSX 0 +#define IHD$C_BPA 1 +#define IHD$C_ALIAS 2 +#define IHD$C_CLI 3 +#define IHD$C_PMAX 4 +#define IHD$C_ALPHA 5 +#define IHD$C_MAXCODE 5 + +#define IHD$C_GEN_XLNKR 1 +#define IHD$C_GEN_NATIVE 2 +#define IHD$C_GEN_LNKFLG 3 +#define IHD$C_GEN_SYSVER 4 +#define IHD$C_GEN_FIXUP 5 + +#define IHD$C_GEN_NEWISD 6 +#define IHD$S_IHDDEF 512 + +struct _ihd { + unsigned short int ihd$w_size; + unsigned short int ihd$w_activoff; + unsigned short int ihd$w_symdbgoff; + unsigned short int ihd$w_imgidoff; + unsigned short int ihd$w_patchoff; + unsigned short int ihd$w_version_array_off; + unsigned short int ihd$w_majorid; + unsigned short int ihd$w_minorid; + unsigned char ihd$b_hdrblkcnt; + unsigned char ihd$b_imgtype; + short int ihddef$$_fill_2; + unsigned long long ihd$q_privreqs; + unsigned short int ihd$w_iochancnt; + unsigned short int ihd$w_imgiocnt; + union { + unsigned int ihd$l_lnkflags; + struct { + unsigned ihd$v_lnkdebug : 1; + unsigned ihd$v_lnknotfr : 1; + unsigned ihd$v_nop0bufs : 1; + unsigned ihd$v_picimg : 1; + unsigned ihd$v_p0image : 1; + unsigned ihd$v_dbgdmt : 1; + unsigned ihd$v_inishr : 1; + unsigned ihd$v_ihslong : 1; + unsigned ihd$v_upcalls : 1; + unsigned ihddef$$_fill_3 : 15; + unsigned ihd$v_matchctl : 3; + unsigned ihd$v_fill_0_ : 5; + }; + }; + unsigned int ihd$l_ident; + unsigned int ihd$l_sysver; + void *ihd$l_iafva; + char ihd$t_skip [462]; + unsigned short int ihd$w_alias; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/ihidef.h binutils/include/nisse/ihidef.h --- binutils-2.16-orig/include/nisse/ihidef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihidef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,16 @@ +#ifndef ihidef_h +#define ihidef_h + +#define IHI$K_LENGTH 80 +#define IHI$C_LENGTH 80 +#define IHI$S_IHIDEF 80 + +struct _ihi { + char ihi$t_imgnam [40]; + char ihi$t_imgid [16]; + unsigned long long ihi$q_linktime; + char ihi$t_linkid [16]; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/ihpdef.h binutils/include/nisse/ihpdef.h --- binutils-2.16-orig/include/nisse/ihpdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihpdef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,22 @@ +#ifndef ihpdef_h +#define ihpdef_h + +#define IHP$K_LENGTH 44 +#define IHP$C_LENGTH 44 +#define IHP$S_IHPDEF 44 + +struct _ihp { + unsigned int ihp$l_eco1; + unsigned int ihp$l_eco2; + unsigned int ihp$l_eco3; + unsigned int ihp$l_eco4; + unsigned int ihp$l_rw_patsiz; + void *ihp$l_rw_patadr; + unsigned int ihp$l_ro_patsiz; + void *ihp$l_ro_patadr; + unsigned int ihp$l_patcomtxt; + unsigned long long ihp$q_patdate; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/ihsdef.h binutils/include/nisse/ihsdef.h --- binutils-2.16-orig/include/nisse/ihsdef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihsdef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,20 @@ +#ifndef ihsdef_h +#define ihsdef_h + +#define IHS$K_LENGTH 28 +#define IHS$C_LENGTH 28 +#define IHS$S_IHSDEF 28 + +struct _ihs { + unsigned int ihs$l_dstvbn; + unsigned int ihs$l_gstvbn; + unsigned short int ihs$w_dstblks; + unsigned short int ihs$w_gstrecs; + unsigned int ihs$l_dmtvbn; + unsigned int ihs$l_dmtbytes; + int ihs$l_dstblks; + int ihs$l_gstrecs; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/ihvndef.h binutils/include/nisse/ihvndef.h --- binutils-2.16-orig/include/nisse/ihvndef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/ihvndef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,32 @@ +#ifndef ihvndef_h +#define ihvndef_h + +#define IHVN$M_SUBVERSION_MINOR_ID 0xFFFF +#define IHVN$M_SUBVERSION_MAJOR_ID 0xFFFF0000 + +struct _img_version_array { + unsigned int ihvn$l_subsystem_mask; + union { + unsigned int ihvn$l_subversion_array; + struct { + unsigned ihvn$v_subversion_minor_id : 16; + unsigned ihvn$v_subversion_major_id : 16; + }; + }; +}; + +#define IHVN$M_VERSION_MINOR_ID 0xFFFFFF +#define IHVN$M_VERSION_MAJOR_ID 0xFF000000 + +struct _img_overall_version { + union { + int ihvn$l_version_bits; + struct { + unsigned ihvn$v_version_minor_id : 24; + unsigned ihvn$v_version_major_id : 8; + }; + }; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/isddef.h binutils/include/nisse/isddef.h --- binutils-2.16-orig/include/nisse/isddef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/isddef.h Wed May 25 09:08:06 2005 @@ -0,0 +1,89 @@ +#ifndef isddef_h +#define isddef_h + +#define ISD$K_LENDZRO 12 +#define ISD$C_LENDZRO 12 +#define ISD$M_GBL 0x1 +#define ISD$M_CRF 0x2 +#define ISD$M_DZRO 0x4 +#define ISD$M_WRT 0x8 +#define ISD$M_MATCHCTL 0x70 +#define ISD$M_LASTCLU 0x80 +#define ISD$M_INITALCODE 0x100 +#define ISD$M_BASED 0x200 +#define ISD$M_FIXUPVEC 0x400 +#define ISD$M_RESIDENT 0x800 +#define ISD$M_VECTOR 0x20000 +#define ISD$M_PROTECT 0x40000 +#define ISD$S_FLAGSIZ 24 +#define ISD$K_LENPRIV 16 +#define ISD$C_LENPRIV 16 +#define ISD$K_LENGLBL 36 +#define ISD$C_LENGLBL 36 +#define ISD$K_MAXLENGLBL 64 +#define ISD$C_MAXLENGLBL 64 + +#define ISD$K_MATALL 0 +#define ISD$K_MATEQU 1 +#define ISD$K_MATLEQ 2 +#define ISD$K_MATNEV 3 + +#define ISD$K_NORMAL 0 +#define ISD$K_SHRFXD 1 +#define ISD$K_PRVFXD 2 +#define ISD$K_SHRPIC 3 +#define ISD$K_PRVPIC 4 +#define ISD$K_USRSTACK 253 +#define ISD$S_ISDDEF 64 + +struct _isd { + unsigned short int isd$w_size; + unsigned short int isd$w_pagcnt; + union { + unsigned int isd$l_vpnpfc; + struct { + unsigned isd$v_vpn : 21; + unsigned isd$v_p1 : 1; + unsigned isd$v_system : 1; + unsigned isddef$$_fill_1 : 1; + unsigned isd$v_pfc : 8; + }; + struct { + unsigned isd$v_vpg : 23; + unsigned isd$v_fill_0_ : 1; + }; + struct { + char isddef$$_fill_4 [3]; + unsigned char isd$b_pfc; + }; + }; + union { + unsigned int isd$l_flags; + struct { + unsigned isd$v_gbl : 1; + unsigned isd$v_crf : 1; + unsigned isd$v_dzro : 1; + unsigned isd$v_wrt : 1; + unsigned isd$v_matchctl : 3; + unsigned isd$v_lastclu : 1; + unsigned isd$v_initalcode : 1; + unsigned isd$v_based : 1; + unsigned isd$v_fixupvec : 1; + unsigned isd$v_resident : 1; + unsigned isddef$$_fill_2 : 5; + unsigned isd$v_vector : 1; + unsigned isd$v_protect : 1; + unsigned isddef$$_fill_3 : 5; + }; + struct { + char isddef$$_fill_5 [3]; + unsigned char isd$b_type; + }; + }; + unsigned int isd$l_vbn; + unsigned int isd$l_ident; + char isd$t_gblnam [44]; +}; + +#endif + diff -ruN binutils-2.16-orig/include/nisse/shldef.h binutils/include/nisse/shldef.h --- binutils-2.16-orig/include/nisse/shldef.h Thu Jan 1 01:00:00 1970 +++ binutils/include/nisse/shldef.h Wed May 25 10:16:19 2005 @@ -0,0 +1,33 @@ +#ifndef shldef_h +#define shldef_h + +#define SHL$M_FIXUP 0x1 +#define SHL$C_OLD_SHL_SIZE 56 +#define SHL$C_MAXNAMLNG 39 +#define SHL$K_LENGTH 64 +#define SHL$C_LENGTH 64 +#define SHL$S_SHLDEF 64 + +struct _shl { + void *shl$l_baseva; + struct _shl *shl$l_shlptr; + + unsigned int shl$l_ident; + void *shl$l_permctx; + char shl$b_shl_size; + short int shldef$$_fill_1; + union { + unsigned char shl$b_flags; + struct { + unsigned shl$v_fixup : 1; + unsigned shl$v_fill_2_ : 7; + }; + }; + void *shl$l_icb; + union { + char shl$t_imgnam [40]; + char shl$b_namlng; + }; +}; + +#endif diff -ruN binutils-2.16-orig/ld/Makefile.in binutils/ld/Makefile.in --- binutils-2.16-orig/ld/Makefile.in Sun Jan 23 06:36:37 2005 +++ binutils/ld/Makefile.in Wed May 25 09:08:06 2005 @@ -1216,6 +1216,9 @@ ealpha.c: $(srcdir)/emulparams/alpha.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/alpha.sc ${GEN_DEPENDS} ${GENSCRIPTS} alpha "$(tdir_alpha)" +ei386vms.c: $(srcdir)/emulparams/i386vms.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/i386vms.sc ${GEN_DEPENDS} + ${GENSCRIPTS} i386vms "$(tdir_i386vms)" earcelf.c: $(srcdir)/emulparams/arcelf.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} arcelf "$(tdir_arcelf)" diff -ruN binutils-2.16-orig/ld/configure.tgt binutils/ld/configure.tgt --- binutils-2.16-orig/ld/configure.tgt Tue Feb 8 20:54:27 2005 +++ binutils/ld/configure.tgt Wed May 25 09:08:06 2005 @@ -471,6 +471,7 @@ tdir_alpha=`echo ${targ_alias} | sed -e 's/linux/linuxecoff/'` ;; alpha*-*-osf*) targ_emul=alpha ;; +i386-*-vms) targ_emul=i386vms targ_extra_emuls=elf_i386;; alpha*-*-gnu*) targ_emul=elf64alpha ;; alpha*-*-netware*) targ_emul=alpha ;; alpha*-*-netbsd*) targ_emul=elf64alpha_nbsd ;; diff -ruN binutils-2.16-orig/ld/emulparams/i386vms.sh binutils/ld/emulparams/i386vms.sh --- binutils-2.16-orig/ld/emulparams/i386vms.sh Thu Jan 1 01:00:00 1970 +++ binutils/ld/emulparams/i386vms.sh Wed May 25 09:08:06 2005 @@ -0,0 +1,16 @@ +SCRIPT_NAME=i386vms +#was elf was/can be nisse (nisse.sc) +OUTPUT_FORMAT="nisse-i386" +TEXT_START_ADDR=0x10000 +#DATA_START_ADDR=0x400000 +MAXPAGESIZE=0x1000 +COMMONPAGESIZE=0x1000 +NONPAGED_TEXT_START_ADDR=0x10000 +ARCH=i386 +MACHINE= +NOP=0x90909090 +TEMPLATE_NAME=elf32 +# make our own of this, too +GENERATE_SHLIB_SCRIPT=yes +GENERATE_PIE_SCRIPT=yes +NO_SMALL_DATA=yes diff -ruN binutils-2.16-orig/ld/scripttempl/i386vms.sc binutils/ld/scripttempl/i386vms.sc --- binutils-2.16-orig/ld/scripttempl/i386vms.sc Thu Jan 1 01:00:00 1970 +++ binutils/ld/scripttempl/i386vms.sc Wed May 25 09:08:06 2005 @@ -0,0 +1,413 @@ +# +# Unusual variables checked by this code: +# NOP - four byte opcode for no-op (defaults to 0) +# NO_SMALL_DATA - no .sbss/.sbss2/.sdata/.sdata2 sections if not +# empty. +# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start +# INITIAL_READONLY_SECTIONS - at start of text segment +# OTHER_READONLY_SECTIONS - other than .text .init .rodata ... +# (e.g., .PARISC.milli) +# OTHER_TEXT_SECTIONS - these get put in .text when relocating +# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ... +# (e.g., .PARISC.global) +# OTHER_BSS_SECTIONS - other than .bss .sbss ... +# OTHER_SECTIONS - at the end +# EXECUTABLE_SYMBOLS - symbols that must be defined for an +# executable (e.g., _DYNAMIC_LINK) +# TEXT_START_SYMBOLS - symbols that appear at the start of the +# .text section. +# DATA_START_SYMBOLS - symbols that appear at the start of the +# .data section. +# OTHER_GOT_SYMBOLS - symbols defined just before .got. +# OTHER_GOT_SECTIONS - sections just after .got. +# OTHER_SDATA_SECTIONS - sections just after .sdata. +# OTHER_BSS_SYMBOLS - symbols that appear at the start of the +# .bss section besides __bss_start. +# DATA_PLT - .plt should be in data segment, not text segment. +# BSS_PLT - .plt should be in bss segment +# TEXT_DYNAMIC - .dynamic in text segment, not data segment. +# EMBEDDED - whether this is for an embedded system. +# SHLIB_TEXT_START_ADDR - if set, add to SIZEOF_HEADERS to set +# start address of shared library. +# INPUT_FILES - INPUT command of files to always include +# WRITABLE_RODATA - if set, the .rodata section should be writable +# INIT_START, INIT_END - statements just before and just after +# combination of .init sections. +# FINI_START, FINI_END - statements just before and just after +# combination of .fini sections. +# STACK_ADDR - start of a .stack section. +# OTHER_END_SYMBOLS - symbols to place right at the end of the script. +# +# When adding sections, do note that the names of some sections are used +# when specifying the start address of the next. +# + +# Many sections come in three flavours. There is the 'real' section, +# like ".data". Then there are the per-procedure or per-variable +# sections, generated by -ffunction-sections and -fdata-sections in GCC, +# and useful for --gc-sections, which for a variable "foo" might be +# ".data.foo". Then there are the linkonce sections, for which the linker +# eliminates duplicates, which are named like ".gnu.linkonce.d.foo". +# The exact correspondences are: +# +# Section Linkonce section +# .text .gnu.linkonce.t.foo +# .rodata .gnu.linkonce.r.foo +# .data .gnu.linkonce.d.foo +# .bss .gnu.linkonce.b.foo +# .sdata .gnu.linkonce.s.foo +# .sbss .gnu.linkonce.sb.foo +# .sdata2 .gnu.linkonce.s2.foo +# .sbss2 .gnu.linkonce.sb2.foo +# .debug_info .gnu.linkonce.wi.foo +# .tdata .gnu.linkonce.td.foo +# .tbss .gnu.linkonce.tb.foo +# +# Each of these can also have corresponding .rel.* and .rela.* sections. + +test -z "$ENTRY" && ENTRY=main +# was: _start +test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT} +test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT} +if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi +test -z "${ELFSIZE}" && ELFSIZE=32 +test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8" +test "$LD_FLAG" = "N" && DATA_ADDR=. +test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE="" +test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE="" +DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))" +DATA_SEGMENT_END="" +if test -n "${COMMONPAGESIZE}"; then + DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})" + DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);" +fi +INTERP="/DISCARD/ ${RELOCATING-0} : { *(.interp) }" +PLT=".plt ${RELOCATING-0} : { *(.plt) }" +test -z "$GOT" && GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.got) }" +DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }" +RODATA=".rodata ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }" +STACKNOTE="/DISCARD/ : { *(.note.GNU-stack) }" +if test -z "${NO_SMALL_DATA}"; then + SBSS=".sbss ${RELOCATING-0} : + { + ${RELOCATING+PROVIDE (__sbss_start = .);} + ${RELOCATING+PROVIDE (___sbss_start = .);} + *(.dynsbss) + *(.sbss${RELOCATING+ .sbss.* .gnu.linkonce.sb.*}) + *(.scommon) + ${RELOCATING+PROVIDE (__sbss_end = .);} + ${RELOCATING+PROVIDE (___sbss_end = .);} + }" + SBSS2=".sbss2 ${RELOCATING-0} : { *(.sbss2${RELOCATING+ .sbss2.* .gnu.linkonce.sb2.*}) }" + SDATA="/* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata ${RELOCATING-0} : + { + ${RELOCATING+${SDATA_START_SYMBOLS}} + *(.sdata${RELOCATING+ .sdata.* .gnu.linkonce.s.*}) + }" + SDATA2=".sdata2 ${RELOCATING-0} : { *(.sdata2${RELOCATING+ .sdata2.* .gnu.linkonce.s2.*}) }" + REL_SDATA=".rel.sdata ${RELOCATING-0} : { *(.rel.sdata${RELOCATING+ .rel.sdata.* .rel.gnu.linkonce.s.*}) } + .rela.sdata ${RELOCATING-0} : { *(.rela.sdata${RELOCATING+ .rela.sdata.* .rela.gnu.linkonce.s.*}) }" + REL_SBSS=".rel.sbss ${RELOCATING-0} : { *(.rel.sbss${RELOCATING+ .rel.sbss.* .rel.gnu.linkonce.sb.*}) } + .rela.sbss ${RELOCATING-0} : { *(.rela.sbss${RELOCATING+ .rela.sbss.* .rela.gnu.linkonce.sb.*}) }" + REL_SDATA2=".rel.sdata2 ${RELOCATING-0} : { *(.rel.sdata2${RELOCATING+ .rel.sdata2.* .rel.gnu.linkonce.s2.*}) } + .rela.sdata2 ${RELOCATING-0} : { *(.rela.sdata2${RELOCATING+ .rela.sdata2.* .rela.gnu.linkonce.s2.*}) }" + REL_SBSS2=".rel.sbss2 ${RELOCATING-0} : { *(.rel.sbss2${RELOCATING+ .rel.sbss2.* .rel.gnu.linkonce.sb2.*}) } + .rela.sbss2 ${RELOCATING-0} : { *(.rela.sbss2${RELOCATING+ .rela.sbss2.* .rela.gnu.linkonce.sb2.*}) }" +fi +CTOR="/DISCARD/ ${CONSTRUCTING-0} : + { + ${CONSTRUCTING+${CTOR_START}} + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin*.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend*.o $OTHER_EXCLUDE_FILES) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + ${CONSTRUCTING+${CTOR_END}} + }" +DTOR="/DISCARD/ ${CONSTRUCTING-0} : + { + ${CONSTRUCTING+${DTOR_START}} + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o $OTHER_EXCLUDE_FILES) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ${CONSTRUCTING+${DTOR_END}} + }" +STACK=" .stack ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} : + { + ${RELOCATING+_stack = .;} + *(.stack) + }" + +# if this is for an embedded system, don't add SIZEOF_HEADERS. +if [ -z "$EMBEDDED" ]; then + test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR} + SIZEOF_HEADERS" +else + test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}" +fi + +cat <