bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gettext patches for cygwin #4: accessing fields of exported structs/


From: Bruno Haible
Subject: Re: gettext patches for cygwin #4: accessing fields of exported structs/arrays
Date: Thu, 24 Nov 2005 13:15:38 +0100
User-agent: KMail/1.5

Charles Wilson wrote:
> A-HA! THERE's the compile-time error you've been seeing and I haven't! 
> It's because I've been relying on auto-import, and you've been using 
> declspec!

Yes. And actually I don't exactly recall which experiments I did with
the MSVC6 compiler and which with a gcc two or three years ago. The
option of using MSVC6 forced me to use __declspec, since the MSVC linker
doesn't have auto-import.

> auto-import hides the compile-time gcc error AND causes both gcc and g++ 
> to generate broken apps in these circumstances.

And furthermore the GNU ld doc says:
   "Use of the 'auto-import' extension will cause the text section of the
    image file to be made writable. This does not conform to the
    PE-COFF format specification published by Microsoft."
Which means that executables and DLLs compiled with this option will
consume much more memory.

Either of these two facts is sufficient motivation for me to turn off
the auto-import.

============================================================================
# Add --disable-auto-import to the LDFLAGS if the linker supports it.
# GNU ld has an --enable-auto-import option, and it is the default on Cygwin
# since July 2005. But it two fatal drawbacks:
#   - It produces executables and shared libraries with relocations in the
#     .text segment, defeating the principles of virtual memory.
#   - For some constructs such as
#         extern int var;
#         int * const b = &var;
#     it creates an executable that will give an error at runtime, rather than
#     either a compile-time or link-time error or a working executable.
#     (This is with both gcc and g++.) Whereas this code, not relying on auto-
#     import:
#         extern __declspec (dllimport) int var;
#         int * const b = &var;
#     gives a compile-time error with gcc and works with g++.
AC_DEFUN([gl_WOE32_DLL],
[
  AC_REQUIRE([AC_CANONICAL_HOST])
  case "$host_os" in
    mingw* | cygwin*)
      AC_MSG_CHECKING([for auto-import of symbols])
      AC_CACHE_VAL([gl_cv_ld_autoimport], [
        gl_save_LDFLAGS="$LDFLAGS"
        LDFLAGS="$LDFLAGS -Wl,--disable-auto-import"
        AC_TRY_LINK([], [], [gl_cv_ld_autoimport=yes], [gl_cv_ld_autoimport=no])
        LDFLAGS="$gl_save_LDFLAGS"])
      AC_MSG_RESULT([$gl_cv_ld_autoimport])
      if test $gl_cv_ld_autoimport = yes; then
        LDFLAGS="$LDFLAGS -Wl,--disable-auto-import"
      fi
      ;;
  esac
])
============================================================================

As long as the auto-import feature has these two drawbacks, it's a nice
spam-stopper for the cygwin mailing lists, against all the newbie questions
on the topic, but I cannot recommend it to serious programmers.

I agree that the goal of --enable-auto-import is the right one (because
it's precisely the limitations of Microsoft's original linker that led
to all this trouble, and modern languages need more dynamic linkers too).
But as long as the linker doesn't give an error message when something will
not work, I don't consider the implementation of --enable-auto-import
finished.

> The ld documentation lists four ways around this problem:
> 
> (1) -enable-runtime-pseudo-reloc linker switch

As I understand, -enable-runtime-pseudo-reloc only fixes one particular
problem that --enable-auto-import had in the past. The other two problems
mentioned above are still present.

> (2) play games with volatility and constness; use explicit pointers, 
> etc.  This is truly ugly stuff.

Too intrusive.

> (4) use a functional interface instead of trying to access variables 
> directly.  This is what I did.

Too intrusive as well.

> (3) declspec(__dll[im|ex]port) the enclosing variable.  This is what you 
> did.

It remains the only workable and recommendable solution for the moment.

> Okay, it appears that the g++ workaround ONLY works if the imported 
> variable is declspec'ed.  It does NOT help if you're using auto-import.

Yes, I agree.

Now about the other topic, functional interfaces:

> > 1) The existing code is ANSI C. According to the principle "fix the
> >    broken code, not the correct code", it is the wrong place to
> >    modify po-lex.[h|c] because of problem that is in Woe32.
> 
> Ok, but my point was that (as of 0.14.5) you WERE 'fixing the correct 
> code' in po-lex for certain platforms, with regards to 
> po_gram_error[_at_line]:
> 
> #if (some compilers)
>     use 'valid ANSI C code' in a macro -- which had the effect of 
> inducing clients to directly accesss blah blah blah
> #else (other compilers)
>     use function calls (also 'valid ANSI C code').
> 
> That was *existing* code in 0.14.5, not something I added. ...
> I simply followed the precedent you set with the 
> po_gram_error accesses

That was about ISO C 99 code, not ANSI C. ISO C is only 6 years old. It's
acceptable to make workarounds for compilers that don't implement ISO C 99
features (such as __VA_ARGS__ or <stdint.h>). But it's not acceptable for
me to change source code for compilers that don't implement the 15-year old
ANSI C.

> However, declspec'ing the variable (option 3 from the ld docu) should 
> work too -- and obviously it does in your testing.  *I* prefer using the 
> auto-import features of gcc on cygwin and mingw (when they work); I find 
> the whole
> 
> #if woe32-related && !building_static
> #if building_dll
> #define SOMETHING declspec(__dllexport)
> #else
> #define SOMETHING declspec(__dllimport)
> #endif
> #else
> #define SOMETHING
> #endif
> 
> thing ugly

Yes. Especially the "building_dll" flag is evil, because it goes against the
goals of gnulib. In gnulib, we have source code files which can be part of
many different packages. The "building_dll" could therefore be a
"building_gettextlib" in one case, "building_coreutilslib" in another,
"building_greplib" in a third one etc.

Fortunately declspec(__dllexport) is actually optional, and the following
does it as well:

#if woe32-related && !building_static
#define SOMETHING declspec(__dllimport)
#else
#define SOMETHING
#endif

Bruno

PS: I hope someone will also fix the other problem with --auto-imports,
namely that it makes the text segment writable. IMO the way to fix it is
to actually change the instructions that contain the references, not just
the references themselves. Such as:

    extern int a; int foo () { return a * a; }            [in the .c file]
    -->
    movl a, %eax                                          [in the .obj file]
    -->
    movl __imp_a, %eax; movl (%eax), %eax                 [in the .exe file]

Of course the instructions become longer this way; you need to rely on the
"linker relaxation" that - fortunately - is already implemented in GNU ld.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]