2

The following code compiles into an executable with no problems:

static const char *foo = "bar";

void main(void)
{
    __asm__ ("mov %0,%%rax"
             :
             : "i"(&foo)
             : "%rax");
}

But as a shared lib, I get an error:

static const char *foo = "bar";

void zot(void)
{
    __asm__ ("mov %0,%%rax"
             :
             : "i"(&foo)
             : "%rax");
}

Compilation result:

hacker@lab$ gcc -shared -o mini-lib mini-lib.c

/usr/bin/ld: /tmp/ccwume3d.o: relocation R_X86_64_32S against `.data' 
  can not be used when making a shared object; recompile with -fPIC
  /tmp/ccwume3d.o: error adding symbols: Bad value

Compiling with -fPIC makes no difference. How can I tweak this in such a way that the linker will relocate a reference to the address of foo? It needs to be an immediate integer operand in the asm.


Update: I ended up using a different instruction that takes a memory operand, since there is apparently no way to do this with immediate operands.

Byron Hawkins
  • 2,536
  • 2
  • 24
  • 34
  • Addresses of `static` variables are _not_ immediates, nor usable as such. You have to specify `m` constraints. The only technical way I can see how to use an actual compile-time-constant here is to state that explicitly, and then use a _linker mapfile_ to ensure `foo` ends up at that location. – FrankH. Jun 17 '14 at 13:59
  • Usual request for clarification: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – FrankH. Jun 17 '14 at 14:01
  • For how to "assign" a variable to a specific address, see http://stackoverflow.com/questions/682697/fixed-address-variable-in-c – FrankH. Jun 17 '14 at 14:05
  • http://stackoverflow.com/questions/10849308/x86-64-is-it-possible-to-in-line-substitute-plt-got-references (pardon the shameless plug but this might be related as well) – FrankH. Jun 17 '14 at 17:03

1 Answers1

1

Would be good if you could clarify what exactly you're trying to achieve.

There is no 64bit movq $imm64, %reg, so you'd have to use movabs instead.

But there's also the X and P operand modifiers which might help by ditching the PLT reference / PC-relative addresses; you could write:

static void *foo;

[ ... ]
void *out[2];

asm("lea %P2, %0\n\t"
    "movabs %X2, %1\n\t" : "=r"(out[0]), "=a"(out[1]) : "g"(foo));

So the question is, do you know (or want to explicitly specify) the exact address of foo ?

If so, this must be done via the linker (mapfiles or command line options to the linker, not the compiler).

Otherwise ... movabs, lea and/or the usage of P / X might do what you're looking for.

Community
  • 1
  • 1
FrankH.
  • 17,675
  • 3
  • 44
  • 63