This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch/rebase] Make rebase 64 bit capable, take 2


On Jul 10 16:00, Corinna Vinschen wrote:
> Here's my patch.  After some brooding I decided that a -4 and -8 option
> is the way to go.  -4 is default if rebase is a 32 bit exe, -8 is default
> if rebase is a 64 bit executable.  While I was at it, I also added
> long options to rebase.  The corresponding long options to -4 and -8 are,
> who would have guessed, --32 and --64 :)
> 
> Whatever you do now, you're either running in 32 bit mode or in 64 bit
> mode.  This implementation does not allow to mix DLLs of both types in
> the same call.  I renamed the databases to rebase.db.i386 and
> rebase.db.x86_64, that should be pretty self-explanatory.  Rather than
> using different megic numbers I decided to add a WORD which keeps the
> machine type as defined for the executable headers as well.
> 
> I also made a couple of changes so that rebase builds on mingw64.  A few
> more changes for mingw and msys are still required.
> 
> rebaseall got another small kick, so you can specify the -4 and
> -8 options as well.  `uname -m` is used to find out the default.
> 
> Please have a look and give it a try.

Update:

I didn't like the way how messages about skipping files are printed.
That's not well covered by the --verbose option, so I decided to print
the "skipped because" messages, unless the --quite option is given.


Corinna


 	* Makefile.in (DEFS): Add define for sysconfdir.
 	(edit): Add substitute expression for sysconfdir.
         * rebase.c: Implement rebase database.
 	(roundup): Define.
 	(roundup2): Define.
 	(machine): New global variable to keep requested machine type.
         (image_storage_flag): New flag.
         (force_rebase_flag): Ditto.
	 (quite): Ditto.
	 (verbose): Convert to type BOOL.
         (progname): New variable for printing application name in error
         output.
         (img_info_hdr_t): New type.
         (img_info_t): De-const name.  Add name_size, slot_size, and
         flag members.
 	(IMG_INFO_FILE_I386): Define database name for i386 systems.
 	(IMG_INFO_FILE_AMD64): Define database name for x86_64 systems.
         (IMG_INFO_FILE): Define default database name.
 	(gen_progname): New function to initialize progname.
         (main): Call gen_progname.  Only fetch Cygwin DLL info in
 	32 bit mode for now.  Always collect file info, then rebase
 	dependent on mode.  In database mode, call load_image_info,
 	collect_image_info, merge_image_info, and save_image_info.
         (img_info_name_cmp): New comparison function.
         (save_image_info): New function to save rebase database.
         (load_image_info): New function to load rebase database.
         (merge_image_info): New function to compute rebase values.
         (collect_image_info): Fix typo in condition.  Check for rebaseable
 	file here.  Convert given filename to absolute pathname.
 	(print_image_info): Revamp to take database into account.  Add
 	collision information.
         (rebase): Take down_flag as parameter to allow influencing the
         algorithm from caller.  Drop call to is_rebaseable here.
 	(long_options): New option array for getopt_long.
 	(short_options): Hold short options.
         (parse_args): Drop anOptions.  Rename anOption to opt.  Call
 	getopt_long.  Handle all new flags.
         (usage): Change to reflect new flags.
         (help): New function.
         * rebaseall.in: Use database mode.  Add -4 and -8 options and
 	handle 32 and 64 bit modes.


Index: Makefile.in
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/Makefile.in,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile.in
--- Makefile.in	7 Jul 2011 16:08:37 -0000	1.5
+++ Makefile.in	10 Jul 2011 14:58:58 -0000
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.5 2011/07/07 16:08:37 corinna Exp $
+# $Id: Makefile.in,v 1.4 2011/06/28 19:43:19 corinna Exp $
 # @configure_input@
 # Makefile for rebase
 
@@ -56,7 +56,7 @@ FGREP = @FGREP@
 ASH = @ASH@
 
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(srcdir)/imagehelper
-DEFS = @DEFS@ -DVERSION='"$(PACKAGE_VERSION)"' -DLIB_VERSION='"$(LIB_VERSION)"'
+DEFS = @DEFS@ -DVERSION='"$(PACKAGE_VERSION)"' -DLIB_VERSION='"$(LIB_VERSION)"' -DSYSCONFDIR='"$(sysconfdir)"'
 
 override CFLAGS+=-Wall -Werror
 override CXXFLAGS+=-Wall -Werror
@@ -109,6 +109,7 @@ getopt_long.$(O):: getopt_long.c getopt.
 # bindir and friends in your shell scripts"
 edit = sed \
 	-e 's|@bindir[@]|$(bindir)|g' \
+	-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
 	-e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
 	-e 's|@prefix[@]|$(prefix)|g' \
 	-e 's|@exec_prefix[@]|$(exec_prefix)|g' \
Index: rebase.c
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/rebase.c,v
retrieving revision 1.5
diff -u -p -r1.5 rebase.c
--- rebase.c	8 Jul 2011 08:22:59 -0000	1.5
+++ rebase.c	10 Jul 2011 14:58:58 -0000
@@ -19,6 +19,9 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#if defined(__CYGWIN__) || defined(__MSYS__)
+#include <sys/cygwin.h>
+#endif
 #include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
@@ -26,125 +29,709 @@
 #include <getopt.h>
 #include <string.h>
 #include <inttypes.h>
+#include <errno.h>
 #include "imagehelper.h"
 
+#define roundup(x,y)	((((x) + ((y) - 1)) / (y)) * (y))
+#define roundup2(x,y)	(((x) + (y) - 1) & ~((y) - 1))
+
+BOOL save_image_info ();
+BOOL load_image_info ();
+BOOL merge_image_info ();
 BOOL collect_image_info (const char *pathname);
 void print_image_info ();
-BOOL rebase (const char *pathname, ULONG64 *new_image_base);
+BOOL rebase (const char *pathname, ULONG64 *new_image_base, BOOL down_flag);
 void parse_args (int argc, char *argv[]);
 unsigned long long string_to_ulonglong (const char *string);
 void usage ();
+void help ();
 BOOL is_rebaseable (const char *pathname);
 FILE *file_list_fopen (const char *file_list);
 char *file_list_fgets (char *buf, int size, FILE *file);
 int file_list_fclose (FILE *file);
 void version ();
 
+#ifdef __x86_64__
+WORD machine = IMAGE_FILE_MACHINE_AMD64;
+#else
+WORD machine = IMAGE_FILE_MACHINE_I386;
+#endif
 ULONG64 image_base = 0;
 BOOL down_flag = FALSE;
 BOOL image_info_flag = FALSE;
