Exemplo n.º 1
0
/* Write resource file */
void
write_res_file (const char *fn,const rc_res_directory *resdir)
{
  asection *sec;
  rc_uint_type language;
  bfd *abfd;
  windres_bfd wrbfd;
  unsigned long sec_length = 0,sec_length_wrote;
  static const bfd_byte sign[] =
  {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  filename = fn;

  abfd = windres_open_as_binary (filename, 0);
  sec = bfd_make_section (abfd, ".data");
  if (sec == NULL)
    bfd_fatal ("bfd_make_section");
  if (! bfd_set_section_flags (abfd, sec,
			       (SEC_HAS_CONTENTS | SEC_ALLOC
			        | SEC_LOAD | SEC_DATA)))
    bfd_fatal ("bfd_set_section_flags");
  /* Requiring this is probably a bug in BFD.  */
  sec->output_section = sec;

  set_windres_bfd (&wrbfd, abfd, sec,
		   (target_is_bigendian ? WR_KIND_BFD_BIN_B
					: WR_KIND_BFD_BIN_L));

  language = -1;
  sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir,
				    (const rc_res_id *) NULL,
				    (const rc_res_id *) NULL, &language, 1);
  if (! bfd_set_section_size (abfd, sec, (sec_length + 3) & ~3))
    bfd_fatal ("bfd_set_section_size");
  if ((sec_length & 3) != 0)
    set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3));
  set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign));
  language = -1;
  sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir,
					  (const rc_res_id *) NULL,
					  (const rc_res_id *) NULL,
					  &language, 1);
  if (sec_length != sec_length_wrote)
    fatal ("res write failed with different sizes (%lu/%lu).", (long) sec_length,
    	   (long) sec_length_wrote);

  bfd_close (abfd);
  return;
}
Exemplo n.º 2
0
static void
mips_elf32_after_open()
{
  /* Call the standard elf routine.  */
  gldelf32ltsmip_after_open ();

#ifdef SUPPORT_EMBEDDED_RELOCS
  if (command_line.embedded_relocs && (! link_info.relocateable))
    {  
      bfd *abfd;

      /* In the embedded relocs mode we create a .rel.sdata section for
	 each input file with a .sdata section which has has
	 relocations.  The BFD backend will fill in these sections
	 with magic numbers which can be used to relocate the data
	 section at run time.  */
      for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
        {
          asection *datasec;

	  /* As first-order business, make sure that each input BFD is
	     ELF.  We need to call a special BFD backend function to
	     generate the embedded relocs, and we have that function
	     only for ELF */

          if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
	    einfo ("%F%B: all input objects must be ELF for --embedded-relocs\n");

	  if (bfd_get_arch_size (abfd) != 32)
	    einfo ("%F%B: all input objects must be 32-bit ELF for --embedded-relocs\n");

          datasec = bfd_get_section_by_name (abfd, ".sdata");
  
          /* Note that we assume that the reloc_count field has already
             been set up.  We could call bfd_get_reloc_upper_bound, but
             that returns the size of a memory buffer rather than a reloc
             count.  We do not want to call bfd_canonicalize_reloc,
             because although it would always work it would force us to
             read in the relocs into BFD canonical form, which would waste
             a significant amount of time and memory.  */

          if (datasec != NULL && datasec->reloc_count > 0)
 	    {
              asection *relsec;
 
	      relsec = bfd_make_section (abfd, ".rel.sdata");
	      if (relsec == NULL
	          || ! bfd_set_section_flags (abfd, relsec,
					      (SEC_ALLOC
					       | SEC_LOAD
					       | SEC_HAS_CONTENTS
					       | SEC_IN_MEMORY))
                  || ! bfd_set_section_alignment (abfd, relsec,
						  (32 == 32) ? 2 : 3)
	          || ! bfd_set_section_size (abfd, relsec,
		  			     datasec->reloc_count
					     * ((32 / 8) + 8)))
	        einfo ("%F%B: cannot create .rel.sdata section: %E\n");
	    }

          /* Double check that all other data sections have no relocs,
             as is required for embedded PIC code.  */
          bfd_map_over_sections (abfd, mips_elf32_check_sections,
				 (PTR) datasec);
        }
    }
#endif /* SUPPORT_EMBEDDED_RELOCS */
}
Exemplo n.º 3
0
static void emit_so_bfd(const Chunk *base, uint64_t textOffs, uint64_t textLen,
                        std::vector<MethBlock> &blocks,
                        std::vector<DebugInfo> &debugInfos)
{
    bfd_init();

    bfd *abfd = bfd_openw("jit.o",
#ifdef __MACH__
                          "mach-o-i386"
#else
                          "elf32-i386"
#endif
)                          ;

    bfd_set_format(abfd, bfd_object);
#ifdef __MACH__
    bfd_set_arch_mach(abfd, bfd_arch_i386, bfd_mach_i386_i386);
#else
    bfd_set_arch_mach(abfd, bfd_arch_i386, bfd_mach_i386_i386);
#endif

    asection *textSection = bfd_make_section(abfd, ".text");

    bfd_set_section_flags(
            abfd, textSection,
            SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_HAS_CONTENTS);
#ifdef __MACH__
    bfd_set_section_size(abfd, textSection, textLen);
    // for mach-o, the .o we generate is linked into a .dylib
    // so just set the alignment to make sure things end up
    // in the right place after link
    textSection->alignment_power = l2(textOffs);

    static const uint64_t textAdj = 0;
#else
    bfd_set_section_size(abfd, textSection, textLen + textOffs);

    // for linux (and oprofile) the generated object is used
    // directly, so just offset the symbols
    uint64_t textAdj = textOffs;
#endif

    asymbol **symbols = (asymbol **) malloc(
            sizeof(asymbol *) * (6 + blocks.size()));
    uint64_t start = ((uint64_t *) base->data)[0] + textOffs;

    int n = 0;
    std::map<std::string, int> namesSeen;

    std::vector<MethBlock>::const_iterator i, e;

    symbols[n++] = make_glob_symbol(abfd, "__jitStart", textSection, textAdj);
    symbols[n++] = make_glob_symbol(abfd, "_jitStart", textSection, textAdj);

    for (i = blocks.begin(), e = blocks.end(); i != e; i++, n++) {
        std::string name = i->name();
        int seen = namesSeen[name]++;

        if (seen) {
            char buf[16];

            sprintf(buf, " (%d)", seen);
            name += buf;
        }
        symbols[n] = make_glob_symbol(abfd, name.c_str(), textSection,
                                      i->start() - start + textAdj);
    }
    symbols[n++] = make_glob_symbol(abfd, "__jitUnused", textSection,
                                    blocks.back().end() - start + textAdj);
    symbols[n++] = make_glob_symbol(abfd, "_jitUnused", textSection,
                                    blocks.back().end() - start + textAdj);
    symbols[n++] = make_glob_symbol(abfd, "__jitEnd", textSection,
                                    textLen + textAdj);
    symbols[n++] = make_glob_symbol(abfd, "_jitEnd", textSection,
                                    textLen + textAdj);

    bfd_set_symtab(abfd, symbols, n);

    for (i = blocks.begin(), e = blocks.end(); i != e; i++, n++)
        if (i->codeBytes())
            bfd_set_section_contents(abfd, textSection, i->codeBytes(),
                                     i->start() - start, i->codeLen());

    bfd_close(abfd);

    for (int n = 0; n < blocks.size(); n++)
        free((void *) symbols[n]->name);
    free(symbols);
}
int
_bfd_vms_slurp_gsd (bfd * abfd, int objtype)
{
  int gsd_type, gsd_size;
  asection *section;
  unsigned char *vms_rec;
  flagword new_flags, old_flags;
  char *name;
  asymbol *symbol;
  vms_symbol_entry *entry;
  unsigned long base_addr;
  unsigned long align_addr;
  static unsigned int psect_idx = 0;

#if VMS_DEBUG
  vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
#endif

  switch (objtype)
    {
    case EOBJ_S_C_EGSD:
      PRIV (vms_rec) += 8;	/* Skip type, size, l_temp.  */
      PRIV (rec_size) -= 8;
      break;
    case OBJ_S_C_GSD:
      PRIV (vms_rec) += 1;
      PRIV (rec_size) -= 1;
      break;
    default:
      return -1;
    }

  /* Calculate base address for each section.  */
  base_addr = 0L;

  abfd->symcount = 0;

  while (PRIV (rec_size) > 0)
    {
      vms_rec = PRIV (vms_rec);

      if (objtype == OBJ_S_C_GSD)
	gsd_type = vms_rec[0];
      else
	{
	  _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
	  gsd_type += EVAX_OFFSET;
	}

#if VMS_DEBUG
      vms_debug (3, "gsd_type %d\n", gsd_type);
#endif

      switch (gsd_type)
	{
	case GSD_S_C_PSC:
	  {
	    /* Program section definition.  */
	    asection *old_section = 0;

#if VMS_DEBUG
	    vms_debug (4, "GSD_S_C_PSC\n");
#endif
	    /* If this section isn't a bfd section.  */
	    if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
	      {
		/* Check for temporary section from TIR record.  */
		if (psect_idx < PRIV (section_count))
		  old_section = PRIV (sections)[psect_idx];
		else
		  old_section = 0;
	      }

	    name = _bfd_vms_save_counted_string (vms_rec + 8);
	    section = bfd_make_section (abfd, name);
	    if (!section)
	      {
		(*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
				       name);
		return -1;
	      }
	    old_flags = bfd_getl16 (vms_rec + 2);
	    section->size = bfd_getl32 (vms_rec + 4);  /* allocation */
	    new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
					     section->size > 0);
	    if (old_flags & EGPS_S_V_REL)
	      new_flags |= SEC_RELOC;
	    if (old_flags & GPS_S_M_OVR)
	      new_flags |= SEC_IS_COMMON;
	    if (!bfd_set_section_flags (abfd, section, new_flags))
	      {
		(*_bfd_error_handler)
		  (_("bfd_set_section_flags (%s, %x) failed"),
		   name, new_flags);
		return -1;
	      }
	    section->alignment_power = vms_rec[1];
	    align_addr = (1 << section->alignment_power);
	    if ((base_addr % align_addr) != 0)
	      base_addr += (align_addr - (base_addr % align_addr));
	    section->vma = (bfd_vma)base_addr;
	    base_addr += section->size;

	    /* Global section is common symbol.  */
	    if (old_flags & GPS_S_M_GBL)
	      {
		entry = _bfd_vms_enter_symbol (abfd, name);
		if (entry == NULL)
		  {
		    bfd_set_error (bfd_error_no_memory);
		    return -1;
		  }
		symbol = entry->symbol;

		symbol->value = 0;
		symbol->section = section;
		symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
	      }

	    /* Copy saved contents if old_section set.  */
	    if (old_section != 0)
	      {
		section->contents = old_section->contents;
		if (section->size < old_section->size)
		  {
		    (*_bfd_error_handler)
		      (_("Size mismatch section %s=%lx, %s=%lx"),
		       old_section->name,
		       (unsigned long) old_section->size,
		       section->name,
		       (unsigned long) section->size);
		    return -1;
		  }
		else if (section->size > old_section->size)
		  {
		    section->contents = bfd_realloc (old_section->contents,
						     section->size);
		    if (section->contents == NULL)
		      {
			bfd_set_error (bfd_error_no_memory);
			return -1;
		      }
		  }
	      }
	    else
	      {
		section->contents = bfd_zmalloc (section->size);
		if (section->contents == NULL)
		  {
		    bfd_set_error (bfd_error_no_memory);
		    return -1;
		  }
	      }
#if VMS_DEBUG
	    vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
		       section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
	    vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
		       section->size, section->vma, section->contents);
#endif

	    gsd_size = vms_rec[8] + 9;

	    psect_idx++;
	  }
	  break;

	case GSD_S_C_EPM:
	case GSD_S_C_EPMW:
#if VMS_DEBUG
	  vms_debug (4, "gsd epm\n");
#endif
	  /* Fall through.  */
	case GSD_S_C_SYM:
	case GSD_S_C_SYMW:
	  {
	    int name_offset = 0, value_offset = 0;

	    /* Symbol specification (definition or reference).  */
#if VMS_DEBUG
	    vms_debug (4, "GSD_S_C_SYM(W)\n");
#endif
	    old_flags = bfd_getl16 (vms_rec + 2);
	    new_flags = BSF_NO_FLAGS;

	    if (old_flags & GSY_S_M_WEAK)
	      new_flags |= BSF_WEAK;

	    switch (gsd_type)
	      {
	      case GSD_S_C_EPM:
		name_offset = 11;
		value_offset = 5;
		new_flags |= BSF_FUNCTION;
		break;
	      case GSD_S_C_EPMW:
		name_offset = 12;
		value_offset = 6;
		new_flags |= BSF_FUNCTION;
		break;
	      case GSD_S_C_SYM:
		if (old_flags & GSY_S_M_DEF)	/* Symbol definition.  */
		  name_offset = 9;
		else
		  name_offset = 4;
		value_offset = 5;
		break;
	      case GSD_S_C_SYMW:
		if (old_flags & GSY_S_M_DEF)	/* Symbol definition.  */
		  name_offset = 10;
		else
		  name_offset = 5;
		value_offset = 6;
		break;
	      }

	    /* Save symbol in vms_symbol_table.  */
	    entry = _bfd_vms_enter_symbol
	      (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset));
	    if (entry == NULL)
	      {
		bfd_set_error (bfd_error_no_memory);
		return -1;
	      }
	    symbol = entry->symbol;

	    if (old_flags & GSY_S_M_DEF)
	      {
		/* Symbol definition.  */
		int psect;

		symbol->value = bfd_getl32 (vms_rec + value_offset);
		if ((gsd_type == GSD_S_C_SYMW)
		    || (gsd_type == GSD_S_C_EPMW))
		  psect = bfd_getl16 (vms_rec + value_offset - 2);
		else
		  psect = vms_rec[value_offset-1];

		symbol->section = (asection *)(unsigned long)psect;
#if VMS_DEBUG
		vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
			  symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
#endif
	      }
	    else
	      {
		/* Symbol reference.  */
#if VMS_DEBUG
		vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
			   symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
#endif
		symbol->section = (asection *)(unsigned long)-1;
	      }

	    gsd_size = vms_rec[name_offset] + name_offset + 1;
	    symbol->flags = new_flags;
	  }

	  break;

	case GSD_S_C_PRO:
	case GSD_S_C_PROW:
