aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1997-06-23 00:08:54 +0000
committerIan Lance Taylor <ian@airs.com>1997-06-23 00:08:54 +0000
commite4486bdf9ffd0c61863eee6ccb2e5ef5621d1417 (patch)
tree50f3865d0257543e4d87f4373208df253546efff /binutils
parent3ce6d9410caa23759ba24cd6735b7f5ed449d302 (diff)
downloadgdb-e4486bdf9ffd0c61863eee6ccb2e5ef5621d1417.zip
gdb-e4486bdf9ffd0c61863eee6ccb2e5ef5621d1417.tar.gz
gdb-e4486bdf9ffd0c61863eee6ccb2e5ef5621d1417.tar.bz2
Another windres snapshot. Can now read the COFF resources directory,
although it doesn't yet parse out the binary format.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/.Sanitize1
-rw-r--r--binutils/ChangeLog1
-rw-r--r--binutils/Makefile.in8
-rw-r--r--binutils/rescoff.c342
-rw-r--r--binutils/resrc.c6
-rw-r--r--binutils/windres.c28
6 files changed, 356 insertions, 30 deletions
diff --git a/binutils/.Sanitize b/binutils/.Sanitize
index 5bae795..e66607a 100644
--- a/binutils/.Sanitize
+++ b/binutils/.Sanitize
@@ -84,6 +84,7 @@ ranlib.1
ranlib.sh
rclex.l
rcparse.y
+rescoff.c
resrc.c
rdcoff.c
rddbg.c
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 2a685dc..3c8f28b 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -6,6 +6,7 @@ Sun Jun 22 17:29:41 1997 Ian Lance Taylor <ian@cygnus.com>
* resrc.c: New file.
* rcparse.y: New file.
* rclex.l: New file.
+ * rescoff.c: New file.
* configure.in: Define and substitute BUILD_WINDRES.
* configure: Rebuild.
* Makefile.in: Rebuild dependencies.
diff --git a/binutils/Makefile.in b/binutils/Makefile.in
index 65d25f7..3a0eb41 100644
--- a/binutils/Makefile.in
+++ b/binutils/Makefile.in
@@ -138,7 +138,7 @@ CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
stabs.c strings.c sysdump.c version.c wrstabs.c \
- windres.c resrc.c
+ windres.c resrc.c rescoff.c
GENERATED_CFILES = \
underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
@@ -409,7 +409,7 @@ nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
$(NLMCONV_PROG): nlmconv.o nlmheader.o $(ADDL_DEPS)
$(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ nlmconv.o nlmheader.o $(ADDL_LIBS) $(EXTRALIBS)
-WINDRES_OBJS = windres.o resrc.o rcparse.o rclex.o
+WINDRES_OBJS = windres.o resrc.o rescoff.o rcparse.o rclex.o
$(WINDRES_PROG): $(WINDRES_OBJS) $(ADDL_DEPS)
$(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(WINDRES_OBJS) $(ADDL_LIBS) $(EXTRALIBS)
@@ -766,6 +766,10 @@ windres.o: windres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
resrc.o: resrc.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
windres.h
+rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+ bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+ windres.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
underscore.o: underscore.c
arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
bucomm.h config.h $(INCDIR)/fopen-same.h arsup.h
diff --git a/binutils/rescoff.c b/binutils/rescoff.c
new file mode 100644
index 0000000..65df9bf
--- /dev/null
+++ b/binutils/rescoff.c
@@ -0,0 +1,342 @@
+/* resrc.c -- read and write Windows rc files.
+ Copyright 1997 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file contains function that read and write Windows resources
+ in COFF files. */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+/* In order to use the address of a resource data entry, we need to
+ get the image base of the file. Right now we extract it from
+ internal BFD information. FIXME. */
+
+#include "coff/internal.h"
+#include "libcoff.h"
+
+/* Information we extract from the file. */
+
+struct coff_file_info
+{
+ /* File name. */
+ const char *filename;
+ /* Data read from the file. */
+ const bfd_byte *data;
+ /* 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;
+};
+
+/* A resource directory table in a COFF file. */
+
+struct extern_res_directory
+{
+ /* Characteristics. */
+ bfd_byte characteristics[4];
+ /* Time stamp. */
+ bfd_byte time[4];
+ /* Major version number. */
+ bfd_byte major[2];
+ /* Minor version number. */
+ bfd_byte minor[2];
+ /* Number of named directory entries. */
+ bfd_byte name_count[2];
+ /* Number of directory entries with IDs. */
+ bfd_byte id_count[2];
+};
+
+/* A resource directory entry in a COFF file. */
+
+struct extern_res_entry
+{
+ /* Name or ID. */
+ bfd_byte name[4];
+ /* Address of resource entry or subdirectory. */
+ bfd_byte rva[4];
+};
+
+/* A resource data entry in a COFF file. */
+
+struct extern_res_data
+{
+ /* Address of resource data. This is apparently a file relative
+ address, rather than a section offset. */
+ bfd_byte rva[4];
+ /* Size of resource data. */
+ bfd_byte size[4];
+ /* Code page. */
+ bfd_byte codepage[4];
+ /* Reserved. */
+ bfd_byte reserved[4];
+};
+
+/* Macros to swap in values. */
+
+#define get_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s))
+#define get_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s))
+
+/* Local functions. */
+
+static void overrun PARAMS ((const struct coff_file_info *, const char *));
+static struct res_directory *read_coff_res_dir
+ PARAMS ((const bfd_byte *, const struct coff_file_info *));
+static struct res_resource *read_coff_data_entry
+ PARAMS ((const bfd_byte *, const struct coff_file_info *));
+
+/* Read the resources in a COFF file. */
+
+struct res_directory *
+read_coff_rsrc (filename, target)
+ const char *filename;
+ const char *target;
+{
+ bfd *abfd;
+ char **matching;
+ asection *sec;
+ bfd_size_type size;
+ bfd_byte *data;
+ struct coff_file_info finfo;
+
+ abfd = bfd_openr (filename, target);
+ if (abfd == NULL)
+ bfd_fatal (filename);
+
+ if (! bfd_check_format_matches (abfd, bfd_object, &matching))
+ {
+ bfd_nonfatal (bfd_get_filename (abfd));
+ if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+ list_matching_formats (matching);
+ xexit (1);
+ }
+
+ sec = bfd_get_section_by_name (abfd, ".rsrc");
+ if (sec == NULL)
+ {
+ fprintf (stderr, "%s: %s: no resource section\n", program_name,
+ filename);
+ xexit (1);
+ }
+
+ size = bfd_section_size (abfd, sec);
+ data = (bfd_byte *) xmalloc (size);
+
+ if (! bfd_get_section_contents (abfd, sec, data, 0, size))
+ bfd_fatal ("can't read resource section");
+
+ 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);
+}
+
+/* Give an error if we are out of bounds. */
+
+static void
+overrun (finfo, msg)
+ const struct coff_file_info *finfo;
+ const char *msg;
+{
+ fatal ("%s: %s: address out of bounds", finfo->filename, msg);
+}
+
+/* Read a resource directory. */
+
+static struct res_directory *
+read_coff_res_dir (data, finfo)
+ const bfd_byte *data;
+ const struct coff_file_info *finfo;
+{
+ const struct extern_res_directory *erd;
+ struct res_directory *rd;
+ int name_count, id_count, i;
+ struct res_entry **pp;
+ const struct extern_res_entry *ere;
+
+ if (finfo->data_end - data < sizeof (struct extern_res_directory))
+ overrun (finfo, "directory");
+
+ erd = (const struct extern_res_directory *) data;
+
+ rd = (struct res_directory *) xmalloc (sizeof *rd);
+ rd->characteristics = get_32 (finfo, erd->characteristics);
+ rd->time = get_32 (finfo, erd->time);
+ rd->major = get_16 (finfo, erd->major);
+ rd->minor = get_16 (finfo, erd->minor);
+ rd->entries = NULL;
+
+ name_count = get_16 (finfo, erd->name_count);
+ id_count = get_16 (finfo, erd->id_count);
+
+ pp = &rd->entries;
+
+ /* The resource directory entries immediately follow the directory
+ table. */
+ ere = (const struct extern_res_entry *) (erd + 1);
+
+ for (i = 0; i < name_count; i++, ere++)
+ {
+ unsigned long name, rva;
+ struct res_entry *re;
+ const bfd_byte *ers;
+ int length, j;
+
+ if ((const bfd_byte *) ere >= finfo->data_end)
+ overrun (finfo, "named directory entry");
+
+ name = get_32 (finfo, ere->name);
+ rva = get_32 (finfo, ere->rva);
+
+ /* For some reason the high bit in NAME is set. */
+ name &=~ 0x80000000;
+
+ if (name > finfo->data_end - finfo->data)
+ overrun (finfo, "directory entry name");
+
+ ers = finfo->data + name;
+
+ re = (struct res_entry *) xmalloc (sizeof *re);
+ re->next = NULL;
+ re->id.named = 1;
+ length = get_16 (finfo, ers);
+ re->id.u.n.length = length;
+ re->id.u.n.name = ((unsigned short *)
+ xmalloc (length * sizeof (unsigned short)));
+ for (j = 0; j < length; j++)
+ re->id.u.n.name[j] = get_16 (finfo, ers + j * 2 + 2);
+
+ if ((rva & 0x80000000) != 0)
+ {
+ rva &=~ 0x80000000;
+ if (rva >= finfo->data_end - finfo->data)
+ overrun (finfo, "named subdirectory");
+ re->subdir = 1;
+ re->u.dir = read_coff_res_dir (finfo->data + rva, finfo);
+ }
+ else
+ {
+ if (rva >= finfo->data_end - finfo->data)
+ overrun (finfo, "named resource");
+ re->subdir = 0;
+ re->u.res = read_coff_data_entry (finfo->data + rva, finfo);
+ }
+
+ *pp = re;
+ pp = &re->next;
+ }
+
+ for (i = 0; i < id_count; i++, ere++)
+ {
+ unsigned long name, rva;
+ struct res_entry *re;
+
+ if ((const bfd_byte *) ere >= finfo->data_end)
+ overrun (finfo, "ID directory entry");
+
+ name = get_32 (finfo, ere->name);
+ rva = get_32 (finfo, ere->rva);
+
+ re = (struct res_entry *) xmalloc (sizeof *re);
+ re->next = NULL;
+ re->id.named = 0;
+ re->id.u.id = name;
+
+ if ((rva & 0x80000000) != 0)
+ {
+ rva &=~ 0x80000000;
+ if (rva >= finfo->data_end - finfo->data)
+ overrun (finfo, "ID subdirectory");
+ re->subdir = 1;
+ re->u.dir = read_coff_res_dir (finfo->data + rva, finfo);
+ }
+ else
+ {
+ if (rva >= finfo->data_end - finfo->data)
+ overrun (finfo, "ID resource");
+ re->subdir = 0;
+ re->u.res = read_coff_data_entry (finfo->data + rva, finfo);
+ }
+
+ *pp = re;
+ pp = &re->next;
+ }
+
+ return rd;
+}
+
+/* Read a resource data entry. */
+
+static struct res_resource *
+read_coff_data_entry (data, finfo)
+ const bfd_byte *data;
+ const struct coff_file_info *finfo;
+{
+ const struct extern_res_data *erd;
+ struct res_resource *r;
+ unsigned long size, rva;
+ const bfd_byte *resdata;
+
+ if (finfo->data_end - data < sizeof (struct extern_res_data))
+ overrun (finfo, "data entry");
+
+ erd = (const struct extern_res_data *) data;
+
+ r = (struct res_resource *) xmalloc (sizeof *r);
+ memset (&r->res_info, 0, sizeof (struct res_res_info));
+ r->coff_info.codepage = get_32 (finfo, erd->codepage);
+ r->coff_info.reserved = get_32 (finfo, erd->reserved);
+
+ size = get_32 (finfo, erd->size);
+ rva = get_32 (finfo, erd->rva);
+ if (rva < finfo->secaddr
+ || rva - finfo->secaddr >= finfo->data_end - finfo->data)
+ overrun (finfo, "resource data");
+
+ resdata = finfo->data + (rva - finfo->secaddr);
+
+ r->type = RES_TYPE_USERDATA;
+ r->u.userdata = ((struct rcdata_data *)
+ xmalloc (sizeof (struct rcdata_data)));
+ r->u.userdata->first = ((struct rcdata_item *)
+ xmalloc (sizeof (struct rcdata_item)));
+ r->u.userdata->last = r->u.userdata->first;
+ r->u.userdata->first->next = NULL;
+ r->u.userdata->first->type = RCDATA_BUFFER;
+ r->u.userdata->first->u.buffer.length = size;
+ r->u.userdata->first->u.buffer.data = (unsigned char *) resdata;
+
+ return r;
+}
diff --git a/binutils/resrc.c b/binutils/resrc.c
index 64c6c78..fb340fa 100644
--- a/binutils/resrc.c
+++ b/binutils/resrc.c
@@ -2009,7 +2009,7 @@ write_rc_rcdata (e, rcdata, ind)
else
{
fprintf (e, ",\n");
- indent (e, ind);
+ indent (e, ind + 2);
}
fprintf (e, "%luL", l);
}
@@ -2024,7 +2024,7 @@ write_rc_rcdata (e, rcdata, ind)
else
{
fprintf (e, ",\n");
- indent (e, ind);
+ indent (e, ind + 2);
}
fprintf (e, "%d", i);
i += 2;
@@ -2037,7 +2037,7 @@ write_rc_rcdata (e, rcdata, ind)
else
{
fprintf (e, ",\n");
- indent (e, ind);
+ indent (e, ind + 2);
}
if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
&& isprint (ri->u.buffer.data[i]))
diff --git a/binutils/windres.c b/binutils/windres.c
index d08fb97..bd17aaf 100644
--- a/binutils/windres.c
+++ b/binutils/windres.c
@@ -306,22 +306,9 @@ res_id_print (stream, id, quote)
fprintf (stream, "%lu", id.u.id);
else
{
- unsigned short *s, *se;
-
if (quote)
putc ('"', stream);
- s = id.u.n.name;
- se = s + id.u.n.length;
- while (s < se)
- {
- if (*s == '"')
- fprintf (stream, "\\\"");
- else if ((*s & 0xff) == *s && isprint (*s))
- putc (*s, stream);
- else
- fprintf (stream, "\\%03o", *s);
- ++s;
- }
+ unicode_print (stream, id.u.n.name, id.u.n.length);
if (quote)
putc ('"', stream);
}
@@ -600,8 +587,8 @@ format_from_filename (filename, input)
fclose (e);
- /* A PE executable starts with 0x4d 0x5a 0x90 0x00. */
- if (b1 == 0x4d && b2 == 0x5a && b3 == 0x90 && b4 == 0)
+ /* A PE executable starts with 0x4d 0x5a. */
+ if (b1 == 0x4d && b2 == 0x5a)
return RES_FORMAT_COFF;
/* A COFF .o file starts with a COFF magic number. */
@@ -885,15 +872,6 @@ read_res_file (filename)
return NULL;
}
-struct res_directory *
-read_coff_rsrc (filename, target)
- const char *filename;
- const char *target;
-{
- fatal ("read_coff_rsrc unimplemented");
- return NULL;
-}
-
void
write_res_file (filename, resources)
const char *filename;