 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Mon Jan 12, 2009 6:11 pm Post subject: crt0 not working correctly |
|
|
crt0 is supposed to call _ps2sdk_args_parse which sets up the initial cwd according to argv[0] but it isnt doing this. To test this I added the following line to the hello sample:
| Code: | char cwd[256];
printf("cwd: %s\n", getcwd(cwd, 256)); |
And when I run the test the cwd is empty. If I add a call to _ps2sdk_args_parse at the start of main then the above code prints out the correct string proving its not been called.
Now if I remove _ps2sdk_args_parse again and comment out this line in crt0.s:
| Code: | | .weak _ps2sdk_args_parse |
Then again the hello sample prints out the correct string. So it appears the weak attribute isnt working correctly in the compiler Im using. Im using build 28072007 from this site: http://lukasz.dk/playstation-2-programming/mingw-tutorial/
Is this working correctly with other peoples setup? |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Mon Jan 12, 2009 6:25 pm Post subject: |
|
|
| I have added a test to ps2sdk\ee\libc\regress so build and run this to see if it works on your system. |
|
| Back to top |
|
 |
Lukasz

Joined: 19 Jan 2004 Posts: 248 Location: Denmark
|
Posted: Mon Jan 12, 2009 6:46 pm Post subject: |
|
|
I just tested this on Ubuntu, I modified your test_init to:
| Code: | static const char *test_init(void *arg)
{
// _ps2sdk_args_parse should setup the initial cwd called from crt0.s
char cwd[256];
if (getcwd(cwd, 256)[0] == '\0')
return "failed to setup cwd";
else
printf("(cwd: \"%s\")\n", getcwd(cwd,256));
return NULL;
} |
I get the following output when using PS2Link 1.46 and ps2client (latest version I think).
| Code: | Running 10 tests
Test 1: init (cwd: "host:")
Test 2: fopen, fclose open name host:testfiles/dummy flag 1 data 44078
open fd = 2
Test 3: fgets open name host:testfiles/dummy flag 1 data 44078
open fd = 2
Test 4: fread open name host:testfiles/dummy flag 1 data 44078
open fd = 2
Test 5: fgetc open name host:testfiles/dummy flag 1 data 44078
open fd = 2
Test 6: fseek, ftell open name host:testfiles/dummy flag 1 data 44078
open fd = 2
Test 7: stat stat() unimplemented
fn host:testfiles/dummy mode 0x0, size 0
Test 8: stat stat() unimplemented
fn host:testfiles mode 0x0, size 0
[expected directory, not regular file]
Test 9: mkdir mkdir name host:dummydir
Test 10: rmdir rmdir name host:dummydir
Total failures: 1
|
Appears to be working correctly. _________________ Lukasz.dk |
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Mon Jan 12, 2009 9:29 pm Post subject: |
|
|
I'm getting the same behavior as you radad. When I commented out the .weak _ps2sdk_args_parse line in crt0.s, it worked. When I added a call to _ps2sdk_args_parse to main, getcwd worked.
I'm guessing what's happening is the linker doesn't explicitly look for the weak _ps2sdk_args_parse definition among library archives and since it's not explicitly called by any functions, the symbol is never actually added in the linking stage. |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Mon Jan 12, 2009 9:35 pm Post subject: |
|
|
What compiler/OS are you using?
It is explicitly called in crt0.s, that should be enough for linker to make sure it is in there. |
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Mon Jan 12, 2009 10:35 pm Post subject: |
|
|
Archlinux x86-64, using a 32-bit standard ps2toolchain compiler on a chroot.
The .weak pseudo-op just tells it to use the definition it has until a global definition supercedes it from user code, or another weak definition from user code, which has to be seen first, supercedes it. Otherwise the weak definition in crt0.s holds sway.
When _ps2sdk_args_parse is called by user code, then the linker searches for the symbol definition, finding the weak one in init.o. Since it finds the weak symbol linked in from init.o from libc first, it supercedes the one defined in crt0.s which is linked in later which causes the code to work.
It's just the matter of placing the other weak _ps2sdk_args_parse call somewhere so it gets linked in prior to crt0.s. Adding _ps2sdk_args_parse to _ps2sdk_stdio_init() seems to fix it, though.
Edit:
Just to make sure, I called it with some false args to see what would happen, but it parsed the args provided by ps2link correctly. |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Tue Jan 13, 2009 6:29 am Post subject: |
|
|
| Im having the same issue with _ps2sdk_stdio_init though. It too uses a weak definition in crt0.s. |
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Tue Jan 13, 2009 11:40 am Post subject: |
|
|
Hrmm, using weak definitions in the crt0.s was a way to get the crt0.o to compile without ps2sdk as well, according to chp. Unfortunately, it depends on the proper definitions being defined prior to crt0.o being linked when compiling with ps2sdk.
Also defining the symbols in crt0.s as .globl prior to defining a .weak symbol might also be causing trouble since global definitions override weak definitions. It didn't seem to make any difference after changing them, though.
I changed it to use .weakext instead. It seems to work fine now. Your clock example was working, and only 2 tests failed, tests 6 & 8. I was getting 4 tests failing with _ps2sdk_args_parse not being defined, and 3 tests failing after that, so I guess libc wasn't being initialized quite right.
| Code: |
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright (c) 2001-2007 ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
# $Id: crt0.s 1466 2008-11-10 01:46:38Z oopo $
# Standard startup file.
.weak _init
.type _init, @function
.weak _fini
.type _fini, @function
.extern _heap_size
.extern _stack
.extern _stack_size
.weakext _ps2sdk_weak_args_parse, _ps2sdk_args_parse
.globl _ps2sdk_weak_args_parse
.type _ps2sdk_weak_args_parse, @function
.weakext _ps2sdk_weak_libc_init, _ps2sdk_libc_init
.globl _ps2sdk_weak_libc_init
.type _ps2sdk_weak_libc_init, @function
.weakext _ps2sdk_weak_libc_deinit, _ps2sdk_libc_deinit
.globl _ps2sdk_weak_libc_deinit
.type _ps2sdk_weak_libc_deinit, @function
.set noat
.set noreorder
.text
.align 2
nop
nop
.globl _start
.ent _start
_start:
zerobss:
# clear bss area
la $2, _fbss
la $3, _end
1:
sltu $1, $2, $3
beq $1, $0, 2f
nop
sq $0, ($2)
addiu $2, $2, 16
j 1b
nop
2:
# store eventual loader arguments (passed via a0)
la $2, _loader_args
sw $4, ($2)
setupthread:
# setup current thread
la $4, _gp
la $5, _stack
la $6, _stack_size
la $7, _args
la $8, _root
move $gp, $4
addiu $3, $0, 60
syscall # SetupThread(_gp, _stack, _stack_size, _args, _root)
move $sp, $2
# initialize heap
la $4, _end
la $5, _heap_size
addiu $3, $0, 61
syscall # SetupHeap(_end, _heap_size)
# writeback data cache
move $4, $0
addiu $3, $0, 100
syscall # FlushCache(0)
parseargs:
# call ps2sdk argument parsing (weak)
la $8, _ps2sdk_weak_args_parse
beqz $8, 1f
nop
jal _getargs
nop
jalr $8 # _ps2sdk_weak_args_parse(argc, argv)
nop
1:
libc_init:
# initialize ps2sdk libc (weak)
la $8, _ps2sdk_weak_libc_init
beqz $8, 1f
nop
jalr $8 # _ps2sdk_weak_libc_init()
nop
1:
ctors:
# call global constructors (weak)
la $8, _init
beqz $8, 1f
nop
jalr $8 # _init()
nop
1:
# call main
ei
jal _getargs
nop
jal main # main(argc, argv)
nop
# call _exit
j _exit # _exit(retval)
move $4, $2
.end _start
.align 3
.globl _exit
.ent _exit
.text
_exit:
la $2, _retval
sw $4, ($2)
dtors:
# call global destructors (weak)
la $8, _fini
beqz $8, 1f
nop
jalr $8 # _fini()
nop
1:
libc_uninit:
# uninitialize ps2sdk libc (weak)
la $8, _ps2sdk_weak_libc_deinit
beqz $8, 1f
nop
jalr $8 # _ps2sdk_weak_libc_deinit()
nop
1:
# conditional exit (depending on if we got arguments through the loader or not)
la $2, _retval
lw $4, ($2)
la $5, _loader_args
lw $6, ($5)
beqz $6, 1f
nop
# called from a loader, close thread
lw $7, ($6)
sw $0, ($7) # clear thread id
addiu $3, $0, 36
syscall # ExitDeleteThread() (noreturn)
1:
# not called from a loader, return to browser
addiu $3, $0, 4
syscall # Exit(retval) (noreturn)
.end _exit
.ent _root
_root:
addiu $3, $0, 35
syscall # ExitThread() (noreturn)
.end _root
.ent _getargs
_getargs:
# check normal arguments
la $2, _args
lw $3, ($2)
bnez $3, 1f
nop
# check for arguments passed by a loader
la $2, _loader_args
lw $3, ($2)
beqzl $3, 2f
addu $4, $0, 0
addiu $2, $3, 4
1:
lw $4, ($2)
addiu $5, $2, 4
2:
jr $ra # $4 = argc, $5 = argv
nop
.end _getargs
.bss
.align 6
_args:
.space 4+16*4+256 # argc, 16 arguments, 256 bytes payload
_loader_args:
.space 4 # pointer to loader arguments: thread id, argc, argv
_retval:
.space 4
|
|
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Tue Jan 13, 2009 12:04 pm Post subject: |
|
|
Looks like a small oversight in fseek causes it to fail when it actually works.
The line
if (ret > 0)
should be
if (ret >= 0)
Edit3:
Fseek regression test problem was related to my version of ps2client so I removed my previous code. |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Thu Jan 15, 2009 7:01 pm Post subject: |
|
|
| committed rev 1508 |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Thu Jan 15, 2009 7:27 pm Post subject: |
|
|
This has broken cpp builds for me. I get this error:
| Code: | C:/Devel/ps2/ps2msys/msys/local/ps2dev/ps2sdk/ee/startup/crt0.o(.text+0xd4): In
function `_start':
src/crt0.s:123: undefined reference to `_init'
C:/Devel/ps2/ps2msys/msys/local/ps2dev/ps2sdk/ee/startup/crt0.o(.text+0xd8):src/
crt0.s:123: undefined reference to `_init'
C:/Devel/ps2/ps2msys/msys/local/ps2dev/ps2sdk/ee/startup/crt0.o(.text+0x114): In
function `_exit':
src/crt0.s:157: undefined reference to `_fini'
C:/Devel/ps2/ps2msys/msys/local/ps2dev/ps2sdk/ee/startup/crt0.o(.text+0x118):src
/crt0.s:158: undefined reference to `_fini' |
|
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Thu Jan 15, 2009 11:04 pm Post subject: |
|
|
I'm pretty sure _init and _fini are defined in crti.o in ee/lib/gcc-lib/ee/3.2.2/. Are you using the -nostartfiles flag when linking instead of -mno-crt0?
The best option for building C++ projects with -nostartfiles right now is defining an empty _init and _fini in your project somewhere.
| Code: | extern "C" {
void _init(void) {}
void _fini(void) {}
}//extern "C" |
Hrmm, it looks like C projects are being forced to include C++ symbols and sections as well, and fails with undefined references to _init and _fini with -nostartfiles, seems to be linker script problem. I'll examine it further. |
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Sat Jan 17, 2009 1:45 am Post subject: |
|
|
Looks like that's normal, :?, never noticed it before, but I haven't dabbled with low-level C++ stuff. The linkmaps indicate that _init and _fini get defined normally by crti.o when using .weak _init and .weak _fini and when using the flag -mno-crt0. Changing them back to .weak shouldn't be a problem, :D.
I tested using some global class instances to make sure.
I pm'd oobles but haven't gotten a response yet. I made a patch, http://homebrew.thewaffleiron.net/ragnarok2040/crt0.patch.gz.
This should fix builds using -nostartfiles that don't rely on global objects. |
|
| Back to top |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Sat Jan 17, 2009 9:58 am Post subject: |
|
|
That fixes it, thanks. I have checked it in.
Give oobles a bit of time, he doesnt check very often.
On a slightly different topic. Anybody know why this section exists in iop/Rules.make
| Code: | ifeq ($(IOP_CC_VERSION),3.2.2)
CFLAGS_TARGET = -fno-builtin
ASFLAGS_TARGET = -march=r3000
LDFLAGS_TARGET = -fno-builtin
endif |
Why is version 3.2.2 special? Is this needed especially as LDFLAGS_TARGET already includes a '-fno-builtin'? Isnt '-fno-builtin' a link option anyway so why is it in CFLAGS_TARGET? |
|
| Back to top |
|
 |
