Two Dimensional Global Variable during ARM Compilation | developer.brewmp.com Two Dimensional Global Variable during ARM Compilation | developer.brewmp.com

Developer

Two Dimensional Global Variable during ARM Compilation

Dear All,

I faced a problem to deal with two dimensinal global array while compiling in ARM. ARM shows ER_RO error.

Here is my structure
-------------------------

typedef struct _Tonmoy
{
char *name;
int i;
Tonmoy;

const Tonmoy tonmoy[4][2] =
{
{
{"Tonmoy",1},{"dfdsf",2}
},
{
{"Tonmoy",1},{"dfdsf",2}
},
{
{"Tonmoy",1},{"dfdsf",2}
},
{
{"Tonmoy",1},{"dfdsf",2}
}
;
// this global declaration causes the ER_R0 ARM compile error

But I found following things are ok:

// OK
const int foo[2][4]=
{
{1,2,3,4},
{1,2,3,4}
;

// OK
const int foo[][4]=
{
{1,2,3,4},
{1,2,3,4}
;

I don't know why in case of 'typedef structure' the error is happening?
Is there anybody to know how to solve it?

Thanks
Tonmoy

You can't have pointers to static data in a static data. Processor architecture limitation.
try changing your code like this.
#define MAX_NAME_LEN 16
typedef struct _Tonmoy
{
char name[MAX_NAME_LEN];
int i;
Tonmoy;
gives some memory overhead, but it works. Otherwise you'll have to create and initialize your global array at runtime.

You can't have pointers to static data in a static data. Processor architecture limitation.
try changing your code like this.
#define MAX_NAME_LEN 16
typedef struct _Tonmoy
{
char name[MAX_NAME_LEN];
int i;
Tonmoy;
gives some memory overhead, but it works. Otherwise you'll have to create and initialize your global array at runtime.

Elaborating on archi's reply: Basically the compiler can detect when you're accessing tonmoy, and do the relevant address fixups for relocatability. But it can't reasonably detect when you access tonmoy[5].name [1] , so can't fix that address up. There are two solutions to this problem:
a) Use PC-relative addressing, since relocation applies to the data segment just as much as it applies to the code segment. However, the ARM can only use PC-relative address within +/- 4K if we are concerning ourselves with single instructions. We can get PC-relative addressing over the full 32-bit range if we use a 2 word construct for every load from an absolute address - but that would bloat code somewhat! Arguably compilers could use this approach for compiling individual code modules, to limit the code bloat to small sections of code, but this would likely be very likely to lead to programmer error.
b) Insulate the program from the effects of relocation by using per-process memory maps. This requires the processor to support memory mapping, and the OS to make use of it. The ARM has only limited support for per process memory maps (yes, it is possible to make it work, though only for small numbers of processes), and BREW does not make use of it in way, having a completely flat memory model.
[1] Obviously it can. But it can't detect ptr->name, where ptr was previously stored as &tonmoy[4], about 5000 lines of code ago...

Elaborating on archi's reply: Basically the compiler can detect when you're accessing tonmoy, and do the relevant address fixups for relocatability. But it can't reasonably detect when you access tonmoy[5].name [1] , so can't fix that address up. There are two solutions to this problem:
a) Use PC-relative addressing, since relocation applies to the data segment just as much as it applies to the code segment. However, the ARM can only use PC-relative address within +/- 4K if we are concerning ourselves with single instructions. We can get PC-relative addressing over the full 32-bit range if we use a 2 word construct for every load from an absolute address - but that would bloat code somewhat! Arguably compilers could use this approach for compiling individual code modules, to limit the code bloat to small sections of code, but this would likely be very likely to lead to programmer error.
b) Insulate the program from the effects of relocation by using per-process memory maps. This requires the processor to support memory mapping, and the OS to make use of it. The ARM has only limited support for per process memory maps (yes, it is possible to make it work, though only for small numbers of processes), and BREW does not make use of it in way, having a completely flat memory model.
[1] Obviously it can. But it can't detect ptr->name, where ptr was previously stored as &tonmoy[4], about 5000 lines of code ago...

This belongs in GNU-ARM compiler as it applies equally to all versions of BREW - any chance of moving it?

This belongs in GNU-ARM compiler as it applies equally to all versions of BREW - any chance of moving it?

Thanks for reply.
Here is my another structure. What would be the solution of it?
--------------------------------------------------------------------------------
// In .h file
struct encoding;
typedef struct encoding ENCODING;
typedef int (*SCANNER)(const ENCODING *,const char *,const char *,
const char **);
struct encoding
{
SCANNER scanners;
;
typedef struct _normal_encoding_{
ENCODING enc;
char type;
normal_encoding;
// In .c file
int prologTok(const ENCODING *enc, const char *ptr, const char *end,const char **nextTokPtr)
{
return 0;

const normal_encoding latin1_encoding = {prologTok,'a'}; // not ok, got ER_RO error
But if I declare the above globals like 'static const' then it is ok. Like:
static const normal_encoding latin1_encoding = {prologTok,'a'}; // OK
But in this case, there is another problem. I can't access its members. Like:
if(latin1_encoding.type == 'A') // for this, ER_RO found
{
// do something

Please help........ I need the solution.......
Thanks
Tonmoy

Thanks for reply.
Here is my another structure. What would be the solution of it?
--------------------------------------------------------------------------------
// In .h file
struct encoding;
typedef struct encoding ENCODING;
typedef int (*SCANNER)(const ENCODING *,const char *,const char *,
const char **);
struct encoding
{
SCANNER scanners;
;
typedef struct _normal_encoding_{
ENCODING enc;
char type;
normal_encoding;
// In .c file
int prologTok(const ENCODING *enc, const char *ptr, const char *end,const char **nextTokPtr)
{
return 0;

const normal_encoding latin1_encoding = {prologTok,'a'}; // not ok, got ER_RO error
But if I declare the above globals like 'static const' then it is ok. Like:
static const normal_encoding latin1_encoding = {prologTok,'a'}; // OK
But in this case, there is another problem. I can't access its members. Like:
if(latin1_encoding.type == 'A') // for this, ER_RO found
{
// do something

Please help........ I need the solution.......
Thanks
Tonmoy

tonmoy80 wrote:Thanks for reply.
Here is my another structure. What would be the solution of it?
--------------------------------------------------------------------------------
// In .h file
struct encoding;
typedef struct encoding ENCODING;
typedef int (*SCANNER)(const ENCODING *,const char *,const char *,
const char **);
struct encoding
{
SCANNER scanners;
;
typedef struct _normal_encoding_{
ENCODING enc;
char type;
normal_encoding;
// In .c file
int prologTok(const ENCODING *enc, const char *ptr, const char *end,const char **nextTokPtr)
{
return 0;

const normal_encoding latin1_encoding = {prologTok,'a'}; // not ok, got ER_RO error
You're initialising a latin1_encoding.enc.scanners with prologTok, whose values isn't known until runtime, due to the relocation. And as I discussed in my previous post the compiler can't fix this for you.
Since you cannot initialise this variable, you'll need to do it via an assignment in a function instead, and call that function from a suitable point in your code.

tonmoy80 wrote:Thanks for reply.
Here is my another structure. What would be the solution of it?
--------------------------------------------------------------------------------
// In .h file
struct encoding;
typedef struct encoding ENCODING;
typedef int (*SCANNER)(const ENCODING *,const char *,const char *,
const char **);
struct encoding
{
SCANNER scanners;
;
typedef struct _normal_encoding_{
ENCODING enc;
char type;
normal_encoding;
// In .c file
int prologTok(const ENCODING *enc, const char *ptr, const char *end,const char **nextTokPtr)
{
return 0;

const normal_encoding latin1_encoding = {prologTok,'a'}; // not ok, got ER_RO error
You're initialising a latin1_encoding.enc.scanners with prologTok, whose values isn't known until runtime, due to the relocation. And as I discussed in my previous post the compiler can't fix this for you.
Since you cannot initialise this variable, you'll need to do it via an assignment in a function instead, and call that function from a suitable point in your code.

BenBlaukopf wrote:This belongs in GNU-ARM compiler as it applies equally to all versions of BREW - any chance of moving it?
Hm... I don't think so. Why would the fixup code that elf2mod inserts in GCC binaries not work for pointers in data? In fact, I'm pretty sure I've used this somewhere.

BenBlaukopf wrote:This belongs in GNU-ARM compiler as it applies equally to all versions of BREW - any chance of moving it?
Hm... I don't think so. Why would the fixup code that elf2mod inserts in GCC binaries not work for pointers in data? In fact, I'm pretty sure I've used this somewhere.

rabidcow wrote:Hm... I don't think so. Why would the fixup code that elf2mod inserts in GCC binaries not work for pointers in data? In fact, I'm pretty sure I've used this somewhere.
Why doesn't the thread belong here? This isn't just the GCC compiler, it's also the thread for the ARM compiler...
You're right thought. I've just tested it, and elf2mod does fix this all these cases quite happily for GCC binaries. I've just realised that instead of doing PC-relative addressing, it could construct code to do a relocation at run-time, so that it all happens at run-time. Having read the docs for Elf2Mod, that's exactly what it does. That'll teach me to argue from a theoretical viewpoint without testing things!
The ARM toolchain used in stock mode - i.e. with a makefile produced by BREW Addins for Visual Studio - has the problems I describe. But Elf2Mod works just as well with the ARM toolchain, so Tonmoy80 can just use that.

rabidcow wrote:Hm... I don't think so. Why would the fixup code that elf2mod inserts in GCC binaries not work for pointers in data? In fact, I'm pretty sure I've used this somewhere.
Why doesn't the thread belong here? This isn't just the GCC compiler, it's also the thread for the ARM compiler...
You're right thought. I've just tested it, and elf2mod does fix this all these cases quite happily for GCC binaries. I've just realised that instead of doing PC-relative addressing, it could construct code to do a relocation at run-time, so that it all happens at run-time. Having read the docs for Elf2Mod, that's exactly what it does. That'll teach me to argue from a theoretical viewpoint without testing things!
The ARM toolchain used in stock mode - i.e. with a makefile produced by BREW Addins for Visual Studio - has the problems I describe. But Elf2Mod works just as well with the ARM toolchain, so Tonmoy80 can just use that.

BenBlaukopf wrote:Why doesn't the thread belong here? This isn't just the GCC compiler, it's also the thread for the ARM compiler...
Yeah, I think I misunderstood what you were saying. :)

BenBlaukopf wrote:Why doesn't the thread belong here? This isn't just the GCC compiler, it's also the thread for the ARM compiler...
Yeah, I think I misunderstood what you were saying. :)