Skip to content

Commit 26d4bd9

Browse files
committed
Merge branch 'GP-3565_ryanmkurtz_macho-markup'
2 parents 7073651 + cf3cc03 commit 26d4bd9

19 files changed

+666
-782
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ public void markup(Program program, MachHeader header, String source, TaskMonito
7979
}
8080
}
8181
catch (Exception e) {
82-
log.appendMsg(DyldChainedFixupsCommand.class.getSimpleName(), "Failed to markup %s."
83-
.formatted(LoadCommandTypes.getLoadCommandName(getCommandType())));
82+
log.appendMsg(DataInCodeCommand.class.getSimpleName(),
83+
"Failed to markup: " + getContextualName(source, null));
8484
}
8585
}
8686
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ public void markup(Program program, MachHeader header, String source, TaskMonito
100100
}
101101
}
102102
catch (Exception e) {
103-
log.appendMsg(DyldChainedFixupsCommand.class.getSimpleName(), "Failed to markup %s."
104-
.formatted(LoadCommandTypes.getLoadCommandName(getCommandType())));
103+
log.appendMsg(DyldChainedFixupsCommand.class.getSimpleName(),
104+
"Failed to markup: " + getContextualName(source, null));
105105
}
106106
}
107107

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
import java.io.IOException;
1919

2020
import ghidra.app.util.bin.BinaryReader;
21+
import ghidra.app.util.bin.format.macho.MachHeader;
22+
import ghidra.app.util.importer.MessageLog;
23+
import ghidra.program.model.address.Address;
24+
import ghidra.program.model.data.DataUtilities;
25+
import ghidra.program.model.listing.Program;
26+
import ghidra.util.exception.CancelledException;
27+
import ghidra.util.task.TaskMonitor;
2128

2229
/**
2330
* Represents a LC_DYLD_EXPORTS_TRIE command
@@ -49,4 +56,29 @@ public class DyldExportsTrieCommand extends LinkEditDataCommand {
4956
public ExportTrie getExportTrie() {
5057
return exportTrie;
5158
}
59+
60+
@Override
61+
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
62+
MessageLog log) throws CancelledException {
63+
Address addr = fileOffsetToAddress(program, header, dataoff, datasize);
64+
if (addr == null) {
65+
return;
66+
}
67+
super.markup(program, header, source, monitor, log);
68+
69+
try {
70+
for (long offset : exportTrie.getUlebOffsets()) {
71+
DataUtilities.createData(program, addr.add(offset), ULEB128, -1,
72+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
73+
}
74+
for (long offset : exportTrie.getStringOffsets()) {
75+
DataUtilities.createData(program, addr.add(offset), STRING, -1,
76+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
77+
}
78+
}
79+
catch (Exception e) {
80+
log.appendMsg(DyldExportsTrieCommand.class.getSimpleName(),
81+
"Failed to markup: " + getContextualName(source, null));
82+
}
83+
}
5284
}

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

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import ghidra.app.util.bin.BinaryReader;
2121
import ghidra.app.util.bin.format.macho.MachConstants;
2222
import ghidra.app.util.bin.format.macho.MachHeader;
23+
import ghidra.app.util.bin.format.macho.commands.dyld.BindOpcode;
24+
import ghidra.app.util.bin.format.macho.commands.dyld.BindingTable;
2325
import ghidra.app.util.importer.MessageLog;
2426
import ghidra.program.flatapi.FlatProgramAPI;
2527
import ghidra.program.model.address.Address;
@@ -45,6 +47,9 @@ public class DyldInfoCommand extends LoadCommand {
4547
private int exportOff;
4648
private int exportSize;
4749

50+
private BindingTable bindingTable;
51+
private BindingTable weakBindingTable;
52+
private BindingTable lazyBindingTable;
4853
private ExportTrie exportTrie;
4954

5055
/**
@@ -72,6 +77,32 @@ public class DyldInfoCommand extends LoadCommand {
7277
exportOff = loadCommandReader.readNextInt();
7378
exportSize = loadCommandReader.readNextInt();
7479

80+
// TODO: rebase
81+
82+
if (bindOff > 0 && bindSize > 0) {
83+
dataReader.setPointerIndex(header.getStartIndex() + bindOff);
84+
bindingTable = new BindingTable(dataReader, header, bindSize, false);
85+
}
86+
else {
87+
bindingTable = new BindingTable();
88+
}
89+
90+
if (weakBindOff > 0 && weakBindSize > 0) {
91+
dataReader.setPointerIndex(header.getStartIndex() + weakBindOff);
92+
weakBindingTable = new BindingTable(dataReader, header, weakBindSize, false);
93+
}
94+
else {
95+
weakBindingTable = new BindingTable();
96+
}
97+
98+
if (lazyBindOff > 0 && lazyBindSize > 0) {
99+
dataReader.setPointerIndex(header.getStartIndex() + lazyBindOff);
100+
lazyBindingTable = new BindingTable(dataReader, header, lazyBindSize, true);
101+
}
102+
else {
103+
lazyBindingTable = new BindingTable();
104+
}
105+
75106
if (exportOff > 0 && exportSize > 0) {
76107
dataReader.setPointerIndex(header.getStartIndex() + exportOff);
77108
exportTrie = new ExportTrie(dataReader);
@@ -151,6 +182,27 @@ public int getExportSize() {
151182
return exportSize;
152183
}
153184

185+
/**
186+
* {@return The binding table}
187+
*/
188+
public BindingTable getBindingTable() {
189+
return bindingTable;
190+
}
191+
192+
/**
193+
* {@return The lazy binding table}
194+
*/
195+
public BindingTable getLazyBindingTable() {
196+
return lazyBindingTable;
197+
}
198+
199+
/**
200+
* {@return The weak binding table}
201+
*/
202+
public BindingTable getWeakBindingTable() {
203+
return weakBindingTable;
204+
}
205+
154206
/**
155207
* {@return The export trie}
156208
*/
@@ -186,11 +238,10 @@ public DataType toDataType() throws DuplicateNameException, IOException {
186238
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
187239
MessageLog log) throws CancelledException {
188240
markupRebaseInfo(program, header, source, monitor, log);
189-
markupBindInfo(program, header, source, monitor, log);
190-
markupWeakBindInfo(program, header, source, monitor, log);
191-
markupLazyBindInfo(program, header, source, monitor, log);
241+
markupBindings(program, header, source, monitor, log);
242+
markupWeakBindings(program, header, source, monitor, log);
243+
markupLazyBindings(program, header, source, monitor, log);
192244
markupExportInfo(program, header, source, monitor, log);
193-
194245
}
195246

