This is the mail archive of the
cygwin-apps
mailing list for the Cygwin project.
[patch/rebase] rebase -i and more
- From: Corinna Vinschen <corinna-cygwin at cygwin dot com>
- To: cygwin-apps at cygwin dot com
- Date: Tue, 21 Jun 2011 14:25:40 +0200
- Subject: [patch/rebase] rebase -i and more
- Reply-to: cygwin-apps at cygwin dot com
Here's another patch to rebase:
- Call setlocale at the start of main to accommodate native character
conversion.
- Adds a -i option to allow to print base address and size of all
files given as arguments or via the -T option. The list is sorted by
base address.
- On Cygwin, check if a DLL has been rebased into the address space
taken by the Cygwin DLL. If so, rebase again.
Ok to apply?
Thanks,
Corinna
* rebase.c (image_info_flag): New flag.
(img_info_list, img_info_size, img_info_max_size): New global
variables used to print image info.
(main): Call setlocale. On Cygwin fetch base address and size of
Cygwin DLL. If image_info_flag is set, call collect_image_info
rather than rebase in loop and eventually call print_image_info.
(collect_image_info): New function.
(img_info_cmp): New function.
(print_image_info): New function.
(rebase): On Cygwin, if a DLL has been rebased into the address space
taken by the Cygwin DLL, move new_image_base and rebase again.
(parse_args): Handle -i option.
(usage): Add -i option to usage output.
(version): Fix copyright.
Index: rebase.c
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/rebase.c,v
retrieving revision 1.2
diff -u -p -r1.2 rebase.c
--- rebase.c 21 Jun 2011 09:39:53 -0000 1.2
+++ rebase.c 21 Jun 2011 12:19:31 -0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2002, 2003 Jason Tishler
+ * Copyright (c) 2001, 2002, 2003, 2004, 2008, 2011 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
@@ -22,9 +22,13 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
+#include <locale.h>
#include <getopt.h>
+#include <string.h>
#include "imagehelper.h"
+BOOL collect_image_info (const char *pathname);
+void print_image_info ();
BOOL rebase (const char *pathname, ULONG *new_image_base);
void parse_args (int argc, char *argv[]);
unsigned long string_to_ulong (const char *string);
@@ -37,21 +41,44 @@ void version ();
ULONG image_base = 0;
BOOL down_flag = FALSE;
+BOOL image_info_flag = FALSE;
ULONG offset = 0;
int args_index = 0;
int verbose = 0;
const char *file_list = 0;
const char *stdin_file_list = "-";
+typedef struct _img_info
+{
+ const char *name;
+ ULONG base;
+ ULONG size;
+} img_info_t;
+
+img_info_t *img_info_list = NULL;
+unsigned int img_info_size = 0;
+unsigned int img_info_max_size = 0;
+
+#ifdef __CYGWIN__
+ULONG cygwin_dll_image_base = 0;
+ULONG cygwin_dll_image_size = 0;
+#endif
+
int
main (int argc, char *argv[])
{
ULONG new_image_base = 0;
int i = 0;
+ setlocale (LC_ALL, "");
parse_args (argc, argv);
new_image_base = image_base;
+#ifdef __CYGWIN__
+ GetImageInfos ("/bin/cygwin1.dll", &cygwin_dll_image_base,
+ &cygwin_dll_image_size);
+#endif
+
/* Rebase file list, if specified. */
if (file_list)
{
@@ -63,7 +90,8 @@ main (int argc, char *argv[])
while (file_list_fgets (filename, MAX_PATH + 2, file))
{
- status = rebase (filename, &new_image_base);
+ status = image_info_flag ? collect_image_info (filename)
+ : rebase (filename, &new_image_base);
if (!status)
break;
}
@@ -77,15 +105,75 @@ main (int argc, char *argv[])
for (i = args_index; i < argc; i++)
{
const char *filename = argv[i];
- BOOL status = rebase (filename, &new_image_base);
+ BOOL status = image_info_flag ? collect_image_info (filename)
+ : rebase (filename, &new_image_base);
if (!status)
exit (2);
}
+ if (image_info_flag)
+ print_image_info ();
+
exit (0);
}
BOOL
+collect_image_info (const char *pathname)
+{
+ /* 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);
+ 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,
+ img_info_max_size
+ * sizeof (img_info_t));
+ if (!img_info_list)
+ {
+ fprintf (stderr, "Out of memory.\n");
+ exit (2);
+ }
+ }
+
+ if (GetImageInfos (pathname, &img_info_list[img_info_size].base,
+ &img_info_list[img_info_size].size))
+ img_info_list[img_info_size++].name = strdup (pathname);
+ return TRUE;
+}
+
+int
+img_info_cmp (const void *a, const void *b)
+{
+ ULONG abase = ((img_info_t *) a)->base;
+ ULONG 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;
+
+ 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%08lx size 0x%08lx\n",
+ img_info_list[i].name,
+ img_info_list[i].base,
+ img_info_list[i].size);
+}
+
+BOOL
rebase (const char *pathname, ULONG *new_image_base)
{
ULONG old_image_size, old_image_base, new_image_size, prev_new_image_base;
@@ -118,6 +206,10 @@ rebase (const char *pathname, ULONG *new
if (down_flag)
*new_image_base -= offset;
+#ifdef __CYGWIN__
+retry:
+#endif
+
/* Rebase the image. */
prev_new_image_base = *new_image_base;
status = ReBaseImage ((char*) pathname, /* CurrentImageName */
@@ -173,6 +265,17 @@ rebase (const char *pathname, ULONG *new
return FALSE;
}
+#ifdef __CYGWIN__
+ /* Avoid the case that a DLL is rebased into the address space taken
+ by the Cygwin DLL. */
+ if (*new_image_base >= cygwin_dll_image_base
+ && *new_image_base <= cygwin_dll_image_base + cygwin_dll_image_size)
+ {
+ *new_image_base = cygwin_dll_image_base - offset;
+ goto retry;
+ }
+#endif
+
/* Display rebase results, if verbose. */
if (verbose)
{
@@ -191,7 +294,7 @@ rebase (const char *pathname, ULONG *new
void
parse_args (int argc, char *argv[])
{
- const char *anOptions = "b:do:T:vV";
+ const char *anOptions = "b:dio:T:vV";
int anOption = 0;
while ((anOption = getopt (argc, argv, anOptions)) != -1)
@@ -204,6 +307,9 @@ parse_args (int argc, char *argv[])
case 'd':
down_flag = TRUE;
break;
+ case 'i':
+ image_info_flag = TRUE;
+ break;
case 'o':
offset = string_to_ulong (optarg);
break;
@@ -224,7 +330,8 @@ parse_args (int argc, char *argv[])
}
}
- if (image_base == 0)
+ if ((image_base == 0 && !image_info_flag)
+ || (image_base && image_info_flag))
{
usage ();
exit (1);
@@ -246,7 +353,8 @@ usage ()
{
fprintf (stderr,
"usage: rebase -b BaseAddress [-Vdv] [-o Offset] "
- "[-T FileList | -] Files...\n");
+ "[-T FileList | -] Files...\n"
+ " rebase -i [-T FileList | -] Files...\n");
}
BOOL
@@ -308,7 +416,7 @@ file_list_fopen (const char *file_list)
FILE *file = stdin;
if (strcmp(file_list, stdin_file_list) != 0)
{
- file = fopen (file_list, "r");
+ file = fopen (file_list, "rt");
if (!file)
fprintf (stderr, "cannot read %s\n", file_list);
}
@@ -342,6 +450,6 @@ version ()
{
fprintf (stderr, "rebase version %s (imagehelper version %s)\n",
VERSION, LIB_VERSION);
- fprintf (stderr, "Copyright (c) 2001, 2002, 2003, 2004, 2008 "
- "Ralf Habacker and Jason Tishler\n");
+ fprintf (stderr, "Copyright (c) 2001, 2002, 2003, 2004, 2008, 2011 "
+ "Ralf Habacker, Jason Tishler, et al.\n");
}
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat