Updated windres tool
This commit is contained in:
parent
950c3b7d2c
commit
4a594fce16
28 changed files with 5799 additions and 3573 deletions
|
@ -2,6 +2,7 @@
|
|||
Copyright 1997, 1998, 1999, 2000, 2003, 2007
|
||||
Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Cygnus Support.
|
||||
Rewritten by Kai Tietz, Onevision.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
|
||||
|
@ -25,8 +26,8 @@
|
|||
|
||||
#include "sysdep.h"
|
||||
#include "bfd.h"
|
||||
#include "libiberty.h"
|
||||
#include "bucomm.h"
|
||||
#include "libiberty.h"
|
||||
#include "windres.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -49,14 +50,12 @@ struct coff_file_info
|
|||
/* End of data read from file. */
|
||||
const bfd_byte *data_end;
|
||||
/* Address of the resource section minus the image base of the file. */
|
||||
bfd_vma secaddr;
|
||||
/* Non-zero if the file is big endian. */
|
||||
int big_endian;
|
||||
rc_uint_type secaddr;
|
||||
};
|
||||
|
||||
/* A resource directory table in a COFF file. */
|
||||
|
||||
struct extern_res_directory
|
||||
struct __attribute__ ((__packed__)) extern_res_directory
|
||||
{
|
||||
/* Characteristics. */
|
||||
bfd_byte characteristics[4];
|
||||
|
@ -97,26 +96,24 @@ struct extern_res_data
|
|||
bfd_byte reserved[4];
|
||||
};
|
||||
|
||||
/* Macros to swap in values. */
|
||||
|
||||
#define getfi_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s))
|
||||
#define getfi_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s))
|
||||
|
||||
/* Local functions. */
|
||||
|
||||
static void overrun (const struct coff_file_info *, const char *);
|
||||
static struct res_directory *read_coff_res_dir
|
||||
(const bfd_byte *, const struct coff_file_info *,
|
||||
const struct res_id *, int);
|
||||
static struct res_resource *read_coff_data_entry
|
||||
(const bfd_byte *, const struct coff_file_info *, const struct res_id *);
|
||||
static rc_res_directory *read_coff_res_dir (windres_bfd *, const bfd_byte *,
|
||||
const struct coff_file_info *,
|
||||
const rc_res_id *, int);
|
||||
static rc_res_resource *read_coff_data_entry (windres_bfd *, const bfd_byte *,
|
||||
const struct coff_file_info *,
|
||||
const rc_res_id *);
|
||||
|
||||
/* Read the resources in a COFF file. */
|
||||
|
||||
struct res_directory *
|
||||
rc_res_directory *
|
||||
read_coff_rsrc (const char *filename, const char *target)
|
||||
{
|
||||
rc_res_directory *ret;
|
||||
bfd *abfd;
|
||||
windres_bfd wrbfd;
|
||||
char **matching;
|
||||
asection *sec;
|
||||
bfd_size_type size;
|
||||
|
@ -144,27 +141,28 @@ read_coff_rsrc (const char *filename, const char *target)
|
|||
fatal (_("%s: no resource section"), filename);
|
||||
}
|
||||
|
||||
set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
|
||||
size = bfd_section_size (abfd, sec);
|
||||
data = (bfd_byte *) res_alloc (size);
|
||||
|
||||
if (! bfd_get_section_contents (abfd, sec, data, 0, size))
|
||||
bfd_fatal (_("can't read resource section"));
|
||||
get_windres_bfd_content (&wrbfd, data, 0, size);
|
||||
|
||||
finfo.filename = filename;
|
||||
finfo.data = data;
|
||||
finfo.data_end = data + size;
|
||||
finfo.secaddr = (bfd_get_section_vma (abfd, sec)
|
||||
- pe_data (abfd)->pe_opthdr.ImageBase);
|
||||
finfo.big_endian = bfd_big_endian (abfd);
|
||||
|
||||
bfd_close (abfd);
|
||||
|
||||
/* Now just read in the top level resource directory. Note that we
|
||||
don't free data, since we create resource entries that point into
|
||||
it. If we ever want to free up the resource information we read,
|
||||
this will have to be cleaned up. */
|
||||
|
||||
return read_coff_res_dir (data, &finfo, (const struct res_id *) NULL, 0);
|
||||
ret = read_coff_res_dir (&wrbfd, data, &finfo, (const rc_res_id *) NULL, 0);
|
||||
|
||||
bfd_close (abfd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Give an error if we are out of bounds. */
|
||||
|
@ -177,14 +175,15 @@ overrun (const struct coff_file_info *finfo, const char *msg)
|
|||
|
||||
/* Read a resource directory. */
|
||||
|
||||
static struct res_directory *
|
||||
read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
||||
const struct res_id *type, int level)
|
||||
static rc_res_directory *
|
||||
read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
|
||||
const struct coff_file_info *finfo,
|
||||
const rc_res_id *type, int level)
|
||||
{
|
||||
const struct extern_res_directory *erd;
|
||||
struct res_directory *rd;
|
||||
rc_res_directory *rd;
|
||||
int name_count, id_count, i;
|
||||
struct res_entry **pp;
|
||||
rc_res_entry **pp;
|
||||
const struct extern_res_entry *ere;
|
||||
|
||||
if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_directory))
|
||||
|
@ -192,15 +191,15 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
|
||||
erd = (const struct extern_res_directory *) data;
|
||||
|
||||
rd = (struct res_directory *) res_alloc (sizeof *rd);
|
||||
rd->characteristics = getfi_32 (finfo, erd->characteristics);
|
||||
rd->time = getfi_32 (finfo, erd->time);
|
||||
rd->major = getfi_16 (finfo, erd->major);
|
||||
rd->minor = getfi_16 (finfo, erd->minor);
|
||||
rd = (rc_res_directory *) res_alloc (sizeof (rc_res_directory));
|
||||
rd->characteristics = windres_get_32 (wrbfd, erd->characteristics, 4);
|
||||
rd->time = windres_get_32 (wrbfd, erd->time, 4);
|
||||
rd->major = windres_get_16 (wrbfd, erd->major, 2);
|
||||
rd->minor = windres_get_16 (wrbfd, erd->minor, 2);
|
||||
rd->entries = NULL;
|
||||
|
||||
name_count = getfi_16 (finfo, erd->name_count);
|
||||
id_count = getfi_16 (finfo, erd->id_count);
|
||||
name_count = windres_get_16 (wrbfd, erd->name_count, 2);
|
||||
id_count = windres_get_16 (wrbfd, erd->id_count, 2);
|
||||
|
||||
pp = &rd->entries;
|
||||
|
||||
|
@ -210,33 +209,33 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
|
||||
for (i = 0; i < name_count; i++, ere++)
|
||||
{
|
||||
unsigned long name, rva;
|
||||
struct res_entry *re;
|
||||
rc_uint_type name, rva;
|
||||
rc_res_entry *re;
|
||||
const bfd_byte *ers;
|
||||
int length, j;
|
||||
|
||||
if ((const bfd_byte *) ere >= finfo->data_end)
|
||||
overrun (finfo, _("named directory entry"));
|
||||
|
||||
name = getfi_32 (finfo, ere->name);
|
||||
rva = getfi_32 (finfo, ere->rva);
|
||||
name = windres_get_32 (wrbfd, ere->name, 4);
|
||||
rva = windres_get_32 (wrbfd, ere->rva, 4);
|
||||
|
||||
/* For some reason the high bit in NAME is set. */
|
||||
name &=~ 0x80000000;
|
||||
|
||||
if (name > (size_t) (finfo->data_end - finfo->data))
|
||||
if (name > (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("directory entry name"));
|
||||
|
||||
ers = finfo->data + name;
|
||||
|
||||
re = (struct res_entry *) res_alloc (sizeof *re);
|
||||
re = (rc_res_entry *) res_alloc (sizeof *re);
|
||||
re->next = NULL;
|
||||
re->id.named = 1;
|
||||
length = getfi_16 (finfo, ers);
|
||||
length = windres_get_16 (wrbfd, ers, 2);
|
||||
re->id.u.n.length = length;
|
||||
re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar));
|
||||
for (j = 0; j < length; j++)
|
||||
re->id.u.n.name[j] = getfi_16 (finfo, ers + j * 2 + 2);
|
||||
re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2);
|
||||
|
||||
if (level == 0)
|
||||
type = &re->id;
|
||||
|
@ -244,18 +243,18 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
if ((rva & 0x80000000) != 0)
|
||||
{
|
||||
rva &=~ 0x80000000;
|
||||
if (rva >= (size_t) (finfo->data_end - finfo->data))
|
||||
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("named subdirectory"));
|
||||
re->subdir = 1;
|
||||
re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
|
||||
re->u.dir = read_coff_res_dir (wrbfd, finfo->data + rva, finfo, type,
|
||||
level + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rva >= (size_t) (finfo->data_end - finfo->data))
|
||||
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("named resource"));
|
||||
re->subdir = 0;
|
||||
re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
|
||||
re->u.res = read_coff_data_entry (wrbfd, finfo->data + rva, finfo, type);
|
||||
}
|
||||
|
||||
*pp = re;
|
||||
|
@ -265,15 +264,15 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
for (i = 0; i < id_count; i++, ere++)
|
||||
{
|
||||
unsigned long name, rva;
|
||||
struct res_entry *re;
|
||||
rc_res_entry *re;
|
||||
|
||||
if ((const bfd_byte *) ere >= finfo->data_end)
|
||||
overrun (finfo, _("ID directory entry"));
|
||||
|
||||
name = getfi_32 (finfo, ere->name);
|
||||
rva = getfi_32 (finfo, ere->rva);
|
||||
name = windres_get_32 (wrbfd, ere->name, 4);
|
||||
rva = windres_get_32 (wrbfd, ere->rva, 4);
|
||||
|
||||
re = (struct res_entry *) res_alloc (sizeof *re);
|
||||
re = (rc_res_entry *) res_alloc (sizeof *re);
|
||||
re->next = NULL;
|
||||
re->id.named = 0;
|
||||
re->id.u.id = name;
|
||||
|
@ -284,18 +283,18 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
if ((rva & 0x80000000) != 0)
|
||||
{
|
||||
rva &=~ 0x80000000;
|
||||
if (rva >= (size_t) (finfo->data_end - finfo->data))
|
||||
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("ID subdirectory"));
|
||||
re->subdir = 1;
|
||||
re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
|
||||
re->u.dir = read_coff_res_dir (wrbfd, finfo->data + rva, finfo, type,
|
||||
level + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rva >= (size_t) (finfo->data_end - finfo->data))
|
||||
if (rva >= (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("ID resource"));
|
||||
re->subdir = 0;
|
||||
re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
|
||||
re->u.res = read_coff_data_entry (wrbfd, finfo->data + rva, finfo, type);
|
||||
}
|
||||
|
||||
*pp = re;
|
||||
|
@ -307,12 +306,14 @@ read_coff_res_dir (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
|
||||
/* Read a resource data entry. */
|
||||
|
||||
static struct res_resource *
|
||||
read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo, const struct res_id *type)
|
||||
static rc_res_resource *
|
||||
read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data,
|
||||
const struct coff_file_info *finfo,
|
||||
const rc_res_id *type)
|
||||
{
|
||||
const struct extern_res_data *erd;
|
||||
struct res_resource *r;
|
||||
unsigned long size, rva;
|
||||
rc_res_resource *r;
|
||||
rc_uint_type size, rva;
|
||||
const bfd_byte *resdata;
|
||||
|
||||
if (type == NULL)
|
||||
|
@ -323,22 +324,22 @@ read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
|
||||
erd = (const struct extern_res_data *) data;
|
||||
|
||||
size = getfi_32 (finfo, erd->size);
|
||||
rva = getfi_32 (finfo, erd->rva);
|
||||
size = windres_get_32 (wrbfd, erd->size, 4);
|
||||
rva = windres_get_32 (wrbfd, erd->rva, 4);
|
||||
if (rva < finfo->secaddr
|
||||
|| rva - finfo->secaddr >= (size_t) (finfo->data_end - finfo->data))
|
||||
|| rva - finfo->secaddr >= (rc_uint_type) (finfo->data_end - finfo->data))
|
||||
overrun (finfo, _("resource data"));
|
||||
|
||||
resdata = finfo->data + (rva - finfo->secaddr);
|
||||
|
||||
if (size > (size_t) (finfo->data_end - resdata))
|
||||
if (size > (rc_uint_type) (finfo->data_end - resdata))
|
||||
overrun (finfo, _("resource data size"));
|
||||
|
||||
r = bin_to_res (*type, resdata, size, finfo->big_endian);
|
||||
r = bin_to_res (wrbfd, *type, resdata, size);
|
||||
|
||||
memset (&r->res_info, 0, sizeof (struct res_res_info));
|
||||
r->coff_info.codepage = getfi_32 (finfo, erd->codepage);
|
||||
r->coff_info.reserved = getfi_32 (finfo, erd->reserved);
|
||||
memset (&r->res_info, 0, sizeof (rc_res_res_info));
|
||||
r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4);
|
||||
r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -348,9 +349,19 @@ read_coff_data_entry (const bfd_byte *data, const struct coff_file_info *finfo,
|
|||
struct bindata_build
|
||||
{
|
||||
/* The data. */
|
||||
struct bindata *d;
|
||||
bindata *d;
|
||||
/* The last structure we have added to the list. */
|
||||
struct bindata *last;
|
||||
bindata *last;
|
||||
/* The size of the list as a whole. */
|
||||
unsigned long length;
|
||||
};
|
||||
|
||||
struct coff_res_data_build
|
||||
{
|
||||
/* The data. */
|
||||
coff_res_data *d;
|
||||
/* The last structure we have added to the list. */
|
||||
coff_res_data *last;
|
||||
/* The size of the list as a whole. */
|
||||
unsigned long length;
|
||||
};
|
||||
|
@ -362,9 +373,7 @@ struct coff_write_info
|
|||
{
|
||||
/* These fields are based on the BFD. */
|
||||
/* The BFD itself. */
|
||||
bfd *abfd;
|
||||
/* Non-zero if the file is big endian. */
|
||||
int big_endian;
|
||||
windres_bfd *wrbfd;
|
||||
/* Pointer to section symbol used to build RVA relocs. */
|
||||
asymbol **sympp;
|
||||
|
||||
|
@ -384,27 +393,19 @@ struct coff_write_info
|
|||
/* Resource data entries. */
|
||||
struct bindata_build dataents;
|
||||
/* Actual resource data. */
|
||||
struct bindata_build resources;
|
||||
struct coff_res_data_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
|
||||
(const struct res_directory *, struct coff_write_info *);
|
||||
static unsigned char *coff_alloc (struct bindata_build *, size_t);
|
||||
static void coff_bin_sizes (const rc_res_directory *, struct coff_write_info *);
|
||||
static bfd_byte *coff_alloc (struct bindata_build *, rc_uint_type);
|
||||
static void coff_to_bin
|
||||
(const struct res_directory *, struct coff_write_info *);
|
||||
(const rc_res_directory *, struct coff_write_info *);
|
||||
static void coff_res_to_bin
|
||||
(const struct res_resource *, struct coff_write_info *);
|
||||
(const rc_res_resource *, struct coff_write_info *);
|
||||
|
||||
/* Write resources to a COFF file. RESOURCES should already be
|
||||
sorted.
|
||||
|
@ -416,12 +417,14 @@ static void coff_res_to_bin
|
|||
|
||||
void
|
||||
write_coff_file (const char *filename, const char *target,
|
||||
const struct res_directory *resources)
|
||||
const rc_res_directory *resources)
|
||||
{
|
||||
bfd *abfd;
|
||||
asection *sec;
|
||||
struct coff_write_info cwi;
|
||||
struct bindata *d;
|
||||
windres_bfd wrbfd;
|
||||
bindata *d;
|
||||
coff_res_data *rd;
|
||||
unsigned long length, offset;
|
||||
|
||||
if (filename == NULL)
|
||||
|
@ -475,8 +478,9 @@ write_coff_file (const char *filename, const char *target,
|
|||
|
||||
We build these different types of data in different lists. */
|
||||
|
||||
cwi.abfd = abfd;
|
||||
cwi.big_endian = bfd_big_endian (abfd);
|
||||
set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
|
||||
|
||||
cwi.wrbfd = &wrbfd;
|
||||
cwi.sympp = sec->symbol_ptr_ptr;
|
||||
cwi.dirsize = 0;
|
||||
cwi.dirstrsize = 0;
|
||||
|
@ -511,7 +515,7 @@ write_coff_file (const char *filename, const char *target,
|
|||
alignment. */
|
||||
if ((cwi.dirstrs.length & 3) != 0)
|
||||
{
|
||||
unsigned char *ex;
|
||||
bfd_byte *ex;
|
||||
|
||||
ex = coff_alloc (&cwi.dirstrs, 2);
|
||||
ex[0] = 0;
|
||||
|
@ -543,21 +547,18 @@ write_coff_file (const char *filename, const char *target,
|
|||
}
|
||||
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");
|
||||
set_windres_bfd_content (&wrbfd, d->data, offset, d->length);
|
||||
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");
|
||||
set_windres_bfd_content (&wrbfd, d->data, offset, d->length);
|
||||
offset += d->length;
|
||||
}
|
||||
for (d = cwi.resources.d; d != NULL; d = d->next)
|
||||
for (rd = cwi.resources.d; rd != NULL; rd = rd->next)
|
||||
{
|
||||
if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
|
||||
bfd_fatal ("bfd_set_section_contents");
|
||||
offset += d->length;
|
||||
res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res);
|
||||
offset += rd->length;
|
||||
}
|
||||
|
||||
assert (offset == length);
|
||||
|
@ -573,10 +574,10 @@ write_coff_file (const char *filename, const char *target,
|
|||
entries. This updates fields in CWI. */
|
||||
|
||||
static void
|
||||
coff_bin_sizes (const struct res_directory *resdir,
|
||||
coff_bin_sizes (const rc_res_directory *resdir,
|
||||
struct coff_write_info *cwi)
|
||||
{
|
||||
const struct res_entry *re;
|
||||
const rc_res_entry *re;
|
||||
|
||||
cwi->dirsize += sizeof (struct extern_res_directory);
|
||||
|
||||
|
@ -596,15 +597,15 @@ coff_bin_sizes (const struct res_directory *resdir,
|
|||
|
||||
/* Allocate data for a particular list. */
|
||||
|
||||
static unsigned char *
|
||||
coff_alloc (struct bindata_build *bb, size_t size)
|
||||
static bfd_byte *
|
||||
coff_alloc (struct bindata_build *bb, rc_uint_type size)
|
||||
{
|
||||
struct bindata *d;
|
||||
bindata *d;
|
||||
|
||||
d = (struct bindata *) reswr_alloc (sizeof *d);
|
||||
d = (bindata *) reswr_alloc (sizeof (bindata));
|
||||
|
||||
d->next = NULL;
|
||||
d->data = (unsigned char *) reswr_alloc (size);
|
||||
d->data = (bfd_byte *) reswr_alloc (size);
|
||||
d->length = size;
|
||||
|
||||
if (bb->d == NULL)
|
||||
|
@ -620,11 +621,11 @@ coff_alloc (struct bindata_build *bb, size_t size)
|
|||
/* Convert the resource directory RESDIR to binary. */
|
||||
|
||||
static void
|
||||
coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
|
||||
coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi)
|
||||
{
|
||||
struct extern_res_directory *erd;
|
||||
int ci, cn;
|
||||
const struct res_entry *e;
|
||||
const rc_res_entry *e;
|
||||
struct extern_res_entry *ere;
|
||||
|
||||
/* Write out the directory table. */
|
||||
|
@ -632,10 +633,10 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
|
|||
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);
|
||||
windres_put_32 (cwi->wrbfd, erd->characteristics, resdir->characteristics);
|
||||
windres_put_32 (cwi->wrbfd, erd->time, resdir->time);
|
||||
windres_put_16 (cwi->wrbfd, erd->major, resdir->major);
|
||||
windres_put_16 (cwi->wrbfd, erd->minor, resdir->minor);
|
||||
|
||||
ci = 0;
|
||||
cn = 0;
|
||||
|
@ -647,8 +648,8 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
|
|||
++ci;
|
||||
}
|
||||
|
||||
putcwi_16 (cwi, cn, erd->name_count);
|
||||
putcwi_16 (cwi, ci, erd->id_count);
|
||||
windres_put_16 (cwi->wrbfd, erd->name_count, cn);
|
||||
windres_put_16 (cwi->wrbfd, erd->id_count, ci);
|
||||
|
||||
/* Write out the data entries. Note that we allocate space for all
|
||||
the entries before writing them out. That permits a recursive
|
||||
|
@ -659,35 +660,33 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
|
|||
for (e = resdir->entries; e != NULL; e = e->next, ere++)
|
||||
{
|
||||
if (! e->id.named)
|
||||
putcwi_32 (cwi, e->id.u.id, ere->name);
|
||||
windres_put_32 (cwi->wrbfd, ere->name, e->id.u.id);
|
||||
else
|
||||
{
|
||||
unsigned char *str;
|
||||
int i;
|
||||
bfd_byte *str;
|
||||
rc_uint_type 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);
|
||||
windres_put_32 (cwi->wrbfd, ere->name,
|
||||
0x80000000 | (cwi->dirsize + cwi->dirstrs.length));
|
||||
|
||||
str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2);
|
||||
putcwi_16 (cwi, e->id.u.n.length, str);
|
||||
windres_put_16 (cwi->wrbfd, str, e->id.u.n.length);
|
||||
for (i = 0; i < e->id.u.n.length; i++)
|
||||
putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2);
|
||||
windres_put_16 (cwi->wrbfd, str + (i + 1) * sizeof (unichar), e->id.u.n.name[i]);
|
||||
}
|
||||
|
||||
if (e->subdir)
|
||||
{
|
||||
putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva);
|
||||
windres_put_32 (cwi->wrbfd, ere->rva, 0x80000000 | cwi->dirs.length);
|
||||
coff_to_bin (e->u.dir, cwi);
|
||||
}
|
||||
else
|
||||
{
|
||||
putcwi_32 (cwi,
|
||||
cwi->dirsize + cwi->dirstrsize + cwi->dataents.length,
|
||||
ere->rva);
|
||||
windres_put_32 (cwi->wrbfd, ere->rva,
|
||||
cwi->dirsize + cwi->dirstrsize + cwi->dataents.length);
|
||||
|
||||
coff_res_to_bin (e->u.res, cwi);
|
||||
}
|
||||
|
@ -697,12 +696,11 @@ coff_to_bin (const struct res_directory *resdir, struct coff_write_info *cwi)
|
|||
/* Convert the resource RES to binary. */
|
||||
|
||||
static void
|
||||
coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
|
||||
coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi)
|
||||
{
|
||||
arelent *r;
|
||||
struct extern_res_data *erd;
|
||||
struct bindata *d;
|
||||
unsigned long length;
|
||||
coff_res_data *d;
|
||||
|
||||
/* For some reason, although every other address is a section
|
||||
offset, the address of the resource data itself is an RVA. That
|
||||
|
@ -715,7 +713,7 @@ coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
|
|||
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);
|
||||
r->howto = bfd_reloc_type_lookup (WR_BFD (cwi->wrbfd), BFD_RELOC_RVA);
|
||||
if (r->howto == NULL)
|
||||
bfd_fatal (_("can't get BFD_RELOC_RVA relocation type"));
|
||||
|
||||
|
@ -727,41 +725,29 @@ coff_res_to_bin (const struct res_resource *res, struct coff_write_info *cwi)
|
|||
|
||||
erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd));
|
||||
|
||||
putcwi_32 (cwi,
|
||||
windres_put_32 (cwi->wrbfd, erd->rva,
|
||||
(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);
|
||||
+ cwi->resources.length));
|
||||
windres_put_32 (cwi->wrbfd, erd->codepage, res->coff_info.codepage);
|
||||
windres_put_32 (cwi->wrbfd, erd->reserved, res->coff_info.reserved);
|
||||
|
||||
d = res_to_bin (res, cwi->big_endian);
|
||||
d = (coff_res_data *) reswr_alloc (sizeof (coff_res_data));
|
||||
d->length = res_to_bin (NULL, (rc_uint_type) 0, res);
|
||||
d->res = res;
|
||||
d->next = NULL;
|
||||
|
||||
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;
|
||||
cwi->resources.length += (d->length + 3) & ~3;
|
||||
|
||||
putcwi_32 (cwi, length, erd->size);
|
||||
windres_put_32 (cwi->wrbfd, erd->size, d->length);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
d->length = (d->length + 3) & ~3;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue