www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - external relocation entries in non-writable section?

reply Rick Mann <rmann-d-lang latencyzero.com> writes:
/usr/bin/ld: ../../target/lib/libdarbonapi.a(CFString.d.o) has external
relocation entries in non-writable section (__TEXT,__text) for symbols:
___CFStringMakeConstantString

I'm not sure what this error message means (does it have to do with packaging
it all in a static library? Don't see why...). In the library I've created, one
of my modules (CFString.d) has this:

struct __CFString {};
typedef const __CFString*				CFStringRef;

extern (C)
CFStringRef
__CFStringMakeConstantString(char* cStr);

Other symbols seem to link just fine. I'm not sure what's different about this
one.

TIA,
Rick
Jan 30 2007
next sibling parent Rick Mann <rmann-d-lang latencyzero.com> writes:
Rick Mann Wrote:

 I'm not sure what this error message means (does it have to do with packaging
it all in a static library? Don't see why...).

Well, I linked all the .d.o files in directly, and I still get the error, so I'm pretty sure it's not because I normally build it as a library. Maybe it's something about the external API...
Jan 30 2007
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Rick Mann wrote:

 /usr/bin/ld: ../../target/lib/libdarbonapi.a(CFString.d.o) has external
relocation entries in non-writable section (__TEXT,__text) for symbols:
 ___CFStringMakeConstantString
 
 I'm not sure what this error message means (does it have to do with packaging
it all in a static library? Don't see why...). In the library I've created, one
of my modules (CFString.d) has this:
 
 struct __CFString {};
 typedef const __CFString*				CFStringRef;
 
 extern (C)
 CFStringRef
 __CFStringMakeConstantString(char* cStr);
 
 Other symbols seem to link just fine. I'm not sure what's different about this
one.

Maybe it has something to do with that extra "const" ? What is that ? (looks to me like it is trying to use the keyword like it was in C++) Although when I tried it, it still worked OK even with the "const"... struct __CFString { } // opaque typedef const __CFString* CFStringRef; extern(C) CFStringRef __CFStringMakeConstantString(char *cStr); alias __CFStringMakeConstantString CFSTR; // only for string literals Then using it something like: err = CreateNibReference(CFSTR("main"), &nibRef); if (err != noErr) goto CantGetNibRef; So I'm not sure what else your code is doing differently than mine ? --anders
Jan 30 2007
parent reply Rick Mann <rmann-d-lang latencyzero.com> writes:
Mostly solved. See below.

Anders F Björklund Wrote:

 Rick Mann wrote:
 struct __CFString {};
 typedef const __CFString*				CFStringRef;
 
 extern (C)
 CFStringRef
 __CFStringMakeConstantString(char* cStr);
 

(looks to me like it is trying to use the keyword like it was in C++)

This is how the C header had it defined. In particular, CFStringRef is supposed to point to an immutable CFString, and (not defined here) CFMutableStringRef points to a mutable one (in the C header it drops the "const"). I'm not sure how const works in D, although I know that you can't specify function parameters as const. I assume the "in" qualifier does the same thing, but I'm not sure (I've been able to write code that modifies unqualified parameters inside the function). Ideally, I'd get a compile-time error if I passed a CFStringRef as a parameter that expected a CFMutableStringRef.
 Although when I tried it, it still worked OK even with the "const"...
 
 struct __CFString { } // opaque
 typedef const __CFString* CFStringRef;
 
 extern(C) CFStringRef __CFStringMakeConstantString(char *cStr);
 alias __CFStringMakeConstantString CFSTR; // only for string literals
 
 
 Then using it something like:
 
      err = CreateNibReference(CFSTR("main"), &nibRef);
      if (err != noErr) goto CantGetNibRef;
 
 So I'm not sure what else your code is doing differently than mine ?

