Beispiel #1
0
asm_program_t*
byte_insn_to_asmp(bfd_architecture arch, address_t addr, unsigned char *bb_bytes, unsigned int len)
{
  asm_program_t *prog = asmir_new_asmp_for_arch(arch);
  unsigned char *bytes = (unsigned char*)bfd_alloc(prog->abfd, len);
  assert(bytes);
  // copy the string, because the old one is freed when we return
  memcpy(bytes, bb_bytes, len);
  section_t *sec = (section_t*)bfd_alloc(prog->abfd, sizeof(section_t));
  assert(sec);
  
  sec->start_addr = addr;
  sec->datasize = len;
  sec->end_addr = addr+len;
  sec->data = bytes;
  sec->is_code = 1;
  sec->next = NULL;
  prog->segs = sec;

  struct disassemble_info *disasm_info = &prog->disasm_info;
  disasm_info->buffer = bytes;
  disasm_info->buffer_vma = addr;
  disasm_info->buffer_length = len;
  disasm_info->section = NULL;

  return prog;
}
Beispiel #2
0
asm_program_t*
byte_insn_to_asmp(bfd_architecture arch, address_t addr, unsigned char *bb_bytes, unsigned int len)
{
  asm_program_t *prog = fake_prog_for_arch(arch);
  unsigned char *bytes = (unsigned char*)bfd_alloc(prog->abfd, len);
  // copy the string, because the old one is freed when we return
  memcpy(bytes, bb_bytes, len);
  Instruction *inst = new Instruction;

  inst->address = addr;
  inst->length = len;
  inst->bytes = bytes;

  struct disassemble_info *disasm_info = &prog->disasm_info;
  disasm_info->buffer = bytes;
  disasm_info->buffer_vma = addr;
  disasm_info->buffer_length = len;
  disasm_info->section = NULL;

  asm_function_t *asmf = new asm_function_t;
  asmf->name = "";
  asmf->start_addr = addr;
  asmf->end_addr = addr+len;
  asmf->instmap[addr] = inst;
  
  prog->functions[addr] = asmf;
      
  return prog;
}
static asection *
make_bfd_asection (bfd *abfd, const char *name, flagword flags,
                   bfd_size_type size, bfd_vma vma,
                   unsigned int alignment_power)
{
  asection *asect;
  char *newname;

  newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
  if (!newname)
    return NULL;

  strcpy (newname, name);

  asect = bfd_make_section_anyway_with_flags (abfd, newname, flags);
  if (!asect)
    return NULL;

  asect->size = size;
  asect->vma = vma;
  asect->filepos = bfd_tell (abfd);
  asect->alignment_power = alignment_power;

  return asect;
}
Beispiel #4
0
static bfd_boolean
oasys_mkobject (bfd *abfd)
{
  bfd_size_type amt = sizeof (oasys_data_type);

  abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt);

  return abfd->tdata.oasys_obj_data != NULL;
}
Beispiel #5
0
/* Duplicate an object attribute string value.  */
char *
_bfd_elf_attr_strdup (bfd *abfd, const char * s)
{
  char * p;
  int len;

  len = strlen (s) + 1;
  p = (char *) bfd_alloc (abfd, len);
  return (char *) memcpy (p, s, len);
}
Beispiel #6
0
bfd_vma asmir_get_base_address(asm_program_t *prog) {
#if SIZEOF_BFD_VMA == 4
  bfd_vma lowest = LONG_MAX;
#else
  bfd_vma lowest = LLONG_MAX;
#endif
  assert(prog);
  bfd *abfd = prog->abfd;
  asection *section;

  if (bfd_get_flavour(abfd) ==  bfd_target_elf_flavour) {

    /* BFD has some issues with ELF files.  ELF files have both
       sections and segments ("program headers").  We really care
       about the lowest address of program segments, but BFD only
       shows sections when an ELF file contains both. So, we need to
       use ELF-specific functions to learn the segment address, which
       is typically different than the section address. */
      int i, is_nice;
      size_t ubound = bfd_get_elf_phdr_upper_bound(abfd);
      Elf_Internal_Phdr *phdrs = bfd_alloc(abfd, ubound);
      if (phdrs == NULL) { bfd_perror(NULL); assert(0); }
      int n = bfd_get_elf_phdrs(abfd, phdrs);
      if (n == -1) { bfd_perror(NULL); assert(0); }

      for (i = 0; i < n; i++) {
        /*
        fprintf(stderr, "VA: %#" BFD_VMA_FMT "x Align: %#" BFD_VMA_FMT "x Aligned: %#" BFD_VMA_FMT "x p_flags: %#" BFD_VMA_FMT "x p_type: %#"BFD_VMA_FMT "x\n", 
            phdrs[i].p_vaddr, 
            phdrs[i].p_align, 
            phdrs[i].p_vaddr & (~(phdrs[i].p_align)), 
            phdrs[i].p_flags, 
            phdrs[i].p_type);
        */
        bfd_vma aligned = phdrs[i].p_vaddr & (~(phdrs[i].p_align));
        /* STACK segment has vaddr=paddr=0. If we don't ignore it, imagebase=0*/
        is_nice = (phdrs[i].p_flags & SHT_PROGBITS) && 
                (phdrs[i].p_type != PT_GNU_STACK);
        if (is_nice && aligned < lowest) { lowest = aligned; }
      }
    } else {

      /* Non-ELF files */
      for (section = abfd->sections; section; section = section->next) {
        /* fprintf(stderr, "Section %s, vma %Lx\n", section->name, section->vma); */
        if ((section->vma < lowest) && (section->flags & SEC_LOAD)) { lowest = section->vma; }
      }
    }

  //fprintf(stderr, "Lowest section is %#" BFD_VMA_FMT "x\n", lowest);
  //fprintf(stderr, "Adjusting by %Lx\n", offset);

  return lowest;
}
Beispiel #7
0
void
gdb_bfd_stash_filename (struct bfd *abfd)
{
  char *name = bfd_get_filename (abfd);
  char *data;

  data = bfd_alloc (abfd, strlen (name) + 1);
  strcpy (data, name);

  /* Unwarranted chumminess with BFD.  */
  abfd->filename = data;
}
Beispiel #8
0
static char *
plugin_strdup (bfd *abfd, const char *str)
{
    size_t strlength;
    char *copy;
    strlength = strlen (str) + 1;
    copy = bfd_alloc (abfd, strlength);
    if (copy == NULL)
        einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"),
               bfd_get_error ());
    memcpy (copy, str, strlength);
    return copy;
}
Beispiel #9
0
static void
initialize_sections(asm_program_t *prog, bfd_vma base)
{
  bfd_vma offset = 0;
  struct disassemble_info *disasm_info = &prog->disasm_info;
  assert(prog);
  bfd *abfd = prog->abfd;
  unsigned int opb = bfd_octets_per_byte(abfd);
  disasm_info->octets_per_byte = opb;
  init_disasm_info(prog);
  section_t **nextseg = &prog->segs;
  asection *section;

  /* Set to NULL in case there are zero segments. */
  *nextseg = NULL;

  /* Look for the section loaded into the lowest memory address */
  if (base != -1) {

    offset = base - asmir_get_base_address(prog);
    //fprintf(stderr, "Adjusting by %Lx\n", offset);
  }

  for(section = abfd->sections; section; section = section->next) {
    section_t *seg;
    bfd_byte *data;
    bfd_vma datasize = bfd_get_section_size_before_reloc(section);

    if(datasize == 0) continue;

    section->vma += offset;
    data = bfd_alloc2(abfd, datasize, sizeof(bfd_byte));
    bfd_get_section_contents(abfd, section, data, 0, datasize);
    seg = bfd_alloc(abfd, sizeof(section_t));
    seg->data = data;
    seg->datasize = datasize;
    seg->start_addr = section->vma;
    seg->end_addr = section->vma + datasize/opb;
    seg->section = section;
    seg->is_code = !!(section->flags & SEC_CODE);


    seg->next = NULL;
    *nextseg = seg;
    nextseg = &seg->next;
  }

}
Beispiel #10
0
static bfd_boolean
bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
{
  preserve->tdata = abfd->tdata.any;
  preserve->arch_info = abfd->arch_info;
  preserve->flags = abfd->flags;
  preserve->sections = abfd->sections;
  preserve->section_last = abfd->section_last;
  preserve->section_count = abfd->section_count;
  preserve->section_htab = abfd->section_htab;
  preserve->marker = bfd_alloc (abfd, 1);
  if (preserve->marker == NULL)
    return FALSE;

  return bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
			      sizeof (struct section_hash_entry));
}
Beispiel #11
0
static bfd_boolean
versados_mkobject (bfd *abfd)
{
  if (abfd->tdata.versados_data == NULL)
    {
      bfd_size_type amt = sizeof (tdata_type);
      tdata_type *tdata = bfd_alloc (abfd, amt);

      if (tdata == NULL)
	return FALSE;
      abfd->tdata.versados_data = tdata;
      tdata->symbols = NULL;
      VDATA (abfd)->alert = 0x12345678;
    }

  bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
  return TRUE;
}
Beispiel #12
0
static enum ld_plugin_status
add_symbols (void * handle,
	     int nsyms,
	     const struct ld_plugin_symbol * syms)
{
  bfd *abfd = handle;
  struct plugin_data_struct *plugin_data =
    bfd_alloc (abfd, sizeof (plugin_data_struct));;

  plugin_data->nsyms = nsyms;
  plugin_data->syms = syms;

  if (nsyms != 0)
    abfd->flags |= HAS_SYMS;

  abfd->tdata.plugin_data = plugin_data;
  return LDPS_OK;
}
elf_property *
_bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
{
  elf_property_list *p, **lastp;

  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
    {
      /* Never should happen.  */
      abort ();
    }

  /* Keep the property list in order of type.  */
  lastp = &elf_properties (abfd);
  for (p = *lastp; p; p = p->next)
    {
      /* Reuse the existing entry.  */
      if (type == p->property.pr_type)
	{
	  if (datasz > p->property.pr_datasz)
	    {
	      /* This can happen when mixing 32-bit and 64-bit objects.  */
	      p->property.pr_datasz = datasz;
	    }
	  return &p->property;
	}
      else if (type < p->property.pr_type)
	break;
      lastp = &p->next;
    }
  p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
  if (p == NULL)
    {
      _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"),
			  abfd);
      _exit (EXIT_FAILURE);
    }
  memset (p, 0, sizeof (*p));
  p->property.pr_type = type;
  p->property.pr_datasz = datasz;
  p->next = *lastp;
  *lastp = p;
  return &p->property;
}
Beispiel #14
0
asection *
_bfd_elf_create_ifunc_dyn_reloc (bfd *abfd, struct bfd_link_info *info,
				 asection *sec, asection *sreloc,
				 struct elf_dyn_relocs **head)
{
  struct elf_dyn_relocs *p;
  struct elf_link_hash_table *htab = elf_hash_table (info);

