rescoff.c

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

C
786
字号
  struct bindata_build dataents;  /* Actual resource data.  */  struct bindata_build resources;  /* Relocations.  */  arelent **relocs;  /* Number of relocations.  */  unsigned int reloc_count;};/* Macros to swap out values.  */#define putcwi_16(cwi, v, s) \  ((cwi->big_endian) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))#define putcwi_32(cwi, v, s) \  ((cwi->big_endian) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))static void coff_bin_sizes  PARAMS ((const struct res_directory *, struct coff_write_info *));static unsigned char *coff_alloc PARAMS ((struct bindata_build *, size_t));static void coff_to_bin  PARAMS ((const struct res_directory *, struct coff_write_info *));static void coff_res_to_bin  PARAMS ((const struct res_resource *, struct coff_write_info *));/* Write resources to a COFF file.  RESOURCES should already be   sorted.   Right now we always create a new file.  Someday we should also   offer the ability to merge resources into an existing file.  This   would require doing the basic work of objcopy, just modifying or   adding the .rsrc section.  */voidwrite_coff_file (filename, target, resources)     const char *filename;     const char *target;     const struct res_directory *resources;{  bfd *abfd;  asection *sec;  struct coff_write_info cwi;  struct bindata *d;  unsigned long length, offset;  if (filename == NULL)    fatal (_("filename required for COFF output"));  abfd = bfd_openw (filename, target);  if (abfd == NULL)    bfd_fatal (filename);  if (! bfd_set_format (abfd, bfd_object))    bfd_fatal ("bfd_set_format");#if defined DLLTOOL_SH  if (! bfd_set_arch_mach (abfd, bfd_arch_sh, 0))    bfd_fatal ("bfd_set_arch_mach(sh)");#elif defined DLLTOOL_MIPS  if (! bfd_set_arch_mach (abfd, bfd_arch_mips, 0))    bfd_fatal ("bfd_set_arch_mach(mips)");#elif defined DLLTOOL_ARM  if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0))    bfd_fatal ("bfd_set_arch_mach(arm)");#else  /* FIXME: This is obviously i386 specific.  */  if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0))    bfd_fatal ("bfd_set_arch_mach(i386)");#endif  if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC))    bfd_fatal ("bfd_set_file_flags");  sec = bfd_make_section (abfd, ".rsrc");  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");  if (! bfd_set_symtab (abfd, sec->symbol_ptr_ptr, 1))    bfd_fatal ("bfd_set_symtab");  /* Requiring this is probably a bug in BFD.  */  sec->output_section = sec;  /* The order of data in the .rsrc section is       resource directory tables and entries       resource directory strings       resource data entries       actual resource data     We build these different types of data in different lists.  */  cwi.abfd = abfd;  cwi.big_endian = bfd_big_endian (abfd);  cwi.sympp = sec->symbol_ptr_ptr;  cwi.dirsize = 0;  cwi.dirstrsize = 0;  cwi.dataentsize = 0;  cwi.dirs.d = NULL;  cwi.dirs.last = NULL;  cwi.dirs.length = 0;  cwi.dirstrs.d = NULL;  cwi.dirstrs.last = NULL;  cwi.dirstrs.length = 0;  cwi.dataents.d = NULL;  cwi.dataents.last = NULL;  cwi.dataents.length = 0;  cwi.resources.d = NULL;  cwi.resources.last = NULL;  cwi.resources.length = 0;  cwi.relocs = NULL;  cwi.reloc_count = 0;  /* Work out the sizes of the resource directory entries, so that we     know the various offsets we will need.  */  coff_bin_sizes (resources, &cwi);  /* Force the directory strings to be 32 bit aligned.  Every other     structure is 32 bit aligned anyhow.  */  cwi.dirstrsize = (cwi.dirstrsize + 3) &~ 3;  /* Actually convert the resources to binary.  */  coff_to_bin (resources, &cwi);  /* Add another 2 bytes to the directory strings if needed for     alignment.  */  if ((cwi.dirstrs.length & 3) != 0)    {      unsigned char *ex;      ex = coff_alloc (&cwi.dirstrs, 2);      ex[0] = 0;      ex[1] = 0;    }  /* Make sure that the data we built came out to the same size as we     calculated initially.  */  assert (cwi.dirs.length == cwi.dirsize);  assert (cwi.dirstrs.length == cwi.dirstrsize);  assert (cwi.dataents.length == cwi.dataentsize);  length = (cwi.dirsize	    + cwi.dirstrsize	    + cwi.dataentsize	    + cwi.resources.length);  if (! bfd_set_section_size (abfd, sec, length))    bfd_fatal ("bfd_set_section_size");  bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count);  offset = 0;  for (d = cwi.dirs.d; d != NULL; d = d->next)    {      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))	bfd_fatal ("bfd_set_section_contents");      offset += d->length;    }  for (d = cwi.dirstrs.d; d != NULL; d = d->next)    {      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))	bfd_fatal ("bfd_set_section_contents");      offset += d->length;    }  for (d = cwi.dataents.d; d != NULL; d = d->next)    {      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))	bfd_fatal ("bfd_set_section_contents");      offset += d->length;    }  for (d = cwi.resources.d; d != NULL; d = d->next)    {      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))	bfd_fatal ("bfd_set_section_contents");      offset += d->length;    }  assert (offset == length);  if (! bfd_close (abfd))    bfd_fatal ("bfd_close");  /* We allocated the relocs array using malloc.  */  free (cwi.relocs);}/* Work out the sizes of the various fixed size resource directory   entries.  This updates fields in CWI.  */static voidcoff_bin_sizes (resdir, cwi)     const struct res_directory *resdir;     struct coff_write_info *cwi;{  const struct res_entry *re;  cwi->dirsize += sizeof (struct extern_res_directory);  for (re = resdir->entries; re != NULL; re = re->next)    {      cwi->dirsize += sizeof (struct extern_res_entry);      if (re->id.named)	cwi->dirstrsize += re->id.u.n.length * 2 + 2;      if (re->subdir)	coff_bin_sizes (re->u.dir, cwi);      else	cwi->dataentsize += sizeof (struct extern_res_data);    }}/* Allocate data for a particular list.  */static unsigned char *coff_alloc (bb, size)     struct bindata_build *bb;     size_t size;{  struct bindata *d;  d = (struct bindata *) reswr_alloc (sizeof *d);  d->next = NULL;  d->data = (unsigned char *) reswr_alloc (size);  d->length = size;  if (bb->d == NULL)    bb->d = d;  else    bb->last->next = d;  bb->last = d;  bb->length += size;  return d->data;}/* Convert the resource directory RESDIR to binary.  */static voidcoff_to_bin (resdir, cwi)     const struct res_directory *resdir;     struct coff_write_info *cwi;{  struct extern_res_directory *erd;  int ci, cn;  const struct res_entry *e;  struct extern_res_entry *ere;  /* Write out the directory table.  */  erd = ((struct extern_res_directory *)	 coff_alloc (&cwi->dirs, sizeof (*erd)));  putcwi_32 (cwi, resdir->characteristics, erd->characteristics);  putcwi_32 (cwi, resdir->time, erd->time);  putcwi_16 (cwi, resdir->major, erd->major);  putcwi_16 (cwi, resdir->minor, erd->minor);  ci = 0;  cn = 0;  for (e = resdir->entries; e != NULL; e = e->next)    {      if (e->id.named)	++cn;      else	++ci;    }  putcwi_16 (cwi, cn, erd->name_count);  putcwi_16 (cwi, ci, erd->id_count);  /* Write out the data entries.  Note that we allocate space for all     the entries before writing them out.  That permits a recursive     call to work correctly when writing out subdirectories.  */  ere = ((struct extern_res_entry *)	 coff_alloc (&cwi->dirs, (ci + cn) * sizeof (*ere)));  for (e = resdir->entries; e != NULL; e = e->next, ere++)    {      if (! e->id.named)	putcwi_32 (cwi, e->id.u.id, ere->name);      else	{	  unsigned char *str;	  int i;	  /* For some reason existing files seem to have the high bit             set on the address of the name, although that is not             documented.  */	  putcwi_32 (cwi,		     0x80000000 | (cwi->dirsize + cwi->dirstrs.length),		     ere->name);	  str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2);	  putcwi_16 (cwi, e->id.u.n.length, str);	  for (i = 0; i < e->id.u.n.length; i++)	    putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2);	}      if (e->subdir)	{	  putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva);	  coff_to_bin (e->u.dir, cwi);	}      else	{	  putcwi_32 (cwi,		     cwi->dirsize + cwi->dirstrsize + cwi->dataents.length,		     ere->rva);	  coff_res_to_bin (e->u.res, cwi);	}    }}/* Convert the resource RES to binary.  */static voidcoff_res_to_bin (res, cwi)     const struct res_resource *res;     struct coff_write_info *cwi;{  arelent *r;  struct extern_res_data *erd;  struct bindata *d;  unsigned long length;  /* For some reason, although every other address is a section     offset, the address of the resource data itself is an RVA.  That     means that we need to generate a relocation for it.  We allocate     the relocs array using malloc so that we can use realloc.  FIXME:     This relocation handling is correct for the i386, but probably     not for any other target.  */  r = (arelent *) reswr_alloc (sizeof (arelent));  r->sym_ptr_ptr = cwi->sympp;  r->address = cwi->dirsize + cwi->dirstrsize + cwi->dataents.length;  r->addend = 0;  r->howto = bfd_reloc_type_lookup (cwi->abfd, BFD_RELOC_RVA);  if (r->howto == NULL)    bfd_fatal (_("can't get BFD_RELOC_RVA relocation type"));  cwi->relocs = xrealloc (cwi->relocs,			  (cwi->reloc_count + 2) * sizeof (arelent *));  cwi->relocs[cwi->reloc_count] = r;  cwi->relocs[cwi->reloc_count + 1] = NULL;  ++cwi->reloc_count;  erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd));  putcwi_32 (cwi,	     (cwi->dirsize	      + cwi->dirstrsize	      + cwi->dataentsize	      + cwi->resources.length),	     erd->rva);  putcwi_32 (cwi, res->coff_info.codepage, erd->codepage);  putcwi_32 (cwi, res->coff_info.reserved, erd->reserved);  d = res_to_bin (res, cwi->big_endian);  if (cwi->resources.d == NULL)    cwi->resources.d = d;  else    cwi->resources.last->next = d;  length = 0;  for (; d->next != NULL; d = d->next)    length += d->length;  length += d->length;  cwi->resources.last = d;  cwi->resources.length += length;  putcwi_32 (cwi, length, erd->size);  /* Force the next resource to have 32 bit alignment.  */  if ((length & 3) != 0)    {      int add;      unsigned char *ex;      add = 4 - (length & 3);      ex = coff_alloc (&cwi->resources, add);      memset (ex, 0, add);    }}

⌨️ 快捷键说明

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