_rtboot.s revision 8fd04b8338ed5093ec2d1e668fa620b7de44c177
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
.file "_rtboot.s"
! Bootstrap routine for alias ld.so. Control arrives here either directly
! from exec() upon invocation of a dynamically linked program specifying our
! alias as its interpreter.
!
! On entry, the stack appears as:
!
!_______________________! high addresses
! !
! Information !
! Block !
! (size varies) !
!_______________________!
! 0 word !
!_______________________!
! Auxiliary !
! vector !
! 2 word entries !
! !
!_______________________!
! 0 word !
!_______________________!
! Environment !
! pointers !
! ... !
! (one word each) !
!_______________________!
! 0 word !
!_______________________!
! Argument ! low addresses
! pointers !
! Argc words !
!_______________________!
! !
! Argc !
!_______________________!<- %sp +64
! !
! Window save area !
!_______________________! <- %sp
#include <sys/asm_linkage.h>
#include <sys/param.h>
#include <sys/syscall.h>
#include <link.h>
#include "alias_boot.h"
.section ".text"
.volatile
.global __rtboot
.local __rtld
.local s.LDSO, s.ZERO
.local f.PANIC, f.OPENAT, f.MMAP, f.FSTATAT, f.SYSCONFIG
.local f.CLOSE, f.EXIT, f.MUNMAP
.type __rtboot, #function
.align 4
! Create a stack frame, perform PIC set up. If we're a "normal" start, we have
! to determine a bunch of things from our "environment" and construct an ELF
! boot attribute value vector. Otherwise, it's already been done and we can
! skip it.
__rtboot:
save %sp, -SA(MINFRAME + (EB_MAX * 8) + ((S_MAX + F_MAX) * 4)), %sp
1: ! PIC prologue
call 2f ! get PIC for PIC work
! Set up pointers to __rtld parameters. eb[], strings[] and funcs[] are on
! the stack. Note that we will call ld.so with an entry vector that causes
! it to use the stack frame we have.
add %sp, MINFRAME, %o0 ! &eb[0]
2:
add %o0, (EB_MAX * 8), %o1 ! &strings[0] == &eb[EB_MAX]
add %o1, (S_MAX * 4), %o2 ! &funcs[0] == &strings[S_MAX]
set EB_ARGV, %l0 ! code for this entry
st %l0, [%o0] ! store it
add %fp, 68, %l0 ! argument vector is at %fp+68
st %l0, [%o0 + 4] ! store that
ld [%fp + 64], %l1 ! get argument count
inc %l1 ! account for last element of 0
sll %l1, 2, %l1 ! multiply by 4
add %l0, %l1, %l0 ! and get address of first env ptr
st %l0, [%o0 + 12] ! store it in the vector
set EB_ENVP, %l1 ! code for environment base
st %l1, [%o0 + 8] ! store it
set EB_AUXV, %l1 ! get code for auxiliary vector
st %l1, [%o0 + 16] ! store it
2:
ld [%l0], %l1 ! get an entry
tst %l1 ! are we at a "0" entry in environment?
bne 2b ! no, go back and look again
add %l0, 4, %l0 ! incrementing pointer in delay
st %l0, [%o0 + 20] ! store aux vector pointer
set EB_NULL, %l0 ! set up for the last pointer
st %l0, [%o0 + 24] ! and store it
! Initialize strings and functions as appropriate
#define SI(n) \
set (s./**/n - 1b), %l0; \
add %o7, %l0, %l0; \
st %l0, [%o1 + (n/**/_S * 4)]
#define FI(n) \
set (f./**/n - 1b), %l0; \
add %o7, %l0, %l0; \
st %l0, [%o2 + (n/**/_F * 4)]
SI(LDSO)
SI(ZERO)
SI(EMPTY)
FI(PANIC)
FI(OPENAT)
FI(MMAP)
FI(FSTATAT)
FI(SYSCONFIG)
FI(CLOSE)
FI(MUNMAP)
! Call the startup function to get the real loader in here.
call __rtld ! call it
mov %o0, %l0 ! and save &eb[0] for later
! On return, jump to the function in %o0, passing &eb[0] in %o0
jmpl %o0, %g0 ! call main program
mov %l0, %i0 ! set up parameter
! Functions
f.PANIC:
save %sp, -SA(MINFRAME), %sp ! make a frame
mov %i0, %o1 ! set up pointer
clr %o2 ! set up character counter
1: ! loop over all characters
ldub [%i0 + %o2], %o0 ! get byte
tst %o0 ! end of string?
bne,a 1b ! no,
inc %o2 ! increment count
call f.WRITE ! write(2, buf, %o2)
mov 2, %o0
2:
call 1f ! get PC
mov l.ERROR, %o2 ! same with constant message
1:
set (s.ERROR - 2b), %o1 ! get PC-relative address
add %o7, %o1, %o1 ! and now make it absolute
call f.WRITE ! write it out
mov 2, %o0 ! to standard error
ba f.EXIT ! leave
nop
f.OPENAT:
ba __syscall
mov SYS_openat, %g1
f.MMAP:
sethi %hi(0x80000000), %g1 ! MAP_NEW
or %g1, %o3, %o3
ba __syscall
mov SYS_mmap, %g1
f.MUNMAP:
ba __syscall
mov SYS_munmap, %g1
f.READ:
ba __syscall
mov SYS_read, %g1
f.WRITE:
ba __syscall
mov SYS_write, %g1
f.LSEEK:
ba __syscall
mov SYS_lseek, %g1
f.CLOSE:
ba __syscall
mov SYS_close, %g1
f.FSTATAT:
ba __syscall
mov SYS_fstatat, %g1
f.SYSCONFIG:
ba __syscall
mov SYS_sysconfig, %g1
f.EXIT:
mov SYS_exit, %g1
__syscall:
t 0x8 ! call the system call
bcs __err_exit ! test for error
nop
retl ! return
nop
__err_exit:
retl ! return
mov -1, %o0
! String constants
s.LDSO: .asciz "/usr/lib/ld.so.1"
s.ZERO: .asciz "/dev/zero"
s.EMPTY:.asciz "(null)"
s.ERROR:.asciz ": no (or bad) /usr/lib/ld.so.1\n"
l.ERROR= . - s.ERROR
.align 4
.size __rtboot, . - __rtboot
! During construction -- the assembly output of _rtld.c2s is placed here.
.section ".text"
.nonvolatile