#if VMS_DEBUG
	  vms_debug (4, "gsd pro\n");
#endif
	  break;
	case GSD_S_C_IDC:
#if VMS_DEBUG
	  vms_debug (4, "gsd idc\n");
#endif
	  break;
	case GSD_S_C_ENV:
#if VMS_DEBUG
	  vms_debug (4, "gsd env\n");
#endif
	  break;
	case GSD_S_C_LSY:
#if VMS_DEBUG
	  vms_debug (4, "gsd lsy\n");
#endif
	  break;
	case GSD_S_C_LEPM:
#if VMS_DEBUG
	  vms_debug (4, "gsd lepm\n");
#endif
	  break;
	case GSD_S_C_LPRO:
#if VMS_DEBUG
	  vms_debug (4, "gsd lpro\n");
#endif
	  break;
	case GSD_S_C_SPSC:
#if VMS_DEBUG
	  vms_debug (4, "gsd spsc\n");
#endif
	  break;
	case GSD_S_C_SYMV:
#if VMS_DEBUG
	  vms_debug (4, "gsd symv\n");
#endif
	  break;
	case GSD_S_C_EPMV:
#if VMS_DEBUG
	  vms_debug (4, "gsd epmv\n");
#endif
	  break;
	case GSD_S_C_PROV:
