Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
Hi Charles, * Charles Wilson wrote on Thu, Nov 13, 2008 at 06:09:20AM CET: Ralf Wildenhues wrote: Well, --verbose is documented to be a reversal of --silent, and documented to be the default. The fact that opt_verbose is never set is a limitation. If fixed, that should better happen in a separate patch. Well, if --verbose is really the negation of --silent, then (unless the functionality is extended as you describe) the effect of --verbose should be to only unset opt_silent (which it does), and there should not exist any 'opt_verbose' variable. Yes, I agree there is some inconsistency currently. In this case, to avoid backwards compatibility issues, the new I want really talkative output, but not --debug option should be something other than '--verbose' -- because that already has a specific meaning: negate--silent. --chatty? (I know, it's idiomatic and that's bad. It's more a tongue-in-cheek suggestion anyway). Regardless, I think the current (2? 3?) usages of opt_verbose should be changed to !opt_silent. 20 uses of func_verbose, actually. A bit much to undo, methinks. OK, how about this. It is a slight backward incompatibility, but not a large one: - --verbose undoes --silent *and* enables verbose output (that one with func_verbose), - --no-silent *only* undoes --silent, It should still be bearable for the user, in the sense that if you use --verbose rather than --no-silent, it's not a big problem. And we don't have to think about what --verbose --verbose --silent causes, we can just make the last one win. If you agree, then let's proceed this way. I don't mind who writes the patch. B) func_win32_libid() gives some confusing errors to users when (a) using recursive make, and (b) MAKEFLAGS does not contain $OBJDUMP. Add a diagnostic error message, rather than allowing $SED to die a horrible death. [...] Actually, this may no longer be necessary given the _LT_DECL_OBJDUMP changes (I /said/ this was an old patch). Here's the thread: http://cygwin.com/ml/cygwin/2008-09/msg00552.html Ah, ok, thanks. When configuring with --disable-static, dlpreopen is very confused. First, libtool tries to extract the symbols -- using $NM and $global_symbols_pipe -- from the DLL. That works...poorly: [...] OK, I see that this is problematic. What I don't understand yet is: is there a way to extract only the interesting symbols from the DLL? I don't yet understand why we have to move to the import library. Because it's extremely tricky. You have to use objdump (not nm), and then search for the exported symbols which is non-trivial because you need a stateful parser -- maybe an awk program... Hmm, yes, agreed. Thanks for all your detailed explanations. I'm glad to not have had to analyze this myself. The ugliest part of my patch is the fallback code for deducing the dllname from an import library. But that's *pretty* compared to mucking with objdump output. OK. :-) Alternatively, libtool used to embed an impgen program which could be ressurected to generate the symbol lists we need (rather than a .def file, as it used to do). A better solution would be to push that functionality into dlltool (Hmm. I need to generate a symbol list or def file for a DLL. but 'dlltool --output-def=my.def my.dll' doesn't do what you expect). Even so, the core functionality of impgen would need some improvements (especially so as to indicate DATA items, which it doesn't do at present). http://loreley.ath.cx/cygwin/impgen/impgen.c But then, you're back to requiring a very recent binutils, or providing a fallback -- see objdump ugliness above. ACK. Once I understand that, I can better judge the rest of the patch. Well, one reason I sat on this for so long was the 'fallback' mechanism for deducing the dll name from the import library was just so...hideous. And it wasn't a fallback -- it was the only mechanism since I hadn't yet enhanced dlltool. Do you steer dlltool development, BTW? The only reason to allow it is because (hopefully) that ugly fallback code can get flagged with a warning, and maybe in a year or so get removed. Sounds like a good idea. Well, that, and it fixes a test that currently fails. Which one, and can you post output for failure as well as success with the patch, please? for example mentioning in the mail whether you considered cygwin or cegcc or so would be helpful for review). cygwin and mingw yes. I know nothing about cegcc. OK, that's what I figured. In summary, it'd be great if you could redo the patch(es) along the comments in the previous message (but read below first). Couple more nits inline: --- a/libltdl/config/ltmain.m4sh +++ b/libltdl/config/ltmain.m4sh @@ -1991,10 +1992,36 @@ extern \C\ { func_verbose extracting global C symbols from \`$dlprefile' func_basename $dlprefile name=$func_basename_result - $opt_dry_run || { - eval
Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
Ralf Wildenhues wrote: I'm actually not sure whether _GLOBAL__F[ID]_.* can appear on w32. Do you know? They should happen with C++ code using constructors and destructors IIRC. Yes they do occur, although not matching that regexp. For one, they will have two leading underscores before the G, as with all symbols compared to their linux counterparts (i.e. __USER_LABEL_PREFIX__ is _ on Cygwin/MinGW.) For another I would have expected the regexp to match [FID] not F[ID] as there seems to generally be only one character in that position, whose purpose is illuminated by this comment in gcc/tree.c: /* Generate a name for a special-purpose function function. The generated name may need to be unique across the whole link. TYPE is some string to identify the purpose of this function to the linker or collect2; it must start with an uppercase letter, one of: I - for constructors D - for destructors N - for C++ anonymous namespaces F - for DWARF unwind frame information. */ A testcase: $ echo struct foo { int x; foo() : x(42) {}; }; static foo bar; \ | g++ -x c++ -S - -o - -O2 .file .section.ctors,w .align 4 .long __GLOBAL__I__77970994_840EDDA1 .lcomm _bar,16 .text .align 2 .p2align 4,,15 .def__GLOBAL__I__77970994_840EDDA1; .scl3; .type 32; .endef __GLOBAL__I__77970994_840EDDA1: pushl %ebp movl$42, %eax movl%esp, %ebp popl%ebp movl%eax, _bar ret Also: $ c++filt __GLOBAL__I__foobar global constructors keyed to _foobar $ c++filt __GLOBAL__D__foobar global destructors keyed to _foobar $ c++filt __GLOBAL__FI__foobar __GLOBAL__FI__foobar This implies that 'FI' is not valid, or at least not recognised by the demangler as significant. Brian
Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
On Thu, 13 Nov 2008 22:09:07 +0100, Ralf Wildenhues said: OK, how about this. It is a slight backward incompatibility, but not a large one: - --verbose undoes --silent *and* enables verbose output (that one with func_verbose), - --no-silent *only* undoes --silent, It should still be bearable for the user, in the sense that if you use --verbose rather than --no-silent, it's not a big problem. And we don't have to think about what --verbose --verbose --silent causes, we can just make the last one win. If you agree, then let's proceed this way. I don't mind who writes the patch. That sounds good to me. The help output would need a little re-wording: # --quiet, --silentdon't print informational messages # -v, --verboseprint informational messages (default) # --no-silent ??? I'll let you do that. g B) func_win32_libid() gives some confusing errors to users when (a) using recursive make, and (b) MAKEFLAGS does not contain $OBJDUMP. Add a diagnostic error message, rather than allowing $SED to die a horrible death. [...] Actually, this may no longer be necessary given the _LT_DECL_OBJDUMP changes (I /said/ this was an old patch). Here's the thread: http://cygwin.com/ml/cygwin/2008-09/msg00552.html Ah, ok, thanks. I'll remove any of these bits from the revised patch(es). Well, one reason I sat on this for so long was the 'fallback' mechanism for deducing the dll name from the import library was just so...hideous. And it wasn't a fallback -- it was the only mechanism since I hadn't yet enhanced dlltool. Do you steer dlltool development, BTW? No. I've contributed a few patches over the years to dlltool and binutils, but that's it. The only reason to allow it is because (hopefully) that ugly fallback code can get flagged with a warning, and maybe in a year or so get removed. Sounds like a good idea. Of course, first I need to revise the dlltool patch and get it accepted; there have been some comments on the binutils list. Well, that, and it fixes a test that currently fails. Which one, and can you post output for failure as well as success with the patch, please? demo-exec after demo-shared, in the old test suite. I'll post the output(s) tonight or tomorrow. Hmm. I reviewed this whole function, and only when done I asked myself this, more radical question: we go great lengths here to find out a name. Iff we have a *.la file to go with the implib, can't we just *know* the name? I mean, we produced that thing, it has the expected name, no? That's what the *.la file was designed for: to not have to look into the binary files for information. Or is this purely for import libraries not created with libtool (and people who throw away *.la files)? The information (e.g. library to dlpreopen) is passed in $dlprefiles. But, if that filename is .la: func_mode_link(): ... dlfiles|dlprefiles) if test $preload = no; then # Add the symbol object into the linking commands. func_append compile_command @SYMFILE@ func_append finalize_command @SYMFILE@ preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. ... ...much later... *.la) # A libtool-controlled library. if test $prev = dlfiles; then # This library was specified with -dlopen. dlfiles=$dlfiles $arg prev= elif test $prev = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles=$dlprefiles $arg prev= else deplibs=$deplibs $arg fi continue ;; So far, so good. But then we eventually source the .la file, and end up here (this is, in fact, what's happening in the demo-shared case): # This library was specified with -dlpreopen. if test $pass = dlpreopen; then if test -z $libdir test $linkmode = prog; then func_fatal_error only libraries may -dlpreopen a convenience library: \`$lib' fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n $old_library; then newdlprefiles=$newdlprefiles $dir/$old_library # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z $libdir \ dlpreconveniencelibs=$dlpreconveniencelibs $dir/$old_library # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n $dlname; then newdlprefiles=$newdlprefiles $dir/$dlname else newdlprefiles=$newdlprefiles $dir/$linklib fi fi # $pass = dlpreopen We've stored the DLL name as just ONE of the entries in $newdlprefiles.
Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
* [EMAIL PROTECTED] wrote on Fri, Nov 14, 2008 at 12:28:36AM CET: The point is, we perhaps STARTED with the .la file, but the whole point of the dlpreopen $pass is to replace each .la file in $dlprefiles with the name of the object from which the symbols should be extracted, to build the symbol table. So, pick one: either the DLL, or the import library (there is no static lib, the failure mode in question occurs when --disable-static). If you pick DLL -- then it's real hard to get the symbols (objdump ugliness, plus figuring out which ones are DATA). If you pick implib -- then it's real hard to get the correct DLL name (but not nearly as hard as extracting the correct symbols from the dll). But the name of the .la file is no longer available. But that's a problem that can be solved. # turn $1 into a string suitable for a shell variable name func_tr_sh () { ... # typically forks, except maybe with bash ${var/subst/repl} } # when treating $dlprefile, save the corresponding .la file name: func_tr_sh $dlprefile eval libfile_$tr_sh_result=\$corresponding_dotla_file # later, when searching for the .la file, test libfile$tr_sh_result # for contents What do you think? Cheers, Ralf
Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
Ralf Wildenhues wrote: The point is, we perhaps STARTED with the .la file, but the whole point of the dlpreopen $pass is to replace each .la file in $dlprefiles with the name of the object from which the symbols should be extracted, to build the symbol table. So, pick one: either the DLL, or the import library (there is no static lib, the failure mode in question occurs when --disable-static). If you pick DLL -- then it's real hard to get the symbols (objdump ugliness, plus figuring out which ones are DATA). If you pick implib -- then it's real hard to get the correct DLL name (but not nearly as hard as extracting the correct symbols from the dll). But the name of the .la file is no longer available. But that's a problem that can be solved. # turn $1 into a string suitable for a shell variable name func_tr_sh () { ... # typically forks, except maybe with bash ${var/subst/repl} } # when treating $dlprefile, save the corresponding .la file name: func_tr_sh $dlprefile eval libfile_$tr_sh_result=\$corresponding_dotla_file # later, when searching for the .la file, test libfile$tr_sh_result # for contents What do you think? That would work. But it only gets rid of the grotty find the name of the DLL given the implib problem -- which is not a small thing, of course. But that presupposes that my change to the dlpreopen $pass, where on cygwin|mingw we replace the la file in the $dlprefiles list with the implib, stands. Did I convince you we needed this bit: - elif test -n $dlname; then - newdlprefiles=$newdlprefiles $dir/$dlname + # Except on mingw|cygwin, where we must use the import library, + # so lt_dlopen is handled in another way else - newdlprefiles=$newdlprefiles $dir/$linklib + case $host in + *cygwin* | *mingw* ) + newdlprefiles=$newdlprefiles $dir/$linklib +;; + * ) + if test -n $dlname; then + newdlprefiles=$newdlprefiles $dir/$dlname + else + newdlprefiles=$newdlprefiles $dir/$linklib + fi +;; + esac If so, then I guess the other code section would look like func_verbose extracting global C symbols from \`$dlprefile' func_basename $dlprefile name=$func_basename_result -$opt_dry_run || { - eval '$ECHO : $name $nlist' - eval $NM $dlprefile 2/dev/null | $global_symbol_pipe '$nlist' -} +case $host in + *cygwin | *mingw* ) +# if an import library, we need to obtain dlname +if func_win32_import_lib_p $dlprefile; then + func_tr_sh $dlprefile + eval curr_lafile=\$libfile_$tr_sh_result + $opt_dry_run || { +if test -n $curr_lafile func_lalib_p $curr_lafile; then + # geez. does this need to happen in a subshell, to + # avoid clobbering our current variable values? + source $curr_lafile + if test -n $dlname ; then +func_basename $dlname +dlbasename=$func_basename_result +eval '$ECHO : $dlbasename $nlist' + else +func_warning Could not compute DLL name from $name +eval '$ECHO : $name $nlist' + fi +else + func_warning Could not determing .la name from $name + eval '$ECHO : $name $nlist' +fi +eval $NM $dlprefile 2/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' '$nlist' + } +else # not an import lib + $opt_dry_run || { + eval '$ECHO : $name $nlist' + eval $NM $dlprefile 2/dev/null | $global_symbol_pipe '$nlist' + } +fi +;; + *) etc. Is that the idea? -- Chuck