+BOOL image_storage_flag = FALSE;
+BOOL force_rebase_flag = FALSE;
 ULONG offset = 0;
 int args_index = 0;
-int verbose = 0;
+BOOL verbose = FALSE;
+BOOL quiet = FALSE;
 const char *file_list = 0;
 const char *stdin_file_list = "-";
 
+const char *progname;
+
+const char IMG_INFO_MAGIC[4] = "rBiI";
+const ULONG IMG_INFO_VERSION = 1;
+
 ULONG ALLOCATION_SLOT;	/* Allocation granularity. */
 
+#pragma pack (push, 4)
+
+typedef struct _img_info_hdr
+{
+  CHAR    magic[4];	/* Always IMG_INFO_MAGIC.                            */
+  WORD    machine;	/* IMAGE_FILE_MACHINE_I386/IMAGE_FILE_MACHINE_AMD64  */
+  WORD    version;	/* Database version, always set to IMG_INFO_VERSION. */
+  ULONG64 base;		/* Base address (-b) used to generate database.      */
+  ULONG   offset;	/* Offset (-o) used to generate database.            */
+  BOOL    down_flag;	/* Always TRUE right now.                            */
+  ULONG   count;	/* Number of img_info_t entries following header.    */
+} img_info_hdr_t;
+
 typedef struct _img_info
 {
-  const char *name;
-  ULONG64 base;
-  ULONG size;
+  union {
+    PCHAR   name;	/* Absolute path to DLL.  The strings are stored     */
+    ULONG64 _filler;	/* right after the img_info_t table, in the same     */
+  };			/* order as the img_info_t entries.                  */
+  ULONG   name_size;	/* Length of name string including trailing NUL.     */
+  ULONG64 base;		/* Base address the DLL has been rebased to.         */
+  ULONG   size;		/* Size of the DLL at rebased time.                  */
+  ULONG   slot_size;	/* Size of the DLL rounded to allocation granularity.*/
+  struct {		/* Flags                                             */
+    unsigned needs_rebasing : 1; /* Set to 0 in the database.  Used only     */
+    				 /* while rebasing.                          */
+  } flag;
 } img_info_t;
 
+#pragma pack (pop)
+
 img_info_t *img_info_list = NULL;
 unsigned int img_info_size = 0;
+unsigned int img_info_rebase_start = 0;
 unsigned int img_info_max_size = 0;
 
+#if !defined (__CYGWIN__) && !defined (__MSYS__)
+#undef SYSCONFDIR
+#define SYSCONFDIR "/../etc"
+#endif
+#define IMG_INFO_FILE_I386 SYSCONFDIR "/rebase.db.i386"
+#define IMG_INFO_FILE_AMD64 SYSCONFDIR "/rebase.db.x86_64"
+#ifdef __x86_64__
+#define IMG_INFO_FILE IMG_INFO_FILE_AMD64
+#else
+#define IMG_INFO_FILE IMG_INFO_FILE_I386
+#endif
+char *db_file = IMG_INFO_FILE;
+char tmp_file[] =     SYSCONFDIR "/rebase.db.XXXXXX";
+
 #ifdef __CYGWIN__
 ULONG64 cygwin_dll_image_base = 0;
 ULONG cygwin_dll_image_size = 0;
 #endif
 
