1 /* Copyright (C) 2003, 2004 Red Hat, Inc.
2 Contributed by Alexandre Oliva <aoliva@redhat.com>
4 This file is part of uClibc.
6 uClibc is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 uClibc is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with uClibc; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
23 /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
25 #if DYNAMIC_LOADER_IN_SIMULATOR
26 #define __NR___syscall_mmap2 __NR_mmap2
27 static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
28 size_t, len, int, prot, int, flags, int, fd, off_t, offset)
30 /* Make sure we don't get another definition of _dl_mmap from the
31 machine-independent code. */
35 /* This is always 12, even on architectures where PAGE_SHIFT != 12. */
36 # ifndef MMAP2_PAGE_SHIFT
37 # define MMAP2_PAGE_SHIFT 12
40 #include <bits/uClibc_page.h> /* for PAGE_SIZE */
41 static __always_inline void *_dl_memset(void*,int,size_t);
42 static __always_inline ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset);
45 _dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
47 size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE;
49 /* This is a hack to enable the dynamic loader to run within a
50 simulator that doesn't support mmap, with a number of very ugly
51 tricks. Also, it's not as useful as it sounds, since only dynamic
52 executables without DT_NEEDED dependencies can be run. AFAIK, they
53 can only be created with -pie. This trick suffices to enable the
54 dynamic loader to obtain a blank page that it maps early in the
56 if ((flags & MAP_FIXED) == 0)
58 void *_dl_mmap_base = 0;
64 __asm__ ("mov sp, %0" : "=r" (stack));
65 _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE);
67 if (((void **)_dl_mmap_base)[0] == _dl_mmap_base
68 && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
69 && (((void **)_dl_mmap_base)[177]
70 == ((void **)_dl_mmap_base)[771]))
72 while (((void**)_dl_mmap_base)[177])
74 _dl_mmap_base = ((void**)_dl_mmap_base)[177];
75 if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
76 && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
77 && (((void **)_dl_mmap_base)[177]
78 == ((void**)_dl_mmap_base)[771])))
85 for (i = 0; i < (int)PAGE_SIZE; i++)
86 if (*(char*)(_dl_mmap_base + i))
90 _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE);
93 ((void**)_dl_mmap_base)[-1] =
94 ((void**)_dl_mmap_base)[0] =
95 ((void**)_dl_mmap_base)[1023] =
102 if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
103 && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
104 && (((void **)_dl_mmap_base)[177]
105 == ((void**)_dl_mmap_base)[771])))
107 ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE);
109 ((void**)_dl_mmap_base)[177] =
110 ((void**)_dl_mmap_base)[771] =
111 (char*)_dl_mmap_base + plen + PAGE_SIZE;
112 ((void**)_dl_mmap_base)[0] =
113 ((void**)_dl_mmap_base)[1023] =
117 if ((flags & MAP_ANONYMOUS) != 0)
119 _dl_memset (ret, 0, plen);
126 if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) {
128 __set_errno (EINVAL);
132 if ((flags & MAP_FIXED) != 0)
134 if (_dl_pread(fd, addr, len, offset) != (ssize_t)len)
135 return (void*)MAP_FAILED;
137 _dl_memset (addr + len, 0, plen - len);
140 return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
145 #ifdef DYNAMIC_LOADER_IN_SIMULATOR
148 #define __NR___syscall_lseek __NR_lseek
149 static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count);
151 static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset,
153 static __always_inline ssize_t
154 _dl_pread(int fd, void *buf, size_t count, off_t offset)
156 __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR);
162 if (__syscall_lseek (fd, offset, SEEK_SET) != offset)
165 ret = _dl_read (fd, buf, count);
167 if (__syscall_lseek (fd, orig, SEEK_SET) != orig)
173 #define __NR___syscall_pread __NR_pread
174 static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
175 size_t, count, off_t, offset_hi, off_t, offset_lo)
177 static __always_inline ssize_t
178 _dl_pread(int fd, void *buf, size_t count, off_t offset)
180 return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset)));
185 #ifdef __NR_sram_alloc
186 #define __NR__dl_sram_alloc __NR_sram_alloc
187 static __always_inline _syscall2(__ptr_t, _dl_sram_alloc,
188 size_t, len, unsigned long, flags)
191 #ifdef __NR_sram_free
192 #define __NR__dl_sram_free __NR_sram_free
193 static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr)
196 #ifdef __NR_dma_memcpy
197 #define __NR__dl_dma_memcpy __NR_dma_memcpy
198 static __always_inline _syscall3(__ptr_t, _dl_dma_memcpy,
199 __ptr_t, dest, __ptr_t, src, size_t, len)
202 #define __UCLIBC_MMAP_HAS_6_ARGS__