Thread overview
external relocation entries in non-writable section?
Jan 30, 2007
Rick Mann
Jan 30, 2007
Rick Mann
Re: external relocation entries in non-writable section? (SOLVED)
Jan 30, 2007
Rick Mann
January 30, 2007
/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

January 30, 2007
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...
January 30, 2007
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
January 30, 2007
Mostly solved. See below.

Anders F Björklund Wrote:

> Rick Mann wrote:
> > struct __CFString {};
> > typedef const __CFString*				CFStringRef;
> > 
> > extern (C)
> > CFStringRef
> > __CFStringMakeConstantString(char* cStr);
> > 
> 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").

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.
January 30, 2007
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