+void
+gen_progname (const char *arg0)
+{
+  char *p;
+
+  p = strrchr (arg0, '/');
+  if (!p)
+    p = strrchr (arg0, '\\');
+  progname = p ? p + 1 : arg0;
+  if ((p = strrchr (progname, '.')) && !strcmp (p, ".exe"))
+    *p = 0;
+}
+
 int
 main (int argc, char *argv[])
 {
-  ULONG64 new_image_base = 0;
   int i = 0;
   SYSTEM_INFO si;
   BOOL status;
 
   setlocale (LC_ALL, "");
+  gen_progname (argv[0]);
   parse_args (argc, argv);
-  new_image_base = image_base;
   GetSystemInfo (&si);
   ALLOCATION_SLOT = si.dwAllocationGranularity;
 
+  /* If database support has been requested, load database. */
+  if (image_storage_flag)
+    {
+      if (load_image_info () < 0)
+      	return 2;
+      img_info_rebase_start = img_info_size;
+    }
+
 #ifdef __CYGWIN__
-  /* Fetch the Cygwin DLLs data to make sure that DLLs aren't rebased
-     into the memory area taken by the Cygwin DLL. */
-  GetImageInfos64 ("/bin/cygwin1.dll", NULL,
-		   &cygwin_dll_image_base, &cygwin_dll_image_size);
-  /* Take the three shared memory areas preceeding the DLL into account. */
-  cygwin_dll_image_base -= 3 * ALLOCATION_SLOT;
-  /* Add a slack of 8 * 64K at the end of the Cygwin DLL.  This leave a
-     bit of room to install newer, bigger Cygwin DLLs, as well as room to
-     install non-optimized DLLs for debugging purposes.  Otherwise the
-     slightest change might break fork again :-P */
-  cygwin_dll_image_size += 3 * ALLOCATION_SLOT + 8 * ALLOCATION_SLOT;
+  if (machine == IMAGE_FILE_MACHINE_I386)
+    {
+      /* Fetch the Cygwin DLLs data to make sure that DLLs aren't rebased
+	 into the memory area taken by the Cygwin DLL. */
+      GetImageInfos64 ("/bin/cygwin1.dll", NULL,
+		       &cygwin_dll_image_base, &cygwin_dll_image_size);
+      /* Take the three shared memory areas preceeding the DLL into account. */
+      cygwin_dll_image_base -= 3 * ALLOCATION_SLOT;
+      /* Add a slack of 8 * 64K at the end of the Cygwin DLL.  This leave a
+	 bit of room to install newer, bigger Cygwin DLLs, as well as room to
+	 install non-optimized DLLs for debugging purposes.  Otherwise the
+	 slightest change might break fork again :-P */
+      cygwin_dll_image_size += 3 * ALLOCATION_SLOT + 8 * ALLOCATION_SLOT;
+    }
 #endif
 
-  /* Rebase file list, if specified. */
+  /* Collect file list, if specified. */
   if (file_list)
     {
-      status = TRUE;
       char filename[MAX_PATH + 2];
       FILE *file = file_list_fopen (file_list);
       if (!file)
-	exit (2);
+	return 2;
 
+      status = TRUE;
       while (file_list_fgets (filename, MAX_PATH + 2, file))
 	{
-	  status = image_info_flag ? collect_image_info (filename)
-				    : rebase (filename, &new_image_base);
+	  status = collect_image_info (filename);
 	  if (!status)
 	    break;
 	}
 
       file_list_fclose (file);
       if (!status)
-	exit (2);
+	return 2;
     }
 
-  /* Rebase command line arguments. */
+  /* Collect command line arguments. */
   for (i = args_index; i < argc; i++)
     {
       const char *filename = argv[i];
-      status = image_info_flag ? collect_image_info (filename)
-				 : rebase (filename, &new_image_base);
+      status = collect_image_info (filename);
       if (!status)
-	exit (2);
+	return 2;
     }
 
+  /* Nothing to do? */
+  if (img_info_size == 0)
+    return 0;
+
+  /* Check what we have to do and do it. */
   if (image_info_flag)
-    print_image_info ();
+    {
+      /* Print. */
+      print_image_info ();
+    }
+  else if (!image_storage_flag)
+    {
+      /* Rebase. */
+      ULONG64 new_image_base = image_base;
+      for (i = 0; i < img_info_size; ++i)
+	{
+	  status = rebase (img_info_list[i].name, &new_image_base, down_flag);
+	  if (!status)
+	    return 2;
+	}
+    }
+  else
+    {
+      /* Rebase with database support. */
+      merge_image_info ();
+      status = TRUE;
+      for (i = 0; i < img_info_size; ++i)
+	if (img_info_list[i].flag.needs_rebasing)
+	  {
+	    ULONG64 new_image_base = img_info_list[i].base;
+	    status = rebase (img_info_list[i].name, &new_image_base, FALSE);
+	    if (status)
+	      img_info_list[i].flag.needs_rebasing = 0;
+	  }
+      if (save_image_info () < 0)
+	return 2;
+    }
+
+  return 0;
+}
+
+int
+img_info_cmp (const void *a, const void *b)
+{
+  ULONG64 abase = ((img_info_t *) a)->base;
+  ULONG64 bbase = ((img_info_t *) b)->base;
 
-  exit (0);
+  if (abase < bbase)
+    return -1;
+  if (abase > bbase)
+    return 1;
+  return strcmp (((img_info_t *) a)->name, ((img_info_t *) b)->name);
+}
+
+int
+img_info_name_cmp (const void *a, const void *b)
+{
+  return strcmp (((img_info_t *) a)->name, ((img_info_t *) b)->name);
+}
+
+#ifndef __CYGWIN__
+int
+mkstemp (char *name)
+{
+  return open (mktemp (name), O_CREAT | O_TRUNC | O_EXCL, 0600);
+}
+#endif
+
+int
+save_image_info ()
+{
+  int i, fd;
+  int ret = 0;
+  img_info_hdr_t hdr;
+
+  /* Remove all DLLs which couldn't be rebased from the list before storing
+     it in the database file. */
+  for (i = 0; i < img_info_size; ++i)
+    if (img_info_list[i].flag.needs_rebasing)
+      img_info_list[i--] = img_info_list[--img_info_size];
+  /* Create a temporary file to write to. */
+  fd = mkstemp (tmp_file);
+  if (fd < 0)
+    {
+      fprintf (stderr, "%s: failed to create temporary rebase database: %s\n",
+	       progname, strerror (errno));
+      return -1;
+    }
+  qsort (img_info_list, img_info_size, sizeof (img_info_t), img_info_name_cmp);
+  /* First write the number of entries. */
+  memcpy (hdr.magic, IMG_INFO_MAGIC, 4);
+  hdr.machine = machine;
+  hdr.version = IMG_INFO_VERSION;
+  hdr.base = image_base;
+  hdr.offset = offset;
+  hdr.down_flag = down_flag;
+  hdr.count = img_info_size;
+  if (write (fd, &hdr, sizeof hdr) < 0)
+    {
+      fprintf (stderr, "%s: failed to write rebase database: %s\n",
+	       progname, strerror (errno));
+      ret = -1;
+    }
+  /* Write the list. */
+  else if (write (fd, img_info_list, img_info_size * sizeof (img_info_t)) < 0)
+    {
+      fprintf (stderr, "%s: failed to write rebase database: %s\n",
+	       progname, strerror (errno));
+      ret = -1;
+    }
+  else
+    {
+      int i;
+
+      /* Write all strings. */
+      for (i = 0; i < img_info_size; ++i)
+	if (write (fd, img_info_list[i].name,
+		   strlen (img_info_list[i].name) + 1) < 0)
+	  {
+	    fprintf (stderr, "%s: failed to write rebase database: %s\n",
+		     progname, strerror (errno));
+	    ret = -1;
+	    break;
+	  }
+    }
+#ifdef __CYGWIN__
+  fchmod (fd, 0660);
+#else
+  chmod (tmp_file, 0660);
+#endif
+  close (fd);
+  if (ret < 0)
+    unlink (tmp_file);
+  else
+    {
+      if (unlink (db_file) < 0 && errno != ENOENT)
+	{
+	  fprintf (stderr,
+		   "%s: failed to remove old rebase database file \"%s\":\n"
+		   "%s\n"
+		   "The new rebase database is stored in \"%s\".\n"
+		   "Manually remove \"%s\" and rename \"%s\" to \"%s\",\n"
+		   "otherwise the new rebase database will be unusable.\n",
+		   progname, db_file,
+		   strerror (errno),
+		   tmp_file,
+		   db_file, tmp_file, db_file);
+	  ret = -1;
+	}
+      else if (rename (tmp_file, db_file) < 0)
+	{
+	  fprintf (stderr,
+		   "%s: failed to rename \"%s\" to \"%s\":\n"
+		   "%s\n"
+		   "Manually rename \"%s\" to \"%s\",\n"
+		   "otherwise the new rebase database will be unusable.\n",
+		   progname, tmp_file, db_file,
+		   strerror (errno),
+		   tmp_file, db_file);
+	  ret = -1;
+	}
+    }
+  return ret;
+}
+
+int
+load_image_info ()
+{
+  int fd;
+  int ret = 0;
+  int i;
+  img_info_hdr_t hdr;
+
+  fd = open (db_file, O_RDONLY);
+  if (fd < 0)
+    {
+      /* It's no error if the file doesn't exist.  However, in this case
+	 the -b option is mandatory. */
+      if (errno == ENOENT && image_base)
+      	return 0;
+      fprintf (stderr, "%s: failed to open rebase database \"%s\":\n%s\n",
+	       progname, db_file, strerror (errno));
+      return -1;
+    }
+  /* First read the header. */
+  if (read (fd, &hdr, sizeof hdr) < 0)
+    {
+      fprintf (stderr, "%s: failed to read rebase database \"%s\":\n%s\n",
+	       progname, db_file, strerror (errno));
+      close (fd);
+      return -1;
+    }
+  /* Check the header. */
+  if (memcmp (hdr.magic, IMG_INFO_MAGIC, 4) != 0)
+    {
+      fprintf (stderr, "%s: \"%s\" is not a valid rebase database.\n",
+	       progname, db_file);
+      close (fd);
+      return -1;
+    }
+  if (hdr.machine != machine)
+    {
+      if (hdr.machine == IMAGE_FILE_MACHINE_I386)
+	fprintf (stderr,
+"%s: \"%s\" is a database file for 32 bit DLLs but\n"
+"I'm started to handle 64 bit DLLs.  If you want to handle 32 bit DLLs,\n"
+"use the -4 option.\n", progname, db_file);
+      else if (hdr.machine == IMAGE_FILE_MACHINE_AMD64)
+	fprintf (stderr,
+"%s: \"%s\" is a database file for 64 bit DLLs but\n"
+"I'm started to handle 32 bit DLLs.  If you want to handle 64 bit DLLs,\n"
+"use the -8 option.\n", progname, db_file);
+      else
+	fprintf (stderr, "%s: \"%s\" is a database file for a machine type\n"
+			 "I don't know about.", progname, db_file);
+      close (fd);
+      return -1;
+    }
+  if (hdr.version != IMG_INFO_VERSION)
+    {
+      fprintf (stderr, "%s: \"%s\" is a version %u rebase database.\n"
+		       "I can only handle versions up to %lu.\n",
+	       progname, db_file, hdr.version, IMG_INFO_VERSION);
+      close (fd);
+      return -1;
+    }
+  /* If no new image base has been specified, use the one from the header. */
+  if (image_base == 0)
+    {
+      image_base = hdr.base;
+      down_flag = hdr.down_flag;
+    }
+  if (offset == 0)
+    offset = hdr.offset;
+  /* Don't enforce rebasing if address and offset are unchanged or taken from
+     the file anyway. */
+  if (image_base == hdr.base && offset == hdr.offset)
+    force_rebase_flag = FALSE;
+  img_info_size = hdr.count;
+  /* Allocate memory for the image list. */
+  if (ret == 0)
+    {
+      img_info_max_size = roundup (img_info_size, 100);
+      img_info_list = (img_info_t *) calloc (img_info_max_size,
+					     sizeof (img_info_t));
+      if (!img_info_list)
+	{
+	  fprintf (stderr, "%s: Out of memory.\n", progname);
+	  ret = -1;
+	}
+    }
+  /* Now read the list. */
+  if (ret == 0
+      && read (fd, img_info_list, img_info_size * sizeof (img_info_t)) < 0)
+    {
+      fprintf (stderr, "%s: failed to read rebase database \"%s\":\n%s\n",
+	       progname, db_file, strerror (errno));
+      ret = -1;
+    }
+  /* Make sure all pointers are NULL. */
+  if (ret == 0)
+    for (i = 0; i < img_info_size; ++i)
+      img_info_list[i].name = NULL;
+  /* Eventually read the strings. */
+  if (ret == 0)
+    {
+      for (i = 0; i < img_info_size; ++i)
+	{
+	  img_info_list[i].name = (char *)
+				  malloc (img_info_list[i].name_size);
+	  if (!img_info_list[i].name)
+	    {
+	      fprintf (stderr, "%s: Out of memory.\n", progname);
+	      ret = -1;
+	      break;
+	    }
+	  if (read (fd, img_info_list[i].name,
+		    img_info_list[i].name_size) < 0)
+	    {
+	      fprintf (stderr, "%s: failed to read rebase database \"%s\": "
+		       "%s\n", progname, db_file, strerror (errno));
+	      ret = -1;
+	      break;
+	    }
+	}
+    }
+  close (fd);
+  /* On failure, free all allocated memory and set list pointer to NULL. */
+  if (ret < 0)
+    {
+      for (i = 0; i < img_info_size && img_info_list[i].name; ++i)
+	free (img_info_list[i].name);
+      free (img_info_list);
+      img_info_list = NULL;
+      img_info_size = 0;
+      img_info_max_size = 0;
+    }
+  return ret;
+}
+
+int
+merge_image_info ()
+{
+  int i, end;
+  img_info_t *match;
+  ULONG64 floating_image_base;
+
+  /* Sort new files from command line by name. */
+  qsort (img_info_list + img_info_rebase_start,
+	 img_info_size - img_info_rebase_start, sizeof (img_info_t),
+	 img_info_name_cmp);
+  /* Iterate through new files and eliminate duplicates. */
+  for (i = img_info_rebase_start; i + 1 < img_info_size; ++i)
+    if ((img_info_list[i].name_size == img_info_list[i + 1].name_size
+	 && !strcmp (img_info_list[i].name, img_info_list[i + 1].name))
+#ifdef __CYGWIN__
+	|| !strcmp (img_info_list[i].name, "/usr/bin/cygwin1.dll")
+#endif
+       )
+      {
+	free (img_info_list[i].name);
+	memmove (img_info_list + i, img_info_list + i + 1, 
+		 (img_info_size - i - 1) * sizeof (img_info_t));
+	--img_info_size;
+	--i;
+      }
+  /* Iterate through new files and see if they are already available in
+     existing database. */
+  if (img_info_rebase_start)
+    {
+      for (i = img_info_rebase_start; i < img_info_size; ++i)
+	{
+	  match = bsearch (&img_info_list[i], img_info_list,
+			   img_info_rebase_start, sizeof (img_info_t),
+			   img_info_name_cmp);
+	  if (match)
+	    {
+	      /* We found a match.  Now test if the "new" file is actually
+		 the old file, or if it at least fits into the memory slot
+		 of the old file.  If so, screw the new file into the old slot.
+		 Otherwise set base to 0 to indicate that this DLL needs a new
+		 base address. */
+	      if (match->base != img_info_list[i].base
+		  || match->slot_size < img_info_list[i].slot_size)
+		{
+		  /* Reuse the old address if possible. */
+		  if (match->slot_size < img_info_list[i].slot_size)
+		    match->base = 0;
+		  match->flag.needs_rebasing = 1;
+		}
+	      /* Unconditionally overwrite old with new size. */
+	      match->size = img_info_list[i].size;
+	      match->slot_size = img_info_list[i].slot_size;
+	      /* Remove new entry from array. */
+	      free (img_info_list[i].name);
+	      img_info_list[i--] = img_info_list[--img_info_size];
+	    }
+	  else
+	    /* Not in database yet.  Set base to 0 to choose a new one. */
+	    img_info_list[i].base = 0;
+	}
+      /* After eliminating the duplicates, check if the user requested
+	 a new base address on the command line.  If so, overwrite all
+	 base addresses with 0 and set img_info_rebase_start to 0, to
+	 skip any further test. */
+      if (force_rebase_flag)
+	img_info_rebase_start = 0;
+    }
+  if (!img_info_rebase_start)
+    {
+      /* No database yet or enforcing a new base address.  Set base of all
+	 DLLs to 0. */
+      for (i = 0; i < img_info_size; ++i)
+	img_info_list[i].base = 0;
+    }
+
+  /* Now sort the old part of the list by base address. */
+  if (img_info_rebase_start)
+    qsort (img_info_list, img_info_rebase_start, sizeof (img_info_t),
+	   img_info_cmp);
+  /* Perform several tests on the information fetched from the database
+     to match with reality. */
+  for (i = 0; i < img_info_rebase_start; ++i)
+    {
+      ULONG64 cur_base;
+      ULONG cur_size, slot_size;
+
+      /* Files with the needs_rebasing flag set have been checked already. */
+      if (img_info_list[i].flag.needs_rebasing)
+	continue;
+      /* Check if the files in the old list still exist.  Drop non-existant
+	 or unaccessible files. */
+      if (access (img_info_list[i].name, F_OK) == -1
+	  || !GetImageInfos64 (img_info_list[i].name, NULL,
+			       &cur_base, &cur_size))
+      	{
+	  free (img_info_list[i].name);
+	  memmove (img_info_list + i, img_info_list + i + 1,
+		   (img_info_size - i - 1) * sizeof (img_info_t));
+	  --img_info_rebase_start;
+	  --img_info_size;
+	  continue;
+	}
+      slot_size = roundup2 (cur_size, ALLOCATION_SLOT);
+      /* If the file has been reinstalled, try to rebase to the same address
+	 in the first place. */
+      if (cur_base != img_info_list[i].base)
+	{
+	  img_info_list[i].flag.needs_rebasing = 1;
+	  /* Set cur_base to the old base to simplify subsequent tests. */
+	  cur_base = img_info_list[i].base;
+	}
+      /* However, if the DLL got bigger and doesn't fit into its slot
+	 anymore, rebase this DLL from scratch. */
+      if (i + 1 < img_info_rebase_start
+	  && cur_base + slot_size + offset >= img_info_list[i + 1].base)
+	img_info_list[i].base = 0;
+      /* Does the file match the base address requirements?  If not,
+	 rebase from scratch. */
+      else if ((down_flag && cur_base + slot_size + offset >= image_base)
+	       || (!down_flag && cur_base < image_base))
+	img_info_list[i].base = 0;
+      /* Unconditionally overwrite old with new size. */
+      img_info_list[i].size = cur_size;
+      img_info_list[i].slot_size = slot_size;
+      /* Make sure all DLLs with base address 0 have the needs_rebasing
+	 flag set. */
+      if (img_info_list[i].base == 0)
+	img_info_list[i].flag.needs_rebasing = 1;
+    }
+  /* The remainder of the function expects img_info_size to be > 0. */
+  if (img_info_size == 0)
+    return 0;
+
+  /* Now sort entire list by base address.  The files with address 0 will
+     be first. */
+  if (!force_rebase_flag)
+    qsort (img_info_list, img_info_size, sizeof (img_info_t), img_info_cmp);
+  /* Try to fit all DLLs with base address 0 into the given list. */
+  /* FIXME: This loop only implements the top-down case.  Implement a
+     bottom-up case, too, at one point. */
+  floating_image_base = image_base;
+  end = img_info_size - 1;
+  while (img_info_list[0].base == 0)
+    {
+      ULONG64 new_base;
+
+      /* Skip trailing entries as long as there is no hole. */
+       while (img_info_list[end].base + img_info_list[end].slot_size + offset
+	     >= floating_image_base)
+	{
+	  floating_image_base = img_info_list[end].base;
+	  --end;
+	}
+      /* Test if one of the DLLs with address 0 fits into the hole. */
+      for (i = 0, new_base = 0; img_info_list[i].base == 0; ++i, new_base = 0)
+	{
+	  new_base = floating_image_base - img_info_list[i].slot_size - offset;
+	  if (new_base >= img_info_list[end].base
+			  + img_info_list[end].slot_size
+#ifdef __CYGWIN__
+	      /* Don't overlap the Cygwin DLL. */
+	      && (new_base >= cygwin_dll_image_base + cygwin_dll_image_size
+		  || new_base + img_info_list[i].slot_size
+		     <= cygwin_dll_image_base)
+#endif
+	     )
+	    break;
+	}
+      /* Found a match.  Mount into list. */
+      if (new_base)
+	{
+	  img_info_t tmp = img_info_list[i];
+	  tmp.base = new_base;
+	  memmove (img_info_list + i, img_info_list + i + 1,
+		   (end - i) * sizeof (img_info_t));
+	  img_info_list[end] = tmp;
+	  continue;
+	}
+      /* Nothing matches.  Set floating_image_base to the start of the
+	 uppermost DLL at this point and try again. */
+#ifdef __CYGWIN__
+      if (floating_image_base >= cygwin_dll_image_base + cygwin_dll_image_size
+	  && img_info_list[end].base < cygwin_dll_image_base)
+	floating_image_base = cygwin_dll_image_base;
+      else
+#endif
+	{
+	  floating_image_base = img_info_list[end].base;
+	  --end;
+	}
+    }
+
+  return 0;
 }
 
 BOOL
 collect_image_info (const char *pathname)
 {
+  BOOL ret;
+  WORD dll_machine;
+
   /* Skip if file does not exist to prevent ReBaseImage() from using it's
      stupid search algorithm (e.g, PATH, etc.). */
   if (access (pathname, F_OK) == -1)
     {
-      fprintf (stderr, "%s: skipped because nonexistent\n", pathname);
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because nonexistent.\n", pathname);
       return TRUE;
     }
 
-  if (img_info_size <= img_info_max_size)
+  /* Skip if not rebaseable, but only if we're collecting for rebasing,
+     not if we're collecting for printing only. */
+  if (!image_info_flag && !is_rebaseable (pathname))
+    {
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because not rebaseable\n", pathname);
+      return TRUE;
+    }
+
+  if (img_info_size >= img_info_max_size)
     {
       img_info_max_size += 100;
       img_info_list = (img_info_t *) realloc (img_info_list,
@@ -152,46 +739,152 @@ collect_image_info (const char *pathname
 					      * sizeof (img_info_t));
       if (!img_info_list)
 	{
-	  fprintf (stderr, "Out of memory.\n");
-	  exit (2);
+	  fprintf (stderr, "%s: Out of memory.\n", progname);
+	  return FALSE;
 	}
     }
 
-  if (GetImageInfos64 (pathname, NULL,
-		       &img_info_list[img_info_size].base,
-		       &img_info_list[img_info_size].size))
-    img_info_list[img_info_size++].name = strdup (pathname);
+  ret = GetImageInfos64 (pathname, &dll_machine,
+			 &img_info_list[img_info_size].base,
+			 &img_info_list[img_info_size].size);
+  if (!ret)
+    {
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because file info unreadable.\n",
+		 pathname);
+      return TRUE;
+    }
+  if (dll_machine != machine)
+    {
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because wrong machine type.\n",
+		 pathname);
+      return TRUE;
+    }
+  img_info_list[img_info_size].slot_size
+    = roundup2 (img_info_list[img_info_size].size, ALLOCATION_SLOT);
+  img_info_list[img_info_size].flag.needs_rebasing = 1;
+  /* This back and forth from POSIX to Win32 is a way to get a full path
+     more thoroughly.  For instance, the difference between /bin and
+     /usr/bin will be eliminated. */
+#if defined (__MSYS__)
+  {
+    char w32_path[MAX_PATH];
+    char full_path[MAX_PATH];
+    cygwin_conv_to_full_win32_path (pathname, w32_path);
+    cygwin_conv_to_full_posix_path (w32_path, full_path);
+    img_info_list[img_info_size].name = strdup (full_path);
+    img_info_list[img_info_size].name_size = strlen (full_path) + 1;
+  }
+#elif defined (__CYGWIN__)
+  {
+    PWSTR w32_path = cygwin_create_path (CCP_POSIX_TO_WIN_W, pathname);
+    if (!w32_path)
+      {
+	fprintf (stderr, "%s: Out of memory.\n", progname);
+	return FALSE;
+      }
+    img_info_list[img_info_size].name
+      = cygwin_create_path (CCP_WIN_W_TO_POSIX, w32_path);
+    if (!img_info_list[img_info_size].name)
+      {
+	fprintf (stderr, "%s: Out of memory.\n", progname);
+	return FALSE;
+      }
+    free (w32_path);
+    img_info_list[img_info_size].name_size
+      = strlen (img_info_list[img_info_size].name) + 1;
+  }
+#else
+  {
+    char full_path[MAX_PATH];
+    GetFullPathName (pathname, MAX_PATH, full_path, NULL);
+    img_info_list[img_info_size].name = strdup (full_path);
+    img_info_list[img_info_size].name_size = strlen (full_path) + 1;
+  }
+#endif
+  ++img_info_size;
   return TRUE;
 }
 
