[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Function Address fixup missing?

From: Mau
Subject: [avr-gcc-list] Function Address fixup missing?
Date: Fri, 26 Jun 2009 16:34:06 +0200
User-agent: Thunderbird (Windows/20090605)

Dear Sirs,
I have a problem that, after much thinking with the disassembly and
maps, I cannot explain other than a compiler or linker bug.

This problem appears on a big program.
I tried to make a smaller version exposing the problem, without success,
in the sense that any smaller version seems to work.
So I am sorry that I cannot place here the full program, but I will try
to give all needed information, hoping for some help.
If needed I can send other information or all the code if necessary.
Thank you in advance for any help or workaround.

I have a program for the AtMega2561 that is more that 128K and that make
use of function pointers. The compiler is WinAvr as of March 13, 2009.

As I understood when a function body is in the upper 128K, and the
address of this function is taken, the compiler (or linker) generates a
small stub in the "trampoline" area in lower memory that contains a jump
to the function body.
The "address of" operator then returns the address of this stub, rather
that the address of the function itself.
This way an indirect jump through the pointer (only 16 bits) ends up,
being the EIND register always zero, to the stub, which in turn makes a
full jump to the function.

If this is correct (and I have verified that this is the case with
smaller programs), the I don't understand the following results:

I have a function in upper 128K:
int ButtamiViaSubito(void) {
  return 3;

In the main (in lower memory) i take the address and then I call the

extern int ButtamiViaSubito(void);
typedef int (*PuntaAButtami)(void);
PuntaAButtami puntatore;

int main(void)
  puntatore = ButtamiViaSubito;    // (1)
  int butta = puntatore();         // (2)

In the disassembly of the full program (out of elf file) i find:

In the trampoline area:
00003e50 <__trampolines_start>:
    3e50:       0d 94 45 07     jmp     0x20e8a ; 0x20e8a <test+0x9e>
which looks correct: the function is at 20e8a.

instruction (1) is:
puntatore = ButtamiViaSubito;
    3efc:       80 e0           ldi     r24, 0x00       ; 0
    3efe:       90 e0           ldi     r25, 0x00       ; 0
    3f00:       90 93 82 0b     sts     0x0B82, r25
    3f04:       80 93 81 0b     sts     0x0B81, r24
which looks wrong. The first 2 ldi should load 3F28 which is the word
address of the trampoline. It looks that this fixup is not filled by the
linker leaving the value at zero.
The pointer is in RAM at B81.

The instruction (2) is also correct:
    int butta = puntatore();
    3ffe:       e0 91 81 0b     lds     r30, 0x0B81
    4002:       f0 91 82 0b     lds     r31, 0x0B82
    4006:       19 95           eicall

The same seems to happen also within the library around the fputc
function, which I assume is using function pointers.
Thanks again for any help.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]