/* All the swapping routines: */ static void DEFUN(swap_reloc_in,(abfd, reloc_src, reloc_dst), bfd *abfd AND RELOC *reloc_src AND struct internal_reloc *reloc_dst) { reloc_dst->r_vaddr = bfd_h_getlong(abfd, reloc_src->r_vaddr); reloc_dst->r_symndx = bfd_h_getlong(abfd, reloc_src->r_symndx); reloc_dst->r_type = bfd_h_getshort(abfd, reloc_src->r_type); #if M88 reloc_dst->r_offset = bfd_h_getshort(abfd, reloc_src->r_offset); #endif } static void DEFUN(swap_reloc_out,(abfd, reloc_src, reloc_dst), bfd *abfd AND struct internal_reloc *reloc_src AND struct external_reloc *reloc_dst) { bfd_h_putlong(abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr); bfd_h_putlong(abfd, reloc_src->r_symndx, reloc_dst->r_symndx); bfd_h_putshort(abfd, reloc_src->r_type, reloc_dst->r_type); #if M88 bfd_h_putshort(abfd, reloc_src->r_offset, reloc_dst->r_offset); #endif } static void DEFUN(swap_filehdr_in,(abfd, filehdr_src, filehdr_dst), bfd *abfd AND FILHDR *filehdr_src AND struct internal_filehdr *filehdr_dst) { filehdr_dst->f_magic = bfd_h_get_x(abfd, filehdr_src->f_magic); filehdr_dst->f_nscns = bfd_h_get_x(abfd,filehdr_src-> f_nscns); filehdr_dst->f_timdat = bfd_h_get_x(abfd,filehdr_src-> f_timdat); filehdr_dst->f_symptr = bfd_h_get_x(abfd,filehdr_src-> f_symptr); filehdr_dst->f_nsyms = bfd_h_get_x(abfd,filehdr_src-> f_nsyms); filehdr_dst->f_opthdr = bfd_h_get_x(abfd,filehdr_src-> f_opthdr); filehdr_dst->f_flags = bfd_h_get_x(abfd,filehdr_src-> f_flags); } static void DEFUN(swap_filehdr_out,(abfd, filehdr_in, filehdr_out), bfd *abfd AND struct internal_filehdr *filehdr_in AND FILHDR *filehdr_out) { bfd_h_put_x(abfd, filehdr_in->f_magic, filehdr_out->f_magic); bfd_h_put_x(abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); bfd_h_put_x(abfd, filehdr_in->f_timdat, filehdr_out->f_timdat); bfd_h_put_x(abfd, filehdr_in->f_symptr, filehdr_out->f_symptr); bfd_h_put_x(abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); bfd_h_put_x(abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr); bfd_h_put_x(abfd, filehdr_in->f_flags, filehdr_out->f_flags); } static void DEFUN(bfd_coff_swap_sym_in,(abfd, ext, in), bfd *abfd AND SYMENT *ext AND struct internal_syment *in) { if( ext->e.e_name[0] == 0) { in->_n._n_n._n_zeroes = 0; in->_n._n_n._n_offset = bfd_h_getlong(abfd, ext->e.e.e_offset); } else { memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN); } in->n_value = bfd_h_get_x(abfd, ext->e_value); in->n_scnum = bfd_h_get_x(abfd, ext->e_scnum); in->n_type = bfd_h_get_x(abfd, ext->e_type); in->n_sclass = bfd_h_get_x(abfd, ext->e_sclass); in->n_numaux = bfd_h_get_x(abfd, ext->e_numaux); } static void DEFUN(bfd_coff_swap_sym_out,(abfd,in, ext), bfd *abfd AND struct internal_syment *in AND SYMENT *ext) { if(in->_n._n_name[0] == 0) { bfd_h_putlong(abfd, 0, ext->e.e.e_zeroes); bfd_h_putlong(abfd, in->_n._n_n._n_offset, ext->e.e.e_offset); } else { memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN); } bfd_h_put_x(abfd, in->n_value , ext->e_value); bfd_h_put_x(abfd, in->n_scnum , ext->e_scnum); bfd_h_put_x(abfd, in->n_type , ext->e_type); bfd_h_put_x(abfd, in->n_sclass , ext->e_sclass); bfd_h_put_x(abfd, in->n_numaux , ext->e_numaux); } static void DEFUN(bfd_coff_swap_aux_in,(abfd, ext, type, class, in), bfd *abfd AND AUXENT *ext AND int type AND int class AND union internal_auxent *in) { switch (class) { case C_FILE: if (ext->x_file.x_fname[0] == 0) { in->x_file.x_n.x_zeroes = 0; in->x_file.x_n.x_offset = bfd_h_getlong(abfd, ext->x_file.x_n.x_offset); } break; case C_STAT: #ifdef C_LEAFSTAT case C_LEAFSTAT: #endif case C_HIDDEN: if (type == T_NULL) { in->x_scn.x_scnlen = bfd_h_get_x(abfd, ext->x_scn.x_scnlen); in->x_scn.x_nreloc = bfd_h_get_x(abfd, ext->x_scn.x_nreloc); in->x_scn.x_nlinno = bfd_h_get_x(abfd, ext->x_scn.x_nlinno); break; } default: in->x_sym.x_tagndx = bfd_h_get_x(abfd, ext->x_sym.x_tagndx); in->x_sym.x_tvndx = bfd_h_get_x(abfd, ext->x_sym.x_tvndx); if (ISARY(type) || class == C_BLOCK) { in->x_sym.x_fcnary.x_ary.x_dimen[0] = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]); in->x_sym.x_fcnary.x_ary.x_dimen[1] = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]); in->x_sym.x_fcnary.x_ary.x_dimen[2] = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]); in->x_sym.x_fcnary.x_ary.x_dimen[3] = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]); } else { in->x_sym.x_fcnary.x_fcn.x_lnnoptr = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr); in->x_sym.x_fcnary.x_fcn.x_endndx = bfd_h_get_x(abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx); } if (ISFCN(type)) { in->x_sym.x_misc.x_fsize = bfd_h_get_x(abfd, ext->x_sym.x_misc.x_fsize); } else { in->x_sym.x_misc.x_lnsz.x_lnno = bfd_h_get_x(abfd, ext->x_sym.x_misc.x_lnsz.x_lnno); in->x_sym.x_misc.x_lnsz.x_size = bfd_h_get_x(abfd, ext->x_sym.x_misc.x_lnsz.x_size); } } } static void DEFUN(bfd_coff_swap_aux_out,(abfd, in, type, class, ext), bfd *abfd AND union internal_auxent *in AND int type AND int class AND AUXENT *ext) { switch (class) { case C_FILE: if (in->x_file.x_fname[0] == 0) { bfd_h_put_x(abfd, 0, ext->x_file.x_n.x_zeroes ); bfd_h_put_x(abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset); } break; case C_STAT: #ifdef C_LEAFSTAT case C_LEAFSTAT: #endif case C_HIDDEN: if (type == T_NULL) { bfd_h_put_x(abfd, in->x_scn.x_scnlen, ext->x_scn.x_scnlen); bfd_h_put_x(abfd, in->x_scn.x_nreloc, ext->x_scn.x_nreloc); bfd_h_put_x(abfd, in->x_scn.x_nlinno, ext->x_scn.x_nlinno); break; } default: bfd_h_put_x(abfd, in->x_sym.x_tagndx, ext->x_sym.x_tagndx); bfd_h_put_x(abfd, in->x_sym.x_tvndx , ext->x_sym.x_tvndx); if (ISARY(type) || class == C_BLOCK) { bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],ext->x_sym.x_fcnary.x_ary.x_dimen[0]); bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],ext->x_sym.x_fcnary.x_ary.x_dimen[1]); bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],ext->x_sym.x_fcnary.x_ary.x_dimen[2]); bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],ext->x_sym.x_fcnary.x_ary.x_dimen[3]); } else { bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr); bfd_h_put_x(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx, ext->x_sym.x_fcnary.x_fcn.x_endndx); } if (ISFCN(type)) { bfd_h_put_x(abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize); } else { bfd_h_put_x(abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext->x_sym.x_misc.x_lnsz.x_lnno); bfd_h_put_x(abfd, in->x_sym.x_misc.x_lnsz.x_size, ext->x_sym.x_misc.x_lnsz.x_size); } } } static void DEFUN(bfd_coff_swap_lineno_in,(abfd, ext, in), bfd *abfd AND LINENO *ext AND struct internal_lineno *in) { in->l_addr.l_symndx = bfd_h_get_x(abfd, ext->l_addr.l_symndx); in->l_lnno = bfd_h_get_x(abfd, ext->l_lnno); } static void DEFUN(bfd_coff_swap_lineno_out,(abfd, in, ext), bfd *abfd AND struct internal_lineno *in AND struct external_lineno *ext) { bfd_h_put_x(abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx); bfd_h_put_x(abfd, in->l_lnno, ext->l_lnno); } static void DEFUN(swap_aouthdr_in,(abfd, aouthdr_ext, aouthdr_int), bfd *abfd AND AOUTHDR *aouthdr_ext AND struct internal_aouthdr *aouthdr_int) { aouthdr_int->magic = bfd_h_get_x(abfd, aouthdr_ext->magic); aouthdr_int->vstamp = bfd_h_get_x(abfd, aouthdr_ext->vstamp); aouthdr_int->tsize = bfd_h_get_x(abfd, aouthdr_ext->tsize); aouthdr_int->dsize = bfd_h_get_x(abfd, aouthdr_ext->dsize); aouthdr_int->bsize = bfd_h_get_x(abfd, aouthdr_ext->bsize); aouthdr_int->entry = bfd_h_get_x(abfd, aouthdr_ext->entry); aouthdr_int->text_start = bfd_h_get_x(abfd, aouthdr_ext->text_start); aouthdr_int->data_start = bfd_h_get_x(abfd, aouthdr_ext->data_start); #ifdef I960 aouthdr_int->tagentries = bfd_h_get_x(abfd, aouthdr_ext->tagentries); #endif } static void DEFUN(swap_aouthdr_out,(abfd, aouthdr_in, aouthdr_out), bfd *abfd AND struct internal_aouthdr *aouthdr_in AND AOUTHDR *aouthdr_out) { bfd_h_put_x(abfd, aouthdr_in->magic, aouthdr_out->magic); bfd_h_put_x(abfd, aouthdr_in->vstamp, aouthdr_out->vstamp); bfd_h_put_x(abfd, aouthdr_in->tsize, aouthdr_out->tsize); bfd_h_put_x(abfd, aouthdr_in->dsize, aouthdr_out->dsize); bfd_h_put_x(abfd, aouthdr_in->bsize, aouthdr_out->bsize); bfd_h_put_x(abfd, aouthdr_in->entry, aouthdr_out->entry); bfd_h_put_x(abfd, aouthdr_in->text_start, aouthdr_out->text_start); bfd_h_put_x(abfd, aouthdr_in->data_start, aouthdr_out->data_start); #ifdef I960 bfd_h_put_x(abfd, aouthdr_in->tagentries, aouthdr_out->tagentries); #endif } static void DEFUN(swap_scnhdr_in,(abfd, scnhdr_ext, scnhdr_int), bfd *abfd AND SCNHDR *scnhdr_ext AND struct internal_scnhdr *scnhdr_int) { memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof(scnhdr_int->s_name)); scnhdr_int->s_vaddr = bfd_h_get_x(abfd, scnhdr_ext->s_vaddr); scnhdr_int->s_paddr = bfd_h_get_x(abfd, scnhdr_ext->s_paddr); scnhdr_int->s_size = bfd_h_get_x(abfd, scnhdr_ext->s_size); scnhdr_int->s_scnptr = bfd_h_get_x(abfd, scnhdr_ext->s_scnptr); scnhdr_int->s_relptr = bfd_h_get_x(abfd, scnhdr_ext->s_relptr); scnhdr_int->s_lnnoptr = bfd_h_get_x(abfd, scnhdr_ext->s_lnnoptr); scnhdr_int->s_nreloc = bfd_h_get_x(abfd, scnhdr_ext->s_nreloc); scnhdr_int->s_nlnno = bfd_h_get_x(abfd, scnhdr_ext->s_nlnno); scnhdr_int->s_flags = bfd_h_get_x(abfd, scnhdr_ext->s_flags); #ifdef I960 scnhdr_int->s_align = bfd_h_get_x(abfd, scnhdr_ext->s_align); #endif } static void DEFUN(swap_scnhdr_out,(abfd, scnhdr_int, scnhdr_ext), bfd *abfd AND struct internal_scnhdr *scnhdr_int AND SCNHDR *scnhdr_ext) { memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name)); bfd_h_put_x(abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr); bfd_h_put_x(abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr); bfd_h_put_x(abfd, scnhdr_int->s_size, scnhdr_ext->s_size); bfd_h_put_x(abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr); bfd_h_put_x(abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr); bfd_h_put_x(abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr); bfd_h_put_x(abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc); bfd_h_put_x(abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno); bfd_h_put_x(abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags); #ifdef I960 bfd_h_put_x(abfd, scnhdr_int->s_align, scnhdr_ext->s_align); #endif } /* initialize a section structure with information peculiar to this particular implementation of coff */ static boolean DEFUN(coff_new_section_hook,(abfd_ignore, section_ignore), bfd *abfd_ignore AND asection *section_ignore) { #ifdef MC88MAGIC /* FIXME, shouldn't this ifdef be on something that says we are actually COMPILING FOR an 88K coff file, rather than simply knowing its magic number? */ /* Align to at least 16 bytes */ section_ignore->alignment_power = 4; #endif #if M68 section_ignore->alignment_power = 3; #endif return true; } /* Take a section header read from a coff file (in HOST byte order), and make a BFD "section" out of it. */ static boolean DEFUN(make_a_section_from_file,(abfd, hdr), bfd *abfd AND struct internal_scnhdr *hdr) { asection *return_section; { /* Assorted wastage to null-terminate the name, thanks AT&T! */ char *name = bfd_alloc(abfd, sizeof (hdr->s_name)+1); if (name == NULL) { bfd_error = no_memory; return false; } strncpy(name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); name[sizeof (hdr->s_name)] = 0; return_section = bfd_make_section(abfd, name); } /* s_paddr is presumed to be = to s_vaddr */ #define assign(to, from) return_section->to = hdr->from assign(vma, s_vaddr); /* assign (vma, s_vaddr); */ assign(size, s_size); assign(filepos, s_scnptr); assign(rel_filepos, s_relptr); assign(reloc_count, s_nreloc); #ifdef I960 { /* FIXME, use a temp var rather than alignment_power */ assign(alignment_power, s_align); { unsigned int i; for (i = 0; i < 32; i++) { if ((1 << i) >= (int) (return_section->alignment_power)) { return_section->alignment_power = i; break; } } } } #endif assign(line_filepos, s_lnnoptr); /* return_section->linesize = hdr->s_nlnno * sizeof (struct lineno); */ #undef assign return_section->lineno_count = hdr->s_nlnno; return_section->userdata = NULL; return_section->next = (asection *) NULL; if ((hdr->s_flags & STYP_TEXT) || (hdr->s_flags & STYP_DATA)) return_section->flags = (SEC_LOAD | SEC_ALLOC); else if (hdr->s_flags & STYP_BSS) return_section->flags = SEC_ALLOC; if (hdr->s_nreloc != 0) return_section->flags |= SEC_RELOC; if (hdr->s_scnptr != 0) return_section->flags |= SEC_HAS_CONTENTS; return true; } static boolean DEFUN(coff_mkobject,(abfd), bfd *abfd) { set_tdata (abfd, bfd_zalloc (abfd,sizeof(coff_data_type))); if (coff_data(abfd) == 0) { bfd_error = no_memory; return false; } coff_data(abfd)->relocbase = 0; return true; } static bfd_target * DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), bfd *abfd AND unsigned nscns AND struct internal_filehdr *internal_f AND struct internal_aouthdr *internal_a) { coff_data_type *coff; size_t readsize; /* length of file_info */ SCNHDR *external_sections; /* Build a play area */ if (coff_mkobject(abfd) != true) return 0; coff = coff_data(abfd); external_sections = (SCNHDR *)bfd_alloc(abfd, readsize = (nscns * SCNHSZ)); if (bfd_read((PTR)external_sections, 1, readsize, abfd) != readsize) { goto fail; } /* Now copy data as required; construct all asections etc */ coff->symbol_index_slew = 0; coff->relocbase =0; coff->raw_syment_count = 0; coff->raw_linenos = 0; coff->raw_syments = 0; coff->sym_filepos =0; coff->flags = internal_f->f_flags; if (nscns != 0) { unsigned int i; for (i = 0; i < nscns; i++) { struct internal_scnhdr tmp; swap_scnhdr_in(abfd, external_sections + i, &tmp); make_a_section_from_file(abfd,&tmp); } } /* Determine the machine architecture and type. */ abfd->obj_machine = 0; switch (internal_f->f_magic) { #ifdef MIPS #ifdef MIPSEBMAGIC case SMIPSEBMAGIC: case SMIPSELMAGIC: case MIPSEBUMAGIC: case MIPSELUMAGIC: case MIPSEBMAGIC: case MIPSELMAGIC: abfd->obj_arch = bfd_arch_mips; abfd->obj_machine = 0; break; #endif #endif #ifdef MC68MAGIC case MC68MAGIC: case M68MAGIC: abfd->obj_arch = bfd_arch_m68k; abfd->obj_machine = 68020; break; #endif #ifdef MC88MAGIC case MC88MAGIC: case MC88DMAGIC: case MC88OMAGIC: abfd->obj_arch = bfd_arch_m88k; abfd->obj_machine = 88100; break; #endif #ifdef I960 #ifdef I960ROMAGIC case I960ROMAGIC: case I960RWMAGIC: abfd->obj_arch = bfd_arch_i960; switch (F_I960TYPE & internal_f->f_flags) { default: case F_I960CORE: abfd->obj_machine = bfd_mach_i960_core; break; case F_I960KB: abfd->obj_machine = bfd_mach_i960_kb_sb; break; case F_I960MC: abfd->obj_machine = bfd_mach_i960_mc; break; case F_I960XA: abfd->obj_machine = bfd_mach_i960_xa; break; case F_I960CA: abfd->obj_machine = bfd_mach_i960_ca; break; case F_I960KA: abfd->obj_machine = bfd_mach_i960_ka_sa; break; } break; #endif #endif default: /* Unreadable input file type */ abfd->obj_arch = bfd_arch_obscure; break; } if (!(internal_f->f_flags & F_RELFLG)) abfd->flags |= HAS_RELOC; if ((internal_f->f_flags & F_EXEC)) abfd->flags |= EXEC_P; if (!(internal_f->f_flags & F_LNNO)) abfd->flags |= HAS_LINENO; if (!(internal_f->f_flags & F_LSYMS)) abfd->flags |= HAS_LOCALS; bfd_get_symcount(abfd) = internal_f->f_nsyms; if (internal_f->f_nsyms) abfd->flags |= HAS_SYMS; coff->sym_filepos = internal_f->f_symptr; coff->symbols = (coff_symbol_type *) NULL; bfd_get_start_address(abfd) = internal_f->f_opthdr ? internal_a->entry : 0; return abfd->xvec; fail: bfd_release(abfd, coff); return (bfd_target *)NULL; } static bfd_target * DEFUN(coff_object_p,(abfd), bfd *abfd) { int nscns; FILHDR filehdr; AOUTHDR opthdr; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; bfd_error = system_call_error; /* figure out how much to read */ if (bfd_read((PTR) &filehdr, 1, FILHSZ, abfd) != FILHSZ) return 0; swap_filehdr_in(abfd, &filehdr, &internal_f); if (BADMAG(internal_f)) { bfd_error = wrong_format; return 0; } nscns =internal_f.f_nscns; if (internal_f.f_opthdr) { if (bfd_read((PTR) &opthdr, 1,AOUTSZ, abfd) != AOUTSZ) { return 0; } swap_aouthdr_in(abfd, &opthdr, &internal_a); } /* Seek past the opt hdr stuff */ bfd_seek(abfd, internal_f.f_opthdr + FILHSZ, SEEK_SET); /* if the optional header is NULL or not the correct size then quit; the only difference I can see between m88k dgux headers (MC88DMAGIC) and Intel 960 readwrite headers (I960WRMAGIC) is that the optional header is of a different size. But the mips keeps extra stuff in it's opthdr, so dont check when doing that */ #ifndef MIPS if (internal_f.f_opthdr != 0 && AOUTSZ != internal_f.f_opthdr) return (bfd_target *)NULL; #endif return coff_real_object_p(abfd, nscns, &internal_f, &internal_a); }