  if (sreloc == NULL)
    {
      const struct elf_backend_data *bed = get_elf_backend_data (abfd);

      if (htab->dynobj == NULL)
	htab->dynobj = abfd;

      sreloc = _bfd_elf_make_dynamic_reloc_section (sec, htab->dynobj,
						    bed->s->log_file_align,
						    abfd,
						    bed->rela_plts_and_copies_p); 
      if (sreloc == NULL)
	return NULL;
    }
		      
  p = *head;
  if (p == NULL || p->sec != sec)
    {
      bfd_size_type amt = sizeof *p;

      p = ((struct elf_dyn_relocs *) bfd_alloc (htab->dynobj, amt));
      if (p == NULL)
	return NULL;
      p->next = *head;
      *head = p;
      p->sec = sec;
      p->count = 0;
      p->pc_count = 0;
    }
  p->count += 1;

  return sreloc;
}
Beispiel #15
0
static struct bfd_link_hash_table *
linux_link_hash_table_create (bfd *abfd)
{
  struct linux_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct linux_link_hash_table);

  ret = (struct linux_link_hash_table *) bfd_alloc (abfd, amt);
  if (ret == (struct linux_link_hash_table *) NULL)
    return (struct bfd_link_hash_table *) NULL;
  if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
					linux_link_hash_newfunc,
					sizeof (struct linux_link_hash_entry)))
    {
      free (ret);
      return (struct bfd_link_hash_table *) NULL;
    }

  ret->dynobj = NULL;
  ret->fixup_count = 0;
  ret->local_builtins = 0;
  ret->fixup_list = NULL;

  return &ret->root.root;
}
Beispiel #16
0
/* Allocate/find an object attribute.  */
static obj_attribute *
elf_new_obj_attr (bfd *abfd, int vendor, int tag)
{
  obj_attribute *attr;
  obj_attribute_list *list;
  obj_attribute_list *p;
  obj_attribute_list **lastp;


  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
    {
      /* Known tags are preallocated.  */
      attr = &elf_known_obj_attributes (abfd)[vendor][tag];
    }
  else
    {
      /* Create a new tag.  */
      list = (obj_attribute_list *)
	bfd_alloc (abfd, sizeof (obj_attribute_list));
      memset (list, 0, sizeof (obj_attribute_list));
      list->tag = tag;
      /* Keep the tag list in order.  */
      lastp = &elf_other_obj_attributes (abfd)[vendor];
      for (p = *lastp; p; p = p->next)
	{
	  if (tag < p->tag)
	    break;
	  lastp = &p->next;
	}
      list->next = *lastp;
      *lastp = list;
      attr = &list->attr;
    }

  return attr;
}
Beispiel #17
0
/* We permute the segment_map to get BFD to do the file layout we want:
   The first non-executable PT_LOAD segment appears first in the file
   and contains the ELF file header and phdrs.  */
