relocs = (struct relocation_info *) malloc (reloc_size); if (!relocs && reloc_size != 0) { bfd_set_error (bfd_error_no_memory); return false; } reloc_cache = (arelent *) malloc ((count+1) * sizeof (arelent));
relocs = (struct relocation_info *) bfd_malloc (reloc_size); if (!relocs && reloc_size != 0) return false; reloc_cache = (arelent *) bfd_malloc ((count+1) * sizeof (arelent));
b_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 *) malloc (reloc_size);  if (!relocs && reloc_size != 0) {    bfd_set_error (bfd_error_no_memory);    return false;  }  reloc_cache = (arelent *) malloc ((count+1) * sizeof (arelent));  if (!reloc_cache) {    if (relocs != NULL)      free ((char*)relocs);    bfd_set_error (bfd_error_no_memory);    return false;  }  if (bfd_read ((PTR) relocs, 1, reloc_size, abfd) != reloc_size) {    free (reloc_cache);    if (relocs != NULL)      free (relocs);    return false;  }  if (abfd->xvec->header_byteorder_big_p) {    /* 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 (abfd->xvec->header_byteorder_big_p)    {      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;}