On Fri, Jan 20, 2023 at 2:56 AM Björn Schäpers <g...@hazardy.de> wrote:
>
> From: Björn Schäpers <bjo...@hazardy.de>
>
> This is actually needed so that libstdc++'s <stacktrace> implementation
> to be able to work on windows.
>
> Tested on x86_64-linux and i686-w64-mingw32.
>
> -- >8 --
>
>         * configure.ac: Add a check for windows.h.
>         * configure, config.h.in: Regenerate.
>         * fileline.c: Add windows_get_executable_path.
>         * fileline.c (fileline_initialiez): Add a pass using
>         windows_get_executable_path.
>
> +#ifdef HAVE_WINDOWS_H
> +
> +static char *
> +windows_get_executable_path (char *buf, backtrace_error_callback 
> error_callback,
> +                            void *data)
> +{
> +  if (GetModuleFileNameA (NULL, buf, MAX_PATH - 1) == 0)
> +    {
> +      error_callback (data,
> +                     "could not get the filename of the current executable",
> +                     (int) GetLastError ());
> +      return NULL;
> +    }
> +  return buf;
> +}

Thanks, but this seems incomplete.  The docs for GetModuleFileNameA
say that if the pathname is too long to fit into the buffer it returns
the size of the buffer and sets the error to
ERROR_INSUFFICIENT_BUFFER.  It seems to me that in that case we should
allocate a larger buffer and try again.  And, in general, it will be
simpler if we always allocate the buffer, as macho_get_executable_path
does.  Unfortunately it appears that Windows does not provide a way to
ask for the required length.  On Windows it seems that MAX_PATH is not
a true limit, as an extended length path may be up to 32767 bytes.

So probably something like (untested)

static char *
windows_get_executable_path (struct backtrace_state *state,
     backtrace_error_callback error_callback,
     void *data)
{
  uint32_t len;
  char *buf;

  len = MAX_PATH;
  while (1)
    {
      uint32_t got;

      name = (char *) backtrace_alloc (state, len, error_callback, data);
      if (name == NULL)
return NULL;
      got = GetModuleFileNameA (NULL, name, len);
      if (got < len - 1) /* -1 because NULB is not counted */
return name;
      backtrace_free (state, name, len, error_callback, data);
      if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
return NULL;
      len *= 2;
    }
}

Ian

Reply via email to