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


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


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