From b6e7c228f22a712bc1eaad9b2b3287096c6d380d Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 2 Apr 2024 13:53:14 -0400 Subject: [PATCH] GP-4380: Adding support for dyld_cache_slide_info5 --- .../macho/dyld/DyldCacheSlideInfo3.java | 2 +- .../macho/dyld/DyldCacheSlideInfo5.java | 166 +++++++++ .../macho/dyld/DyldCacheSlideInfoCommon.java | 2 + .../bin/format/macho/dyld/DyldChainedPtr.java | 323 ++++++------------ 4 files changed, 276 insertions(+), 217 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo5.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo3.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo3.java index db60d3819f..d20096a458 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo3.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo3.java @@ -112,7 +112,7 @@ public class DyldCacheSlideInfo3 extends DyldCacheSlideInfoCommon { } /** - * Walks the pointer chain at the given reader offset to find necessary {@link DyldFixup}s + * Walks the pointer chain at the given reader offset to find necessary {@link DyldFixup}s * * @param segmentOffset The segment offset * @param pageOffset The page offset diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo5.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo5.java new file mode 100644 index 0000000000..2bfb271ace --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfo5.java @@ -0,0 +1,166 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.util.bin.format.macho.dyld; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import ghidra.app.util.bin.BinaryReader; +import ghidra.app.util.bin.format.macho.MachConstants; +import ghidra.app.util.bin.format.macho.dyld.DyldChainedPtr.DyldChainType; +import ghidra.app.util.importer.MessageLog; +import ghidra.program.model.data.*; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.DuplicateNameException; +import ghidra.util.task.TaskMonitor; + +/** + * Represents a dyld_cache_slide_info5 structure. + *

+ * Seen in macOS 14.4 and later. + */ +public class DyldCacheSlideInfo5 extends DyldCacheSlideInfoCommon { + + private static final int DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE = 0xFFFF; + private static final DyldChainType TYPE = DyldChainType.DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE; + + private int pageSize; + private int pageStartsCount; + private long valueAdd; + private short[] pageStarts; + + /** + * {@return The page size} + */ + public int getPageSize() { + return pageSize; + } + + /** + * {@return The page starts count} + */ + public int getPageStartsCount() { + return pageStartsCount; + } + + /** + * {@return The "value add"} + */ + public long getValueAdd() { + return valueAdd; + } + + /** + * {@return The page starts array} + */ + public short[] getPageStarts() { + return pageStarts; + } + + /** + * Create a new {@link DyldCacheSlideInfo5}. + * + * @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 5 + * @param mappingAddress The base address of where the slide fixups will take place + * @param mappingSize The size of the slide fixups block + * @param mappingFileOffset The base file offset of where the slide fixups will take place + * @throws IOException if there was an IO-related problem creating the DYLD slide info 5 + */ + public DyldCacheSlideInfo5(BinaryReader reader, long mappingAddress, long mappingSize, + long mappingFileOffset) throws IOException { + super(reader, mappingAddress, mappingSize, mappingFileOffset); + pageSize = reader.readNextInt(); + pageStartsCount = reader.readNextInt(); + reader.readNextInt(); // padding + valueAdd = reader.readNextLong(); + pageStarts = reader.readNextShortArray(pageStartsCount); + } + + @Override + public List getSlideFixups(BinaryReader reader, int pointerSize, MessageLog log, + TaskMonitor monitor) throws IOException, CancelledException { + List fixups = new ArrayList<>(); + + monitor.initialize(pageStartsCount, "Getting DYLD Cache V5 slide fixups..."); + for (int index = 0; index < pageStartsCount; index++) { + monitor.increment(); + + long segmentOffset = pageSize * index; + + int pageEntry = Short.toUnsignedInt(pageStarts[index]); + if (pageEntry == DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE) { + continue; + } + + long pageOffset = (pageEntry / 8) * 8; // first entry byte based; + fixups.addAll(processPointerChain(segmentOffset, pageOffset, reader, monitor)); + } + + return fixups; + } + + /** + * Walks the pointer chain at the given reader offset to find necessary {@link DyldFixup}s + * + * @param segmentOffset The segment offset + * @param pageOffset The page offset + * @param reader A reader positioned at the start of the segment to fix + * @param monitor A cancellable monitor + * @return A {@link List} of {@link DyldFixup}s + * @throws IOException If an IO-related error occurred + * @throws CancelledException If the user cancelled the operation + */ + private List processPointerChain(long segmentOffset, long pageOffset, + BinaryReader reader, TaskMonitor monitor) throws IOException, CancelledException { + + List fixups = new ArrayList<>(1024); + + int size = DyldChainedPtr.getSize(TYPE); + long stride = DyldChainedPtr.getStride(TYPE); + + for (long delta = -1; delta != 0; pageOffset += delta * stride) { + monitor.checkCancelled(); + + long dataOffset = segmentOffset + pageOffset; + long chainValue = DyldChainedPtr.getChainValue(reader, dataOffset, TYPE); + long newPtrValue = DyldChainedPtr.getTarget(TYPE, chainValue) + valueAdd; + delta = DyldChainedPtr.getNext(TYPE, chainValue); + + if (!DyldChainedPtr.isAuthenticated(TYPE, chainValue)) { + long high8 = (chainValue >>> 34) & 0xff; + newPtrValue |= high8 << 56; + } + + fixups.add(new DyldFixup(dataOffset, newPtrValue, size, null, null)); + } + + return fixups; + } + + @Override + public DataType toDataType() throws DuplicateNameException, IOException { + StructureDataType struct = new StructureDataType("dyld_cache_slide_info5", 0); + struct.add(DWORD, "version", "currently 5"); + struct.add(DWORD, "page_size", "currently 4096 (may also be 16384)"); + struct.add(DWORD, "page_starts_count", ""); + struct.add(DWORD, "pad", ""); + struct.add(QWORD, "value_add", ""); + struct.add(new ArrayDataType(WORD, pageStartsCount, 1), "page_starts", ""); + struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY)); + return struct; + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfoCommon.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfoCommon.java index dac7b89fe1..13c06cd9b6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfoCommon.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheSlideInfoCommon.java @@ -81,6 +81,8 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter { mappingFileOffset); case 4 -> new DyldCacheSlideInfo4(reader, mappingAddress, mappingSize, mappingFileOffset); + case 5 -> new DyldCacheSlideInfo5(reader, mappingAddress, mappingSize, + mappingFileOffset); default -> throw new IOException(); // will be caught and version will be added to message }; monitor.incrementProgress(1); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldChainedPtr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldChainedPtr.java index c38c93ef77..e91e0f5b60 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldChainedPtr.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldChainedPtr.java @@ -18,11 +18,6 @@ package ghidra.app.util.bin.format.macho.dyld; import java.io.IOException; import ghidra.app.util.bin.BinaryReader; -import ghidra.program.model.address.Address; -import ghidra.program.model.mem.Memory; -import ghidra.program.model.mem.MemoryAccessException; -import ghidra.program.model.reloc.Relocation.Status; -import ghidra.program.model.reloc.RelocationResult; /** * @see mach-o/fixup-chains.h @@ -42,6 +37,7 @@ public class DyldChainedPtr { DYLD_CHAINED_PTR_ARM64E_FIRMWARE(10), // stride 4, unauth target is vmaddr DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE(11), // stride 1, x86_64 kernel caches DYLD_CHAINED_PTR_ARM64E_USERLAND24(12), // stride 8, unauth target is vm offset, 24-bit bind + DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE(13), // stride 8, regular/auth targets both vm offsets. Only A keys supported DYLD_CHAINED_PTR_TYPE_UNKNOWN(-1); private final int val; @@ -53,33 +49,22 @@ public class DyldChainedPtr { } public static DyldChainType lookupChainPtr(int val) { - switch (val) { - case 1: - return DYLD_CHAINED_PTR_ARM64E; - case 2: - return DYLD_CHAINED_PTR_64; - case 3: - return DYLD_CHAINED_PTR_32; - case 4: - return DYLD_CHAINED_PTR_32_CACHE; - case 5: - return DYLD_CHAINED_PTR_32_FIRMWARE; - case 6: - return DYLD_CHAINED_PTR_64_OFFSET; - case 7: - return DYLD_CHAINED_PTR_ARM64E_KERNEL; - case 8: - return DYLD_CHAINED_PTR_64_KERNEL_CACHE; - case 9: - return DYLD_CHAINED_PTR_ARM64E_USERLAND; - case 10: - return DYLD_CHAINED_PTR_ARM64E_FIRMWARE; - case 11: - return DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE; - case 12: - return DYLD_CHAINED_PTR_ARM64E_USERLAND24; - } - return DYLD_CHAINED_PTR_TYPE_UNKNOWN; + return switch (val) { + case 1 -> DYLD_CHAINED_PTR_ARM64E; + case 2 -> DYLD_CHAINED_PTR_64; + case 3 -> DYLD_CHAINED_PTR_32; + case 4 -> DYLD_CHAINED_PTR_32_CACHE; + case 5 -> DYLD_CHAINED_PTR_32_FIRMWARE; + case 6 -> DYLD_CHAINED_PTR_64_OFFSET; + case 7 -> DYLD_CHAINED_PTR_ARM64E_KERNEL; + case 8 -> DYLD_CHAINED_PTR_64_KERNEL_CACHE; + case 9 -> DYLD_CHAINED_PTR_ARM64E_USERLAND; + case 10 -> DYLD_CHAINED_PTR_ARM64E_FIRMWARE; + case 11 -> DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE; + case 12 -> DYLD_CHAINED_PTR_ARM64E_USERLAND24; + case 13 -> DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE; + default -> DYLD_CHAINED_PTR_TYPE_UNKNOWN; + }; } public int getValue() { @@ -96,84 +81,55 @@ public class DyldChainedPtr { public static final int DYLD_CHAINED_PTR_START_LAST = 0x8000; public static long getStride(DyldChainType ptrFormat) { - switch (ptrFormat) { - case DYLD_CHAINED_PTR_ARM64E: - case DYLD_CHAINED_PTR_ARM64E_USERLAND: - case DYLD_CHAINED_PTR_ARM64E_USERLAND24: - return 8; - case DYLD_CHAINED_PTR_64: - case DYLD_CHAINED_PTR_64_OFFSET: - case DYLD_CHAINED_PTR_ARM64E_KERNEL: - case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - case DYLD_CHAINED_PTR_32: - case DYLD_CHAINED_PTR_32_CACHE: - case DYLD_CHAINED_PTR_32_FIRMWARE: - return 4; - case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - return 1; - default: - return 1; - } - } - - public static int getSize(DyldChainType ptrFormat) { return switch (ptrFormat) { - case DYLD_CHAINED_PTR_ARM64E: - case DYLD_CHAINED_PTR_ARM64E_USERLAND: - case DYLD_CHAINED_PTR_ARM64E_USERLAND24: case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: case DYLD_CHAINED_PTR_ARM64E_KERNEL: case DYLD_CHAINED_PTR_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - yield 8; - case DYLD_CHAINED_PTR_32: case DYLD_CHAINED_PTR_32_CACHE: case DYLD_CHAINED_PTR_32_FIRMWARE: yield 4; + case DYLD_CHAINED_PTR_ARM64E: + case DYLD_CHAINED_PTR_ARM64E_USERLAND: + case DYLD_CHAINED_PTR_ARM64E_USERLAND24: + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + yield 8; + case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: + default: + yield 1; + }; + } + public static int getSize(DyldChainType ptrFormat) { + return switch (ptrFormat) { + case DYLD_CHAINED_PTR_32: + case DYLD_CHAINED_PTR_32_CACHE: + case DYLD_CHAINED_PTR_32_FIRMWARE: + yield 4; + case DYLD_CHAINED_PTR_ARM64E: + case DYLD_CHAINED_PTR_ARM64E_USERLAND: + case DYLD_CHAINED_PTR_ARM64E_USERLAND24: + case DYLD_CHAINED_PTR_64: + case DYLD_CHAINED_PTR_64_OFFSET: + case DYLD_CHAINED_PTR_ARM64E_KERNEL: + case DYLD_CHAINED_PTR_64_KERNEL_CACHE: + case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: + case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: default: yield 8; }; } - public static RelocationResult setChainValue(Memory memory, Address chainLoc, - DyldChainType ptrFormat, - long value) throws MemoryAccessException { - int byteLength; - switch (ptrFormat) { - case DYLD_CHAINED_PTR_ARM64E: - case DYLD_CHAINED_PTR_ARM64E_USERLAND: - case DYLD_CHAINED_PTR_ARM64E_USERLAND24: - case DYLD_CHAINED_PTR_64: - case DYLD_CHAINED_PTR_64_OFFSET: - case DYLD_CHAINED_PTR_ARM64E_KERNEL: - case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - memory.setLong(chainLoc, value); - byteLength = 8; - break; - - case DYLD_CHAINED_PTR_32: - case DYLD_CHAINED_PTR_32_CACHE: - case DYLD_CHAINED_PTR_32_FIRMWARE: - memory.setInt(chainLoc, (int) (value & 0xFFFFFFFFL)); - byteLength = 4; - break; - - default: - return RelocationResult.UNSUPPORTED; - } - return new RelocationResult(Status.APPLIED_OTHER, byteLength); - } - public static long getChainValue(BinaryReader reader, long chainLoc, DyldChainType ptrFormat) throws IOException { - switch (ptrFormat) { + return switch (ptrFormat) { + case DYLD_CHAINED_PTR_32: + case DYLD_CHAINED_PTR_32_CACHE: + case DYLD_CHAINED_PTR_32_FIRMWARE: + yield reader.readUnsignedInt(chainLoc); case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: @@ -183,104 +139,61 @@ public class DyldChainedPtr { case DYLD_CHAINED_PTR_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - return reader.readLong(chainLoc); - - case DYLD_CHAINED_PTR_32: - case DYLD_CHAINED_PTR_32_CACHE: - case DYLD_CHAINED_PTR_32_FIRMWARE: - return reader.readUnsignedInt(chainLoc); + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + yield reader.readLong(chainLoc); default: - return 0; - } + yield 0; + }; } public static boolean isRelative(DyldChainType ptrFormat) { - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_64_OFFSET: case DYLD_CHAINED_PTR_ARM64E_KERNEL: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: case DYLD_CHAINED_PTR_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - return true; + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + yield true; default: - return false; - } + yield false; + }; } public static boolean isBound(DyldChainType ptrFormat, long chainValue) { - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_KERNEL: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: - return ((chainValue >>> 62) & 1) != 0; - + yield ((chainValue >>> 62) & 1) != 0; case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: - return ((chainValue >>> 63) & 1) != 0; - + yield ((chainValue >>> 63) & 1) != 0; case DYLD_CHAINED_PTR_32: - return ((chainValue >>> 31) & 1) != 0; - - // Never bound - case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_32_CACHE: - case DYLD_CHAINED_PTR_32_FIRMWARE: + yield ((chainValue >>> 31) & 1) != 0; default: - return false; - } + yield false; + }; } public static boolean isAuthenticated(DyldChainType ptrFormat, long chainValue) { - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: case DYLD_CHAINED_PTR_32: case DYLD_CHAINED_PTR_32_CACHE: case DYLD_CHAINED_PTR_32_FIRMWARE: - return false; + yield false; default: - break; - } - - boolean isAuthenticated = ((chainValue >>> 63) & 1) != 0; - - return isAuthenticated; - } - - public static long getDiversity(DyldChainType ptrFormat, long chainValue) { - if (!isAuthenticated(ptrFormat, chainValue)) { - return 0; - } - - long diversityData = (chainValue >>> 32) & 0xFFFF; - - return diversityData; - } - - public static boolean hasAddrDiversity(DyldChainType ptrFormat, long chainValue) { - if (!isAuthenticated(ptrFormat, chainValue)) { - return false; - } - - return ((chainValue >>> 48) & 1) == 1; - } - - public static long getKey(DyldChainType ptrFormat, long chainValue) { - if (!isAuthenticated(ptrFormat, chainValue)) { - return 0; - } - - return (chainValue >>> 49L) & 0x3; + yield ((chainValue >>> 63) & 1) != 0; + }; } public static long getTarget(DyldChainType ptrFormat, long chainValue) { - long target = 0; if (isBound(ptrFormat, chainValue)) { return -1; } @@ -295,12 +208,14 @@ public class DyldChainedPtr { case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_64_KERNEL_CACHE: return (chainValue & 0x3FFFFFFFL); // 30 bits + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + return (chainValue & 0x3FFFFFFFFL); // 34 bits default: break; } } - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: @@ -311,8 +226,7 @@ public class DyldChainedPtr { if (top8Bits == 0x80) { top8Bits = 0; } - target = (top8Bits << 56) | bottom43Bits; - break; + yield (top8Bits << 56) | bottom43Bits; case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: @@ -322,30 +236,27 @@ public class DyldChainedPtr { if (top8Bits == 0x80) { top8Bits = 0; } - target = (top8Bits << 56) | bottom36Bits; - break; + yield (top8Bits << 56) | bottom36Bits; case DYLD_CHAINED_PTR_32: - target = (chainValue & 0x3FFFFF); // 26 bits - break; + yield (chainValue & 0x3FFFFF); // 26 bits case DYLD_CHAINED_PTR_32_CACHE: - target = (chainValue & 0x3FFFFFFF); // 30 bits - break; + yield (chainValue & 0x3FFFFFFF); // 30 bits case DYLD_CHAINED_PTR_32_FIRMWARE: - target = (chainValue & 0x3FFFFF); // 26 bits - break; + yield (chainValue & 0x3FFFFF); // 26 bits case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - target = (chainValue & 0x3FFFFFFF); // 30 bits - break; - default: - return 0; - } + yield (chainValue & 0x3FFFFFFF); // 30 bits - return target; + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + yield (chainValue & 0x3FFFFFFFFL); // 34 bits + + default: + yield 0; + }; } public static long getAddend(DyldChainType ptrFormat, long chainValue) { @@ -354,103 +265,83 @@ public class DyldChainedPtr { return 0; } - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: long addend = (chainValue >>> 32) & 0x7FFFF; addend = ((addend & 0x40000) != 0 ? (addend | 0xFFFFFFFFFFFC0000L) : addend); - return addend; + yield addend; case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: - return (chainValue >>> 24) & 0xFF; + yield (chainValue >>> 24) & 0xFF; case DYLD_CHAINED_PTR_32: - return (chainValue >>> 20) & 0x3F; // 6 bits + yield (chainValue >>> 20) & 0x3F; // 6 bits + default: - return 0; - } + yield 0; + }; } public static long getOrdinal(DyldChainType ptrFormat, long chainValue) { - long ordinal = -1; if (!isBound(ptrFormat, chainValue)) { return -1; } - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_KERNEL: case DYLD_CHAINED_PTR_ARM64E_USERLAND: - ordinal = chainValue & 0xFFFF; - break; + yield chainValue & 0xFFFF; case DYLD_CHAINED_PTR_ARM64E_USERLAND24: case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: - ordinal = chainValue & 0xFFFFFF; - break; + yield chainValue & 0xFFFFFF; case DYLD_CHAINED_PTR_32: - ordinal = chainValue & 0xFFFFF; - break; + yield chainValue & 0xFFFFF; - // Never Ordinal - case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - case DYLD_CHAINED_PTR_32_CACHE: - case DYLD_CHAINED_PTR_32_FIRMWARE: - break; default: - break; - } - - return ordinal; + yield -1; + }; } public static long getNext(DyldChainType ptrFormat, long chainValue) { - - long next = 1; - - switch (ptrFormat) { + return switch (ptrFormat) { case DYLD_CHAINED_PTR_ARM64E: case DYLD_CHAINED_PTR_ARM64E_USERLAND: case DYLD_CHAINED_PTR_ARM64E_USERLAND24: case DYLD_CHAINED_PTR_ARM64E_KERNEL: - next = (chainValue >>> 51) & 0x7FF; // 11-bits - break; + yield (chainValue >>> 51) & 0x7FF; // 11-bits case DYLD_CHAINED_PTR_64: case DYLD_CHAINED_PTR_64_OFFSET: case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: case DYLD_CHAINED_PTR_64_KERNEL_CACHE: - next = (chainValue >>> 51) & 0xFFF; // 12 bits - break; + yield (chainValue >>> 51) & 0xFFF; // 12 bits case DYLD_CHAINED_PTR_32: - next = (chainValue >>> 26) & 0x1F; // 5 bits - break; + yield (chainValue >>> 26) & 0x1F; // 5 bits // Never bound case DYLD_CHAINED_PTR_ARM64E_FIRMWARE: - next = 0; - break; + yield 0; case DYLD_CHAINED_PTR_32_CACHE: - next = (chainValue >>> 30) & 0x3; // 2 bits - break; + yield (chainValue >>> 30) & 0x3; // 2 bits case DYLD_CHAINED_PTR_32_FIRMWARE: - next = (chainValue >>> 26) & 0x3F; // 6 bits - break; + yield (chainValue >>> 26) & 0x3F; // 6 bits + + case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE: + yield (chainValue >>> 52) & 0x7FF; // 11 bits default: - break; - } - - return next; + yield 1; + }; } }