a4b8639bc4345044ebf1e8605262b55f0641730b
[platform/upstream/linaro-glibc.git] / sysdeps / generic / dl-sysdep.c
1 /* Operating system support for run-time dynamic linker.  Generic Unix version.
2 Copyright (C) 1995, 96 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <elf.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24 #include <fcntl.h>
25 #include <link.h>
26 #include <unistd.h>
27 #include <stdarg.h>
28 #include <string.h>
29
30
31 extern int _dl_argc;
32 extern char **_dl_argv;
33 extern char **_environ;
34 extern void _start (void);
35 extern int _dl_secure;
36
37 ElfW(Addr)
38 _dl_sysdep_start (void **start_argptr,
39                   void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
40                                    ElfW(Addr) *user_entry))
41 {
42   const ElfW(Phdr) *phdr;
43   ElfW(Word) phnum;
44   ElfW(Addr) user_entry;
45   ElfW(auxv_t) *av;
46   uid_t uid, euid;
47   gid_t gid, egid;
48   unsigned int seen;
49
50   user_entry = (ElfW(Addr)) &_start;
51   _dl_argc = *(long *) start_argptr;
52   _dl_argv = (char **) start_argptr + 1;
53   _environ = &_dl_argv[_dl_argc + 1];
54   start_argptr = (void **) _environ;
55   while (*start_argptr)
56     ++start_argptr;
57
58   seen = 0;
59 #define M(type) (1 << (type))
60
61   for (av = (void *) ++start_argptr;
62        av->a_type != AT_NULL;
63        seen |= M ((++av)->a_type))
64     switch (av->a_type)
65       {
66       case AT_PHDR:
67         phdr = av->a_un.a_ptr;
68         break;
69       case AT_PHNUM:
70         phnum = av->a_un.a_val;
71         break;
72       case AT_ENTRY:
73         user_entry = av->a_un.a_val;
74         break;
75       case AT_UID:
76         uid = av->a_un.a_val;
77         break;
78       case AT_GID:
79         gid = av->a_un.a_val;
80         break;
81       case AT_EUID:
82         euid = av->a_un.a_val;
83         break;
84       case AT_EGID:
85         egid = av->a_un.a_val;
86         break;
87       }
88
89   /* Linux doesn't provide us with any of these values on the stack
90      when the dynamic linker is run directly as a program.  */
91
92 #define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
93   SEE (UID, uid);
94   SEE (GID, gid);
95   SEE (EUID, euid);
96   SEE (EGID, egid);
97
98
99   __libc_enable_secure = uid != euid || gid != egid;
100
101 #ifdef DL_SYSDEP_INIT
102   DL_SYSDEP_INIT;
103 #endif
104
105   (*dl_main) (phdr, phnum, &user_entry);
106   return user_entry;
107 }
108
109 void
110 _dl_sysdep_start_cleanup (void)
111 {
112 }
113 \f
114 #ifndef MAP_ANON
115 /* This is only needed if the system doesn't support MAP_ANON.  */
116
117 int
118 _dl_sysdep_open_zero_fill (void)
119 {
120   return __open ("/dev/zero", O_RDONLY);
121 }
122 #endif
123
124 /* Read the whole contents of FILE into new mmap'd space with given
125    protections.  *SIZEP gets the size of the file.  */
126
127 void *
128 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
129 {
130   void *result;
131   struct stat st;
132   int fd = __open (file, O_RDONLY);
133   if (fd < 0)
134     return NULL;
135   if (__fstat (fd, &st) < 0)
136     result = NULL;
137   else
138     {
139       /* Map a copy of the file contents.  */
140       result = __mmap (0, st.st_size, prot,
141 #ifdef MAP_COPY
142                        MAP_COPY
143 #else
144                        MAP_PRIVATE
145 #endif
146 #ifdef MAP_FILE
147                        | MAP_FILE
148 #endif
149                        , fd, 0);
150       if (result == (void *) -1)
151         result = NULL;
152       else
153         *sizep = st.st_size;
154     }
155   __close (fd);
156   return result;
157 }
158
159 void
160 _dl_sysdep_fatal (const char *msg, ...)
161 {
162   va_list ap;
163
164   va_start (ap, msg);
165   do
166     {
167       size_t len = strlen (msg);
168       __write (STDERR_FILENO, msg, len);
169       msg = va_arg (ap, const char *);
170     } while (msg);
171   va_end (ap);
172
173   _exit (127);
174 }
175
176
177 void
178 _dl_sysdep_message (const char *msg, ...)
179 {
180   va_list ap;
181
182   va_start (ap, msg);
183   do
184     {
185       size_t len = strlen (msg);
186       __write (STDOUT_FILENO, msg, len);
187       msg = va_arg (ap, const char *);
188     } while (msg);
189   va_end (ap);
190 }