public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Fedin Pavel <p.fedin@samsung.com>
To: 'Andrew Schulman' <schulman.andrew@epamail.epa.gov>, cygwin@cygwin.com
Subject: [PATCH] Fix optional variables in libargp
Date: Wed, 17 Jul 2013 09:57:00 -0000	[thread overview]
Message-ID: <002601ce82b7$63229580$2967c080$%fedin@samsung.com> (raw)
In-Reply-To: <tq50u89pa1s7us0cff5rnu8k5ocumac510@4ax.com>

[-- Attachment #1: Type: text/plain, Size: 1744 bytes --]

 Hello!

> Okay, well I agree that this sounds like a good solution.  For now you
> have a workaround, and I'll be glad to consider a patch if you submit
> one.

 Please take it. This is my experimental implementation which appears to be
simpler than i suggested.

 Some details: this implementation adds explicit dllexport attribute to
these 4 variables. This allows to look them up using GetProcAddress(). The
dllexport attribute has to be added explicitly because when compiling an
.exe file (without -shared switch) gcc does not mark externals as exportable
by default. When building a .dll, all external symbols are marked as
exportable by default, *UNLESS* we have at least one explicit dllexport
specification, hence i surrounded this with #ifndef DLL_EXPORT, this
definition is introduced by libtool when building a shared library.
 This implementation would not work in the following corner cases:
 a) .exe file uses some foo.dll library, which defines these variables and
uses libargp - symbols are picked up only from .exe file itself.
 b) Building that foo.dll manually without DLL_EXPORT definition can get
broken - the compiler will see dllexport attribute, and it will override the
default behavior to make all externs exportable.
 I believe these cases are quite unusual so it's OK. Getting rid of these
limitations would need more complex implementation with more changes.

 I have tested the implementation on x86-64 with RedHat's Prelink utility,
and it works quite fine. i386 should work too, but please retest, just in
case.

 Additionally, i added the second #ifdef _WIN32 in order to make the same
thing working also for MinGW target.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia

[-- Attachment #2: libargp-20110921-fix-optional-variables.diff --]
[-- Type: application/octet-stream, Size: 3788 bytes --]

diff -ru src/libargp-20110921.orig/gllib/argp.h src/libargp-20110921/gllib/argp.h
--- src/libargp-20110921.orig/gllib/argp.h	2011-09-23 03:31:26.000000000 +0500
+++ src/libargp-20110921/gllib/argp.h	2013-07-15 12:03:51.616647900 +0500
@@ -64,6 +64,18 @@
 typedef int error_t;
 # define __error_t_defined
 #endif
+
+#ifndef DLL_EXPORT
+#ifdef __CYGWIN__
+#define __dllexport __declspec(dllexport)
+#endif
+#ifdef _WIN32
+#define __dllexport __declspec(dllexport)
+#endif
+#endif
+#ifndef __dllexport
+#define __dllexport
+#endif
 \f
 #ifdef  __cplusplus
 extern "C" {
@@ -441,14 +453,14 @@
    option --version is added (unless the ARGP_NO_HELP flag is used), which
    will print this string followed by a newline and exit (unless the
    ARGP_NO_EXIT flag is used).  Overridden by ARGP_PROGRAM_VERSION_HOOK.  */
-extern const char *argp_program_version;
+__dllexport extern const char *argp_program_version;
 
 /* If defined or set by the user program to a non-zero value, then a default
    option --version is added (unless the ARGP_NO_HELP flag is used), which
    calls this function with a stream to print the version to and a pointer to
    the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
    used).  This variable takes precedent over ARGP_PROGRAM_VERSION.  */
-extern void (*argp_program_version_hook) (FILE *__restrict __stream,
+__dllexport extern void (*argp_program_version_hook) (FILE *__restrict __stream,
                                           struct argp_state *__restrict
                                           __state);
 
@@ -457,12 +469,12 @@
    argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
    standard help messages), embedded in a sentence that says something like
    `Report bugs to ADDR.'.  */
-extern const char *argp_program_bug_address;
+__dllexport extern const char *argp_program_bug_address;
 
 /* The exit status that argp will use when exiting due to a parsing error.
    If not defined or set by the user program, this defaults to EX_USAGE from
    <sysexits.h>.  */
-extern error_t argp_err_exit_status;
+__dllexport extern error_t argp_err_exit_status;
 \f
 /* Flags for argp_help.  */
 #define ARGP_HELP_USAGE         0x01 /* a Usage: message. */
diff -ru src/libargp-20110921.orig/gllib/argp-parse.c src/libargp-20110921/gllib/argp-parse.c
--- src/libargp-20110921.orig/gllib/argp-parse.c	2011-09-23 03:31:26.000000000 +0500
+++ src/libargp-20110921/gllib/argp-parse.c	2013-07-15 11:39:49.690236100 +0500
@@ -64,6 +64,42 @@
 /* EZ alias for ARGP_ERR_UNKNOWN.  */
 #define EBADKEY ARGP_ERR_UNKNOWN
 \f
+/* Windows does not support things like weak symbols, neither it will merge two
+   external symbols. In order to make our optional variables working, we have
+   to do this trick. What we do here is looking up respective variables in
+   main .exe file and patching our versions with correct pointers
+   Note that the whole thing relies on these variables being declared with
+   __declspec(dllexport). */
+#ifdef DLL_EXPORT
+
+#include <windows.h>
+
+#ifdef __i386__
+#define PREFIX "_"
+#else
+#define PREFIX
+#endif
+
+#define PatchPtr(var)					\
+  p = (void **)GetProcAddress(NULL, PREFIX #var );	\
+  if (p) var = *p;
+
+#define PatchInt(var)					\
+  i = (int *)GetProcAddress(NULL, PREFIX #var );	\
+  if (i) var = *i;
+
+static void __attribute__((constructor)) patch_vars(void)
+{
+  void **p;
+  int *i;
+
+  PatchPtr(argp_program_version);
+  PatchPtr(argp_program_version_hook);
+  PatchPtr(argp_program_bug_address);
+  PatchInt(argp_err_exit_status);
+}
+#endif
+
 /* Default options.  */
 
 /* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep


[-- Attachment #3: Type: text/plain, Size: 218 bytes --]

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

  reply	other threads:[~2013-07-17  6:32 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-11 10:17 libargp: argp_program_version does not work Fedin Pavel
2013-07-11 16:35 ` Andrew Schulman
2013-07-11 22:02   ` Andrew Schulman
2013-07-12 14:52     ` Fedin Pavel
2013-07-12 15:36       ` Andrew Schulman
2013-07-17  9:57         ` Fedin Pavel [this message]
2013-07-17 12:59           ` [PATCH] Fix optional variables in libargp Eric Blake
2013-07-22  7:33           ` Andrew Schulman
2013-07-22  8:12             ` Pavel Fedin
2013-07-22 13:19             ` Pavel Fedin
2013-07-23 15:07               ` Andrew Schulman
2013-07-24  9:56                 ` Pavel Fedin
2022-02-18 13:30               ` Andrew Schulman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='002601ce82b7$63229580$2967c080$%fedin@samsung.com' \
    --to=p.fedin@samsung.com \
    --cc=cygwin@cygwin.com \
    --cc=schulman.andrew@epamail.epa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).