#if VMS_DEBUG
	  vms_debug (4, "gsd prov\n");
#endif
	  break;

	case EGSD_S_C_PSC + EVAX_OFFSET:
	  {
	    /* Program section definition.  */
	    name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
	    section = bfd_make_section (abfd, name);
	    if (!section)
	      return -1;
	    old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
	    section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
	    new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
					     section->size > 0);
	    if (old_flags & EGPS_S_V_REL)
	      new_flags |= SEC_RELOC;
	    if (!bfd_set_section_flags (abfd, section, new_flags))
	      return -1;
	    section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
	    align_addr = (1 << section->alignment_power);
	    if ((base_addr % align_addr) != 0)
	      base_addr += (align_addr - (base_addr % align_addr));
	    section->vma = (bfd_vma)base_addr;
	    base_addr += section->size;
	    section->contents = bfd_zmalloc (section->size);
	    if (section->contents == NULL)
	      return -1;
	    section->filepos = (unsigned int)-1;
#if VMS_DEBUG
	    vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
		       section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
	    vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
		       section->size, section->vma, section->contents);
#endif
	  }
	  break;

	case EGSD_S_C_SYM + EVAX_OFFSET:
	  {
	    /* Global symbol specification (definition or reference).  */
	    symbol = bfd_make_empty_symbol (abfd);
	    if (symbol == 0)
	      return -1;

	    old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
	    new_flags = BSF_NO_FLAGS;

	    if (old_flags & EGSY_S_V_WEAK)
	      new_flags |= BSF_WEAK;

	    if (old_flags & EGSY_S_V_DEF)
	      {
		/* Symbol definition.  */
		if (old_flags & EGSY_S_V_NORM)
		  new_flags |= BSF_FUNCTION;
		symbol->name =
		  _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
		symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
		symbol->section =
		  (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
#if VMS_DEBUG
		vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
			   abfd->symcount, symbol->name, (long)symbol->section,
			   old_flags, flag2str (gsyflagdesc, old_flags));
#endif
	      }
	    else
	      {
		/* Symbol reference.  */
		symbol->name =
		  _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
#if VMS_DEBUG
		vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
			   abfd->symcount, symbol->name, old_flags,
			   flag2str (gsyflagdesc, old_flags));
#endif
		symbol->section = (asection *)(unsigned long)-1;
	      }

	    symbol->flags = new_flags;

	    /* Register symbol in VMS symbol table.  */
	    entry = (vms_symbol_entry *) bfd_hash_lookup
	      (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);

	    if (entry == NULL)
	      {
		bfd_set_error (bfd_error_no_memory);
		return -1;
	      }

	    if (entry->symbol != NULL)
	      {
		/* FIXME ?, DEC C generates this.  */
#if VMS_DEBUG
		vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
#endif
	      }
	    else
	      {
		entry->symbol = symbol;
		PRIV (gsd_sym_count)++;
		abfd->symcount++;
	      }
	  }
	  break;

	case EGSD_S_C_SYMG + EVAX_OFFSET:
	  {
	    /* Universal symbol specification (definition).  */
	    symbol = bfd_make_empty_symbol (abfd);
	    if (symbol == 0)
	      return -1;

	    old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
	    new_flags = BSF_NO_FLAGS;

	    if (old_flags & EGSY_S_V_WEAK)
	      new_flags |= BSF_WEAK;

	    if (old_flags & EGSY_S_V_DEF) /* symbol definition */
	      {
		if (old_flags & EGSY_S_V_NORM)
		  new_flags |= BSF_FUNCTION;

		symbol->name =
		  _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);

		/* For BSF_FUNCTION symbols, the entry point is in LP_1
		   and the descriptor in LP_2.  For other symbols, the
		   unique value is in LP_2.  */
		symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);

		/* Adding this offset is necessary in order for GDB to
		   read the DWARF-2 debug info from shared libraries.  */
		if (abfd->flags & DYNAMIC
		    && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
		  symbol->value += PRIV (symvva);
	      }
	    else /* symbol reference */
	      (*_bfd_error_handler) ("Invalid EGST reference");

	    symbol->flags = new_flags;

	    if (register_universal_symbol (abfd, symbol, old_flags) < 0)
	      return -1;

	    /* Make a second symbol for the entry point.  */
	    if (symbol->flags & BSF_FUNCTION)
	      {
		asymbol *en_sym;
		char *name = bfd_alloc (abfd, strlen (symbol->name) + 5);

		en_sym = bfd_make_empty_symbol (abfd);
		if (en_sym == 0)
		  return -1;

		strcpy (name, symbol->name);
		strcat (name, "..en");

		en_sym->name = name;
		en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);

		if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
		  return -1;
	      }
	  }
	  break;

	case EGSD_S_C_IDC + EVAX_OFFSET:
  	  break;

	default:
	  (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
	  bfd_set_error (bfd_error_bad_value);
	  return -1;
	}

      PRIV (rec_size) -= gsd_size;
      PRIV (vms_rec) += gsd_size;
    }

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

  return 0;
}
Exemplo n.º 5
0
static const bfd_target *
aout_adobe_callback (bfd *abfd)
{
  struct internal_exec *execp = exec_hdr (abfd);
  asection *sect;
  struct external_segdesc ext[1];
  char *section_name;
  char try_again[30];	/* Name and number.  */
  char *newname;
  int trynum;
  flagword flags;

  /* Architecture and machine type -- unknown in this format.  */
  bfd_set_arch_mach (abfd, bfd_arch_unknown, 0L);

  /* The positions of the string table and symbol table.  */
  obj_str_filepos (abfd) = N_STROFF (*execp);
  obj_sym_filepos (abfd) = N_SYMOFF (*execp);

  /* Suck up the section information from the file, one section at a time.  */
  for (;;)
    {
      bfd_size_type amt = sizeof (*ext);
      if (bfd_bread ( ext, amt, abfd) != amt)
	{
	  if (bfd_get_error () != bfd_error_system_call)
	    bfd_set_error (bfd_error_wrong_format);

	  return NULL;
	}
      switch (ext->e_type[0])
	{
	case N_TEXT:
	  section_name = ".text";
	  flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
	  break;

	case N_DATA:
	  section_name = ".data";
	  flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
	  break;

	case N_BSS:
	  section_name = ".bss";
	  flags = SEC_DATA | SEC_HAS_CONTENTS;
	  break;

	case 0:
	  goto no_more_sections;

	default:
	  (*_bfd_error_handler)
	    (_("%B: Unknown section type in a.out.adobe file: %x\n"),
	     abfd, ext->e_type[0]);
	  goto no_more_sections;
	}

      /* First one is called ".text" or whatever; subsequent ones are
	 ".text1", ".text2", ...  */
      bfd_set_error (bfd_error_no_error);
      sect = bfd_make_section (abfd, section_name);
      trynum = 0;

      while (!sect)
	{
	  if (bfd_get_error () != bfd_error_no_error)
	    /* Some other error -- slide into the sunset.  */
	    return NULL;
	  sprintf (try_again, "%s%d", section_name, ++trynum);
	  sect = bfd_make_section (abfd, try_again);
	}

      /* Fix the name, if it is a sprintf'd name.  */
      if (sect->name == try_again)
	{
	  amt = strlen (sect->name);
	  newname = bfd_zalloc (abfd, amt);
	  if (newname == NULL)
	    return NULL;
	  strcpy (newname, sect->name);
	  sect->name = newname;
	}

      /* Now set the section's attributes.  */
      bfd_set_section_flags (abfd, sect, flags);
      /* Assumed big-endian.  */
      sect->size = ((ext->e_size[0] << 8)
		    | ext->e_size[1] << 8
		    | ext->e_size[2]);
      sect->vma = H_GET_32 (abfd, ext->e_virtbase);
      sect->filepos = H_GET_32 (abfd, ext->e_filebase);
      /* FIXME XXX alignment?  */

      /* Set relocation information for first section of each type.  */
      if (trynum == 0)
	switch (ext->e_type[0])
	  {
	  case N_TEXT:
	    sect->rel_filepos = N_TRELOFF (*execp);
	    sect->reloc_count = execp->a_trsize;
	    break;

	  case N_DATA:
	    sect->rel_filepos = N_DRELOFF (*execp);
	    sect->reloc_count = execp->a_drsize;
	    break;

	  default:
	    break;
	  }
    }
 no_more_sections:

  adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
  adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
  adata (abfd).page_size = 1; /* Not applicable.  */
  adata (abfd).segment_size = 1; /* Not applicable.  */
  adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;

  return abfd->xvec;
}
Exemplo n.º 6
0
/* Process GSD/EGSD record.
 * Return 0 on success, -1 on error.  */
