Tcl Source Code

View Ticket
Login
Ticket UUID: 2959713
Title: Link error with gcc 4.1
Type: Bug Version: obsolete: 8.6b1.1
Submitter: decosterjos Created on: 2010-02-26 16:25:06
Subsystem: 53. Configuration and Build Tools Assigned To: nijtmans
Priority: 7 High Severity:
Status: Closed Last Modified: 2010-03-01 20:13:46
Resolution: Fixed Closed By: nijtmans
    Closed on: 2010-02-28 09:14:09
Description:
Building Tcl from CVS head with gcc 4.1 results in the following link error:

/usr/bin/ld: tclTomMathInterface.o: relocation R_X86_64_PC32 against symbol `tclTomMathConstStubs' can not be used when making a shared object; recompile with -fPIC

Adding MODULE_SCOPE to tclStubInit.c as suggested by Kevin Kenny:

MODULE_SCOPE const TclTomMathStubs tclTomMathConstStubs = {
   ..

solves the issue..

Jos.
User Comments: dkf added on 2010-03-01 20:13:46:
Yeah. The MODULE_SCOPE should go on the declaration (which should be in a header, and may be repeated many times across the whole binary module) and the initialization on the definition (which should be in a .c file, and should only occur once within a binary module).

I think. I have trouble remembering which term is which (decl/defn). :-)

nijtmans added on 2010-03-01 19:14:30:
Thanks, Donal, I couldn't have said it better. But there is one more thing. I don't remember any more which platform, but I had problems in the long
long past with constructs like:
  MODULE_SCOPE <type > <name> = { ....
This should be changed to:
  MODULE_SCOPE <type > <name>;
  <type > <name> = { ....

So don't do a MODULE_SCOPE and an
initialization in the same line, split it in 2
lines! The reason is that MODULE_SCOPE
is by default defined as "extern", and it's
impossible to initialize an external
variable: It's extern, so the external module
should initialize it, isn't it?

dkf added on 2010-03-01 17:33:12:

allow_comments - 1

There are two issues. 1) Not all linkers treat symbols for structures the same as symbols for functions. 2) There's only two supported build methods in general: with stubs through the stub table pointer obtained during the call to Tcl_InitStubs (as implemented in the stub library) or without stubs through directly accessing the functions (when you link directly against the Tcl library).

Consequently, the tclStubs variable is to never be exported from the library, and I see that it has the correct linkage now; good. Similarly, tclStubsPtr is also to be MODULE_SCOPE (though the module scope in question is the client library, not Tcl); again, it looks like the linkage is correct.

Generally, for any symbol the linkage should be one of internal-to-function, 'static', 'MODULE_SCOPE' or 'EXTERN'. Non-function symbols should never be EXTERN because of weird linker issues (which are stupid, but not something we should try to fix; we don't want to be in the business of making full toolchains!) and hardly any function symbols should be EXTERN either. If we stick to these rules, then most of the pain goes away.

nijtmans added on 2010-03-01 16:24:36:
Any symbol is in fact just a pointer to the location where
the storage is. So, exporting a stub table or exporting a
pointer to it is - internally - exactly the same. It's just
syntactic suger. The important thing is to declare all
stub tables const, that really prevents others to mess
with it. Doing that though an extra pointer adds really
nothing, in my view.

dkf added on 2010-02-28 23:56:15:
But the stub table itself isn't really exported; pointers to it are. Exporting a stub table (and the indigestion it causes some linkers) is what was the trigger for this bug report in the first place.

nijtmans added on 2010-02-28 16:14:09:
Let me comment on this.

Of all the stub tables, there are two that
need to be exported, the rest can be
static. Previously, the way the export was
done was first make all tables static, and then
define pointers to it which are visible from the
outside.
Therefore, I extended genStubs.tcl, so it can
find out which stub table is the 'parent'. This one
is exported (yes, should be MODULE_SCOPE), the
other ones are static. It saves the use of the pointer.

So, the intention of the change in genStubs.tcl is
that only the table needed outside is exported, the
others are left static.

It would even be better to move the two
MODULE_SCOPE definitions to tclInt.h, that's
where the list of inter-module symbols really
should be.

hobbs added on 2010-02-28 03:03:23:
Sorry Kevin - I had the bug up before you reassigned it and didn't refresh before adding my comment.

kennykb added on 2010-02-27 22:59:01:
Assigning to nijtmans - Jeff, why'd you assign it back to me?

hobbs added on 2010-02-27 05:27:17:
Kevin's patch is correct, except the real question is why these aren't all static.  It would need one modification to remove the existing "MODULE_SCOPE" for tclStubs in tclStubInit.c:44.  Also, tclOOStubs needs the treatment.

Jan - can you please explain why these aren't all being left static?

kennykb added on 2010-02-27 00:17:32:

File Added - 364579: 2959713.patch

kennykb added on 2010-02-27 00:17:00:

File Deleted - 364575:

kennykb added on 2010-02-27 00:05:09:

File Added - 364575: 2959713.patch

kennykb added on 2010-02-27 00:04:05:
In gcc 4.1, it is not valid to initialise a data item with a pointer to an exported data item. (It is all right to use a pointer to an exported function or a pointer to a data item at module or static scope.) The problem can be worked around by using -Wl,-Bsymbolic on the link flags, but that approach should not be adopted without further thought: see http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects/ for some of the pitfalls. Alternatively, the scope of the Stubs tables can be restricted: the attached patch to tools/genStubs.tcl puls it back to MODULE_SCOPE.

Donal Fellows and I discussed the correct linkage for tclTomMathStubs and tclOOStubs, and we believe that both of those tables ought to be 'static' unless there's something that you need to do with them that we fail to comprehend. In any case, I don't understand what you're trying to do with the code that marks them 'static' if they have subinterfaces and 'extern' otherwise. In any case, 'extern' is wrong: all symbols exported from the shared library should be EXTERN, and all symbols internal to it should be MODULE_SCOPE.

The attached patch attempts to be conservative: it makes the sharing as wide as possible while still linking successfully. I'd also request that you add some commentary in genStubs.tcl giving the rest of us some indication what you're trying to do. The change to make the tables external rather than static seems somewhat gratuitous, and of course has been observed to break at least one build.

kennykb added on 2010-02-26 23:29:02:
I'm looking into this - it relates to nijtmans's commit to tools/genStubs.tcl on 2010-02-05.

Attachments: