Debugging 32X program memory issues from linker map file

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

Post Reply
ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Debugging 32X program memory issues from linker map file

Post by ammianus » Thu Dec 27, 2012 3:22 pm

It seems like I get one thing working and I run into my next frustrating issue.

I added a new global shared variable into my game. It's an array meant to store some graphics for display. This is exactly how I store some of the backgrounds and other images in my game. Basically I initialize the array in one file and load graphic data into it.

Long story short I get the "Black Screen of Death" in the emulators when I add this variable in.

If I remove it everything works. I narrowed it down to the size of the array:

Code: Select all

volatile unsigned char myring[844];
Everything works fine.

Code: Select all

volatile unsigned char myring[845];
Black screen of death.

So I gather I am hitting some kind of memory limitation in the 32X, but I can't make any sense of why?

I've been checking the starting address of this variable:
0600F904

The stack for the "master" is starting at 0603F00. According to the SP in R15 this grows down to 0603EF30

So by my calculations, I shouldn't have any conflict between my variables and the stack?

I have been looking at the map produced by the linker (using linker flag

Code: Select all

-Map=output.map
Where I can see my shared variable "myring" in the common symbols section.

Code: Select all

Allocating common symbols
Common symbol       size              file

foregroundObjects   0x30              shared_objects.o
ninja               0xa0              shared_objects.o
ME_menuFont         0x40              menu.o
ME_menuFill         0x40              menu.o
background_image    0xc800            shared_objects.o
level1              0x1008            shared_objects.o
myring              0x34c             shared_objects.o
etc...
Ok, so that is the expected size. Only difference with [845] the size is 0x34d.

If I look later in the map file I see the address for the common symbols at 0600f904. This stays the same with size of 844 (ok) or 845 (crash)

Code: Select all

 COMMON         0x000000000600202c    0x1a500 shared_objects.o
                0x000000000600202c                foregroundObjects
                0x000000000600205c                ninja
                0x00000000060020fc                background_image
                0x000000000600e8fc                level1
                0x000000000600f904                myring
                0x000000000600fc50                backgroundObjects
                0x000000000600fc80                dummy
                0x000000000600fd20                camera
                0x000000000600fd2c                background_image2
 COMMON         0x000000000601c52c        0x4 C:/bin/_gcc/gen/sh-elf/sh-elf/lib\libc.a(lib_a-syscalls.o)
                0x000000000601c52c                errno
                0x000000000601c530                _end = ALIGN (0x8)
                0x000000000601c530                __end = _end
                0x000000000601c530                end = _end
In the map file for the code with size 845, everything is in the same order, it's just pushed down by 4

Code: Select all

                0x000000000600fc54                backgroundObjects
                0x000000000600fc84                dummy
                0x000000000600fd24                camera
                0x000000000600fd30                background_image2
 COMMON         0x000000000601c530        0x4 C:/bin/_gcc/gen/sh-elf/sh-elf/lib\libc.a(lib_a-syscalls.o)
                0x000000000601c530                errno
                0x000000000601c538                _end = ALIGN (0x8)
                0x000000000601c538                __end = _end
                0x000000000601c538                end = _end
I am not aware of 0x000000000601c538 or beyond being any kind of special address in SH2's memory map, and this should be within the SDRAM space unless my math is off. It doesn't seem to conflict with the stack growing down from 0x0603F000 (FYI slave SP is 0x0603FFE0). So what else could be significant about this limit?

Is there anywhere else I should be investigating? Is there any error information I can get from 32X emulators themselves about what is causing the crash :?:

I reproduce the same error in all emulators consistently, Gens, Gens K-Mod, KFusion, etc..

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Dec 27, 2012 7:43 pm

Maybe an alignment issue... or maybe you have overlapping variables somewhere. It's probably one line that you keep overlooking - we read the code the way we WANTED to write it, not the way we ACTUALLY wrote it.

Try making the array MUCH bigger instead of one byte bigger. Try moving the array to someplace else.

If it's a shared resource, you should be accessing it uncached or flushing the cache... maybe the issue is there. 75% of my 32X issue are usually cache related. Making something volatile does NOT help with caching issues - you have to explicitly maintain cache coherence yourself.

EDIT: If you get the same problem in an emulator, it's probably not cache related since the emulators don't emulate the cache. It's probably bad pointers or overlapping variables or something like that.

EDIT 2: Oh, if you malloc memory in the program, you may be running out of memory. Changing the size of the array pushed the BSS up a little, and that reduces the amount of ram available to malloc.

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Thu Dec 27, 2012 10:19 pm

Chilly Willy wrote:Maybe an alignment issue... or maybe you have overlapping variables somewhere. It's probably one line that you keep overlooking - we read the code the way we WANTED to write it, not the way we ACTUALLY wrote it.

Try making the array MUCH bigger instead of one byte bigger. Try moving the array to someplace else.
Holy crap, you were right :D . What is frustrating, is that originally it was a larger size of 2048, and that didn't work.

I just tried now with 4096 and it works? What?

So compiler / linker might randomly create non-aligned things in memory? Might there be any way to control that with some flags for making C variables always aligned so we could hopefully rule out some of the mistakes I make enough for myself :)
If it's a shared resource, you should be accessing it uncached or flushing the cache... maybe the issue is there. 75% of my 32X issue are usually cache related. Making something volatile does NOT help with caching issues - you have to explicitly maintain cache coherence yourself.