int
_bfd_vms_slurp_gsd(bfd * abfd, int objtype)
{
#if defined(VMS_DEBUG) && VMS_DEBUG
  static struct flagdescstruct gpsflagdesc[] =
    {
      { "PIC", 0x0001 },
      { "LIB", 0x0002 },
      { "OVR", 0x0004 },
      { "REL", 0x0008 },
      { "GBL", 0x0010 },
      { "SHR", 0x0020 },
      { "EXE", 0x0040 },
      { "RD",  0x0080 },
      { "WRT", 0x0100 },
      { "VEC", 0x0200 },
      { "NOMOD", 0x0400 },
      { "COM", 0x0800 },
      { NULL, 0 }
    };

  static struct flagdescstruct gsyflagdesc[] =
    {
      { "WEAK", 0x0001 },
      { "DEF",  0x0002 },
      { "UNI",  0x0004 },
      { "REL",  0x0008 },
      { "COMM", 0x0010 },
      { "VECEP", 0x0020 },
      { "NORM", 0x0040 },
      { NULL, 0 }
    };
#endif /* VMS_DEBUG */

  int gsd_type, gsd_size;
  asection *section;
  unsigned char *vms_rec;
  flagword new_flags, old_flags;
  char *name;
  asymbol *symbol;
  vms_symbol_entry *entry;
  unsigned long base_addr;
  unsigned long align_addr;
  static unsigned int psect_idx = 0;

  gsd_size = 0;

#if defined(VMS_DEBUG) && VMS_DEBUG
  vms_debug(2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
#endif /* VMS_DEBUG */

  switch (objtype)
    {
    case EOBJ_S_C_EGSD:
      PRIV(vms_rec) += 8;	/* Skip type, size, l_temp.  */
      PRIV(rec_size) -= 8;
      break;
    case OBJ_S_C_GSD:
      PRIV(vms_rec) += 1;
      PRIV(rec_size) -= 1;
      break;
    default:
      return -1;
    }

  /* Calculate base address for each section: */
  base_addr = 0L;

  abfd->symcount = 0;

  while (PRIV(rec_size) > 0)
    {
      vms_rec = PRIV(vms_rec);

      if (objtype == OBJ_S_C_GSD)
	gsd_type = *vms_rec;
      else
	{
	  _bfd_vms_get_header_values(abfd, vms_rec, &gsd_type, &gsd_size);
	  gsd_type += EVAX_OFFSET;
	}

#if defined(VMS_DEBUG) && VMS_DEBUG
      vms_debug (3, "gsd_type %d\n", gsd_type);
#endif

      switch (gsd_type)
	{
	case GSD_S_C_PSC:
	  {
	    /* Program section definition.  */
	    asection *old_section = 0;

#if defined(VMS_DEBUG) && VMS_DEBUG
	    vms_debug (4, "GSD_S_C_PSC\n");
#endif
	    /* If this section isn't a bfd section.  */
	    if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1)))
	      {
		/* Check for temporary section from TIR record.  */
		if (psect_idx < PRIV (section_count))
		  old_section = PRIV (sections)[psect_idx];
		else
		  old_section = 0;
	      }

	    name = _bfd_vms_save_counted_string (vms_rec + 8);
	    section = bfd_make_section (abfd, name);
	    if (!section)
	      {
		(*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
				       name);
		return -1;
	      }
	    old_flags = bfd_getl16 (vms_rec + 2);
	    section->size = bfd_getl32 (vms_rec + 4);  /* allocation */
	    new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
					     section->size > 0);
	    if (old_flags & EGPS_S_V_REL)
	      new_flags |= SEC_RELOC;
	    if (old_flags & GPS_S_M_OVR)
	      new_flags |= SEC_IS_COMMON;
	    if (!bfd_set_section_flags (abfd, section, new_flags))
	      {
		(*_bfd_error_handler)
		  (_("bfd_set_section_flags (%s, %x) failed"),
		   name, new_flags);
		return -1;
	      }
	    section->alignment_power = vms_rec[1];
	    align_addr = (1 << section->alignment_power);
	    if ((base_addr % align_addr) != 0)
	      base_addr += (align_addr - (base_addr % align_addr));
	    section->vma = (bfd_vma)base_addr;
	    base_addr += section->size;

	    /* Global section is common symbol.  */

	    if (old_flags & GPS_S_M_GBL)
	      {
		entry = _bfd_vms_enter_symbol (abfd, name);
		if (entry == NULL)
		  {
		    bfd_set_error (bfd_error_no_memory);
		    return -1;
		  }
		symbol = entry->symbol;

		symbol->value = 0;
		symbol->section = section;
		symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
	      }

	    /* Copy saved contents if old_section set.  */
	    if (old_section != 0)
	      {
		section->contents = old_section->contents;
		if (section->size < old_section->size)
		  {
		    (*_bfd_error_handler)
		      (_("Size mismatch section %s=%lx, %s=%lx"),
		       old_section->name,
		       (unsigned long) old_section->size,
		       section->name,
		       (unsigned long) section->size);
		    return -1;
		  }
		else if (section->size > old_section->size)
		  {
		    section->contents = (unsigned char *)bfd_realloc(old_section->contents,
                                                                     section->size);
		    if (section->contents == NULL)
		      {
			bfd_set_error (bfd_error_no_memory);
			return -1;
		      }
		  }
	      }
	    else
	      {
		section->contents = (unsigned char *)bfd_zmalloc(section->size);
		if (section->contents == NULL)
		  {
		    bfd_set_error (bfd_error_no_memory);
		    return -1;
		  }
	      }
#if defined(VMS_DEBUG) && VMS_DEBUG
	    vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
		       section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
	    vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
		       section->size, section->vma, section->contents);
