dl-inlines.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* Copyright (C) 2003, 2004 Red Hat, Inc.
  2. * Contributed by Alexandre Oliva <aoliva@redhat.com>
  3. * Copyright (C) 2006-2011 Analog Devices, Inc.
  4. *
  5. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  6. */
  7. #include <bfin_sram.h>
  8. #define __dl_loadaddr_unmap __dl_loadaddr_unmap
  9. #include "../fdpic/dl-inlines.h"
  10. void
  11. __dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr,
  12. struct funcdesc_ht *funcdesc_ht)
  13. {
  14. int i;
  15. for (i = 0; i < loadaddr.map->nsegs; i++)
  16. {
  17. struct elf32_fdpic_loadseg *segdata;
  18. ssize_t offs;
  19. segdata = loadaddr.map->segs + i;
  20. /* FIXME:
  21. A more cleaner way is to add type for struct elf32_fdpic_loadseg,
  22. and release the memory according to the type.
  23. Currently, we hardcode the memory address of L1 SRAM. */
  24. if ((segdata->addr & 0xff800000) == 0xff800000)
  25. {
  26. _dl_sram_free ((void *)segdata->addr);
  27. continue;
  28. }
  29. offs = (segdata->p_vaddr & ADDR_ALIGN);
  30. _dl_munmap ((void*)segdata->addr - offs,
  31. segdata->p_memsz + offs);
  32. }
  33. /* _dl_unmap is only called for dlopen()ed libraries, for which
  34. calling free() is safe, or before we've completed the initial
  35. relocation, in which case calling free() is probably pointless,
  36. but still safe. */
  37. _dl_free (loadaddr.map);
  38. if (funcdesc_ht)
  39. htab_delete (funcdesc_ht);
  40. }
  41. static __always_inline int
  42. __dl_is_special_segment (Elf32_Ehdr *epnt,
  43. Elf32_Phdr *ppnt)
  44. {
  45. if (ppnt->p_type != PT_LOAD)
  46. return 0;
  47. if ((epnt->e_flags & EF_BFIN_CODE_IN_L1)
  48. && !(ppnt->p_flags & PF_W)
  49. && (ppnt->p_flags & PF_X))
  50. return 1;
  51. if ((epnt->e_flags & EF_BFIN_DATA_IN_L1)
  52. && (ppnt->p_flags & PF_W)
  53. && !(ppnt->p_flags & PF_X))
  54. return 1;
  55. /* 0xfeb00000, 0xfec00000, 0xff700000, 0xff800000, 0xff900000,
  56. and 0xffa00000 are also used in GNU ld and linux kernel.
  57. They need to be kept synchronized. */
  58. if (ppnt->p_vaddr == 0xff700000
  59. || ppnt->p_vaddr == 0xff800000
  60. || ppnt->p_vaddr == 0xff900000
  61. || ppnt->p_vaddr == 0xffa00000
  62. || ppnt->p_vaddr == 0xfeb00000
  63. || ppnt->p_vaddr == 0xfec00000)
  64. return 1;
  65. return 0;
  66. }
  67. static __always_inline char *
  68. __dl_map_segment (Elf32_Ehdr *epnt,
  69. Elf32_Phdr *ppnt,
  70. int infile,
  71. int flags)
  72. {
  73. char *status, *tryaddr, *addr;
  74. size_t size;
  75. if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000)
  76. && !(ppnt->p_flags & PF_W)
  77. && (ppnt->p_flags & PF_X)) {
  78. status = (char *) _dl_mmap
  79. (tryaddr = 0,
  80. size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz,
  81. LXFLAGS(ppnt->p_flags),
  82. flags | MAP_EXECUTABLE | MAP_DENYWRITE,
  83. infile, ppnt->p_offset & OFFS_ALIGN);
  84. if (_dl_mmap_check_error(status)
  85. || (tryaddr && tryaddr != status))
  86. return NULL;
  87. addr = (char *) _dl_sram_alloc (ppnt->p_filesz, L1_INST_SRAM);
  88. if (addr != NULL)
  89. _dl_dma_memcpy (addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz);
  90. _dl_munmap (status, size);
  91. if (addr == NULL)
  92. _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__);
  93. return addr;
  94. }
  95. if (((epnt->e_flags & EF_BFIN_DATA_IN_L1)
  96. || ppnt->p_vaddr == 0xff700000
  97. || ppnt->p_vaddr == 0xff800000
  98. || ppnt->p_vaddr == 0xff900000)
  99. && (ppnt->p_flags & PF_W)
  100. && !(ppnt->p_flags & PF_X)) {
  101. if (ppnt->p_vaddr == 0xff800000)
  102. addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_A_SRAM);
  103. else if (ppnt->p_vaddr == 0xff900000)
  104. addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_B_SRAM);
  105. else
  106. addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_SRAM);
  107. if (addr == NULL) {
  108. _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__);
  109. } else {
  110. if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
  111. _dl_sram_free (addr);
  112. return NULL;
  113. }
  114. if (ppnt->p_filesz < ppnt->p_memsz)
  115. _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
  116. }
  117. return addr;
  118. }
  119. if (ppnt->p_vaddr == 0xfeb00000
  120. || ppnt->p_vaddr == 0xfec00000) {
  121. addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L2_SRAM);
  122. if (addr == NULL) {
  123. _dl_dprintf(2, "%s:%i: L2 allocation failed\n", _dl_progname, __LINE__);
  124. } else {
  125. if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
  126. _dl_sram_free (addr);
  127. return NULL;
  128. }
  129. if (ppnt->p_filesz < ppnt->p_memsz)
  130. _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
  131. }
  132. return addr;
  133. }
  134. return 0;
  135. }