Forums | developer.brewmp.com Forums | developer.brewmp.com

Developer

Forums

Forums:

Recently one of my games on my T720 crashed (BREW 1.1). I only made a couple of minor changes (one small graphics edition, a scoring change, and a change of the PREF version number to invalidate old high scores). I tried for two days doing many different things but never could figure out a reason why. Any ideas?

1. deleting the game, power cycling the game made no difference.
2. using a file for preferences instead of the ISHELL prefs made no difference
3. Changing the BID number made no difference.
4. reverting the code and art back made no difference.
5. getting a new sig file made no difference.
6. replacing the code with hello world demo made no difference!

All of these work fine on my VX6000.

The logger shows no output from the program.

I tried master clear (not master reset) on the phone out of desparation and it seems to have cleared the test enable bit. So my phone is on it's way back to Qualcomm today.

Can you describe in more detail exactly what is happening/when the app is crashing?

Can you describe in more detail exactly what is happening/when the app is crashing?

I can't tell when it crashes but it must be on the AEEApplet_New() because there is no DBGPRINTF from the logger and the game code looks like:
myapp_t * pApp = (myapp_t *)pi;
AEEApplet * pMe = &pApp->a;
switch (eCode)
{
case EVT_APP_START:
//initialize variables
...
MEMSET(pApp->pAllocFlags, 0, sizeof(char) * ID_MAX);
{
AECHAR szBuf[] = {'H','e','l','l','o',' ','W','o', 'r', 'l', 'd', '\0'}; //wide-character string
MYPRINTF(("****** Starting *****"));
pApp->pISoundPlayer = NULL;
IDISPLAY_ClearScreen(pMe->m_pIDisplay);
IDISPLAY_DrawText(pMe->m_pIDisplay, AEE_FONT_BOLD, szBuf, -1, 0, 0, 0, IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE);
DISPLAY_Update(pMe->m_pIDisplay);
return(TRUE);
...

I can't tell when it crashes but it must be on the AEEApplet_New() because there is no DBGPRINTF from the logger and the game code looks like:
myapp_t * pApp = (myapp_t *)pi;
AEEApplet * pMe = &pApp->a;
switch (eCode)
{
case EVT_APP_START:
//initialize variables
...
MEMSET(pApp->pAllocFlags, 0, sizeof(char) * ID_MAX);
{
AECHAR szBuf[] = {'H','e','l','l','o',' ','W','o', 'r', 'l', 'd', '\0'}; //wide-character string
MYPRINTF(("****** Starting *****"));
pApp->pISoundPlayer = NULL;
IDISPLAY_ClearScreen(pMe->m_pIDisplay);
IDISPLAY_DrawText(pMe->m_pIDisplay, AEE_FONT_BOLD, szBuf, -1, 0, 0, 0, IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE);
DISPLAY_Update(pMe->m_pIDisplay);
return(TRUE);
...

I was asking becasue I wanted to see if you are sure the appliation actually starts up. If not, maybe you signature has expired... did you check that?

I was asking becasue I wanted to see if you are sure the appliation actually starts up. If not, maybe you signature has expired... did you check that?

I thought of that even though it has been less than 90 days. I built a new one (see item 5 in my original posting) and it made no difference.
In any case I do not expect the phone to crash with an out of date .sign file. Maybe not run or get an error but not crash.

I thought of that even though it has been less than 90 days. I built a new one (see item 5 in my original posting) and it made no difference.
In any case I do not expect the phone to crash with an out of date .sign file. Maybe not run or get an error but not crash.

I had the following construct under C:
static AECHAR array = { ...};
As they warn us DO NOT USE GLOBAL STATICS! Evenn though this works fine on the emulator and the same binary runs under the LG VX6000, this construct fucks up the T720.
For what it is worth I am using the Gnu Compiler. I do not know if the ARM compiler would prevent this problem.

I had the following construct under C:
static AECHAR array = { ...};
As they warn us DO NOT USE GLOBAL STATICS! Evenn though this works fine on the emulator and the same binary runs under the LG VX6000, this construct fucks up the T720.
For what it is worth I am using the Gnu Compiler. I do not know if the ARM compiler would prevent this problem.

That's what linkers create MAP files for. ;)

That's what linkers create MAP files for. ;)

A static array has global scope and Brew does not allow variables in the global scope. If you want to use such an array globally you want to add the const keyword to indicate it is not variable but constant.
static AECHAR format[] = {'%','d','\0'};
will not work and reports an error as you have seen.
static const AECHAR format[] = {'%','d','\0'};
on the other hand does work because it is not an array of variables, but of constants.
Once again, Brew does not allow you to have variables in the global scope. It is a requirement of the OS, plain and simple and has to do with the fact that phones have limited resources and need to be able to swap memory pages in and out. If they contained variables that would not be as easy and efficient, as it is if the OS knows all the contents of the memory segment is definitely constant - it can just discard the contents and reload them from scratch if need be.
I was referring to the Map file because the Map file shows you exactly how your data is mapped in the file. If you have global variables you will see it there because they are indicated with an RW flag, rather than the RO that they should be. These terms stand for "read-write" and "read-only" of course. Since it is very easy to overlook adding the const keyword, and since the emulator is not showing it as an error, my first step after creating a MOD file is typically to look voer the Map file to make sure I do not have RW data segments in the global space.

A static array has global scope and Brew does not allow variables in the global scope. If you want to use such an array globally you want to add the const keyword to indicate it is not variable but constant.
static AECHAR format[] = {'%','d','\0'};
will not work and reports an error as you have seen.
static const AECHAR format[] = {'%','d','\0'};
on the other hand does work because it is not an array of variables, but of constants.
Once again, Brew does not allow you to have variables in the global scope. It is a requirement of the OS, plain and simple and has to do with the fact that phones have limited resources and need to be able to swap memory pages in and out. If they contained variables that would not be as easy and efficient, as it is if the OS knows all the contents of the memory segment is definitely constant - it can just discard the contents and reload them from scratch if need be.
I was referring to the Map file because the Map file shows you exactly how your data is mapped in the file. If you have global variables you will see it there because they are indicated with an RW flag, rather than the RO that they should be. These terms stand for "read-write" and "read-only" of course. Since it is very easy to overlook adding the const keyword, and since the emulator is not showing it as an error, my first step after creating a MOD file is typically to look voer the Map file to make sure I do not have RW data segments in the global space.

Actually, global variables do work if you build your app with GCC.

Actually, global variables do work if you build your app with GCC.

Just because you can create them doesn't mean they work. Visual Studio can create them as well, but they do not work properly on phones.
Brew is designed as to assume that there are no global variables. If you break with that convention you will eventually run into problems. Whether your compiler allows you to create them or not is irrelevant in that context. I can get ADS to also create gobal variables and keep them in a MOD file. I constantly do... by accident... but that is not the point.

Just because you can create them doesn't mean they work. Visual Studio can create them as well, but they do not work properly on phones.
Brew is designed as to assume that there are no global variables. If you break with that convention you will eventually run into problems. Whether your compiler allows you to create them or not is irrelevant in that context. I can get ADS to also create gobal variables and keep them in a MOD file. I constantly do... by accident... but that is not the point.

Quote:Originally posted by Dragon
Just because you can create them doesn't mean they work.
Quite true, but that's not what I claimed.
Quote:Brew is designed as to assume that there are no global variables.
ADS uses a base register to find global variables, but BREW doesn't do anything to preserve registers, so this base register will contain bogus data. GCC uses a table that contains absolute addresses of global data. The code finds this table by assuming it is at a particular offset from the program counter. Of course, since BREW apps are position independent, the addresses in this table must be changed when the app is loaded into memory. BREWelf2mod.exe inserts an ARM routine into your MOD that fixes the addresses in this table when the module is loaded by BREW.

Quote:Originally posted by Dragon
Just because you can create them doesn't mean they work.
Quite true, but that's not what I claimed.
Quote:Brew is designed as to assume that there are no global variables.
ADS uses a base register to find global variables, but BREW doesn't do anything to preserve registers, so this base register will contain bogus data. GCC uses a table that contains absolute addresses of global data. The code finds this table by assuming it is at a particular offset from the program counter. Of course, since BREW apps are position independent, the addresses in this table must be changed when the app is loaded into memory. BREWelf2mod.exe inserts an ARM routine into your MOD that fixes the addresses in this table when the module is loaded by BREW.

Very interesting. Never came across that. Then again, never had the need for it either. :)

Very interesting. Never came across that. Then again, never had the need for it either. :)

OK here is the scoop. I am using GCC and using BREW 1.1. I have a simple app that uses the following where "format" is never modified:
static AECHAR format[] = {'%','d','\0'};
On two of my four applications this will crash the T720 phone when it starts up. The app dies even before the first DBGPRINTF.
Changing this line to the following allows these programs to run again:
static const AECHAR format[] = {'%','d','\0'};
The link map shows the first case puts 6 bytes into .data and in the last case adds 6 bytes to the .rodata section. There is also some padding added to get word alignment.
Of course this is proof by example and this would not necessarily mean it would not fail on some other handset or version of BREW.
Just a minor point, but when BREW claims we should not use static variables, I assumed they meant we could use modify the static variable but that static data was OK.

OK here is the scoop. I am using GCC and using BREW 1.1. I have a simple app that uses the following where "format" is never modified:
static AECHAR format[] = {'%','d','\0'};
On two of my four applications this will crash the T720 phone when it starts up. The app dies even before the first DBGPRINTF.
Changing this line to the following allows these programs to run again:
static const AECHAR format[] = {'%','d','\0'};
The link map shows the first case puts 6 bytes into .data and in the last case adds 6 bytes to the .rodata section. There is also some padding added to get word alignment.
Of course this is proof by example and this would not necessarily mean it would not fail on some other handset or version of BREW.
Just a minor point, but when BREW claims we should not use static variables, I assumed they meant we could use modify the static variable but that static data was OK.

Quote:Originally posted by eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%65%6c%6f%67%67%40%67%65%6e%70%6c%61%79%2e%63%22%3e%65%6c%6f%67%67%40%67%65%6e%70%6c%61%79%2e%63%3c%2f%61%3e%27%29%3b'))
Just a minor point, but when BREW claims we should not use static variables, I assumed they meant we could use modify the static variable but that static data was OK.
That pertains to ARM's tools only. For ADS, non-const static variable do not work, even if you are not changing them. Static const variables are fine.
Anyway, that non-const static variable should work just fine with GCC. Just to be sure, when you say you are "using BREW 1.1", you mean that you are building against the 1.1 header files? And you are using the patched header files that come with BREWelf2mod?
Are you accessing the static variable in any way before the crash occurs?

Quote:Originally posted by eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%65%6c%6f%67%67%40%67%65%6e%70%6c%61%79%2e%63%22%3e%65%6c%6f%67%67%40%67%65%6e%70%6c%61%79%2e%63%3c%2f%61%3e%27%29%3b'))
Just a minor point, but when BREW claims we should not use static variables, I assumed they meant we could use modify the static variable but that static data was OK.
That pertains to ARM's tools only. For ADS, non-const static variable do not work, even if you are not changing them. Static const variables are fine.
Anyway, that non-const static variable should work just fine with GCC. Just to be sure, when you say you are "using BREW 1.1", you mean that you are building against the 1.1 header files? And you are using the patched header files that come with BREWelf2mod?
Are you accessing the static variable in any way before the crash occurs?

Yes I am using the BREW 1.1 header files.
The data is never accessed before the crash. It appears the phone is crashing even before the app is actually started. I would guess form the copy from Flash memory into RAM.
If I am using any gnu header files it is transparent to me. Is there something specific you want me to look for?

Yes I am using the BREW 1.1 header files.
The data is never accessed before the crash. It appears the phone is crashing even before the app is actually started. I would guess form the copy from Flash memory into RAM.
If I am using any gnu header files it is transparent to me. Is there something specific you want me to look for?

DBGPRINTF from Logger can be asynchronous (you could force it to be synchronous by using ###7, just to make sure). Is it possible that it reboots on DBGPRINTF()? It happened to me on Samsung A530 - everything was working great on VX6000, but when lauched on A530 it crashed. DBGPRITNF()'s argument was too long.
Just 2c...

DBGPRINTF from Logger can be asynchronous (you could force it to be synchronous by using ###7, just to make sure). Is it possible that it reboots on DBGPRINTF()? It happened to me on Samsung A530 - everything was working great on VX6000, but when lauched on A530 it crashed. DBGPRITNF()'s argument was too long.
Just 2c...