forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

crt0 not working correctly

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development
View previous topic :: View next topic  
Author Message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Mon Jan 12, 2009 6:11 pm    Post subject: crt0 not working correctly Reply with quote

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
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Mon Jan 12, 2009 6:25 pm    Post subject: Reply with quote

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
View user's profile Send private message
Lukasz



Joined: 19 Jan 2004
Posts: 248
Location: Denmark

PostPosted: Mon Jan 12, 2009 6:46 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Mon Jan 12, 2009 9:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Mon Jan 12, 2009 9:35 pm    Post subject: Reply with quote

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
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Mon Jan 12, 2009 10:35 pm    Post subject: Reply with quote

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
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Tue Jan 13, 2009 6:29 am    Post subject: Reply with quote

Im having the same issue with _ps2sdk_stdio_init though. It too uses a weak definition in crt0.s.
Back to top
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Tue Jan 13, 2009 11:40 am    Post subject: Reply with quote

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
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Tue Jan 13, 2009 12:04 pm    Post subject: Reply with quote

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
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Thu Jan 15, 2009 7:01 pm    Post subject: Reply with quote

committed rev 1508
Back to top
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Thu Jan 15, 2009 7:27 pm    Post subject: Reply with quote

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
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Thu Jan 15, 2009 11:04 pm    Post subject: Reply with quote

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
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Sat Jan 17, 2009 1:45 am    Post subject: Reply with quote

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
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Sat Jan 17, 2009 9:58 am    Post subject: Reply with quote

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
View user's profile Send private message
ragnarok2040



Joined: 09 Aug 2006
Posts: 230

PostPosted: Sat Jan 17, 2009 9:56 pm    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
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