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