[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: GOT error in gas
From: |
Mikulas Patocka |
Subject: |
Re: GOT error in gas |
Date: |
Fri, 16 Feb 2007 16:28:52 +0100 (CET) |
Hi
Hi Mikulas,
__asm__ (".global number; number = 0x12345678");
extern void number;
These two declarations are not compatible. The latter declares number as
a data symbol, but the former defines it is an absolute symbol.
I thought that .types do not care for linking,
Andreas is not talking about .types. He is talking about the sections to
which the symbol belongs. Writing "extern void number" declares "number" as
a symbol that will live in the .data section(1). The address of "number" is
not known until the linker has performed a final link (for static code) or
the loader has initialised the executable (for PIC code).
Writing "__asm__(".global number; number=0x12345678")" however declares
"number" as a symbol with an absolute *address*. The symbol does not have a
value, or rather its value is whatever happens to be in the memory location
0x12345678. This symbol does not live in a section, and its address does not
change during linking or loading.
I know --- but in the example I posted I am just taking its address (which
should be 0x12345678), I am not taking value of that variable (that should
segfault on access to 0x12345678). But taking address shouldn't segfault.
I looked at gas code --- fixing it to stop evaluating constant symbols for
@GOT expressions seems to be hard or impossible because expression
evaluation function doesn't know that there is "@GOT" following.
--- but there is another issue --- @GOT is completely ignored if
expression is constant.
Note that
movl address@hidden, %eax
shouldn't put 123 to eax but an offset in GOT where 123 is stored. Gas
should either write error or make symbol with absolute value 123 and
output relocation against it.
movl address@hidden, %eax
will correctly output internal symbol name ("L0\001") as relocation, so
movl address@hidden, %eax could do just the same trick, setting "L0\001" to
absolute value --- static or dynamic linker will handle it correctly.
Hence the two declarations are inconsistent and you get undefined behaviour.
How otherwise should external C variables be placed at absolute locations?
You could adapt the mechanism that you already have. You say that everything
works if the __asm__ statement is in a separate compilation unit, so just
split out all of your absolute C variables into one (or more) separate files
and have a header file containing "extern void..." declarations for them.
I see but gas should at least write error and not generate incorrect code.
Mikulas
Alternatively you could provide the addresses for these symbols via a linker
script, rather than trying to define them in C. For example:
% cat addr.t
number = ABSOLUTE (0x12345678);
% cat test.c
#include <stdio.h>
extern void number;
int main (void) { return printf ("%p\n", & number); }
% gcc test.c -Wl,addr.t -fPIC
% ./a.out
0x12345678
Cheers
Nick
(1) Or some similar section such as .common or .sdata.