UnixPageAllocator.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. using MonoMod.Utils;
  5. namespace BepInEx.IL2CPP.Allocator
  6. {
  7. /// <summary>
  8. /// Based on https://github.com/kubo/funchook
  9. /// </summary>
  10. internal abstract class UnixPageAllocator : PageAllocator
  11. {
  12. protected abstract IMemoryMapper OpenMemoryMap();
  13. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  14. private static bool CheckFreeRegionBefore(IntPtr start, IntPtr hint, IntPtr[] result)
  15. {
  16. if (start.ToInt64() < hint.ToInt64())
  17. {
  18. var addr = start - PAGE_SIZE;
  19. if (hint.ToInt64() - addr.ToInt64() < int.MaxValue)
  20. result[0] = addr;
  21. }
  22. return false;
  23. }
  24. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  25. private static bool CheckFreeRegionAfter(IntPtr end, IntPtr hint, IntPtr[] result)
  26. {
  27. if (hint.ToInt64() < end.ToInt64())
  28. {
  29. if (end.ToInt64() - hint.ToInt64() < int.MaxValue)
  30. result[1] = end;
  31. return true;
  32. }
  33. return false;
  34. }
  35. private IntPtr[] GetFreeAddresses(IntPtr hint)
  36. {
  37. var result = new IntPtr[2];
  38. var prevEnd = IntPtr.Zero;
  39. using var mapper = OpenMemoryMap();
  40. while (mapper.FindNextFree(out var start, out var end))
  41. {
  42. if ((prevEnd + PAGE_SIZE).ToInt64() <= start.ToInt64())
  43. if (CheckFreeRegionBefore(start, hint, result) || CheckFreeRegionAfter(prevEnd, hint, result))
  44. return result;
  45. prevEnd = end;
  46. }
  47. if (CheckFreeRegionAfter(prevEnd, hint, result))
  48. return result;
  49. throw new PageAllocatorException($"Could not find free region near {hint.ToInt64():X8}");
  50. }
  51. public override IntPtr Allocate(IntPtr hint)
  52. {
  53. throw new NotImplementedException();
  54. }
  55. public override void Free(IntPtr page)
  56. {
  57. throw new NotImplementedException();
  58. }
  59. protected interface IMemoryMapper: IDisposable
  60. {
  61. bool FindNextFree(out IntPtr start, out IntPtr end);
  62. }
  63. }
  64. }