-int
-img_info_cmp (const void *a, const void *b)
-{
-  ULONG64 abase = ((img_info_t *) a)->base;
-  ULONG64 bbase = ((img_info_t *) b)->base;
-
-  if (abase < bbase)
-    return -1;
-  if (abase > bbase)
-    return 1;
-  return strcmp (((img_info_t *) a)->name, ((img_info_t *) b)->name);
-}
-
 void
 print_image_info ()
 {
   unsigned int i;
 
+  /* Sort list by name. */
+  qsort (img_info_list, img_info_size, sizeof (img_info_t), img_info_name_cmp);
+  /* Iterate through list and eliminate duplicates. */
+  for (i = 0; i + 1 < img_info_size; ++i)
+    if (img_info_list[i].name_size == img_info_list[i + 1].name_size
+	&& !strcmp (img_info_list[i].name, img_info_list[i + 1].name))
+      {
+	/* Remove duplicate, but prefer one from the command line over one
+	   from the database, because the one from the command line reflects
+	   the reality, while the database is wishful thinking. */
+	if (img_info_list[i].flag.needs_rebasing == 0)
+	  {
+	    free (img_info_list[i].name);
+	    memmove (img_info_list + i, img_info_list + i + 1, 
+		     (img_info_size - i - 1) * sizeof (img_info_t));
+	  }
+	else
+	  {
+	    free (img_info_list[i + 1].name);
+	    if (i + 2 < img_info_size)
+	      memmove (img_info_list + i + 1, img_info_list + i + 2, 
+		       (img_info_size - i - 2) * sizeof (img_info_t));
+	  }
+	--img_info_size;
+	--i;
+      }
+  /* For entries loaded from database, collect image info to reflect reality.
+     Also, collect_image_info sets needs_rebasing to 1, so reset here. */
+  for (i = 0; i < img_info_size; ++i)
+    {
+      if (img_info_list[i].flag.needs_rebasing == 0)
+	{
+	  ULONG64 base;
+	  ULONG size;
+
+	  if (GetImageInfos64 (img_info_list[i].name, NULL, &base, &size))
+	    {
+	      img_info_list[i].base = base;
+	      img_info_list[i].size = size;
+	      img_info_list[i].slot_size
+		= roundup2 (img_info_list[i].size, ALLOCATION_SLOT);
+	    }
+	}
+      else
+	img_info_list[i].flag.needs_rebasing = 0;
+    }
+  /* Now sort by address. */
   qsort (img_info_list, img_info_size, sizeof (img_info_t), img_info_cmp);
   for (i = 0; i < img_info_size; ++i)
-    printf ("%-47s base 0x%08" PRIx64 " size 0x%08lx\n",
-	    img_info_list[i].name,
-	    img_info_list[i].base,
-	    img_info_list[i].size);
+    {
+      int tst;
+      ULONG64 end = img_info_list[i].base + img_info_list[i].slot_size;
+
+      /* Check for overlap and mark both DLLs. */
+      for (tst = i + 1;
+	   tst < img_info_size && img_info_list[tst].base < end;
+	   ++tst)
+	{
+	  img_info_list[i].flag.needs_rebasing = 1;
+	  img_info_list[tst].flag.needs_rebasing = 1;
+	}
+      printf ("%-*s base 0x%0*" PRIx64 " size 0x%08lx %c\n",
+	      machine == IMAGE_FILE_MACHINE_I386 ? 45 : 37,
+	      img_info_list[i].name,
+	      machine == IMAGE_FILE_MACHINE_I386 ? 8 : 16,
+	      img_info_list[i].base,
+	      img_info_list[i].size,
+	      img_info_list[i].flag.needs_rebasing ? '*' : ' ');
+    }
 }
 
 BOOL
