This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [1.7] rebaseall doesn't solve the problem


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/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]