1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

bug 270790: Mach-O Parser doesn't recognize x86_64 binaries

Patch from Marc-Andre Laperle. Based on work of Alfons Laarman and Sal Scotto.
This commit is contained in:
Andrew Gvozdev 2009-11-04 14:47:43 +00:00
parent d046afcb84
commit 24ce2c4fb4
11 changed files with 438 additions and 233 deletions

View file

@ -40,7 +40,8 @@ GNUElfParser.name=GNU Elf Parser
PEWindowsParser.name=PE Windows Parser PEWindowsParser.name=PE Windows Parser
CygwinPEParser.name=Cygwin PE Parser CygwinPEParser.name=Cygwin PE Parser
XCOFF32Parser.name=AIX XCOFF32 Parser XCOFF32Parser.name=AIX XCOFF32 Parser
MachOParser.name=Mach-O Parser MachOParser.name=Mach-O Parser (Deprecated)
MachOParser64.name=Mach-O 64 Parser
SOMParser.name=HP-UX SOM Parser SOMParser.name=HP-UX SOM Parser
CDTGNUCErrorParser.name=CDT GNU C/C++ Error Parser CDTGNUCErrorParser.name=CDT GNU C/C++ Error Parser

View file

@ -136,6 +136,16 @@
</run> </run>
</cextension> </cextension>
</extension> </extension>
<extension
id="MachO64"
name="%MachOParser64.name"
point="org.eclipse.cdt.core.BinaryParser">
<cextension>
<run
class="org.eclipse.cdt.utils.macho.parser.MachOParser64">
</run>
</cextension>
</extension>
<!-- =================================================================================== --> <!-- =================================================================================== -->
<!-- Define the list of Error Parser provided by the CDT --> <!-- Define the list of Error Parser provided by the CDT -->
<!-- =================================================================================== --> <!-- =================================================================================== -->

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others. * Copyright (c) 2000, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -60,6 +60,8 @@ public final class StabConstant {
public final static int N_NBLCS = 0xf8; public final static int N_NBLCS = 0xf8;
public final static int SIZE = 12; // 4 + 1 + 1 + 2 + 4 public final static int SIZE = 12; // 4 + 1 + 1 + 2 + 4
/** @since 5.2 */
public final static int SIZE_64 = 16; // 4 + 1 + 1 + 2 + 8
public static String type2String(int t) { public static String type2String(int t) {
switch (t) { switch (t) {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006 Nokia and others. * Copyright (c) 2006, 2009 Nokia and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -21,16 +21,23 @@ public class StabsReader implements ISymbolReader {
byte[] stabData; byte[] stabData;
byte[] stabstrData; byte[] stabstrData;
boolean isLe; boolean isLe;
boolean is64;
List<String> fileList; List<String> fileList;
String[] files = null; String[] files = null;
boolean parsed = false; boolean parsed = false;
String currentFile; String currentFile;
public StabsReader(byte[] data, byte[] stabstr, boolean littleEndian) { public StabsReader(byte[] data, byte[] stabstr, boolean littleEndian) {
this(data,stabstr,littleEndian,false);
}
/**
* @since 5.2
*/
public StabsReader(byte[] data, byte[] stabstr, boolean littleEndian, boolean is64bit) {
stabData = data; stabData = data;
stabstrData = stabstr; stabstrData = stabstr;
isLe = littleEndian; isLe = littleEndian;
is64 = is64bit;
fileList = new ArrayList<String>(); fileList = new ArrayList<String>();
} }
@ -80,7 +87,28 @@ public class StabsReader implements ISymbolReader {
} }
return (short) (((bytes[offset] & 0xff) << 8) | (bytes[offset + 1] & 0xff)); return (short) (((bytes[offset] & 0xff) << 8) | (bytes[offset + 1] & 0xff));
} }
private long read_8_bytes(byte[] bytes, int offset) throws IndexOutOfBoundsException {
if (isLe) {
return (((bytes[offset + 7] & 0xff) << 56)
| ((bytes[offset +6] & 0xff) << 48)
| ((bytes[offset +5] & 0xff) << 40)
| ((bytes[offset +4] & 0xff) << 32)
| ((bytes[offset +3] & 0xff) << 24)
| ((bytes[offset +2] & 0xff) << 16)
| ((bytes[offset +1] & 0xff) << 8)
| (bytes[offset +0] & 0xff));
}
return (((bytes[offset +0] & 0xff) << 56)
| ((bytes[offset +1] & 0xff) << 48)
| ((bytes[offset +2] & 0xff) << 40)
| ((bytes[offset +3] & 0xff) << 32)
| ((bytes[offset +4] & 0xff) << 24)
| ((bytes[offset +5] & 0xff) << 16)
| ((bytes[offset +6] & 0xff) << 8)
| (bytes[offset +7] & 0xff));
}
private String fixUpPath(String path) { private String fixUpPath(String path) {
// some compilers generate extra back slashes // some compilers generate extra back slashes
path = path.replaceAll("\\\\\\\\", "\\\\"); //$NON-NLS-1$//$NON-NLS-2$ path = path.replaceAll("\\\\\\\\", "\\\\"); //$NON-NLS-1$//$NON-NLS-2$
@ -115,7 +143,8 @@ public class StabsReader implements ISymbolReader {
} }
private void parse() { private void parse() {
long nstab = stabData.length / StabConstant.SIZE; int size = is64 ? StabConstant.SIZE_64 : StabConstant.SIZE;
long nstab = stabData.length / size;
int i, offset; int i, offset;
String holder = null; String holder = null;
long stroff = 0; long stroff = 0;
@ -124,7 +153,7 @@ public class StabsReader implements ISymbolReader {
short desc = 0; short desc = 0;
long value = 0; long value = 0;
for (i = offset = 0; i < nstab; i++, offset += StabConstant.SIZE) { for (i = offset = 0; i < nstab; i++, offset += size) {
// get the type; 1 byte; // get the type; 1 byte;
type = 0xff & stabData[offset + 4]; type = 0xff & stabData[offset + 4];
@ -137,7 +166,7 @@ public class StabsReader implements ISymbolReader {
// get the desc // get the desc
desc = read_2_bytes(stabData, offset + 6); desc = read_2_bytes(stabData, offset + 6);
// get the value // get the value
value = read_4_bytes(stabData, offset + 8); value = is64 ? read_8_bytes(stabData, offset + 8) : read_4_bytes(stabData, offset + 8);
// get the offset for the string; 4 bytes // get the offset for the string; 4 bytes
stroff = read_4_bytes(stabData, offset); stroff = read_4_bytes(stabData, offset);

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others. * Copyright (c) 2000, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -24,9 +24,12 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ISymbolReader; import org.eclipse.cdt.core.ISymbolReader;
import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.debug.stabs.StabsReader; import org.eclipse.cdt.utils.debug.stabs.StabsReader;
import org.eclipse.cdt.utils.debug.stabs.StabConstant;
// test checkin /**
public class MachO { * @since 5.2
*/
public class MachO64 {
protected ERandomAccessFile efile; protected ERandomAccessFile efile;
protected MachOhdr mhdr; protected MachOhdr mhdr;
@ -35,7 +38,7 @@ public class MachO {
protected CPPFilt cppFilt; protected CPPFilt cppFilt;
protected String file; protected String file;
protected boolean debugsym = false; /* contains debugging symbols */ protected boolean debugsym = false; /* contains debugging symbols */
protected boolean b64 = false;
private Symbol[] symbols; /* symbols from SymtabCommand */ private Symbol[] symbols; /* symbols from SymtabCommand */
private Symbol[] local_symbols; /* local symbols from DySymtabCommand */ private Symbol[] local_symbols; /* local symbols from DySymtabCommand */
private boolean dynsym = false; /* set if DynSymtabCommand is present */ private boolean dynsym = false; /* set if DynSymtabCommand is present */
@ -54,18 +57,31 @@ public class MachO {
public final static int MH_MAGIC = 0xfeedface; /* the mach magic number */ public final static int MH_MAGIC = 0xfeedface; /* the mach magic number */
public final static int MH_CIGAM = 0xcefaedfe; public final static int MH_CIGAM = 0xcefaedfe;
public final static int MH_UNIVERSAL = 0xcafebabe; public final static int MH_UNIVERSAL = 0xcafebabe;
public final static int MH_MAGIC_64 = 0xfeedfacf;
public final static int MH_CIGAM_64 = 0xcffaedfe;
/* Capability mashs for cpu type*/
public final static int CPU_ARCH_MASK = 0xff000000;
public final static int CPU_ARCH_ABI64 = 0x01000000;
/* values of cputype */ /* values of cputype */
public final static int CPU_TYPE_ANY = -1; public final static int CPU_TYPE_ANY = -1;
public final static int CPU_TYPE_VAX = 1; public final static int CPU_TYPE_VAX = 1;
public final static int CPU_TYPE_MC680x0 = 6; public final static int CPU_TYPE_MC680x0 = 6;
public final static int CPU_TYPE_I386 = 7; public final static int CPU_TYPE_I386 = 7;
public final static int CPU_TYPE_X86 = 7;
public final static int CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64);
public final static int CPU_TYPE_MC98000 = 10; public final static int CPU_TYPE_MC98000 = 10;
public final static int CPU_TYPE_HPPA = 11; public final static int CPU_TYPE_HPPA = 11;
public final static int CPU_TYPE_MC88000 = 13; public final static int CPU_TYPE_MC88000 = 13;
public final static int CPU_TYPE_SPARC = 14; public final static int CPU_TYPE_SPARC = 14;
public final static int CPU_TYPE_I860 = 15; public final static int CPU_TYPE_I860 = 15;
public final static int CPU_TYPE_POWERPC = 18; public final static int CPU_TYPE_POWERPC = 18;
public final static int CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64);
/* Capability bits for cpu_subtype*/
public final static int CPU_SUBTYPE_MASK = 0xff000000;
public final static int CPU_SUBTYPE_LIB64 = 0x80000000;
/* values of cpusubtype */ /* values of cpusubtype */
public final static int CPU_SUBTYPE_MULTIPLE = -1; public final static int CPU_SUBTYPE_MULTIPLE = -1;
@ -97,6 +113,21 @@ public class MachO {
public final static int CPU_SUBTYPE_PENTPRO = 32; public final static int CPU_SUBTYPE_PENTPRO = 32;
public final static int CPU_SUBTYPE_PENTII_M3 = 54; public final static int CPU_SUBTYPE_PENTII_M3 = 54;
public final static int CPU_SUBTYPE_PENTII_M5 = 86; public final static int CPU_SUBTYPE_PENTII_M5 = 86;
public final static int CPU_SUBTYPE_CELERON = 7 + (6 << 4);
public final static int CPU_SUBTYPE_CELERON_MOBILE = 7 + (7 << 4);
public final static int CPU_SUBTYPE_PENTIUM_3 = 8 + (0 << 4);
public final static int CPU_SUBTYPE_PENTIUM_3_M = 8 + (1 << 4);
public final static int CPU_SUBTYPE_PENTIUM_3_XEON = 8 + (2 << 4);
public final static int CPU_SUBTYPE_PENTIUM_M = 9 + (0 << 4);
public final static int CPU_SUBTYPE_PENTIUM_4 = 10 + (0 << 4);
public final static int CPU_SUBTYPE_PENTIUM_4_M = 10 + (0 << 1);
public final static int CPU_SUBTYPE_ITANIUM = 11 + (0 << 4);
public final static int CPU_SUBTYPE_ITANIUM_2 = 11 + (1 << 4);
public final static int CPU_SUBTYPE_XEON = 12 + (0 << 4);
public final static int CPU_SUBTYPE_XEON_MP = 12 + (1 << 4);
public final static int CPU_SUBTYPE_X86_ALL = 3;
public final static int CPU_SUBTYPE_X86_64_ALL = 3;
public final static int CPU_SUBTYPE_X86_ARCH1 = 4;
public final static int CPU_SUBTYPE_MIPS_ALL = 0; public final static int CPU_SUBTYPE_MIPS_ALL = 0;
public final static int CPU_SUBTYPE_MIPS_R2300 = 1; public final static int CPU_SUBTYPE_MIPS_R2300 = 1;
public final static int CPU_SUBTYPE_MIPS_R2600 = 2; public final static int CPU_SUBTYPE_MIPS_R2600 = 2;
@ -140,6 +171,7 @@ public class MachO {
public final static int MH_DYLINKER = 0x7; /* dynamic link editor */ public final static int MH_DYLINKER = 0x7; /* dynamic link editor */
public final static int MH_BUNDLE = 0x8; /* dynamically bound bundle file */ public final static int MH_BUNDLE = 0x8; /* dynamically bound bundle file */
public final static int MH_DYLIB_STUB = 0x9; /* shared library stub for static linking only, no section contents */ public final static int MH_DYLIB_STUB = 0x9; /* shared library stub for static linking only, no section contents */
public final static int MH_DSYM = 0xa; /* companion file with only debug */
/* values of flags */ /* values of flags */
public final static int MH_NOUNDEFS = 0x1; /* the object file has no undefined references */ public final static int MH_NOUNDEFS = 0x1; /* the object file has no undefined references */
@ -153,7 +185,17 @@ public class MachO {
public final static int MH_FORCE_FLAT = 0x100; /* the executable is forcing all images to use flat name space bindings */ public final static int MH_FORCE_FLAT = 0x100; /* the executable is forcing all images to use flat name space bindings */
public final static int MH_NOMULTIDEFS = 0x200; /* this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. */ public final static int MH_NOMULTIDEFS = 0x200; /* this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. */
public final static int MH_NOFIXPREBINDING = 0x400; /* do not have dyld notify the prebinding agent about this executable */ public final static int MH_NOFIXPREBINDING = 0x400; /* do not have dyld notify the prebinding agent about this executable */
public final static int MH_PREBINDABLE = 0x800; /* the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. */
public final static int MH_ALLMODSBOUND = 0x1000; /* indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. */
public final static int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000; /* safe to divide up the sections into sub-sections via symbols for dead code stripping */
public final static int MH_CANONICAL = 0x4000; /* the binary has been canonicalized via the unprebind operation */
public final static int MH_WEAK_DEFINES = 0x8000; /* the final linked image contains external weak symbols */
public final static int MH_BINDS_TO_WEAK = 0x10000; /* the final linked image uses weak symbols */
public final static int MH_ALLOW_STACK_EXECUTION = 0x20000; /* When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes. */
public final static int MH_ROOT_SAFE = 0x40000; /* When this bit is set, the binary declares it is safe for use in processes with uid zero */
public final static int MH_SETUID_SAFE = 0x80000; /* When this bit is set, the binary declares it is safe for use in processes when issetugid() is true */
public final static int MH_NO_REEXPORTED_DYLIBS = 0x100000; /* When this bit is set on a dylib,the static linker does not need to examine dependent dylibs to see if any are re-exported */
public final static int MH_PIE = 0x200000; /* When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. */
public int magic; /* mach magic number identifier */ public int magic; /* mach magic number identifier */
public int cputype; /* cpu specifier */ public int cputype; /* cpu specifier */
public int cpusubtype; /* machine specifier */ public int cpusubtype; /* machine specifier */
@ -161,13 +203,16 @@ public class MachO {
public int ncmds; /* number of load commands */ public int ncmds; /* number of load commands */
public int sizeofcmds; /* the size of all the load commands */ public int sizeofcmds; /* the size of all the load commands */
public int flags; /* flags */ public int flags; /* flags */
public int reserved; // 64bit reserved
protected MachOhdr() throws IOException { protected MachOhdr() throws IOException {
efile.seek(0); efile.seek(0);
efile.setEndian(false); efile.setEndian(false);
magic = efile.readIntE(); magic = efile.readIntE();
if ( magic == MH_CIGAM ) if ( magic == MH_CIGAM || magic == MH_CIGAM_64) {
efile.setEndian(true); efile.setEndian(true);
if (MH_CIGAM_64 == magic)
b64 = true;
}
else else
if ( magic == MH_UNIVERSAL) if ( magic == MH_UNIVERSAL)
{ {
@ -180,35 +225,46 @@ public class MachO {
int archiveOffset = efile.readIntE(); // archiveOffset int archiveOffset = efile.readIntE(); // archiveOffset
efile.readIntE(); // archiveSize efile.readIntE(); // archiveSize
efile.readIntE(); // archiveAlignment efile.readIntE(); // archiveAlignment
if ((cpuType == MachO.MachOhdr.CPU_TYPE_I386 && arch.equalsIgnoreCase("i386")) || //$NON-NLS-1$ if ((cpuType == MachO64.MachOhdr.CPU_TYPE_I386 && arch.equalsIgnoreCase("i386")) || //$NON-NLS-1$
(cpuType == MachO.MachOhdr.CPU_TYPE_POWERPC && arch.equalsIgnoreCase("ppc"))) //$NON-NLS-1$ (cpuType == MachO64.MachOhdr.CPU_TYPE_POWERPC && arch.equalsIgnoreCase("ppc")) || //$NON-NLS-1$
(cpuType == MachO64.MachOhdr.CPU_TYPE_X86_64 && arch.equalsIgnoreCase("x86_64"))) //$NON-NLS-1$
{ {
if (cpuType == MachO64.MachOhdr.CPU_TYPE_X86_64)
b64 = true;
efile.seek(archiveOffset); efile.seek(archiveOffset);
magic = efile.readIntE(); magic = efile.readIntE();
if ( magic == MH_CIGAM ) if ( magic == MH_CIGAM || magic == MH_CIGAM_64)
efile.setEndian(true); efile.setEndian(true);
else if ( magic != MH_MAGIC ) else if ( magic != MH_MAGIC && magic != MH_MAGIC_64)
throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
break; break;
} }
} }
} }
else if ( magic != MH_MAGIC ) else if ( magic != MH_MAGIC && magic != MH_MAGIC_64)
throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64)
b64 = true;
cputype = efile.readIntE(); cputype = efile.readIntE();
cpusubtype = efile.readIntE(); cpusubtype = efile.readIntE();
filetype = efile.readIntE(); filetype = efile.readIntE();
ncmds = efile.readIntE(); ncmds = efile.readIntE();
sizeofcmds = efile.readIntE(); sizeofcmds = efile.readIntE();
flags = efile.readIntE(); flags = efile.readIntE();
if (b64) {
reserved = efile.readIntE();
}
} }
protected MachOhdr(byte [] bytes) throws IOException { protected MachOhdr(byte [] bytes) throws IOException {
boolean isle = false; boolean isle = false;
int offset = 0; int offset = 0;
magic = makeInt(bytes, offset, isle); offset += 4; magic = makeInt(bytes, offset, isle); offset += 4;
if ( magic == MH_CIGAM ) if ( magic == MH_CIGAM || magic == MH_CIGAM_64) {
isle = true; isle = true;
if (MH_CIGAM_64 == magic)
b64 = true;
}
else else
if ( magic == MH_UNIVERSAL) if ( magic == MH_UNIVERSAL)
{ {
@ -221,27 +277,38 @@ public class MachO {
int archiveOffset = makeInt(bytes, offset, isle); offset += 4; int archiveOffset = makeInt(bytes, offset, isle); offset += 4;
offset += 4; // archiveSize offset += 4; // archiveSize
offset += 4; // archiveAlignment offset += 4; // archiveAlignment
if ((cpuType == MachO.MachOhdr.CPU_TYPE_I386 && arch.equalsIgnoreCase("i386")) || //$NON-NLS-1$ if ((cpuType == MachO64.MachOhdr.CPU_TYPE_I386 && arch.equalsIgnoreCase("i386")) || //$NON-NLS-1$
(cpuType == MachO.MachOhdr.CPU_TYPE_POWERPC && arch.equalsIgnoreCase("ppc"))) //$NON-NLS-1$ (cpuType == MachO64.MachOhdr.CPU_TYPE_POWERPC && arch.equalsIgnoreCase("ppc")) || //$NON-NLS-1$
(cpuType == MachO64.MachOhdr.CPU_TYPE_X86_64 && arch.equalsIgnoreCase("x86_64"))) //$NON-NLS-1$
{ {
if (cpuType == MachO64.MachOhdr.CPU_TYPE_X86_64)
b64 = true;
offset = archiveOffset; offset = archiveOffset;
magic = makeInt(bytes, offset, isle); offset += 4; magic = makeInt(bytes, offset, isle); offset += 4;
if ( magic == MH_CIGAM ) if ( magic == MH_CIGAM || magic == MH_CIGAM_64 )
isle = true; isle = true;
else if ( magic != MH_MAGIC ) else if ( magic != MH_MAGIC && magic != MH_MAGIC_64)
throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
break; break;
} }
} }
} }
else if ( magic != MH_MAGIC ) else if ( magic != MH_MAGIC && magic != MH_MAGIC_64)
throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64)
b64 = true;
cputype = makeInt(bytes, offset, isle); offset += 4; cputype = makeInt(bytes, offset, isle); offset += 4;
cpusubtype = makeInt(bytes, offset, isle); offset += 4; cpusubtype = makeInt(bytes, offset, isle); offset += 4;
filetype = makeInt(bytes, offset, isle); offset += 4; filetype = makeInt(bytes, offset, isle); offset += 4;
ncmds = makeInt(bytes, offset, isle); offset += 4; ncmds = makeInt(bytes, offset, isle); offset += 4;
sizeofcmds = makeInt(bytes, offset, isle); offset += 4; sizeofcmds = makeInt(bytes, offset, isle); offset += 4;
flags = makeInt(bytes, offset, isle); offset += 4; flags = makeInt(bytes, offset, isle); offset += 4;
if (b64) {
reserved = makeInt(bytes, offset, isle); offset += 4;
}
}
public boolean is64() {
return b64;
} }
} }
@ -289,6 +356,9 @@ public class MachO {
public final static int LC_SUB_LIBRARY = 0x15; /* sub library */ public final static int LC_SUB_LIBRARY = 0x15; /* sub library */
public final static int LC_TWOLEVEL_HINTS = 0x16; /* two-level namespace lookup hints */ public final static int LC_TWOLEVEL_HINTS = 0x16; /* two-level namespace lookup hints */
public final static int LC_PREBIND_CKSUM = 0x17; /* prebind checksum */ public final static int LC_PREBIND_CKSUM = 0x17; /* prebind checksum */
public final static int LC_SEGMENT_64 = 0x19;
public final static int LC_ROUTINES_64 = 0x1a;
public final static int LC_UUID = 0x1b;
/* /*
* load a dynamically linked shared library that is allowed to be missing * load a dynamically linked shared library that is allowed to be missing
* (all symbols are weak imported). * (all symbols are weak imported).
@ -325,10 +395,10 @@ public class MachO {
public final static int VM_PROT_WANTS_COPY = 0x10; public final static int VM_PROT_WANTS_COPY = 0x10;
public String segname; /* segment name */ public String segname; /* segment name */
public int vmaddr; /* memory address of this segment */ public long vmaddr; /* memory address of this segment */
public int vmsize; /* memory size of this segment */ public long vmsize; /* memory size of this segment */
public int fileoff; /* file offset of this segment */ public long fileoff; /* file offset of this segment */
public int filesize; /* amount to map from the file */ public long filesize; /* amount to map from the file */
public int maxprot; /* maximum VM protection */ public int maxprot; /* maximum VM protection */
public int initprot; /* initial VM protection */ public int initprot; /* initial VM protection */
public int nsects; /* number of sections in segment */ public int nsects; /* number of sections in segment */
@ -369,8 +439,8 @@ public class MachO {
public String sectname; /* name of this section */ public String sectname; /* name of this section */
public String segname; /* name segment this section goes in */ public String segname; /* name segment this section goes in */
public SegmentCommand segment; /* segment this section goes in */ public SegmentCommand segment; /* segment this section goes in */
public int addr; /* memory address of this section */ public long addr; /* memory address of this section */
public int size; /* size in bytes of this section */ public long size; /* size in bytes of this section */
public int offset; /* file offset of this section */ public int offset; /* file offset of this section */
public int align; /* section alignment (power of 2) */ public int align; /* section alignment (power of 2) */
public int reloff; /* file offset of relocation entries */ public int reloff; /* file offset of relocation entries */
@ -378,6 +448,7 @@ public class MachO {
public int flags; /* flags (section type and attributes)*/ public int flags; /* flags (section type and attributes)*/
public int reserved1; /* reserved */ public int reserved1; /* reserved */
public int reserved2; /* reserved */ public int reserved2; /* reserved */
public int reserved3;
public int flags(int mask) { public int flags(int mask) {
return flags & mask; return flags & mask;
@ -398,7 +469,9 @@ public class MachO {
return lc_str_name; return lc_str_name;
} }
} }
public class MachUUID extends LoadCommand {
public String uuid;
}
public class FVMLibCommand extends LoadCommand { public class FVMLibCommand extends LoadCommand {
public FVMLib fvmlib; /* the library identification */ public FVMLib fvmlib; /* the library identification */
} }
@ -507,14 +580,14 @@ public class MachO {
} }
public class RoutinesCommand extends LoadCommand { public class RoutinesCommand extends LoadCommand {
public int init_address; /* address of initialization routine */ public long init_address; /* address of initialization routine */
public int init_module; /* index into the module table that the init routine is defined in */ public long init_module; /* index into the module table that the init routine is defined in */
public int reserved1; public long reserved1;
public int reserved2; public long reserved2;
public int reserved3; public long reserved3;
public int reserved4; public long reserved4;
public int reserved5; public long reserved5;
public int reserved6; public long reserved6;
} }
public class SymtabCommand extends LoadCommand { public class SymtabCommand extends LoadCommand {
@ -564,7 +637,7 @@ public class MachO {
public int nextrel; /* number of external relocation entries */ public int nextrel; /* number of external relocation entries */
public int iinit_iterm; /* low 16 bits are the index into the init section, high 16 bits are the index into the term section */ public int iinit_iterm; /* low 16 bits are the index into the init section, high 16 bits are the index into the term section */
public int ninit_nterm; /* low 16 bits are the number of init section entries, high 16 bits are the number of term section entries */ public int ninit_nterm; /* low 16 bits are the number of init section entries, high 16 bits are the number of term section entries */
public int objc_module_info_addr; /* for this module address of the start of the (__OBJC,__module_info) section */ public long objc_module_info_addr; /* for this module address of the start of the (__OBJC,__module_info) section */
public int objc_module_info_size; /* for this module size of the (__OBJC,__module_info) section */ public int objc_module_info_size; /* for this module size of the (__OBJC,__module_info) section */
} }
@ -627,7 +700,7 @@ public class MachO {
} }
} }
protected String string_from_macho_symtab(MachO.SymtabCommand symtab, int index) throws IOException { protected String string_from_macho_symtab(MachO64.SymtabCommand symtab, int index) throws IOException {
if ( index > symtab.strsize ) { if ( index > symtab.strsize ) {
return EMPTY_STRING; return EMPTY_STRING;
} }
@ -697,7 +770,7 @@ public class MachO {
public short n_desc; public short n_desc;
public byte n_type; public byte n_type;
public byte n_sect; public byte n_sect;
public boolean is64;
private String name = null; /* symbol name */ private String name = null; /* symbol name */
private Line line = null; /* symbol line information */ private Line line = null; /* symbol line information */
@ -936,22 +1009,22 @@ public class MachO {
} }
//A hollow entry, to be used with caution in controlled situations //A hollow entry, to be used with caution in controlled situations
protected MachO () { protected MachO64 () {
} }
public MachO (String file, long offset) throws IOException { public MachO64 (String file, long offset) throws IOException {
commonSetup( file, offset, true ); commonSetup( file, offset, true );
} }
public MachO (String file) throws IOException { public MachO64 (String file) throws IOException {
commonSetup( file, 0, true ); commonSetup( file, 0, true );
} }
public MachO (String file, long offset, boolean filton) throws IOException { public MachO64 (String file, long offset, boolean filton) throws IOException {
commonSetup( file, offset, filton ); commonSetup( file, offset, filton );
} }
public MachO (String file, boolean filton) throws IOException { public MachO64 (String file, boolean filton) throws IOException {
commonSetup( file, 0, filton ); commonSetup( file, 0, filton );
} }
@ -1008,62 +1081,67 @@ public class MachO {
Attribute attrib = new Attribute(); Attribute attrib = new Attribute();
switch( mhdr.filetype ) { switch( mhdr.filetype ) {
case MachO.MachOhdr.MH_OBJECT: case MachO64.MachOhdr.MH_OBJECT:
attrib.type = Attribute.MACHO_TYPE_OBJ; attrib.type = Attribute.MACHO_TYPE_OBJ;
break; break;
case MachO.MachOhdr.MH_EXECUTE: case MachO64.MachOhdr.MH_EXECUTE:
case MachO.MachOhdr.MH_PRELOAD: case MachO64.MachOhdr.MH_PRELOAD:
case MachO.MachOhdr.MH_BUNDLE: case MachO64.MachOhdr.MH_BUNDLE:
case MachO.MachOhdr.MH_DYLINKER: case MachO64.MachOhdr.MH_DYLINKER:
attrib.type = Attribute.MACHO_TYPE_EXE; attrib.type = Attribute.MACHO_TYPE_EXE;
break; break;
case MachO.MachOhdr.MH_CORE: case MachO64.MachOhdr.MH_CORE:
attrib.type = Attribute.MACHO_TYPE_CORE; attrib.type = Attribute.MACHO_TYPE_CORE;
break; break;
case MachO.MachOhdr.MH_DYLIB: case MachO64.MachOhdr.MH_DYLIB:
case MachO.MachOhdr.MH_FVMLIB: case MachO64.MachOhdr.MH_FVMLIB:
attrib.type = Attribute.MACHO_TYPE_SHLIB; attrib.type = Attribute.MACHO_TYPE_SHLIB;
break; break;
} }
switch (mhdr.cputype) { switch (mhdr.cputype) {
case MachO.MachOhdr.CPU_TYPE_I386 : case MachO64.MachOhdr.CPU_TYPE_X86_64:
attrib.cpu = "x86_64"; //$NON-NLS-1$
break;
case MachO64.MachOhdr.CPU_TYPE_I386 :
attrib.cpu = "x86"; //$NON-NLS-1$ attrib.cpu = "x86"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_POWERPC : case MachO64.MachOhdr.CPU_TYPE_POWERPC :
attrib.cpu = "ppc"; //$NON-NLS-1$ attrib.cpu = "ppc"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_VAX : case MachO64.MachOhdr.CPU_TYPE_VAX :
attrib.cpu = "vax"; //$NON-NLS-1$ attrib.cpu = "vax"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_MC680x0 : case MachO64.MachOhdr.CPU_TYPE_MC680x0 :
attrib.cpu = "m68k"; //$NON-NLS-1$ attrib.cpu = "m68k"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_MC98000 : case MachO64.MachOhdr.CPU_TYPE_MC98000 :
attrib.cpu = "98000"; //$NON-NLS-1$ attrib.cpu = "98000"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_MC88000 : case MachO64.MachOhdr.CPU_TYPE_MC88000 :
attrib.cpu = "88000"; //$NON-NLS-1$ attrib.cpu = "88000"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_HPPA : case MachO64.MachOhdr.CPU_TYPE_HPPA :
attrib.cpu = "hp"; //$NON-NLS-1$ attrib.cpu = "hp"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_SPARC: case MachO64.MachOhdr.CPU_TYPE_SPARC:
attrib.cpu = "sparc"; //$NON-NLS-1$ attrib.cpu = "sparc"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_I860: case MachO64.MachOhdr.CPU_TYPE_I860:
attrib.cpu = "i860"; //$NON-NLS-1$ attrib.cpu = "i860"; //$NON-NLS-1$
break; break;
case MachO.MachOhdr.CPU_TYPE_ANY: case MachO64.MachOhdr.CPU_TYPE_ANY:
default: default:
attrib.cpu = "any"; //$NON-NLS-1$ attrib.cpu = "any"; //$NON-NLS-1$
} }
switch (mhdr.magic) { switch (mhdr.magic) {
case MachO.MachOhdr.MH_CIGAM : case MachO64.MachOhdr.MH_CIGAM_64:
case MachO64.MachOhdr.MH_CIGAM :
attrib.isle = true; attrib.isle = true;
break; break;
case MachO.MachOhdr.MH_MAGIC : case MachO64.MachOhdr.MH_MAGIC_64 :
case MachO64.MachOhdr.MH_MAGIC :
attrib.isle = false; attrib.isle = false;
break; break;
} }
@ -1076,7 +1154,7 @@ public class MachO {
} }
public static Attribute getAttributes(String file) throws IOException { public static Attribute getAttributes(String file) throws IOException {
MachO macho = new MachO(file); MachO64 macho = new MachO64(file);
Attribute attrib = macho.getAttributes(); Attribute attrib = macho.getAttributes();
macho.dispose(); macho.dispose();
return attrib; return attrib;
@ -1084,9 +1162,9 @@ public class MachO {
public static Attribute getAttributes(byte [] array) throws IOException { public static Attribute getAttributes(byte [] array) throws IOException {
MachO emptyMachO = new MachO(); MachO64 emptyMachO = new MachO64();
emptyMachO.mhdr = emptyMachO.new MachOhdr(array); emptyMachO.mhdr = emptyMachO.new MachOhdr(array);
//emptyMachO.sections = new MachO.Section[0]; //emptyMachO.sections = new MachO64.Section[0];
Attribute attrib = emptyMachO.getAttributes(); Attribute attrib = emptyMachO.getAttributes();
emptyMachO.dispose(); emptyMachO.dispose();
@ -1096,7 +1174,7 @@ public class MachO {
public static boolean isMachOHeader(byte[] bytes) { public static boolean isMachOHeader(byte[] bytes) {
try { try {
int magic = makeInt(bytes, 0, false); int magic = makeInt(bytes, 0, false);
return (magic == MachO.MachOhdr.MH_MAGIC || magic == MachO.MachOhdr.MH_CIGAM || magic == MachO.MachOhdr.MH_UNIVERSAL); return (magic == MachO64.MachOhdr.MH_MAGIC || magic == MachO64.MachOhdr.MH_CIGAM || magic == MachO64.MachOhdr.MH_UNIVERSAL || magic == MachO64.MachOhdr.MH_CIGAM_64 || magic == MachO64.MachOhdr.MH_MAGIC_64);
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} }
@ -1140,10 +1218,15 @@ public class MachO {
ArrayList<Symbol> symList = new ArrayList<Symbol>(symtab.nsyms); ArrayList<Symbol> symList = new ArrayList<Symbol>(symtab.nsyms);
for (int s = 0; s < symtab.nsyms; s++) { for (int s = 0; s < symtab.nsyms; s++) {
Symbol symbol = new Symbol(); Symbol symbol = new Symbol();
symbol.is64 = b64;
symbol.n_strx = efile.readIntE(); symbol.n_strx = efile.readIntE();
symbol.n_type = (byte)efile.readUnsignedByte(); symbol.n_type = (byte)efile.readUnsignedByte();
symbol.n_sect = (byte)efile.readUnsignedByte(); symbol.n_sect = (byte)efile.readUnsignedByte();
symbol.n_desc = efile.readShortE(); symbol.n_desc = efile.readShortE();
// figure out 64 bit file an dload 64 bit symbols
if (b64)
symbol.n_value = efile.readLongE();
else
symbol.n_value = efile.readIntE(); symbol.n_value = efile.readIntE();
symList.add(symbol); symList.add(symbol);
if ((symbol.n_type & Symbol.N_STAB) != 0) { if ((symbol.n_type & Symbol.N_STAB) != 0) {
@ -1241,8 +1324,13 @@ public class MachO {
efile.readFully(segname); efile.readFully(segname);
section.segment = seg; section.segment = seg;
section.segname = new String(segname, 0, 16); section.segname = new String(segname, 0, 16);
if (b64) {
section.addr = efile.readLongE();
section.size = efile.readLongE();
}else {
section.addr = efile.readIntE(); section.addr = efile.readIntE();
section.size = efile.readIntE(); section.size = efile.readIntE();
}
section.offset = efile.readIntE(); section.offset = efile.readIntE();
section.align = efile.readIntE(); section.align = efile.readIntE();
section.reloff = efile.readIntE(); section.reloff = efile.readIntE();
@ -1250,6 +1338,8 @@ public class MachO {
section.flags = efile.readIntE(); section.flags = efile.readIntE();
section.reserved1 = efile.readIntE(); section.reserved1 = efile.readIntE();
section.reserved2 = efile.readIntE(); section.reserved2 = efile.readIntE();
if (b64)
section.reserved3 = efile.readInt();
sections.add(section); sections.add(section);
} }
return sections; return sections;
@ -1302,13 +1392,32 @@ public class MachO {
loadcommands = new LoadCommand[mhdr.ncmds]; loadcommands = new LoadCommand[mhdr.ncmds];
for ( int i = 0; i < mhdr.ncmds; i++ ) { for ( int i = 0; i < mhdr.ncmds; i++ ) {
int cmd = efile.readIntE(); int cmd = efile.readIntE();
int len; int len = efile.readIntE();
switch (cmd) { switch (cmd) {
case LoadCommand.LC_SEGMENT_64:
SegmentCommand seg64 = new SegmentCommand();
byte[] segname64 = new byte[16];
seg64.cmd = cmd;
seg64.cmdsize = len;
efile.readFully(segname64);
seg64.segname = new String(segname64, 0, 16);
seg64.vmaddr = efile.readLongE();
seg64.vmsize = efile.readLongE();
seg64.fileoff = efile.readLongE();
seg64.filesize = efile.readLongE();
seg64.maxprot = efile.readIntE();
seg64.initprot = efile.readIntE();
seg64.nsects = efile.readIntE();
seg64.flags = efile.readIntE();
sections.addAll(getSections(seg64));
loadcommands[i] = seg64;
break;
case LoadCommand.LC_SEGMENT: case LoadCommand.LC_SEGMENT:
SegmentCommand seg = new SegmentCommand(); SegmentCommand seg = new SegmentCommand();
byte[] segname = new byte[16]; byte[] segname = new byte[16];
seg.cmd = cmd; seg.cmd = cmd;
seg.cmdsize = efile.readIntE(); seg.cmdsize = len;
efile.readFully(segname); efile.readFully(segname);
seg.segname = new String(segname, 0, 16); seg.segname = new String(segname, 0, 16);
seg.vmaddr = efile.readIntE(); seg.vmaddr = efile.readIntE();
@ -1326,7 +1435,7 @@ public class MachO {
case LoadCommand.LC_SYMTAB: case LoadCommand.LC_SYMTAB:
SymtabCommand stcmd = new SymtabCommand(); SymtabCommand stcmd = new SymtabCommand();
stcmd.cmd = cmd; stcmd.cmd = cmd;
stcmd.cmdsize = efile.readIntE(); stcmd.cmdsize = len;
stcmd.symoff = efile.readIntE(); stcmd.symoff = efile.readIntE();
stcmd.nsyms = efile.readIntE(); stcmd.nsyms = efile.readIntE();
stcmd.stroff = efile.readIntE(); stcmd.stroff = efile.readIntE();
@ -1337,7 +1446,7 @@ public class MachO {
case LoadCommand.LC_SYMSEG: case LoadCommand.LC_SYMSEG:
SymSegCommand sscmd = new SymSegCommand(); SymSegCommand sscmd = new SymSegCommand();
sscmd.cmd = cmd; sscmd.cmd = cmd;
sscmd.cmdsize = efile.readIntE(); sscmd.cmdsize = len;
sscmd.offset = efile.readIntE(); sscmd.offset = efile.readIntE();
sscmd.size = efile.readIntE(); sscmd.size = efile.readIntE();
loadcommands[i] = sscmd; loadcommands[i] = sscmd;
@ -1347,8 +1456,8 @@ public class MachO {
case LoadCommand.LC_UNIXTHREAD: case LoadCommand.LC_UNIXTHREAD:
ThreadCommand thcmd = new ThreadCommand(); ThreadCommand thcmd = new ThreadCommand();
thcmd.cmd = cmd; thcmd.cmd = cmd;
thcmd.cmdsize = efile.readIntE(); thcmd.cmdsize = len;
efile.skipBytes(thcmd.cmdsize - 8 /* sizeof(ThreadCommand) */); efile.skipBytes(len - 8);
loadcommands[i] = thcmd; loadcommands[i] = thcmd;
break; break;
@ -1356,7 +1465,7 @@ public class MachO {
case LoadCommand.LC_IDFVMLIB: case LoadCommand.LC_IDFVMLIB:
FVMLibCommand fvmcmd = new FVMLibCommand(); FVMLibCommand fvmcmd = new FVMLibCommand();
fvmcmd.cmd = cmd; fvmcmd.cmd = cmd;
fvmcmd.cmdsize = efile.readIntE(); fvmcmd.cmdsize = len;
fvmcmd.fvmlib = new FVMLib(); fvmcmd.fvmlib = new FVMLib();
fvmcmd.fvmlib.name = efile.readIntE(); fvmcmd.fvmlib.name = efile.readIntE();
fvmcmd.fvmlib.minor_version = efile.readIntE(); fvmcmd.fvmlib.minor_version = efile.readIntE();
@ -1371,14 +1480,14 @@ public class MachO {
case LoadCommand.LC_IDENT: case LoadCommand.LC_IDENT:
IdentCommand icmd = new IdentCommand(); IdentCommand icmd = new IdentCommand();
icmd.cmd = cmd; icmd.cmd = cmd;
icmd.cmdsize = efile.readIntE(); icmd.cmdsize = len;
loadcommands[i] = icmd; loadcommands[i] = icmd;
break; break;
case LoadCommand.LC_FVMFILE: case LoadCommand.LC_FVMFILE:
FVMFileCommand fcmd = new FVMFileCommand(); FVMFileCommand fcmd = new FVMFileCommand();
fcmd.cmd = cmd; fcmd.cmd = cmd;
fcmd.cmdsize = efile.readIntE(); fcmd.cmdsize = len;
fcmd.name = efile.readIntE(); fcmd.name = efile.readIntE();
fcmd.header_addr = efile.readIntE(); fcmd.header_addr = efile.readIntE();
len = fcmd.cmdsize - 16 /* sizeof FVMFileCommand */; len = fcmd.cmdsize - 16 /* sizeof FVMFileCommand */;
@ -1391,7 +1500,7 @@ public class MachO {
case LoadCommand.LC_DYSYMTAB: case LoadCommand.LC_DYSYMTAB:
DySymtabCommand dscmd = new DySymtabCommand(); DySymtabCommand dscmd = new DySymtabCommand();
dscmd.cmd = cmd; dscmd.cmd = cmd;
dscmd.cmdsize = efile.readIntE(); dscmd.cmdsize = len;
dscmd.ilocalsym = efile.readIntE(); dscmd.ilocalsym = efile.readIntE();
dscmd.nlocalsym = efile.readIntE(); dscmd.nlocalsym = efile.readIntE();
dscmd.iextdefsym = efile.readIntE(); dscmd.iextdefsym = efile.readIntE();
@ -1419,7 +1528,7 @@ public class MachO {
case LoadCommand.LC_LOAD_WEAK_DYLIB: case LoadCommand.LC_LOAD_WEAK_DYLIB:
DyLibCommand dylcmd = new DyLibCommand(); DyLibCommand dylcmd = new DyLibCommand();
dylcmd.cmd = cmd; dylcmd.cmd = cmd;
dylcmd.cmdsize = efile.readIntE(); dylcmd.cmdsize = len;
dylcmd.dylib = new DyLib(); dylcmd.dylib = new DyLib();
dylcmd.dylib.name = efile.readIntE(); dylcmd.dylib.name = efile.readIntE();
dylcmd.dylib.timestamp = efile.readIntE(); dylcmd.dylib.timestamp = efile.readIntE();
@ -1436,7 +1545,7 @@ public class MachO {
case LoadCommand.LC_ID_DYLINKER: case LoadCommand.LC_ID_DYLINKER:
DyLinkerCommand dylkcmd = new DyLinkerCommand(); DyLinkerCommand dylkcmd = new DyLinkerCommand();
dylkcmd.cmd = cmd; dylkcmd.cmd = cmd;
dylkcmd.cmdsize = efile.readIntE(); dylkcmd.cmdsize = len;
dylkcmd.name = efile.readIntE(); dylkcmd.name = efile.readIntE();
len = dylkcmd.cmdsize - 12 /* sizeof(DyLinkerCommand) */; len = dylkcmd.cmdsize - 12 /* sizeof(DyLinkerCommand) */;
dylkcmd.lc_str_name = getLCStr(len); dylkcmd.lc_str_name = getLCStr(len);
@ -1448,7 +1557,7 @@ public class MachO {
case LoadCommand.LC_PREBOUND_DYLIB: case LoadCommand.LC_PREBOUND_DYLIB:
PreboundDyLibCommand pbcmd = new PreboundDyLibCommand(); PreboundDyLibCommand pbcmd = new PreboundDyLibCommand();
pbcmd.cmd = cmd; pbcmd.cmd = cmd;
pbcmd.cmdsize = efile.readIntE(); pbcmd.cmdsize = len;
pbcmd.name = efile.readIntE(); pbcmd.name = efile.readIntE();
pbcmd.nmodules = efile.readIntE(); pbcmd.nmodules = efile.readIntE();
pbcmd.linked_modules = efile.readIntE(); pbcmd.linked_modules = efile.readIntE();
@ -1459,10 +1568,25 @@ public class MachO {
loadcommands[i] = pbcmd; loadcommands[i] = pbcmd;
break; break;
case LoadCommand.LC_ROUTINES_64:
RoutinesCommand rcmd64 = new RoutinesCommand();
rcmd64.cmd = cmd;
rcmd64.cmdsize = len;
rcmd64.init_address = efile.readLongE();
rcmd64.init_module = efile.readLongE();
rcmd64.reserved1 = efile.readLongE();
rcmd64.reserved2 = efile.readLongE();
rcmd64.reserved3 = efile.readLongE();
rcmd64.reserved4 = efile.readLongE();
rcmd64.reserved5 = efile.readLongE();
rcmd64.reserved6 = efile.readLongE();
loadcommands[i] = rcmd64;
break;
case LoadCommand.LC_ROUTINES: case LoadCommand.LC_ROUTINES:
RoutinesCommand rcmd = new RoutinesCommand(); RoutinesCommand rcmd = new RoutinesCommand();
rcmd.cmd = cmd; rcmd.cmd = cmd;
rcmd.cmdsize = efile.readIntE(); rcmd.cmdsize = len;
rcmd.init_address = efile.readIntE(); rcmd.init_address = efile.readIntE();
rcmd.init_module = efile.readIntE(); rcmd.init_module = efile.readIntE();
rcmd.reserved1 = efile.readIntE(); rcmd.reserved1 = efile.readIntE();
@ -1477,7 +1601,7 @@ public class MachO {
case LoadCommand.LC_SUB_FRAMEWORK: case LoadCommand.LC_SUB_FRAMEWORK:
SubFrameworkCommand subfcmd = new SubFrameworkCommand(); SubFrameworkCommand subfcmd = new SubFrameworkCommand();
subfcmd.cmd = cmd; subfcmd.cmd = cmd;
subfcmd.cmdsize = efile.readIntE(); subfcmd.cmdsize = len;
subfcmd.umbrella = efile.readIntE(); subfcmd.umbrella = efile.readIntE();
len = subfcmd.cmdsize - 12 /* sizeof(SubFrameworkCommand) */ ; len = subfcmd.cmdsize - 12 /* sizeof(SubFrameworkCommand) */ ;
subfcmd.lc_str_name = getLCStr(len); subfcmd.lc_str_name = getLCStr(len);
@ -1489,7 +1613,7 @@ public class MachO {
case LoadCommand.LC_SUB_UMBRELLA: case LoadCommand.LC_SUB_UMBRELLA:
SubUmbrellaCommand subucmd = new SubUmbrellaCommand(); SubUmbrellaCommand subucmd = new SubUmbrellaCommand();
subucmd.cmd = cmd; subucmd.cmd = cmd;
subucmd.cmdsize = efile.readIntE(); subucmd.cmdsize = len;
subucmd.sub_umbrella = efile.readIntE(); subucmd.sub_umbrella = efile.readIntE();
len = subucmd.cmdsize - 12 /* sizeof(SubUmbrellaCommand) */; len = subucmd.cmdsize - 12 /* sizeof(SubUmbrellaCommand) */;
subucmd.lc_str_name = getLCStr(len); subucmd.lc_str_name = getLCStr(len);
@ -1501,7 +1625,7 @@ public class MachO {
case LoadCommand.LC_SUB_CLIENT: case LoadCommand.LC_SUB_CLIENT:
SubClientCommand subccmd = new SubClientCommand(); SubClientCommand subccmd = new SubClientCommand();
subccmd.cmd = cmd; subccmd.cmd = cmd;
subccmd.cmdsize = efile.readIntE(); subccmd.cmdsize = len;
subccmd.client = efile.readIntE(); subccmd.client = efile.readIntE();
len = subccmd.cmdsize - 12 /* sizeof(SubClientCommand) */; len = subccmd.cmdsize - 12 /* sizeof(SubClientCommand) */;
subccmd.lc_str_name = getLCStr(len); subccmd.lc_str_name = getLCStr(len);
@ -1513,7 +1637,7 @@ public class MachO {
case LoadCommand.LC_SUB_LIBRARY: case LoadCommand.LC_SUB_LIBRARY:
SubLibraryCommand sublcmd = new SubLibraryCommand(); SubLibraryCommand sublcmd = new SubLibraryCommand();
sublcmd.cmd = cmd; sublcmd.cmd = cmd;
sublcmd.cmdsize = efile.readIntE(); sublcmd.cmdsize = len;
sublcmd.sub_library = efile.readIntE(); sublcmd.sub_library = efile.readIntE();
len = sublcmd.cmdsize - 12 /* sizeof(SubLibraryCommand) */; len = sublcmd.cmdsize - 12 /* sizeof(SubLibraryCommand) */;
sublcmd.lc_str_name = getLCStr(len); sublcmd.lc_str_name = getLCStr(len);
@ -1525,16 +1649,24 @@ public class MachO {
case LoadCommand.LC_TWOLEVEL_HINTS: case LoadCommand.LC_TWOLEVEL_HINTS:
TwoLevelHintsCommand tlhcmd = new TwoLevelHintsCommand(); TwoLevelHintsCommand tlhcmd = new TwoLevelHintsCommand();
tlhcmd.cmd = cmd; tlhcmd.cmd = cmd;
tlhcmd.cmdsize = efile.readIntE(); tlhcmd.cmdsize = len;
tlhcmd.offset = efile.readIntE(); tlhcmd.offset = efile.readIntE();
tlhcmd.nhints = efile.readIntE(); tlhcmd.nhints = efile.readIntE();
loadcommands[i] = tlhcmd; loadcommands[i] = tlhcmd;
break; break;
case LoadCommand.LC_UUID:
MachUUID uuidCmd = new MachUUID();
uuidCmd.cmd = cmd;
uuidCmd.cmdsize = len;
byte[] uuid = new byte[16];
efile.readFully(uuid);
uuidCmd.uuid = new String(uuid,0,16);
loadcommands[i] = uuidCmd;
break;
case LoadCommand.LC_PREBIND_CKSUM: case LoadCommand.LC_PREBIND_CKSUM:
PrebindCksumCommand pbccmd = new PrebindCksumCommand(); PrebindCksumCommand pbccmd = new PrebindCksumCommand();
pbccmd.cmd = cmd; pbccmd.cmd = cmd;
pbccmd.cmdsize = efile.readIntE(); pbccmd.cmdsize = len;
pbccmd.cksum = efile.readIntE(); pbccmd.cksum = efile.readIntE();
loadcommands[i] = pbccmd; loadcommands[i] = pbccmd;
break; break;
@ -1558,7 +1690,9 @@ public class MachO {
loadLineTable(); loadLineTable();
} }
} }
public boolean is64() {
return b64;
}
public Symbol[] getSymbols() { public Symbol[] getSymbols() {
return symbols; return symbols;
} }
@ -1617,7 +1751,7 @@ public class MachO {
} }
public long swapInt( long val ) { public long swapInt( long val ) {
if ( mhdr.magic == MachOhdr.MH_CIGAM ) { if ( mhdr.magic == MachOhdr.MH_CIGAM || mhdr.magic == MachOhdr.MH_CIGAM_64 ) {
short tmp[] = new short[4]; short tmp[] = new short[4];
tmp[0] = (short)(val & 0x00ff); tmp[0] = (short)(val & 0x00ff);
tmp[1] = (short)((val >> 8) & 0x00ff); tmp[1] = (short)((val >> 8) & 0x00ff);
@ -1629,7 +1763,7 @@ public class MachO {
} }
public int swapShort( short val ) { public int swapShort( short val ) {
if ( mhdr.magic == MachOhdr.MH_CIGAM ) { if ( mhdr.magic == MachOhdr.MH_CIGAM || mhdr.magic == MachOhdr.MH_CIGAM_64) {
short tmp[] = new short[2]; short tmp[] = new short[2];
tmp[0] = (short)(val & 0x00ff); tmp[0] = (short)(val & 0x00ff);
tmp[1] = (short)((val >> 8) & 0x00ff); tmp[1] = (short)((val >> 8) & 0x00ff);
@ -1649,7 +1783,7 @@ public class MachO {
if ( loadcommands == null ) { if ( loadcommands == null ) {
loadLoadCommands(); loadLoadCommands();
} }
} catch (IOException e) { } } catch (Throwable e) { e.printStackTrace(); }
for (LoadCommand loadcommand : loadcommands) { for (LoadCommand loadcommand : loadcommands) {
@ -1657,15 +1791,15 @@ public class MachO {
{ {
symtab = (SymtabCommand)loadcommand; symtab = (SymtabCommand)loadcommand;
try { try {
int symSize = symtab.nsyms * 12; int symSize = symtab.nsyms * (mhdr.is64() ? StabConstant.SIZE_64 :StabConstant.SIZE);
byte[] data = new byte[symSize]; byte[] data = new byte[symSize];
efile.seek(symtab.symoff); efile.seek(symtab.symoff);
efile.readFully(data); efile.readFully(data);
byte[] stabstr = new byte[symtab.strsize]; byte[] stabstr = new byte[symtab.strsize];
efile.seek(symtab.stroff); efile.seek(symtab.stroff);
efile.readFully(stabstr); efile.readFully(stabstr);
symReader = new StabsReader(data, stabstr, getAttributes().isLittleEndian()); symReader = new StabsReader(data, stabstr, getAttributes().isLittleEndian(),mhdr.is64());
} catch (IOException e) {} } catch (Throwable e) { e.printStackTrace(); }
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2000, 2007 QNX Software Systems and others. * Copyright (c) 2000, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -15,24 +15,25 @@ package org.eclipse.cdt.utils.macho;
import java.io.IOException; import java.io.IOException;
import java.util.Vector; import java.util.Vector;
import org.eclipse.cdt.utils.macho.MachO.DyLib; import org.eclipse.cdt.utils.macho.MachO64.DyLib;
import org.eclipse.cdt.utils.macho.MachO.Section; import org.eclipse.cdt.utils.macho.MachO64.Section;
import org.eclipse.cdt.utils.macho.MachO.Symbol; import org.eclipse.cdt.utils.macho.MachO64.Symbol;
/** /**
* <code>MachOHelper</code> is a wrapper class for the <code>MachO</code> class * <code>MachOHelper64</code> is a wrapper class for the <code>MachO64</code> class
* to provide higher level API for sorting/searching the MachO data. * to provide higher level API for sorting/searching the MachO data.
* *
* @see MachO * @see MachO64
* @since 5.2
*/ */
public class MachOHelper { public class MachOHelper64 {
private MachO macho; private MachO64 macho;
private MachO.Symbol[] dynsyms; private MachO64.Symbol[] dynsyms;
private MachO.Symbol[] symbols; private MachO64.Symbol[] symbols;
private MachO.Section[] sections; private MachO64.Section[] sections;
private MachO.DyLib[] needed; private MachO64.DyLib[] needed;
private MachO.DyLib[] sonames; private MachO64.DyLib[] sonames;
public void dispose() { public void dispose() {
if (macho != null) { if (macho != null) {
@ -40,7 +41,9 @@ public class MachOHelper {
macho = null; macho = null;
} }
} }
public boolean is64() {
return macho.is64();
}
public class Sizes { public class Sizes {
public long text; public long text;
public long data; public long data;
@ -60,8 +63,8 @@ public class MachOHelper {
symbols = macho.getSymtabSymbols(); symbols = macho.getSymtabSymbols();
dynsyms = macho.getDynamicSymbols(); dynsyms = macho.getDynamicSymbols();
sections = macho.getSections(); sections = macho.getSections();
needed = macho.getDyLibs(MachO.LoadCommand.LC_LOAD_DYLIB); needed = macho.getDyLibs(MachO64.LoadCommand.LC_LOAD_DYLIB);
sonames = macho.getDyLibs(MachO.LoadCommand.LC_ID_DYLIB); sonames = macho.getDyLibs(MachO64.LoadCommand.LC_ID_DYLIB);
if (dynsyms == null) if (dynsyms == null)
dynsyms = symbols; dynsyms = symbols;
@ -70,158 +73,157 @@ public class MachOHelper {
/** /**
* Create a new <code>MachOHelper</code> using an existing <code>MachO</code> * Create a new <code>MachOHelper64</code> using an existing <code>MachO64</code>
* object. * object.
* @param macho An existing MachO object to wrap. * @param macho An existing MachO64 object to wrap.
* @throws IOException Error processing the MachO file. * @throws IOException Error processing the MachO file.
*/ */
public MachOHelper(MachO macho) throws IOException { public MachOHelper64(MachO64 macho) throws IOException {
this.macho = macho; this.macho = macho;
} }
/** /**
* Create a new <code>MachOHelper</code> based on the given filename. * Create a new <code>MachOHelper64</code> based on the given filename.
* *
* @param filename The file to use for creating a new MachO object. * @param filename The file to use for creating a new MachO64 object.
* @throws IOException Error processing the MachO file. * @throws IOException Error processing the MachO file.
* @see MachO#MachO( String ) * @see MachO64#MachO64( String )
*/ */
public MachOHelper(String filename) throws IOException { public MachOHelper64(String filename) throws IOException {
macho = new MachO(filename); macho = new MachO64(filename);
} }
/** /**
* Create a new <code>MachOHelper</code> based on the given filename. * Create a new <code>MachOHelper64</code> based on the given filename.
* *
* @param filename The file to use for creating a new MachO object. * @param filename The file to use for creating a new MachO64 object.
* @throws IOException Error processing the MachO file. * @throws IOException Error processing the MachO file.
* @see MachO#MachO( String ) * @see MachO64#MachO64( String )
*/ */
public MachOHelper(String filename, long offset) throws IOException { public MachOHelper64(String filename, long offset) throws IOException {
macho = new MachO(filename, offset); macho = new MachO64(filename, offset);
} }
public MachOHelper(String filename, boolean filton) throws IOException { public MachOHelper64(String filename, boolean filton) throws IOException {
macho = new MachO(filename, filton); macho = new MachO64(filename, filton);
} }
/** Give back the MachO object that this helper is wrapping */ /** Give back the MachO64 object that this helper is wrapping */
public MachO getMachO() { public MachO64 getMachO() {
return macho; return macho;
} }
public MachO.Symbol[] getExternalFunctions() throws IOException { public MachO64.Symbol[] getExternalFunctions() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (Symbol sym : dynsyms) { for (Symbol sym : dynsyms) {
if ((sym.n_type_mask(MachO.Symbol.N_PEXT) if ((sym.n_type_mask(MachO64.Symbol.N_PEXT)
|| sym.n_type_mask(MachO.Symbol.N_EXT)) || sym.n_type_mask(MachO64.Symbol.N_EXT))
&& sym.n_desc(MachO.Symbol.REFERENCE_FLAG_UNDEFINED_LAZY)) { && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_UNDEFINED_LAZY)) {
String name = sym.toString(); String name = sym.toString();
if (name != null && name.trim().length() > 0) if (name != null && name.trim().length() > 0)
v.add(sym); v.add(sym);
} }
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
public MachO.Symbol[] getExternalObjects() throws IOException { public MachO64.Symbol[] getExternalObjects() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (Symbol sym : dynsyms) { for (Symbol sym : dynsyms) {
if ((sym.n_type_mask(MachO.Symbol.N_PEXT) if ((sym.n_type_mask(MachO64.Symbol.N_PEXT)
|| sym.n_type_mask(MachO.Symbol.N_EXT)) || sym.n_type_mask(MachO64.Symbol.N_EXT))
&& sym.n_desc(MachO.Symbol.REFERENCE_FLAG_UNDEFINED_NON_LAZY)) { && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_UNDEFINED_NON_LAZY)) {
String name = sym.toString(); String name = sym.toString();
if (name != null && name.trim().length() > 0) if (name != null && name.trim().length() > 0)
v.add(sym); v.add(sym);
} }
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
public MachO.Symbol[] getUndefined() throws IOException { public MachO64.Symbol[] getUndefined() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (Symbol dynsym : dynsyms) { for (Symbol dynsym : dynsyms) {
if (dynsym.n_type(MachO.Symbol.N_UNDF)) if (dynsym.n_type(MachO64.Symbol.N_UNDF))
v.add(dynsym); v.add(dynsym);
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
/* /*
* TODO: I'm not sure if this are correct. Need to check * TODO: I'm not sure if this are correct. Need to check
*/ */
public MachO.Symbol[] getLocalFunctions() throws IOException { public MachO64.Symbol[] getLocalFunctions() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (Symbol sym : dynsyms) { for (Symbol sym : dynsyms) {
if ((!sym.n_type_mask(MachO.Symbol.N_PEXT) if ((!sym.n_type_mask(MachO64.Symbol.N_PEXT)
&& !sym.n_type_mask(MachO.Symbol.N_EXT)) && !sym.n_type_mask(MachO64.Symbol.N_EXT))
&& sym.n_desc(MachO.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)) { && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)) {
String name = sym.toString(); String name = sym.toString();
if (name != null && name.trim().length() > 0) if (name != null && name.trim().length() > 0)
v.add(sym); v.add(sym);
} }
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
/* /*
* TODO: I'm not sure if this are correct. Need to check * TODO: I'm not sure if this are correct. Need to check
*/ */
public MachO.Symbol[] getLocalObjects() throws IOException { public MachO64.Symbol[] getLocalObjects() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (Symbol sym : dynsyms) { for (Symbol sym : dynsyms) {
if ((!sym.n_type_mask(MachO.Symbol.N_PEXT) if ((!sym.n_type_mask(MachO64.Symbol.N_PEXT)
&& !sym.n_type_mask(MachO.Symbol.N_EXT)) && !sym.n_type_mask(MachO64.Symbol.N_EXT))
&& sym.n_desc(MachO.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)) { && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)) {
String name = sym.toString(); String name = sym.toString();
if (name != null && name.trim().length() > 0) if (name != null && name.trim().length() > 0)
v.add(sym); v.add(sym);
} }
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
public MachO.Symbol[] getCommonObjects() throws IOException { public MachO64.Symbol[] getCommonObjects() throws IOException {
Vector<Symbol> v = new Vector<Symbol>(); Vector<Symbol> v = new Vector<Symbol>();
loadBinary(); loadBinary();
for (int i = 0; i < dynsyms.length; i++) { for (int i = 0; i < dynsyms.length; i++) {
MachO.Symbol sym = dynsyms[i]; MachO64.Symbol sym = dynsyms[i];
if (sym.n_type_mask(MachO.Symbol.N_EXT) if (sym.n_type_mask(MachO64.Symbol.N_EXT)
&& sym.n_type(MachO.Symbol.N_UNDF) && sym.n_type(MachO64.Symbol.N_UNDF)
&& sym.n_value != 0) { && sym.n_value != 0) {
v.add(symbols[i]); v.add(symbols[i]);
} }
} }
MachO.Symbol[] ret = v.toArray(new MachO.Symbol[0]); MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]);
return ret; return ret;
} }
@ -299,15 +301,15 @@ public class MachOHelper {
loadBinary(); loadBinary();
for (Section section : sections) { for (Section section : sections) {
MachO.SegmentCommand seg = section.segment; MachO64.SegmentCommand seg = section.segment;
if (section.flags(MachO.Section.SECTION_TYP) != MachO.Section.S_ZEROFILL) { if (section.flags(MachO64.Section.SECTION_TYP) != MachO64.Section.S_ZEROFILL) {
if (seg.prot(MachO.SegmentCommand.VM_PROT_EXECUTE)) { if (seg.prot(MachO64.SegmentCommand.VM_PROT_EXECUTE)) {
text += section.size; text += section.size;
} else if (!seg.prot(MachO.SegmentCommand.VM_PROT_WRITE)) { } else if (!seg.prot(MachO64.SegmentCommand.VM_PROT_WRITE)) {
data += section.size; data += section.size;
} }
} else { } else {
if (seg.prot(MachO.SegmentCommand.VM_PROT_WRITE)) { if (seg.prot(MachO64.SegmentCommand.VM_PROT_WRITE)) {
bss += section.size; bss += section.size;
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2008 QNX Software Systems and others. * Copyright (c) 2002, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -22,12 +22,13 @@ import org.eclipse.cdt.utils.macho.AR;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
/** /**
* @since 5.2
*/ */
public class MachOBinaryArchive extends BinaryFile implements IBinaryArchive { public class MachOBinaryArchive64 extends BinaryFile implements IBinaryArchive {
ArrayList<IBinaryObject> children; ArrayList<IBinaryObject> children;
public MachOBinaryArchive(IBinaryParser parser, IPath p) throws IOException { public MachOBinaryArchive64(IBinaryParser parser, IPath p) throws IOException {
super(parser, p, IBinaryFile.ARCHIVE); super(parser, p, IBinaryFile.ARCHIVE);
new AR(p.toOSString()).dispose(); // check file type new AR(p.toOSString()).dispose(); // check file type
children = new ArrayList<IBinaryObject>(5); children = new ArrayList<IBinaryObject>(5);
@ -44,7 +45,7 @@ public class MachOBinaryArchive extends BinaryFile implements IBinaryArchive {
ar = new AR(getPath().toOSString()); ar = new AR(getPath().toOSString());
AR.ARHeader[] headers = ar.getHeaders(); AR.ARHeader[] headers = ar.getHeaders();
for (int i = 0; i < headers.length; i++) { for (int i = 0; i < headers.length; i++) {
IBinaryObject bin = new MachOBinaryObject(getBinaryParser(), getPath(), headers[i]); IBinaryObject bin = new MachOBinaryObject64(getBinaryParser(), getPath(), headers[i]);
children.add(bin); children.add(bin);
} }
} catch (IOException e) { } catch (IOException e) {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2006 QNX Software Systems and others. * Copyright (c) 2004, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -16,9 +16,12 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
public class MachOBinaryExecutable extends MachOBinaryObject implements IBinaryExecutable { /**
* @since 5.2
*/
public class MachOBinaryExecutable64 extends MachOBinaryObject64 implements IBinaryExecutable {
public MachOBinaryExecutable(IBinaryParser parser, IPath path) { public MachOBinaryExecutable64(IBinaryParser parser, IPath path) {
super(parser, path, IBinaryFile.EXECUTABLE); super(parser, path, IBinaryFile.EXECUTABLE);
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2007 QNX Software Systems and others. * Copyright (c) 2002, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -15,6 +15,7 @@ import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -27,28 +28,32 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.IBinaryParser.ISymbol; import org.eclipse.cdt.core.IBinaryParser.ISymbol;
import org.eclipse.cdt.utils.Addr32; import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr32Factory; import org.eclipse.cdt.utils.Addr32Factory;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.cdt.utils.Addr64Factory;
import org.eclipse.cdt.utils.BinaryObjectAdapter; import org.eclipse.cdt.utils.BinaryObjectAdapter;
import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.Symbol; import org.eclipse.cdt.utils.Symbol;
import org.eclipse.cdt.utils.macho.AR; import org.eclipse.cdt.utils.macho.AR;
import org.eclipse.cdt.utils.macho.MachO; import org.eclipse.cdt.utils.macho.MachO64;
import org.eclipse.cdt.utils.macho.MachOHelper; import org.eclipse.cdt.utils.macho.MachOHelper64;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
/* /**
* MachOBinaryObject * MachOBinaryObject64
* @since 5.2
*/ */
public class MachOBinaryObject extends BinaryObjectAdapter { public class MachOBinaryObject64 extends BinaryObjectAdapter {
protected AR.ARHeader header; protected AR.ARHeader header;
protected IAddressFactory addressFactory; protected IAddressFactory addressFactory;
protected MachO.Attribute attributes; protected MachO64.Attribute attributes;
protected MachOHelper.Sizes sizes; protected MachOHelper64.Sizes sizes;
protected ISymbol[] symbols; protected ISymbol[] symbols;
protected String soname; protected String soname;
protected String[] needed; protected String[] needed;
protected long timeStamp; protected long timeStamp;
protected boolean is64 = false;
private static final String[] NO_NEEDED = new String[0]; private static final String[] NO_NEEDED = new String[0];
@ -57,7 +62,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
* @param path * @param path
* @param header * @param header
*/ */
public MachOBinaryObject(IBinaryParser parser, IPath path, AR.ARHeader header) { public MachOBinaryObject64(IBinaryParser parser, IPath path, AR.ARHeader header) {
super(parser, path, IBinaryFile.OBJECT); super(parser, path, IBinaryFile.OBJECT);
this.header = header; this.header = header;
} }
@ -67,7 +72,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
* @param path * @param path
* @param type * @param type
*/ */
public MachOBinaryObject(IBinaryParser parser, IPath path, int type) { public MachOBinaryObject64(IBinaryParser parser, IPath path, int type) {
super(parser, path, type); super(parser, path, type);
} }
@ -92,13 +97,13 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
return super.getContents(); return super.getContents();
} }
protected MachOHelper getMachOHelper() throws IOException { protected MachOHelper64 getMachOHelper() throws IOException {
IPath path = getPath(); IPath path = getPath();
if (path != null) { if (path != null) {
if (header != null) { if (header != null) {
return new MachOHelper(path.toOSString(), header.getObjectDataOffset()); return new MachOHelper64(path.toOSString(), header.getObjectDataOffset());
} else { } else {
return new MachOHelper(path.toOSString()); return new MachOHelper64(path.toOSString());
} }
} }
return null; return null;
@ -121,8 +126,15 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public IAddressFactory getAddressFactory() { public IAddressFactory getAddressFactory() {
if (addressFactory == null) { if (addressFactory == null) {
if (soname == null)
loadBinaryInfo();
if (is64) {
addressFactory = new Addr64Factory();
}
else {
addressFactory = new Addr32Factory(); addressFactory = new Addr32Factory();
} }
}
return addressFactory; return addressFactory;
} }
@ -134,18 +146,19 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
needed = null; needed = null;
} }
protected MachO.Attribute internalGetAttributes() { protected MachO64.Attribute internalGetAttributes() {
if (hasChanged()) { if (hasChanged()) {
clearCachedValues(); clearCachedValues();
} }
if (attributes == null) { if (attributes == null) {
MachOHelper helper = null; MachOHelper64 helper = null;
try { try {
helper = getMachOHelper(); helper = getMachOHelper();
if (helper != null) { if (helper != null) {
attributes = helper.getMachO().getAttributes(); attributes = helper.getMachO().getAttributes();
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
} finally { } finally {
if (helper != null) { if (helper != null) {
helper.dispose(); helper.dispose();
@ -155,12 +168,12 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
return attributes; return attributes;
} }
protected MachOHelper.Sizes internalGetSizes() { protected MachOHelper64.Sizes internalGetSizes() {
if (hasChanged()) { if (hasChanged()) {
clearCachedValues(); clearCachedValues();
} }
if (sizes == null) { if (sizes == null) {
MachOHelper helper = null; MachOHelper64 helper = null;
try { try {
helper = getMachOHelper(); helper = getMachOHelper();
if (helper != null) { if (helper != null) {
@ -172,6 +185,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
} }
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
} finally { } finally {
if (helper != null) { if (helper != null) {
helper.dispose(); helper.dispose();
@ -212,19 +226,17 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
} }
protected void loadBinaryInfo() { protected void loadBinaryInfo() {
MachOHelper helper = null; MachOHelper64 helper = null;
try { try {
helper = getMachOHelper(); helper = getMachOHelper();
if (helper != null) { if (helper != null) {
//TODO we can probably optimize this further in MachOHelper //TODO we can probably optimize this further in MachOHelper
symbols = loadSymbols(helper); symbols = loadSymbols(helper);
//TODO is the sort necessary? //TODO is the sort necessary?
Arrays.sort(symbols); Arrays.sort(symbols);
soname = helper.getSoname(); soname = helper.getSoname();
needed = helper.getNeeded(); needed = helper.getNeeded();
is64 = helper.is64();
// since we're invoking the helper we might as well update the // since we're invoking the helper we might as well update the
// sizes since it's a pretty lightweight operation by comparison // sizes since it's a pretty lightweight operation by comparison
if (sizes == null) { if (sizes == null) {
@ -237,6 +249,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
} }
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
symbols = NO_SYMBOLS; symbols = NO_SYMBOLS;
} finally { } finally {
if (helper != null) { if (helper != null) {
@ -245,14 +258,14 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
} }
} }
protected ISymbol[] loadSymbols(MachOHelper helper) throws IOException { protected ISymbol[] loadSymbols(MachOHelper64 helper) throws IOException {
CPPFilt cppfilt = null; CPPFilt cppfilt = null;
try { try {
ArrayList<Symbol> list = new ArrayList<Symbol>(); ArrayList<Symbol> list = new ArrayList<Symbol>();
// Hack should be remove when Elf is clean // Hack should be remove when Elf is clean
helper.getMachO().setCppFilter(false); helper.getMachO().setCppFilter(false);
cppfilt = getCPPFilt(); cppfilt = getCPPFilt();
//TODO we can probably optimize this further in MachOHelper //TODO we can probably optimize this further in MachOHelper64
addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, cppfilt, list); addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, cppfilt, list);
addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, cppfilt, list); addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, cppfilt, list);
addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, cppfilt, list); addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, cppfilt, list);
@ -266,12 +279,12 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
} }
protected CPPFilt getCPPFilt() { protected CPPFilt getCPPFilt() {
MachOParser parser = (MachOParser) getBinaryParser(); MachOParser64 parser = (MachOParser64) getBinaryParser();
return parser.getCPPFilt(); return parser.getCPPFilt();
} }
private void addSymbols(MachO.Symbol[] array, int type, CPPFilt cppfilt, List<Symbol> list) { private void addSymbols(MachO64.Symbol[] array, int type, CPPFilt cppfilt, List<Symbol> list) {
for (org.eclipse.cdt.utils.macho.MachO.Symbol element : array) { for (MachO64.Symbol element : array) {
String name = element.toString(); String name = element.toString();
if (cppfilt != null) { if (cppfilt != null) {
try { try {
@ -284,13 +297,18 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
int size = 0; int size = 0;
String filename = element.getFilename(); String filename = element.getFilename();
IPath filePath = (filename != null) ? new Path(filename) : null; IPath filePath = (filename != null) ? new Path(filename) : null;
list.add(new Symbol(this, name, type, new Addr32(element.n_value), size, filePath, element.getLineNumber(addr), element.getLineNumber(addr + size - 1))); IAddress symbolAddr;
if (element.is64)
symbolAddr = new Addr32(element.n_value);
else
symbolAddr = new Addr64(BigInteger.valueOf(element.n_value));
list.add(new Symbol(this, name, type, symbolAddr, size, filePath, element.getLineNumber(addr), element.getLineNumber(addr + size - 1)));
} }
} }
@Override @Override
public String getCPU() { public String getCPU() {
MachO.Attribute attribute = internalGetAttributes(); MachO64.Attribute attribute = internalGetAttributes();
if (attribute != null) { if (attribute != null) {
return attribute.getCPU(); return attribute.getCPU();
} }
@ -299,7 +317,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public boolean hasDebug() { public boolean hasDebug() {
MachO.Attribute attribute = internalGetAttributes(); MachO64.Attribute attribute = internalGetAttributes();
if (attribute != null) { if (attribute != null) {
return attribute.hasDebug(); return attribute.hasDebug();
} }
@ -308,7 +326,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public boolean isLittleEndian() { public boolean isLittleEndian() {
MachO.Attribute attribute = internalGetAttributes(); MachO64.Attribute attribute = internalGetAttributes();
if (attribute != null) { if (attribute != null) {
return attribute.isLittleEndian(); return attribute.isLittleEndian();
} }
@ -317,7 +335,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public long getBSS() { public long getBSS() {
MachOHelper.Sizes size = internalGetSizes(); MachOHelper64.Sizes size = internalGetSizes();
if (size != null) { if (size != null) {
return size.bss; return size.bss;
} }
@ -326,7 +344,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public long getData() { public long getData() {
MachOHelper.Sizes size = internalGetSizes(); MachOHelper64.Sizes size = internalGetSizes();
if (size != null) { if (size != null) {
return size.data; return size.data;
} }
@ -335,7 +353,7 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@Override @Override
public long getText() { public long getText() {
MachOHelper.Sizes size = internalGetSizes(); MachOHelper64.Sizes size = internalGetSizes();
if (size != null) { if (size != null) {
return size.text; return size.text;
} }
@ -398,14 +416,14 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public Object getAdapter(Class adapter) { public Object getAdapter(Class adapter) {
if (adapter.equals(MachO.class)) { if (adapter.equals(MachO64.class)) {
try { try {
return new MachO(getPath().toOSString()); return new MachO64(getPath().toOSString());
} catch (IOException e) { } catch (IOException e) {
} }
} }
if (adapter.equals(ISymbolReader.class)) { if (adapter.equals(ISymbolReader.class)) {
MachO macho = (MachO)getAdapter(MachO.class); MachO64 macho = (MachO64)getAdapter(MachO64.class);
if (macho != null) { if (macho != null) {
return macho.getSymbolReader(); return macho.getSymbolReader();
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2006 QNX Software Systems and others. * Copyright (c) 2004, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -16,9 +16,12 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryShared;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
public class MachOBinaryShared extends MachOBinaryObject implements IBinaryShared { /**
* @since 5.2
*/
public class MachOBinaryShared64 extends MachOBinaryObject64 implements IBinaryShared {
protected MachOBinaryShared(IBinaryParser parser, IPath path) { protected MachOBinaryShared64(IBinaryParser parser, IPath path) {
super(parser, path, IBinaryFile.SHARED); super(parser, path, IBinaryFile.SHARED);
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2007 QNX Software Systems and others. * Copyright (c) 2002, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -18,14 +18,15 @@ import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.ICExtensionReference; import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.utils.CPPFilt; import org.eclipse.cdt.utils.CPPFilt;
import org.eclipse.cdt.utils.macho.AR; import org.eclipse.cdt.utils.macho.AR;
import org.eclipse.cdt.utils.macho.MachO; import org.eclipse.cdt.utils.macho.MachO64;
import org.eclipse.cdt.utils.macho.MachO.Attribute; import org.eclipse.cdt.utils.macho.MachO64.Attribute;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
/** /**
* @since 5.2
*/ */
public class MachOParser extends AbstractCExtension implements IBinaryParser { public class MachOParser64 extends AbstractCExtension implements IBinaryParser {
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath) * @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath)
@ -42,10 +43,10 @@ public class MachOParser extends AbstractCExtension implements IBinaryParser {
IBinaryFile binary = null; IBinaryFile binary = null;
try { try {
MachO.Attribute attribute = null; MachO64.Attribute attribute = null;
if (hints != null && hints.length > 0) { if (hints != null && hints.length > 0) {
try { try {
attribute = MachO.getAttributes(hints); attribute = MachO64.getAttributes(hints);
} catch (IOException eof) { } catch (IOException eof) {
// continue, the array was to small. // continue, the array was to small.
} }
@ -53,7 +54,7 @@ public class MachOParser extends AbstractCExtension implements IBinaryParser {
//Take a second run at it if the data array failed. //Take a second run at it if the data array failed.
if(attribute == null) { if(attribute == null) {
attribute = MachO.getAttributes(path.toOSString()); attribute = MachO64.getAttributes(path.toOSString());
} }
if (attribute != null) { if (attribute != null) {
@ -92,7 +93,7 @@ public class MachOParser extends AbstractCExtension implements IBinaryParser {
* @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath)
*/ */
public boolean isBinary(byte[] array, IPath path) { public boolean isBinary(byte[] array, IPath path) {
return MachO.isMachOHeader(array) || AR.isARHeader(array); return MachO64.isMachOHeader(array) || AR.isARHeader(array);
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -117,6 +118,7 @@ public class MachOParser extends AbstractCExtension implements IBinaryParser {
return cppfilt; return cppfilt;
} }
@SuppressWarnings("deprecation")
protected IPath getCPPFiltPath() { protected IPath getCPPFiltPath() {
ICExtensionReference ref = getExtensionReference(); ICExtensionReference ref = getExtensionReference();
String value = ref.getExtensionData("c++filt"); //$NON-NLS-1$ String value = ref.getExtensionData("c++filt"); //$NON-NLS-1$
@ -131,18 +133,18 @@ public class MachOParser extends AbstractCExtension implements IBinaryParser {
} }
protected IBinaryObject createBinaryObject(IPath path) throws IOException { protected IBinaryObject createBinaryObject(IPath path) throws IOException {
return new MachOBinaryObject(this, path, IBinaryFile.OBJECT); return new MachOBinaryObject64(this, path, IBinaryFile.OBJECT);
} }
protected IBinaryExecutable createBinaryExecutable(IPath path) throws IOException { protected IBinaryExecutable createBinaryExecutable(IPath path) throws IOException {
return new MachOBinaryExecutable(this, path); return new MachOBinaryExecutable64(this, path);
} }
protected IBinaryShared createBinaryShared(IPath path) throws IOException { protected IBinaryShared createBinaryShared(IPath path) throws IOException {
return new MachOBinaryShared(this, path); return new MachOBinaryShared64(this, path);
} }
protected IBinaryObject createBinaryCore(IPath path) throws IOException { protected IBinaryObject createBinaryCore(IPath path) throws IOException {
return new MachOBinaryObject(this, path, IBinaryFile.CORE); return new MachOBinaryObject64(this, path, IBinaryFile.CORE);
} }
} }