1/* rescoff.c -- read and write resources in Windows COFF files.
2   Copyright 1997, 1998, 1999, 2000, 2003
3   Free Software Foundation, Inc.
4   Written by Ian Lance Taylor, Cygnus Support.
5
6   This file is part of GNU Binutils.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21   02110-1301, USA.  */
22
23/* This file contains function that read and write Windows resources
24   in COFF files.  */
25
26#include "bfd.h"
27#include "bucomm.h"
28#include "libiberty.h"
29#include "windres.h"
30
31#include <assert.h>
32
33/* In order to use the address of a resource data entry, we need to
34   get the image base of the file.  Right now we extract it from
35   internal BFD information.  FIXME.  */
36
37#include "coff/internal.h"
38#include "libcoff.h"
39
40/* Information we extract from the file.  */
41
42struct coff_file_info
43{
44  /* File name.  */
45  const char *filename;
46  /* Data read from the file.  */
47  const bfd_byte *data;
48  /* End of data read from file.  */
49  const bfd_byte *data_end;
50  /* Address of the resource section minus the image base of the file.  */
51  bfd_vma secaddr;
52  /* Non-zero if the file is big endian.  */
53  int big_endian;
54};
55
56/* A resource directory table in a COFF file.  */
57
58struct extern_res_directory
59{
60  /* Characteristics.  */
61  bfd_byte characteristics[4];
62  /* Time stamp.  */
63  bfd_byte time[4];
64  /* Major version number.  */
65  bfd_byte major[2];
66  /* Minor version number.  */
67  bfd_byte minor[2];
68  /* Number of named directory entries.  */
69  bfd_byte name_count[2];
70  /* Number of directory entries with IDs.  */
71  bfd_byte id_count[2];
72};
73
74/* A resource directory entry in a COFF file.  */
75
76struct extern_res_entry
77{
78  /* Name or ID.  */
79  bfd_byte name[4];
80  /* Address of resource entry or subdirectory.  */
81  bfd_byte rva[4];
82};
83
84/* A resource data entry in a COFF file.  */
85
86struct extern_res_data
87{
88  /* Address of resource data.  This is apparently a file relative
89     address, rather than a section offset.  */
90  bfd_byte rva[4];
91  /* Size of resource data.  */
92  bfd_byte size[4];
93  /* Code page.  */
94  bfd_byte codepage[4];
95  /* Reserved.  */
96  bfd_byte reserved[4];
97};
98
99/* Macros to swap in values.  */
100
101#define getfi_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s))
102#define getfi_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s))
103
104/* Local functions.  */
105
106static void overrun (const struct coff_file_info *, const char *);
107static struct res_directory *read_coff_res_dir
108  (const bfd_byte *, const struct coff_file_info *,
109   const struct res_id *, int);
110static struct res_resource *read_coff_data_entry
111  (const bfd_byte *, const struct coff_file_info *, const struct res_id *);
112
113/* Read the resources in a COFF file.  */
114
115struct res_directory *
116read_coff_rsrc (const char *filename, const char *target)
117{
118  bfd *abfd;
119  char **matching;
120  asection *sec;
121  bfd_size_type size;
122  bfd_byte *data;
123  struct coff_file_info finfo;
124
125  if (filename == NULL)
126    fatal (_("filename required for COFF input"));
127
128  abfd = bfd_openr (filename, target);
129  if (abfd == NULL)
130    bfd_fatal (filename);
131
132  if (! bfd_check_format_matches (abfd, bfd_object, &matching))
133    {
134      bfd_nonfatal (bfd_get_filename (abfd));
135      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
136	list_matching_formats (matching);
137      xexit (1);
138    }
139
140  sec = bfd_get_section_by_name (abfd, ".rsrc");
141  if (sec == NULL)
142    {
143      fatal (_("%s: no resource section"), filename);
144    }
145
146  size = bfd_section_size (abfd, sec);
147  data = (bfd_byte *) res_alloc (size);
148
149  if (! bfd_get_section_contents (abfd, sec, data, 0, size))
150    bfd_fatal (_("can't read resource section"));
151
152  finfo.filename = filename;
153  finfo.data = data;
154  finfo.data_end = data + size;
155  finfo.secaddr = (bfd_get_section_vma (abfd, sec)
156		   - pe_data (abfd)->pe_opthdr.ImageBase);
157  finfo.big_endian = bfd_big_endian (abfd);
158
159  bfd_close (abfd);
160
161  /* Now just read in the top level resource directory.  Note that we
162     don't free data, since we create resource entries that point into
163     it.  If we ever want to free up the resource information we read,
164     this will have to be cleaned up.  */
165
166  return read_coff_res_dir (data, &finfo, (const struct res_id *) NULL, 0);
167}
168
169/* Give an error if we are out of bounds.  */
170
171static void
172overrun (const struct coff_file_info *finfo, const char *msg)
173{
174  fatal (_("%s: %s: address out of bounds"), finfo->filename, msg);
175}
176
177/* Read a resource directory.  */
178
179static struct res_directory *
180read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
181		   const struct res_id *type, int level)
182{
183  const struct extern_res_directory *erd;
184  struct res_directory *rd;
185  int name_count, id_count, i;
186  struct res_entry **pp;
187  const struct extern_res_entry *ere;
188
189  if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_directory))
190    overrun (finfo, _("directory"));
191
192  erd = (const struct extern_res_directory *) data;
193
194  rd = (struct res_directory *) res_alloc (sizeof *rd);
195  rd->characteristics = getfi_32 (finfo, erd->characteristics);
196  rd->time = getfi_32 (finfo, erd->time);
197  rd->major = getfi_16 (finfo, erd->major);
198  rd->minor = getfi_16 (finfo, erd->minor);
199  rd->entries = NULL;
200
201  name_count = getfi_16 (finfo, erd->name_count);
202  id_count = getfi_16 (finfo, erd->id_count);
203
204  pp = &rd->entries;
205
206  /* The resource directory entries immediately follow the directory
207     table.  */
208  ere = (const struct extern_res_entry *) (erd + 1);
209
210  for (i = 0; i < name_count; i++, ere++)
211    {
212      unsigned long name, rva;
213      struct res_entry *re;
214      const bfd_byte *ers;
215      int length, j;
216
217      if ((const bfd_byte *) ere >= finfo->data_end)
218	overrun (finfo, _("named directory entry"));
219
220      name = getfi_32 (finfo, ere->name);
221      rva = getfi_32 (finfo, ere->rva);
222
223      /* For some reason the high bit in NAME is set.  */
224      name &=~ 0x80000000;
225
226      if (name > (size_t) (finfo->data_end - finfo->data))
227	overrun (finfo, _("directory entry name"));
228
229      ers = finfo->data + name;
230
231      re = (struct res_entry *) res_alloc (sizeof *re);
232      re->next = NULL;
233      re->id.named = 1;
234      length = getfi_16 (finfo, ers);
235      re->id.u.n.length = length;
236      re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar));
237      for (j = 0; j < length; j++)
238	re->id.u.n.name[j] = getfi_16 (finfo, ers + j * 2 + 2);
239
240      if (level == 0)
241	type = &re->id;
242
243      if ((rva & 0x80000000) != 0)
244	{
245	  rva &=~ 0x80000000;
246	  if (rva >= (size_t) (finfo->data_end - finfo->data))
247	    overrun (finfo, _("named subdirectory"));
248	  re->subdir = 1;
249	  re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
250					 level + 1);
251	}
252      else
253	{
254	  if (rva >= (size_t) (finfo->data_end - finfo->data))
255	    overrun (finfo, _("named resource"));
256	  re->subdir = 0;
257	  re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
258	}
259
260      *pp = re;
261      pp = &re->next;
262    }
263
264  for (i = 0; i < id_count; i++, ere++)
265    {
266      unsigned long name, rva;
267      struct res_entry *re;
268
269      if ((const bfd_byte *) ere >= finfo->data_end)
270	overrun (finfo, _("ID directory entry"));
271
272      name = getfi_32 (finfo, ere->name);
273      rva = getfi_32 (finfo, ere->rva);
274
275      re = (struct res_entry *) res_alloc (sizeof *re);
276      re->next = NULL;
277      re->id.named = 0;
278      re->id.u.id = name;
279
280      if (level == 0)
281	type = &re->id;
282
283      if ((rva & 0x80000000) != 0)
284	{
285	  rva &=~ 0x80000000;
286	  if (rva >= (size_t) (finfo->data_end - finfo->data))
287	    overrun (finfo, _("ID subdirectory"));
288	  re->subdir = 1;
289	  re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
290					 level + 1);
291	}
292      else
293	{
294	  if (rva >= (size_t) (finfo->data_end - finfo->data))
295	    overrun (finfo, _("ID resource"));
296	  re->subdir = 0;
297	  re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
298	}
299
300      *pp = re;
301      pp = &re->next;
302    }
303
304  return rd;
305}
306
307/* Read a resource data entry.  */
308
309static struct res_resource *
310read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo, const struct res_id *type)
311{
312  const struct extern_res_data *erd;
313  struct res_resource *r;
314  unsigned long size, rva;
315  const bfd_byte *resdata;
316
317  if (type == NULL)
318    fatal (_("resource type unknown"));
319
320  if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_data))
321    overrun (finfo, _("data entry"));
322
323  erd = (const struct extern_res_data *) data;
324
325  size = getfi_32 (finfo, erd->size);
326  rva = getfi_32 (finfo, erd->rva);
327  if (rva < finfo->secaddr
328      || rva - finfo->secaddr >= (size_t) (finfo->data_end - finfo->data))
329    overrun (finfo, _("resource data"));
330
331  resdata = finfo->data + (rva - finfo->secaddr);
332
333  if (size > (size_t) (finfo->data_end - resdata))
334    overrun (finfo, _("resource data size"));
335
336  r = bin_to_res (*type, resdata, size, finfo->big_endian);
337
338  memset (&r->res_info, 0, sizeof (struct res_res_info));
339  r->coff_info.codepage = getfi_32 (finfo, erd->codepage);
340  r->coff_info.reserved = getfi_32 (finfo, erd->reserved);
341
342  return r;
343}
344
345/* This structure is used to build a list of bindata structures.  */
346
347struct bindata_build
348{
349  /* The data.  */
350  struct bindata *d;
351  /* The last structure we have added to the list.  */
352  struct bindata *last;
353  /* The size of the list as a whole.  */
354  unsigned long length;
355};
356
357/* This structure keeps track of information as we build the directory
358   tree.  */
359
360struct coff_write_info
361{
362  /* These fields are based on the BFD.  */
363  /* The BFD itself.  */
364  bfd *abfd;
365  /* Non-zero if the file is big endian.  */
366  int big_endian;
367  /* Pointer to section symbol used to build RVA relocs.  */
368  asymbol **sympp;
369
370  /* These fields are computed initially, and then not changed.  */
371  /* Length of directory tables and entries.  */
372  unsigned long dirsize;
373  /* Length of directory entry strings.  */
374  unsigned long dirstrsize;
375  /* Length of resource data entries.  */
376  unsigned long dataentsize;
377
378  /* These fields are updated as we add data.  */
379  /* Directory tables and entries.  */
380  struct bindata_build dirs;
381  /* Directory entry strings.  */
382  struct bindata_build dirstrs;
383  /* Resource data entries.  */
384  struct bindata_build dataents;
385  /* Actual resource data.  */
386  struct bindata_build resources;
387  /* Relocations.  */
388  arelent **relocs;
389  /* Number of relocations.  */
390  unsigned int reloc_count;
391};
392
393/* Macros to swap out values.  */
394
395#define putcwi_16(cwi, v, s) \
396  ((cwi->big_endian) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
397#define putcwi_32(cwi, v, s) \
398  ((cwi->big_endian) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
399
400static void coff_bin_sizes
401  (const struct res_directory *, struct coff_write_info *);
402static unsigned char *coff_alloc (struct bindata_build *, size_t);
403static void coff_to_bin
404  (const struct res_directory *, struct coff_write_info *);
405static void coff_res_to_bin
406  (const struct res_resource *, struct coff_write_info *);
407
408/* Write resources to a COFF file.  RESOURCES should already be
409   sorted.
410
411   Right now we always create a new file.  Someday we should also
412   offer the ability to merge resources into an existing file.  This
413   would require doing the basic work of objcopy, just modifying or
414   adding the .rsrc section.  */
415
416void
417write_coff_file (const char *filename, const char *target,
418		 const struct res_directory *resources)
419{
420  bfd *abfd;
421  asection *sec;
422  struct coff_write_info cwi;
423  struct bindata *d;
424  unsigned long length, offset;
425
426  if (filename == NULL)
427    fatal (_("filename required for COFF output"));
428
429  abfd = bfd_openw (filename, target);
430  if (abfd == NULL)
431    bfd_fatal (filename);
432
433  if (! bfd_set_format (abfd, bfd_object))
434    bfd_fatal ("bfd_set_format");
435
436#if defined DLLTOOL_SH
437  if (! bfd_set_arch_mach (abfd, bfd_arch_sh, 0))
438    bfd_fatal ("bfd_set_arch_mach(sh)");
439#elif defined DLLTOOL_MIPS
440  if (! bfd_set_arch_mach (abfd, bfd_arch_mips, 0))
441    bfd_fatal ("bfd_set_arch_mach(mips)");
442#elif defined DLLTOOL_ARM
443  if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0))
444    bfd_fatal ("bfd_set_arch_mach(arm)");
445#else
446  /* FIXME: This is obviously i386 specific.  */
447  if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0))
448    bfd_fatal ("bfd_set_arch_mach(i386)");
449#endif
450
451  if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC))
452    bfd_fatal ("bfd_set_file_flags");
453
454  sec = bfd_make_section (abfd, ".rsrc");
455  if (sec == NULL)
456    bfd_fatal ("bfd_make_section");
457
458  if (! bfd_set_section_flags (abfd, sec,
459			       (SEC_HAS_CONTENTS | SEC_ALLOC
460				| SEC_LOAD | SEC_DATA)))
461    bfd_fatal ("bfd_set_section_flags");
462
463  if (! bfd_set_symtab (abfd, sec->symbol_ptr_ptr, 1))
464    bfd_fatal ("bfd_set_symtab");
465
466  /* Requiring this is probably a bug in BFD.  */
467  sec->output_section = sec;
468
469  /* The order of data in the .rsrc section is
470       resource directory tables and entries
471       resource directory strings
472       resource data entries
473       actual resource data
474
475     We build these different types of data in different lists.  */
476
477  cwi.abfd = abfd;
478  cwi.big_endian = bfd_big_endian (abfd);
479  cwi.sympp = sec->symbol_ptr_ptr;
480  cwi.dirsize = 0;
481  cwi.dirstrsize = 0;
482  cwi.dataentsize = 0;
483  cwi.dirs.d = NULL;
484  cwi.dirs.last = NULL;
485  cwi.dirs.length = 0;
486  cwi.dirstrs.d = NULL;
487  cwi.dirstrs.last = NULL;
488  cwi.dirstrs.length = 0;
489  cwi.dataents.d = NULL;
490  cwi.dataents.last = NULL;
491  cwi.dataents.length = 0;
492  cwi.resources.d = NULL;
493  cwi.resources.last = NULL;
494  cwi.resources.length = 0;
495  cwi.relocs = NULL;
496  cwi.reloc_count = 0;
497
498  /* Work out the sizes of the resource directory entries, so that we
499     know the various offsets we will need.  */
500  coff_bin_sizes (resources, &cwi);
501
502  /* Force the directory strings to be 32 bit aligned.  Every other
503     structure is 32 bit aligned anyhow.  */
504  cwi.dirstrsize = (cwi.dirstrsize + 3) &~ 3;
505
506  /* Actually convert the resources to binary.  */
507  coff_to_bin (resources, &cwi);
508
509  /* Add another 2 bytes to the directory strings if needed for
510     alignment.  */
511  if ((cwi.dirstrs.length & 3) != 0)
512    {
513      unsigned char *ex;
514
515      ex = coff_alloc (&cwi.dirstrs, 2);
516      ex[0] = 0;
517      ex[1] = 0;
518    }
519
520  /* Make sure that the data we built came out to the same size as we
521     calculated initially.  */
522  assert (cwi.dirs.length == cwi.dirsize);
523  assert (cwi.dirstrs.length == cwi.dirstrsize);
524  assert (cwi.dataents.length == cwi.dataentsize);
525
526  length = (cwi.dirsize
527	    + cwi.dirstrsize
528	    + cwi.dataentsize
529	    + cwi.resources.length);
530
531  if (! bfd_set_section_size (abfd, sec, length))
532    bfd_fatal ("bfd_set_section_size");
533
534  bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count);
535
536  offset = 0;
537  for (d = cwi.dirs.d; d != NULL; d = d->next)
538    {
539      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
540	bfd_fatal ("bfd_set_section_contents");
541      offset += d->length;
542    }
543  for (d = cwi.dirstrs.d; d != NULL; d = d->next)
544    {
545      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
546	bfd_fatal ("bfd_set_section_contents");
547      offset += d->length;
548    }
549  for (d = cwi.dataents.d; d != NULL; d = d->next)
550    {
551      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
552	bfd_fatal ("bfd_set_section_contents");
553      offset += d->length;
554    }
555  for (d = cwi.resources.d; d != NULL; d = d->next)
556    {
557      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
558	bfd_fatal ("bfd_set_section_contents");
559      offset += d->length;
560    }
561
562  assert (offset == length);
563
564  if (! bfd_close (abfd))
565    bfd_fatal ("bfd_close");
566
567  /* We allocated the relocs array using malloc.  */
568  free (cwi.relocs);
569}
570
571/* Work out the sizes of the various fixed size resource directory
572   entries.  This updates fields in CWI.  */
573
574static void
575coff_bin_sizes (const struct res_directory *resdir,
576		struct coff_write_info *cwi)
577{
578  const struct res_entry *re;
579
580  cwi->dirsize += sizeof (struct extern_res_directory);
581
582  for (re = resdir->entries; re != NULL; re = re->next)
583    {
584      cwi->dirsize += sizeof (struct extern_res_entry);
585
586      if (re->id.named)
587	cwi->dirstrsize += re->id.u.n.length * 2 + 2;
588
589      if (re->subdir)
590	coff_bin_sizes (re->u.dir, cwi);
591      else
592	cwi->dataentsize += sizeof (struct extern_res_data);
593    }
594}
595
596/* Allocate data for a particular list.  */
597
598static unsigned char *
599coff_alloc (struct bindata_build *bb, size_t size)
600{
601  struct bindata *d;
602
603  d = (struct bindata *) reswr_alloc (sizeof *d);
604
605  d->next = NULL;
606  d->data = (unsigned char *) reswr_alloc (size);
607  d->length = size;
608
609  if (bb->d == NULL)
610    bb->d = d;
611  else
612    bb->last->next = d;
613  bb->last = d;
614  bb->length += size;
615
616  return d->data;
617}
618
619/* Convert the resource directory RESDIR to binary.  */
620
621static void
622coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
623{
624  struct extern_res_directory *erd;
625  int ci, cn;
626  const struct res_entry *e;
627  struct extern_res_entry *ere;
628
629  /* Write out the directory table.  */
630
631  erd = ((struct extern_res_directory *)
632	 coff_alloc (&cwi->dirs, sizeof (*erd)));
633
634  putcwi_32 (cwi, resdir->characteristics, erd->characteristics);
635  putcwi_32 (cwi, resdir->time, erd->time);
636  putcwi_16 (cwi, resdir->major, erd->major);
637  putcwi_16 (cwi, resdir->minor, erd->minor);
638
639  ci = 0;
640  cn = 0;
641  for (e = resdir->entries; e != NULL; e = e->next)
642    {
643      if (e->id.named)
644	++cn;
645      else
646	++ci;
647    }
648
649  putcwi_16 (cwi, cn, erd->name_count);
650  putcwi_16 (cwi, ci, erd->id_count);
651
652  /* Write out the data entries.  Note that we allocate space for all
653     the entries before writing them out.  That permits a recursive
654     call to work correctly when writing out subdirectories.  */
655
656  ere = ((struct extern_res_entry *)
657	 coff_alloc (&cwi->dirs, (ci + cn) * sizeof (*ere)));
658  for (e = resdir->entries; e != NULL; e = e->next, ere++)
659    {
660      if (! e->id.named)
661	putcwi_32 (cwi, e->id.u.id, ere->name);
662      else
663	{
664	  unsigned char *str;
665	  int i;
666
667	  /* For some reason existing files seem to have the high bit
668             set on the address of the name, although that is not
669             documented.  */
670	  putcwi_32 (cwi,
671		     0x80000000 | (cwi->dirsize + cwi->dirstrs.length),
672		     ere->name);
673
674	  str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2);
675	  putcwi_16 (cwi, e->id.u.n.length, str);
676	  for (i = 0; i < e->id.u.n.length; i++)
677	    putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2);
678	}
679
680      if (e->subdir)
681	{
682	  putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva);
683	  coff_to_bin (e->u.dir, cwi);
684	}
685      else
686	{
687	  putcwi_32 (cwi,
688		     cwi->dirsize + cwi->dirstrsize + cwi->dataents.length,
689		     ere->rva);
690
691	  coff_res_to_bin (e->u.res, cwi);
692	}
693    }
694}
695
696/* Convert the resource RES to binary.  */
697
698static void
699coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
700{
701  arelent *r;
702  struct extern_res_data *erd;
703  struct bindata *d;
704  unsigned long length;
705
706  /* For some reason, although every other address is a section
707     offset, the address of the resource data itself is an RVA.  That
708     means that we need to generate a relocation for it.  We allocate
709     the relocs array using malloc so that we can use realloc.  FIXME:
710     This relocation handling is correct for the i386, but probably
711     not for any other target.  */
712
713  r = (arelent *) reswr_alloc (sizeof (arelent));
714  r->sym_ptr_ptr = cwi->sympp;
715  r->address = cwi->dirsize + cwi->dirstrsize + cwi->dataents.length;
716  r->addend = 0;
717  r->howto = bfd_reloc_type_lookup (cwi->abfd, BFD_RELOC_RVA);
718  if (r->howto == NULL)
719    bfd_fatal (_("can't get BFD_RELOC_RVA relocation type"));
720
721  cwi->relocs = xrealloc (cwi->relocs,
722			  (cwi->reloc_count + 2) * sizeof (arelent *));
723  cwi->relocs[cwi->reloc_count] = r;
724  cwi->relocs[cwi->reloc_count + 1] = NULL;
725  ++cwi->reloc_count;
726
727  erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd));
728
729  putcwi_32 (cwi,
730	     (cwi->dirsize
731	      + cwi->dirstrsize
732	      + cwi->dataentsize
733	      + cwi->resources.length),
734	     erd->rva);
735  putcwi_32 (cwi, res->coff_info.codepage, erd->codepage);
736  putcwi_32 (cwi, res->coff_info.reserved, erd->reserved);
737
738  d = res_to_bin (res, cwi->big_endian);
739
740  if (cwi->resources.d == NULL)
741    cwi->resources.d = d;
742  else
743    cwi->resources.last->next = d;
744
745  length = 0;
746  for (; d->next != NULL; d = d->next)
747    length += d->length;
748  length += d->length;
749  cwi->resources.last = d;
750  cwi->resources.length += length;
751
752  putcwi_32 (cwi, length, erd->size);
753
754  /* Force the next resource to have 32 bit alignment.  */
755
756  if ((length & 3) != 0)
757    {
758      int add;
759      unsigned char *ex;
760
761      add = 4 - (length & 3);
762
763      ex = coff_alloc (&cwi->resources, add);
764      memset (ex, 0, add);
765    }
766}
767