bout.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,528 行 · 第 1/3 页

C
1,528
字号
static booleanb_out_slurp_reloc_table (abfd, asect, symbols)     bfd *abfd;     sec_ptr asect;     asymbol **symbols;{  register struct relocation_info *rptr;  unsigned int counter ;  arelent *cache_ptr ;  int extern_mask, pcrel_mask, callj_mask, length_shift;  int incode_mask;  int size_mask;  bfd_vma prev_addr = 0;  unsigned int count;  size_t  reloc_size;  struct relocation_info *relocs;  arelent *reloc_cache;  if (asect->relocation)    return true;  if (!aout_32_slurp_symbol_table (abfd))    return false;  if (asect == obj_datasec (abfd)) {    reloc_size = exec_hdr(abfd)->a_drsize;    goto doit;  }  if (asect == obj_textsec (abfd)) {    reloc_size = exec_hdr(abfd)->a_trsize;    goto doit;  }  if (asect == obj_bsssec (abfd)) {    reloc_size = 0;    goto doit;  }  bfd_set_error (bfd_error_invalid_operation);  return false; doit:  if (bfd_seek (abfd, (file_ptr) (asect->rel_filepos),  SEEK_SET) != 0)    return false;  count = reloc_size / sizeof (struct relocation_info);  relocs = (struct relocation_info *) bfd_malloc (reloc_size);  if (!relocs && reloc_size != 0)    return false;  reloc_cache = (arelent *) bfd_malloc ((count+1) * sizeof (arelent));  if (!reloc_cache) {    if (relocs != NULL)      free ((char*)relocs);    return false;  }  if (bfd_read ((PTR) relocs, 1, reloc_size, abfd) != reloc_size) {    free (reloc_cache);    if (relocs != NULL)      free (relocs);    return false;  }  if (bfd_header_big_endian (abfd)) {    /* big-endian bit field allocation order */    pcrel_mask  = 0x80;    extern_mask = 0x10;    incode_mask = 0x08;    callj_mask  = 0x02;    size_mask =   0x20;    length_shift = 5;  } else {    /* little-endian bit field allocation order */    pcrel_mask  = 0x01;    extern_mask = 0x08;    incode_mask = 0x10;    callj_mask  = 0x40;    size_mask   = 0x02;    length_shift = 1;  }  for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;       counter < count;       counter++, rptr++, cache_ptr++)  {    unsigned char *raw = (unsigned char *)rptr;    unsigned int symnum;    cache_ptr->address = bfd_h_get_32 (abfd, raw + 0);    cache_ptr->howto = 0;    if (bfd_header_big_endian (abfd))    {      symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];    }    else    {      symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4];    }    if (raw[7] & extern_mask)    {      /* if this is set then the r_index is a index into the symbol table;       * if the bit is not set then r_index contains a section map.       * we either fill in the sym entry with a pointer to the symbol,       * or point to the correct section       */      cache_ptr->sym_ptr_ptr = symbols + symnum;      cache_ptr->addend = 0;    } else    {      /* in a.out symbols are relative to the beginning of the       * file rather than sections ?       * (look in translate_from_native_sym_flags)       * the reloc entry addend has added to it the offset into the       * file of the data, so subtract the base to make the reloc       * section relative */      int s;      {	/* sign-extend symnum from 24 bits to whatever host uses */	s = symnum;	if (s & (1 << 23))	  s |= (~0) << 24;      }      cache_ptr->sym_ptr_ptr = (asymbol **)NULL;      switch (s)      {       case N_TEXT:       case N_TEXT | N_EXT:	cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr;	cache_ptr->addend = - obj_textsec(abfd)->vma;	break;       case N_DATA:       case N_DATA | N_EXT:	cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr;	cache_ptr->addend = - obj_datasec(abfd)->vma;	break;       case N_BSS:       case N_BSS | N_EXT:	cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;	cache_ptr->addend =  - obj_bsssec(abfd)->vma;	break;       case N_ABS:       case N_ABS | N_EXT:	cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;	cache_ptr->addend = 0;	break;      case -2: /* .align */	if (raw[7] & pcrel_mask)	  {	    cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];	    cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	  }	else	  {	    /* .org? */	    abort ();	  }	cache_ptr->addend = 0;	break;       default:	BFD_ASSERT(0);	break;      }    }    /* the i960 only has a few relocation types:       abs 32-bit and pcrel 24bit.   except for callj's!  */    if (cache_ptr->howto != 0)      ;    else if (raw[7] & callj_mask)    {      cache_ptr->howto = &howto_reloc_callj;    }    else if ( raw[7] & pcrel_mask)    {      if (raw[7] & size_mask)       cache_ptr->howto = &howto_reloc_pcrel13;      else       cache_ptr->howto = &howto_reloc_pcrel24;    }    else    {      if (raw[7] & incode_mask)      {	cache_ptr->howto = &howto_reloc_abs32code;      }      else      {	cache_ptr->howto = &howto_reloc_abs32;      }    }    if (cache_ptr->address < prev_addr)    {      /* Ouch! this reloc is out of order, insert into the right place       */      arelent tmp;      arelent *cursor = cache_ptr-1;      bfd_vma stop = cache_ptr->address;      tmp  = *cache_ptr;      while (cursor->address > stop && cursor >= reloc_cache)      {	cursor[1] = cursor[0];	cursor--;      }      cursor[1] = tmp;    }    else    {      prev_addr = cache_ptr->address;    }  }  if (relocs != NULL)    free (relocs);  asect->relocation = reloc_cache;  asect->reloc_count = count;  return true;}static booleanb_out_squirt_out_relocs (abfd, section)     bfd *abfd;     asection *section;{  arelent **generic;  int r_extern = 0;  int r_idx;  int incode_mask;  int len_1;  unsigned int count = section->reloc_count;  struct relocation_info *native, *natptr;  size_t natsize = count * sizeof (struct relocation_info);  int extern_mask, pcrel_mask,  len_2, callj_mask;  if (count == 0) return true;  generic   = section->orelocation;  native = ((struct relocation_info *) bfd_malloc (natsize));  if (!native && natsize != 0)    return false;  if (bfd_header_big_endian (abfd))  {    /* Big-endian bit field allocation order */    pcrel_mask  = 0x80;    extern_mask = 0x10;    len_2       = 0x40;    len_1       = 0x20;    callj_mask  = 0x02;    incode_mask = 0x08;  }  else  {    /* Little-endian bit field allocation order */    pcrel_mask  = 0x01;    extern_mask = 0x08;    len_2       = 0x04;    len_1       = 0x02;    callj_mask  = 0x40;    incode_mask = 0x10;  }  for (natptr = native; count > 0; --count, ++natptr, ++generic)  {    arelent *g = *generic;    unsigned char *raw = (unsigned char *)natptr;    asymbol *sym = *(g->sym_ptr_ptr);    asection *output_section = sym->section->output_section;    bfd_h_put_32(abfd, g->address, raw);    /* Find a type in the output format which matches the input howto -     * at the moment we assume input format == output format FIXME!!     */    r_idx = 0;    /* FIXME:  Need callj stuff here, and to check the howto entries to       be sure they are real for this architecture.  */    if (g->howto== &howto_reloc_callj)    {      raw[7] = callj_mask + pcrel_mask + len_2;    }    else if (g->howto == &howto_reloc_pcrel24)    {      raw[7] = pcrel_mask + len_2;    }    else if (g->howto == &howto_reloc_pcrel13)    {      raw[7] = pcrel_mask + len_1;    }    else if (g->howto == &howto_reloc_abs32code)    {      raw[7] = len_2 + incode_mask;    }    else if (g->howto >= howto_align_table	     && g->howto <= (howto_align_table			    + sizeof (howto_align_table) / sizeof (howto_align_table[0])			    - 1))      {	/* symnum == -2; extern_mask not set, pcrel_mask set */	r_idx = -2;	r_extern = 0;	raw[7] = (pcrel_mask		  | ((g->howto - howto_align_table) << 1));      }    else {      raw[7] = len_2;    }    if (r_idx != 0)      /* already mucked with r_extern, r_idx */;    else if (bfd_is_com_section (output_section)	     || bfd_is_abs_section (output_section)	     || bfd_is_und_section (output_section))    {      if (bfd_abs_section_ptr->symbol == sym)      {	/* Whoops, looked like an abs symbol, but is really an offset	   from the abs section */	r_idx = 0;	r_extern = 0;       }      else      {	/* Fill in symbol */	r_extern = 1;	r_idx = (*g->sym_ptr_ptr)->udata.i;      }    }    else    {      /* Just an ordinary section */      r_extern = 0;      r_idx  = output_section->target_index;    }    if (bfd_header_big_endian (abfd)) {      raw[4] = (unsigned char) (r_idx >> 16);      raw[5] = (unsigned char) (r_idx >>  8);      raw[6] = (unsigned char) (r_idx     );    } else {      raw[6] = (unsigned char) (r_idx >> 16);      raw[5] = (unsigned char) (r_idx>>  8);      raw[4] = (unsigned char) (r_idx     );    }    if (r_extern)     raw[7] |= extern_mask;  }  if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {    free((PTR)native);    return false;  }  free ((PTR)native);  return true;}/* This is stupid.  This function should be a boolean predicate */static longb_out_canonicalize_reloc (abfd, section, relptr, symbols)     bfd *abfd;     sec_ptr section;     arelent **relptr;     asymbol **symbols;{  arelent *tblptr;  unsigned int count;  if ((section->flags & SEC_CONSTRUCTOR) != 0)    {      arelent_chain *chain = section->constructor_chain;      for (count = 0; count < section->reloc_count; count++)	{	  *relptr++ = &chain->relent;	  chain = chain->next;	}    }  else    {      if (section->relocation == NULL	  && ! b_out_slurp_reloc_table (abfd, section, symbols))	return -1;      tblptr = section->relocation;      for (count = 0; count++ < section->reloc_count;)	*relptr++ = tblptr++;    }  *relptr = NULL;  return section->reloc_count;}static longb_out_get_reloc_upper_bound (abfd, asect)     bfd *abfd;     sec_ptr asect;{  if (bfd_get_format (abfd) != bfd_object) {    bfd_set_error (bfd_error_invalid_operation);    return -1;  }  if (asect->flags & SEC_CONSTRUCTOR)    return sizeof (arelent *) * (asect->reloc_count + 1);  if (asect == obj_datasec (abfd))    return (sizeof (arelent *) *	    ((exec_hdr(abfd)->a_drsize / sizeof (struct relocation_info))	     +1));  if (asect == obj_textsec (abfd))    return (sizeof (arelent *) *	    ((exec_hdr(abfd)->a_trsize / sizeof (struct relocation_info))	     +1));  if (asect == obj_bsssec (abfd))    return 0;  bfd_set_error (bfd_error_invalid_operation);  return -1;}static booleanb_out_set_section_contents (abfd, section, location, offset, count)     bfd *abfd;     asection *section;     PTR location;     file_ptr offset;     bfd_size_type count;{  if (abfd->output_has_begun == false) { /* set by bfd.c handler */    if (! aout_32_make_sections (abfd))      return false;    obj_textsec (abfd)->filepos = sizeof (struct internal_exec);    obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos                                 +  obj_textsec (abfd)->_raw_size;  }  /* regardless, once we know what we're doing, we might as well get going */  if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)    return false;  if (count != 0) {    return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;  }  return true;}static booleanb_out_set_arch_mach (abfd, arch, machine)     bfd *abfd;     enum bfd_architecture arch;     unsigned long machine;{  bfd_default_set_arch_mach(abfd, arch, machine);  if (arch == bfd_arch_unknown)	/* Unknown machine arch is OK */    return true;  if (arch == bfd_arch_i960)	/* i960 default is OK */    switch (machine) {    case bfd_mach_i960_core:    case bfd_mach_i960_kb_sb:    case bfd_mach_i960_mc:    case bfd_mach_i960_xa:    case bfd_mach_i960_ca:    case bfd_mach_i960_ka_sa:    case bfd_mach_i960_jx:    case bfd_mach_i960_hx:    case 0:      return true;    default:      return false;    }  return false;}static intb_out_sizeof_headers (ignore_abfd, ignore)     bfd *ignore_abfd ATTRIBUTE_UNUSED;     boolean ignore ATTRIBUTE_UNUSED;{  return sizeof (struct internal_exec);}/************************************************************************/static bfd_vmaget_value (reloc, link_info, input_section)     arelent *reloc;     struct bfd_link_info *link_info;     asection *input_section;{  bfd_vma value;  asymbol *symbol = *(reloc->sym_ptr_ptr);  /* A symbol holds a pointer to a section, and an offset from the     base of the section.  To relocate, we find where the section will     live in the output and add that in */  if (bfd_is_und_section (symbol->section))    {      struct bfd_link_hash_entry *h;      /* The symbol is undefined in this BFD.  Look it up in the	 global linker hash table.  FIXME: This should be changed when	 we convert b.out to use a specific final_link function and

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?