mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Improving the efficiency of fixing up dyld_shared_cache slide pointers
This commit is contained in:
parent
eaa8aeb0c8
commit
c474967356
17 changed files with 299 additions and 259 deletions
|
@ -223,7 +223,7 @@ public class MachoFunctionStartsAnalyzer extends AbstractAnalyzer {
|
||||||
boolean foundLinkEdit = false;
|
boolean foundLinkEdit = false;
|
||||||
for (DyldCacheHeader header : providerMap.keySet()) {
|
for (DyldCacheHeader header : providerMap.keySet()) {
|
||||||
for (DyldCacheMappingInfo mappingInfo : header.getMappingInfos()) {
|
for (DyldCacheMappingInfo mappingInfo : header.getMappingInfos()) {
|
||||||
if (mappingInfo.contains(linkEdit.getVMaddress())) {
|
if (mappingInfo.contains(linkEdit.getVMaddress(), true)) {
|
||||||
analyzeFunctionStarts(program, machoHeader, set, monitor);
|
analyzeFunctionStarts(program, machoHeader, set, monitor);
|
||||||
foundLinkEdit = true;
|
foundLinkEdit = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -191,7 +191,7 @@ public class LoadCommandFactory {
|
||||||
for (int i = 0; i < splitDyldCache.size(); i++) {
|
for (int i = 0; i < splitDyldCache.size(); i++) {
|
||||||
DyldCacheHeader dyldCacheHeader = splitDyldCache.getDyldCacheHeader(i);
|
DyldCacheHeader dyldCacheHeader = splitDyldCache.getDyldCacheHeader(i);
|
||||||
for (DyldCacheMappingInfo mappingInfo : dyldCacheHeader.getMappingInfos()) {
|
for (DyldCacheMappingInfo mappingInfo : dyldCacheHeader.getMappingInfos()) {
|
||||||
if (mappingInfo.contains(linkEdit.getVMaddress())) {
|
if (mappingInfo.contains(linkEdit.getVMaddress(), true)) {
|
||||||
return new BinaryReader(splitDyldCache.getProvider(i), true);
|
return new BinaryReader(splitDyldCache.getProvider(i), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -206,6 +206,10 @@ public class SegmentCommand extends LoadCommand {
|
||||||
return (flags & SegmentConstants.FLAG_APPLE_PROTECTED) != 0;
|
return (flags & SegmentConstants.FLAG_APPLE_PROTECTED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean is32bit() {
|
||||||
|
return is32bit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the segment contains the given address
|
* Returns true if the segment contains the given address
|
||||||
*
|
*
|
||||||
|
|
|
@ -402,20 +402,19 @@ public class DyldCacheHeader implements StructConverter {
|
||||||
DyldCacheMappingInfo mappingInfo =
|
DyldCacheMappingInfo mappingInfo =
|
||||||
mappingInfoList.get(DyldCacheSlideInfoCommon.DATA_PAGE_MAP_ENTRY);
|
mappingInfoList.get(DyldCacheSlideInfoCommon.DATA_PAGE_MAP_ENTRY);
|
||||||
DyldCacheSlideInfoCommon info = DyldCacheSlideInfoCommon.parseSlideInfo(reader,
|
DyldCacheSlideInfoCommon info = DyldCacheSlideInfoCommon.parseSlideInfo(reader,
|
||||||
slideInfoOffset, mappingInfo.getAddress(), mappingInfo.getSize(),
|
slideInfoOffset, mappingInfo, log, monitor);
|
||||||
mappingInfo.getFileOffset(), log, monitor);
|
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
slideInfoList.add(info);
|
slideInfoList.add(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cacheMappingAndSlideInfoList.size() > 0) {
|
else if (cacheMappingAndSlideInfoList.size() > 0) {
|
||||||
for (DyldCacheMappingAndSlideInfo info : cacheMappingAndSlideInfoList) {
|
for (int i = 0; i < cacheMappingAndSlideInfoList.size(); i++) {
|
||||||
|
DyldCacheMappingAndSlideInfo info = cacheMappingAndSlideInfoList.get(i);
|
||||||
if (info.getSlideInfoFileOffset() == 0) {
|
if (info.getSlideInfoFileOffset() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DyldCacheSlideInfoCommon slideInfo = DyldCacheSlideInfoCommon.parseSlideInfo(reader,
|
DyldCacheSlideInfoCommon slideInfo = DyldCacheSlideInfoCommon.parseSlideInfo(reader,
|
||||||
info.getSlideInfoFileOffset(), info.getAddress(), info.getSize(),
|
info.getSlideInfoFileOffset(), mappingInfoList.get(i), log, monitor);
|
||||||
info.getFileOffset(), log, monitor);
|
|
||||||
if (slideInfo != null) {
|
if (slideInfo != null) {
|
||||||
slideInfoList.add(slideInfo);
|
slideInfoList.add(slideInfo);
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1066,7 @@ public class DyldCacheHeader implements StructConverter {
|
||||||
List<DyldCacheImage> images = new ArrayList<>();
|
List<DyldCacheImage> images = new ArrayList<>();
|
||||||
for (DyldCacheImage imageInfo : imageInfoList) {
|
for (DyldCacheImage imageInfo : imageInfoList) {
|
||||||
for (DyldCacheMappingInfo mappingInfo : mappingInfoList) {
|
for (DyldCacheMappingInfo mappingInfo : mappingInfoList) {
|
||||||
if (mappingInfo.contains(imageInfo.getAddress())) {
|
if (mappingInfo.contains(imageInfo.getAddress(), true)) {
|
||||||
images.add(imageInfo);
|
images.add(imageInfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,11 +187,15 @@ public class DyldCacheMappingAndSlideInfo implements StructConverter {
|
||||||
* Returns true if the mapping contains the given address
|
* Returns true if the mapping contains the given address
|
||||||
*
|
*
|
||||||
* @param addr The address to check
|
* @param addr The address to check
|
||||||
|
* @param isAddr True if the {@code addr} parameter is an address; false if it's a file offset
|
||||||
* @return True if the mapping contains the given address; otherwise, false
|
* @return True if the mapping contains the given address; otherwise, false
|
||||||
*/
|
*/
|
||||||
public boolean contains(long addr) {
|
public boolean contains(long addr, boolean isAddr) {
|
||||||
return Long.compareUnsigned(addr, address) >= 0 &&
|
return isAddr
|
||||||
Long.compareUnsigned(addr, address + size) < 0;
|
? Long.compareUnsigned(addr, address) >= 0 &&
|
||||||
|
Long.compareUnsigned(addr, address + size) < 0
|
||||||
|
: Long.compareUnsigned(addr, fileOffset) >= 0 &&
|
||||||
|
Long.compareUnsigned(addr, fileOffset + size) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -106,15 +106,27 @@ public class DyldCacheMappingInfo implements StructConverter {
|
||||||
return (initProt & SegmentConstants.PROTECTION_X) != 0;
|
return (initProt & SegmentConstants.PROTECTION_X) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxProtection() {
|
||||||
|
return maxProt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInitialProtection() {
|
||||||
|
return initProt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the mapping contains the given address
|
* Returns true if the mapping contains the given address
|
||||||
*
|
*
|
||||||
* @param addr The address to check
|
* @param addr The address to check
|
||||||
|
* @param isAddr True if the {@code addr} parameter is an address; false if it's a file offset
|
||||||
* @return True if the mapping contains the given address; otherwise, false
|
* @return True if the mapping contains the given address; otherwise, false
|
||||||
*/
|
*/
|
||||||
public boolean contains(long addr) {
|
public boolean contains(long addr, boolean isAddr) {
|
||||||
return Long.compareUnsigned(addr, address) >= 0 &&
|
return isAddr
|
||||||
Long.compareUnsigned(addr, address + size) < 0;
|
? Long.compareUnsigned(addr, address) >= 0 &&
|
||||||
|
Long.compareUnsigned(addr, address + size) < 0
|
||||||
|
: Long.compareUnsigned(addr, fileOffset) >= 0 &&
|
||||||
|
Long.compareUnsigned(addr, fileOffset + size) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -47,14 +47,12 @@ public class DyldCacheSlideInfo1 extends DyldCacheSlideInfoCommon {
|
||||||
* Create a new {@link DyldCacheSlideInfo1}.
|
* Create a new {@link DyldCacheSlideInfo1}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 1
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 1
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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 1
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info 1
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfo1(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfo1(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
super(reader, mappingAddress, mappingSize, mappingFileOffset);
|
super(reader, mappingInfo);
|
||||||
long startIndex = reader.getPointerIndex() - 4; // version # already read
|
long startIndex = reader.getPointerIndex() - 4; // version # already read
|
||||||
|
|
||||||
tocOffset = reader.readNextInt();
|
tocOffset = reader.readNextInt();
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -51,14 +51,12 @@ public class DyldCacheSlideInfo2 extends DyldCacheSlideInfoCommon {
|
||||||
* Create a new {@link DyldCacheSlideInfo2}.
|
* Create a new {@link DyldCacheSlideInfo2}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 2
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 2
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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 2
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info 2
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfo2(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfo2(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
super(reader, mappingAddress, mappingSize, mappingFileOffset);
|
super(reader, mappingInfo);
|
||||||
pageSize = reader.readNextInt();
|
pageSize = reader.readNextInt();
|
||||||
pageStartsOffset = reader.readNextInt();
|
pageStartsOffset = reader.readNextInt();
|
||||||
pageStartsCount = reader.readNextInt();
|
pageStartsCount = reader.readNextInt();
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -73,14 +73,12 @@ public class DyldCacheSlideInfo3 extends DyldCacheSlideInfoCommon {
|
||||||
* Create a new {@link DyldCacheSlideInfo3}.
|
* Create a new {@link DyldCacheSlideInfo3}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 3
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 3
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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 3
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info 3
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfo3(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfo3(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
super(reader, mappingAddress, mappingSize, mappingFileOffset);
|
super(reader, mappingInfo);
|
||||||
pageSize = reader.readNextInt();
|
pageSize = reader.readNextInt();
|
||||||
pageStartsCount = reader.readNextInt();
|
pageStartsCount = reader.readNextInt();
|
||||||
reader.readNextInt(); // padding
|
reader.readNextInt(); // padding
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -116,14 +116,12 @@ public class DyldCacheSlideInfo4 extends DyldCacheSlideInfoCommon {
|
||||||
* Create a new {@link DyldCacheSlideInfo4}.
|
* Create a new {@link DyldCacheSlideInfo4}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 3
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 3
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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 3
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info 3
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfo4(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfo4(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
super(reader, mappingAddress, mappingSize, mappingFileOffset);
|
super(reader, mappingInfo);
|
||||||
pageSize = reader.readNextInt();
|
pageSize = reader.readNextInt();
|
||||||
pageStartsOffset = reader.readNextInt();
|
pageStartsOffset = reader.readNextInt();
|
||||||
pageStartsCount = reader.readNextInt();
|
pageStartsCount = reader.readNextInt();
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -75,14 +75,12 @@ public class DyldCacheSlideInfo5 extends DyldCacheSlideInfoCommon {
|
||||||
* Create a new {@link DyldCacheSlideInfo5}.
|
* Create a new {@link DyldCacheSlideInfo5}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info 5
|
* @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 mappingInfo The {@link DyldCacheMappingInfo} 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
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info 5
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfo5(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfo5(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
super(reader, mappingAddress, mappingSize, mappingFileOffset);
|
super(reader, mappingInfo);
|
||||||
pageSize = reader.readNextInt();
|
pageSize = reader.readNextInt();
|
||||||
pageStartsCount = reader.readNextInt();
|
pageStartsCount = reader.readNextInt();
|
||||||
reader.readNextInt(); // padding
|
reader.readNextInt(); // padding
|
||||||
|
|
|
@ -51,16 +51,13 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info
|
||||||
* @param slideInfoOffset The offset of the slide info to parse
|
* @param slideInfoOffset The offset of the slide info to parse
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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
|
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
* @return The slide info object
|
* @return The slide info object
|
||||||
*/
|
*/
|
||||||
public static DyldCacheSlideInfoCommon parseSlideInfo(BinaryReader reader, long slideInfoOffset,
|
public static DyldCacheSlideInfoCommon parseSlideInfo(BinaryReader reader, long slideInfoOffset,
|
||||||
long mappingAddress, long mappingSize, long mappingFileOffset, MessageLog log,
|
DyldCacheMappingInfo mappingInfo, MessageLog log,TaskMonitor monitor) {
|
||||||
TaskMonitor monitor) {
|
|
||||||
if (slideInfoOffset == 0) {
|
if (slideInfoOffset == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -73,16 +70,11 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
int version = reader.readInt(reader.getPointerIndex());
|
int version = reader.readInt(reader.getPointerIndex());
|
||||||
errorMessage += version;
|
errorMessage += version;
|
||||||
DyldCacheSlideInfoCommon returnedSlideInfo = switch (version) {
|
DyldCacheSlideInfoCommon returnedSlideInfo = switch (version) {
|
||||||
case 1 -> new DyldCacheSlideInfo1(reader, mappingAddress, mappingSize,
|
case 1 -> new DyldCacheSlideInfo1(reader, mappingInfo);
|
||||||
mappingFileOffset);
|
case 2 -> new DyldCacheSlideInfo2(reader, mappingInfo);
|
||||||
case 2 -> new DyldCacheSlideInfo2(reader, mappingAddress, mappingSize,
|
case 3 -> new DyldCacheSlideInfo3(reader, mappingInfo);
|
||||||
mappingFileOffset);
|
case 4 -> new DyldCacheSlideInfo4(reader, mappingInfo);
|
||||||
case 3 -> new DyldCacheSlideInfo3(reader, mappingAddress, mappingSize,
|
case 5 -> new DyldCacheSlideInfo5(reader, mappingInfo);
|
||||||
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
|
default -> throw new IOException(); // will be caught and version will be added to message
|
||||||
};
|
};
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
|
@ -97,24 +89,18 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
|
|
||||||
protected int version;
|
protected int version;
|
||||||
protected long slideInfoOffset;
|
protected long slideInfoOffset;
|
||||||
protected long mappingAddress;
|
protected DyldCacheMappingInfo mappingInfo;
|
||||||
protected long mappingSize;
|
|
||||||
protected long mappingFileOffset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link DyldCacheSlideInfoCommon}.
|
* Create a new {@link DyldCacheSlideInfoCommon}.
|
||||||
*
|
*
|
||||||
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info
|
* @param reader A {@link BinaryReader} positioned at the start of a DYLD slide info
|
||||||
* @param mappingAddress The base address of where the slide fixups will take place
|
* @param mappingInfo The {@link DyldCacheMappingInfo} 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
|
* @throws IOException if there was an IO-related problem creating the DYLD slide info
|
||||||
*/
|
*/
|
||||||
public DyldCacheSlideInfoCommon(BinaryReader reader, long mappingAddress, long mappingSize,
|
public DyldCacheSlideInfoCommon(BinaryReader reader, DyldCacheMappingInfo mappingInfo)
|
||||||
long mappingFileOffset) throws IOException {
|
throws IOException {
|
||||||
this.mappingAddress = mappingAddress;
|
this.mappingInfo = mappingInfo;
|
||||||
this.mappingSize = mappingSize;
|
|
||||||
this.mappingFileOffset = mappingFileOffset;
|
|
||||||
this.version = reader.readNextInt();
|
this.version = reader.readNextInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,22 +121,8 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
/**
|
/**
|
||||||
* {@return The base address of where the slide fixups will take place}
|
* {@return The base address of where the slide fixups will take place}
|
||||||
*/
|
*/
|
||||||
public long getMappingAddress() {
|
public DyldCacheMappingInfo getMappingInfo() {
|
||||||
return mappingAddress;
|
return mappingInfo;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return The size of the slide fixups block}
|
|
||||||
*/
|
|
||||||
public long getMappingSize() {
|
|
||||||
return mappingSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return The base file offset of where the slide fixups will take place}
|
|
||||||
*/
|
|
||||||
public long getMappingFileOffset() {
|
|
||||||
return mappingFileOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,7 +157,7 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
||||||
|
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
|
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
Address dataPageAddr = space.getAddress(mappingAddress);
|
Address dataPageAddr = space.getAddress(mappingInfo.getAddress());
|
||||||
|
|
||||||
try (ByteProvider provider = new MemoryByteProvider(memory, dataPageAddr)) {
|
try (ByteProvider provider = new MemoryByteProvider(memory, dataPageAddr)) {
|
||||||
BinaryReader reader = new BinaryReader(provider, !memory.isBigEndian());
|
BinaryReader reader = new BinaryReader(provider, !memory.isBigEndian());
|
||||||
|
|
|
@ -281,37 +281,23 @@ public class ExtractedMacho {
|
||||||
* @throws IOException If there was an IO-related issue performing the fix-up
|
* @throws IOException If there was an IO-related issue performing the fix-up
|
||||||
*/
|
*/
|
||||||
private void fixupLoadCommands() throws IOException {
|
private void fixupLoadCommands() throws IOException {
|
||||||
for (LoadCommand cmd : machoHeader.getLoadCommands()) {
|
for (LoadCommand lc : machoHeader.getLoadCommands()) {
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (cmd.getCommandType()) {
|
switch (lc) {
|
||||||
case LoadCommandTypes.LC_SEGMENT:
|
case SegmentCommand cmd -> fixupSegment(cmd);
|
||||||
fixupSegment((SegmentCommand) cmd, false);
|
case SymbolTableCommand cmd -> fixupSymbolTable(cmd);
|
||||||
break;
|
case DynamicSymbolTableCommand cmd -> fixupDynamicSymbolTable(cmd);
|
||||||
case LoadCommandTypes.LC_SEGMENT_64:
|
case DyldInfoCommand cmd -> fixupDyldInfo(cmd);
|
||||||
fixupSegment((SegmentCommand) cmd, true);
|
case LinkEditDataCommand cmd -> fixupLinkEditData(cmd);
|
||||||
break;
|
case CorruptLoadCommand cmd -> throw new IOException(
|
||||||
case LoadCommandTypes.LC_SYMTAB:
|
"Error fixing corrupt %s at 0x%x".formatted(
|
||||||
fixupSymbolTable((SymbolTableCommand) cmd);
|
LoadCommandTypes.getLoadCommandName(cmd.getCommandType()),
|
||||||
break;
|
cmd.getStartIndex()));
|
||||||
case LoadCommandTypes.LC_DYSYMTAB:
|
default -> {
|
||||||
fixupDynamicSymbolTable((DynamicSymbolTableCommand) cmd);
|
// Do nothing
|
||||||
break;
|
}
|
||||||
case LoadCommandTypes.LC_DYLD_INFO:
|
|
||||||
case LoadCommandTypes.LC_DYLD_INFO_ONLY:
|
|
||||||
fixupDyldInfo((DyldInfoCommand) cmd);
|
|
||||||
break;
|
|
||||||
case LoadCommandTypes.LC_CODE_SIGNATURE:
|
|
||||||
case LoadCommandTypes.LC_SEGMENT_SPLIT_INFO:
|
|
||||||
case LoadCommandTypes.LC_FUNCTION_STARTS:
|
|
||||||
case LoadCommandTypes.LC_DATA_IN_CODE:
|
|
||||||
case LoadCommandTypes.LC_DYLIB_CODE_SIGN_DRS:
|
|
||||||
case LoadCommandTypes.LC_OPTIMIZATION_HINT:
|
|
||||||
case LoadCommandTypes.LC_DYLD_EXPORTS_TRIE:
|
|
||||||
case LoadCommandTypes.LC_DYLD_CHAINED_FIXUPS:
|
|
||||||
fixupLinkEditData((LinkEditDataCommand) cmd);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,11 +307,11 @@ public class ExtractedMacho {
|
||||||
* for the newly packed Mach-O
|
* for the newly packed Mach-O
|
||||||
*
|
*
|
||||||
* @param segment The segment to fix-up
|
* @param segment The segment to fix-up
|
||||||
* @param is64bit True if the segment is 64-bit; false if 32-bit
|
|
||||||
* @throws IOException If there was an IO-related issue performing the fix-up
|
* @throws IOException If there was an IO-related issue performing the fix-up
|
||||||
*/
|
*/
|
||||||
private void fixupSegment(SegmentCommand segment, boolean is64bit) throws IOException {
|
private void fixupSegment(SegmentCommand segment) throws IOException {
|
||||||
long adjustment = packedSegmentAdjustments.getOrDefault(segment, 0);
|
long adjustment = packedSegmentAdjustments.getOrDefault(segment, 0);
|
||||||
|
boolean is64bit = !segment.is32bit();
|
||||||
|
|
||||||
set(segment.getStartIndex() + (is64bit ? 0x18 : 0x18), segment.getVMaddress(),
|
set(segment.getStartIndex() + (is64bit ? 0x18 : 0x18), segment.getVMaddress(),
|
||||||
is64bit ? 8 : 4);
|
is64bit ? 8 : 4);
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.file.formats.ios.dyldcache;
|
||||||
import com.google.common.collect.RangeSet;
|
import com.google.common.collect.RangeSet;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldCacheMappingAndSlideInfo;
|
import ghidra.app.util.bin.format.macho.dyld.DyldCacheMappingAndSlideInfo;
|
||||||
|
import ghidra.app.util.bin.format.macho.dyld.DyldCacheMappingInfo;
|
||||||
import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
|
import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,10 +27,13 @@ import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
|
||||||
* @param path The path of the entry
|
* @param path The path of the entry
|
||||||
* @param splitCacheIndex The entry's {@link SplitDyldCache} index
|
* @param splitCacheIndex The entry's {@link SplitDyldCache} index
|
||||||
* @param rangeSet The entry's address ranges
|
* @param rangeSet The entry's address ranges
|
||||||
* @param mappingInfo The entry's {@link DyldCacheMappingAndSlideInfo}; could be null if this entry
|
* @param mappingInfo The entry's {@link DyldCacheMappingInfo}; could be null if this entry
|
||||||
* represents a DYLIB
|
* represents a DYLIB
|
||||||
* @param mappingIndex The entry's {@link DyldCacheMappingAndSlideInfo} index; ignored if the
|
* @param mappingAndSlideInfo The entry's {@link DyldCacheMappingAndSlideInfo}; could be null if
|
||||||
|
* this entry represents a DYLIB, or if the cache is old and doesn't support this structure
|
||||||
|
* @param mappingIndex The entry's {@link DyldCacheMappingInfo} index; ignored if the
|
||||||
* {@code mappingInfo} is null.
|
* {@code mappingInfo} is null.
|
||||||
*/
|
*/
|
||||||
public record DyldCacheEntry(String path, int splitCacheIndex, RangeSet<Long> rangeSet,
|
public record DyldCacheEntry(String path, int splitCacheIndex, RangeSet<Long> rangeSet,
|
||||||
DyldCacheMappingAndSlideInfo mappingInfo, int mappingIndex) {}
|
DyldCacheMappingInfo mappingInfo, DyldCacheMappingAndSlideInfo mappingAndSlideInfo,
|
||||||
|
int mappingIndex) {}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
|
||||||
import ghidra.file.formats.ios.ExtractedMacho;
|
import ghidra.file.formats.ios.ExtractedMacho;
|
||||||
import ghidra.formats.gfilesystem.FSRL;
|
import ghidra.formats.gfilesystem.FSRL;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.NotFoundException;
|
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +51,6 @@ public class DyldCacheExtractor {
|
||||||
*
|
*
|
||||||
* @param entry The mapping's {@link DyldCacheEntry}
|
* @param entry The mapping's {@link DyldCacheEntry}
|
||||||
* @param splitDyldCache The {@link SplitDyldCache}
|
* @param splitDyldCache The {@link SplitDyldCache}
|
||||||
* @param index The DYLIB's {@link SplitDyldCache} index
|
|
||||||
* @param slideFixupMap A {@link Map} of {@link DyldFixup}s to perform
|
* @param slideFixupMap A {@link Map} of {@link DyldFixup}s to perform
|
||||||
* @param fsrl {@link FSRL} to assign to the resulting {@link ByteProvider}
|
* @param fsrl {@link FSRL} to assign to the resulting {@link ByteProvider}
|
||||||
* @param monitor {@link TaskMonitor}
|
* @param monitor {@link TaskMonitor}
|
||||||
|
@ -62,12 +60,12 @@ public class DyldCacheExtractor {
|
||||||
* @throws CancelledException If the user cancelled the operation
|
* @throws CancelledException If the user cancelled the operation
|
||||||
*/
|
*/
|
||||||
public static ByteProvider extractDylib(DyldCacheEntry entry, SplitDyldCache splitDyldCache,
|
public static ByteProvider extractDylib(DyldCacheEntry entry, SplitDyldCache splitDyldCache,
|
||||||
int index, Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap,
|
Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap, FSRL fsrl,
|
||||||
FSRL fsrl, TaskMonitor monitor) throws IOException, MachException, CancelledException {
|
TaskMonitor monitor) throws IOException, MachException, CancelledException {
|
||||||
long dylibOffset = entry.rangeSet().asRanges().iterator().next().lowerEndpoint() -
|
long dylibOffset = entry.rangeSet().asRanges().iterator().next().lowerEndpoint() -
|
||||||
splitDyldCache.getDyldCacheHeader(entry.splitCacheIndex()).getBaseAddress();
|
splitDyldCache.getDyldCacheHeader(entry.splitCacheIndex()).getBaseAddress();
|
||||||
ExtractedMacho extractedMacho = new DyldPackedSegments(dylibOffset, splitDyldCache, index,
|
ExtractedMacho extractedMacho = new DyldPackedSegments(dylibOffset, splitDyldCache,
|
||||||
FOOTER_V1, slideFixupMap, monitor);
|
entry.splitCacheIndex(), FOOTER_V1, slideFixupMap, monitor);
|
||||||
extractedMacho.pack();
|
extractedMacho.pack();
|
||||||
return extractedMacho.getByteProvider(fsrl);
|
return extractedMacho.getByteProvider(fsrl);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +76,6 @@ public class DyldCacheExtractor {
|
||||||
* @param entry The mapping's {@link DyldCacheEntry}
|
* @param entry The mapping's {@link DyldCacheEntry}
|
||||||
* @param segmentName The name of the segment in the resulting Mach-O
|
* @param segmentName The name of the segment in the resulting Mach-O
|
||||||
* @param splitDyldCache The {@link SplitDyldCache}
|
* @param splitDyldCache The {@link SplitDyldCache}
|
||||||
* @param index The mapping's {@link SplitDyldCache} index
|
|
||||||
* @param slideFixupMap A {@link Map} of {@link DyldFixup}s to perform
|
* @param slideFixupMap A {@link Map} of {@link DyldFixup}s to perform
|
||||||
* @param fsrl {@link FSRL} to assign to the resulting {@link ByteProvider}
|
* @param fsrl {@link FSRL} to assign to the resulting {@link ByteProvider}
|
||||||
* @param monitor {@link TaskMonitor}
|
* @param monitor {@link TaskMonitor}
|
||||||
|
@ -88,35 +85,15 @@ public class DyldCacheExtractor {
|
||||||
* @throws CancelledException If the user cancelled the operation
|
* @throws CancelledException If the user cancelled the operation
|
||||||
*/
|
*/
|
||||||
public static ByteProvider extractMapping(DyldCacheEntry entry, String segmentName,
|
public static ByteProvider extractMapping(DyldCacheEntry entry, String segmentName,
|
||||||
SplitDyldCache splitDyldCache, int index,
|
SplitDyldCache splitDyldCache,
|
||||||
Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap, FSRL fsrl,
|
Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap, FSRL fsrl,
|
||||||
TaskMonitor monitor) throws IOException, MachException, CancelledException {
|
TaskMonitor monitor) throws IOException, MachException, CancelledException {
|
||||||
|
|
||||||
int magic = MachConstants.MH_MAGIC_64;
|
int magic = MachConstants.MH_MAGIC_64;
|
||||||
List<Range<Long>> ranges = new ArrayList<>(entry.rangeSet().asRanges());
|
List<Range<Long>> ranges = new ArrayList<>(entry.rangeSet().asRanges());
|
||||||
DyldCacheMappingAndSlideInfo mappingInfo = entry.mappingInfo();
|
DyldCacheMappingInfo mappingInfo = entry.mappingInfo();
|
||||||
int allSegmentsSize = SegmentCommand.size(magic) * ranges.size();
|
int allSegmentsSize = SegmentCommand.size(magic) * ranges.size();
|
||||||
|
|
||||||
// Fix slide pointers
|
|
||||||
ByteProvider origProvider = splitDyldCache.getProvider(index);
|
|
||||||
byte[] fixedProviderBytes = origProvider.readBytes(0, origProvider.length());
|
|
||||||
DyldCacheSlideInfoCommon slideInfo = slideFixupMap.keySet()
|
|
||||||
.stream()
|
|
||||||
.filter(e -> e.getMappingAddress() == mappingInfo.getAddress())
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
if (slideInfo != null) {
|
|
||||||
List<DyldFixup> slideFixups = slideFixupMap.get(slideInfo);
|
|
||||||
monitor.initialize(slideFixups.size(), "Fixing slide pointers...");
|
|
||||||
for (DyldFixup fixup : slideFixups) {
|
|
||||||
monitor.increment();
|
|
||||||
long fileOffset = slideInfo.getMappingFileOffset() + fixup.offset();
|
|
||||||
byte[] newBytes = ExtractedMacho.toBytes(fixup.value(), fixup.size());
|
|
||||||
System.arraycopy(newBytes, 0, fixedProviderBytes, (int) fileOffset,
|
|
||||||
newBytes.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mach-O Header
|
// Mach-O Header
|
||||||
byte[] header = MachHeader.create(magic, 0x100000c, 0x80000002, 6, ranges.size(),
|
byte[] header = MachHeader.create(magic, 0x100000c, 0x80000002, 6, ranges.size(),
|
||||||
allSegmentsSize, 0x42100085, 0);
|
allSegmentsSize, 0x42100085, 0);
|
||||||
|
@ -125,19 +102,22 @@ public class DyldCacheExtractor {
|
||||||
List<byte[]> segments = new ArrayList<>();
|
List<byte[]> segments = new ArrayList<>();
|
||||||
List<byte[]> data = new ArrayList<>();
|
List<byte[]> data = new ArrayList<>();
|
||||||
int current = header.length + allSegmentsSize;
|
int current = header.length + allSegmentsSize;
|
||||||
try (ByteProvider fixedProvider = new ByteArrayProvider(fixedProviderBytes)) {
|
try (ByteProvider slidProvider =
|
||||||
|
new DyldCacheSlidProvider(entry.mappingInfo(), splitDyldCache, entry.splitCacheIndex(),
|
||||||
|
slideFixupMap, monitor)) {
|
||||||
for (int i = 0; i < ranges.size(); i++) {
|
for (int i = 0; i < ranges.size(); i++) {
|
||||||
Range<Long> range = ranges.get(i);
|
Range<Long> range = ranges.get(i);
|
||||||
|
|
||||||
// Segment Command
|
// Segment Command
|
||||||
long dataSize = range.upperEndpoint() - range.lowerEndpoint();
|
long dataSize = range.upperEndpoint() - range.lowerEndpoint();
|
||||||
segments.add(
|
segments.add(
|
||||||
SegmentCommand.create(magic, "%s.%d.%d".formatted(segmentName, index, i),
|
SegmentCommand.create(magic,
|
||||||
|
"%s.%d.%d".formatted(segmentName, entry.splitCacheIndex(), i),
|
||||||
range.lowerEndpoint(), dataSize, current, dataSize,
|
range.lowerEndpoint(), dataSize, current, dataSize,
|
||||||
mappingInfo.getMaxProtection(), mappingInfo.getMaxProtection(), 0, 0));
|
mappingInfo.getMaxProtection(), mappingInfo.getMaxProtection(), 0, 0));
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
data.add(fixedProvider.readBytes(
|
data.add(slidProvider.readBytes(
|
||||||
range.lowerEndpoint() - mappingInfo.getAddress() + mappingInfo.getFileOffset(),
|
range.lowerEndpoint() - mappingInfo.getAddress() + mappingInfo.getFileOffset(),
|
||||||
dataSize));
|
dataSize));
|
||||||
|
|
||||||
|
@ -176,10 +156,10 @@ public class DyldCacheExtractor {
|
||||||
* @throws CancelledException If the user cancelled the operation
|
* @throws CancelledException If the user cancelled the operation
|
||||||
* @throws IOException If there was an IO-related issue with getting the slide fixups
|
* @throws IOException If there was an IO-related issue with getting the slide fixups
|
||||||
*/
|
*/
|
||||||
public static Map<DyldCacheSlideInfoCommon, List<DyldFixup>> getSlideFixups(
|
public static Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> getSlideFixups(
|
||||||
SplitDyldCache splitDyldCache, TaskMonitor monitor)
|
SplitDyldCache splitDyldCache, TaskMonitor monitor)
|
||||||
throws CancelledException, IOException {
|
throws CancelledException, IOException {
|
||||||
Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap = new HashMap<>();
|
Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap = new HashMap<>();
|
||||||
MessageLog log = new MessageLog();
|
MessageLog log = new MessageLog();
|
||||||
|
|
||||||
for (int i = 0; i < splitDyldCache.size(); i++) {
|
for (int i = 0; i < splitDyldCache.size(); i++) {
|
||||||
|
@ -187,13 +167,18 @@ public class DyldCacheExtractor {
|
||||||
ByteProvider bp = splitDyldCache.getProvider(i);
|
ByteProvider bp = splitDyldCache.getProvider(i);
|
||||||
DyldArchitecture arch = header.getArchitecture();
|
DyldArchitecture arch = header.getArchitecture();
|
||||||
for (DyldCacheSlideInfoCommon slideInfo : header.getSlideInfos()) {
|
for (DyldCacheSlideInfoCommon slideInfo : header.getSlideInfos()) {
|
||||||
try (ByteProvider wrapper = new ByteProviderWrapper(bp,
|
DyldCacheMappingInfo mappingInfo = slideInfo.getMappingInfo();
|
||||||
slideInfo.getMappingFileOffset(), slideInfo.getMappingSize())) {
|
try (ByteProvider wrapper = new ByteProviderWrapper(bp, mappingInfo.getFileOffset(),
|
||||||
|
mappingInfo.getSize())) {
|
||||||
BinaryReader wrapperReader =
|
BinaryReader wrapperReader =
|
||||||
new BinaryReader(wrapper, !arch.getEndianness().isBigEndian());
|
new BinaryReader(wrapper, !arch.getEndianness().isBigEndian());
|
||||||
List<DyldFixup> fixups = slideInfo.getSlideFixups(wrapperReader,
|
List<DyldFixup> fixups = slideInfo.getSlideFixups(wrapperReader,
|
||||||
arch.is64bit() ? 8 : 4, log, monitor);
|
arch.is64bit() ? 8 : 4, log, monitor);
|
||||||
slideFixupMap.put(slideInfo, fixups);
|
HashMap<Long, DyldFixup> subMap = new HashMap<>();
|
||||||
|
for (DyldFixup fixup : fixups) {
|
||||||
|
subMap.put(mappingInfo.getFileOffset() + fixup.offset(), fixup);
|
||||||
|
}
|
||||||
|
slideFixupMap.put(mappingInfo, subMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +194,7 @@ public class DyldCacheExtractor {
|
||||||
private static class DyldPackedSegments extends ExtractedMacho {
|
private static class DyldPackedSegments extends ExtractedMacho {
|
||||||
|
|
||||||
private SplitDyldCache splitDyldCache;
|
private SplitDyldCache splitDyldCache;
|
||||||
private Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap;
|
private Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link DyldPackedSegments} object
|
* Creates a new {@link DyldPackedSegments} object
|
||||||
|
@ -226,7 +211,7 @@ public class DyldCacheExtractor {
|
||||||
* @throws CancelledException If the user cancelled the operation
|
* @throws CancelledException If the user cancelled the operation
|
||||||
*/
|
*/
|
||||||
public DyldPackedSegments(long dylibOffset, SplitDyldCache splitDyldCache, int index,
|
public DyldPackedSegments(long dylibOffset, SplitDyldCache splitDyldCache, int index,
|
||||||
byte[] footer, Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap,
|
byte[] footer, Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap,
|
||||||
TaskMonitor monitor) throws MachException, IOException, CancelledException {
|
TaskMonitor monitor) throws MachException, IOException, CancelledException {
|
||||||
super(splitDyldCache.getProvider(index), dylibOffset,
|
super(splitDyldCache.getProvider(index), dylibOffset,
|
||||||
new MachHeader(splitDyldCache.getProvider(index), dylibOffset, false)
|
new MachHeader(splitDyldCache.getProvider(index), dylibOffset, false)
|
||||||
|
@ -236,19 +221,14 @@ public class DyldCacheExtractor {
|
||||||
this.slideFixupMap = slideFixupMap;
|
this.slideFixupMap = slideFixupMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void pack() throws IOException, CancelledException {
|
|
||||||
super.pack();
|
|
||||||
fixupSlidePointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ByteProvider getSegmentProvider(SegmentCommand segment) throws IOException {
|
protected ByteProvider getSegmentProvider(SegmentCommand segment) throws IOException {
|
||||||
for (int i = 0; i < splitDyldCache.size(); i++) {
|
for (int i = 0; i < splitDyldCache.size(); i++) {
|
||||||
DyldCacheHeader dyldCacheheader = splitDyldCache.getDyldCacheHeader(i);
|
DyldCacheHeader dyldCacheheader = splitDyldCache.getDyldCacheHeader(i);
|
||||||
for (DyldCacheMappingInfo mappingInfo : dyldCacheheader.getMappingInfos()) {
|
for (DyldCacheMappingInfo mappingInfo : dyldCacheheader.getMappingInfos()) {
|
||||||
if (mappingInfo.contains(segment.getVMaddress())) {
|
if (mappingInfo.contains(segment.getVMaddress(), true)) {
|
||||||
return splitDyldCache.getProvider(i);
|
return new DyldCacheSlidProvider(mappingInfo, splitDyldCache, i,
|
||||||
|
slideFixupMap, monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,54 +242,6 @@ public class DyldCacheExtractor {
|
||||||
DyldCacheLocalSymbolsInfo info = splitDyldCache.getLocalSymbolInfo();
|
DyldCacheLocalSymbolsInfo info = splitDyldCache.getLocalSymbolInfo();
|
||||||
return info != null ? info.getNList(textSegment.getVMaddress() - base) : List.of();
|
return info != null ? info.getNList(textSegment.getVMaddress() - base) : List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes-up the slide pointers
|
|
||||||
*
|
|
||||||
* @throws IOException If there was an IO-related issue performing the fix-up
|
|
||||||
* @throws CancelledException If the user cancelled the operation
|
|
||||||
*/
|
|
||||||
private void fixupSlidePointers() throws IOException, CancelledException {
|
|
||||||
// TODO; Optimize this fixup algorithm
|
|
||||||
long total = slideFixupMap.values().stream().flatMap(List::stream).count();
|
|
||||||
monitor.initialize(total, "Fixing slide pointers...");
|
|
||||||
for (DyldCacheSlideInfoCommon slideInfo : slideFixupMap.keySet()) {
|
|
||||||
for (DyldFixup fixup : slideFixupMap.get(slideInfo)) {
|
|
||||||
monitor.increment();
|
|
||||||
long addr = slideInfo.getMappingAddress() + fixup.offset();
|
|
||||||
long fileOffset = slideInfo.getMappingFileOffset() + fixup.offset();
|
|
||||||
SegmentCommand segment = getSegmentContaining(addr);
|
|
||||||
if (segment == null) {
|
|
||||||
// Fixup is not in this Mach-O
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
byte[] newBytes = ExtractedMacho.toBytes(fixup.value(), fixup.size());
|
|
||||||
try {
|
|
||||||
System.arraycopy(newBytes, 0, packed,
|
|
||||||
(int) getPackedOffset(fileOffset, segment), newBytes.length);
|
|
||||||
}
|
|
||||||
catch (NotFoundException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the {@link SegmentCommand segment} that contains the given virtual address
|
|
||||||
*
|
|
||||||
* @param addr The address
|
|
||||||
* @return The {@link SegmentCommand segment} that contains the given virtual address
|
|
||||||
*/
|
|
||||||
private SegmentCommand getSegmentContaining(long addr) {
|
|
||||||
for (SegmentCommand segment : machoHeader.getAllSegments()) {
|
|
||||||
if (addr >= segment.getVMaddress() &&
|
|
||||||
addr < segment.getVMaddress() + segment.getVMsize()) {
|
|
||||||
return segment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
private ByteProvider provider;
|
private ByteProvider provider;
|
||||||
private SplitDyldCache splitDyldCache;
|
private SplitDyldCache splitDyldCache;
|
||||||
private boolean parsedLocalSymbols = false;
|
private boolean parsedLocalSymbols = false;
|
||||||
private Map<DyldCacheSlideInfoCommon, List<DyldFixup>> slideFixupMap;
|
private Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap;
|
||||||
private RangeMap<Long, DyldCacheEntry> rangeMap = TreeRangeMap.create();
|
private RangeMap<Long, DyldCacheEntry> rangeMap = TreeRangeMap.create();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,7 +94,7 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
rangeSet.add(range);
|
rangeSet.add(range);
|
||||||
}
|
}
|
||||||
DyldCacheEntry entry =
|
DyldCacheEntry entry =
|
||||||
new DyldCacheEntry(mappedImage.getPath(), i, rangeSet, null, -1);
|
new DyldCacheEntry(mappedImage.getPath(), i, rangeSet, null, null, -1);
|
||||||
rangeSet.asRanges().forEach(r -> rangeMap.put(r, entry));
|
rangeSet.asRanges().forEach(r -> rangeMap.put(r, entry));
|
||||||
allDylibRanges.addAll(rangeSet);
|
allDylibRanges.addAll(rangeSet);
|
||||||
fsIndex.storeFile(mappedImage.getPath(), fsIndex.getFileCount(), false, -1,
|
fsIndex.storeFile(mappedImage.getPath(), fsIndex.getFileCount(), false, -1,
|
||||||
|
@ -110,18 +110,24 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
DyldCacheHeader header = splitDyldCache.getDyldCacheHeader(i);
|
||||||
String name = splitDyldCache.getName(i);
|
String name = splitDyldCache.getName(i);
|
||||||
List<DyldCacheMappingAndSlideInfo> mappingInfos = header.getCacheMappingAndSlideInfos();
|
List<DyldCacheMappingInfo> mappingInfos = header.getMappingInfos();
|
||||||
|
List<DyldCacheMappingAndSlideInfo> mappingAndSlideInfos =
|
||||||
|
header.getCacheMappingAndSlideInfos();
|
||||||
for (int j = 0; j < mappingInfos.size(); j++) {
|
for (int j = 0; j < mappingInfos.size(); j++) {
|
||||||
DyldCacheMappingAndSlideInfo mappingInfo = mappingInfos.get(j);
|
DyldCacheMappingInfo mappingInfo = mappingInfos.get(j);
|
||||||
|
DyldCacheMappingAndSlideInfo mappingAndSlideInfo =
|
||||||
|
!mappingAndSlideInfos.isEmpty() ? mappingAndSlideInfos.get(j) : null;
|
||||||
Range<Long> mappingRange = Range.openClosed(mappingInfo.getAddress(),
|
Range<Long> mappingRange = Range.openClosed(mappingInfo.getAddress(),
|
||||||
mappingInfo.getAddress() + mappingInfo.getSize());
|
mappingInfo.getAddress() + mappingInfo.getSize());
|
||||||
RangeSet<Long> reducedRangeSet = TreeRangeSet.create();
|
RangeSet<Long> reducedRangeSet = TreeRangeSet.create();
|
||||||
reducedRangeSet.add(mappingRange);
|
reducedRangeSet.add(mappingRange);
|
||||||
reducedRangeSet.removeAll(allDylibRanges);
|
reducedRangeSet.removeAll(allDylibRanges);
|
||||||
for (Range<Long> range : reducedRangeSet.asRanges()) {
|
for (Range<Long> range : reducedRangeSet.asRanges()) {
|
||||||
String path = getComponentPath(name, mappingInfo, j, range);
|
String path =
|
||||||
|
getComponentPath(name, mappingInfo, mappingAndSlideInfo, j, range);
|
||||||
DyldCacheEntry entry = new DyldCacheEntry(path, i,
|
DyldCacheEntry entry = new DyldCacheEntry(path, i,
|
||||||
TreeRangeSet.create(CollectionUtils.asIterable(range)), mappingInfo, j);
|
TreeRangeSet.create(CollectionUtils.asIterable(range)), mappingInfo,
|
||||||
|
mappingAndSlideInfo, j);
|
||||||
rangeMap.put(range, entry);
|
rangeMap.put(range, entry);
|
||||||
fsIndex.storeFile(path, fsIndex.getFileCount(), false, -1, entry);
|
fsIndex.storeFile(path, fsIndex.getFileCount(), false, -1, entry);
|
||||||
}
|
}
|
||||||
|
@ -152,11 +158,11 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
try {
|
try {
|
||||||
if (entry.mappingInfo() != null) {
|
if (entry.mappingInfo() != null) {
|
||||||
return DyldCacheExtractor.extractMapping(entry,
|
return DyldCacheExtractor.extractMapping(entry,
|
||||||
getComponentName(entry.mappingInfo()), splitDyldCache,
|
getComponentName(entry.mappingAndSlideInfo()), splitDyldCache, slideFixupMap,
|
||||||
entry.splitCacheIndex(), slideFixupMap, file.getFSRL(), monitor);
|
file.getFSRL(), monitor);
|
||||||
}
|
}
|
||||||
return DyldCacheExtractor.extractDylib(entry, splitDyldCache, entry.splitCacheIndex(),
|
return DyldCacheExtractor.extractDylib(entry, splitDyldCache, slideFixupMap,
|
||||||
slideFixupMap, file.getFSRL(), monitor);
|
file.getFSRL(), monitor);
|
||||||
}
|
}
|
||||||
catch (MachException e) {
|
catch (MachException e) {
|
||||||
throw new IOException("Invalid Mach-O header detected at: " + entry);
|
throw new IOException("Invalid Mach-O header detected at: " + entry);
|
||||||
|
@ -213,32 +219,32 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
rangeMap.clear();
|
rangeMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getComponentName(DyldCacheMappingAndSlideInfo mappingInfo) {
|
private String getComponentName(DyldCacheMappingAndSlideInfo mappingAndSlideInfo) {
|
||||||
String name;
|
String name = "DYLD";
|
||||||
if (mappingInfo.isDirtyData()) {
|
if (mappingAndSlideInfo == null) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
if (mappingAndSlideInfo.isDirtyData()) {
|
||||||
name = "DATA_DIRTY";
|
name = "DATA_DIRTY";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isConstData()) {
|
else if (mappingAndSlideInfo.isConstData()) {
|
||||||
name = mappingInfo.isAuthData() ? "AUTH_CONST" : "DATA_CONST";
|
name = mappingAndSlideInfo.isAuthData() ? "AUTH_CONST" : "DATA_CONST";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isTextStubs()) {
|
else if (mappingAndSlideInfo.isTextStubs()) {
|
||||||
name = "TEXT_STUBS";
|
name = "TEXT_STUBS";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isConfigData()) {
|
else if (mappingAndSlideInfo.isConfigData()) {
|
||||||
name = "DATA_CONFIG";
|
name = "DATA_CONFIG";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isAuthData()) {
|
else if (mappingAndSlideInfo.isAuthData()) {
|
||||||
name = "AUTH";
|
name = "AUTH";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isReadOnlyData()) {
|
else if (mappingAndSlideInfo.isReadOnlyData()) {
|
||||||
name = "DATA_RO";
|
name = "DATA_RO";
|
||||||
}
|
}
|
||||||
else if (mappingInfo.isConstTproData()) {
|
else if (mappingAndSlideInfo.isConstTproData()) {
|
||||||
name = "DATA_CONST_TPRO";
|
name = "DATA_CONST_TPRO";
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
name = "DYLD";
|
|
||||||
}
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,9 +256,10 @@ public class DyldCacheFileSystem extends AbstractFileSystem<DyldCacheEntry> {
|
||||||
* @param mappingIndex The mapping index
|
* @param mappingIndex The mapping index
|
||||||
* @return The DYLD component path of the given DYLD component
|
* @return The DYLD component path of the given DYLD component
|
||||||
*/
|
*/
|
||||||
private String getComponentPath(String dyldCacheName, DyldCacheMappingAndSlideInfo mappingInfo,
|
private String getComponentPath(String dyldCacheName, DyldCacheMappingInfo mappingInfo,
|
||||||
int mappingIndex, Range<Long> range) {
|
DyldCacheMappingAndSlideInfo mappingAndSlideInfo, int mappingIndex, Range<Long> range) {
|
||||||
return "/DYLD/%s/%s.%d.0x%x-0x%x".formatted(dyldCacheName, getComponentName(mappingInfo),
|
return "/DYLD/%s/%s.%d.0x%x-0x%x".formatted(dyldCacheName,
|
||||||
mappingIndex, range.lowerEndpoint(), range.upperEndpoint());
|
getComponentName(mappingAndSlideInfo), mappingIndex, range.lowerEndpoint(),
|
||||||
|
range.upperEndpoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/* ###
|
||||||
|
* 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.file.formats.ios.dyldcache;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
import ghidra.app.util.bin.format.macho.dyld.DyldCacheMappingInfo;
|
||||||
|
import ghidra.app.util.bin.format.macho.dyld.DyldFixup;
|
||||||
|
import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ByteProvider} that provides slid dyld_shared_cache bytes for a given
|
||||||
|
* {@link DyldCacheMappingInfo byte mapping}
|
||||||
|
*/
|
||||||
|
public class DyldCacheSlidProvider implements ByteProvider {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private ByteProvider origProvider;
|
||||||
|
private DyldCacheMappingInfo mappingInfo;
|
||||||
|
private Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap;
|
||||||
|
private TaskMonitor monitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link DyldCacheSlidProvider}
|
||||||
|
*
|
||||||
|
* @param mappingInfo The {@link DyldCacheMappingInfo} that is being requested
|
||||||
|
* @param splitDyldCache The {@link SplitDyldCache}
|
||||||
|
* @param splitCacheIndex The mapping's {@link SplitDyldCache} index
|
||||||
|
* @param slideFixupMap A {@link Map} of {@link DyldFixup}s to perform
|
||||||
|
* @param monitor A {@link TaskMonitor} to monitor the reads
|
||||||
|
*/
|
||||||
|
public DyldCacheSlidProvider(DyldCacheMappingInfo mappingInfo, SplitDyldCache splitDyldCache,
|
||||||
|
int splitCacheIndex, Map<DyldCacheMappingInfo, Map<Long, DyldFixup>> slideFixupMap,
|
||||||
|
TaskMonitor monitor) {
|
||||||
|
this.name = splitDyldCache.getName(splitCacheIndex);
|
||||||
|
this.origProvider = splitDyldCache.getProvider(splitCacheIndex);
|
||||||
|
this.mappingInfo = mappingInfo;
|
||||||
|
this.slideFixupMap = slideFixupMap;
|
||||||
|
this.monitor = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte readByte(long index) throws IOException {
|
||||||
|
if (!mappingInfo.contains(index, false)) {
|
||||||
|
return origProvider.readByte(index);
|
||||||
|
}
|
||||||
|
Map<Long, DyldFixup> fixups = slideFixupMap.get(mappingInfo);
|
||||||
|
if (fixups == null) {
|
||||||
|
return origProvider.readByte(index);
|
||||||
|
}
|
||||||
|
long aligned = index & ~3;
|
||||||
|
DyldFixup fixup = fixups.get(aligned);
|
||||||
|
if (fixup == null) {
|
||||||
|
aligned = index & ~7;
|
||||||
|
fixup = fixups.get(aligned);
|
||||||
|
if (fixup != null && fixup.size() != 8) {
|
||||||
|
fixup = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fixup == null) {
|
||||||
|
return origProvider.readByte(index);
|
||||||
|
}
|
||||||
|
return (byte) (fixup.value() >> ((index - aligned) * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] readBytes(long index, long length) throws IOException {
|
||||||
|
if (length < 0 || length > Integer.MAX_VALUE) {
|
||||||
|
throw new IllegalArgumentException("unsupported length");
|
||||||
|
}
|
||||||
|
if (index < 0) {
|
||||||
|
throw new IllegalArgumentException("invalid index");
|
||||||
|
}
|
||||||
|
byte[] ret = new byte[(int) length];
|
||||||
|
monitor.initialize(length, "Reading " + name);
|
||||||
|
// TODO: spped this up by using super.readBytes() to read the chunks that don't contain fixups
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
monitor.incrementProgress();
|
||||||
|
ret[i] = readByte(index + i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile() {
|
||||||
|
return origProvider.getFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAbsolutePath() {
|
||||||
|
return origProvider.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long length() throws IOException {
|
||||||
|
return origProvider.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidIndex(long i) {
|
||||||
|
return origProvider.isValidIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// This is a wrapper, so don't close
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue