Merge remote-tracking branch

'origin/GP-1973_ryanmkurtz_dylib-extract-fixes' (#4175)
This commit is contained in:
Ryan Kurtz
2022-04-29 01:18:33 -04:00
3 changed files with 396 additions and 268 deletions
@@ -135,9 +135,9 @@ public class MachHeader implements StructConverter {
_commandIndex = _reader.getPointerIndex(); _commandIndex = _reader.getPointerIndex();
} }
public void parse() throws IOException, MachException { public MachHeader parse() throws IOException, MachException {
if (_parsed) { if (_parsed) {
return; return this;
} }
for (int i = 0; i < nCmds; ++i) { for (int i = 0; i < nCmds; ++i) {
_reader.setPointerIndex(_commandIndex); _reader.setPointerIndex(_commandIndex);
@@ -146,6 +146,7 @@ public class MachHeader implements StructConverter {
_commandIndex += lc.getCommandSize(); _commandIndex += lc.getCommandSize();
} }
_parsed = true; _parsed = true;
return this;
} }
public int getMagic() { public int getMagic() {
@@ -21,161 +21,192 @@ import java.util.List;
/** /**
* Constants for the flags field of the mach_header * Constants for the flags field of the mach_header
*
* @see <a href="https://opensource.apple.com/source/xnu/xnu-7195.81.3/EXTERNAL_HEADERS/mach-o/loader.h.auto.html">mach-o/loader.h</a>
*/ */
public final class MachHeaderFlags { public final class MachHeaderFlags {
/** /**
* the object file has no undefined references. * the object file has no undefined references
*/ */
public final static int MH_NOUNDEFS = 0x1; public final static int MH_NOUNDEFS = 0x1;
/** /**
* the object file is the output of an incremental * the object file is the output of an incremental link against a base file and
* link against a base file and can't be link * can't be link edited again.
* edited again.
*/ */
public final static int MH_INCRLINK = 0x2; public final static int MH_INCRLINK = 0x2;
/** /**
* the object file is input for the dynamic * the object file is input for the dynamic linker and can't be staticly link
* linker and can't be staticly link edited again. * edited again
*/ */
public final static int MH_DYLDLINK = 0x4; public final static int MH_DYLDLINK = 0x4;
/** /**
* the object file's undefined references * the object file's undefined references are bound by the dynamic linker when
* are bound by the dynamic linker when loaded. * loaded
*/ */
public final static int MH_BINDATLOAD = 0x8; public final static int MH_BINDATLOAD = 0x8;
/** /**
* the file has its dynamic undefined references * the file has its dynamic undefined references prebound
* prebound.
*/ */
public final static int MH_PREBOUND = 0x10; public final static int MH_PREBOUND = 0x10;
/** /**
* the file has its read-only and read-write * the file has its read-only and read-write segments split
* segments split.
*/ */
public final static int MH_SPLIT_SEGS = 0x20; public final static int MH_SPLIT_SEGS = 0x20;
/** /**
* the shared library init routine is to be * the shared library init routine is to be run lazily via catching memory faults to its
* run lazily via catching memory faults to its * writeable segments (obsolete)
* writeable segments (obsolete).
*/ */
public final static int MH_LAZY_INIT = 0x40; public final static int MH_LAZY_INIT = 0x40;
/** /**
* the image is using two-level name space bindings. * the image is using two-level name space bindings
*/ */
public final static int MH_TWOLEVEL = 0x80; public final static int MH_TWOLEVEL = 0x80;
/** /**
* the executable is forcing all images to use * the executable is forcing all images to use flat name space bindings
* flat name space bindings.
*/ */
public final static int MH_FORCE_FLAT = 0x100; public final static int MH_FORCE_FLAT = 0x100;
/** /**
* this umbrella guarantees no multiple defintions * this umbrella guarantees no multiple definitions of symbols in its sub-images so the
* of symbols in its sub-images so the two-level * two-level namespace hints can always be used
* namespace hints can always be used.
* */
public final static int MH_NOMULTIDEFS = 0x200;
/**
* do not have dyld notify the prebinding
* agent about this executable.
*/ */
public final static int MH_NOFIXPREBINDING = 0x400; public final static int MH_NOMULTIDEFS = 0x200;
/** /**
* the binary is not prebound but can have * do not have dyld notify the prebinding agent about this executable
* its prebinding redone. only used when
* MH_PREBOUND is not set.
*/ */
public final static int MH_PREBINDABLE = 0x800; public final static int MH_NOFIXPREBINDING = 0x400;
/** /**
* indicates that this binary binds to all * the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is
* two-level namespace modules of its dependent * not set
* libraries. only used when MH_PREBINDABLE and
* MH_TWOLEVEL are both set.
*/ */
public final static int MH_ALLMODSBOUND = 0x1000; public final static int MH_PREBINDABLE = 0x800;
/** /**
* safe to divide up the sections into * indicates that this binary binds to all two-level namespace modules of its dependent
* sub-sections via symbols for dead code * libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set.
* stripping.
*/ */
public final static int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000; public final static int MH_ALLMODSBOUND = 0x1000;
/**
* safe to divide up the sections into sub-sections via symbols for dead code stripping
*/
public final static int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;
/** /**
* the binary has been canonicalized via the unprebind operation. * the binary has been canonicalized via the unprebind operation.
*/ */
public final static int MH_CANONICAL = 0x4000; public final static int MH_CANONICAL = 0x4000;
/** /**
* the final linked image contains external weak symbols. * the final linked image contains external weak symbols.
*/ */
public final static int MH_WEAK_DEFINES = 0x8000; public final static int MH_WEAK_DEFINES = 0x8000;
/** /**
* the final linked image uses weak symbols. * the final linked image uses weak symbols.
*/ */
public final static int MH_BINDS_TO_WEAK = 0x10000; public final static int MH_BINDS_TO_WEAK = 0x10000;
/** /**
* when this bit is set, all stacks in the task * When this bit is set, all stacks in the task will be given stack execution privilege. only
* will be given stack execution privilege. * used in MH_EXECUTE filetypes.
* only used in MH_EXECUTE filetypes.
*/ */
public final static int MH_ALLOW_STACK_EXECUTION = 0x20000; public final static int MH_ALLOW_STACK_EXECUTION = 0x20000;
/** /**
* When this bit is set, the binary declares it is safe for use in * When this bit is set, the binary declares it is safe for use in processes with uid zero
* processes with uid zero
*/ */
public final static int MH_ROOT_SAFE = 0x40000; public final static int MH_ROOT_SAFE = 0x40000;
/** /**
* When this bit is set, the binary declares it is safe for use in * When this bit is set, the binary declares it is safe for use in processes when issetugid()
* processes when issetugid() is true * is true
*/ */
public final static int MH_SETUID_SAFE = 0x80000; public final static int MH_SETUID_SAFE = 0x80000;
/** /**
* When this bit is set on a dylib, the static linker does not need to * When this bit is set on a dylib, the static linker does not need to examine dependent dylibs
* examine dependent dylibs to see if any are re-exported * to see if any are re-exported
*/ */
public final static int MH_NO_REEXPORTED_DYLIBS = 0x100000; public final static int MH_NO_REEXPORTED_DYLIBS = 0x100000;
/** /**
* When this bit is set, the OS will load the main executable at a * When this bit is set, the OS will load the main executable at a random address. Only used in
* random address. Only used in MH_EXECUTE filetypes. * MH_EXECUTE filetypes.
*/ */
public final static int MH_PIE = 0x200000; public final static int MH_PIE = 0x200000;
/** /**
* Only for use on dylibs. * Only for use on dylibs. When linking against a dylib that has this bit set, the static linker
* When linking against a dylib that * will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are
* has this bit set, the static linker will automatically not create a * being referenced from the dylib.
* LC_LOAD_DYLIB load command to the
* dylib if no symbols are being referenced from the dylib.
*/ */
public final static int MH_DEAD_STRIPPABLE_DYLIB = 0x400000; public final static int MH_DEAD_STRIPPABLE_DYLIB = 0x400000;
/** /**
* Contains a section of type S_THREAD_LOCAL_VARIABLES. * Contains a section of type S_THREAD_LOCAL_VARIABLES.
*/ */
public final static int MH_HAS_TLV_DESCRIPTORS = 0x800000; public final static int MH_HAS_TLV_DESCRIPTORS = 0x800000;
/** /**
* When this bit is set, the OS will run the main executable * When this bit is set, the OS will run the main executable with a non-executable heap even on
* with a non-executable heap even on platforms ( e.g., i386 ) * platforms ( e.g., i386 ) that don't require it. Only used in MH_EXECUTE file types.
* that don't require it.
* Only used in MH_EXECUTE file types.
*/ */
public final static int MH_NO_HEAP_EXECUTION = 0x1000000; public final static int MH_NO_HEAP_EXECUTION = 0x1000000;
/** /**
* * The code was linked for use in an application extension.
*/ */
public final static int MH_APP_EXTENSION_SAFE = 0x2000000; public final static int MH_APP_EXTENSION_SAFE = 0x2000000;
/**
* The external symbols listed in the nlist symbol table do not include all the symbols listed
* in the dyld info.
*/
public final static int MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000;
/**
* Allow LC_MIN_VERSION_MACOS and LC_BUILD_VERSION load commands with the platforms macOS,
* iOSMac, iOSSimulator, tvOSSimulator and watchOSSimulator.
*/
public final static int MH_SIM_SUPPORT = 0x08000000;
/**
* Only for use on dylibs. When this bit is set, the dylib is part of the dyld shared cache,
* rather than loose in the filesystem.
*/
public final static int MH_DYLIB_IN_CACHE = 0x80000000;
/** /**
* Returns string representation of the flag values. * Returns string representation of the flag values.
*
* @param flags the flags value to get the string representation of.
* @return a string representation of the flag values.
*/ */
public final static List<String> getFlags(int flags) { public final static List<String> getFlags(int flags) {
List<String> list = new ArrayList<String>(); List<String> list = new ArrayList<>();
Field [] fields = MachHeaderFlags.class.getDeclaredFields(); Field[] fields = MachHeaderFlags.class.getDeclaredFields();
for (Field field : fields) { for (Field field : fields) {
if (field.getName().startsWith("MH_")) { if (field.getName().startsWith("MH_")) {
try { try {
Integer value = (Integer)field.get(null); Integer value = (Integer) field.get(null);
if ((flags & value) != 0) { if ((flags & value) != 0) {
list.add(field.getName().substring("MH_".length())); list.add(field.getName().substring("MH_".length()));
} }
} }
catch (Exception e) { catch (Exception e) {
// do nothing
} }
} }
} }