#endif /* VMS_DEBUG */

	    gsd_size = vms_rec[8] + 9;

	    psect_idx++;
	  }
	  break;

	case GSD_S_C_EPM:
	case GSD_S_C_EPMW:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd epm\n");
#endif
	  /* Fall through.  */
	case GSD_S_C_SYM:
	case GSD_S_C_SYMW:
	  {
	    int name_offset = 0, value_offset = 0;

	    /* Symbol specification (definition or reference).  */
#if defined(VMS_DEBUG) && VMS_DEBUG
	    vms_debug(4, "GSD_S_C_SYM(W)\n");
#endif
	    old_flags = bfd_getl16 (vms_rec + 2);
	    new_flags = BSF_NO_FLAGS;

	    if (old_flags & GSY_S_M_WEAK)
	      new_flags |= BSF_WEAK;

	    switch (gsd_type) {
	      case GSD_S_C_EPM:
		name_offset = 11;
		value_offset = 5;
		new_flags |= BSF_FUNCTION;
		break;
	      case GSD_S_C_EPMW:
		name_offset = 12;
		value_offset = 6;
		new_flags |= BSF_FUNCTION;
		break;
	      case GSD_S_C_SYM:
		if (old_flags & GSY_S_M_DEF)	/* Symbol definition.  */
		  name_offset = 9;
		else
		  name_offset = 4;
		value_offset = 5;
		break;
	      case GSD_S_C_SYMW:
		if (old_flags & GSY_S_M_DEF)	/* Symbol definition.  */
		  name_offset = 10;
		else
		  name_offset = 5;
		value_offset = 6;
		break;
              default:
                break;
	    } /* end "switch (gsd_type)" */

	    /* Save symbol in vms_symbol_table: */
	    entry
              = _bfd_vms_enter_symbol(abfd,
                                      _bfd_vms_save_counted_string(vms_rec + name_offset));
	    if (entry == NULL)
	      {
		bfd_set_error (bfd_error_no_memory);
		return -1;
	      }
	    symbol = entry->symbol;

	    if (old_flags & GSY_S_M_DEF)
	      {
		/* Symbol definition.  */
		int psect;

		symbol->value = bfd_getl32 (vms_rec + value_offset);
		if ((gsd_type == GSD_S_C_SYMW)
		    || (gsd_type == GSD_S_C_EPMW))
		  psect = bfd_getl16 (vms_rec + value_offset - 2);
		else
		  psect = vms_rec[value_offset-1];

		symbol->section = (asection *) (size_t) psect;
#if defined(VMS_DEBUG) && VMS_DEBUG
		vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount,
			   symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
#endif
	      }
	    else
	      {
		/* Symbol reference.  */
		symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
#if defined(VMS_DEBUG) && VMS_DEBUG
		vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n",
			   abfd->symcount, symbol->name, symbol->section->name,
			   symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
#endif
	      }

	    gsd_size = vms_rec[name_offset] + name_offset + 1;
	    symbol->flags = new_flags;
	  }

	  break;

	case GSD_S_C_PRO:
	case GSD_S_C_PROW:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd pro\n");