ragnarok2040
Joined: 09 Aug 2006 Posts: 230
|
Posted: Sat Jan 17, 2009 9:56 pm Post subject: |
|
|
Hrmm, weird. Since ps2sdk uses LDFLAGS for CFLAGS when linking and CFLAGS for CFLAGS when compiling object code, I'm guessing it's to ensure that gcc doesn't try to optimize code for their builtin functions during both stages. It should be part of the CFLAGS for the older toolchains as well, then. Perhaps the behavior changed where gcc-3.2.2 does some optimizing during object code generation for builtin functions.
I'm not sure why LDFLAGS_TARGET was added since "-fno-builtin" is already in the original LDFLAGS. I'm pretty sure -march wasn't supported by the mips target in older IOP toolchains and -mcpu was deprecated in gcc-3.2.2.
Changing it to: | Code: | ifeq ($ (IOP_CC_VERSION), 3.2.2)
ASFLAGS_TARGET = -march=r3000
endif | And changing the flags to: | Code: | IOP_CFLAGS := -fno-builtin -O2 -G0 -c $(IOP_INCS) $(IOP_CFLAGS)
IOP_ASFLAGS := $(ASFLAGS_TARGET) -EL -G0 $(IOP_ASFLAGS)
IOP_LDFLAGS := -fno-builtin -nostdlib $(IOP_LDFLAGS) | Should work for gcc-3.2.2 and older toolchains. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|