bfd_boolean
nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
{
    const struct elf_backend_data *const bed = get_elf_backend_data (abfd);
    struct elf_segment_map **m = &elf_seg_map (abfd);
    struct elf_segment_map **first_load = NULL;
    struct elf_segment_map **last_load = NULL;
    bfd_boolean moved_headers = FALSE;
    int sizeof_headers;

    if (info != NULL && info->user_phdrs)
        /* The linker script used PHDRS explicitly, so don't change what the
           user asked for.  */
        return TRUE;

    if (info != NULL)
        /* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script.  */
        sizeof_headers = bfd_sizeof_headers (abfd, info);
    else
    {
        /* We're not doing linking, so this is objcopy or suchlike.
        We just need to collect the size of the existing headers.  */
        struct elf_segment_map *seg;
        sizeof_headers = bed->s->sizeof_ehdr;
        for (seg = *m; seg != NULL; seg = seg->next)
            sizeof_headers += bed->s->sizeof_phdr;
    }

    while (*m != NULL)
    {
        struct elf_segment_map *seg = *m;

        if (seg->p_type == PT_LOAD)
        {
            bfd_boolean executable = segment_executable (seg);

            if (executable
                    && seg->count > 0
                    && seg->sections[0]->vma % bed->minpagesize == 0)
            {
                asection *lastsec = seg->sections[seg->count - 1];
                bfd_vma end = lastsec->vma + lastsec->size;
                if (end % bed->minpagesize != 0)
                {
                    /* This is an executable segment that starts on a page
                       boundary but does not end on a page boundary.  Fill
                       it out to a whole page with code fill (the tail of
                       the segment will not be within any section).  Thus
                       the entire code segment can be mapped from the file
                       as whole pages and that mapping will contain only
                       valid instructions.

                       To accomplish this, we must fake out the code in
                       assign_file_positions_for_load_sections (elf.c) so
                       that it advances past the rest of the final page,
                       rather than trying to put the next (unaligned, or
                       unallocated) section.  We do this by appending a
                       dummy section record to this element in the segment
                       map.  No such output section ever actually exists,
                       but this gets the layout logic to advance the file
                       positions past this partial page.  Since we are
                       lying to BFD like this, nothing will ever know to
                       write the section contents.  So we do that by hand
                       after the fact, in nacl_final_write_processing, below.  */

                    struct elf_segment_map *newseg;
                    asection *sec;
                    struct bfd_elf_section_data *secdata;

                    BFD_ASSERT (!seg->p_size_valid);

                    secdata = bfd_zalloc (abfd, sizeof *secdata);
                    if (secdata == NULL)
                        return FALSE;

                    sec = bfd_zalloc (abfd, sizeof *sec);
                    if (sec == NULL)
                        return FALSE;

                    /* Fill in only the fields that actually affect the logic
                       in assign_file_positions_for_load_sections.  */
                    sec->vma = end;
                    sec->lma = lastsec->lma + lastsec->size;
                    sec->size = bed->minpagesize - (end % bed->minpagesize);
                    sec->flags = (SEC_ALLOC | SEC_LOAD
                                  | SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED);
                    sec->used_by_bfd = secdata;

                    secdata->this_hdr.sh_type = SHT_PROGBITS;
                    secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
                    secdata->this_hdr.sh_addr = sec->vma;
                    secdata->this_hdr.sh_size = sec->size;

                    newseg = bfd_alloc (abfd,
                                        sizeof *newseg + ((seg->count + 1)
                                                          * sizeof (asection *)));
                    if (newseg == NULL)
                        return FALSE;
                    memcpy (newseg, seg,
                            sizeof *newseg + (seg->count * sizeof (asection *)));
                    newseg->sections[newseg->count++] = sec;
                    *m = seg = newseg;
                }
            }

            /* First, we're just finding the earliest PT_LOAD.
               By the normal rules, this will be the lowest-addressed one.
               We only have anything interesting to do if it's executable.  */
            last_load = m;
            if (first_load == NULL)
            {
                if (!executable)
                    goto next;
                first_load = m;
            }
            /* Now that we've noted the first PT_LOAD, we're looking for
               the first non-executable PT_LOAD with a nonempty p_filesz.  */
            else if (!moved_headers
                     && segment_eligible_for_headers (seg, bed->minpagesize,
                             sizeof_headers))
            {
                /* This is the one we were looking for!

                First, clear the flags on previous segments that
                 say they include the file header and phdrs.  */
                struct elf_segment_map *prevseg;
                for (prevseg = *first_load;
                        prevseg != seg;
                        prevseg = prevseg->next)
                    if (prevseg->p_type == PT_LOAD)
                    {
                        prevseg->includes_filehdr = 0;
                        prevseg->includes_phdrs = 0;
                    }

                /* This segment will include those headers instead.  */
                seg->includes_filehdr = 1;
                seg->includes_phdrs = 1;

                moved_headers = TRUE;
            }
        }

next:
        m = &seg->next;
    }

    if (first_load != last_load && moved_headers)
    {
        /* Now swap the first and last PT_LOAD segments'
        positions in segment_map.  */
        struct elf_segment_map *first = *first_load;
        struct elf_segment_map *last = *last_load;
        *first_load = first->next;
        first->next = last->next;
        last->next = first;
    }

    return TRUE;
}
bfd_boolean
_bfd_discard_section_stabs (bfd *abfd,
			    asection *stabsec,
			    void * psecinfo,
			    bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
			    void * cookie)
{
  bfd_size_type count, amt;
  struct stab_section_info *secinfo;
  bfd_byte *stabbuf = NULL;
  bfd_byte *sym, *symend;
  bfd_size_type skip;
  bfd_size_type *pstridx;
  int deleting;

  if (stabsec->size == 0)
    /* This file does not contain stabs debugging information.  */
    return FALSE;

  if (stabsec->size % STABSIZE != 0)
    /* Something is wrong with the format of these stab symbols.
       Don't try to optimize them.  */
    return FALSE;

  if ((stabsec->output_section != NULL
       && bfd_is_abs_section (stabsec->output_section)))
    /* At least one of the sections is being discarded from the
       link, so we should just ignore them.  */
    return FALSE;

  /* We should have initialized our data in _bfd_link_section_stabs.
     If there was some bizarre error reading the string sections, though,
     we might not have.  Bail rather than asserting.  */
  if (psecinfo == NULL)
    return FALSE;

  count = stabsec->rawsize / STABSIZE;
  secinfo = (struct stab_section_info *) psecinfo;

  /* Read the stabs information from abfd.  */
  if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf))
    goto error_return;

  /* Look through the stabs symbols and discard any information for
     discarded functions.  */
  skip = 0;
  deleting = -1;

  symend = stabbuf + stabsec->rawsize;
  for (sym = stabbuf, pstridx = secinfo->stridxs;
       sym < symend;
       sym += STABSIZE, ++pstridx)
    {
      int type;

      if (*pstridx == (bfd_size_type) -1)
	/* This stab was deleted in a previous pass.  */
	continue;

      type = sym[TYPEOFF];

      if (type == (int) N_FUN)
	{
	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);

	  if (strx == 0)
	    {
	      if (deleting)
		{
		  skip++;
		  *pstridx = -1;
		}
	      deleting = -1;
	      continue;
	    }
	  deleting = 0;
	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
	    deleting = 1;
	}

      if (deleting == 1)
	{
	  *pstridx = -1;
	  skip++;
	}
      else if (deleting == -1)
	{
	  /* Outside of a function.  Check for deleted variables.  */
	  if (type == (int) N_STSYM || type == (int) N_LCSYM)
	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
	      {
		*pstridx = -1;
		skip ++;
	      }
	  /* We should also check for N_GSYM entries which reference a
	     deleted global, but those are less harmful to debuggers
	     and would require parsing the stab strings.  */
	}
    }

  free (stabbuf);
  stabbuf = NULL;

  /* Shrink the stabsec as needed.  */
  stabsec->size -= skip * STABSIZE;
  if (stabsec->size == 0)
    stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;

  /* Recalculate the `cumulative_skips' array now that stabs have been
     deleted for this section.  */

  if (skip != 0)
    {
      bfd_size_type i, offset;
      bfd_size_type *pskips;

      if (secinfo->cumulative_skips == NULL)
	{
	  amt = count * sizeof (bfd_size_type);
	  secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
	  if (secinfo->cumulative_skips == NULL)
	    goto error_return;
	}

      pskips = secinfo->cumulative_skips;
      pstridx = secinfo->stridxs;
      offset = 0;

      for (i = 0; i < count; i++, pskips++, pstridx++)
	{
	  *pskips = offset;
	  if (*pstridx == (bfd_size_type) -1)
	    offset += STABSIZE;
	}

      BFD_ASSERT (offset != 0);
    }

  return skip > 0;

 error_return:
  if (stabbuf != NULL)
    free (stabbuf);
  return FALSE;
}
Beispiel #19
0
static int
bfd_pef_parse_traceback_table (bfd *abfd,
			       asection *section,
			       unsigned char *buf,
			       size_t len,
			       size_t pos,
			       asymbol *sym,
			       FILE *file)
{
  struct traceback_table table;
  size_t offset;
  const char *s;
  asymbol tmpsymbol;

  if (sym == NULL)
    sym = & tmpsymbol;

  sym->name = NULL;
  sym->value = 0;
  sym->the_bfd = abfd;
  sym->section = section;
  sym->flags = 0;
  sym->udata.i = 0;

  /* memcpy is fine since all fields are unsigned char.  */
  if ((pos + 8) > len)
    return -1;
  memcpy (&table, buf + pos, 8);

  /* Calling code relies on returned symbols having a name and
     correct offset.  */
  if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS))
    return -1;

  if (! (table.flags2 & TB_NAME_PRESENT))
    return -1;

  if (! (table.flags1 & TB_HAS_TBOFF))
    return -1;

  offset = 8;

  if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams))
    offset += 4;

  if (table.flags1 & TB_HAS_TBOFF)
    {
      struct traceback_table_tboff off;

      if ((pos + offset + 4) > len)
	return -1;
      off.tb_offset = bfd_getb32 (buf + pos + offset);
      offset += 4;

      /* Need to subtract 4 because the offset includes the 0x0L
	 preceding the table.  */
      if (file != NULL)
	fprintf (file, " [offset = 0x%lx]", off.tb_offset);

      if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset)))
	return -1;

      sym->value = pos - off.tb_offset - 4;
    }

  if (table.flags2 & TB_INT_HNDL)
    offset += 4;

  if (table.flags1 & TB_HAS_CTL)
    {
      struct traceback_table_anchors anchors;

      if ((pos + offset + 4) > len)
	return -1;
      anchors.ctl_info = bfd_getb32 (buf + pos + offset);
      offset += 4;

      if (anchors.ctl_info > 1024)
	return -1;

      offset += anchors.ctl_info * 4;
    }

  if (table.flags2 & TB_NAME_PRESENT)
    {
      struct traceback_table_routine name;
      char *namebuf;

      if ((pos + offset + 2) > len)
	return -1;
      name.name_len = bfd_getb16 (buf + pos + offset);
      offset += 2;

      if (name.name_len > 4096)
	return -1;

      if ((pos + offset + name.name_len) > len)
	return -1;

      namebuf = bfd_alloc (abfd, name.name_len + 1);
      if (namebuf == NULL)
	return -1;

      memcpy (namebuf, buf + pos + offset, name.name_len);
      namebuf[name.name_len] = '\0';

      /* Strip leading period inserted by compiler.  */
      if (namebuf[0] == '.')
	memmove (namebuf, namebuf + 1, name.name_len + 1);

      sym->name = namebuf;

      for (s = sym->name; (*s != '\0'); s++)
	if (! ISPRINT (*s))
	  return -1;

      offset += name.name_len;
    }

  if (table.flags2 & TB_USES_ALLOCA)
    offset += 4;

  if (table.flags4 & TB_HAS_VEC_INFO)
    offset += 4;

  if (file != NULL)
    fprintf (file, " [length = 0x%lx]", (unsigned long) offset);

  return offset;
}
Beispiel #20
0
/* Get view of the input file.  */
static enum ld_plugin_status
get_view (const void *handle, const void **viewp)
{
    plugin_input_file_t *input = (plugin_input_file_t *) handle;
    char *buffer;
    size_t size = input->filesize;
    off_t offset = input->offset;
#if HAVE_MMAP && HAVE_GETPAGESIZE
    off_t bias;
#endif

    ASSERT (called_plugin);

    /* FIXME: einfo should support %lld.  */
    if ((off_t) size != input->filesize)
        einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"),
        input->name, (long) input->filesize);

    /* Check the cached view buffer.  */
    if (input->view_buffer.addr != NULL
    && input->view_buffer.filesize == size
    && input->view_buffer.offset == offset)
    {
        *viewp = input->view_buffer.addr;
        return LDPS_OK;
    }

    input->view_buffer.filesize = size;
    input->view_buffer.offset = offset;

