mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/Ghidra_11.4'
This commit is contained in:
commit
33b9688d7c
15 changed files with 138 additions and 121 deletions
|
@ -46,6 +46,7 @@ public final class DyldInfoCommandConstants {
|
|||
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_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_NON_WEAK_DEFINITION = 0x8;
|
||||
|
|
|
@ -28,15 +28,15 @@ import ghidra.app.util.opinion.MachoProgramBuilder;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.reloc.Relocation.Status;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolTable;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
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
|
||||
* will need to be applied to the image
|
||||
|
@ -67,10 +67,10 @@ public class DyldChainedFixups {
|
|||
|
||||
long chainLoc = page + nextOff;
|
||||
final long chainValue = DyldChainedPtr.getChainValue(reader, chainLoc, pointerFormat);
|
||||
long newChainValue = chainValue;
|
||||
Long newChainValue = chainValue;
|
||||
boolean isAuthenticated = DyldChainedPtr.isAuthenticated(pointerFormat, chainValue);
|
||||
boolean isBound = DyldChainedPtr.isBound(pointerFormat, chainValue);
|
||||
Symbol symbol = null;
|
||||
String symbol = null;
|
||||
Integer libOrdinal = null;
|
||||
|
||||
if (isBound) {
|
||||
|
@ -88,14 +88,17 @@ public class DyldChainedFixups {
|
|||
int chainOrdinal = (int) DyldChainedPtr.getOrdinal(pointerFormat, chainValue);
|
||||
long addend = DyldChainedPtr.getAddend(pointerFormat, chainValue);
|
||||
DyldChainedImport chainedImport = chainedImports.getChainedImport(chainOrdinal);
|
||||
List<Symbol> globalSymbols = symbolTable.getGlobalSymbols(chainedImport.getName());
|
||||
if (globalSymbols.size() > 0) {
|
||||
symbol = globalSymbols.get(0);
|
||||
newChainValue = symbol.getAddress().getOffset();
|
||||
symbol = SymbolUtilities.replaceInvalidChars(chainedImport.getName(), true);
|
||||
libOrdinal = chainedImport.getLibOrdinal();
|
||||
}
|
||||
List<Symbol> globalSymbols = symbolTable.getGlobalSymbols(symbol);
|
||||
if (globalSymbols.size() > 0) {
|
||||
newChainValue = globalSymbols.getFirst().getAddress().getOffset();
|
||||
newChainValue += isAuthenticated ? auth_value_add : addend;
|
||||
}
|
||||
else {
|
||||
newChainValue = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isAuthenticated) {
|
||||
newChainValue = imagebase +
|
||||
|
@ -110,7 +113,7 @@ public class DyldChainedFixups {
|
|||
}
|
||||
|
||||
fixups.add(new DyldFixup(chainLoc, newChainValue, DyldChainedPtr.getSize(pointerFormat),
|
||||
symbol != null ? symbol.getName() : null, libOrdinal));
|
||||
symbol, libOrdinal));
|
||||
|
||||
next = DyldChainedPtr.getNext(pointerFormat, chainValue);
|
||||
nextOff += next * DyldChainedPtr.getStride(pointerFormat);
|
||||
|
@ -128,12 +131,11 @@ public class DyldChainedFixups {
|
|||
* @param log The log
|
||||
* @param monitor A cancellable monitor
|
||||
* @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
|
||||
*/
|
||||
public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program,
|
||||
Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor)
|
||||
throws MemoryAccessException, CancelledException {
|
||||
throws CancelledException {
|
||||
List<Address> fixedAddrs = new ArrayList<>();
|
||||
if (fixups.isEmpty()) {
|
||||
return fixedAddrs;
|
||||
|
@ -142,39 +144,44 @@ public class DyldChainedFixups {
|
|||
monitor.initialize(fixups.size(), "Fixing up chained pointers...");
|
||||
for (DyldFixup fixup : fixups) {
|
||||
monitor.increment();
|
||||
Status status = Status.FAILURE;
|
||||
Status status = Status.UNSUPPORTED;
|
||||
Address addr = imagebase.add(fixup.offset());
|
||||
String symbol = fixup.symbol();
|
||||
long[] value = new long[] {};
|
||||
try {
|
||||
if (fixup.value() != null) {
|
||||
if (fixup.size() == 8 || fixup.size() == 4) {
|
||||
if (fixup.size() == 8) {
|
||||
memory.setLong(addr, fixup.value());
|
||||
}
|
||||
else {
|
||||
memory.setInt(addr, (int) fixup.value());
|
||||
memory.setInt(addr, fixup.value().intValue());
|
||||
}
|
||||
fixedAddrs.add(addr);
|
||||
status = Status.APPLIED_OTHER;
|
||||
}
|
||||
else {
|
||||
status = Status.UNSUPPORTED;
|
||||
value = new long[] { fixup.value() };
|
||||
}
|
||||
}
|
||||
finally {
|
||||
program.getRelocationTable()
|
||||
.add(addr, status, 0, new long[] { fixup.value() }, fixup.size(),
|
||||
fixup.symbol() != null ? fixup.symbol() : null);
|
||||
}
|
||||
if (fixup.symbol() != null && fixup.libOrdinal() != null) {
|
||||
if (symbol != null && fixup.libOrdinal() != null) {
|
||||
value = new long[] { fixup.libOrdinal() };
|
||||
try {
|
||||
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
|
||||
fixup.libOrdinal(), fixup.symbol());
|
||||
fixup.libOrdinal(), symbol);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.appendMsg("WARNING: Problem fixing up symbol '%s' - %s"
|
||||
.formatted(fixup.symbol(), e.getMessage()));
|
||||
.formatted(symbol, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
status = Status.FAILURE;
|
||||
}
|
||||
finally {
|
||||
program.getRelocationTable()
|
||||
.add(addr, status, RELOCATION_TYPE, value, fixup.size(), symbol);
|
||||
}
|
||||
}
|
||||
log.appendMsg("Fixed up " + fixedAddrs.size() + " chained pointers.");
|
||||
return fixedAddrs;
|
||||
}
|
||||
|
|
|
@ -47,14 +47,16 @@ public class DyldChainedImport implements StructConverter {
|
|||
switch (imports_format) {
|
||||
case DYLD_CHAINED_IMPORT: {
|
||||
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;
|
||||
name_offset = (ival >> 9 & 0x7fffff);
|
||||
break;
|
||||
}
|
||||
case DYLD_CHAINED_IMPORT_ADDEND: {
|
||||
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;
|
||||
name_offset = (ival >> 9 & 0x7fffff);
|
||||
addend = reader.readNextInt();
|
||||
|
@ -62,7 +64,8 @@ public class DyldChainedImport implements StructConverter {
|
|||
}
|
||||
case DYLD_CHAINED_IMPORT_ADDEND64: {
|
||||
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;
|
||||
name_offset = ((ival >> 32) & 0xffffffffL);
|
||||
addend = reader.readNextLong();
|
||||
|
|
|
@ -207,7 +207,7 @@ public class DyldCacheSlideInfo4 extends DyldCacheSlideInfoCommon {
|
|||
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;
|
||||
|
|
|
@ -173,7 +173,7 @@ public abstract class DyldCacheSlideInfoCommon implements StructConverter {
|
|||
memory.setLong(addr, fixup.value());
|
||||
}
|
||||
else {
|
||||
memory.setInt(addr, (int) fixup.value());
|
||||
memory.setInt(addr, fixup.value().intValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ package ghidra.app.util.bin.format.macho.dyld;
|
|||
* 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 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 symbol The symbol 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) {}
|
||||
|
|
|
@ -684,18 +684,15 @@ public class MachoProgramBuilder {
|
|||
monitor.increment();
|
||||
int symbolIndex = indirectSymbols.get(i);
|
||||
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
|
||||
if (symbol != null) {
|
||||
String name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true);
|
||||
if (name != null && name.length() > 0) {
|
||||
String name =
|
||||
symbol != null ? SymbolUtilities.replaceInvalidChars(symbol.getString(), true)
|
||||
: "STUB_" + startAddr;
|
||||
Function stubFunc = createOneByteFunction(name, startAddr);
|
||||
if (stubFunc != null) {
|
||||
if (stubFunc != null && symbol != null) {
|
||||
ExternalLocation loc = program.getExternalManager()
|
||||
.addExtLocation(Library.UNKNOWN, name, null,
|
||||
SourceType.IMPORTED);
|
||||
.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
|
||||
stubFunc.setThunkedFunction(loc.createFunction());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startAddr = startAddr.add(symbolSize);
|
||||
}
|
||||
|
@ -1283,7 +1280,8 @@ public class MachoProgramBuilder {
|
|||
|
||||
String libraryPath = null;
|
||||
|
||||
if (command instanceof DynamicLibraryCommand dylibCommand) {
|
||||
if (command instanceof DynamicLibraryCommand dylibCommand &&
|
||||
dylibCommand.getCommandType() != LoadCommandTypes.LC_ID_DYLIB) {
|
||||
DynamicLibrary dylib = dylibCommand.getDynamicLibrary();
|
||||
libraryPath = dylib.getName().getString();
|
||||
}
|
||||
|
@ -1861,6 +1859,15 @@ public class MachoProgramBuilder {
|
|||
*/
|
||||
public static void fixupExternalLibrary(Program program, List<String> libraryPaths,
|
||||
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();
|
||||
int libraryIndex = libraryOrdinal - 1;
|
||||
if (libraryIndex < 0 || libraryIndex >= libraryPaths.size()) {
|
||||
|
|
|
@ -52,6 +52,46 @@ public class ExternalSymbolResolver implements Closeable {
|
|||
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 TaskMonitor monitor;
|
||||
private final List<ProgramSymbolResolver> programsToFix = new ArrayList<>();
|
||||
|
@ -333,7 +373,7 @@ public class ExternalSymbolResolver implements Closeable {
|
|||
private List<ExtLibInfo> getLibsToSearch() throws CancelledException {
|
||||
List<ExtLibInfo> result = new ArrayList<>();
|
||||
ExternalManager externalManager = program.getExternalManager();
|
||||
for (String libName : getOrderedRequiredLibraryNames()) {
|
||||
for (String libName : getOrderedRequiredLibraryNames(program)) {
|
||||
Library lib = externalManager.getExternalLibrary(libName);
|
||||
String libPath = lib != null ? lib.getAssociatedProgramPath() : null;
|
||||
Program libProg = libPath != null ? getLibraryProgram(libPath) : null;
|
||||
|
@ -409,46 +449,6 @@ public class ExternalSymbolResolver implements Closeable {
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -352,9 +352,9 @@ id="the-listings-are-not-in-sync-i.e.-they-do-not-move-together."
|
|||
class="level3">
|
||||
<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
|
||||
behavior, but, still, check it first. In the top-right of the Dynamic
|
||||
Listing is its local drop-down menu. Click it and check that
|
||||
<strong>Auto-Sync Cursor with Static Listing</strong> is selected.</p>
|
||||
behavior, but, still, check it first. In the <strong>Debugger →
|
||||
Synchronization</strong> menu, check that <strong>Synchronize Static and
|
||||
Dynamic Locations</strong> is selected.</p>
|
||||
<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
|
||||
window. If you are in a system library, e.g., <code>ld-linux</code>,
|
||||
|
|
|
@ -167,8 +167,7 @@ The re-use of connections and/or the use of multiple concurrent connections is *
|
|||
|
||||
First, check that synchronization is enabled.
|
||||
This is the default behavior, but, still, check it first.
|
||||
In the top-right of the Dynamic Listing is its local drop-down menu.
|
||||
Click it and check that **Auto-Sync Cursor with Static Listing** is selected.
|
||||
In the **Debugger → Synchronization** menu, check that **Synchronize Static and Dynamic Locations** is selected.
|
||||
|
||||
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.
|
||||
|
|
|
@ -162,8 +162,7 @@ src="images/breakpoint-enable.png" alt="set breakpoint" /> Set
|
|||
Breakpoint, press <strong><code>K</code></strong> on the keyboard, or
|
||||
double-click the margin.</li>
|
||||
<li>From the Breakpoints window, use the <strong>Set Breakpoint</strong>
|
||||
dropdown to access the various breakpoint actions defined by
|
||||
GDB.</li>
|
||||
dropdown to access the various breakpoint actions defined by GDB.</li>
|
||||
<li>From the Terminal window, use the GDB command, e.g.,
|
||||
<code>break main</code>.</li>
|
||||
</ol>
|
||||
|
|
|
@ -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>
|
||||
<li>The <strong>PC</strong> column gives the address of the next
|
||||
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
|
||||
containing the PC mapped to its static program database, if
|
||||
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
|
||||
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
|
||||
|
|
|
@ -128,8 +128,8 @@ The columns are:
|
|||
* 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.
|
||||
* 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 **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.
|
||||
This can be edited in the table, or by pressing **`CTRL`-`SHIFT`-`N`** to mark interesting snapshots.
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ Mappings</a></li>
|
|||
<li><a href="#moving-knowledge-from-dynamic-to-static"
|
||||
id="toc-moving-knowledge-from-dynamic-to-static">Moving Knowledge from
|
||||
Dynamic to Static</a></li>
|
||||
<li><a href="#exercise-export-and-map-ncurses"
|
||||
id="toc-exercise-export-and-map-ncurses">Exercise: Export and Map
|
||||
<code>ncurses</code></a></li>
|
||||
<li><a href="#exercise-export-and-map-system-supplied-dso"
|
||||
id="toc-exercise-export-and-map-system-supplied-dso">Exercise: Export
|
||||
and Map <code>system-supplied DSO</code></a></li>
|
||||
<li><a href="#exercise-cheat-like-the-devs"
|
||||
id="toc-exercise-cheat-like-the-devs">Exercise: Cheat Like the
|
||||
Devs</a></li>
|
||||
|
@ -276,7 +276,7 @@ anyway.</p></li>
|
|||
<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
|
||||
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>
|
||||
<li><p>Click <strong>Copy</strong>.</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>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="exercise-export-and-map-ncurses" class="level2">
|
||||
<h2>Exercise: Export and Map <code>ncurses</code></h2>
|
||||
<section id="exercise-export-and-map-system-supplied-dso"
|
||||
class="level2">
|
||||
<h2>Exercise: Export and Map <code>system-supplied DSO</code></h2>
|
||||
<p>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 <strong>Import From File System</strong>.</p>
|
||||
|
|
|
@ -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. 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.
|
||||
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. 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.
|
||||
|
@ -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. 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.
|
||||
In practice, there is no real reason to do this, but this particular module prevents you from using **Import From File System**.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue