dl-syscalls.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* Copyright (C) 2003, 2004 Red Hat, Inc.
  2. Contributed by Alexandre Oliva <aoliva@redhat.com>
  3. This file is part of uClibc.
  4. uClibc is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. uClibc is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with uClibc; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  15. USA. */
  16. /* We can't use the real errno in ldso, since it has not yet
  17. * been dynamicly linked in yet. */
  18. #include "sys/syscall.h"
  19. extern int _dl_errno;
  20. #undef __set_errno
  21. #define __set_errno(X) {(_dl_errno) = (X);}
  22. #include <sys/mman.h>
  23. /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
  24. #if DYNAMIC_LOADER_IN_SIMULATOR
  25. #define __NR___syscall_mmap2 __NR_mmap2
  26. static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
  27. size_t, len, int, prot, int, flags, int, fd, off_t, offset);
  28. /* Make sure we don't get another definition of _dl_mmap from the
  29. machine-independent code. */
  30. #undef __NR_mmap
  31. #undef __NR_mmap2
  32. /* This is always 12, even on architectures where PAGE_SHIFT != 12. */
  33. # ifndef MMAP2_PAGE_SHIFT
  34. # define MMAP2_PAGE_SHIFT 12
  35. # endif
  36. #include <bits/uClibc_page.h> /* for PAGE_SIZE */
  37. inline static void *_dl_memset(void*,int,size_t);
  38. inline static ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset);
  39. static __ptr_t
  40. _dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
  41. {
  42. size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE;
  43. /* This is a hack to enable the dynamic loader to run within a
  44. simulator that doesn't support mmap, with a number of very ugly
  45. tricks. Also, it's not as useful as it sounds, since only dynamic
  46. executables without DT_NEEDED dependencies can be run. AFAIK, they
  47. can only be created with -pie. This trick suffices to enable the
  48. dynamic loader to obtain a blank page that it maps early in the
  49. bootstrap. */
  50. if ((flags & MAP_FIXED) == 0)
  51. {
  52. void *_dl_mmap_base = 0;
  53. __ptr_t *ret = 0;
  54. if (! _dl_mmap_base)
  55. {
  56. void *stack;
  57. __asm__ ("mov sp, %0" : "=r" (stack));
  58. _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE);
  59. retry:
  60. if (((void **)_dl_mmap_base)[0] == _dl_mmap_base
  61. && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
  62. && (((void **)_dl_mmap_base)[177]
  63. == ((void **)_dl_mmap_base)[771]))
  64. {
  65. while (((void**)_dl_mmap_base)[177])
  66. {
  67. _dl_mmap_base = ((void**)_dl_mmap_base)[177];
  68. if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
  69. && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
  70. && (((void **)_dl_mmap_base)[177]
  71. == ((void**)_dl_mmap_base)[771])))
  72. ((void(*)())0)();
  73. }
  74. }
  75. else
  76. {
  77. int i;
  78. for (i = 0; i < (int)PAGE_SIZE; i++)
  79. if (*(char*)(_dl_mmap_base + i))
  80. break;
  81. if (i != PAGE_SIZE)
  82. {
  83. _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE);
  84. goto retry;
  85. }
  86. ((void**)_dl_mmap_base)[-1] =
  87. ((void**)_dl_mmap_base)[0] =
  88. ((void**)_dl_mmap_base)[1023] =
  89. _dl_mmap_base;
  90. }
  91. }
  92. if (_dl_mmap_base)
  93. {
  94. if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
  95. && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
  96. && (((void **)_dl_mmap_base)[177]
  97. == ((void**)_dl_mmap_base)[771])))
  98. ((void(*)())0)();
  99. ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE);
  100. _dl_mmap_base =
  101. ((void**)_dl_mmap_base)[177] =
  102. ((void**)_dl_mmap_base)[771] =
  103. (char*)_dl_mmap_base + plen + PAGE_SIZE;
  104. ((void**)_dl_mmap_base)[0] =
  105. ((void**)_dl_mmap_base)[1023] =
  106. _dl_mmap_base;
  107. }
  108. if ((flags & MAP_ANONYMOUS) != 0)
  109. {
  110. _dl_memset (ret, 0, plen);
  111. return ret;
  112. }
  113. flags |= MAP_FIXED;
  114. addr = ret;
  115. }
  116. if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) {
  117. #if 0
  118. __set_errno (EINVAL);
  119. #endif
  120. return MAP_FAILED;
  121. }
  122. if ((flags & MAP_FIXED) != 0)
  123. {
  124. if (_dl_pread(fd, addr, len, offset) != (ssize_t)len)
  125. return (void*)MAP_FAILED;
  126. if (plen != len)
  127. _dl_memset (addr + len, 0, plen - len);
  128. return addr;
  129. }
  130. return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
  131. }
  132. #endif
  133. #ifdef __NR_pread
  134. #ifdef DYNAMIC_LOADER_IN_SIMULATOR
  135. #include <unistd.h>
  136. #define __NR___syscall_lseek __NR_lseek
  137. inline static unsigned long _dl_read(int fd, const void *buf, unsigned long count);
  138. inline static _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset,
  139. int, whence);
  140. inline static ssize_t
  141. _dl_pread(int fd, void *buf, size_t count, off_t offset)
  142. {
  143. __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR);
  144. ssize_t ret;
  145. if (orig == -1)
  146. return -1;
  147. if (__syscall_lseek (fd, offset, SEEK_SET) != offset)
  148. return -1;
  149. ret = _dl_read (fd, buf, count);
  150. if (__syscall_lseek (fd, orig, SEEK_SET) != orig)
  151. ((void(*)())0)();
  152. return ret;
  153. }
  154. #else
  155. #define __NR___syscall_pread __NR_pread
  156. inline static _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
  157. size_t, count, off_t, offset_hi, off_t, offset_lo);
  158. inline static ssize_t
  159. _dl_pread(int fd, void *buf, size_t count, off_t offset)
  160. {
  161. return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset)));
  162. }
  163. #endif
  164. #endif
  165. #ifdef __NR_sram_alloc
  166. #define __NR__dl_sram_alloc __NR_sram_alloc
  167. inline static _syscall2(__ptr_t, _dl_sram_alloc,
  168. size_t, len, unsigned long, flags);
  169. #endif
  170. #ifdef __NR_sram_free
  171. #define __NR__dl_sram_free __NR_sram_free
  172. inline static _syscall1(int, _dl_sram_free, __ptr_t, addr);
  173. #endif
  174. #ifdef __NR_dma_memcpy
  175. #define __NR__dl_dma_memcpy __NR_dma_memcpy
  176. inline static _syscall3(__ptr_t, _dl_dma_memcpy,
  177. __ptr_t, dest, __ptr_t, src, size_t, len);
  178. #endif
  179. #define __UCLIBC_MMAP_HAS_6_ARGS__