This is the mail archive of the
cygwin-apps
mailing list for the Cygwin project.
Re: More fault tolerant rebase (was Re: libtcl8.5.dll collides with Cygwin DLL by default)
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