#endif
	  break;
	case GSD_S_C_IDC:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd idc\n");
#endif
	  break;
	case GSD_S_C_ENV:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd env\n");
#endif
	  break;
	case GSD_S_C_LSY:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd lsy\n");
#endif
	  break;
	case GSD_S_C_LEPM:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd lepm\n");
#endif
	  break;
	case GSD_S_C_LPRO:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd lpro\n");
#endif
	  break;
	case GSD_S_C_SPSC:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd spsc\n");
#endif
	  break;
	case GSD_S_C_SYMV:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd symv\n");
#endif
	  break;
	case GSD_S_C_EPMV:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd epmv\n");
#endif
	  break;
	case GSD_S_C_PROV:
#if defined(VMS_DEBUG) && VMS_DEBUG
	  vms_debug (4, "gsd prov\n");
#endif
	  break;

	case EGSD_S_C_PSC + EVAX_OFFSET:
	  {
	    /* Program section definition.  */
	    name = _bfd_vms_save_counted_string (vms_rec + 12);
	    section = bfd_make_section (abfd, name);
	    if (!section)
	      return -1;
	    old_flags = bfd_getl16 (vms_rec + 6);
	    section->size = bfd_getl32 (vms_rec + 8);	/* Allocation.  */
	    new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
					     section->size > 0);
	    if (old_flags & EGPS_S_V_REL)
	      new_flags |= SEC_RELOC;
	    if (!bfd_set_section_flags (abfd, section, new_flags))
	      return -1;
	    section->alignment_power = vms_rec[4];
	    align_addr = (1 << section->alignment_power);
	    if ((base_addr % align_addr) != 0)
	      base_addr += (align_addr - (base_addr % align_addr));
	    section->vma = (bfd_vma)base_addr;
	    base_addr += section->size;
	    section->contents = (unsigned char *)bfd_zmalloc(section->size);
	    if (section->contents == NULL)
	      return -1;
