This is the mail archive of the cygwin-apps 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: [patch/peflags] Allow to change PE header stack and heap sizes


On 8/9/2011 8:19 AM, Corinna Vinschen wrote:
> Hi Chuck,
> 
> here's the change to peflags which allows to change the stack size and
> other stuff.

Cool, thanks.

> Here's the patch.  Builds and works fine on Cygwin and x86_64-mingw64.

Needs one small tweak for MSYS, but works fine after that.  Sadly,
__builtin_offset was not added until gcc-4.0:

#if defined(__GNUC__) && (__GNUC__ >= 4)

> +sizeof_values_t sizeof_vals[5] = {
> +  { 0, "stack reserve size      ", "bytes", 0, FALSE,
> +    __builtin_offsetof (IMAGE_NT_HEADERS64, OptionalHeader.SizeOfStackReserve),
> +    __builtin_offsetof (IMAGE_NT_HEADERS32, OptionalHeader.SizeOfStackReserve),
> +  },
> +  { 0, "stack commit size       ", "bytes", 0, FALSE,
> +    __builtin_offsetof (IMAGE_NT_HEADERS64, OptionalHeader.SizeOfStackCommit),
> +    __builtin_offsetof (IMAGE_NT_HEADERS32, OptionalHeader.SizeOfStackCommit),
> +  },
> +  { 0, "Win32 heap reserve size ", "bytes", 0, FALSE,
> +    __builtin_offsetof (IMAGE_NT_HEADERS64, OptionalHeader.SizeOfHeapReserve),
> +    __builtin_offsetof (IMAGE_NT_HEADERS32, OptionalHeader.SizeOfHeapReserve),
> +  },
> +  { 0, "Win32 heap commit size  ", "bytes", 0, FALSE,
> +    __builtin_offsetof (IMAGE_NT_HEADERS64, OptionalHeader.SizeOfHeapCommit),
> +    __builtin_offsetof (IMAGE_NT_HEADERS32, OptionalHeader.SizeOfHeapCommit),
> +  },
> +  { 0, "initial Cygwin heap size", "MB", 0, TRUE,
> +    __builtin_offsetof (IMAGE_NT_HEADERS64, OptionalHeader.LoaderFlags),
> +    __builtin_offsetof (IMAGE_NT_HEADERS32, OptionalHeader.LoaderFlags),
> +  }
> +};

#else
... repeat above, using the offsetof () macro.  Can't #define
my_offsetof in terms of offsetof() or __builtin_offsetof() because that
requires double macro subst (*)
#endif

(*) Unless you do something like this:

#if defined(__GNUC__) && (__GNUC__ < 4)
# define my_offsetof(st, m) \
     ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
#else
# define my_offsetof(st, m) __builtin_offsetof(st, m)
#endif

...with proper care for safe type punning(?), etc etc...  I think it's
simpler just to duplicate the five struct member initializations.


>    new_coff_characteristics = old_coff_characteristics;
>    new_coff_characteristics |= coff_characteristics_set;
> @@ -349,20 +426,47 @@ do_mark (const char *pathname)
>    if (verbose
>        || !mark_any
>        || coff_characteristics_show
> -      || pe_characteristics_show)
> +      || pe_characteristics_show
> +      || handle_any_sizeof != DONT_HANDLE)

I'm a little confused by this logic (above and below). You basically have:
   if (a || !b || !c)
   {
      if (a || (!b && c))

where
a = verbose || coff_characteristics_show || pe_characteristics_show
b = mark_any
c = handle_any_sizeof == DONT_HANDLE

Is that right?

[time passes]

Oh, wait, I get it.  If the user only specified "display" stack/heap
data, then you don't want to gratuitously show the pe/coff flags.  And
vice versa: if the use only specified "display" pe/coff flags, you don't
want to gratuitously show stack/heap data.

But if she specified "display" (at least one pe/coff) and (at least one
stack/heap) -- then you want to display both types.

> +      if (verbose
> +	  || (!mark_any && handle_any_sizeof == DONT_HANDLE)
> +	  || coff_characteristics_show || pe_characteristics_show)
> +	{
> +	  display_flags ("coff", coff_symbolic_flags,
> +			 coff_characteristics_show ?:
> +			 verbose ? old_coff_characteristics : 0,
> +			 old_coff_characteristics,
> +			 new_coff_characteristics);
> +	  display_flags ("pe", pe_symbolic_flags,
> +			 pe_characteristics_show ?:
> +			 verbose ? old_pe_characteristics : 0,
> +			 old_pe_characteristics,
> +			 new_pe_characteristics);
> +	  puts ("");
> +	  printed_characteristic = TRUE;
> +	}
>



> +
> +static void
>  handle_pe_flag_option (const char *option_name,
>                         const char *option_arg,
>                         WORD   flag_value)
> @@ -537,6 +672,16 @@ parse_args (int argc, char *argv[])
>        c = getopt_long (argc, argv, short_options, long_options, &option_index);
>        if (c == -1)
>          break;
> +      /* Workaround the problem that option_index is not valid if the user
> +	 specified a short option. */
> +      if (option_index == 0 && c != 'd')

This threw me for a loop, for a minute. It depends on the fact that the
0th entry in long_options has short option value 'd'.  Maybe this would
be better (especially if we ever re-order long_options)?

> +      if (option_index == 0 && c != long_options[0].val)


> +	{
> +	  for (option_index = 1;
> +	       long_options[option_index].name;
> +	       ++option_index)
> +	    if (long_options[option_index].val == c)
> +	      break;
> +	}

>  
> +void
> +get_and_set_size (const pe_file *pep, sizeof_values_t *val)
> +{
> +  if (val->handle == DO_READ)
> +    {
> +      if (!pep->is_64bit)
> +	val->value = *pulong (pep->ntheader32, val->offset32);
> +      else if (val->is_ulong)
> +	val->value = *pulong (pep->ntheader64, val->offset64);
> +      else
> +	val->value = *pulonglong (pep->ntheader64, val->offset64);
> +    }
> +  else if (val->handle == DO_WRITE)
> +    {
> +      if (!pep->is_64bit)
> +	*pulong (pep->ntheader32, val->offset32) = val->value;

is there an issue here, with this assignment:

  *ULONG = (ULONGLONG) value; ?

> +      else if (val->is_ulong)
> +	*pulong (pep->ntheader64, val->offset64) = val->value;

ditto here?

I'm just wondering if, to avoid warnings, we need to explicitly cast the
RHS to ULONG.

DO_READ doesn't have the same issue, because we're assigning a smaller
type to a larger storage, in that case; it just gets sign-extended.

> +      else
> +	*pulonglong (pep->ntheader64, val->offset64) = val->value;
> +    }
> +}

--
Chuck


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