diff options
| author | 2023-10-11 11:13:19 -0400 | |
|---|---|---|
| committer | 2023-10-11 11:13:19 -0400 | |
| commit | 7b5d234558f20fc1fb1efe6b1f42982125f232bc (patch) | |
| tree | d2ba595ac08eeeff81ba44376f62d6ffbc0af5da | |
| parent | Merge pull request #11734 from Kelebek1/device_local_buffer_alloc (diff) | |
| download | yuzu-7b5d234558f20fc1fb1efe6b1f42982125f232bc.tar.gz yuzu-7b5d234558f20fc1fb1efe6b1f42982125f232bc.tar.xz yuzu-7b5d234558f20fc1fb1efe6b1f42982125f232bc.zip | |
jit: add support for relr-type relocations
| -rw-r--r-- | src/common/elf.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/jit/jit_context.cpp | 36 |
2 files changed, 42 insertions, 2 deletions
diff --git a/src/common/elf.h b/src/common/elf.h index 14a5e9597..0b728dc54 100644 --- a/src/common/elf.h +++ b/src/common/elf.h | |||
| @@ -211,6 +211,11 @@ struct Elf64_Rela { | |||
| 211 | Elf64_Sxword r_addend; /* Addend */ | 211 | Elf64_Sxword r_addend; /* Addend */ |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | /* RELR relocation table entry */ | ||
| 215 | |||
| 216 | using Elf32_Relr = Elf32_Word; | ||
| 217 | using Elf64_Relr = Elf64_Xword; | ||
| 218 | |||
| 214 | /* How to extract and insert information held in the r_info field. */ | 219 | /* How to extract and insert information held in the r_info field. */ |
| 215 | 220 | ||
| 216 | static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { | 221 | static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { |
| @@ -328,6 +333,9 @@ constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */ | |||
| 328 | constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ | 333 | constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ |
| 329 | constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ | 334 | constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ |
| 330 | constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ | 335 | constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ |
| 336 | constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */ | ||
| 337 | constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */ | ||
| 338 | constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */ | ||
| 331 | 339 | ||
| 332 | } // namespace ELF | 340 | } // namespace ELF |
| 333 | } // namespace Common | 341 | } // namespace Common |
diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 4ed3f02e2..0090e8568 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp | |||
| @@ -156,6 +156,8 @@ public: | |||
| 156 | 156 | ||
| 157 | bool LoadNRO(std::span<const u8> data) { | 157 | bool LoadNRO(std::span<const u8> data) { |
| 158 | local_memory.clear(); | 158 | local_memory.clear(); |
| 159 | |||
| 160 | relocbase = local_memory.size(); | ||
| 159 | local_memory.insert(local_memory.end(), data.begin(), data.end()); | 161 | local_memory.insert(local_memory.end(), data.begin(), data.end()); |
| 160 | 162 | ||
| 161 | if (FixupRelocations()) { | 163 | if (FixupRelocations()) { |
| @@ -181,8 +183,8 @@ public: | |||
| 181 | // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html | 183 | // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html |
| 182 | // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html | 184 | // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html |
| 183 | VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; | 185 | VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; |
| 184 | VAddr rela_dyn = 0; | 186 | VAddr rela_dyn = 0, relr_dyn = 0; |
| 185 | size_t num_rela = 0; | 187 | size_t num_rela = 0, num_relr = 0; |
| 186 | while (true) { | 188 | while (true) { |
| 187 | const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)}; | 189 | const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)}; |
| 188 | dynamic_offset += sizeof(Elf64_Dyn); | 190 | dynamic_offset += sizeof(Elf64_Dyn); |
| @@ -196,6 +198,12 @@ public: | |||
| 196 | if (dyn.d_tag == ElfDtRelasz) { | 198 | if (dyn.d_tag == ElfDtRelasz) { |
| 197 | num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela); | 199 | num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela); |
| 198 | } | 200 | } |
| 201 | if (dyn.d_tag == ElfDtRelr) { | ||
| 202 | relr_dyn = dyn.d_un.d_ptr; | ||
| 203 | } | ||
| 204 | if (dyn.d_tag == ElfDtRelrsz) { | ||
| 205 | num_relr = dyn.d_un.d_val / sizeof(Elf64_Relr); | ||
| 206 | } | ||
| 199 | } | 207 | } |
| 200 | 208 | ||
| 201 | for (size_t i = 0; i < num_rela; i++) { | 209 | for (size_t i = 0; i < num_rela; i++) { |
| @@ -207,6 +215,29 @@ public: | |||
| 207 | callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend); | 215 | callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend); |
| 208 | } | 216 | } |
| 209 | 217 | ||
| 218 | VAddr relr_where = 0; | ||
| 219 | for (size_t i = 0; i < num_relr; i++) { | ||
| 220 | const auto relr{callbacks->ReadMemory<Elf64_Relr>(relr_dyn + i * sizeof(Elf64_Relr))}; | ||
| 221 | const auto incr{[&](VAddr where) { | ||
| 222 | callbacks->MemoryWrite64(where, callbacks->MemoryRead64(where) + relocbase); | ||
| 223 | }}; | ||
| 224 | |||
| 225 | if ((relr & 1) == 0) { | ||
| 226 | // where pointer | ||
| 227 | relr_where = relocbase + relr; | ||
| 228 | incr(relr_where); | ||
| 229 | relr_where += sizeof(Elf64_Addr); | ||
| 230 | } else { | ||
| 231 | // bitmap | ||
| 232 | for (int bit = 1; bit < 64; bit++) { | ||
| 233 | if ((relr & (1ULL << bit)) != 0) { | ||
| 234 | incr(relr_where + i * sizeof(Elf64_Addr)); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | relr_where += 63 * sizeof(Elf64_Addr); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 210 | return true; | 241 | return true; |
| 211 | } | 242 | } |
| 212 | 243 | ||
| @@ -313,6 +344,7 @@ public: | |||
| 313 | Core::Memory::Memory& memory; | 344 | Core::Memory::Memory& memory; |
| 314 | VAddr top_of_stack; | 345 | VAddr top_of_stack; |
| 315 | VAddr heap_pointer; | 346 | VAddr heap_pointer; |
| 347 | VAddr relocbase; | ||
| 316 | }; | 348 | }; |
| 317 | 349 | ||
| 318 | void DynarmicCallbacks64::CallSVC(u32 swi) { | 350 | void DynarmicCallbacks64::CallSVC(u32 swi) { |