#if defined(VMS_DEBUG) && VMS_DEBUG
	    vms_debug (4, "egsd psc %d (%s, flags %04x=%s) ",
		       section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
	    vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
		       section->size, section->vma, section->contents);
#endif
	  }
	  break;

	case EGSD_S_C_SYM + EVAX_OFFSET:
	  {
	    /* Symbol specification (definition or reference).  */
	    symbol = bfd_make_empty_symbol (abfd);
	    if (symbol == 0)
	      return -1;

	    old_flags = bfd_getl16 (vms_rec + 6);
	    new_flags = BSF_NO_FLAGS;

	    if (old_flags & EGSY_S_V_WEAK)
	      new_flags |= BSF_WEAK;

	    if (vms_rec[6] & EGSY_S_V_DEF)
	      {
		/* Symbol definition.  */
		symbol->name = _bfd_vms_save_counted_string (vms_rec + 32);
		if (old_flags & EGSY_S_V_NORM)
		  /* Proc def.  */
		  new_flags |= BSF_FUNCTION;

		symbol->value = bfd_getl64 (vms_rec + 8);
		symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28));
#if defined(VMS_DEBUG) && VMS_DEBUG
		vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount,
			   symbol->name, (int) symbol->section, old_flags,
			   flag2str (gsyflagdesc, old_flags));
