dl-inlines.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Copyright (C) 2010 Texas Instruments Incorporated
  2. * Contributed by Mark Salter <msalter@redhat.com>
  3. *
  4. * Borrowed heavily from frv arch:
  5. * Copyright (C) 2003, 2004 Red Hat, Inc.
  6. *
  7. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  8. */
  9. /* Figure out whether the given address is in one of the mapped
  10. segments. */
  11. static __always_inline int
  12. __dl_addr_in_loadaddr (void *p, struct elf32_dsbt_loadaddr loadaddr)
  13. {
  14. struct elf32_dsbt_loadmap *map = loadaddr.map;
  15. int c;
  16. for (c = 0; c < map->nsegs; c++)
  17. if ((void*)map->segs[c].addr <= p
  18. && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz)
  19. return 1;
  20. return 0;
  21. }
  22. /* Figure out how many LOAD segments there are in the given headers,
  23. and allocate a block for the load map big enough for them.
  24. got_value will be properly initialized later on, with INIT_GOT. */
  25. static __always_inline int
  26. __dl_init_loadaddr (struct elf32_dsbt_loadaddr *loadaddr, Elf32_Phdr *ppnt,
  27. int pcnt)
  28. {
  29. int count = 0, i;
  30. size_t size;
  31. for (i = 0; i < pcnt; i++)
  32. if (ppnt[i].p_type == PT_LOAD)
  33. count++;
  34. size = sizeof (struct elf32_dsbt_loadmap)
  35. + sizeof (struct elf32_dsbt_loadseg) * count;
  36. loadaddr->map = _dl_malloc (size);
  37. if (! loadaddr->map)
  38. _dl_exit (-1);
  39. loadaddr->map->version = 0;
  40. loadaddr->map->nsegs = 0;
  41. return count;
  42. }
  43. /* Incrementally initialize a load map. */
  44. static __always_inline void
  45. __dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
  46. Elf32_Phdr *phdr, int maxsegs)
  47. {
  48. struct elf32_dsbt_loadseg *segdata;
  49. if (loadaddr.map->nsegs == maxsegs)
  50. _dl_exit (-1);
  51. segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
  52. segdata->addr = (Elf32_Addr) addr;
  53. segdata->p_vaddr = phdr->p_vaddr;
  54. segdata->p_memsz = phdr->p_memsz;
  55. #if defined (__SUPPORT_LD_DEBUG__)
  56. {
  57. if (_dl_debug)
  58. _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
  59. loadaddr.map->nsegs-1,
  60. segdata->p_vaddr, segdata->addr, segdata->p_memsz);
  61. }
  62. #endif
  63. }
  64. /* Replace an existing entry in the load map. */
  65. static __always_inline void
  66. __dl_update_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
  67. Elf32_Phdr *phdr)
  68. {
  69. struct elf32_dsbt_loadseg *segdata;
  70. void *oldaddr;
  71. int i;
  72. for (i = 0; i < loadaddr.map->nsegs; i++)
  73. if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
  74. && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
  75. break;
  76. if (i == loadaddr.map->nsegs)
  77. _dl_exit (-1);
  78. segdata = loadaddr.map->segs + i;
  79. oldaddr = (void *)segdata->addr;
  80. _dl_munmap (oldaddr, segdata->p_memsz);
  81. segdata->addr = (Elf32_Addr) addr;
  82. #if defined (__SUPPORT_LD_DEBUG__)
  83. if (_dl_debug)
  84. _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
  85. loadaddr.map->nsegs-1,
  86. segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
  87. #endif
  88. }
  89. static __always_inline void
  90. __dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
  91. {
  92. int i;
  93. for (i = 0; i < loadaddr.map->nsegs; i++)
  94. _dl_munmap ((void*)loadaddr.map->segs[i].addr,
  95. loadaddr.map->segs[i].p_memsz);
  96. /* _dl_unmap is only called for dlopen()ed libraries, for which
  97. calling free() is safe, or before we've completed the initial
  98. relocation, in which case calling free() is probably pointless,
  99. but still safe. */
  100. _dl_free (loadaddr.map);
  101. }