#128674 - Dwedit - Mon May 14, 2007 12:31 am
Source code available at: http://www.dwedit.org/dwedit_board/attachment.php?item=67
I need help here. I've got SMSAdvance building on GCC with no compiler errors, except the generated .GBA file has a zero-filled IWRAM section instead of the code it's supposed to have.
Here are the sequence of commands used to generate the binary (batch file):
Code: |
arm-eabi-gcc -mthumb -mthumb-interwork -Os -fomit-frame-pointer -Wall -c main.c -o main.o
arm-eabi-gcc -mthumb -mthumb-interwork -Os -fomit-frame-pointer -Wall -c ui.c -o ui.o
arm-eabi-gcc -mthumb -mthumb-interwork -Os -fomit-frame-pointer -Wall -c sram.c -o sram.o
arm-eabi-gcc -mthumb -mthumb-interwork -Os -fomit-frame-pointer -Wall -c minilzo.107/minilzo.c -o minilzo.o
cd asm
arm-eabi-as all.s -o all.o
cd ..
arm-eabi-gcc -mthumb-interwork -Wall main.o sram.o ui.o minilzo.o asm/all.o -o smsadvance.elf -specs=gba_mb.specs
arm-eabi-objcopy -v -O binary smsadvance.elf smsadvance.gba
gbafix smsadvance.gba -tSMSAdvance
|
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128721 - Dwedit - Mon May 14, 2007 3:08 pm
What's weird is that the ELF file contains all the iwram code, but after using OBJCOPY on it, the iwram code disappears! Also when loading the elf file in VBA or NO$GBA, the iwram code disappears as well. So far, the only thing that works is manually copying the iwram section into the GBA file with a hex editor.
Output of ReadElf:
Code: |
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x2000000
Start of program headers: 52 (bytes into file)
Start of section headers: 97572 (bytes into file)
Flags: 0x4000002, has entry point, <unrecognized EABI>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 21
Section header string table index: 18
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .init PROGBITS 02000000 008000 000224 00 AX 0 0 4
[ 2] .text PROGBITS 02000224 008224 005960 00 AX 0 0 4
[ 3] .fini PROGBITS 02005b84 00db84 000018 00 AX 0 0 4
[ 4] .rodata PROGBITS 02005b9c 00db9c 000870 00 A 0 0 4
[ 5] .init_array INIT_ARRAY 0200640c 00e40c 000004 00 WA 0 0 4
[ 6] .fini_array FINI_ARRAY 02006410 00e410 000004 00 WA 0 0 4
[ 7] .jcr PROGBITS 02006414 00e414 000004 00 WA 0 0 4
[ 8] .eh_frame PROGBITS 02006418 00e418 000004 00 A 0 0 4
[ 9] .iwram PROGBITS 03000000 00fc48 007b9c 00 0 0 4
[10] .bss NOBITS 03007b9c 00fc48 0000a8 00 WA 0 0 4
[11] .data PROGBITS 03007c44 00fc44 000004 00 WA 0 0 4
[12] .comment PROGBITS 00000000 0177e4 0002b9 00 0 0 1
[13] .debug_aranges PROGBITS 00000000 017aa0 000050 00 0 0 8
[14] .debug_info PROGBITS 00000000 017af0 0000b6 00 0 0 1
[15] .debug_abbrev PROGBITS 00000000 017ba6 000020 00 0 0 1
[16] .debug_line PROGBITS 00000000 017bc6 000092 00 0 0 1
[17] .ARM.attributes LOPROC+3 00000000 017c58 000010 00 0 0 1
[18] .shstrtab STRTAB 00000000 017c68 0000bc 00 0 0 1
[19] .symtab SYMTAB 00000000 01806c 007760 10 20 1466 4
[20] .strtab STRTAB 00000000 01f7cc 003c42 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x008000 0x02000000 0x02000000 0x0641c 0x0641c RWE 0x8000
LOAD 0x00fc44 0x03007c44 0x0200dfb8 0x00004 0x00004 RW 0x8000
LOAD 0x00fb9c 0x03007b9c 0x03007b9c 0x00000 0x000a8 RW 0x8000
Section to Segment mapping:
Segment Sections...
00 .init .text .fini .rodata .init_array .fini_array .jcr .eh_frame
01 .data
02 .bss
|
Any idea why the .iwram section gets dropped by objcopy?
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128740 - tepples - Mon May 14, 2007 6:51 pm
I noticed that .iwram's "Flg" column doesn't have "A".
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#128749 - Cearn - Mon May 14, 2007 7:21 pm
The proper section declaration for iwram is
Code: |
.section .iwram, "ax", %progbits |
When you use that instead of `.section ".iwram" ', the IWRAM stuff still end up in the binary. I don't trust all that non-aligned code though: it's possible that all the data and code happen to be word-aligned, but it'd better to add .align explicitly. Also, IWRAM is very ful. The counter goes up to 0300:7C00, leaving less than 1kb for the stack.
#128757 - Dwedit - Mon May 14, 2007 9:54 pm
Thanks!
I had tried the '.section .iwram, "ax", %progbits' thing before, and got a compiler warning that the change in attributes was being ignored, so I made sure to replace all instances, then it finally worked. Yay!
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128926 - Dwedit - Wed May 16, 2007 7:49 pm
I see that __end__ is a valid symbol for the last byte in multiboot mode, but it is not valid for cartridge mode. What is a valid symbol for the last byte in cartridge mode? All the symbols I've seen on the table are 8 bytes short of the last byte, for some reason there's this "dkARM\0\0\0" found 8 bytes from the end, and all of the last symbols point there.
Edit: Ah, I see: Version 1.5 deliberately corrupted the linkscript by adding the "dkarm\0\0\0" string. That really needs to go. I wonder if more people got burned by not having a real end symbol, or by the auto-trimmers which prompted the creation of junk in the linkscript?
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128931 - tepples - Wed May 16, 2007 8:06 pm
I think the addition had something to do with adding more robust support for appended data in general, rather than ad-hoc solutions such as GBFS.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#128943 - Dwedit - Wed May 16, 2007 11:14 pm
I think I've hit a bug in GCC.
I'm building for cartridge, so that .text is at 08000000. The program makes a few calls (from THUMB to ARM) to functions in .iwram. Whenever it calls an ARM function from thumb, there is an 8-byte veneer, consisting of two thumb instructions (bx pc \ nop) and an arm instruction (b xxxxxxxx). In the case where it calls from 08xxxxxx to 03xxxxxx, the jump is too long for a branch instruction, and it instead jumps to 07xxxxxx. In my case, it was trying to jump to 03005ccc, but instead jumped to 07005CCC. Of course, executing 07xxxxxx proceeds to execute a ton of NOPS, then it "reboots" when it hits 08000000.
I'd call this a GCC bug because it didn't try to make the jump long, or raise a linker error.
For comparison, ARM SDT raised a link error, and then proceeded to not give any information about that error, making it a long annoying guessing game. I don't know which is worse, ignoring an error so it crashes/reboots, or giving an error and not telling where it is.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128953 - wintermute - Thu May 17, 2007 1:50 am
I'm really not sure how you managed to get it to do that, I was having a play with this code a couple of days ago and got a whole bunch of relocation errors. I was going to fix it & post a zip but that project is too much of a mess for me to spare the time on unfortunately.
I've massaged things a bit to fit into a standard devkitPro build if you want to have a look at it.
http://www.devkitpro.org/files/smsadvance.zip
In order to get rid of the relocation errors you'll need to separate the assembly files into separate objects rather than including them in all.s. Once you've done that the .iwram code will need to be separated from the .text code and assembled separately - gcc assumes that functions in the same compilation unit will be within short branch range.
This was tested with devkitARM release 20, I highly recommend using that. It sounds like you may have an old buggy set of binutils in whatever you're using now. I also recommend using the devkitPro updater/installer rather than trying to install manually on windows.
You'll also need to edit gba_cart.ld found in /path/to/devkitARM/arm-eabi/lib
replace
end = __sbss_end;
with
_end = __sbss_end;
This tweak will be present in release 21
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog
#128954 - wintermute - Thu May 17, 2007 1:57 am
Dwedit wrote: |
I see that __end__ is a valid symbol for the last byte in multiboot mode, but it is not valid for cartridge mode. What is a valid symbol for the last byte in cartridge mode? All the symbols I've seen on the table are 8 bytes short of the last byte, for some reason there's this "dkARM\0\0\0" found 8 bytes from the end, and all of the last symbols point there.
Edit: Ah, I see: Version 1.5 deliberately corrupted the linkscript by adding the "dkarm\0\0\0" string. That really needs to go. I wonder if more people got burned by not having a real end symbol, or by the auto-trimmers which prompted the creation of junk in the linkscript? |
1. It's not corruption, it has zero effect other than to combat buggy auto trimmers.
2. __end__ is a pefectly valid symbol in my gba_cart.ld but _end is not, thus the tweak above. end was removed because far too many people suffered memory corruption due to using a variable called end - a bug in the original devkit advance scripts these were based on.
3. What version of devkitARM are you using? You seem to have broken it somehow. Are you sure you have no other toolchains in your path and/or odd environment variables defined?
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog
#128960 - Dwedit - Thu May 17, 2007 3:16 am
First, this is the corrected and (mostly) working code I am using. (use of mbclient.c is disabled since it's not working, otherwise everything works fine, don't know what's up, but it says "Sending..." and never stops)
http://www.dwedit.org/dwedit_board/attachment.php?item=75
In order to reproduce the broken jump, change: asmcalls.h (replace run_c with run), change main.c (replace all run_c calls with run).
"make rom" at a command line to build it.
You don't even need to append any roms to see the glitch in action. If you run the generated smsadvance_rom.gba, you will first see the 'rainbow splash screen' (copying open bus to vram), then you see it reboot and hear a staticy noise. That's it calling run, and getting to 07xxxxxx.
Edit: spoke too soon, forgot to modify code to trigger the problem. Clean devkitpro DOES have the problem.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
Last edited by Dwedit on Thu May 17, 2007 3:41 am; edited 1 time in total
#128961 - wintermute - Thu May 17, 2007 3:41 am
Is there any particular reason why you've copied the specs & crtls into your project?
That "makefile" is worse than the original bat file :/
You're mixing arm and thumb code and not telling the compiler, use -mthumb-interwork.
You're still going to have to separate the iwram code into separate objects to get it to work in rom.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog
#128962 - Dwedit - Thu May 17, 2007 3:47 am
For the "multiboot" build, I needed a modified crt0.s file. I needed to know whether it was initially executed from a cartridge or from multiboot mode based on the initial PC, and the default crt0.s has no way of reporting that.
For the "rom" build, I needed to kill the 8 byte trailer with a modified linkscript, it was either that, or adding 8 to a C variable manually. I thought adding 8 for the padding section was too 'hacky'. Then again, maybe I should instead use objcopy or something to just exclude that section?
It would be nice if I could just get the modified crt0.s file without needing to provide the specs and linkscript as well.
edit: "-R.pad" added to the objcopy line removes the need for the included linkscript in cart mode, yay
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128964 - wintermute - Thu May 17, 2007 4:03 am
How is the trailing 8 bytes a problem? It would be good if you could explain this one in detail.
EDIT: bah, stop editing your posts while I'm replying :P
I still don't understand why the 8 bytes are causing you problems.
A flag for multiboot code run from cart sounds like it might be useful. I'm going to consider that a feature request for r21
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog
#128965 - Dwedit - Thu May 17, 2007 4:18 am
The program depends on having a filesystem-like thingy appended to the rom. The program is dumb and doesn't do any searching, it assumes it will appear at a specific address given by a symbol address. If it gets the wrong address, it fails to find the filesystem. 8 bytes of appended data screws it up enough.
Right now, I'm using the symbol '__load_stop_iwram9' since that symbol is the end address of the binary in both multiboot and cart linkscripts. I'd perfer to use __end__, but __end__ has a value of 02000000 in my builds using the cart linkscript, so it's useless for that purpose.
Removing the .pad section works fine for removing the default appended data for now, it's just that it was unexpected that anything would even be there. Maybe __end__ needs to be redefined so that it points to the address after the padding.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#128967 - Dwedit - Thu May 17, 2007 4:46 am
How do I have multiple iwram sections that I can select the order in which they go into the binary? It looks like the linkscript provides a way to do it, but I can't tell how.
For now I'm using .subsections and putting everything in to the same file, there has to be a better way.
edit: Also, does gnu assembler support instructions like: ldr r0,[r10,#my_label - my_base] if 'my_label' and 'my_base' are external symbols?
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#129383 - Dwedit - Tue May 22, 2007 7:18 am
Ran out of stack space, finally had to modify both linkscripts. I changed the IRQ stack to start at 7FA0 (system default) instead of 7F00, and the User stack to start at 7F00 instead of 7E00.
Why was the IRQ stack placed at 7F00 anyway, when it is usually at 7FA0?
What else would the memory at 7F00-7FA0 be used for?
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."