I'm not either. I wrote a sample program defining everything in one file, and it worked fine. I also moved the defs to a separate file, and it still worked fine (with the "const" in there). I called CFShow() to output the value of the constructed CFStringRef, and it worked great. I can't figure out what's going on...hmm. I just went to reproduce the error, and now it seems to be working...? Ah! In the same file that defines __CFStringMakeConstantString, I define this (lexically before __CFStringMakeConstantString): CFStringRef CFSTR(char[] inString) { return __CFStringMakeConstantString(inString.ptr); } If I move it to after __CFStringMakeConstantString(), then it works okay.
Jan 30 2007
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Rick Mann wrote:

Maybe it has something to do with that extra "const" ? What is that ?
(looks to me like it is trying to use the keyword like it was in C++)

This is how the C header had it defined. In particular, CFStringRef is supposed to point to an immutable CFString, and (not defined here) CFMutableStringRef points to a mutable one (in the C header it drops the "const").

D doesn't have immutable references, it uses a Gentlemen's Agreement. "if I hand you this reference, you promise not clobber it before .dup" You can see this a lot with the D strings ("char[]"), for instance... It's currently an unsolved issue with D, how to handle read-only args.
 I'm not sure how const works in D, although I know that you can't specify
function parameters as const. I assume the "in" qualifier does the same thing,
but I'm not sure (I've been able to write code that modifies unqualified
parameters inside the function).

Basically it doesn't work as a modifier, only as a storage class... So when porting C/C++ to D, all the "const" get silently dropped. And the "in" qualifier is the default, so it doesn't add anything. (there are enormous amounts of discussions on this topic, in d.D)
 Ideally, I'd get a compile-time error if I passed a CFStringRef as a parameter
that expected a CFMutableStringRef.

The typedef should take care of that, I think ? ("typedef" vs "alias") What you don't get is protection from messing about with the innards.
So I'm not sure what else your code is doing differently than mine ?

I'm not either. I wrote a sample program defining everything in one file, and it worked fine. I also moved the defs to a separate file, and it still worked fine (with the "const" in there). I called CFShow() to output the value of the constructed CFStringRef, and it worked great. I can't figure out what's going on...hmm. I just went to reproduce the error, and now it seems to be working...? Ah! In the same file that defines __CFStringMakeConstantString, I define this (lexically before __CFStringMakeConstantString): CFStringRef CFSTR(char[] inString) { return __CFStringMakeConstantString(inString.ptr); } If I move it to after __CFStringMakeConstantString(), then it works okay.

Might be a GDC/Mac quirk. It does fail to create the $stub, if you declare it as an extern(C) *after* you first use it. The $stub is an assembly construct looking something like: (in PowerPC assembler, just ignore this part if confusing) .picsymbol_stub L___CFStringMakeConstantString$stub: .indirect_symbol ___CFStringMakeConstantString mflr r0 bcl 20,31,L0$___CFStringMakeConstantString L0$___CFStringMakeConstantString: mflr r11 addis r11,r11,ha16(L___CFStringMakeConstantString$lazy_ptr-L0$___CFStringMakeConstantString) mtlr r0 lwz r12,lo16(L___CFStringMakeConstantString$lazy_ptr-L0$___CFStringMakeConstantString)(r11) mtctr r12 addi r11,r11,lo16(L___CFStringMakeConstantString$lazy_ptr-L0$___CFStringMakeConstantString) bctr .data .lazy_symbol_pointer L___CFStringMakeConstantString$lazy_ptr: .indirect_symbol ___CFStringMakeConstantString .long dyld_stub_binding_helper Basically it looks up the external symbol indirectly, rather than just branching to the local symbol directly. i.e. extern(C) after: branch to ___CFStringMakeConstantString extern(C) before: branch to L___CFStringMakeConstantString$stub That is what your first variant did, which caused the "external relocation entry" - due to label not being known. Moral of the story: declare your extern(C) before using. :-) I'm not sure if it is supposed to work, declaring it afterwards. Might do a small test case and report to David for validation ? --anders
Jan 30 2007