Executable.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using ChocolArm64.Memory;
  2. using Ryujinx.HLE.HOS;
  3. using Ryujinx.HLE.HOS.Kernel;
  4. using Ryujinx.HLE.Loaders.Executables;
  5. using Ryujinx.HLE.Utilities;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.IO;
  10. using System.Linq;
  11. namespace Ryujinx.HLE.Loaders
  12. {
  13. class Executable
  14. {
  15. private AMemory Memory;
  16. private List<ElfDyn> Dynamic;
  17. public ReadOnlyCollection<ElfSym> SymbolTable;
  18. public string Name { get; private set; }
  19. public string FilePath { get; private set; }
  20. public long ImageBase { get; private set; }
  21. public long ImageEnd { get; private set; }
  22. private KMemoryManager MemoryManager;
  23. public Executable(IExecutable Exe, KMemoryManager MemoryManager, AMemory Memory, long ImageBase)
  24. {
  25. Dynamic = new List<ElfDyn>();
  26. FilePath = Exe.FilePath;
  27. if (FilePath != null)
  28. {
  29. Name = Path.GetFileNameWithoutExtension(FilePath.Replace(Homebrew.TemporaryNroSuffix, ""));
  30. }
  31. this.Memory = Memory;
  32. this.MemoryManager = MemoryManager;
  33. this.ImageBase = ImageBase;
  34. this.ImageEnd = ImageBase;
  35. long TextPosition = ImageBase + (uint)Exe.TextOffset;
  36. long ROPosition = ImageBase + (uint)Exe.ROOffset;
  37. long DataPosition = ImageBase + (uint)Exe.DataOffset;
  38. long TextSize = (uint)IntUtils.AlignUp(Exe.Text.Length, KMemoryManager.PageSize);
  39. long ROSize = (uint)IntUtils.AlignUp(Exe.RO.Length, KMemoryManager.PageSize);
  40. long DataSize = (uint)IntUtils.AlignUp(Exe.Data.Length, KMemoryManager.PageSize);
  41. long DataAndBssSize = (uint)IntUtils.AlignUp(Exe.BssSize, KMemoryManager.PageSize) + DataSize;
  42. ImageEnd = DataPosition + DataAndBssSize;
  43. MemoryManager.HleMapProcessCode(TextPosition, TextSize + ROSize + DataAndBssSize);
  44. MemoryManager.SetProcessMemoryPermission(ROPosition, ROSize, MemoryPermission.Read);
  45. MemoryManager.SetProcessMemoryPermission(DataPosition, DataAndBssSize, MemoryPermission.ReadAndWrite);
  46. Memory.WriteBytes(TextPosition, Exe.Text);
  47. Memory.WriteBytes(ROPosition, Exe.RO);
  48. Memory.WriteBytes(DataPosition, Exe.Data);
  49. if (Exe.Mod0Offset == 0)
  50. {
  51. return;
  52. }
  53. long Mod0Offset = ImageBase + Exe.Mod0Offset;
  54. int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0);
  55. long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
  56. long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset;
  57. long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset;
  58. long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset;
  59. long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
  60. long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;
  61. while (true)
  62. {
  63. long TagVal = Memory.ReadInt64(DynamicOffset + 0);
  64. long Value = Memory.ReadInt64(DynamicOffset + 8);
  65. DynamicOffset += 0x10;
  66. ElfDynTag Tag = (ElfDynTag)TagVal;
  67. if (Tag == ElfDynTag.DT_NULL)
  68. {
  69. break;
  70. }
  71. Dynamic.Add(new ElfDyn(Tag, Value));
  72. }
  73. long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB);
  74. long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB);
  75. long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
  76. List<ElfSym> Symbols = new List<ElfSym>();
  77. while ((ulong)SymTblAddr < (ulong)StrTblAddr)
  78. {
  79. ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr);
  80. Symbols.Add(Sym);
  81. SymTblAddr += SymEntSize;
  82. }
  83. SymbolTable = Array.AsReadOnly(Symbols.OrderBy(x => x.Value).ToArray());
  84. }
  85. private ElfRel GetRelocation(long Position)
  86. {
  87. long Offset = Memory.ReadInt64(Position + 0);
  88. long Info = Memory.ReadInt64(Position + 8);
  89. long Addend = Memory.ReadInt64(Position + 16);
  90. int RelType = (int)(Info >> 0);
  91. int SymIdx = (int)(Info >> 32);
  92. ElfSym Symbol = GetSymbol(SymIdx);
  93. return new ElfRel(Offset, Addend, Symbol, (ElfRelType)RelType);
  94. }
  95. private ElfSym GetSymbol(int Index)
  96. {
  97. long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB);
  98. long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB);
  99. long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
  100. long Position = SymTblAddr + Index * SymEntSize;
  101. return GetSymbol(Position, StrTblAddr);
  102. }
  103. private ElfSym GetSymbol(long Position, long StrTblAddr)
  104. {
  105. int NameIndex = Memory.ReadInt32(Position + 0);
  106. int Info = Memory.ReadByte(Position + 4);
  107. int Other = Memory.ReadByte(Position + 5);
  108. int SHIdx = Memory.ReadInt16(Position + 6);
  109. long Value = Memory.ReadInt64(Position + 8);
  110. long Size = Memory.ReadInt64(Position + 16);
  111. string Name = string.Empty;
  112. for (int Chr; (Chr = Memory.ReadByte(StrTblAddr + NameIndex++)) != 0;)
  113. {
  114. Name += (char)Chr;
  115. }
  116. return new ElfSym(Name, Info, Other, SHIdx, Value, Size);
  117. }
  118. private long GetFirstValue(ElfDynTag Tag)
  119. {
  120. foreach (ElfDyn Entry in Dynamic)
  121. {
  122. if (Entry.Tag == Tag)
  123. {
  124. return Entry.Value;
  125. }
  126. }
  127. return 0;
  128. }
  129. }
  130. }