#endif
	      }
	    else
	      {
		/* Symbol reference.  */
		symbol->name = _bfd_vms_save_counted_string (vms_rec + 8);
#if defined(VMS_DEBUG) && VMS_DEBUG
		vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
			  symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
#endif
		symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
	      }

	    symbol->flags = new_flags;

	    /* Save symbol in vms_symbol_table: */
	    entry = (vms_symbol_entry *)bfd_hash_lookup(PRIV(vms_symbol_table),
                                                        symbol->name,
                                                        TRUE, FALSE);
	    if (entry == NULL)
	      {
		bfd_set_error(bfd_error_no_memory);
		return -1;
	      }

	    if (entry->symbol != NULL)
	      {
		/* FIXME ?, DEC C generates this.  */
#if defined(VMS_DEBUG) && VMS_DEBUG
		vms_debug(4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
#endif /* VMS_DEBUG */
	      }
	    else
	      {
		entry->symbol = symbol;
		PRIV(gsd_sym_count)++;
		abfd->symcount++;
	      }
	  }
	  break;

	case EGSD_S_C_IDC + EVAX_OFFSET:
	  break;

	default:
	  (*_bfd_error_handler)(_("unknown gsd/egsd subtype %d"), gsd_type);
	  bfd_set_error(bfd_error_bad_value);
	  return -1;
	}

      PRIV(rec_size) -= gsd_size;
      PRIV(vms_rec) += gsd_size;
    }

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

  return 0;
}