SectionMemoryManager.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //===-- SectionMemoryManager.cpp - The memory manager for MCJIT -----------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the implementation of the section-based memory manager
  11. // used by MCJIT.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/Config/config.h"
  15. #include "llvm/Support/DynamicLibrary.h"
  16. #include "SectionMemoryManager.h"
  17. #ifdef __linux__
  18. // These includes used by SectionMemoryManager::getPointerToNamedFunction()
  19. // for Glibc trickery. Look comments in this function for more information.
  20. #ifdef HAVE_SYS_STAT_H
  21. #include <sys/stat.h>
  22. #endif
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #endif
  26. namespace llvm {
  27. uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
  28. unsigned Alignment,
  29. unsigned SectionID) {
  30. if (!Alignment)
  31. Alignment = 16;
  32. uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment);
  33. AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size));
  34. return Addr;
  35. }
  36. uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size,
  37. unsigned Alignment,
  38. unsigned SectionID) {
  39. if (!Alignment)
  40. Alignment = 16;
  41. unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1);
  42. uintptr_t Addr = 0;
  43. // Look in the list of free code memory regions and use a block there if one
  44. // is available.
  45. for (int i = 0, e = FreeCodeMem.size(); i != e; ++i) {
  46. sys::MemoryBlock &MB = FreeCodeMem[i];
  47. if (MB.size() >= NeedAllocate) {
  48. Addr = (uintptr_t)MB.base();
  49. uintptr_t EndOfBlock = Addr + MB.size();
  50. // Align the address.
  51. Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
  52. // Store cutted free memory block.
  53. FreeCodeMem[i] = sys::MemoryBlock((void*)(Addr + Size),
  54. EndOfBlock - Addr - Size);
  55. return (uint8_t*)Addr;
  56. }
  57. }
  58. // No pre-allocated free block was large enough. Allocate a new memory region.
  59. sys::MemoryBlock MB = sys::Memory::AllocateRWX(NeedAllocate, 0, 0);
  60. AllocatedCodeMem.push_back(MB);
  61. Addr = (uintptr_t)MB.base();
  62. uintptr_t EndOfBlock = Addr + MB.size();
  63. // Align the address.
  64. Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
  65. // The AllocateRWX may allocate much more memory than we need. In this case,
  66. // we store the unused memory as a free memory block.
  67. unsigned FreeSize = EndOfBlock-Addr-Size;
  68. if (FreeSize > 16)
  69. FreeCodeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize));
  70. // Return aligned address
  71. return (uint8_t*)Addr;
  72. }
  73. void SectionMemoryManager::invalidateInstructionCache() {
  74. for (int i = 0, e = AllocatedCodeMem.size(); i != e; ++i)
  75. sys::Memory::InvalidateInstructionCache(AllocatedCodeMem[i].base(),
  76. AllocatedCodeMem[i].size());
  77. }
  78. void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name,
  79. bool AbortOnFailure) {
  80. #if defined(__linux__)
  81. //===--------------------------------------------------------------------===//
  82. // Function stubs that are invoked instead of certain library calls
  83. //
  84. // Force the following functions to be linked in to anything that uses the
  85. // JIT. This is a hack designed to work around the all-too-clever Glibc
  86. // strategy of making these functions work differently when inlined vs. when
  87. // not inlined, and hiding their real definitions in a separate archive file
  88. // that the dynamic linker can't see. For more info, search for
  89. // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
  90. if (Name == "stat") return (void*)(intptr_t)&stat;
  91. if (Name == "fstat") return (void*)(intptr_t)&fstat;
  92. if (Name == "lstat") return (void*)(intptr_t)&lstat;
  93. if (Name == "stat64") return (void*)(intptr_t)&stat64;
  94. if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
  95. if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
  96. if (Name == "atexit") return (void*)(intptr_t)&atexit;
  97. if (Name == "mknod") return (void*)(intptr_t)&mknod;
  98. #endif // __linux__
  99. const char *NameStr = Name.c_str();
  100. void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
  101. if (Ptr) return Ptr;
  102. // If it wasn't found and if it starts with an underscore ('_') character,
  103. // try again without the underscore.
  104. if (NameStr[0] == '_') {
  105. Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
  106. if (Ptr) return Ptr;
  107. }
  108. if (AbortOnFailure)
  109. report_fatal_error("Program used external function '" + Name +
  110. "' which could not be resolved!");
  111. return 0;
  112. }
  113. SectionMemoryManager::~SectionMemoryManager() {
  114. for (unsigned i = 0, e = AllocatedCodeMem.size(); i != e; ++i)
  115. sys::Memory::ReleaseRWX(AllocatedCodeMem[i]);
  116. for (unsigned i = 0, e = AllocatedDataMem.size(); i != e; ++i)
  117. free(AllocatedDataMem[i].base());
  118. }
  119. } // namespace llvm