EmbDev.net

Forum: ARM programming with GCC/GNU tools Function pointer calling: possible GCC bug? (yagarto)


von Denis R. (denisrn)


Rate this post
useful
not useful
Hi there,
this days I've been working on one project of mines involving an 
AT91SAM7-S micro-controller, I'm actually using the GCC compiler I've 
found in the yagarto toolpack, pre-compiled an just ready to use.
Invoking the compiler with --version I get the following output:

C:\Documents and Settings\Administrator>arm-elf-gcc --version
arm-elf-gcc (GCC) 4.4.2
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is 
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.


I've got some really weird and bad trouble with my project and on 
further investigation I discovered that I'm having some problem on 
function calling. To make it clear I wrote a sample program that 
reproduces the situation (and the problems) I've encountered in my 
application, here it is the simple program:
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <math.h>
4
#include "AT91SAM7S256.h"
5
6
struct BigDealStruct {
7
  unsigned int member0;
8
  unsigned char member1;
9
  long int member2;
10
};
11
12
static unsigned char (*function_ptr)(unsigned int, unsigned int, struct BigDealStruct);
13
unsigned char my_function(unsigned int, unsigned int, struct BigDealStruct);
14
15
void main()
16
{
17
  function_ptr = my_function;
18
19
  unsigned int my_reg1 = 58;
20
  unsigned int my_reg2 = 34;
21
  struct BigDealStruct my_struct;
22
23
  function_ptr(my_reg1, my_reg2, my_struct);
24
25
  while(1);
26
}
27
28
unsigned char my_function(unsigned int arg0, unsigned int arg1, struct BigDealStruct arg3)
29
{
30
  unsigned int dummy = arg0;
31
}

The following are the values with which the function is being called 
(the ones in the struct are random but who cares) and the values inside 
the function. These have been retrieved with gdb.

Calling values:
- my_reg1 = 58
- my_reg2 = 34
- my_struct.member0 = 2099276
- my_struct.member1 = 76
- my_struct.member2 = 58

Inside-function values:
- arg1 = 2099276
- arg2 = 58
- arg3.member0 = 58
- arg3.member1 = 76
- arg3.member2 = 2099276

It's all messed up! But why?

I discovered that for the problem to occur a quite big amount of data to 
be passed is needed, indeed removing one of the two unsigned int args 
fixes the problem. Is it possible that arm calling conventions used by 
GCC can't manage to pass a load of data like this or larger?

Can someone please try this out in its own platform and let me know if 
he's getting the same problem as me?

Any help or advice would be really appreciated!

von (prx) A. K. (prx)


Rate this post
useful
not useful
At first you should try to find out whether it's a problem with the code 
or just a problem with gdb's knowledge of argument placement. Do 
something like
1
unsigned int a1, a2;
2
struct BigDealStruct a3;
3
4
unsigned char my_function(unsigned int arg1, unsigned int arg2, struct BigDealStruct arg3)
5
{
6
    a1 = arg1;
7
    a2 = arg2;
8
    a3 = arg3;
9
    return 0;
10
}
and look at a1,a2,a3 instead.

Also you should be careful at what place within the funktion you look at 
the values, because the first instructions of the called funktion affect 
the argument placement and gdb might need a few instruction steps to be 
in sync with the machine.

von (prx) A. K. (prx)


Rate this post
useful
not useful
BTW: The code generated with 4.3.3 looks fine.

Regarding the calling convention: According to the generated code, the 
first 4 argument words are always passed in R0-R3, even when there are 2 
scalars and a 3-word struct, so the struct is split in 2 words passed in 
registers and 1 word passed on the stack. Therefore the code looks a bit 
weird and it takes a few insns to get the struct back together in one 
piece.

von Denis R. (denisrn)


Rate this post
useful
not useful
Hi A.K., thank you for your promptness!
Looks like you pointed it out. Following your advice I added some global 
vars and looked at them instead. Once the function exits the global 
values are OK (i.e. the same as the local ones in main).
Still I don't understand why gdb shows those weird values for the 
arguments (I'm actually looking at them for the entire scope of the 
function, all the way from entry to exit).

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.