mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-27 04:41:02 +08:00
AIX startup code.
This commit is contained in:
parent
7fac016cfa
commit
5f55815d27
290
sysdeps/unix/sysv/aix/start.c
Normal file
290
sysdeps/unix/sysv/aix/start.c
Normal file
@ -0,0 +1,290 @@
|
||||
/* Copyright (C) 1991, 93, 1995-1998, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
/* Old compatibility names for C types. */
|
||||
typedef unsigned char uchar; /* sb in libc/posix/types.h */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <xcoff.h>
|
||||
#include <rtinit.h>
|
||||
#include <dlldr.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
/* The first piece of initialized data. */
|
||||
int __data_start = 0;
|
||||
|
||||
extern int errno;
|
||||
|
||||
/* extern __pthread_init; */
|
||||
|
||||
typedef void (*FPV)(void);
|
||||
|
||||
typedef struct crt0_info
|
||||
{
|
||||
int *p_argc;
|
||||
FPV threads_init;
|
||||
} INFO;
|
||||
|
||||
|
||||
INFO crt0_info;
|
||||
int argc;
|
||||
char **argv;
|
||||
char **__environ;
|
||||
int module_count;
|
||||
caddr_t text_origin;
|
||||
caddr_t data_origin;
|
||||
|
||||
asm("
|
||||
.toc
|
||||
LL..0: .tc argc[TC],argc
|
||||
LL..1: .tc argv[TC],argv
|
||||
LL..2: .tc __environ[TC],__environ
|
||||
LL..3: .tc module_count[TC],module_count
|
||||
LL..4: .tc text_origin[TC],text_origin
|
||||
LL..5: .tc data_origin[TC],data_origin
|
||||
");
|
||||
|
||||
int main (int argc,char **argv,char **__environ);
|
||||
int modinit(int argc,INFO *crt0_info, int module_count,
|
||||
caddr_t text_origin, caddr_t data_origin);
|
||||
|
||||
void mod_init1(void *handler,__RTINIT *rti);
|
||||
|
||||
__RTINIT *find_rtinit(caddr_t text_origin,caddr_t data_origin, int module_count);
|
||||
|
||||
extern int *__loadx();
|
||||
|
||||
void __start(void)
|
||||
{
|
||||
#ifdef __64BIT__
|
||||
asm("
|
||||
ld 17,LL..0(2) # argc
|
||||
std 14,0(17) # copy reg14 to argc
|
||||
ld 17,LL..1(2) # argv
|
||||
std 15,0(17) # copy reg15 to argv
|
||||
ld 17,LL..2(2) # envp
|
||||
std 16,0(17) # copy reg16 to envp
|
||||
ld 17,LL..3(2) # module_count
|
||||
std 30,0(17) # copy reg30 to module_count
|
||||
ld 17,LL..4(2) # text_origin
|
||||
std 29,0(17) # copy reg29 to text_origin
|
||||
ld 17,LL..5(2) # data_origin
|
||||
std 28,0(17) # copy reg28 to data_origin
|
||||
");
|
||||
#else
|
||||
asm("
|
||||
lwz 17,LL..0(2) # argc
|
||||
stw 3,0(17) # copy reg3 to argc
|
||||
lwz 17,LL..1(2) # argv
|
||||
stw 4,0(17) # copy reg4 to argv
|
||||
lwz 17,LL..2(2) # envp
|
||||
stw 5,0(17) # copy reg5 to envp
|
||||
lwz 17,LL..3(2) # module_count
|
||||
stw 30,0(17) # copy reg30 to module_count
|
||||
lwz 17,LL..4(2) # text_origin
|
||||
stw 29,0(17) # copy reg29 to text_origin
|
||||
lwz 17,LL..5(2) # data_origin
|
||||
stw 28,0(17) # copy reg28 to data_origin
|
||||
");
|
||||
#endif
|
||||
crt0_info.p_argc = (int*)&argc;
|
||||
|
||||
/* crt0_info.threads_init = (FPV) &__pthread_init; */
|
||||
|
||||
/*
|
||||
* Do run-time linking, if enabled and call the init()
|
||||
* for all loaded modules.
|
||||
*/
|
||||
argc = modinit(argc,&crt0_info,module_count,text_origin,data_origin);
|
||||
|
||||
errno=0;
|
||||
/*
|
||||
* Call the user program.
|
||||
*/
|
||||
exit (main (argc, argv, __environ));
|
||||
}
|
||||
|
||||
/*
|
||||
* The modinit() function performs run-time linking,
|
||||
* if enabled, and calling the init() function for
|
||||
* all loaded modules.
|
||||
*
|
||||
* int modinit(argc,crt0_info,module_count,text,data)
|
||||
*
|
||||
* argc - current value of argc.
|
||||
* info - crt0 information passed
|
||||
* module_count - number of modules loaded.
|
||||
* text - Beginning of text address
|
||||
* data - Beginning of data address
|
||||
*/
|
||||
|
||||
#define DL_BUFFER_SIZE 1000
|
||||
|
||||
int modinit(int argc,INFO *crt0_info, int module_count,
|
||||
caddr_t text_origin, caddr_t data_origin)
|
||||
{
|
||||
int *handler = 0;
|
||||
__RTINIT *rtinit_info = 0;
|
||||
int flag;
|
||||
DL_INFO dl_buffer[DL_BUFFER_SIZE];
|
||||
DL_INFO *dl_info = dl_buffer;
|
||||
int i;
|
||||
FPV p;
|
||||
__libc_lock_define_initialized(static,modinit_lock);
|
||||
|
||||
/*
|
||||
* try to find __rtinit symbols
|
||||
*/
|
||||
rtinit_info = find_rtinit(text_origin,data_origin,module_count);
|
||||
|
||||
flag = DL_EXECQ;
|
||||
if (rtinit_info && rtinit_info->rtl) flag |= DL_LOAD_RTL;
|
||||
|
||||
/*
|
||||
* get a list of modules that have __rtinit
|
||||
*/
|
||||
if (__loadx(flag, dl_info, sizeof(dl_buffer))) exit(0x90);
|
||||
|
||||
if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
|
||||
{
|
||||
rtinit_info = find_rtinit(dl_info[1].dlinfo_textorg,
|
||||
dl_info[1].dlinfo_dataorg,
|
||||
module_count);
|
||||
if ((rtinit_info != NULL) & (rtinit_info->rtl != NULL))
|
||||
{
|
||||
if((*rtinit_info->rtl)(dl_info,0)) exit(0x90);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize threads in case any init
|
||||
* functions need thread functions
|
||||
*/
|
||||
if (crt0_info->threads_init)
|
||||
(*crt0_info->threads_init)();
|
||||
|
||||
p = (FPV) __loadx(DL_GLOBALSYM | DL_SRCHLOADLIST,"pthread_init");
|
||||
if (p)
|
||||
(*p)();
|
||||
|
||||
__libc_lock_lock(modinit_lock);
|
||||
|
||||
/*
|
||||
* initialization each module loaded that has __rtinit.
|
||||
*/
|
||||
if (( dl_info[0].dlinfo_xflags & DL_INFO_OK))
|
||||
{
|
||||
for (i=1; i < dl_info[0].dlinfo_arraylen + 1; i++)
|
||||
{
|
||||
if (dl_info[i].dlinfo_flags & DL_HAS_RTINIT)
|
||||
{
|
||||
rtinit_info = find_rtinit(dl_info[i].dlinfo_textorg,
|
||||
dl_info[i].dlinfo_dataorg,
|
||||
module_count);
|
||||
if (rtinit_info)
|
||||
{
|
||||
mod_init1(handler,rtinit_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__libc_lock_unlock(modinit_lock);
|
||||
/*
|
||||
* reload argc if needed.
|
||||
*/
|
||||
return((int) (*crt0_info->p_argc));
|
||||
}
|
||||
|
||||
/*
|
||||
* The mod_init1 calls every initialization function
|
||||
* for a given module.
|
||||
*
|
||||
* void mod_init1(handler, rti)
|
||||
*
|
||||
* void *handler - if NULL init funtions for modules loaded at exec time
|
||||
* are being executed. Otherwise, the handler points to the
|
||||
* module loaded.
|
||||
*
|
||||
* __RTINIT *rti - pointer to __rtinit data structure (with rti->init_offset
|
||||
* not equal to zero)
|
||||
*/
|
||||
|
||||
void mod_init1(void *handler,__RTINIT *rtl)
|
||||
{
|
||||
__RTINIT_DESCRIPTOR *descriptor;
|
||||
|
||||
descriptor =(__RTINIT_DESCRIPTOR *) ((caddr_t)&rtl->rtl + rtl->init_offset);
|
||||
while (descriptor->f)
|
||||
{
|
||||
if (!(descriptor->flags & _RT_CALLED))
|
||||
{
|
||||
descriptor->flags |= _RT_CALLED;
|
||||
( descriptor->f )(handler,rtl,descriptor); /* execute init/fini */
|
||||
}
|
||||
descriptor = (__RTINIT_DESCRIPTOR *) ((caddr_t)descriptor +
|
||||
rtl->__rtinit_descriptor_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find __rtinit symbol
|
||||
*
|
||||
* __RTINIT *find_rtinit(caddr_t text_origin)
|
||||
*
|
||||
* caddr_t text_origin - Beginning of text area
|
||||
* caddr_t data_origin - Beginning of data area
|
||||
* int module_count - Number of modules loaded
|
||||
* __RTINIT *rti - pointer to __rtinit data structure
|
||||
*/
|
||||
|
||||
__RTINIT *find_rtinit(caddr_t text_origin, caddr_t data_origin, int module_count)
|
||||
{
|
||||
struct xcoffhdr *xcoff_hdr;
|
||||
SCNHDR *sec_hdr;
|
||||
SCNHDR *ldr_sec_hdr;
|
||||
SCNHDR *data_sec_hdr;
|
||||
LDSYM *ldsym_hdr;
|
||||
__RTINIT *rtl;
|
||||
|
||||
xcoff_hdr = (struct xcoffhdr *) text_origin;
|
||||
sec_hdr = (SCNHDR *) ((caddr_t)&xcoff_hdr->aouthdr +
|
||||
xcoff_hdr->filehdr.f_opthdr);
|
||||
ldr_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_snloader - 1));
|
||||
ldsym_hdr = (LDSYM *) ((caddr_t)xcoff_hdr + ldr_sec_hdr->s_scnptr +
|
||||
LDHDRSZ);
|
||||
|
||||
if ( module_count <= 0)
|
||||
{
|
||||
if ( !(ldr_sec_hdr->s_scnptr) ) return ((__RTINIT *) 0);
|
||||
|
||||
if ( memcmp(ldsym_hdr,RTINIT_NAME,sizeof(RTINIT_NAME)-1))
|
||||
return ((__RTINIT *) 0);
|
||||
}
|
||||
|
||||
data_sec_hdr = (SCNHDR *) (sec_hdr + (xcoff_hdr->aouthdr.o_sndata - 1));
|
||||
rtl = (__RTINIT *) (ldsym_hdr->l_value +
|
||||
(data_origin - data_sec_hdr->s_vaddr));
|
||||
return(rtl);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user