Merge remote-tracking branch 'origin/Ghidra_11.4'

This commit is contained in:
Ryan Kurtz 2025-05-15 11:58:09 -04:00
commit 33b9688d7c
15 changed files with 138 additions and 121 deletions

View file

@ -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.
@ -43,9 +43,10 @@ public final class DyldInfoCommandConstants {
public final static int BIND_TYPE_TEXT_ABSOLUTE32 = 2; public final static int BIND_TYPE_TEXT_ABSOLUTE32 = 2;
public final static int BIND_TYPE_TEXT_PCREL32 = 3; public final static int BIND_TYPE_TEXT_PCREL32 = 3;
public final static int BIND_SPECIAL_DYLIB_SELF = 0; public final static int BIND_SPECIAL_DYLIB_SELF = 0;
public final static int BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1; public final static int BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1;
public final static int BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2; public final static int BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2;
public final static int BIND_SPECIAL_DYLIB_WEAK_LOOKUP = -3;
public final static int BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1; public final static int BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1;
public final static int BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8; public final static int BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8;

View file

@ -28,15 +28,15 @@ import ghidra.app.util.opinion.MachoProgramBuilder;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status; import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.*;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DyldChainedFixups { public class DyldChainedFixups {
public static final int RELOCATION_TYPE = 0x8888;
/** /**
* Walks the chained fixup information and collects a {@link List} of {@link DyldFixup}s that * Walks the chained fixup information and collects a {@link List} of {@link DyldFixup}s that
* will need to be applied to the image * will need to be applied to the image
@ -67,10 +67,10 @@ public class DyldChainedFixups {
long chainLoc = page + nextOff; long chainLoc = page + nextOff;
final long chainValue = DyldChainedPtr.getChainValue(reader, chainLoc, pointerFormat); final long chainValue = DyldChainedPtr.getChainValue(reader, chainLoc, pointerFormat);
long newChainValue = chainValue; Long newChainValue = chainValue;
boolean isAuthenticated = DyldChainedPtr.isAuthenticated(pointerFormat, chainValue); boolean isAuthenticated = DyldChainedPtr.isAuthenticated(pointerFormat, chainValue);
boolean isBound = DyldChainedPtr.isBound(pointerFormat, chainValue); boolean isBound = DyldChainedPtr.isBound(pointerFormat, chainValue);
Symbol symbol = null; String symbol = null;
Integer libOrdinal = null; Integer libOrdinal = null;
if (isBound) { if (isBound) {
@ -88,13 +88,16 @@ public class DyldChainedFixups {
int chainOrdinal = (int) DyldChainedPtr.getOrdinal(pointerFormat, chainValue); int chainOrdinal = (int) DyldChainedPtr.getOrdinal(pointerFormat, chainValue);
long addend = DyldChainedPtr.getAddend(pointerFormat, chainValue); long addend = DyldChainedPtr.getAddend(pointerFormat, chainValue);
DyldChainedImport chainedImport = chainedImports.getChainedImport(chainOrdinal); DyldChainedImport chainedImport = chainedImports.getChainedImport(chainOrdinal);
List<Symbol> globalSymbols = symbolTable.getGlobalSymbols(chainedImport.getName()); symbol = SymbolUtilities.replaceInvalidChars(chainedImport.getName(), true);
libOrdinal = chainedImport.getLibOrdinal();
List<Symbol> globalSymbols = symbolTable.getGlobalSymbols(symbol);
if (globalSymbols.size() > 0) { if (globalSymbols.size() > 0) {
symbol = globalSymbols.get(0); newChainValue = globalSymbols.getFirst().getAddress().getOffset();
newChainValue = symbol.getAddress().getOffset(); newChainValue += isAuthenticated ? auth_value_add : addend;
libOrdinal = chainedImport.getLibOrdinal(); }
else {
newChainValue = null;
} }
newChainValue += isAuthenticated ? auth_value_add : addend;
} }
else { else {
if (isAuthenticated) { if (isAuthenticated) {
@ -110,7 +113,7 @@ public class DyldChainedFixups {
} }
fixups.add(new DyldFixup(chainLoc, newChainValue, DyldChainedPtr.getSize(pointerFormat), fixups.add(new DyldFixup(chainLoc, newChainValue, DyldChainedPtr.getSize(pointerFormat),
symbol != null ? symbol.getName() : null, libOrdinal)); symbol, libOrdinal));
next = DyldChainedPtr.getNext(pointerFormat, chainValue); next = DyldChainedPtr.getNext(pointerFormat, chainValue);
nextOff += next * DyldChainedPtr.getStride(pointerFormat); nextOff += next * DyldChainedPtr.getStride(pointerFormat);
@ -128,12 +131,11 @@ public class DyldChainedFixups {
* @param log The log * @param log The log
* @param monitor A cancellable monitor * @param monitor A cancellable monitor
* @return A {@link List} of fixed up {@link Address}'s * @return A {@link List} of fixed up {@link Address}'s
* @throws MemoryAccessException If there was a problem accessing memory
* @throws CancelledException If the user cancelled the operation * @throws CancelledException If the user cancelled the operation
*/ */
public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program, public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program,
Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor) Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor)
throws MemoryAccessException, CancelledException { throws CancelledException {
List<Address> fixedAddrs = new ArrayList<>(); List<Address> fixedAddrs = new ArrayList<>();
if (fixups.isEmpty()) { if (fixups.isEmpty()) {
return fixedAddrs; return fixedAddrs;
@ -142,37 +144,42 @@ public class DyldChainedFixups {
monitor.initialize(fixups.size(), "Fixing up chained pointers..."); monitor.initialize(fixups.size(), "Fixing up chained pointers...");
for (DyldFixup fixup : fixups) { for (DyldFixup fixup : fixups) {
monitor.increment(); monitor.increment();
Status status = Status.FAILURE; Status status = Status.UNSUPPORTED;
Address addr = imagebase.add(fixup.offset()); Address addr = imagebase.add(fixup.offset());
String symbol = fixup.symbol();
long[] value = new long[] {};
try { try {
if (fixup.size() == 8 || fixup.size() == 4) { if (fixup.value() != null) {
if (fixup.size() == 8) { if (fixup.size() == 8 || fixup.size() == 4) {
memory.setLong(addr, fixup.value()); if (fixup.size() == 8) {
memory.setLong(addr, fixup.value());
}
else {
memory.setInt(addr, fixup.value().intValue());
}
fixedAddrs.add(addr);
status = Status.APPLIED_OTHER;
} }
else { value = new long[] { fixup.value() };
memory.setInt(addr, (int) fixup.value()); }
if (symbol != null && fixup.libOrdinal() != null) {
value = new long[] { fixup.libOrdinal() };
try {
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
fixup.libOrdinal(), symbol);
}
catch (Exception e) {
log.appendMsg("WARNING: Problem fixing up symbol '%s' - %s"
.formatted(symbol, e.getMessage()));
} }
fixedAddrs.add(addr);
status = Status.APPLIED_OTHER;
}
else {
status = Status.UNSUPPORTED;
} }
} }
catch (Exception e) {
status = Status.FAILURE;
}
finally { finally {
program.getRelocationTable() program.getRelocationTable()
.add(addr, status, 0, new long[] { fixup.value() }, fixup.size(), .add(addr, status, RELOCATION_TYPE, value, fixup.size(), symbol);
fixup.symbol() != null ? fixup.symbol() : null);
}
if (fixup.symbol() != null && fixup.libOrdinal() != null) {
try {
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
fixup.libOrdinal(), fixup.symbol());
}
catch (Exception e) {
log.appendMsg("WARNING: Problem fixing up symbol '%s' - %s"
.formatted(fixup.symbol(), e.getMessage()));
}
} }
} }
log.appendMsg("Fixed up " + fixedAddrs.size() + " chained pointers."); log.appendMsg("Fixed up " + fixedAddrs.size() + " chained pointers.");

View file

@ -47,14 +47,16 @@ public class DyldChainedImport implements StructConverter {
switch (imports_format) { switch (imports_format) {
case DYLD_CHAINED_IMPORT: { case DYLD_CHAINED_IMPORT: {
int ival = reader.readNextInt(); int ival = reader.readNextInt();
lib_ordinal = ival & 0xff; int ordinal = ival & 0xff;
lib_ordinal = ordinal > 0xf0 ? (byte) ordinal : ordinal;
weak_import = ((ival >> 8) & 1) == 1; weak_import = ((ival >> 8) & 1) == 1;
name_offset = (ival >> 9 & 0x7fffff); name_offset = (ival >> 9 & 0x7fffff);
break; break;
} }
case DYLD_CHAINED_IMPORT_ADDEND: { case DYLD_CHAINED_IMPORT_ADDEND: {
int ival = reader.readNextInt(); int ival = reader.readNextInt();
lib_ordinal = ival & 0xff; int ordinal = ival & 0xff;
lib_ordinal = ordinal > 0xf0 ? (byte) ordinal : ordinal;
weak_import = ((ival >> 8) & 1) == 1; weak_import = ((ival >> 8) & 1) == 1;
name_offset = (ival >> 9 & 0x7fffff); name_offset = (ival >> 9 & 0x7fffff);
addend = reader.readNextInt(); addend = reader.readNextInt();
@ -62,7 +64,8 @@ public class DyldChainedImport implements StructConverter {
} }
case DYLD_CHAINED_IMPORT_ADDEND64: { case DYLD_CHAINED_IMPORT_ADDEND64: {
long ival = reader.readNextLong(); long ival = reader.readNextLong();
lib_ordinal = (int) (ival & 0xffff); int ordinal = (int) (ival & 0xffff);
lib_ordinal = ordinal > 0xfff0 ? (short) ordinal : ordinal;
weak_import = ((ival >> 16) & 1) == 1; weak_import = ((ival >> 16) & 1) == 1;
name_offset = ((ival >> 32) & 0xffffffffL); name_offset = ((ival >> 32) & 0xffffffffL);
addend = reader.readNextLong(); addend = reader.readNextLong();

View file

@ -207,7 +207,7 @@ public class DyldCacheSlideInfo4 extends DyldCacheSlideInfoCommon {
chainValue += valueAdd /* + slide */; chainValue += valueAdd /* + slide */;
} }
fixups.add(new DyldFixup(dataOffset, chainValue, 4, null, null)); fixups.add(new DyldFixup(dataOffset, Long.valueOf(chainValue), 4, null, null));
} }
return fixups; return fixups;

View file

@ -173,7 +173,7 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
memory.setLong(addr, fixup.value()); memory.setLong(addr, fixup.value());
} }
else { else {
memory.setInt(addr, (int) fixup.value()); memory.setInt(addr, fixup.value().intValue());
} }
} }

View file

@ -19,9 +19,9 @@ package ghidra.app.util.bin.format.macho.dyld;
* Stores information needed to perform a dyld pointer fixup * Stores information needed to perform a dyld pointer fixup
* *
* @param offset The offset of where to perform the fixup (from some base address/index) * @param offset The offset of where to perform the fixup (from some base address/index)
* @param value The fixed up value * @param value The fixed up value, or {@code null} if this fixup is unsupported
* @param size The size of the fixup in bytes * @param size The size of the fixup in bytes
* @param symbol The symbol associated with the fixup (could be null) * @param symbol The symbol associated with the fixup (could be null)
* @param libOrdinal The library ordinal associated with the fixup (could be null) * @param libOrdinal The library ordinal associated with the fixup (could be null)
*/ */
public record DyldFixup(long offset, long value, int size, String symbol, Integer libOrdinal) {} public record DyldFixup(long offset, Long value, int size, String symbol, Integer libOrdinal) {}

View file

@ -684,17 +684,14 @@ public class MachoProgramBuilder {
monitor.increment(); monitor.increment();
int symbolIndex = indirectSymbols.get(i); int symbolIndex = indirectSymbols.get(i);
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex); NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
if (symbol != null) { String name =
String name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true); symbol != null ? SymbolUtilities.replaceInvalidChars(symbol.getString(), true)
if (name != null && name.length() > 0) { : "STUB_" + startAddr;
Function stubFunc = createOneByteFunction(name, startAddr); Function stubFunc = createOneByteFunction(name, startAddr);
if (stubFunc != null) { if (stubFunc != null && symbol != null) {
ExternalLocation loc = program.getExternalManager() ExternalLocation loc = program.getExternalManager()
.addExtLocation(Library.UNKNOWN, name, null, .addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
SourceType.IMPORTED); stubFunc.setThunkedFunction(loc.createFunction());
stubFunc.setThunkedFunction(loc.createFunction());
}
}
} }
startAddr = startAddr.add(symbolSize); startAddr = startAddr.add(symbolSize);
@ -1283,7 +1280,8 @@ public class MachoProgramBuilder {
String libraryPath = null; String libraryPath = null;
if (command instanceof DynamicLibraryCommand dylibCommand) { if (command instanceof DynamicLibraryCommand dylibCommand &&
dylibCommand.getCommandType() != LoadCommandTypes.LC_ID_DYLIB) {
DynamicLibrary dylib = dylibCommand.getDynamicLibrary(); DynamicLibrary dylib = dylibCommand.getDynamicLibrary();
libraryPath = dylib.getName().getString(); libraryPath = dylib.getName().getString();
} }
@ -1861,6 +1859,15 @@ public class MachoProgramBuilder {
*/ */
public static void fixupExternalLibrary(Program program, List<String> libraryPaths, public static void fixupExternalLibrary(Program program, List<String> libraryPaths,
int libraryOrdinal, String symbol) throws Exception { int libraryOrdinal, String symbol) throws Exception {
switch (libraryOrdinal) {
case DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_SELF:
case DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
case DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
case DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
return;
}
ExternalManager extManager = program.getExternalManager(); ExternalManager extManager = program.getExternalManager();
int libraryIndex = libraryOrdinal - 1; int libraryIndex = libraryOrdinal - 1;
if (libraryIndex < 0 || libraryIndex >= libraryPaths.size()) { if (libraryIndex < 0 || libraryIndex >= libraryPaths.size()) {

View file

@ -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.
@ -52,6 +52,46 @@ public class ExternalSymbolResolver implements Closeable {
StringUtilities.pad("" + libraryIndex, ' ', 4)); StringUtilities.pad("" + libraryIndex, ' ', 4));
} }
/**
* Returns an ordered list of library names, as specified by the logic/rules of the original
* operating system's loader (eg. Elf / MachO dynamic library loading / symbol resolving
* rules)
*
* @param program The {@link Program}
* @return list of library names, in original order
*/
public static List<String> getOrderedRequiredLibraryNames(Program program) {
TreeMap<Integer, String> orderLibraryMap = new TreeMap<>();
Options options = program.getOptions(Program.PROGRAM_INFO);
for (String optionName : options.getOptionNames()) {
// Legacy programs may have the old "ELF Required Library [" program property, so
// we should not assume that the option name starts exactly with
// REQUIRED_LIBRARY_PROPERTY_PREFIX. We must deal with a potential substring at the
// start of the option name.
int prefixIndex = optionName.indexOf(REQUIRED_LIBRARY_PROPERTY_PREFIX);
if (prefixIndex == -1 || !optionName.endsWith("]")) {
continue;
}
String libName = options.getString(optionName, null);
if (libName == null) {
continue;
}
String indexStr = optionName
.substring(prefixIndex + REQUIRED_LIBRARY_PROPERTY_PREFIX.length(),
optionName.length() - 1)
.trim();
try {
orderLibraryMap.put(Integer.parseInt(indexStr), libName.trim());
}
catch (NumberFormatException e) {
Msg.error(ExternalSymbolResolver.class,
"Program contains invalid property: " + optionName);
}
}
return new ArrayList<>(orderLibraryMap.values());
}
private final ProjectData projectData; private final ProjectData projectData;
private final TaskMonitor monitor; private final TaskMonitor monitor;
private final List<ProgramSymbolResolver> programsToFix = new ArrayList<>(); private final List<ProgramSymbolResolver> programsToFix = new ArrayList<>();
@ -333,7 +373,7 @@ public class ExternalSymbolResolver implements Closeable {
private List<ExtLibInfo> getLibsToSearch() throws CancelledException { private List<ExtLibInfo> getLibsToSearch() throws CancelledException {
List<ExtLibInfo> result = new ArrayList<>(); List<ExtLibInfo> result = new ArrayList<>();
ExternalManager externalManager = program.getExternalManager(); ExternalManager externalManager = program.getExternalManager();
for (String libName : getOrderedRequiredLibraryNames()) { for (String libName : getOrderedRequiredLibraryNames(program)) {
Library lib = externalManager.getExternalLibrary(libName); Library lib = externalManager.getExternalLibrary(libName);
String libPath = lib != null ? lib.getAssociatedProgramPath() : null; String libPath = lib != null ? lib.getAssociatedProgramPath() : null;
Program libProg = libPath != null ? getLibraryProgram(libPath) : null; Program libProg = libPath != null ? getLibraryProgram(libPath) : null;
@ -409,46 +449,6 @@ public class ExternalSymbolResolver implements Closeable {
} }
return symbolIds; return symbolIds;
} }
/**
* Returns an ordered list of library names, as specified by the logic/rules of the original
* operating system's loader (eg. Elf / MachO dynamic library loading / symbol resolving
* rules)
*
* @return list of library names, in original order
*/
private Collection<String> getOrderedRequiredLibraryNames() {
TreeMap<Integer, String> orderLibraryMap = new TreeMap<>();
Options options = program.getOptions(Program.PROGRAM_INFO);
for (String optionName : options.getOptionNames()) {
// Legacy programs may have the old "ELF Required Library [" program property, so
// we should not assume that the option name starts exactly with
// REQUIRED_LIBRARY_PROPERTY_PREFIX. We must deal with a potential substring at the
// start of the option name.
int prefixIndex = optionName.indexOf(REQUIRED_LIBRARY_PROPERTY_PREFIX);
if (prefixIndex == -1 || !optionName.endsWith("]")) {
continue;
}
String libName = options.getString(optionName, null);
if (libName == null) {
continue;
}
String indexStr = optionName
.substring(prefixIndex + REQUIRED_LIBRARY_PROPERTY_PREFIX.length(),
optionName.length() - 1)
.trim();
try {
orderLibraryMap.put(Integer.parseInt(indexStr), libName.trim());
}
catch (NumberFormatException e) {
Msg.error(ExternalSymbolResolver.class,
"Program contains invalid property: " + optionName);
}
}
return orderLibraryMap.values();
}
} }
/** /**

View file

@ -352,9 +352,9 @@ id="the-listings-are-not-in-sync-i.e.-they-do-not-move-together."
class="level3"> class="level3">
<h3>The listings are not in sync, i.e., they do not move together.</h3> <h3>The listings are not in sync, i.e., they do not move together.</h3>
<p>First, check that synchronization is enabled. This is the default <p>First, check that synchronization is enabled. This is the default
behavior, but, still, check it first. In the top-right of the Dynamic behavior, but, still, check it first. In the <strong>Debugger →
Listing is its local drop-down menu. Click it and check that Synchronization</strong> menu, check that <strong>Synchronize Static and
<strong>Auto-Sync Cursor with Static Listing</strong> is selected.</p> Dynamic Locations</strong> is selected.</p>
<p>If that does not work, check the top-left label of the Dynamic <p>If that does not work, check the top-left label of the Dynamic
Listing to see what module you are in. Also check the Debug Console Listing to see what module you are in. Also check the Debug Console
window. If you are in a system library, e.g., <code>ld-linux</code>, window. If you are in a system library, e.g., <code>ld-linux</code>,

View file

@ -167,8 +167,7 @@ The re-use of connections and/or the use of multiple concurrent connections is *
First, check that synchronization is enabled. First, check that synchronization is enabled.
This is the default behavior, but, still, check it first. This is the default behavior, but, still, check it first.
In the top-right of the Dynamic Listing is its local drop-down menu. In the **Debugger &rarr; Synchronization** menu, check that **Synchronize Static and Dynamic Locations** is selected.
Click it and check that **Auto-Sync Cursor with Static Listing** is selected.
If that does not work, check the top-left label of the Dynamic Listing to see what module you are in. If that does not work, check the top-left label of the Dynamic Listing to see what module you are in.
Also check the Debug Console window. Also check the Debug Console window.

View file

@ -162,8 +162,7 @@ src="images/breakpoint-enable.png" alt="set breakpoint" /> Set
Breakpoint, press <strong><code>K</code></strong> on the keyboard, or Breakpoint, press <strong><code>K</code></strong> on the keyboard, or
double-click the margin.</li> double-click the margin.</li>
<li>From the Breakpoints window, use the <strong>Set Breakpoint</strong> <li>From the Breakpoints window, use the <strong>Set Breakpoint</strong>
dropdown to access the various breakpoint actions defined by dropdown to access the various breakpoint actions defined by GDB.</li>
GDB.</li>
<li>From the Terminal window, use the GDB command, e.g., <li>From the Terminal window, use the GDB command, e.g.,
<code>break main</code>.</li> <code>break main</code>.</li>
</ol> </ol>

View file

@ -239,11 +239,11 @@ caused the target to break. This only applies to snapshots that were
created because of an event, which is most.</li> created because of an event, which is most.</li>
<li>The <strong>PC</strong> column gives the address of the next <li>The <strong>PC</strong> column gives the address of the next
instruction.</li> instruction.</li>
<li>The <strong>Module</strong> column gives the name of the module
containing the PC.</li>
<li>The <strong>Function</strong> column gives the name of the function <li>The <strong>Function</strong> column gives the name of the function
containing the PC mapped to its static program database, if containing the PC mapped to its static program database, if
available.</li> available.</li>
<li>The <strong>Module</strong> column gives the name of the module
containing the PC.</li>
<li>The <strong>Description</strong> column describes the event that <li>The <strong>Description</strong> column describes the event that
generated the snapshot. This can be edited in the table, or by pressing generated the snapshot. This can be edited in the table, or by pressing
<strong><code>CTRL</code>-<code>SHIFT</code>-<code>N</code></strong> to <strong><code>CTRL</code>-<code>SHIFT</code>-<code>N</code></strong> to

View file

@ -128,8 +128,8 @@ The columns are:
* The **Event Thread** column indicates which thread caused the target to break. * The **Event Thread** column indicates which thread caused the target to break.
This only applies to snapshots that were created because of an event, which is most. This only applies to snapshots that were created because of an event, which is most.
* The **PC** column gives the address of the next instruction. * The **PC** column gives the address of the next instruction.
* The **Function** column gives the name of the function containing the PC mapped to its static program database, if available.
* The **Module** column gives the name of the module containing the PC. * The **Module** column gives the name of the module containing the PC.
* The **Function** column gives the name of the function containing the PC mapped to its static program database, if available.
* The **Description** column describes the event that generated the snapshot. * The **Description** column describes the event that generated the snapshot.
This can be edited in the table, or by pressing **`CTRL`-`SHIFT`-`N`** to mark interesting snapshots. This can be edited in the table, or by pressing **`CTRL`-`SHIFT`-`N`** to mark interesting snapshots.

View file

@ -55,9 +55,9 @@ Mappings</a></li>
<li><a href="#moving-knowledge-from-dynamic-to-static" <li><a href="#moving-knowledge-from-dynamic-to-static"
id="toc-moving-knowledge-from-dynamic-to-static">Moving Knowledge from id="toc-moving-knowledge-from-dynamic-to-static">Moving Knowledge from
Dynamic to Static</a></li> Dynamic to Static</a></li>
<li><a href="#exercise-export-and-map-ncurses" <li><a href="#exercise-export-and-map-system-supplied-dso"
id="toc-exercise-export-and-map-ncurses">Exercise: Export and Map id="toc-exercise-export-and-map-system-supplied-dso">Exercise: Export
<code>ncurses</code></a></li> and Map <code>system-supplied DSO</code></a></li>
<li><a href="#exercise-cheat-like-the-devs" <li><a href="#exercise-cheat-like-the-devs"
id="toc-exercise-cheat-like-the-devs">Exercise: Cheat Like the id="toc-exercise-cheat-like-the-devs">Exercise: Cheat Like the
Devs</a></li> Devs</a></li>
@ -276,7 +276,7 @@ anyway.</p></li>
<li><p>The table displays the <em>copy plan</em>. For a new program, <li><p>The table displays the <em>copy plan</em>. For a new program,
this will copy with an identical mapping of addresses, which is probably this will copy with an identical mapping of addresses, which is probably
the best plan, since the target system has already applied fixups. Do the best plan, since the target system has already applied fixups. Do
not change any addresses, lest your corrupt references in the not change any addresses, lest you corrupt references in the
copy.</p></li> copy.</p></li>
<li><p>Click <strong>Copy</strong>.</p></li> <li><p>Click <strong>Copy</strong>.</p></li>
<li><p>When prompted, name the program <code>libncurses</code>.</p></li> <li><p>When prompted, name the program <code>libncurses</code>.</p></li>
@ -296,8 +296,9 @@ libncurses</strong>.</li>
<li>Check the proposed mapping and click <strong>OK</strong>.</li> <li>Check the proposed mapping and click <strong>OK</strong>.</li>
</ol> </ol>
</section> </section>
<section id="exercise-export-and-map-ncurses" class="level2"> <section id="exercise-export-and-map-system-supplied-dso"
<h2>Exercise: Export and Map <code>ncurses</code></h2> class="level2">
<h2>Exercise: Export and Map <code>system-supplied DSO</code></h2>
<p>Repeat this technique for the “system-supplied DSO” module. In <p>Repeat this technique for the “system-supplied DSO” module. In
practice, there is no real reason to do this, but this particular module practice, there is no real reason to do this, but this particular module
prevents you from using <strong>Import From File System</strong>.</p> prevents you from using <strong>Import From File System</strong>.</p>

View file

@ -144,7 +144,7 @@ For demonstration, we will walk through this second case, pretending we cannot l
1. It is probably best to include everything, though **Bytes** is the bare minimum. 1. It is probably best to include everything, though **Bytes** is the bare minimum.
1. The table displays the *copy plan*. 1. The table displays the *copy plan*.
For a new program, this will copy with an identical mapping of addresses, which is probably the best plan, since the target system has already applied fixups. For a new program, this will copy with an identical mapping of addresses, which is probably the best plan, since the target system has already applied fixups.
Do not change any addresses, lest your corrupt references in the copy. Do not change any addresses, lest you corrupt references in the copy.
1. Click **Copy**. 1. Click **Copy**.
1. When prompted, name the program `libncurses`. 1. When prompted, name the program `libncurses`.
1. You may need to click the `termmines` tab in the Static Listing to get the UI to completely update. 1. You may need to click the `termmines` tab in the Static Listing to get the UI to completely update.
@ -157,7 +157,7 @@ Undoubtedly, we would like to map that new program into our dynamic session.
1. In the top pane of the Modules window, right-click `libncurses` and choose **Map to libncurses**. 1. In the top pane of the Modules window, right-click `libncurses` and choose **Map to libncurses**.
1. Check the proposed mapping and click **OK**. 1. Check the proposed mapping and click **OK**.
## Exercise: Export and Map `ncurses` ## Exercise: Export and Map `system-supplied DSO`
Repeat this technique for the "system-supplied DSO" module. Repeat this technique for the "system-supplied DSO" module.
In practice, there is no real reason to do this, but this particular module prevents you from using **Import From File System**. In practice, there is no real reason to do this, but this particular module prevents you from using **Import From File System**.