-rebase (const char *pathname, ULONG64 *new_image_base)
+rebase (const char *pathname, ULONG64 *new_image_base, BOOL down_flag)
 {
   ULONG64 old_image_base, prev_new_image_base;
   ULONG old_image_size, new_image_size;
@@ -201,22 +894,16 @@ rebase (const char *pathname, ULONG64 *n
      stupid search algorithm (e.g, PATH, etc.). */
   if (access (pathname, F_OK) == -1)
     {
-      fprintf (stderr, "%s: skipped because nonexistent\n", pathname);
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because nonexistent\n", pathname);
       return TRUE;
     }
 
   /* Skip if not writable. */
   if (access (pathname, W_OK) == -1)
     {
-      fprintf (stderr, "%s: skipped because not writable\n", pathname);
-      return TRUE;
-    }
-
-  /* Skip if not rebaseable. */
-  if (!is_rebaseable (pathname))
-    {
-      if (verbose)
-	fprintf (stderr, "%s: skipped because not rebaseable\n", pathname);
+      if (!quiet)
+	fprintf (stderr, "%s: skipped because not writable\n", pathname);
       return TRUE;
     }
 
@@ -312,18 +999,47 @@ retry:
   return TRUE;
 }
 
+static struct option long_options[] = {
+  {"32",	no_argument,	   NULL, '4'},
+  {"64",	no_argument,	   NULL, '8'},
+  {"base",	required_argument, NULL, 'b'},
+  {"down",	no_argument,	   NULL, 'd'},
+  {"help",	no_argument,	   NULL, 'h'},
+  {"usage",	no_argument,	   NULL, 'h'},
+  {"info",	no_argument,	   NULL, 'i'},
+  {"offset",	required_argument, NULL, 'o'},
+  {"quiet",	no_argument,	   NULL, 'q'},
+  {"database",	no_argument,	   NULL, 's'},
+  {"filelist",	required_argument, NULL, 'T'},
+  {"usage",	no_argument,	   NULL, 'h'},
+  {"verbose",	no_argument,	   NULL, 'v'},
+  {"version",	no_argument,	   NULL, 'V'},
+  {NULL,	no_argument,	   NULL,  0 }
+};
+
+static const char *short_options = "48b:dhioq:sT:vV";
+
 void
 parse_args (int argc, char *argv[])
 {
-  const char *anOptions = "b:dio:T:vV";
-  int anOption = 0;
+  int opt = 0;
 
-  while ((anOption = getopt (argc, argv, anOptions)) != -1)
+  while ((opt = getopt_long (argc, argv, short_options, long_options, NULL))
+	 != -1)
     {
-      switch (anOption)
+      switch (opt)
 	{
+	case '4':
+	  machine = IMAGE_FILE_MACHINE_I386;
+	  db_file = IMG_INFO_FILE_I386;
+	  break;
+	case '8':
+	  machine = IMAGE_FILE_MACHINE_AMD64;
+	  db_file = IMG_INFO_FILE_AMD64;
+	  break;
 	case 'b':
 	  image_base = string_to_ulonglong (optarg);
+	  force_rebase_flag = TRUE;
 	  break;
 	case 'd':
 	  down_flag = TRUE;
@@ -333,6 +1049,15 @@ parse_args (int argc, char *argv[])
 	  break;
 	case 'o':
 	  offset = string_to_ulonglong (optarg);
+	  force_rebase_flag = TRUE;
+	  break;
+	case 'q':
+	  quiet = TRUE;
+	  break;
+	case 's':
+	  image_storage_flag = TRUE;
+	  /* FIXME: For now enforce top-down rebasing when using the database.*/
+	  down_flag = TRUE;
 	  break;
 	case 'T':
 	  file_list = optarg;
@@ -340,6 +1065,10 @@ parse_args (int argc, char *argv[])
 	case 'v':
 	  verbose = TRUE;
 	  break;
+	case 'h':
+	  help ();
+	  exit (1);
+	  break;
 	case 'V':
 	  version ();
 	  exit (1);
@@ -351,7 +1080,7 @@ parse_args (int argc, char *argv[])
 	}
     }
 
-  if ((image_base == 0 && !image_info_flag)
+  if ((image_base == 0 && !image_info_flag && !image_storage_flag)
       || (image_base && image_info_flag))
     {
       usage ();
@@ -373,9 +1102,56 @@ void
 usage ()
 {
   fprintf (stderr,
-	   "usage: rebase -b BaseAddress [-Vdv] [-o Offset] "
-	   "[-T FileList | -] Files...\n"
-	   "       rebase -i [-T FileList | -] Files...\n");
+"usage: %s [-b BaseAddress] [-o Offset] [-48dsvV] [-T FileList | -] Files...\n"
+"       %s -i [-48s] [-T FileList | -] Files...\n"
+"       %s --help or --usage for full help text\n",
+	   progname, progname, progname);
+}
+
+void
+help ()
+{
+  printf ("\
+Usage: %s [OPTIONS] [FILE]...\n\
+Rebase PE files, usually DLLs, to a specified address or address range.\n\
+\n\
+  -4, --32                Only rebase 32 bit DLLs."
+#ifndef __x86_64__
+                          "  This is the default."
+#endif
+"\n\
+  -8, --64                Only rebase 64 bit DLLs."
+#ifdef __x86_64__
+                          "  This is the default."
+#endif
+"\n\
+  -b, --base=BASEADDRESS  Specifies the base address at which to start rebasing.\n\
+  -s, --database          Utilize the rebase database to find unused memory\n\
+                          slots to rebase the files on the command line to.\n\
+                          (Implies -d).\n\
+                          If -b is given, too, the database gets recreated.\n\
+  -i, --info              Rather then rebasing, just print the current base\n\
+                          address and size of the files.  With -s, use the\n\
+                          database.  The files are ordered by base address.\n\
+                          A '*' at the end of the line is printed if a\n\
+                          collisions with an adjacent file is detected.\n\
+\n\
+  One of the options -b, -s or -i is mandatory.  If no rebase database exists\n\
+  yet, -b is required together with -s.\n\
+\n\
+  -d, --down              Treat the BaseAddress as upper ceiling and rebase\n\
+                          files top-down from there.  Without this option the\n\
+                          files are rebased from BaseAddress bottom-up.\n\
+                          With the -s option, this option is implicitly set.\n\
+  -o, --offset=OFFSET     Specify an additional offset between adjacent DLLs\n\
+                          when rebasing.  Default is no offset.\n\
+  -T, --filelist=FILE     Also rebase the files specified in FILE.  The format\n\
+                          of FILE is one DLL per line.\n\
+  -q, --quiet             Be quiet about non-critical issues.\n\
+  -v, --verbose           Print some debug output.\n\
+  -V, --version           Print version info and exit.\n\
+  -h, --help, --usage     This help.\n",
+	  progname);
 }
 
 BOOL
Index: rebaseall.in
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/rebaseall.in,v
retrieving revision 1.3
diff -u -p -r1.3 rebaseall.in
--- rebaseall.in	28 Jun 2011 19:43:19 -0000	1.3
+++ rebaseall.in	10 Jul 2011 14:58:58 -0000
@@ -13,7 +13,7 @@
 #
 # Written by Jason Tishler <jason@tishler.net>
 #
-# $Id: rebaseall.in,v 1.3 2011/06/28 19:43:19 corinna Exp $
+# $Id: rebaseall.in,v 1.2 2011/06/21 15:40:10 corinna Exp $
 #
 
 # Define constants
@@ -22,7 +22,7 @@ tp2=${tp1:-.}
 PATH=$(cd $tp2 && pwd):@bindir@:/bin
 
 ProgramName=${0##*/}
-ProgramOptions='b:o:s:T:v'
+ProgramOptions='48b:o:s:T:v'
 DefaultBaseAddress=0x70000000
 DefaultOffset=@DEFAULT_OFFSET_VALUE@
 DefaultVerbose=
@@ -32,31 +32,43 @@ DefaultSuffixes='dll|so'
 # Define functions
 usage()
 {
-    echo "usage: $ProgramName [-b BaseAddress] [-o Offset] [-s DllSuffix] [-T FileList | -] [-v]"
+    echo "usage: ${ProgramName} [-b BaseAddress] [-o Offset] [-s DllSuffix] [-T FileList | -] [-4|-8] [-v]"
     exit 1
 }
 
 cleanup()
 {
-    rm -f "$TmpFile"
-    exit $ExitCode
+    rm -f "${TmpFile}"
+    exit ${ExitCode}
 }
 
 # Set traps
 trap cleanup 1 2 15
 
 # Set defaults
-BaseAddress=$DefaultBaseAddress
-Offset=$DefaultOffset
-Verbose=$DefaultVerbose
-FileList=$DefaultFileList
-Suffixes=$DefaultSuffixes
+BaseAddress=""
+Offset="${DefaultOffset}"
+Verbose="${DefaultVerbose}"
+FileList="${DefaultFileList}"
+Suffixes="${DefaultSuffixes}"
+db_file_i386="@sysconfdir@/rebase.db.i386"
+db_file_x86_64="@sysconfdir@/rebase.db.x86_64"
+case `uname -m` in
+    i[3456]86)
+	db_file="${db_file_i386}";
+	Mach="-4"
+	;;
+    x86_64)
+	Mach="-8"
+	db_file="${db_file_x86_64}"
+	;;
+esac
 
 # Verify only ash or dash processes are running
 grep -E -q -i -v '/d?ash(.exe)?$' /proc/[0-9]*/exename
-if [ $? -eq 0 -a -z "$RebaseDebug" ]
+if [ $? -eq 0 -a -z "${RebaseDebug}" ]
 then
-    echo "$ProgramName: only ash or dash processes are allowed during rebasing"
+    echo "${ProgramName}: only ash or dash processes are allowed during rebasing"
     echo "    Exit all Cygwin processes and stop all Cygwin services."
     echo "    Execute ash (or dash) from Start/Run... or a cmd or command window."
     echo "    Execute '/bin/rebaseall' from ash (or dash)."
@@ -64,24 +76,43 @@ then
 fi
 
 # Parse command line arguments
-while getopts $ProgramOptions Option "$@"
+while getopts "${ProgramOptions}" Option "$@"
 do
-    case $Option in
+    case "${Option}" in
+    4)
+	db_file="${db_file_i386}";
+	Mach="-4"
+	;;
+    8)
+	Mach="-8"
+	db_file="${db_file_x86_64}"
+	;;
     b)