196247
private void markupRebaseInfo(Program program, MachHeader header, String source,
@@ -199,28 +250,80 @@ private void markupRebaseInfo(Program program, MachHeader header, String source,
199250
source, "rebase");
200251
}
201252

202-
private void markupBindInfo(Program program, MachHeader header, String source,
253+
private void markupBindings(Program program, MachHeader header, String source,
203254
TaskMonitor monitor, MessageLog log) {
204-
markupPlateComment(program, fileOffsetToAddress(program, header, bindOff, bindSize),
205-
source, "bind");
255+
Address bindAddr = fileOffsetToAddress(program, header, bindOff, bindSize);
256+
markupPlateComment(program, bindAddr, source, "bind");
257+
markupBindingTable(program, bindAddr, bindingTable, source, "bind", log);
206258
}
207259

208-
private void markupWeakBindInfo(Program program, MachHeader header, String source,
260+
private void markupWeakBindings(Program program, MachHeader header, String source,
209261
TaskMonitor monitor, MessageLog log) {
210-
markupPlateComment(program, fileOffsetToAddress(program, header, weakBindOff, weakBindSize),
211-
source, "weak bind");
262+
Address addr = fileOffsetToAddress(program, header, weakBindOff, weakBindSize);
263+
markupPlateComment(program, addr, source, "weak bind");
264+
markupBindingTable(program, addr, weakBindingTable, source, "weak bind", log);
265+
212266
}
213267

214-
private void markupLazyBindInfo(Program program, MachHeader header, String source,
268+
private void markupLazyBindings(Program program, MachHeader header, String source,
215269
TaskMonitor monitor, MessageLog log) {
216-
markupPlateComment(program, fileOffsetToAddress(program, header, lazyBindOff, lazyBindSize),
217-
source, "lazy bind");
270+
Address addr = fileOffsetToAddress(program, header, lazyBindOff, lazyBindSize);
271+
markupPlateComment(program, addr, source, "lazy bind");
272+
markupBindingTable(program, addr, lazyBindingTable, source, "lazy bind", log);
273+
}
274+
275+
private void markupBindingTable(Program program, Address addr, BindingTable table,
276+
String source, String additionalDescription, MessageLog log) {
277+
if (addr == null) {
278+
return;
279+
}
280+
try {
281+
DataType bindOpcodeDataType = BindOpcode.toDataType();
282+
for (long offset : table.getOpcodeOffsets()) {
283+
DataUtilities.createData(program, addr.add(offset), bindOpcodeDataType, -1,
284+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
285+
}
286+
for (long offset : table.getUlebOffsets()) {
287+
DataUtilities.createData(program, addr.add(offset), ULEB128, -1,
288+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
289+
}
290+
for (long offset : table.getSlebOffsets()) {
291+
DataUtilities.createData(program, addr.add(offset), SLEB128, -1,
292+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
293+
}
294+
for (long offset : table.getStringOffsets()) {
295+
DataUtilities.createData(program, addr.add(offset), STRING, -1,
296+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
297+
}
298+
}
299+
catch (Exception e) {
300+
log.appendMsg(DyldInfoCommand.class.getSimpleName(),
301+
"Failed to markup: " + getContextualName(source, additionalDescription));
302+
}
218303
}
219304

220305
private void markupExportInfo(Program program, MachHeader header, String source,
221306
TaskMonitor monitor, MessageLog log) {
222-
markupPlateComment(program, fileOffsetToAddress(program, header, exportOff, exportSize),
223-
source, "export");
307+
Address exportAddr = fileOffsetToAddress(program, header, exportOff, exportSize);
308+
if (exportAddr == null) {
309+
return;
310+
}
311+
markupPlateComment(program, exportAddr, source, "export");
312+
313+
try {
314+
for (long offset : exportTrie.getUlebOffsets()) {
315+
DataUtilities.createData(program, exportAddr.add(offset), ULEB128, -1,
316+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
317+
}
318+
for (long offset : exportTrie.getStringOffsets()) {
319+
DataUtilities.createData(program, exportAddr.add(offset), STRING, -1,
320+
DataUtilities.ClearDataMode.CHECK_FOR_SPACE);
321+
}
322+
}
323+
catch (Exception e) {
324+
log.appendMsg(DyldInfoCommand.class.getSimpleName(),
325+
"Failed to markup: " + getContextualName(source, "export"));
326+
}
224327
}
225328

226329
@Override

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ public final class DyldInfoCommandConstants {
5252

5353
public final static int BIND_OPCODE_MASK = 0xF0;
5454
public final static int BIND_IMMEDIATE_MASK = 0x0F;
55-
public final static int BIND_OPCODE_DONE = 0x00;
56-
public final static int BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10;
57-
public final static int BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20;
58-
public final static int BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30;
59-
public final static int BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40;
60-
public final static int BIND_OPCODE_SET_TYPE_IMM = 0x50;
61-
public final static int BIND_OPCODE_SET_ADDEND_SLEB = 0x60;
62-
public final static int BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70;
63-
public final static int BIND_OPCODE_ADD_ADDR_ULEB = 0x80;
64-
public final static int BIND_OPCODE_DO_BIND = 0x90;
65-
public final static int BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0;
66-
public final static int BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0;
67-
public final static int BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0;
68-
public final static int BIND_OPCODE_THREADED = 0xD0;
55+
public final static int BIND_OPCODE_DONE = 0x00;
56+
public final static int BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10;
57+
public final static int BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20;
58+
public final static int BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30;
59+
public final static int BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40;
60+
public final static int BIND_OPCODE_SET_TYPE_IMM = 0x50;
61+
public final static int BIND_OPCODE_SET_ADDEND_SLEB = 0x60;
62+
public final static int BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70;
63+
public final static int BIND_OPCODE_ADD_ADDR_ULEB = 0x80;
64+
public final static int BIND_OPCODE_DO_BIND = 0x90;
65+
public final static int BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0;
66+
public final static int BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0;
67+
public final static int BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0;
68+
public final static int BIND_OPCODE_THREADED = 0xD0;
6969

7070
public final static int BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB = 0x00;
7171
public final static int BIND_SUBOPCODE_THREADED_APPLY = 0x01;

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,8 @@ private void markupIndirectSymbolTable(Program program, MachHeader header, Strin
395395
}
396396
}
397397
catch (Exception e) {
398-
String name = LoadCommandTypes.getLoadCommandName(getCommandType()) + " (indirect)";
399398
log.appendMsg(DynamicSymbolTableCommand.class.getSimpleName(),
400-
"Failed to markup %s.".formatted(name));
399+
"Failed to markup: " + getContextualName(source, "indirect"));
401400
}
402401
}
403402

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,19 @@ public class ExportTrie {
3535

3636
private BinaryReader reader;
3737
private long base;
38+
3839
private List<ExportEntry> exports;
40+
private List<Long> ulebOffsets;
41+
private List<Long> stringOffsets;
3942

4043
/**
4144
* Creates an empty {@link ExportTrie}. This is useful for export trie load commands that are
4245
* defined but do not point to any data.
4346
*/
4447
public ExportTrie() {
4548
this.exports = new ArrayList<>();
49+
this.ulebOffsets = new ArrayList<>();
50+
this.stringOffsets = new ArrayList<>();
4651
}
4752

4853
/**
@@ -105,30 +110,38 @@ private void parseTrie() throws IOException {
105110
private LinkedList<Node> parseNode(String name, int offset) throws IOException {
106111
LinkedList<Node> children = new LinkedList<>();
107112
reader.setPointerIndex(base + offset);
113+
ulebOffsets.add(reader.getPointerIndex() - base);
108114
int terminalSize = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
109115
long childrenIndex = reader.getPointerIndex() + terminalSize;
110116
if (terminalSize != 0) {
117+
ulebOffsets.add(reader.getPointerIndex() - base);
111118
long flags = reader.readNext(LEB128::unsigned);
112119
long address = 0;
113120
long other = 0;
114121
String importName = null;
115122
if ((flags & EXPORT_SYMBOL_FLAGS_REEXPORT) != 0) {
123+
ulebOffsets.add(reader.getPointerIndex() - base);
116124
other = reader.readNext(LEB128::unsigned); // dylib ordinal
117125
importName = reader.readNextAsciiString();
118126
}
119127
else {
128+
ulebOffsets.add(reader.getPointerIndex() - base);
120129
address = reader.readNext(LEB128::unsigned);
121130
if ((flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) != 0) {
131+
ulebOffsets.add(reader.getPointerIndex() - base);
122132
other = reader.readNext(LEB128::unsigned);
123133
}
124134
}
125135
ExportEntry export = new ExportEntry(name, address, flags, other, importName);
126136
exports.add(export);
127137
}
128138
reader.setPointerIndex(childrenIndex);
139+
ulebOffsets.add(reader.getPointerIndex() - base);
129140
int numChildren = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
130141
for (int i = 0; i < numChildren; i++) {
142+
stringOffsets.add(reader.getPointerIndex() - base);
131143
String childName = reader.readNextAsciiString();
144+
ulebOffsets.add(reader.getPointerIndex() - base);
132145
int childOffset = reader.readNextUnsignedVarIntExact(LEB128::unsigned);
133146
children.add(new Node(childName, childOffset));
134147
}
@@ -163,6 +176,20 @@ public String toString() {
163176
}
164177
}
165178

179+
/**
180+
* {@return ULEB128 offsets from the start of the export trie}
181+
*/
182+
public List<Long> getUlebOffsets() {
183+
return ulebOffsets;
184+
}
185+
186+
/**
187+
* {@return String offsets from the start of the export trie}
188+
*/
189+
public List<Long> getStringOffsets() {
190+
return stringOffsets;
191+
}
192+
166193
/**
167194
* A trie node
168195
*/

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ public void markup(Program program, MachHeader header, String source, TaskMonito
112112

113113
}
114114
catch (Exception e) {
115-
log.appendMsg(DyldChainedFixupsCommand.class.getSimpleName(), "Failed to markup %s."
116-
.formatted(LoadCommandTypes.getLoadCommandName(getCommandType())));
115+
log.appendMsg(FunctionStartsCommand.class.getSimpleName(),
116+
"Failed to markup: " + getContextualName(source, null));
117117
}
118118
}
119119
}

0 commit comments

Comments
 (0)