On Mar  9 21:30, Corinna Vinschen wrote:
> On Mar  8 10:12, Corinna Vinschen wrote:
> > What rebase *should* do is to mark the DLLs as blocked, and keep them in
> > the list together with their current address and size, so it can arrange
> > the addresses of the other DLLs, taking the blocked address space into
> > account, just like it does with the Cygwin DLL.  And of course, the DLL
> > should not be removed from the database.
> > 
> > Is there anybody here who would like to tackle this?
> 
> After the roaring silence died down, I thought I should try myself.
> Here's my idea how to handfle that problem.  It's not even much code.
> 
> I would be really grateful if somebody (Chuck? Jason? Yaakov?) could have a 
> look if the idea is ok and maybe even test it.  With this code, the
> DLLs are tested if they allow writing at the time, and if not, are
> marked as not rebaseable.  If so, rebase will not try to move them,
> and they are kept in the database nevertheless.
> 
> 
> Corinna

I extended the patch a bit, so that it prints on the command line which
DLL couldn't be rebased for what reason.  See below.  Did anybody try
the patch except me?


Corinna


Index: rebase-db.h
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/rebase-db.h,v
retrieving revision 1.3
diff -u -p -r1.3 rebase-db.h
--- rebase-db.h 5 Aug 2011 14:21:11 -0000       1.3
+++ rebase-db.h 13 Mar 2012 13:03:17 -0000
@@ -63,8 +63,10 @@ typedef struct _img_info
   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.                          */
+    ULONG needs_rebasing : 1; /* Set to 0 in the database.  Used only        */
+                             /* while rebasing.                             */
+    ULONG cannot_rebase  : 1; /* Set to 0 in the database.  Used only        */
+                             /* while rebasing.                             */
   } flag;
 } img_info_t;
 
Index: rebase.c
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/rebase.c,v
retrieving revision 1.12
diff -u -p -r1.12 rebase.c
--- rebase.c    9 Aug 2011 09:32:47 -0000       1.12
+++ rebase.c    13 Mar 2012 13:03:17 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2002, 2003, 2004, 2008, 2011 Jason Tishler
+ * Copyright (c) 2001, 2002, 2003, 2004, 2008, 2011, 2012 Jason Tishler
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -232,6 +232,8 @@ main (int argc, char *argv[])
   else
     {
       /* Rebase with database support. */
+      BOOL header;
+
       merge_image_info ();
       status = TRUE;
       for (i = 0; i < img_info_size; ++i)
@@ -242,6 +244,29 @@ main (int argc, char *argv[])
            if (status)
              img_info_list[i].flag.needs_rebasing = 0;
          }
+      for (header = FALSE, i = 0; i < img_info_size; ++i)
+       if (img_info_list[i].flag.cannot_rebase)
+         {
+           if (!header)
+             {
+               fputs ("\nThe following DLLs couldn't be rebased "
+                      "because they were in use:\n", stderr);
+               header = TRUE;
+             }
+           fprintf (stderr, "  %s\n", img_info_list[i].name);
+           img_info_list[i].flag.cannot_rebase = 0;
+         }
+      for (header = FALSE, i = 0; i < img_info_size; ++i)
+       if (img_info_list[i].flag.needs_rebasing)
+         {
+           if (!header)
+             {
+               fputs ("\nThe following DLLs couldn't be rebased "
+                      "due to errors:\n", stderr);
+               header = TRUE;
+             }
+           fprintf (stderr, "  %s\n", img_info_list[i].name);
+         }
       if (save_image_info () < 0)
        return 2;
     }
@@ -269,8 +294,10 @@ save_image_info ()
   /* 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];
+    {
+      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)
@@ -509,6 +536,17 @@ load_image_info ()
   return ret;
 }
 
+static BOOL
+set_cannot_rebase (img_info_t *img)
+{
+  int fd = open (img->name, O_WRONLY);
+  if (fd < 0)
+    img->flag.cannot_rebase = 1;
+  else
+    close (fd);
+  return img->flag.cannot_rebase;
+}
+
 int
 merge_image_info ()
 {
@@ -541,6 +579,9 @@ merge_image_info ()
     {
       for (i = img_info_rebase_start; i < img_info_size; ++i)
        {
+         /* First test if we can open the DLL for writing.  If not, it's
+            probably blocked by another process. */
+         set_cannot_rebase (&img_info_list[i]);
          match = bsearch (&img_info_list[i], img_info_list,
                           img_info_rebase_start, sizeof (img_info_t),
                           img_info_name_cmp);
@@ -551,8 +592,10 @@ merge_image_info ()
                 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)
+             if (img_info_list[i].flag.cannot_rebase)
+               match->base = img_info_list[i].base;
+             else 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)
@@ -566,23 +609,24 @@ merge_image_info ()
              free (img_info_list[i].name);
              img_info_list[i--] = img_info_list[--img_info_size];
            }
-         else
+         else if (!img_info_list[i].flag.cannot_rebase)
            /* 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)
+  if (!img_info_rebase_start || force_rebase_flag)
     {
       /* No database yet or enforcing a new base address.  Set base of all
-        DLLs to 0. */
+        DLLs to 0, if possible. */
       for (i = 0; i < img_info_size; ++i)
-       img_info_list[i].base = 0;
+       {
+         /* Test DLLs already in database for writability. */
+         if (i < img_info_rebase_start)
+           set_cannot_rebase (&img_info_list[i]);
+         if (!img_info_list[i].flag.cannot_rebase)
+           img_info_list[i].base = 0;
+       }
+      img_info_rebase_start = 0;
     }
 
   /* Now sort the old part of the list by base address. */
@@ -596,8 +640,10 @@ merge_image_info ()
       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)
+      /* Files with the needs_rebasing or cannot_rebase flags set have been
+        checked already. */
+      if (img_info_list[i].flag.needs_rebasing
+         || img_info_list[i].flag.cannot_rebase)
        continue;
       /* Check if the files in the old list still exist.  Drop non-existant
         or unaccessible files. */
@@ -613,24 +659,34 @@ merge_image_info ()
          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)
+      if (set_cannot_rebase (&img_info_list[i]))
+       img_info_list[i].base = cur_base;
+      else
        {
-         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;
+         /* 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 previous DLL reach into the address space of this
+            DLL?  This happens if the previous DLL is not rebaseable. */
+         else if (i > 0 && cur_base < img_info_list[i - 1].base
+                                      + img_info_list[i + 1].slot_size)
+           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;
        }
-      /* 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;

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

Reply via email to