-	BaseAddress=$OPTARG;;
+	BaseAddress="${OPTARG}";;
     o)
-	Offset=$OPTARG;;
+	Offset="${OPTARG}";;
     s)
-	Suffixes="$Suffixes|$OPTARG";;
+	Suffixes="${Suffixes}|${OPTARG}";;
     T)
-	FileList="$OPTARG";;
+	FileList="${OPTARG}";;
     v)
-	Verbose=-v;;
+	Verbose="-v";;
     \?)
 	usage;;
     esac
 done
 
+# Check if rebase database already exists.
+database_exists="no"
+[ -f "${db_file}" ] && database_exists="yes"
+
+# If BaseAddress has not been specified, and the rebase database doesn't exist
+# yet, set BaseAddress to default.
+if [ -z "${BaseAddress}" -a "${database_exists}" != "yes" ]
+then
+  BaseAddress=$DefaultBaseAddress
+fi
+
 # Set temp directory
 TmpDir="${TMP:-${TEMP:-/tmp}}"
 
@@ -112,16 +143,20 @@ find /etc/setup -name '*.lst.gz' | xargs
     grep -E "\.($Suffixes)\$" |
     sed -e '/cygwin1\.dll$/d' -e '/cyglsa.*\.dll$/d' \
 	-e '/sys-root\/mingw/d' \
-	-e 's/^/\//' -e '/d?ash\.exe$/d' -e '/rebase\.exe$/d' >"$TmpFile"
+	-e 's/^/\//' -e '/d?ash\.exe$/d' -e '/rebase\.exe$/d' >"${TmpFile}"
 
 # Append user supplied file list, if any
-if [ -n "$FileList" ]
+if [ -n "${FileList}" ]
 then
-    cat "$FileList" >>"$TmpFile"
+    cat "${FileList}" >>"${TmpFile}"
 fi
 
-# Rebase files
-rebase $Verbose -d -b $BaseAddress -o $Offset -T "$TmpFile"
+if [ -z "${BaseAddress}" ]
+then
+  ./rebase "${Verbose}" -s "${Mach}" -T "${TmpFile}"
+else
+  ./rebase "${Verbose}" -s "${Mach}" -b "${BaseAddress}" -o "${Offset}" -T "${TmpFile}"
+fi
 ExitCode=$?
 
 # Clean up


-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]