dl-sysdep.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* Copyright (C) 2003, 2004 Red Hat, Inc.
  2. Contributed by Alexandre Oliva <aoliva@redhat.com>
  3. Based on ../i386/dl-sysdep.h
  4. This file is part of uClibc.
  5. uClibc is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU Lesser General Public License as
  7. published by the Free Software Foundation; either version 2.1 of the
  8. License, or (at your option) any later version.
  9. uClibc is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with uClibc; see the file COPYING.LIB. If not, write to
  15. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  16. USA. */
  17. /*
  18. * Various assembly language/system dependent hacks that are required
  19. * so that we can minimize the amount of platform specific code.
  20. */
  21. /*
  22. * Define this if the system uses RELOCA.
  23. */
  24. #undef ELF_USES_RELOCA
  25. /* JMPREL relocs are inside the DT_RELA table. */
  26. #define ELF_MACHINE_PLTREL_OVERLAP
  27. #define DL_NO_COPY_RELOCS
  28. #define HAVE_DL_INLINES_H
  29. /*
  30. * Initialization sequence for a GOT. Copy the resolver function
  31. * descriptor and the pointer to the elf_resolve/link_map data
  32. * structure. Initialize the got_value in the module while at that.
  33. */
  34. #define INIT_GOT(GOT_BASE,MODULE) \
  35. { \
  36. (MODULE)->loadaddr.got_value = (GOT_BASE); \
  37. GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \
  38. GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \
  39. GOT_BASE[2] = (unsigned long) MODULE; \
  40. }
  41. /* Here we define the magic numbers that this dynamic loader should accept */
  42. #define MAGIC1 EM_BLACKFIN
  43. #undef MAGIC2
  44. /* Used for error messages */
  45. #define ELF_TARGET "BFIN"
  46. struct elf_resolve;
  47. struct funcdesc_value
  48. {
  49. void *entry_point;
  50. void *got_value;
  51. } __attribute__((__aligned__(8)));
  52. extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
  53. /* 4KiB page alignment. Should perhaps be made dynamic using
  54. getpagesize(), based on AT_PAGESZ from auxvt? */
  55. #define PAGE_ALIGN 0xfffff000
  56. #define ADDR_ALIGN 0xfff
  57. #define OFFS_ALIGN 0x7ffff000
  58. struct funcdesc_ht;
  59. #undef SEND_EARLY_STDERR
  60. #define SEND_EARLY_STDERR(S) \
  61. do { \
  62. static const char __attribute__((section(".text"))) __s[] = (S); \
  63. const char *__p, *__scratch; \
  64. __asm__ ("call 1f;\n1:\n\t" \
  65. "%1 = RETS;\n\t" \
  66. "%0 = [%3 + 1b@GOT17M4];\n\t" \
  67. "%1 = %1 - %0;\n\t" \
  68. "%1 = %1 + %2;\n\t" \
  69. : "=&d" (__scratch), "=&d" (__p) \
  70. : "d" (__s), "a" (dl_boot_got_pointer) : "RETS"); \
  71. SEND_STDERR (__p); \
  72. { int __t; \
  73. for (__t = 0; __t < 0x1000000; __t++) __asm__ __volatile__ (""); } \
  74. } while (0)
  75. #define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr
  76. #define DL_RELOC_ADDR(LOADADDR, ADDR) \
  77. ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
  78. #define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \
  79. ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value))
  80. #define _dl_stabilize_funcdesc(val) \
  81. ({ __asm__ ("" : "+m" (*(val))); (val); })
  82. #define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
  83. ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \
  84. void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \
  85. (* SIGNATURE pf)(__VA_ARGS__); })
  86. #define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
  87. (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \
  88. dl_boot_ldsomap ?: dl_boot_progmap))
  89. #define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
  90. (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap))
  91. #define DL_INIT_LOADADDR_EXTRA_DECLS \
  92. int dl_init_loadaddr_load_count;
  93. #define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
  94. (dl_init_loadaddr_load_count = \
  95. __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
  96. #define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
  97. (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
  98. dl_init_loadaddr_load_count))
  99. #define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
  100. (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
  101. #define DL_LIB_UNMAP(LIB, LEN) \
  102. (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht))
  103. #define DL_LOADADDR_BASE(LOADADDR) \
  104. ((LOADADDR).got_value)
  105. /* This is called from dladdr(), such that we map a function
  106. descriptor's address to the function's entry point before trying to
  107. find in which library it's defined. */
  108. #define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS))
  109. #define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
  110. (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
  111. /*
  112. * Compute the GOT address. On several platforms, we use assembly
  113. * here. on FR-V FDPIC, there's no way to compute the GOT address,
  114. * since the offset between text and data is not fixed, so we arrange
  115. * for the assembly _dl_boot to pass this value as an argument to
  116. * _dl_boot. */
  117. #define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer)
  118. #define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
  119. ((dpnt) = dl_boot_ldso_dyn_pointer)
  120. /* We only support loading FDPIC independently-relocatable shared
  121. libraries. It probably wouldn't be too hard to support loading
  122. shared libraries that require relocation by the same amount, but we
  123. don't know that they exist or would be useful, and the dynamic
  124. loader code could leak the whole-library map unless we keeping a
  125. bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's
  126. keep things simple for now. */
  127. #define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
  128. do \
  129. { \
  130. if (((epnt)->e_flags & EF_BFIN_FDPIC) && ! ((epnt)->e_flags & EF_BFIN_PIC)) \
  131. (piclib) = 2; \
  132. else \
  133. { \
  134. _dl_internal_error_number = LD_ERROR_NOTDYN; \
  135. _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \
  136. "\n", (_dl_progname), (libname)); \
  137. _dl_close(infile); \
  138. return NULL; \
  139. } \
  140. \
  141. } \
  142. while (0)
  143. /* We want want to apply all relocations in the interpreter during
  144. bootstrap. Because of this, we have to skip the interpreter
  145. relocations in _dl_parse_relocation_information(), see
  146. elfinterp.c. */
  147. #define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
  148. #ifdef __NR_pread
  149. #define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
  150. (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
  151. #endif
  152. /* We want to return to dlsym() a function descriptor if the symbol
  153. turns out to be a function. */
  154. #define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \
  155. (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \
  156. && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \
  157. ? _dl_funcdesc_for ((void *)DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value), \
  158. (TPNT)->loadaddr.got_value) \
  159. : DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value))
  160. #define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) \
  161. __dl_is_special_segment(EPNT, PPNT)
  162. #define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \
  163. __dl_map_segment (EPNT, PPNT, INFILE, FLAGS)
  164. #define DL_GET_READY_TO_RUN_EXTRA_PARMS \
  165. , struct elf32_fdpic_loadmap *dl_boot_progmap, Elf32_Addr dl_boot_got_pointer
  166. #define DL_GET_READY_TO_RUN_EXTRA_ARGS \
  167. , dl_boot_progmap, dl_boot_got_pointer
  168. #ifdef __USE_GNU
  169. # include <link.h>
  170. #else
  171. # define __USE_GNU
  172. # include <link.h>
  173. # undef __USE_GNU
  174. #endif
  175. #include <elf.h>
  176. static __inline__ void
  177. elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
  178. Elf32_Word relative_count)
  179. {
  180. #if 0
  181. Elf32_Rel * rpnt = (void *) rel_addr;
  182. --rpnt;
  183. do {
  184. Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
  185. *reloc_addr = DL_RELOC_ADDR (load_off, *reloc_addr);
  186. } while (--relative_count);
  187. #endif
  188. }