#if HAVE_MMAP
# if HAVE_GETPAGESIZE
    bias = offset % plugin_pagesize;
    offset -= bias;
    size += bias;
# endif
    buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, offset);
    if (buffer != MAP_FAILED)
    {
        input->use_mmap = TRUE;
# if HAVE_GETPAGESIZE
        buffer += bias;
# endif
    }
    else
#endif
    {
        char *p;

        input->use_mmap = FALSE;

        if (lseek (input->fd, offset, SEEK_SET) < 0)
            return LDPS_ERR;

        buffer = bfd_alloc (input->abfd, size);
        if (buffer == NULL)
            return LDPS_ERR;

        p = buffer;
        do
        {
            ssize_t got = read (input->fd, p, size);
            if (got == 0)
                break;
            else if (got > 0)
            {
                p += got;
                size -= got;
            }
            else if (errno != EINTR)
                return LDPS_ERR;
        }
        while (size > 0);
    }

    input->view_buffer.addr = buffer;
    *viewp = buffer;

    return LDPS_OK;
}
Beispiel #21
0
static bfd_size_type
bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
			       bfd_byte *uncompressed_buffer,
			       bfd_size_type uncompressed_size)
{
  uLong compressed_size;
  bfd_byte *buffer;
  bfd_size_type buffer_size;
  bfd_boolean decompress;
#if defined(__GNUC__) && GCC_VERSION < 4007
  /* Work around a GCC uninitialized warning bug fixed in GCC 4.7.  */
  int zlib_size = 0;
#else
  int zlib_size;
#endif
  int orig_compression_header_size;
  int compression_header_size
    = bfd_get_compression_header_size (abfd, NULL);
  bfd_boolean compressed
    = bfd_is_section_compressed_with_header (abfd, sec,
					     &orig_compression_header_size);

  if (compressed)
    {
      /* We shouldn't decompress unsupported compressed section.  */
      if (orig_compression_header_size < 0)
	abort ();

      /* Different compression schemes.  Just move the compressed section
	 contents to the right position. */
      if (orig_compression_header_size == 0)
	{
	  /* Convert it from .zdebug* section.  Get the uncompressed
	     size first.  */
	  zlib_size = uncompressed_size;
	  compressed_size = zlib_size + compression_header_size;
	  uncompressed_size = bfd_getb64 (uncompressed_buffer + 4);
	}
      else
	{
	  /* Convert it to .zdebug* section. */
	  zlib_size = uncompressed_size - orig_compression_header_size;
	  compressed_size = zlib_size;
	}
    }
  else
    compressed_size = compressBound (uncompressed_size) + 12;

  /* When converting from .zdebug* section, uncompress if it leads to
     smaller size.  */
  if (compressed
      && orig_compression_header_size == 0
      && compressed_size > uncompressed_size)
    {
      decompress = TRUE;
      buffer_size = uncompressed_size;
    }
  else
    {
      decompress = FALSE;
      buffer_size = compressed_size + compression_header_size;
    }
  buffer = (bfd_byte *) bfd_alloc (abfd, buffer_size);
  if (buffer == NULL)
    return 0;

  if (compressed)
    {
      sec->size = uncompressed_size;
      if (decompress)
	{
	  if (!decompress_contents (uncompressed_buffer, zlib_size,
				    buffer, uncompressed_size))
	    {
	      bfd_set_error (bfd_error_bad_value);
	      bfd_release (abfd, buffer);
	      return 0;
	    }
	  free (uncompressed_buffer);
	  sec->contents = buffer;
	  sec->compress_status = COMPRESS_SECTION_DONE;
	  return uncompressed_size;
	}
      else
	{
	  bfd_update_compression_header (abfd, buffer, sec);
	  memmove (buffer + compression_header_size,
		   uncompressed_buffer + orig_compression_header_size,
		   zlib_size);
	}
    }
  else
    {
      bfd_size_type size = uncompressed_size;
      int header_size = 12 + compression_header_size;
      if (compress ((Bytef*) buffer + header_size,
		    &compressed_size,
		    (const Bytef*) uncompressed_buffer,
		    uncompressed_size) != Z_OK)
	{
	  bfd_release (abfd, buffer);
	  bfd_set_error (bfd_error_bad_value);
	  return 0;
	}

      compressed_size += header_size;
      /* PR binutils/18087: If compression didn't make the section smaller,
	 just keep it uncompressed.  */
      if (compressed_size < uncompressed_size)
	{
	  bfd_update_compression_header (abfd, buffer, sec);

	  /* Write the zlib header.  In this case, it should be "ZLIB"
	     followed by the uncompressed section size, 8 bytes in
	     big-endian order.  */
	  memcpy (buffer + compression_header_size, "ZLIB", 4);
	  bfd_putb64 (size, buffer + compression_header_size + 4);
	}
      else
	{
	  /* NOTE: There is a small memory leak here since
	     uncompressed_buffer is malloced and won't be freed.  */
	  bfd_release (abfd, buffer);
	  sec->contents = uncompressed_buffer;
	  sec->compress_status = COMPRESS_SECTION_NONE;
	  return uncompressed_size;
	}
    }

  free (uncompressed_buffer);
  sec->contents = buffer;
  sec->size = compressed_size;
  sec->compress_status = COMPRESS_SECTION_DONE;

  return uncompressed_size;
}
Beispiel #22
0
static bfd_boolean
oasys_slurp_symbol_table (bfd *const abfd)
{
  oasys_record_union_type record;
  oasys_data_type *data = OASYS_DATA (abfd);
  bfd_boolean loop = TRUE;
  asymbol *dest_defined;
  asymbol *dest;
  char *string_ptr;
  bfd_size_type amt;

  if (data->symbols != NULL)
    return TRUE;

  /* Buy enough memory for all the symbols and all the names.  */
  amt = abfd->symcount;
  amt *= sizeof (asymbol);
  data->symbols = bfd_alloc (abfd, amt);

  amt = data->symbol_string_length;
#ifdef UNDERSCORE_HACK
  /* Buy 1 more char for each symbol to keep the underscore in.  */
  amt += abfd->symcount;
#endif
  data->strings = bfd_alloc (abfd, amt);

  if (!data->symbols || !data->strings)
    return FALSE;

  dest_defined = data->symbols + abfd->symcount - 1;

  string_ptr = data->strings;
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    return FALSE;
  while (loop)
    {
      if (! oasys_read_record (abfd, &record))
	return FALSE;

      switch (record.header.type)
	{
	case oasys_record_is_header_enum:
	  break;
	case oasys_record_is_local_enum:
	case oasys_record_is_symbol_enum:
	  {
	    int flag = record.header.type == (int) oasys_record_is_local_enum ?
	    (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);

	    size_t length = oasys_string_length (&record);
	    switch (record.symbol.relb & RELOCATION_TYPE_BITS)
	      {
	      case RELOCATION_TYPE_ABS:
		dest = dest_defined--;
		dest->section = bfd_abs_section_ptr;
		dest->flags = 0;

		break;
	      case RELOCATION_TYPE_REL:
		dest = dest_defined--;
		dest->section =
		  OASYS_DATA (abfd)->sections[record.symbol.relb &
					      RELOCATION_SECT_BITS];
		if (record.header.type == (int) oasys_record_is_local_enum)
		  {
		    dest->flags = BSF_LOCAL;
		    if (dest->section == (asection *) (~0))
		      {
			/* It seems that sometimes internal symbols are tied up, but
		       still get output, even though there is no
		       section */
			dest->section = 0;
		      }
		  }
		else
		  dest->flags = flag;
		break;
	      case RELOCATION_TYPE_UND:
		dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
		dest->section = bfd_und_section_ptr;
		break;
	      case RELOCATION_TYPE_COM:
		dest = dest_defined--;
		dest->name = string_ptr;
		dest->the_bfd = abfd;
		dest->section = bfd_com_section_ptr;
		break;
	      default:
		dest = dest_defined--;
		BFD_ASSERT (FALSE);
		break;
	      }
	    dest->name = string_ptr;
	    dest->the_bfd = abfd;
	    dest->udata.p = NULL;
	    dest->value = H_GET_32 (abfd, record.symbol.value);

#ifdef UNDERSCORE_HACK
	    if (record.symbol.name[0] != '_')
	      {
		string_ptr[0] = '_';
		string_ptr++;
	      }
#endif
	    memcpy (string_ptr, record.symbol.name, length);

	    string_ptr[length] = 0;
	    string_ptr += length + 1;
	  }
	  break;
	default:
	  loop = FALSE;
	}
    }
  return TRUE;
}
Beispiel #23
0
static const bfd_target *
plugin_object_p (bfd *ibfd)
{
    int claimed;
    plugin_input_file_t *input;
    struct ld_plugin_input_file file;
    bfd *abfd;

    /* Don't try the dummy object file.  */
    if ((ibfd->flags & BFD_PLUGIN) != 0)
        return NULL;

    if (ibfd->plugin_format != bfd_plugin_unknown)
    {
        if (ibfd->plugin_format == bfd_plugin_yes)
            return ibfd->plugin_dummy_bfd->xvec;
        else
            return NULL;
    }

    /* We create a dummy BFD, initially empty, to house whatever symbols
       the plugin may want to add.  */
    abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);

    input = bfd_alloc (abfd, sizeof (*input));
    if (input == NULL)
        einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
               bfd_get_error ());

    if (!bfd_plugin_open_input (ibfd, &file))
        return NULL;

    if (file.name == ibfd->filename)
    {
        /* We must copy filename attached to ibfd if it is not an archive
        member since it may be freed by bfd_close below.  */
        file.name = plugin_strdup (abfd, file.name);
    }

    file.handle = input;
    /* The plugin API expects that the file descriptor won't be closed
       and reused as done by the bfd file cache.  So dup one.  */
    file.fd = dup (file.fd);
    if (file.fd < 0)
        return NULL;

    input->abfd = abfd;
    input->view_buffer.addr = NULL;
    input->view_buffer.filesize = 0;
    input->view_buffer.offset = 0;
    input->fd = file.fd;
    input->use_mmap = FALSE;
    input->offset = file.offset;
    input->filesize = file.filesize;
    input->name = plugin_strdup (abfd, ibfd->filename);

    claimed = 0;

    if (plugin_call_claim_file (&file, &claimed))
        einfo (_("%P%F: %s: plugin reported error claiming file\n"),
               plugin_error_plugin ());

    if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec))
    {
        /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
        doesn't need fd after plugin_call_claim_file, doesn't use
         BFD plugin target vector.  Since GCC plugin doesn't call
         release_input_file, we close it here.  LLVM plugin, which
         needs fd after plugin_call_claim_file and calls
         release_input_file after it is done, uses BFD plugin target
         vector.  This scheme doesn't work when a plugin needs fd and
         doesn't use BFD plugin target vector neither.  */
        close (input->fd);
        input->fd = -1;
    }

    if (claimed)
    {
        ibfd->plugin_format = bfd_plugin_yes;
        ibfd->plugin_dummy_bfd = abfd;
        bfd_make_readable (abfd);
        return abfd->xvec;
    }
    else
    {
#if HAVE_MMAP
        if (input->use_mmap)
        {
            /* If plugin didn't claim the file, unmap the buffer.  */
            char *addr = input->view_buffer.addr;
            off_t size = input->view_buffer.filesize;
# if HAVE_GETPAGESIZE
            off_t bias = input->view_buffer.offset % plugin_pagesize;
            size += bias;
            addr -= bias;
# endif
            munmap (addr, size);
        }
#endif

        /* If plugin didn't claim the file, we don't need the dummy bfd.
        Can't avoid speculatively creating it, alas.  */
        ibfd->plugin_format = bfd_plugin_no;
        bfd_close_all_done (abfd);
        return NULL;
    }
}
bfd_boolean
_bfd_link_section_stabs (bfd *abfd,
			 struct stab_info *sinfo,
			 asection *stabsec,
			 asection *stabstrsec,
			 void * *psecinfo,
			 bfd_size_type *pstring_offset)
{
  bfd_boolean first;
  bfd_size_type count, amt;
  struct stab_section_info *secinfo;
  bfd_byte *stabbuf = NULL;
  bfd_byte *stabstrbuf = NULL;
  bfd_byte *sym, *symend;
  bfd_size_type stroff, next_stroff, skip;
  bfd_size_type *pstridx;

  if (stabsec->size == 0
      || stabstrsec->size == 0)
    /* This file does not contain stabs debugging information.  */
    return TRUE;

  if (stabsec->size % STABSIZE != 0)
    /* Something is wrong with the format of these stab symbols.
       Don't try to optimize them.  */
    return TRUE;

  if ((stabstrsec->flags & SEC_RELOC) != 0)
    /* We shouldn't see relocations in the strings, and we aren't
       prepared to handle them.  */
    return TRUE;

  if (bfd_is_abs_section (stabsec->output_section)
      || bfd_is_abs_section (stabstrsec->output_section))
    /* At least one of the sections is being discarded from the
       link, so we should just ignore them.  */
    return TRUE;

  first = FALSE;

  if (sinfo->stabstr == NULL)
    {
      flagword flags;

      /* Initialize the stabs information we need to keep track of.  */
      first = TRUE;
      sinfo->strings = _bfd_stringtab_init ();
      if (sinfo->strings == NULL)
	goto error_return;
      /* Make sure the first byte is zero.  */
      (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
      if (! bfd_hash_table_init (&sinfo->includes,
				 stab_link_includes_newfunc,
				 sizeof (struct stab_link_includes_entry)))
	goto error_return;
      flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING
	       | SEC_LINKER_CREATED);
      sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr",
							   flags);
      if (sinfo->stabstr == NULL)
	goto error_return;
    }

  /* Initialize the information we are going to store for this .stab
     section.  */
  count = stabsec->size / STABSIZE;

  amt = sizeof (struct stab_section_info);
  amt += (count - 1) * sizeof (bfd_size_type);
  *psecinfo = bfd_alloc (abfd, amt);
  if (*psecinfo == NULL)
    goto error_return;

  secinfo = (struct stab_section_info *) *psecinfo;
  secinfo->excls = NULL;
  stabsec->rawsize = stabsec->size;
  secinfo->cumulative_skips = NULL;
  memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type));

  /* Read the stabs information from abfd.  */
  if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf)
      || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf))
    goto error_return;

  /* Look through the stabs symbols, work out the new string indices,
     and identify N_BINCL symbols which can be eliminated.  */
  stroff = 0;
  /* The stabs sections can be split when
     -split-by-reloc/-split-by-file is used.  We must keep track of
     each stab section's place in the single concatenated string
     table.  */
  next_stroff = pstring_offset ? *pstring_offset : 0;
  skip = 0;

  symend = stabbuf + stabsec->size;
  for (sym = stabbuf, pstridx = secinfo->stridxs;
       sym < symend;
       sym += STABSIZE, ++pstridx)
    {
      bfd_size_type symstroff;
      int type;
      const char *string;

      if (*pstridx != 0)
	/* This symbol has already been handled by an N_BINCL pass.  */
	continue;

      type = sym[TYPEOFF];

      if (type == 0)
	{
	  /* Special type 0 stabs indicate the offset to the next
	     string table.  We only copy the very first one.  */
	  stroff = next_stroff;
	  next_stroff += bfd_get_32 (abfd, sym + 8);
	  if (pstring_offset)
	    *pstring_offset = next_stroff;
	  if (! first)
	    {
	      *pstridx = (bfd_size_type) -1;
	      ++skip;
	      continue;
	    }
	  first = FALSE;
	}

      /* Store the string in the hash table, and record the index.  */
      symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF);
      if (symstroff >= stabstrsec->size)
	{
	  _bfd_error_handler
	    /* xgettext:c-format */
	    (_("%B(%A+0x%lx): Stabs entry has invalid string index."),
	     abfd, stabsec, (long) (sym - stabbuf));
	  bfd_set_error (bfd_error_bad_value);
	  goto error_return;
	}
      string = (char *) stabstrbuf + symstroff;
      *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE);

      /* An N_BINCL symbol indicates the start of the stabs entries
	 for a header file.  We need to scan ahead to the next N_EINCL
	 symbol, ignoring nesting, adding up all the characters in the
	 symbol names, not including the file numbers in types (the
	 first number after an open parenthesis).  */
      if (type == (int) N_BINCL)
	{
	  bfd_vma sum_chars;
	  bfd_vma num_chars;
	  bfd_vma buf_len = 0;
	  char * symb;
	  char * symb_rover;
	  int nest;
	  bfd_byte * incl_sym;
	  struct stab_link_includes_entry * incl_entry;
	  struct stab_link_includes_totals * t;
	  struct stab_excl_list * ne;

	  symb = symb_rover = NULL;
	  sum_chars = num_chars = 0;
	  nest = 0;

	  for (incl_sym = sym + STABSIZE;
	       incl_sym < symend;
	       incl_sym += STABSIZE)
	    {
	      int incl_type;

	      incl_type = incl_sym[TYPEOFF];
	      if (incl_type == 0)
		break;
	      else if (incl_type == (int) N_EXCL)
		continue;
	      else if (incl_type == (int) N_EINCL)
		{
		  if (nest == 0)
		    break;
		  --nest;
		}
	      else if (incl_type == (int) N_BINCL)
		++nest;
	      else if (nest == 0)
		{
		  const char *str;

		  str = ((char *) stabstrbuf
			 + stroff
			 + bfd_get_32 (abfd, incl_sym + STRDXOFF));
		  for (; *str != '\0'; str++)
		    {
		      if (num_chars >= buf_len)
			{
			  buf_len += 32 * 1024;
			  symb = (char *) bfd_realloc_or_free (symb, buf_len);
			  if (symb == NULL)
			    goto error_return;
			  symb_rover = symb + num_chars;
			}
		      * symb_rover ++ = * str;
		      sum_chars += *str;
		      num_chars ++;
		      if (*str == '(')
			{
			  /* Skip the file number.  */
			  ++str;
			  while (ISDIGIT (*str))
			    ++str;
			  --str;
			}
		    }
		}
	    }

	  BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));

	  /* If we have already included a header file with the same
	     value, then replaced this one with an N_EXCL symbol.  */
	  incl_entry = (struct stab_link_includes_entry * )
	    bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE);
	  if (incl_entry == NULL)
	    goto error_return;

	  for (t = incl_entry->totals; t != NULL; t = t->next)
	    if (t->sum_chars == sum_chars
		&& t->num_chars == num_chars
		&& memcmp (t->symb, symb, num_chars) == 0)
	      break;

	  /* Record this symbol, so that we can set the value
	     correctly.  */
	  amt = sizeof *ne;
	  ne = (struct stab_excl_list *) bfd_alloc (abfd, amt);
	  if (ne == NULL)
	    goto error_return;
	  ne->offset = sym - stabbuf;
	  ne->val = sum_chars;
	  ne->type = (int) N_BINCL;
	  ne->next = secinfo->excls;
	  secinfo->excls = ne;

	  if (t == NULL)
	    {
	      /* This is the first time we have seen this header file
		 with this set of stabs strings.  */
	      t = (struct stab_link_includes_totals *)
                  bfd_hash_allocate (&sinfo->includes, sizeof *t);
	      if (t == NULL)
		goto error_return;
	      t->sum_chars = sum_chars;
	      t->num_chars = num_chars;
              /* Trim data down.  */
	      t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars);
	      t->next = incl_entry->totals;
	      incl_entry->totals = t;
	    }
	  else
	    {
	      bfd_size_type *incl_pstridx;

	      /* We have seen this header file before.  Tell the final
		 pass to change the type to N_EXCL.  */
	      ne->type = (int) N_EXCL;

	      /* Free off superfluous symbols.  */
	      free (symb);

	      /* Mark the skipped symbols.  */

	      nest = 0;
	      for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1;
		   incl_sym < symend;
		   incl_sym += STABSIZE, ++incl_pstridx)
		{
		  int incl_type;

		  incl_type = incl_sym[TYPEOFF];

		  if (incl_type == (int) N_EINCL)
		    {
		      if (nest == 0)
			{
			  *incl_pstridx = (bfd_size_type) -1;
			  ++skip;
			  break;
			}
		      --nest;
		    }
		  else if (incl_type == (int) N_BINCL)
		    ++nest;
		  else if (incl_type == (int) N_EXCL)
		    /* Keep existing exclusion marks.  */
		    continue;
		  else if (nest == 0)
		    {
		      *incl_pstridx = (bfd_size_type) -1;
		      ++skip;
		    }
		}
	    }
	}
    }

  free (stabbuf);
  stabbuf = NULL;
  free (stabstrbuf);
  stabstrbuf = NULL;

  /* We need to set the section sizes such that the linker will
     compute the output section sizes correctly.  We set the .stab
     size to not include the entries we don't want.  We set
     SEC_EXCLUDE for the .stabstr section, so that it will be dropped
     from the link.  We record the size of the strtab in the first
     .stabstr section we saw, and make sure we don't set SEC_EXCLUDE
     for that section.  */
  stabsec->size = (count - skip) * STABSIZE;
  if (stabsec->size == 0)
    stabsec->flags |= SEC_EXCLUDE | SEC_KEEP;
  stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP;
  sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings);

  /* Calculate the `cumulative_skips' array now that stabs have been
     deleted for this section.  */

  if (skip != 0)
    {
      bfd_size_type i, offset;
      bfd_size_type *pskips;

      amt = count * sizeof (bfd_size_type);
      secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
      if (secinfo->cumulative_skips == NULL)
	goto error_return;

      pskips = secinfo->cumulative_skips;
      pstridx = secinfo->stridxs;
      offset = 0;

      for (i = 0; i < count; i++, pskips++, pstridx++)
	{
	  *pskips = offset;
	  if (*pstridx == (bfd_size_type) -1)
	    offset += STABSIZE;
	}

      BFD_ASSERT (offset != 0);
    }

  return TRUE;

 error_return:
  if (stabbuf != NULL)
    free (stabbuf);
  if (stabstrbuf != NULL)
    free (stabstrbuf);
  return FALSE;
}
Beispiel #25
0
static bfd_boolean
vms_initialize (bfd * abfd)
{
  int i;
  bfd_size_type amt;

  bfd_set_start_address(abfd, (bfd_vma)-1);

  amt = sizeof(struct vms_private_data_struct);
  abfd->tdata.any = bfd_alloc(abfd, amt);
  if (abfd->tdata.any == NULL) {
      return FALSE;
  }

#ifdef __ALPHA
  PRIV(is_vax) = FALSE;
#else
  PRIV(is_vax) = TRUE;
#endif /* __ALPHA */
  PRIV(vms_buf) = NULL;
  PRIV(buf_size) = 0;
  PRIV(rec_length) = 0;
  PRIV(file_format) = FF_UNKNOWN;
  PRIV(fixup_done) = FALSE;
  PRIV(sections) = NULL;

  amt = (sizeof(struct stack_struct) * STACKSIZE);
  PRIV(stack) = (struct stack_struct *)bfd_alloc(abfd, amt);
  if (PRIV(stack) == NULL) {
      goto error_ret1;
  }
  PRIV(stackptr) = 0;

  amt = sizeof(struct bfd_hash_table);
  PRIV(vms_symbol_table) = (struct bfd_hash_table *)bfd_alloc(abfd, amt);
  if (PRIV (vms_symbol_table) == NULL)
    goto error_ret1;

  if (!bfd_hash_table_init (PRIV (vms_symbol_table), _bfd_vms_hash_newfunc))
    goto error_ret1;

  amt = sizeof(struct location_struct) * LOCATION_SAVE_SIZE;
  PRIV(location_stack) = (struct location_struct *)bfd_alloc(abfd, amt);
  if (PRIV(location_stack) == NULL) {
      goto error_ret2;
  }

  for ((i = 0); (i < VMS_SECTION_COUNT); i++) {
      PRIV(vms_section_table)[i] = NULL;
  }

  amt = MAX_OUTREC_SIZE;
  PRIV(output_buf) = (unsigned char *)bfd_alloc(abfd, amt);
  if (PRIV(output_buf) == NULL) {
      goto error_ret2;
  }

  PRIV (push_level) = 0;
  PRIV (pushed_size) = 0;
  PRIV (length_pos) = 2;
  PRIV (output_size) = 0;
  PRIV (output_alignment) = 1;

  return TRUE;

 error_ret2:
  bfd_hash_table_free (PRIV (vms_symbol_table));
 error_ret1:
  bfd_release (abfd, abfd->tdata.any);
  abfd->tdata.any = NULL;
  return FALSE;
}
Beispiel #26
0
bfd_boolean
bfd_elf64_archive_slurp_armap (bfd *abfd)
{
  struct artdata *ardata = bfd_ardata (abfd);
  char nextname[17];
  bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
  struct areltdata *mapdata;
  bfd_byte int_buf[8];
  char *stringbase;
  char *stringend;
  bfd_byte *raw_armap = NULL;
  carsym *carsyms;
  bfd_size_type amt;

  ardata->symdefs = NULL;

  /* Get the name of the first element.  */
  i = bfd_bread (nextname, 16, abfd);
  if (i == 0)
    return TRUE;
  if (i != 16)
    return FALSE;

  if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
    return FALSE;

  /* Archives with traditional armaps are still permitted.  */
  if (CONST_STRNEQ (nextname, "/               "))
    return bfd_slurp_armap (abfd);

  if (! CONST_STRNEQ (nextname, "/SYM64/         "))
    {
      bfd_has_map (abfd) = FALSE;
      return TRUE;
    }

  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
  if (mapdata == NULL)
    return FALSE;
  parsed_size = mapdata->parsed_size;
  free (mapdata);

  if (bfd_bread (int_buf, 8, abfd) != 8)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_malformed_archive);
      return FALSE;
    }

  nsymz = bfd_getb64 (int_buf);
  stringsize = parsed_size - 8 * nsymz - 8;

  carsym_size = nsymz * sizeof (carsym);
  ptrsize = 8 * nsymz;

  amt = carsym_size + stringsize + 1;
  if (carsym_size < nsymz || ptrsize < nsymz || amt < nsymz)
    {
      bfd_set_error (bfd_error_malformed_archive);
      return FALSE;
    }
  ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
  if (ardata->symdefs == NULL)
    return FALSE;
  carsyms = ardata->symdefs;
  stringbase = ((char *) ardata->symdefs) + carsym_size;
  stringbase[stringsize] = 0;
  stringend = stringbase + stringsize;

  raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
  if (raw_armap == NULL)
    goto release_symdefs;

  if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
      || bfd_bread (stringbase, stringsize, abfd) != stringsize)
    {
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_malformed_archive);
      goto release_raw_armap;
    }

  for (i = 0; i < nsymz; i++)
    {
      carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
      carsyms->name = stringbase;
      if (stringbase < stringend)
	stringbase += strlen (stringbase) + 1;
      ++carsyms;
    }
  *stringbase = '\0';

  ardata->symdef_count = nsymz;
  ardata->first_file_filepos = bfd_tell (abfd);
  /* Pad to an even boundary if you have to.  */
  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;

  bfd_has_map (abfd) = TRUE;
  bfd_release (abfd, raw_armap);

  return TRUE;

