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


Another ping.

Where are you, guys?  I'm getting concerned.


Corinna

On Jul 13 14:51, Corinna Vinschen wrote:
> Jason?  Chuck?
> 
> Ping?
> 
> On Jul 10 17:00, Corinna Vinschen wrote:
> > 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
> 
> -- 
> Corinna Vinschen                  Please, send mails regarding Cygwin to
> Cygwin Project Co-Leader          cygwin AT cygwin DOT com
> Red Hat

-- 
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]