This is the mail archive of the
cygwin
mailing list for the Cygwin project.
Re: [1.7] rebaseall doesn't solve the problem
- From: Charles Wilson <cygwin at cwilson dot fastmail dot fm>
- To: cygwin at cygwin dot com
- Date: Wed, 04 Mar 2009 01:01:01 -0500
- Subject: Re: [1.7] rebaseall doesn't solve the problem
- References: <499F6682.1090204@cwilson.fastmail.fm> <20090224100616.GC6035@calimero.vinschen.de> <49A85971.6070300@cwilson.fastmail.fm> <20090228104337.GG19887@calimero.vinschen.de> <49A986B4.2080501@cwilson.fastmail.fm> <20090228201625.GA8503@calimero.vinschen.de> <49A9AA0C.9020904@cwilson.fastmail.fm> <20090301102035.GB10046@calimero.vinschen.de> <49AE18D8.3010009@cwilson.fastmail.fm>
Charles Wilson wrote:
> Corinna Vinschen wrote:
>
>> Can you tweak the tool so I can test that next week?
>
> Attached,
It helps when you actually attach the file.
--
Chuck
/*
* Copyright (c) 2009 Charles Wilson
* Based on rebase.c by Jason Tishler
* Significant contributions by Dave Korn
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* A copy of the GNU General Public License can be found at
* http://www.gnu.org/
*/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <windows.h>
typedef struct
{
const char *name;
int len;
int value;
} definfoflag;
#define C(name) { #name, sizeof(#name) - 1, name }
#define CF(name,flag) { #name, sizeof(#name) - 1, flag }
static const definfoflag dllchrctnames[] =
{
/* Accept a few handy abbreviations. */
CF(dynbase, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE),
CF(forceinteg, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY),
CF(nxcompat, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT),
CF(noisolation, IMAGE_DLLCHARACTERISTICS_NO_ISOLATION),
CF(noseh, IMAGE_DLLCHARACTERISTICS_NO_SEH),
CF(nobind, IMAGE_DLLCHARACTERISTICS_NO_BIND),
CF(wdmdriver, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER),
CF(tsaware, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE),
/* And the full names as defined in the PE specification. */
C(IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE),
C(IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY),
C(IMAGE_DLL_CHARACTERISTICS_NX_COMPAT),
C(IMAGE_DLLCHARACTERISTICS_NO_ISOLATION),
C(IMAGE_DLLCHARACTERISTICS_NO_SEH),
C(IMAGE_DLLCHARACTERISTICS_WDM_DRIVER),
C(IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE),
{ 0, 0, 0 },
};
static const definfoflag imgfilechrctnames[] =
{
/* Accept a few handy abbreviations. */
CF(wstrim, IMAGE_FILE_AGGRESIVE_WS_TRIM),
CF(bigaddr, IMAGE_FILE_LARGE_ADDRESS_AWARE),
CF(sepdbg, IMAGE_FILE_DEBUG_STRIPPED), /* debug info in separate .dbg file */
/* And the full names as defined in the PE specification. */
C(IMAGE_FILE_RELOCS_STRIPPED),
C(IMAGE_FILE_EXECUTABLE_IMAGE),
C(IMAGE_FILE_LINE_NUMS_STRIPPED),
C(IMAGE_FILE_LOCAL_SYMS_STRIPPED),
C(IMAGE_FILE_AGGRESIVE_WS_TRIM),
C(IMAGE_FILE_LARGE_ADDRESS_AWARE),
C(IMAGE_FILE_BYTES_REVERSED_LO),
C(IMAGE_FILE_32BIT_MACHINE),
C(IMAGE_FILE_DEBUG_STRIPPED),
C(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
C(IMAGE_FILE_NET_RUN_FROM_SWAP),
C(IMAGE_FILE_SYSTEM),
C(IMAGE_FILE_DLL),
C(IMAGE_FILE_UP_SYSTEM_ONLY),
C(IMAGE_FILE_BYTES_REVERSED_HI),
{ 0, 0, 0 },
};
typedef struct
{
void *ptr;
int size;
int value;
char *symbol;
int inited;
const definfoflag *flagnames;
} definfo;
#define D(var,symbol,def) {&var,sizeof(var), def, symbol, 0, 0}
#define DF(var,symbol,def,flags) {&var,sizeof(var), def, symbol, 0, flags}
#define DEFAULT_SHOW_DLL_CHARACTERISTICS IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE |\
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT |\
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
#define DEFAULT_SHOW_IMG_CHARACTERISTICS 0x0
static uint16_t ImgFileCharacteristicsSET;
static uint16_t ImgFileCharacteristicsCLR;
static uint16_t ImgFileCharacteristicsSHOW;
static uint16_t DllCharacteristicsSET;
static uint16_t DllCharacteristicsCLR;
static uint16_t DllCharacteristicsSHOW;
#define SHOWSTR "show__"
static definfo init[] =
{
DF(ImgFileCharacteristicsSET, "__img_file_characteristics_set__", 0x0, imgfilechrctnames),
DF(ImgFileCharacteristicsCLR, "__img_file_characteristics_clr__", 0x0, imgfilechrctnames),
DF(ImgFileCharacteristicsSHOW, "__img_file_characteristics_" SHOWSTR, DEFAULT_SHOW_IMG_CHARACTERISTICS, imgfilechrctnames),
DF(DllCharacteristicsSET, "__dll_characteristics_set__", 0x0, dllchrctnames),
DF(DllCharacteristicsCLR, "__dll_characteristics_clr__", 0x0, dllchrctnames),
DF(DllCharacteristicsSHOW, "__dll_characteristics_" SHOWSTR, DEFAULT_SHOW_DLL_CHARACTERISTICS, dllchrctnames),
{ NULL, 0, 0, NULL, 0, 0 }
};
#define OPTION_SET_IMAGE_FILE_CHARACTERISTICS 150
#define OPTION_CLR_IMAGE_FILE_CHARACTERISTICS OPTION_SET_IMAGE_FILE_CHARACTERISTICS+1
#define OPTION_SHOW_IMAGE_FILE_CHARACTERISTICS OPTION_CLR_IMAGE_FILE_CHARACTERISTICS+1
#define OPTION_SET_DLL_CHARACTERISTICS OPTION_SHOW_IMAGE_FILE_CHARACTERISTICS+1
#define OPTION_CLR_DLL_CHARACTERISTICS OPTION_SET_DLL_CHARACTERISTICS+1
#define OPTION_SHOW_DLL_CHARACTERISTICS OPTION_CLR_DLL_CHARACTERISTICS+1
#define OPTION_FLAG_HELP OPTION_SHOW_DLL_CHARACTERISTICS+1
static struct option long_options[] = {
{"dynbase", required_argument, NULL, 'd'},
{"tsaware", required_argument, NULL, 't'},
{"nxcompat", required_argument, NULL, 'n'},
{"filelist", required_argument, NULL, 'T'},
{"set-image-characteristics", required_argument, NULL, OPTION_SET_IMAGE_FILE_CHARACTERISTICS},
{"clr-image-characteristics", required_argument, NULL, OPTION_CLR_IMAGE_FILE_CHARACTERISTICS},
{"show-image-characteristics", required_argument, NULL, OPTION_SHOW_IMAGE_FILE_CHARACTERISTICS},
{"set-dll-characteristics", required_argument, NULL, OPTION_SET_DLL_CHARACTERISTICS},
{"clr-dll-characteristics", required_argument, NULL, OPTION_CLR_DLL_CHARACTERISTICS},
{"show-dll-characteristics", required_argument, NULL, OPTION_SHOW_DLL_CHARACTERISTICS},
{"flag-help", no_argument, NULL, OPTION_FLAG_HELP},
{"verbose", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{NULL, no_argument, NULL, 0}
};
static const definfoflag *find_pe_flag_name (const char *name, const definfoflag *flagnames);
static definfo *find_pe_name (const char *name);
static void set_pe_name (const char *name, long val);
static void set_pe_by_flagname (const char *name, const char *flagname);
static char is_flag_sep (char x);
static void set_pe_value_from_flags (const char *name);
static void short_usage (FILE *f);
static void help (FILE *f);
static void help_flags (FILE *f);
static void version (FILE *f);
int do_mark (const char *pathname);
int get_characteristics(const char *pathname,
uint16_t* pe_img_file_characteristics,
uint16_t* pe_dll_characteristics);
int set_pe_img_file_characteristics(const char *pathname,
uint16_t pe_img_file_characteristics);
int set_pe_dll_characteristics(const char *pathname,
uint16_t pe_dll_characteristics);
static int pe_get16 (int fd, off_t offset, uint16_t* value);
static int pe_get32 (int fd, off_t offset, uint32_t* value);
static int pe_set16 (int fd, off_t offset, uint16_t value);
static char *symbolic (long flags, const char *name);
static void append_and_decorate (char **str, int is_set, const char *name, int len);
static int strendswith (const char *str, const char *prefix);
static void *xmalloc (size_t num);
#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
void parse_args (int argc, char *argv[]);
int string_to_bool (const char *string, int *value);
int string_to_ulong (const char *string, unsigned long *value);
FILE *file_list_fopen (const char *file_list);
char *file_list_fgets (char *buf, int size, FILE *file);
int file_list_fclose (FILE *file);
int args_index = 0;
int verbose = 0;
const char *file_list = 0;
const char *stdin_file_list = "-";
int
main (int argc, char *argv[])
{
int i = 0;
parse_args (argc, argv);
/* Operate on files in file list, if specified. */
if (file_list)
{
int status = 0;
char filename[MAX_PATH + 2];
FILE *file = file_list_fopen (file_list);
if (!file)
exit (2);
while (file_list_fgets (filename, MAX_PATH + 2, file))
{
if ((status = do_mark (filename)) != 0)
break;
}
file_list_fclose (file);
if (status != 0)
exit (2);
}
/* Operate on files listed as command line arguments. */
for (i = args_index; i < argc; i++)
{
const char *filename = argv[i];
if (do_mark (filename) != 0)
exit (2);
}
exit (0);
}
int
do_mark (const char *pathname)
{
int mark_any = FALSE;
int has_relocs;
int is_executable;
int is_dll;
uint16_t old_img_characteristics;
uint16_t new_img_characteristics;
uint16_t old_dll_characteristics;
uint16_t new_dll_characteristics;
int i;
/* Skip if file does not exist */
if (access (pathname, F_OK) == -1)
{
fprintf (stderr, "%s: skipped because nonexistent\n", pathname);
return 0;
}
/* determine if we are actually to write anything. Skip
entries in init[] that are display oriented */
for (i = 0; init[i].ptr; i++)
if (!strendswith (init[i].symbol, SHOWSTR))
mark_any |= init[i].inited;
if (mark_any)
{
/* Skip if not writable. */
if (access (pathname, W_OK) == -1)
{
fprintf (stderr, "%s: skipped because not writable\n", pathname);
return 0;
}
}
if (get_characteristics (pathname,
&old_img_characteristics,
&old_dll_characteristics) != 0)
{
fprintf (stderr,
"%s: skipped because could not read file characteristics\n",
pathname);
return 0;
}
new_img_characteristics = old_img_characteristics;
new_img_characteristics |= ImgFileCharacteristicsSET;
new_img_characteristics &= ~ImgFileCharacteristicsCLR;
new_dll_characteristics = old_dll_characteristics;
new_dll_characteristics |= DllCharacteristicsSET;
new_dll_characteristics &= ~DllCharacteristicsCLR;
is_executable = ((new_img_characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) > 0);
is_dll = ((new_img_characteristics & IMAGE_FILE_DLL) > 0);
has_relocs = ((new_img_characteristics & IMAGE_FILE_RELOCS_STRIPPED) == 0);
/* validation and warnings about things that are
problematic, but that we are not explicitly
changing */
if (!has_relocs)
{
if (verbose
&& (new_dll_characteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE)
&& (old_dll_characteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE))
{
fprintf (stderr,
"Warning: file has no relocation info but has dynbase set (%s).\n",
pathname);
}
}
if (!is_executable || is_dll)
{
if (verbose
&& (new_dll_characteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
&& (old_dll_characteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE))
{
fprintf (stderr,
"Warning: file is non-executable but has tsaware set (%s).\n",
pathname);
}
}
if (mark_any)
{
/* validation and warnings about things we are changing */
if (!has_relocs)
{
if ( (new_dll_characteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE)
&& !(old_dll_characteristics & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE))
{
fprintf (stderr,
"Warning: setting dynbase on file with no relocation info (%s).\n",
pathname);
}
}
if (!is_executable || is_dll)
{
if ( (new_dll_characteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
&& !(old_dll_characteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE))
{
fprintf (stderr,
"Warning: setting tsaware on non-executable (%s).\n",
pathname);
}
}
/* setting */
if (new_img_characteristics != old_img_characteristics)
if (set_pe_img_file_characteristics (pathname,
new_img_characteristics) != 0)
{
fprintf (stderr,
"Error: could not update image file characteristics (%s)\n",
pathname);
return 1;
}
if (new_dll_characteristics != old_dll_characteristics)
if (set_pe_dll_characteristics (pathname,
new_dll_characteristics) != 0)
{
fprintf (stderr,
"Error: could not update dll characteristics (%s)\n",
pathname);
return 1;
}
}
/* Display image characteristics. */
if (verbose || !mark_any)
{
printf ("%s: ", pathname);
if (ImgFileCharacteristicsSHOW)
{
if (old_img_characteristics != new_img_characteristics)
{
char * oldImgSymbolic = symbolic(old_img_characteristics,"__img_file_characteristics_" SHOWSTR);
char * newImgSymbolic = symbolic(new_img_characteristics,"__img_file_characteristics_" SHOWSTR);
printf ("image-characteristics(0x%04x%s==>0x%04x%s) ",
old_img_characteristics,oldImgSymbolic,
new_img_characteristics,newImgSymbolic);
free (oldImgSymbolic);
free (newImgSymbolic);
}
else
{
char * oldImgSymbolic = symbolic(old_img_characteristics,"__img_file_characteristics_" SHOWSTR);
printf ("image-characteristics(0x%04x%s) ",
old_img_characteristics,oldImgSymbolic);
free (oldImgSymbolic);
}
}
else
{
if (old_img_characteristics != new_img_characteristics)
printf ("image-characteristics(0x%04x==>0x%04x) ",
old_img_characteristics,
new_img_characteristics);
else
printf ("image-characteristics(0x%04x) ",
old_img_characteristics);
}
if (DllCharacteristicsSHOW)
{
if (old_dll_characteristics != new_dll_characteristics)
{
char * oldDllSymbolic = symbolic(old_dll_characteristics,"__dll_characteristics_" SHOWSTR);
char * newDllSymbolic = symbolic(new_dll_characteristics,"__dll_characteristics_" SHOWSTR);
printf ("dll-characteristics(0x%04x%s==>0x%04x%s) ",
old_dll_characteristics,oldDllSymbolic,
new_dll_characteristics,newDllSymbolic);
free (oldDllSymbolic);
free (newDllSymbolic);
}
else
{
char * oldDllSymbolic = symbolic(old_dll_characteristics,"__dll_characteristics_" SHOWSTR);
printf ("dll-characteristics(0x%04x%s) ",
old_dll_characteristics,oldDllSymbolic);
free (oldDllSymbolic);
}
}
else
{
if (old_dll_characteristics != new_dll_characteristics)
printf ("dll-characteristics(0x%04x==>0x%04x) ",
old_dll_characteristics,
new_dll_characteristics);
else
printf ("dll-characteristics(0x%04x) ",
old_dll_characteristics);
}
}
return 0;
}
static char *
symbolic (long flags, const char *name)
{
int i;
long already_marked = 0;
definfo *someVar = find_pe_name (name);
char * rVal = NULL;
for (i = 0; someVar->flagnames[i].name; i++)
{
if (someVar->value & someVar->flagnames[i].value & ~already_marked)
{
append_and_decorate (&rVal,
(flags & someVar->flagnames[i].value),
someVar->flagnames[i].name,
someVar->flagnames[i].len);
already_marked |= someVar->flagnames[i].value;
}
}
if (rVal)
{
size_t len = strlen (rVal);
char *tmp = XMALLOC (char, len + 3);
*tmp = '[';
memcpy (tmp+1, rVal, len);
tmp[len+1] = ']';
tmp[len+2] = '\0';
free (rVal);
rVal = tmp;
}
return rVal;
}
static void
append_and_decorate (char **str, int is_set, const char *name, int len)
{
char *tmp;
int slen;
if (!*str)
{
*str = XMALLOC (char, len + 2);
(*str)[0] = (is_set ? '+' : '-');
memcpy ((*str)+1, name, len);
(*str)[len+1] = '\0';
return;
}
else
{
slen = strlen (*str);
tmp = XMALLOC (char, slen + 2 + len + 1);
memcpy (tmp, *str, slen);
free (*str);
*str = tmp;
tmp = *str + slen;
*tmp++ = ',';
*tmp++ = (is_set ? '+' : '-');
memcpy (tmp, name, len);
tmp[len] = '\0';
}
}
static void *
xmalloc (size_t num)
{
void *p = (void *) malloc (num);
if (!p)
{
fputs ("Memory exhausted", stderr);
exit (2);
}
return p;
}
static int
strendswith (const char *str, const char *prefix)
{
size_t slen = strlen (str);
size_t plen = strlen (prefix);
if (slen < plen)
return 0;
return (strncmp (str + (slen - plen), prefix, plen) == 0);
}
void
parse_args (int argc, char *argv[])
{
int c;
int bool_value;
while (1)
{
int option_index = 0;
c = getopt_long (argc, argv, "d:t:n:T:vhV", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 'h':
help (stdout);
exit (0);
break;
case 'V':
version (stdout);
exit (0);
break;
case OPTION_FLAG_HELP:
help_flags (stdout);
exit (0);
break;
case 'd':
if (string_to_bool (optarg, &bool_value) != 0)
{
fprintf (stderr, "Invalid argument for %s: %s\n",
long_options[option_index].name, optarg);
short_usage (stderr);
exit (1);
}
if (bool_value)
set_pe_by_flagname ("__dll_characteristics_set__", "dynbase");
else
set_pe_by_flagname ("__dll_characteristics_clr__", "dynbase");
break;
case 'n':
if (string_to_bool (optarg, &bool_value) != 0)
{
fprintf (stderr, "Invalid argument for %s: %s\n",
long_options[option_index].name, optarg);
short_usage (stderr);
exit (1);
}
if (bool_value)
set_pe_by_flagname ("__dll_characteristics_set__", "nxcompat");
else
set_pe_by_flagname ("__dll_characteristics_clr__", "nxcompat");
break;
case 't':
if (string_to_bool (optarg, &bool_value) != 0)
{
fprintf (stderr, "Invalid argument for %s: %s\n",
long_options[option_index].name, optarg);
short_usage (stderr);
exit (1);
}
if (bool_value)
set_pe_by_flagname ("__dll_characteristics_set__", "tsaware");
else
set_pe_by_flagname ("__dll_characteristics_clr__", "tsaware");
break;
case 'T':
file_list = optarg;
break;
case 'v':
verbose = TRUE;
break;
case OPTION_SET_IMAGE_FILE_CHARACTERISTICS:
set_pe_value_from_flags ("__img_file_characteristics_set__");
break;
case OPTION_CLR_IMAGE_FILE_CHARACTERISTICS:
set_pe_value_from_flags ("__img_file_characteristics_clr__");
break;
case OPTION_SHOW_IMAGE_FILE_CHARACTERISTICS:
set_pe_value_from_flags ("__img_file_characteristics_" SHOWSTR);
break;
case OPTION_SET_DLL_CHARACTERISTICS:
set_pe_value_from_flags ("__dll_characteristics_set__");
break;
case OPTION_CLR_DLL_CHARACTERISTICS:
set_pe_value_from_flags ("__dll_characteristics_clr__");
break;
case OPTION_SHOW_DLL_CHARACTERISTICS:
set_pe_value_from_flags ("__dll_characteristics_" SHOWSTR);
break;
case '?':
break;
default:
short_usage (stderr);
exit (1);
break;
}
}
args_index = optind;
/* now, iterate thru init[] and apply the accumulated
values to the global variables */
for (c = 0; init[c].ptr; c++)
{
long val = init[c].value;
if (init[c].size == sizeof (short))
*(short *) init[c].ptr = val;
else if (init[c].size == sizeof (int))
*(int *) init[c].ptr = val;
else if (init[c].size == sizeof (long))
*(long *) init[c].ptr = val;
else abort ();
}
}
int
string_to_bool (const char *string, int *value)
{
unsigned long number = 0;
if (!string || !*string)
return 1;
if (string_to_ulong (string, &number) != 0)
{
size_t len = strlen (string);
if ( (len == 4 && strcasecmp (string, "true") == 0)
||(len == 3 && strcasecmp (string, "yes") == 0)
||(len == 1 && strcasecmp (string, "t") == 0)
||(len == 1 && strcasecmp (string, "y") == 0))
{
*value = TRUE;
}
else if ( (len == 5 && strcasecmp (string, "false") == 0)
||(len == 2 && strcasecmp (string, "no") == 0)
||(len == 1 && strcasecmp (string, "f") == 0)
||(len == 1 && strcasecmp (string, "n") == 0))
{
*value = FALSE;
}
else
{
return 1;
}
}
else
{
*value = (number != 0);
}
return 0;
}
int
string_to_ulong (const char *string, unsigned long *value)
{
unsigned long number = 0;
char * endp;
errno = 0;
/* null or empty input */
if (!string || !*string)
return 1;
number = strtoul (string, &endp, 0);
/* out of range */
if (ERANGE == errno)
return 1;
/* no valid numeric input */
if (endp == string)
return 1;
/* non-numeric trailing characters */
if (*endp != '\0')
return 1;
*value = number;
return 0;
}
int
get_characteristics(const char *pathname,
uint16_t* pe_img_file_characteristics,
uint16_t* pe_dll_characteristics)
{
uint32_t pe_header_offset, opthdr_ofs;
int status = 1;
int fd, size;
uint32_t pe_sig;
fd = open (pathname, O_RDONLY|O_BINARY);
if (fd == -1)
goto done;
if (pe_get32 (fd, 0x3c, &pe_header_offset) != 0)
goto done;
opthdr_ofs = pe_header_offset + 4 + 20;
pe_sig = 0;
if (pe_get32 (fd, pe_header_offset, &pe_sig) != 0)
goto done;
if (pe_sig != IMAGE_NT_SIGNATURE)
goto done;
if (pe_get16 (fd, pe_header_offset + 4 + 18, pe_img_file_characteristics) != 0)
goto done;
if (pe_get16 (fd, opthdr_ofs + 70, pe_dll_characteristics) != 0)
goto done;
status = 0;
done:
close (fd);
return status;
}
int
set_pe_img_file_characteristics(const char *pathname,
uint16_t pe_img_file_characteristics)
{
uint32_t pe_header_offset;
int status = 1;
int fd, size;
/* no extra checking of file's contents below, because
get_characteristics already did that */
fd = open (pathname, O_RDWR|O_BINARY);
if (fd == -1)
goto done;
if (pe_get32 (fd, 0x3c, &pe_header_offset) != 0)
goto done;
if (pe_set16 (fd, pe_header_offset + 4 + 18, pe_img_file_characteristics) != 0)
{
fprintf (stderr,
"CATASTROPIC ERROR: attempt to write to file failed! %s could be corrupted; HALTING.\n",
pathname);
close (fd);
exit(2);
}
status = 0;
done:
close (fd);
return status;
}
int
set_pe_dll_characteristics(const char *pathname,
uint16_t pe_dll_characteristics)
{
uint32_t pe_header_offset, opthdr_ofs;
int status = 1;
int fd, size;
/* no extra checking of file's contents below, because
get_characteristics already did that */
fd = open (pathname, O_RDWR|O_BINARY);
if (fd == -1)
goto done;
if (pe_get32 (fd, 0x3c, &pe_header_offset) != 0)
goto done;
opthdr_ofs = pe_header_offset + 4 + 20;
if (pe_set16 (fd, opthdr_ofs + 70, pe_dll_characteristics) != 0)
{
fprintf (stderr,
"CATASTROPIC ERROR: attempt to write to file failed! %s could be corrupted; HALTING.\n",
pathname);
close (fd);
exit(2);
}
status = 0;
done:
close (fd);
return status;
}
static int
pe_get16 (int fd, off_t offset, uint16_t* value)
{
unsigned char b[2];
if (lseek (fd, offset, SEEK_SET) == -1)
return 1;
if (read (fd, b, 2) != 2)
return 1;
*value = b[0] + (b[1]<<8);
return 0;
}
static int
pe_get32 (int fd, off_t offset, uint32_t* value)
{
unsigned char b[4];
if (lseek (fd, offset, SEEK_SET) == -1)
return 1;
if (read (fd, b, 4) != 4)
return 1;
*value = b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
return 0;
}
static int
pe_set16 (int fd, off_t offset, uint16_t value)
{
unsigned char b[2];
b[0] = (unsigned char) (value & 0x00ff);
b[1] = (unsigned char) ((value>>8) & 0x00ff);
if (lseek (fd, offset, SEEK_SET) == -1)
return 1;
if (write (fd, b, 2) != 2)
return 1;
return 0;
}
FILE *
file_list_fopen (const char *file_list)
{
FILE *file = stdin;
if (strcmp(file_list, stdin_file_list) != 0)
{
file = fopen (file_list, "r");
if (!file)
fprintf (stderr, "cannot read %s\n", file_list);
}
return file;
}
char *
file_list_fgets (char *buf, int size, FILE *file)
{
char *status = fgets (buf, size, file);
if (status)
{
size_t length = strlen (buf);
if (buf[length - 1] == '\n')
buf[length - 1] = '\0';
}
return status;
}
int
file_list_fclose (FILE *file)
{
int status = 0;
if (strcmp(file_list, stdin_file_list) != 0)
status = fclose (file);
return status;
}
static const definfoflag *
find_pe_flag_name (const char *name, const definfoflag *flagnames)
{
int i;
/* Look for the name, return pointer to definfoflag if found. */
for (i = 0; flagnames[i].name; i++)
if (strncmp (name, flagnames[i].name, flagnames[i].len) == 0)
return &flagnames[i];
/* Unknown name could be an integer, so not an error here. */
return 0;
}
static definfo *
find_pe_name (const char *name)
{
int i;
/* Look for the name, return pointer to definfo. */
for (i = 0; init[i].ptr; i++)
if (strcmp (name, init[i].symbol) == 0)
return &init[i];
/* Unknown name is a serious internal coding error, so don't
bother to diagnose or return error indication, just bail. */
abort ();
}
static void
set_pe_by_flagname (const char *name,
const char *flagname)
{
long flags = 0;
const definfoflag *flag;
definfo *someVar = find_pe_name (name);
flag = find_pe_flag_name (flagname, someVar->flagnames);
if (flag)
flags |= flag->value;
else
fprintf (stderr, "Error: unrecognised integer/flag '%s' for PE parameter '%s'\n",
optarg, name);
if (someVar->inited)
someVar->value |= flags;
else
{
someVar->value = flags;
someVar->inited = 1;
}
}
static void
set_pe_name (const char *name, long val)
{
/* Find the name and set it. */
definfo *someVar = find_pe_name (name);
someVar->value = val;
someVar->inited = 1;
}
static char
is_flag_sep (char x)
{
return x == '+' || x == '|' || x == ':' || x == ',';
}
static void
set_pe_value_from_flags (const char *name)
{
long flags = 0;
definfo *someVar;
/* Look up the symbolic flag names. Even if there aren't any we
will still parse multiple integers combined by separators. */
someVar = find_pe_name (name);
/* Parse the flags out of optarg. We accept any combination of
symbolic abbreviations and strtoul-parseable integers, separated
by any combination of '+', '|', ':' and ',' characters. */
while (*optarg)
{
const definfoflag *flag;
/* Deliberately allow multiple conjoined separators. */
while (is_flag_sep (*optarg))
optarg++;
/* Even trailing at the end. */
if (!*optarg)
break;
flag = find_pe_flag_name (optarg, someVar->flagnames);
if (flag)
{
flags |= flag->value;
optarg += flag->len;
}
else
{
char *end;
long value;
value = strtoul (optarg, &end, 0);
if (end == optarg)
fprintf (stderr, "Error: unrecognised integer/flag '%s' for PE parameter '%s'\n",
optarg, name);
flags |= value;
optarg = end;
}
/* If there's any more, we do insist on at least one separator. */
if (*optarg && !is_flag_sep (*optarg))
fprintf (stderr, "Error: unparseable at '%s' for PE parameter '%s'\n",
optarg, name);
}
set_pe_name (name, flags);
}
static void
short_usage (FILE *f)
{
fputs ("Usage: peflags [OPTIONS] file...\n", f);
fputs ("Sets or clears various flags in PE files (that is, exes and dlls)\n", f);
fputs ("Use --help for full help text\n", f);
}
static void
help (FILE *f)
{
fputs ("Usage: peflags [OPTIONS] file...\n", f);
fputs ("Sets or clears various flags in PE files (that is, exes and dlls)\n", f);
fputs (" -d, --dynbase=BOOL Sets or clears the dynbase flag\n", f);
fputs (" -t, --tsaware=BOOL Sets or clears the tsaware flag\n", f);
fputs (" -n, --nxcompat=BOOL Sets or clears the nxcompat flag\n", f);
fputs (" --set-image-characteristics=SPECSTR Set or clear various flags in the\n", f);
fputs (" --clr-image-characteristics=SPECSTR 'Characteristics' field of the PE\n", f);
fputs (" --show-image-characteristics=SPECSTR file's ImageFileHeader. See winnt.h\n", f);
fputs (" for possible values. The --show-*h\n", f);
fputs (" option indicates which flags to\n", f);
fputs (" display symbolically.n", f);
fputs (" --set-dll-characteristics=SPECSTR Set or clear various flags in the\n", f);
fputs (" --clr-dll-characteristics=SPECSTR 'DllCharacteristics' field of the\n", f);
fputs (" --show-dll-characteristics=SPECSTR PE file's ImageOptionalHeader. See\n", f);
fputs (" winnt.h for possible values; this\n", f);
fputs (" field is not only for DLLs\n", f);
fputs (" -T, --filelist FILE Indicate that FILE contains a list\n", f);
fputs (" of PE files to process\n", f);
fputs (" --verbose display diagnostic information\n", f);
fputs (" -V, --version display version information\n", f);
fputs (" -h, --help display this help\n", f);
fputs (" --flag-help display all symbolic flag names\n", f);
fputs ("\n", f);
fputs ("BOOL: may be 1, true, or yes - indicates that the flag should be set\n", f);
fputs (" if 0, false, or no - indicates that the flag should be cleared\n", f);
fputs ("\n", f);
fputs ("SPECSTR: <name>|<integer>[(+|,:)<name>|<integer>[...]]\n", f);
fputs (" where <name> is one of several known symbolic names (see --flag-help)\n", f);
fputs (" and any of +|;: may be used to join multiple values in a single option\n", f);
}
static void
help_flags (FILE *f)
{
int i;
fputs ("Flag help: peflags [OPTIONS] file...\n", f);
fputs ("The --set-* and --clr-* options accept as an argument a specification\n", f);
fputs ("string of the following form:\n", f);
fputs (" <name>|<integer>[(+|,:)<name>|<integer>[...]]\n", f);
fputs ("That is, flag values may be expressed using a combination of numeric\n", f);
fputs ("values and symbolic names. For example:\n", f);
fputs (" --set-dll-characteristics=0x0400|0x0100\n", f);
fputs (" --set-dll-characteristics=1+128+1024,noseh,nobind\n", f);
fputs (" --set-dll-characteristics=noseh:nobind:tsaware\n", f);
fputs ("There are a number of these symbolic names, which are listed below\n", f);
fputs (" --[set|clr|show]-dll-characteristics:\n", f);
/* Loop over symbolic names */
for (i = 0; dllchrctnames[i].name; i++)
fprintf (f, " %s\n", dllchrctnames[i].name);
fputs (" --[set|clr|show]-image-characteristics:\n", f);
/* Loop over symbolic names */
for (i = 0; imgfilechrctnames[i].name; i++)
fprintf (f, " %s\n", imgfilechrctnames[i].name);
}
static void
version (FILE *f)
{
fprintf (f, "peflags version %s\n", VERSION);
fprintf (f, "Copyright (c) 2009 Charles Wilson, Dave Korn, Jason Tishler\n");
}
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/