release_raw_armap:
  bfd_release (abfd, raw_armap);
release_symdefs:
  bfd_release (abfd, ardata->symdefs);
  return FALSE;
}
Beispiel #27
0
static const bfd_target *
plugin_object_p (bfd *ibfd)
{
  int claimed;
  plugin_input_file_t *input;
  off_t offset, filesize;
  struct ld_plugin_input_file file;
  bfd *abfd;
  bfd_boolean inarchive;
  const char *name;
  int fd;

  /* Don't try the dummy object file.  */
  if ((ibfd->flags & BFD_PLUGIN) != 0)
    return NULL;

  if (ibfd->plugin_format != bfd_plugin_uknown)
    {
      if (ibfd->plugin_format == bfd_plugin_yes)
	return ibfd->plugin_dummy_bfd->xvec;
      else
	return NULL;
    }

  inarchive = bfd_my_archive (ibfd) != NULL;
  name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
  fd = open (name, O_RDONLY | O_BINARY);

  if (fd < 0)
    return NULL;

  /* We create a dummy BFD, initially empty, to house whatever symbols
     the plugin may want to add.  */
  abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);

  input = bfd_alloc (abfd, sizeof (*input));
  if (input == NULL)
    einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
	   bfd_get_error ());

  if (inarchive)
    {
      /* Offset and filesize must refer to the individual archive
	 member, not the whole file, and must exclude the header.
	 Fortunately for us, that is how the data is stored in the
	 origin field of the bfd and in the arelt_data.  */
      offset = ibfd->origin;
      filesize = arelt_size (ibfd);
    }
  else
    {
      offset = 0;
      filesize = lseek (fd, 0, SEEK_END);

      /* We must copy filename attached to ibfd if it is not an archive
	 member since it may be freed by bfd_close below.  */
      name = plugin_strdup (abfd, name);
    }

  file.name = name;
  file.offset = offset;
  file.filesize = filesize;
  file.fd = fd;
  file.handle = input;

  input->abfd = abfd;
  input->view_buffer.addr = NULL;
  input->view_buffer.filesize = 0;
  input->view_buffer.offset = 0;
  input->fd = fd;
  input->use_mmap = FALSE;
  input->offset = offset;
  input->filesize = filesize;
  input->name = plugin_strdup (abfd, ibfd->filename);

  claimed = 0;

  if (plugin_call_claim_file (&file, &claimed))
    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
	   plugin_error_plugin ());

  if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec))
    {
      /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
	 doesn't need fd after plugin_call_claim_file, doesn't use
	 BFD plugin target vector.  Since GCC plugin doesn't call
	 release_input_file, we close it here.  LLVM plugin, which
	 needs fd after plugin_call_claim_file and calls
	 release_input_file after it is done, uses BFD plugin target
	 vector.  This scheme doesn't work when a plugin needs fd and
	 doesn't use BFD plugin target vector neither.  */
      close (fd);
      input->fd = -1;
    }

  if (claimed)
    {
      ibfd->plugin_format = bfd_plugin_yes;
      ibfd->plugin_dummy_bfd = abfd;
      bfd_make_readable (abfd);
      return abfd->xvec;
    }
  else
    {
#if HAVE_MMAP
      if (input->use_mmap)
	{
	  /* If plugin didn't claim the file, unmap the buffer.  */
	  char *addr = input->view_buffer.addr;
	  off_t size = input->view_buffer.filesize;
# if HAVE_GETPAGESIZE
	  off_t bias = input->view_buffer.offset % plugin_pagesize;
	  size += bias;
	  addr -= bias;
# endif
	  munmap (addr, size);
	}
#endif

      /* If plugin didn't claim the file, we don't need the dummy bfd.
	 Can't avoid speculatively creating it, alas.  */
      ibfd->plugin_format = bfd_plugin_no;
      bfd_close_all_done (abfd);
      return NULL;
    }
}
Beispiel #28
0
static bfd_boolean
parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
{
  bfd_byte *xptr;

  /* Load the ".line" section from the bfd if we haven't already.  */
  if (stash->line_section == 0)
    {
      asection *msec;
      bfd_size_type size;

      msec = bfd_get_section_by_name (stash->abfd, ".line");
      if (! msec)
	return FALSE;

      size = msec->rawsize ? msec->rawsize : msec->size;
      stash->line_section
	= bfd_simple_get_relocated_section_contents
	(stash->abfd, msec, NULL, stash->syms);

      if (! stash->line_section)
	return FALSE;

      stash->line_section_end = stash->line_section + size;
    }

  xptr = stash->line_section + aUnit->stmt_list_offset;
  if (xptr < stash->line_section_end)
    {
      unsigned long eachLine;
      bfd_byte *tblend;
      unsigned long base;
      bfd_size_type amt;

      /* First comes the length.  */
      tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
      xptr += 4;

      /* Then the base address for each address in the table.  */
      base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
      xptr += 4;

      /* How many line entrys?
	 10 = 4 (line number) + 2 (pos in line) + 4 (address in line).  */
      aUnit->line_count = (tblend - xptr) / 10;

      /* Allocate an array for the entries.  */
      amt = sizeof (struct linenumber) * aUnit->line_count;
      aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd,
                                                                 amt);
      if (!aUnit->linenumber_table)
	return FALSE;

      for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
	{
	  /* A line number.  */
	  aUnit->linenumber_table[eachLine].linenumber
	    = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
	  xptr += 4;

	  /* Skip the position within the line.  */
	  xptr += 2;

	  /* And finally the address.  */
	  aUnit->linenumber_table[eachLine].addr
	    = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
	  xptr += 4;
	}
    }

  return TRUE;
}
Beispiel #29
0
static bfd_boolean
oasys_slurp_section_data (bfd *const abfd)
{
  oasys_record_union_type record;
  oasys_data_type *data = OASYS_DATA (abfd);
  bfd_boolean loop = TRUE;
  oasys_per_section_type *per;
  asection *s;
  bfd_size_type amt;

  /* See if the data has been slurped already.  */
  for (s = abfd->sections; s != NULL; s = s->next)
    {
      per = oasys_per_section (s);
      if (per->initialized)
	return TRUE;
    }

  if (data->first_data_record == 0)
    return TRUE;

  if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
    return FALSE;

  while (loop)
    {
      if (! oasys_read_record (abfd, &record))
	return FALSE;

      switch (record.header.type)
	{
	case oasys_record_is_header_enum:
	  break;
	case oasys_record_is_data_enum:
	  {
	    bfd_byte *src = record.data.data;
	    bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
	    bfd_byte *dst_ptr;
	    bfd_byte *dst_base_ptr;
	    unsigned int relbit;
	    unsigned int count;
	    asection *section =
	    data->sections[record.data.relb & RELOCATION_SECT_BITS];
	    bfd_vma dst_offset;

	    per = oasys_per_section (section);

	    if (! per->initialized)
	      {
		arelent **relpp;

		per->data = bfd_zalloc (abfd, section->size);
		if (!per->data)
		  return FALSE;
		relpp = &section->relocation;
		per->reloc_tail_ptr = (oasys_reloc_type **) relpp;
		per->had_vma = FALSE;
		per->initialized = TRUE;
		section->reloc_count = 0;
		section->flags = SEC_ALLOC;
	      }

	    dst_offset = H_GET_32 (abfd, record.data.addr);
	    if (! per->had_vma)
	      {
		/* Take the first vma we see as the base.  */
		section->vma = dst_offset;
		per->had_vma = TRUE;
	      }

	    dst_offset -= section->vma;

	    dst_base_ptr = oasys_per_section (section)->data;
	    dst_ptr = oasys_per_section (section)->data +
	      dst_offset;

	    if (src < end_src)
	      section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;

	    while (src < end_src)
	      {
		unsigned char mod_byte = *src++;
		size_t gap = end_src - src;

		count = 8;
		if (mod_byte == 0 && gap >= 8)
		  {
		    dst_ptr[0] = src[0];
		    dst_ptr[1] = src[1];
		    dst_ptr[2] = src[2];
		    dst_ptr[3] = src[3];
		    dst_ptr[4] = src[4];
		    dst_ptr[5] = src[5];
		    dst_ptr[6] = src[6];
		    dst_ptr[7] = src[7];
		    dst_ptr += 8;
		    src += 8;
		  }
		else
		  {
		    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
		      {
			if (relbit & mod_byte)
			  {
			    unsigned char reloc = *src;
			    /* This item needs to be relocated.  */
			    switch (reloc & RELOCATION_TYPE_BITS)
			      {
			      case RELOCATION_TYPE_ABS:
				break;

			      case RELOCATION_TYPE_REL:
				{
				  /* Relocate the item relative to the section.  */
				  oasys_reloc_type *r;

				  amt = sizeof (oasys_reloc_type);
				  r = bfd_alloc (abfd, amt);
				  if (!r)
				    return FALSE;
				  *(per->reloc_tail_ptr) = r;
				  per->reloc_tail_ptr = &r->next;
				  r->next = NULL;
				  /* Reference to undefined symbol.  */
				  src++;
				  /* There is no symbol.  */
				  r->symbol = 0;
				  /* Work out the howto.  */
				  abort ();
				  r->relent.address = dst_ptr - dst_base_ptr;
				  r->relent.howto = &howto_table[reloc >> 6];
				  r->relent.sym_ptr_ptr = NULL;
				  section->reloc_count++;

				  /* Fake up the data to look like
				     it's got the -ve pc in it, this
				     makes it much easier to convert
				     into other formats.  This is done
				     by hitting the addend.  */
				  if (r->relent.howto->pc_relative)
				    r->relent.addend -= dst_ptr - dst_base_ptr;
				}
				break;

			      case RELOCATION_TYPE_UND:
				{
				  oasys_reloc_type *r;

				  amt = sizeof (oasys_reloc_type);
				  r = bfd_alloc (abfd, amt);
				  if (!r)
				    return FALSE;
				  *(per->reloc_tail_ptr) = r;
				  per->reloc_tail_ptr = &r->next;
				  r->next = NULL;
				  /* Reference to undefined symbol.  */
				  src++;
				  /* Get symbol number.  */
				  r->symbol = (src[0] << 8) | src[1];
				  /* Work out the howto.  */
				  abort ();

				  r->relent.addend = 0;
				  r->relent.address = dst_ptr - dst_base_ptr;
				  r->relent.howto = &howto_table[reloc >> 6];
				  r->relent.sym_ptr_ptr = NULL;
				  section->reloc_count++;

				  src += 2;
				  /* Fake up the data to look like
				     it's got the -ve pc in it, this
				     makes it much easier to convert
				     into other formats.  This is done
				     by hitting the addend.  */
				  if (r->relent.howto->pc_relative)
				    r->relent.addend -= dst_ptr - dst_base_ptr;
				}
				break;
			      case RELOCATION_TYPE_COM:
				BFD_FAIL ();
			      }
			  }
			*dst_ptr++ = *src++;
		      }
		  }
	      }
	  }
	  break;
	case oasys_record_is_local_enum:
	case oasys_record_is_symbol_enum:
	case oasys_record_is_section_enum:
	  break;
	default:
	  loop = FALSE;
	}
    }
Beispiel #30
0
const bfd_target *
lynx_core_file_p (bfd *abfd)
{
  int secnum;
  struct pssentry pss;
  bfd_size_type tcontext_size;
  core_st_t *threadp;
  int pagesize;
  asection *newsect;
  bfd_size_type amt;

  pagesize = getpagesize ();	/* Serious cross-target issue here...  This
				   really needs to come from a system-specific
				   header file.  */

  /* Get the pss entry from the core file */

  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    return NULL;

  amt = sizeof pss;
  if (bfd_bread ((void *) &pss, amt, abfd) != amt)
    {
      /* Too small to be a core file */
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      return NULL;
    }

  amt = sizeof (struct lynx_core_struct);
  core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);

  if (!core_hdr (abfd))
    return NULL;

  strncpy (core_command (abfd), pss.pname, PNMLEN + 1);

  /* Compute the size of the thread contexts */

  tcontext_size = pss.threadcnt * sizeof (core_st_t);

  /* Allocate space for the thread contexts */

  threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size);
  if (!threadp)
    goto fail;

  /* Save thread contexts */

  if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0)
    goto fail;

  if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size)
    {
      /* Probably too small to be a core file */
      if (bfd_get_error () != bfd_error_system_call)
	bfd_set_error (bfd_error_wrong_format);
      goto fail;
    }

  core_signal (abfd) = threadp->currsig;

  newsect = make_bfd_asection (abfd, ".stack",
			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			       pss.ssize,
			       pss.slimit,
			       pagesize + tcontext_size);
  if (!newsect)
    goto fail;

  newsect = make_bfd_asection (abfd, ".data",
			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
			       pss.data_len + pss.bss_len,
			       pss.data_start,
			       pagesize + tcontext_size + pss.ssize
#if defined (SPARC) || defined (__SPARC__)
			       /* SPARC Lynx seems to start dumping
				  the .data section at a page
				  boundary.  It's OK to check a
				  #define like SPARC here because this
				  file can only be compiled on a Lynx
				  host.  */
			       + pss.data_start % pagesize
#endif
			       );
  if (!newsect)
    goto fail;

/* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
   .reg/XXX section, where XXX is the thread id (without leading zeros).  The
   currently running thread (at the time of the core dump) also has an alias
   called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
   opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
   point registers.  */

  newsect = make_bfd_asection (abfd, ".reg",
			       SEC_HAS_CONTENTS,
			       sizeof (core_st_t),
			       0,
			       pagesize);
  if (!newsect)
    goto fail;

  for (secnum = 0; secnum < pss.threadcnt; secnum++)
    {
      char secname[100];

      sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
      newsect = make_bfd_asection (abfd, secname,
				   SEC_HAS_CONTENTS,
				   sizeof (core_st_t),
				   0,
				   pagesize + secnum * sizeof (core_st_t));
      if (!newsect)
	goto fail;
    }

  return abfd->xvec;

 fail:
  bfd_release (abfd, core_hdr (abfd));
  core_hdr (abfd) = NULL;
  bfd_section_list_clear (abfd);
  return NULL;
}