Skip to content

Commit 0241b2b

Browse files
committed
Merge remote-tracking branch 'origin/GP-2052_ryanmkurtz_prelink'
2 parents 9f4f3fc + 9cf8c84 commit 0241b2b

File tree

3 files changed

+51
-18
lines changed

3 files changed

+51
-18
lines changed

Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/MachHeader.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ public MachHeader parse() throws IOException, MachException {
139139
if (_parsed) {
140140
return this;
141141
}
142+
long currentIndex = _commandIndex;
142143
for (int i = 0; i < nCmds; ++i) {
143-
_reader.setPointerIndex(_commandIndex);
144+
_reader.setPointerIndex(currentIndex);
144145
LoadCommand lc = LoadCommandTypes.getLoadCommand(_reader, this);
145146
_commands.add(lc);
146-
_commandIndex += lc.getCommandSize();
147+
currentIndex += lc.getCommandSize();
147148
}
148149
_parsed = true;
149150
return this;
@@ -289,6 +290,15 @@ public boolean isLittleEndian() {//TODO -- if intel it is LE
289290
return magic == MachConstants.MH_CIGAM || magic == MachConstants.MH_CIGAM_64;
290291
}
291292

293+
/**
294+
* Gets the size of this {@link MachHeader} in bytes
295+
*
296+
* @return The size of this {@link MachHeader} in bytes
297+
*/
298+
public long getSize() {
299+
return _commandIndex - _machHeaderStartIndexInProvider;
300+
}
301+
292302
public String getDescription() {//TODO
293303
StringBuffer buffer = new StringBuffer();
294304
buffer.append("Magic: 0x" + Integer.toHexString(magic));

Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoPrelinkUtils.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
2323
import org.jdom.JDOMException;
2424

25-
import ghidra.app.util.bin.ByteProvider;
26-
import ghidra.app.util.bin.ByteProviderWrapper;
25+
import ghidra.app.util.bin.*;
2726
import ghidra.app.util.bin.format.macho.MachException;
2827
import ghidra.app.util.bin.format.macho.MachHeader;
2928
import ghidra.app.util.bin.format.macho.commands.*;
@@ -36,6 +35,42 @@
3635
*/
3736
public class MachoPrelinkUtils {
3837

38+
/**
39+
* Check to see if the given {@link ByteProvider} is a Mach-O PRELINK binary
40+
*
41+
* @param provider The {@link ByteProvider} to check
42+
* @param monitor A monitor
43+
* @return True if the given {@link ByteProvider} is a Mach-O PRELINK binary; otherwise, false
44+
*/
45+
public static boolean isMachoPrelink(ByteProvider provider, TaskMonitor monitor) {
46+
try {
47+
MachHeader header = new MachHeader(provider);
48+
BinaryReader reader = new BinaryReader(provider, header.isLittleEndian());
49+
reader.setPointerIndex(header.getSize());
50+
51+
// Doing a full header parse is too slow...we really just need to see if a segment
52+
// exists that starts with __PRELINK. Parse the minimal amount to do that check.
53+
for (int i = 0; i < header.getNumberOfCommands(); i++) {
54+
int type = reader.peekNextInt();
55+
if (type == LoadCommandTypes.LC_SEGMENT || type == LoadCommandTypes.LC_SEGMENT_64) {
56+
SegmentCommand segment = new SegmentCommand(reader, header.is32bit());
57+
if (segment.getSegmentName().startsWith("__PRELINK")) {
58+
return true;
59+
}
60+
}
61+
else {
62+
type = reader.readNextInt();
63+
int size = reader.readNextInt();
64+
reader.setPointerIndex(reader.getPointerIndex() + size - 8);
65+
}
66+
}
67+
}
68+
catch (MachException | IOException e) {
69+
// Assume it's not a Mach-O PRELINK...fall through
70+
}
71+
return false;
72+
}
73+
3974
/**
4075
* Parses the provider looking for PRELINK XML.
4176
*

Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/PrelinkFileSystem.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
*/
1616
package ghidra.file.formats.ios.prelink;
1717

18-
import java.util.*;
19-
2018
import java.io.IOException;
2119
import java.io.InputStream;
20+
import java.util.*;
2221

2322
import org.apache.commons.collections4.BidiMap;
2423
import org.jdom.JDOMException;
@@ -76,18 +75,7 @@ public void close() throws IOException {
7675

7776
@Override
7877
public boolean isValid(TaskMonitor monitor) throws IOException {
79-
try {
80-
return MachHeader.isMachHeader(provider) &&
81-
!MachoPrelinkUtils.parsePrelinkXml(provider, monitor).isEmpty();
82-
}
83-
catch (JDOMException e) {
84-
Msg.warn(this, e.getMessage());
85-
return true; // use KModInfo technique to open
86-
}
87-
catch (IOException e) {
88-
Msg.warn(this, e.getMessage());
89-
return false;
90-
}
78+
return MachoPrelinkUtils.isMachoPrelink(provider, monitor);
9179
}
9280

9381
@Override

0 commit comments

Comments
 (0)