EDIT: If you get the same problem in an emulator, it's probably not cache related since the emulators don't emulate the cache. It's probably bad pointers or overlapping variables or something like that.

EDIT 2: Oh, if you malloc memory in the program, you may be running out of memory. Changing the size of the array pushed the BSS up a little, and that reduces the amount of ram available to malloc.
I am using malloc. That might have something to do with it.

How would I tell it to reserve the appropriate space for .bss? Looking in the mars.ld linker file, is there anything else I need to add here:

Code: Select all

  .bss 0x06000000 + SIZEOF (.data) :
  {
    __bss_start = . ;
    *(.shbss)
    *(.bss .bss.*)
    *(COMMON)
    _end =  ALIGN (0x8);
    __end = _end;
    end = _end;
  } > ram

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Fri Dec 28, 2012 12:18 am

Look in the map file to see the BSS usage. Look at the end of the bss segment, then subtract from the stack - estimated stack usage: that will give you a rough idea of how much memory is left to be malloc'd. For example, if __bss_end is something like 0x06020000, and the stack is at 0x0603FF00 and you estimate 8KB of stack being used, you have about 0x0603DF00 - 0x06020000 or 0x1DF00 bytes available. Be very careful about local storage... look at this

Code: Select all

void func(void)
{
    int temp[1000];
...
You just used almost 4KB of stack there in one function! I've seen RECURSIVE functions that used almost 100KB per recursion on certain PC programs. That was back when I was working on the PSP - someone was complaining that their port of a program crashed at a certain point... and I pointed out the function in question which was easily eating 20 to 80 MB of ram. No big deal on a PC - VERY big deal on a PSP with maybe 20MB of free ram. Now remember that the 32X has 256KB of ram total! Depending on data and bss, you may have as little as 64KB to share between malloc and the stack. Or less!!

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sat Dec 29, 2012 4:20 pm

Look in the map file to see the BSS usage. Look at the end of the bss segment, then subtract from the stack - estimated stack usage: that will give you a rough idea of how much memory is left to be malloc'd. For example, if __bss_end is something like 0x06020000, and the stack is at 0x0603FF00 and you estimate 8KB of stack being used, you have about 0x0603DF00 - 0x06020000 or 0x1DF00 bytes available. Be very careful about local storage... look at this
Just did this math.
0x20540 bytes available. Should be enough for what I was malloc'ing. But it still wouldn't explain why it should fail with my variable at size 2048, but succeed with larger amounts up to 4096...


Since this problem is bugging me and I don't understand the root cause, I've tried looking into it a bit more. If I got up to size of 8096 it works, but beyond that it goes back to the BSOD and I've tried going much higher than that.

I captured the debug of Master SH2 from Gens KMod. But I don't understand the status. It basically hangs at this address 0600033A. But I don't see what that is from the linker's map file. But It appears to be this instruction

Code: Select all

stc sr, r0
But why that would fail is beyond my understanding.

Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Dec 29, 2012 7:32 pm

It's getting an exception - at the moment, there's only a generic error trap. I need to make a REAL error handler that prints the error and registers and stack. That way you can tell what kind of error you are getting and where...

This is where I normally turn to logging - printing what's being done and seeing what the last thing to do is before it goes out to lunch. :lol:

Post Reply