Generating PIC object files from the LLVM API

I’m trying to add static code generation capabilities to my MCJIT compiler on LLVM 3.4. To that extent I have:

targetMachine = engineBuilder.selectTarget();

// …
targetMachine->addPassesToEmitFile(<…>);

At first glance this appears to work, but when linking the object file I get the warning:

ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in <…>. To fix this warning, don’t compile with -mdynamic-no-pic or link with -Wl,-no_pie

This novice developer thought that the solution would be:

engineBuilder.setRelocationModel(Reloc::PIC_);

However this has no diff in the resulting object file. Have I overlooked something simple? Is this feature not supported and I need to link with -Wl,-no_pie?

Thanks in advance!

v/r
Josh

TL;DR: engineBuilder.setRelocationModel(Reloc::PIC_) appears to have no effect when generating object file

This novice developer thought that the solution would be:

    engineBuilder.setRelocationModel(Reloc::PIC_);

Hmm. That's exactly what I'd expect too. I don't suppose you're
calling setRelocationModel after selectTarget or something odd like
that?

The only other wrinkle I see is that COFF targets (only Windows, I
believe) don't seem to support PIC yet (from a very cursory reading of
X86TargetMachine.cpp). You seem to be using ld so this is a long shot,
but are you trying to use a COFF triple?

Another possibility (which I assume you've checked) is that the
absolute relocations might not be coming from a bog-standard
addressing situation that -fPIC would fix. I'd take a quick look at
the exact section and function ld is telling you about to make sure
there's nothing odd going on there.

If neither of those apply, I'd start delving into a debugger: put a
break-point on X86TargetMachine's constructor and see where the value
for the Reloc::Model comes from (and whether it is actually PIC).

Cheers.

Tim.

Thanks for the quick response. I was able fix the problem by generating the target machine like llc does with:

TargetRegistry::lookupTarget(<…>)->createTargetMachine(<…>)

Working backwards from there, it became apparent that the cause of the issue was EngineBuilder’s default code model was CodeModel::JITDefault but what I needed for static code generation was CodeModel::Default.

Is there any documentation on CodeModel? I couldn’t find any in the usual places.

Cheers,
Josh

Thanks for the quick response. I was able fix the problem by generating the
target machine like llc does with:

    TargetRegistry::lookupTarget(<...>)->createTargetMachine(<...>)

Working backwards from there, it became apparent that the cause of the issue
was EngineBuilder's default code model was CodeModel::JITDefault but what I
needed for static code generation was CodeModel::Default.

Interesting. Glad you sorted it, anyway!

Is there any documentation on CodeModel? I couldn't find any in the usual
places.

Well, it maps to the GCC option "-mcmodel" with common values "tiny",
"small", "medium", "large" & "kernel". Unfortunately what each of
those means (and even whether it's a valid option) is completely
target specific.

The outline is that by specifying one you're promising the compiler
that all your code and statically allocated data will be within
certain bounds, size-wise (& location). With that promise in hand, it
can use more efficient code sequences. For example on x86_64 it can
reference global variables using something like ("small" model == all
code and static data are in low 2GB of memory):

    movl var(%rip), %eax

rather than ("large" model == code and static data can be anywhere in
64-bit address space):

   movabsq $var, %ebx
   movl (%rbx), %eax

Of course, just where the boundaries between these models should be
placed depends on what instructions your CPU has. And so CPU designers
specify just what each mode means on their target.

I *think* this affected you because LLVM defaults to "large" for JIT,
which doesn't have good support for PIC. For static codegen it
defaults to "small", which is where most C & C++ code is compiled so
obviously supports PIC rather well.

Cheers.

Tim.