Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java4
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/plugin.properties11
-rw-r--r--build/org.eclipse.cdt.managedbuilder.ui/plugin.xml449
-rw-r--r--core/org.eclipse.cdt.core.macosx/.cdtproject6
-rw-r--r--core/org.eclipse.cdt.core.macosx/.classpath7
-rw-r--r--core/org.eclipse.cdt.core.macosx/.cvsignore2
-rw-r--r--core/org.eclipse.cdt.core.macosx/.project29
-rw-r--r--core/org.eclipse.cdt.core.macosx/ChangeLog3
-rw-r--r--core/org.eclipse.cdt.core.macosx/build.properties8
-rw-r--r--core/org.eclipse.cdt.core.macosx/fragment.xml23
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/.cvsignore1
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/Makefile46
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/PTY.h21
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/PTYInputStream.h32
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/PTYOutputStream.h29
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/Spawner.h45
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/SpawnerInputStream.h32
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/SpawnerOutputStream.h29
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/exec0.h11
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/exec_unix.c135
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/io.c103
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/openpty.c104
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/openpty.h10
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/pfind.c78
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/pty.c35
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/ptyio.c107
-rw-r--r--core/org.eclipse.cdt.core.macosx/library/spawner.c218
-rw-r--r--core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libpty.jnilibbin0 -> 10220 bytes
-rw-r--r--core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libspawner.jnilibbin0 -> 15288 bytes
-rw-r--r--core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessInfo.java45
-rw-r--r--core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessList.java68
-rw-r--r--core/org.eclipse.cdt.core/plugin.properties2
-rw-r--r--core/org.eclipse.cdt.core/plugin.xml18
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/AR.java336
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/ERandomAccessFile.java80
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachO.java1561
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachOHelper.java315
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/SymbolSortCompare.java24
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/ARMember.java83
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/BinaryArchive.java80
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOBinaryObject.java170
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOParser.java147
-rw-r--r--core/org.eclipse.cdt.ui/plugin.xml5
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/MachOBinaryParserPage.java217
44 files changed, 4722 insertions, 7 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
index 080ebe4a344..fda02ca13f0 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java
@@ -347,7 +347,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
outputPrefix = info.getOutputPrefix(outputExtension);
// The command to build
- String buildCmd = cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO;
+ String buildCmd = cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO;
buffer.append(TAB + AT + ECHO + WHITESPACE + buildCmd + NEWLINE);
buffer.append(TAB + AT + buildCmd);
@@ -583,7 +583,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
}
buffer.append(NEWLINE);
buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_START_BUILD + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE);
- buffer.append(TAB + cmd + WHITESPACE + flags + WHITESPACE + outflag + OUT_MACRO + WHITESPACE + "$(OBJS) $(USER_OBJS) $(LIBS)" + NEWLINE); //$NON-NLS-1$
+ buffer.append(TAB + cmd + WHITESPACE + flags + WHITESPACE + outflag + WHITESPACE + OUT_MACRO + WHITESPACE + "$(OBJS) $(USER_OBJS) $(LIBS)" + NEWLINE); //$NON-NLS-1$
buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_FINISH_FILE + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE + NEWLINE);
// Always add a clean target
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.properties b/build/org.eclipse.cdt.managedbuilder.ui/plugin.properties
index d141c037daa..624440fdfb0 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.properties
+++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.properties
@@ -29,7 +29,9 @@ TargetName.gnu.lib=Static Library (Gnu)
TargetName.cygw.exe=Executable (Gnu on Windows)
TargetName.cygw.so=Shared Library (Gnu on Windows)
TargetName.cygw.lib=Static Library (Gnu on Windows)
-
+TargetName.macosx.exe=Executable (MacOS X)
+TargetName.macosx.so=Shared Library (MacOS X)
+TargetName.macosx.lib=Static Library (MacOS X)
# No longer needed post-2.0
TargetName.cygw=Cygwin
@@ -64,6 +66,10 @@ ToolName.linker.gnu.cpp = GCC C++ Linker
ToolName.archiver.gnu = GCC Archiver
ToolName.assembler.gnu = GCC Assembler
+# Mach-O tool names
+ToolName.linker.macosx.c = MacOS X C Linker
+ToolName.linker.macosx.cpp = MacOS X C++ Linker
+
# Generic Category Names
OptionCategory.Symbols = Symbols
OptionCategory.Preproc = Preprocessor
@@ -138,4 +144,5 @@ Option.Gnu.Assembler.version=Announce version (-v)
Option.Windows.Windres.OutputFormat = Output format
Option.Windows.Windres.OutputFormat.Coff = coff (--output-format coff)
Option.Windows.Windres.OutputFormat.RC = rc (--output-format rc)
-Option.Windows.Windres.OutputFormat.Res = res (--output-format res) \ No newline at end of file
+Option.Windows.Windres.OutputFormat.Res = res (--output-format res)
+Option.MacOSX.Linker.Shared=Shared (-Wl,-dylib) \ No newline at end of file
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
index b61720b00a3..635d34ab4d8 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
+++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
@@ -479,6 +479,224 @@
name="%Option.Gnu.Assembler.version"
id="gnu.both.asm.option.version"/>
</tool>
+ <tool
+ natureFilter="cnature"
+ sources="o"
+ name="%ToolName.linker.macosx.c"
+ outputFlag="-o"
+ command="gcc"
+ dependencyCalculator="org.eclipse.cdt.managedbuilder.makegen.internal.DefaultNoDependencyCalculator"
+ id="cdt.managedbuild.tool.macosx.c.linker">
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.c.linker"
+ name="%OptionCategory.General"
+ id="macosx.c.link.category.general">
+ </optionCategory>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoStartFiles"
+ category="macosx.c.link.category.general"
+ command="-nostartfiles"
+ id="macosx.c.link.option.nostart"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoDefLibs"
+ category="macosx.c.link.category.general"
+ command="-nodefaultlibs"
+ id="macosx.c.link.option.nodeflibs"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoStdLibs"
+ category="macosx.c.link.category.general"
+ command="-nostdlib"
+ id="macosx.c.link.option.nostdlibs"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.Strip"
+ category="macosx.c.link.category.general"
+ command="--strip-all"
+ id="macosx.c.link.option.strip"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.Static"
+ category="macosx.c.link.category.general"
+ command="-static"
+ id="macosx.c.link.option.noshared"
+ valueType="boolean">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.c.linker"
+ name="%OptionCategory.Libs"
+ id="macosx.c.link.category.libs">
+ </optionCategory>
+ <option
+ name="%Option.Posix.Libs"
+ category="macosx.c.link.category.libs"
+ command="-l"
+ id="macosx.c.link.option.libs"
+ browseType="file"
+ valueType="libs">
+ </option>
+ <option
+ name="%Option.Posix.Libsearch"
+ category="macosx.c.link.category.libs"
+ command="-L"
+ id="macosx.c.link.option.paths"
+ browseType="directory"
+ valueType="stringList">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.c.linker"
+ name="%OptionCategory.Misc"
+ id="macosx.c.link.category.other">
+ </optionCategory>
+ <option
+ name="%Option.Posix.Linker.Flags"
+ category="macosx.c.link.category.other"
+ valueType="string"
+ id="macosx.c.link.option.ldflags">
+ </option>
+ <option
+ name="%Option.Posix.Linker.XLinker"
+ category="macosx.c.link.category.other"
+ command="-Xlinker,"
+ valueType="stringList"
+ id="macosx.c.link.option.other">
+ </option>
+ <option
+ name="%Option.Posix.UserObjs"
+ category="macosx.c.link.category.other"
+ browseType="file"
+ valueType="userObjs"
+ id="macosx.c.link.option.userobjs">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.c.linker"
+ name="%OptionCategory.Shared.Settings"
+ id="macosx.c.link.category.shared">
+ </optionCategory>
+ <option
+ defaultValue="false"
+ name="%Option.MacOSX.Linker.Shared"
+ category="macosx.c.link.category.shared"
+ command="-Wl,-dylib"
+ id="macosx.c.link.option.shared"
+ valueType="boolean">
+ </option>
+ </tool>
+ <tool
+ natureFilter="ccnature"
+ sources="o"
+ name="%ToolName.linker.macosx.cpp"
+ outputFlag="-o"
+ command="g++"
+ dependencyCalculator="org.eclipse.cdt.managedbuilder.makegen.internal.DefaultNoDependencyCalculator"
+ id="cdt.managedbuild.tool.macosx.cpp.linker">
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.cpp.linker"
+ name="%OptionCategory.General"
+ id="macosx.cpp.link.category.options">
+ </optionCategory>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoStartFiles"
+ category="macosx.cpp.link.category.options"
+ command="-nostartfiles"
+ id="macosx.cpp.link.option.nostart"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoDefLibs"
+ category="macosx.cpp.link.category.options"
+ command="-nodefaultlibs"
+ id="macosx.cpp.link.option.nodeflibs"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.NoStdLibs"
+ category="macosx.cpp.link.category.options"
+ command="-nostdlib"
+ id="macosx.cpp.link.option.nostdlibs"
+ valueType="boolean">
+ </option>
+ <option
+ defaultValue="false"
+ name="%Option.Posix.Linker.Strip"
+ category="macosx.cpp.link.category.options"
+ command="--strip-all"
+ id="macosx.cpp.link.option.strip"
+ valueType="boolean">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.cpp.linker"
+ name="%OptionCategory.Libs"
+ id="macosx.cpp.link.category.libs">
+ </optionCategory>
+ <option
+ name="%Option.Posix.Libs"
+ category="macosx.cpp.link.category.libs"
+ command="-l"
+ id="macosx.cpp.link.option.libs"
+ browseType="file"
+ valueType="libs">
+ </option>
+ <option
+ name="%Option.Posix.Libsearch"
+ category="macosx.cpp.link.category.libs"
+ command="-L"
+ id="macosx.cpp.link.option.paths"
+ browseType="directory"
+ valueType="stringList">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.cpp.linker"
+ name="%OptionCategory.Misc"
+ id="macosx.cpp.link.category.other">
+ </optionCategory>
+ <option
+ name="%Option.Posix.Linker.Flags"
+ category="macosx.cpp.link.category.other"
+ valueType="string"
+ id="macosx.cpp.link.option.flags">
+ </option>
+ <option
+ name="%Option.Posix.Linker.XLinker"
+ category="macosx.cpp.link.category.other"
+ command="-Xlinker "
+ valueType="stringList"
+ id="macosx.cpp.link.option.other">
+ </option>
+ <option
+ name="%Option.Posix.UserObjs"
+ category="macosx.cpp.link.category.other"
+ browseType="file"
+ valueType="userObjs"
+ id="macosx.cpp.link.option.userobjs">
+ </option>
+ <optionCategory
+ owner="cdt.managedbuild.tool.macosx.cpp.linker"
+ name="%OptionCategory.Shared.Settings"
+ id="macosx.cpp.link.category.shared">
+ </optionCategory>
+ <option
+ defaultValue="false"
+ name="%Option.MacOSX.Linker.Shared"
+ category="macosx.cpp.link.category.shared"
+ command="-Wl,-dylib"
+ valueType="boolean"
+ id="macosx.cpp.link.option.shared">
+ </option>
+ </tool>
<target
name="%TargetName.gnu"
id="cdt.managedbuild.target.gnu"
@@ -959,7 +1177,7 @@
</target>
<target
isAbstract="false"
- osList="solaris,linux,hpux,aix,macosx,qnx"
+ osList="solaris,linux,hpux,aix,qnx"
scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
isTest="false"
makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
@@ -1027,7 +1245,7 @@
</target>
<target
isTest="false"
- osList="solaris,linux,hpux,aix,macosx,qnx"
+ osList="solaris,linux,hpux,aix,qnx"
scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
name="%TargetName.gnu.so"
@@ -1106,7 +1324,7 @@
</target>
<target
isTest="false"
- osList="solaris,linux,hpux,aix,macosx,qnx"
+ osList="solaris,linux,hpux,aix,qnx"
scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
name="%TargetName.gnu.lib"
@@ -1392,6 +1610,231 @@
id="cdt.managedbuild.tool.gnu.archiver">
</toolReference>
</target>
+ <target
+ name="%TargetName.macosx.exe"
+ id="cdt.managedbuild.target.macosx.exe"
+ isTest="false"
+ scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
+ makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
+ isAbstract="false"
+ binaryParser="org.eclipse.cdt.core.MachO"
+ parent="cdt.managedbuild.target.gnu"
+ osList="macosx">
+ <configuration
+ name="%ConfigName.Dbg"
+ id="cdt.managedbuild.config.gnu.macosx.exe.debug">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.none"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.max"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.none"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.max"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <configuration
+ name="%ConfigName.Rel"
+ id="cdt.managedbuild.config.macosx.exe.release">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.most"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.none"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.most"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.none"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <toolReference
+ outputs="exe"
+ id="cdt.managedbuild.tool.macosx.c.linker">
+ </toolReference>
+ <toolReference
+ outputs="exe"
+ id="cdt.managedbuild.tool.macosx.cpp.linker">
+ </toolReference>
+ </target>
+ <target
+ name="%TargetName.macosx.so"
+ id="cdt.managedbuild.target.macosx.so"
+ isTest="false"
+ defaultExtension="dylib"
+ scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
+ makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
+ isAbstract="false"
+ binaryParser="org.eclipse.cdt.core.MachO"
+ parent="cdt.managedbuild.target.gnu"
+ osList="macosx">
+ <configuration
+ name="%ConfigName.Dbg"
+ id="cdt.managedbuild.config.macosx.so.debug">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.none"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.max"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.none"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.max"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <configuration
+ name="%ConfigName.Rel"
+ id="cdt.managedbuild.config.macosx.so.release">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.most"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.none"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.most"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.none"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <toolReference
+ outputs="dylib"
+ outputPrefix="lib"
+ id="cdt.managedbuild.tool.macosx.c.linker">
+ <optionReference
+ defaultValue="true"
+ id="macosx.c.link.option.shared"/>
+ <optionReference
+ defaultValue="true"
+ id="macosx.c.link.option.nostart"/>
+ <optionReference
+ defaultValue="true"
+ id="macosx.c.link.option.nodeflibs"/>
+ </toolReference>
+ <toolReference
+ outputs="dylib"
+ id="cdt.managedbuild.tool.macosx.cpp.linker">
+ <optionReference
+ defaultValue="true"
+ id="macosx.cpp.link.option.shared"/>
+ </toolReference>
+ </target>
+ <target
+ name="%TargetName.macosx.lib"
+ id="cdt.managedbuild.target.macosx.lib"
+ isTest="false"
+ makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator"
+ defaultExtension="a"
+ scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector"
+ isAbstract="false"
+ binaryParser="org.eclipse.cdt.core.MachO"
+ parent="cdt.managedbuild.target.gnu"
+ osList="macosx">
+ <configuration
+ name="%ConfigName.Dbg"
+ id="cdt.managedbuild.config.macosx.lib.debug">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.none"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.max"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.none"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.max"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <configuration
+ name="%ConfigName.Rel"
+ id="cdt.managedbuild.config.macosxlib.release">
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.c.compiler">
+ <optionReference
+ defaultValue="gnu.c.optimization.level.most"
+ id="gnu.c.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.c.debugging.level.none"
+ id="gnu.c.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ <toolReference
+ id="cdt.managedbuild.tool.gnu.cpp.compiler">
+ <optionReference
+ defaultValue="gnu.cpp.compiler.optimization.level.most"
+ id="gnu.cpp.compiler.option.optimization.level">
+ </optionReference>
+ <optionReference
+ defaultValue="gnu.cpp.compiler.debugging.level.none"
+ id="gnu.cpp.compiler.option.debugging.level">
+ </optionReference>
+ </toolReference>
+ </configuration>
+ <toolReference
+ outputPrefix="lib"
+ outputs="a"
+ id="cdt.managedbuild.tool.gnu.archiver">
+ </toolReference>
+ </target>
</extension>
</plugin>
diff --git a/core/org.eclipse.cdt.core.macosx/.cdtproject b/core/org.eclipse.cdt.core.macosx/.cdtproject
new file mode 100644
index 00000000000..31dce0c7c03
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/.cdtproject
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse-cdt version="2.0"?>
+
+<cdtproject>
+<data/>
+</cdtproject>
diff --git a/core/org.eclipse.cdt.core.macosx/.classpath b/core/org.eclipse.cdt.core.macosx/.classpath
new file mode 100644
index 00000000000..065ac06e197
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/core/org.eclipse.cdt.core.macosx/.cvsignore b/core/org.eclipse.cdt.core.macosx/.cvsignore
new file mode 100644
index 00000000000..693869726de
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/.cvsignore
@@ -0,0 +1,2 @@
+bin
+doc
diff --git a/core/org.eclipse.cdt.core.macosx/.project b/core/org.eclipse.cdt.core.macosx/.project
new file mode 100644
index 00000000000..0cda5672e50
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.core.macosx</name>
+ <comment></comment>
+ <projects>
+ <project>org.eclipse.cdt.core</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/core/org.eclipse.cdt.core.macosx/ChangeLog b/core/org.eclipse.cdt.core.macosx/ChangeLog
new file mode 100644
index 00000000000..2d3f92fbf78
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/ChangeLog
@@ -0,0 +1,3 @@
+2004-04-25 Greg Watson
+
+ Converted to MacOSX
diff --git a/core/org.eclipse.cdt.core.macosx/build.properties b/core/org.eclipse.cdt.core.macosx/build.properties
new file mode 100644
index 00000000000..4e44ac9b92f
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/build.properties
@@ -0,0 +1,8 @@
+bin.includes = fragment.xml,\
+ fragment.properties,\
+ about.html,\
+ cdt_macosx.jar,\
+ os/
+src.includes = about.html,\
+ library/
+source.cdt_macosx.jar = src/
diff --git a/core/org.eclipse.cdt.core.macosx/fragment.xml b/core/org.eclipse.cdt.core.macosx/fragment.xml
new file mode 100644
index 00000000000..84fd4b3795d
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<fragment
+ id="org.eclipse.cdt.core.macosx"
+ name="%fragmentName.macosx"
+ version="2.0.0"
+ provider-name="%providerName"
+ plugin-id="org.eclipse.cdt.core"
+ plugin-version="2.0.0">
+
+ <runtime>
+ <library name="cdt_macosx.jar"/>
+ </runtime>
+
+
+ <extension
+ point="org.eclipse.cdt.core.ProcessList">
+ <processList
+ platform="macosx"
+ class="org.eclipse.cdt.internal.core.macosx.ProcessList">
+ </processList>
+ </extension>
+</fragment>
diff --git a/core/org.eclipse.cdt.core.macosx/library/.cvsignore b/core/org.eclipse.cdt.core.macosx/library/.cvsignore
new file mode 100644
index 00000000000..5761abcfdf0
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/.cvsignore
@@ -0,0 +1 @@
+*.o
diff --git a/core/org.eclipse.cdt.core.macosx/library/Makefile b/core/org.eclipse.cdt.core.macosx/library/Makefile
new file mode 100644
index 00000000000..4fd9486e984
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/Makefile
@@ -0,0 +1,46 @@
+# makefile for libspawner.so
+# See http://developer.apple.com/documentation/Java/Conceptual/Java141Development/Core_APIs/chapter_6_section_4.html
+
+JAVA_HOME = /Library/Java/Home
+ifeq ($(JAVA_HOME),)
+$(warning JAVA_HOME not set in environment)
+endif
+
+# Defaults which can be overridden.
+OS = macosx
+ARCH = ppc
+
+JDK_INCLUDES= $(JAVA_HOME)/include
+
+CC=gcc
+LD=libtool
+CPPFLAGS = -I. -I$(JDK_INCLUDES) #-I$(JDK_OS_INCLUDES)
+CFLAGS +=-fPIC -D_REENTRANT
+
+INSTALL_DIR = ../os/$(OS)/$(ARCH)
+
+LIB_NAME_SPAWNER = libspawner.dylib
+LIB_NAME_FULL_SPAWNER = $(INSTALL_DIR)/libspawner.jnilib
+OBJS_SPAWNER=spawner.o io.o exec_unix.o pfind.o
+
+LIB_NAME_PTY = libpty.so
+LIB_NAME_FULL_PTY = $(INSTALL_DIR)/libpty.jnilib
+OBJS_PTY= openpty.o pty.o ptyio.o
+
+OBJS = $(OBJS_SPAWNER) $(OBJS_PTY)
+
+all: $(LIB_NAME_FULL_SPAWNER) $(LIB_NAME_FULL_PTY)
+
+rebuild: clean all
+
+$(LIB_NAME_FULL_SPAWNER) : $(OBJS_SPAWNER)
+ mkdir -p $(INSTALL_DIR)
+ $(CC) -dynamiclib -o $(LIB_NAME_FULL_SPAWNER) $(OBJS_SPAWNER) -lc -framework JavaVM
+
+$(LIB_NAME_FULL_PTY): $(OBJS_PTY)
+ mkdir -p $(INSTALL_DIR)
+ $(CC) -dynamiclib -o $(LIB_NAME_FULL_PTY) $(OBJS_PTY) -lc -framework JavaVM
+
+clean :
+ $(RM) $(OBJS_SPAWNER) $(LIB_NAME_FULL_SPAWNER)
+ $(RM) $(OBJS_PTY) $(LIB_NAME_FULL_PTY)
diff --git a/core/org.eclipse.cdt.core.macosx/library/PTY.h b/core/org.eclipse.cdt.core.macosx/library/PTY.h
new file mode 100644
index 00000000000..fabf58152d0
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/PTY.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_eclipse_cdt_utils_pty_PTY */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTY
+#define _Included_org_eclipse_cdt_utils_pty_PTY
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: forkpty
+ * Signature: ()I
+ */
+JNIEXPORT jstring JNICALL Java_org_eclipse_cdt_utils_pty_PTY_forkpty
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/PTYInputStream.h b/core/org.eclipse.cdt.core.macosx/library/PTYInputStream.h
new file mode 100644
index 00000000000..e7349272b56
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/PTYInputStream.h
@@ -0,0 +1,32 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_eclipse_cdt_utils_pty_PTYInputStream */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTYInputStream
+#define _Included_org_eclipse_cdt_utils_pty_PTYInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_eclipse_cdt_utils_pty_PTYInputStream_SKIP_BUFFER_SIZE
+#define org_eclipse_cdt_utils_pty_PTYInputStream_SKIP_BUFFER_SIZE 2048L
+/* Inaccessible static: skipBuffer */
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: read0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYInputStream_read0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYInputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/PTYOutputStream.h b/core/org.eclipse.cdt.core.macosx/library/PTYOutputStream.h
new file mode 100644
index 00000000000..fb28491060e
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/PTYOutputStream.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_eclipse_cdt_utils_pty_PTYOutputStream */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTYOutputStream
+#define _Included_org_eclipse_cdt_utils_pty_PTYOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: write0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYOutputStream_write0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYOutputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/Spawner.h b/core/org.eclipse.cdt.core.macosx/library/Spawner.h
new file mode 100644
index 00000000000..287c8370ab0
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/Spawner.h
@@ -0,0 +1,45 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_qnx_tools_utils_spawner_Spawner */
+
+#ifndef _Included_com_qnx_tools_utils_spawner_Spawner
+#define _Included_com_qnx_tools_utils_spawner_Spawner
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: exec0
+ * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
+ (JNIEnv *, jobject, jobjectArray, jobjectArray, jstring, jintArray);
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: exec0
+ * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
+ (JNIEnv *, jobject, jobjectArray, jobjectArray, jstring);
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: raise
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: waitFor
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/SpawnerInputStream.h b/core/org.eclipse.cdt.core.macosx/library/SpawnerInputStream.h
new file mode 100644
index 00000000000..ecf8f8c6a78
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/SpawnerInputStream.h
@@ -0,0 +1,32 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_qnx_tools_utils_spawner_SpawnerInputStream */
+
+#ifndef _Included_com_qnx_tools_utils_spawner_SpawnerInputStream
+#define _Included_com_qnx_tools_utils_spawner_SpawnerInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_qnx_tools_utils_spawner_SpawnerInputStream_SKIP_BUFFER_SIZE
+#define com_qnx_tools_utils_spawner_SpawnerInputStream_SKIP_BUFFER_SIZE 2048L
+/* Inaccessible static: skipBuffer */
+/*
+ * Class: org_elipse_cdt_utils_spawner_SpawnerInputStream
+ * Method: read0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_read0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerInputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/SpawnerOutputStream.h b/core/org.eclipse.cdt.core.macosx/library/SpawnerOutputStream.h
new file mode 100644
index 00000000000..444d71c698c
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/SpawnerOutputStream.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_qnx_tools_utils_spawner_SpawnerOutputStream */
+
+#ifndef _Included_com_qnx_tools_utils_spawner_SpawnerOutputStream
+#define _Included_com_qnx_tools_utils_spawner_SpawnerOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerOutputStream
+ * Method: write0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_write0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerOutputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/exec0.h b/core/org.eclipse.cdt.core.macosx/library/exec0.h
new file mode 100644
index 00000000000..354b1c3d769
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/exec0.h
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+
+extern pid_t exec0(const char *path, char *const argv[],
+ char *const envp[], const char *dirpath,
+ int channels[3] );
+
+extern int wait0(pid_t pid);
diff --git a/core/org.eclipse.cdt.core.macosx/library/exec_unix.c b/core/org.eclipse.cdt.core.macosx/library/exec_unix.c
new file mode 100644
index 00000000000..6cb8ac88d8b
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/exec_unix.c
@@ -0,0 +1,135 @@
+#include "exec0.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+#include <stdlib.h>
+
+/* from pfind.c */
+extern char *pfind(const char *name);
+
+pid_t
+exec0(const char *path, char *const argv[], char *const envp[],
+ const char *dirpath, int channels[3])
+{
+ int pipe0[2], pipe1[2], pipe2[2];
+ pid_t childpid;
+ char *full_path;
+
+ /*
+ * We use pfind() to check that the program exists and is an executable.
+ * If not pass the error up. Also execve() wants a full path.
+ */
+ full_path = pfind(path);
+ if (full_path == NULL) {
+ fprintf(stderr, "Unable to find full path for \"%s\"\n", (path) ? path : "");
+ return -1;
+ }
+
+ /*
+ * Make sure we can create our pipes before forking.
+ */
+ if (channels != NULL) {
+ if (pipe(pipe0) < 0 || pipe(pipe1) < 0 || pipe(pipe2) < 0) {
+ fprintf(stderr, "%s(%d): returning due to error.\n",
+ __FUNCTION__, __LINE__);
+ free(full_path);
+ return -1;
+ }
+ }
+
+ childpid = fork();
+
+ if (childpid < 0) {
+ fprintf(stderr, "%s(%d): returning due to error: %s\n",
+ __FUNCTION__, __LINE__, strerror(errno));
+ free(full_path);
+ return -1;
+ } else if (childpid == 0) { /* child */
+ char *ptr;
+
+ chdir(dirpath);
+
+ if (channels != NULL) {
+ /* Close the write end of pipe0 */
+ if (close(pipe0[1]) == -1)
+ perror("close(pipe0[1])");
+
+ /* Close the read end of pipe1 */
+ if (close(pipe1[0]) == -1)
+ perror("close(pipe1[0])");
+
+ /* Close the read end of pipe2 */
+ if (close(pipe2[0]) == -1)
+ perror("close(pipe2[0]))");
+
+ /* redirections */
+ dup2(pipe0[0], STDIN_FILENO); /* dup stdin */
+ dup2(pipe1[1], STDOUT_FILENO); /* dup stdout */
+ dup2(pipe2[1], STDERR_FILENO); /* dup stderr */
+ }
+
+ /* Close all the fd's in the child */
+ {
+ int fdlimit = sysconf(_SC_OPEN_MAX);
+ int fd = 3;
+
+ while (fd < fdlimit)
+ close(fd++);
+ }
+
+ if (envp[0] == NULL) {
+ execv(full_path, argv);
+ } else {
+ execve(full_path, argv, envp);
+ }
+
+ _exit(127);
+
+ } else if (childpid != 0) { /* parent */
+
+ char b;
+
+ if (channels != NULL) {
+ /* close the read end of pipe1 */
+ if (close(pipe0[0]) == -1)
+ perror("close(pipe0[0])");
+
+ /* close the write end of pipe2 */
+ if (close(pipe1[1]) == -1)
+ perror("close(pipe1[1])");
+
+ /* close the write end of pipe2 */
+ if (close(pipe2[1]) == -1)
+ perror("close(pipe2[1])");
+
+ channels[0] = pipe0[1]; /* Output Stream. */
+ channels[1] = pipe1[0]; /* Input Stream. */
+ channels[2] = pipe2[0]; /* Input Stream. */
+ }
+
+ free(full_path);
+ return childpid;
+ }
+
+ free(full_path);
+ return -1; /*NOT REACHED */
+}
+
+
+int wait0(pid_t pid)
+{
+ int status;
+ int val = -1;
+
+ if (pid < 0 || waitpid(pid, &status, 0) < 0)
+ return -1;
+
+ if (WIFEXITED(status)) {
+ val = WEXITSTATUS(status);
+ }
+
+ return val;
+}
diff --git a/core/org.eclipse.cdt.core.macosx/library/io.c b/core/org.eclipse.cdt.core.macosx/library/io.c
new file mode 100644
index 00000000000..499d4a7b567
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/io.c
@@ -0,0 +1,103 @@
+#include <jni.h>
+#include <stdio.h>
+#include <SpawnerInputStream.h>
+#include <SpawnerOutputStream.h>
+#include <unistd.h>
+
+/* Header for class _org_eclipse_cdt_utils_spawner_SpawnerInputStream */
+/* Header for class _org_eclipse_cdt_utils_spawner_SpawnerOutputStream */
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerInputStream
+ * Method: read0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_read0(JNIEnv * env,
+ jobject jobj,
+ jint jfd,
+ jbyteArray buf,
+ jint buf_len)
+{
+ int fd;
+ int status;
+ jbyte *data;
+ int data_len;
+
+ data = (*env)->GetByteArrayElements(env, buf, 0);
+ data_len = buf_len;
+ fd = jfd;
+
+ status = read( fd, data, data_len );
+ (*env)->ReleaseByteArrayElements(env, buf, data, 0);
+
+ if (status == 0) {
+ /* EOF. */
+ status = -1;
+ } else if (status == -1) {
+ /* Error, toss an exception */
+ jclass exception = (*env)->FindClass(env, "java/io/IOException");
+ if (exception == NULL) {
+ /* Give up. */
+ return -1;
+ }
+ (*env)->ThrowNew(env, exception, "read error");
+ }
+
+ return status;
+}
+
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerInputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0(JNIEnv * env,
+ jobject jobj,
+ jint fd)
+{
+ return close(fd);
+}
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerOutputStream
+ * Method: write0
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_write0(JNIEnv * env,
+ jobject jobj,
+ jint jfd,
+ jbyteArray buf,
+ jint buf_len)
+{
+ int status;
+ int fd;
+ jbyte *data;
+ int data_len;
+
+ data = (*env)->GetByteArrayElements(env, buf, 0);
+ data_len = buf_len;
+ fd = jfd;
+
+ status = write(fd, data, data_len);
+ (*env)->ReleaseByteArrayElements(env, buf, data, 0);
+
+ return status;
+}
+
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_SpawnerOutputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0(JNIEnv * env,
+ jobject jobj,
+ jint fd)
+{
+ return close(fd);
+}
diff --git a/core/org.eclipse.cdt.core.macosx/library/openpty.c b/core/org.eclipse.cdt.core.macosx/library/openpty.c
new file mode 100644
index 00000000000..b1660a13b78
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/openpty.c
@@ -0,0 +1,104 @@
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <grp.h>
+
+#include <stdlib.h>
+
+/**
+ * This is taken from R. W. Stevens book.
+ * Alain Magloire.
+ */
+
+int ptym_open (char *pts_name);
+int ptys_open (int fdm, char * pts_name);
+
+int
+openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp)
+{
+ char line[20];
+ line[0]=0;
+ *amaster = ptym_open(line);
+ if (*amaster < 0)
+ return -1;
+ *aslave = ptys_open(*amaster, line);
+ if (*aslave < 0) {
+ close(*amaster);
+ return -1;
+ }
+ if (name)
+ strcpy(name, line);
+#ifndef TCSAFLUSH
+#define TCSAFLUSH TCSETAF
+#endif
+ if (termp)
+ (void) tcsetattr(*aslave, TCSAFLUSH, termp);
+#ifdef TIOCSWINSZ
+ if (winp)
+ (void) ioctl(*aslave, TIOCSWINSZ, (char *)winp);
+#endif
+ return 0;
+}
+
+int
+ptym_open(char * pts_name)
+{
+ char *ptr1, *ptr2;
+ int fdm;
+
+ strcpy(pts_name, "/dev/ptyXY");
+ /* array index: 012345689 (for references in following code) */
+ for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
+ pts_name[8] = *ptr1;
+ for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
+ pts_name[9] = *ptr2;
+ /* try to open master */
+ fdm = open(pts_name, O_RDWR);
+ if (fdm < 0) {
+ if (errno == ENOENT) {/* different from EIO */
+ return -1; /* out of pty devices */
+ } else {
+ continue; /* try next pty device */
+ }
+ }
+ pts_name[5] = 't'; /* chage "pty" to "tty" */
+ return fdm; /* got it, return fd of master */
+ }
+ }
+ return -1; /* out of pty devices */
+}
+
+int
+ptys_open(int fdm, char * pts_name)
+{
+ int gid, fds;
+ struct group *grptr;
+
+ grptr = getgrnam("tty");
+ if (grptr != NULL) {
+ gid = grptr->gr_gid;
+ } else {
+ gid = -1; /* group tty is not in the group file */
+ }
+
+ /* following two functions don't work unless we're root */
+ chown(pts_name, getuid(), gid);
+ chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
+ fds = open(pts_name, O_RDWR);
+ if (fds < 0) {
+ close(fdm);
+ return -1;
+ }
+ return fds;
+}
diff --git a/core/org.eclipse.cdt.core.macosx/library/openpty.h b/core/org.eclipse.cdt.core.macosx/library/openpty.h
new file mode 100644
index 00000000000..fd7b7be1b2f
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/openpty.h
@@ -0,0 +1,10 @@
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ *
+ */
+#ifndef _OPENPTY_H
+#define _OPENPTY_H
+int ptym_open (char *pts_name);
+int ptys_open (int fdm, char * pts_name);
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/pfind.c b/core/org.eclipse.cdt.core.macosx/library/pfind.c
new file mode 100644
index 00000000000..d13dae5f0e2
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/pfind.c
@@ -0,0 +1,78 @@
+/*
+ * pfind.c - Search for a binary in $PATH.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+
+char * pfind(const char *name)
+{
+ char *tok;
+ char *sp;
+ char *path;
+ char fullpath[PATH_MAX+1];
+
+ /* Sanity check. */
+ if (name == NULL) {
+ fprintf(stderr, "pfind(): Null argument.\n");
+ return NULL;
+ }
+
+ /* For absolute name or name with a path, check if it is an executable. */
+ if (name[0] == '/' || name[0] == '.') {
+ if (access(name, X_OK | R_OK) == 0) {
+ return strdup(name);
+ }
+ return NULL;
+ }
+
+ /* Search in the PATH environment. */
+ path = getenv("PATH" );
+
+ if (path == NULL || strlen(path) <= 0) {
+ fprintf(stderr, "Unable to get $PATH.\n");
+ return NULL;
+ }
+
+ /* The value return by getenv() is readonly */
+ path = strdup(path);
+
+ tok = strtok_r(path, ":", &sp);
+ while (tok != NULL) {
+ snprintf(fullpath, sizeof(fullpath) - 1, "%s/%s", tok, name);
+
+ if (access(fullpath, X_OK | R_OK) == 0) {
+ free(path);
+ return strdup(fullpath);
+ }
+
+ tok = strtok_r( NULL, ":", &sp );
+ }
+
+ free(path);
+ return NULL;
+}
+
+#ifdef BUILD_WITH_MAIN
+int main(int argc, char **argv)
+{
+ int i;
+ char *fullpath;
+
+ for (i=1; i<argc; i++) {
+ fullpath = pfind(argv[i]);
+ if (fullpath == NULL)
+ printf("Unable to find %s in $PATH.\n", argv[i]);
+ else
+ printf("Found %s @ %s.\n", argv[i], fullpath);
+ }
+}
+#endif
diff --git a/core/org.eclipse.cdt.core.macosx/library/pty.c b/core/org.eclipse.cdt.core.macosx/library/pty.c
new file mode 100644
index 00000000000..4b9e682c3ee
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/pty.c
@@ -0,0 +1,35 @@
+#include "PTY.h"
+#include "openpty.h"
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: forkpty
+ * Signature: ()I
+ */
+JNIEXPORT jstring JNICALL
+Java_org_eclipse_cdt_utils_pty_PTY_forkpty (JNIEnv *env, jobject jobj) {
+ jfieldID fid; /* Store the field ID */
+ jstring jstr = NULL;
+ int master = -1;
+ char line[1024]; /* FIXME: Should be enough */
+ jclass cls;
+
+ line[0] = '\0';
+
+ master = ptym_open(line);
+ if (master >= 0) {
+ /* Get a reference to the obj's class */
+ cls = (*env)->GetObjectClass(env, jobj);
+
+ /* Set the master fd. */
+ fid = (*env)->GetFieldID(env, cls, "master", "I");
+ if (fid == NULL) {
+ return NULL;
+ }
+ (*env)->SetIntField(env, jobj, fid, (jint)master);
+
+ /* Create a new String for the slave. */
+ jstr = (*env)->NewStringUTF(env, line);
+ }
+ return jstr;
+}
diff --git a/core/org.eclipse.cdt.core.macosx/library/ptyio.c b/core/org.eclipse.cdt.core.macosx/library/ptyio.c
new file mode 100644
index 00000000000..67d7594154d
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/ptyio.c
@@ -0,0 +1,107 @@
+#include <jni.h>
+#include <stdio.h>
+#include <PTYInputStream.h>
+#include <PTYOutputStream.h>
+#include <unistd.h>
+
+/* Header for class _org_eclipse_cdt_utils_pty_PTYInputStream */
+/* Header for class _org_eclipse_cdt_utils_pty_PTYOutputStream */
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: read0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_pty_PTYInputStream_read0(JNIEnv * env,
+ jobject jobj,
+ jint jfd,
+ jbyteArray buf,
+ jint buf_len)
+{
+ int fd;
+ int status;
+ jbyte *data;
+ int data_len;
+
+ data = (*env)->GetByteArrayElements(env, buf, 0);
+ data_len = buf_len;
+ fd = jfd;
+
+ status = read( fd, data, data_len );
+ (*env)->ReleaseByteArrayElements(env, buf, data, 0);
+
+ if (status == 0) {
+ /* EOF. */
+ status = -1;
+ } else if (status == -1) {
+ /* Error, toss an exception */
+ /* Ignore the error for now, the debugger will attempt
+ * to close this multiple time. */
+#if 0
+ jclass exception = (*env)->FindClass(env, "java/io/IOException");
+ if (exception == NULL) {
+ /* Give up. */
+ return -1;
+ }
+ (*env)->ThrowNew(env, exception, "read error");
+#endif
+ }
+
+ return status;
+}
+
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_pty_PTYInputStream_close0(JNIEnv * env,
+ jobject jobj,
+ jint fd)
+{
+ return close(fd);
+}
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: write0
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_pty_PTYOutputStream_write0(JNIEnv * env,
+ jobject jobj,
+ jint jfd,
+ jbyteArray buf,
+ jint buf_len)
+{
+ int status;
+ int fd;
+ jbyte *data;
+ int data_len;
+
+ data = (*env)->GetByteArrayElements(env, buf, 0);
+ data_len = buf_len;
+ fd = jfd;
+
+ status = write(fd, data, data_len);
+ (*env)->ReleaseByteArrayElements(env, buf, data, 0);
+
+ return status;
+}
+
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_pty_PTYOutputStream_close0(JNIEnv * env,
+ jobject jobj,
+ jint fd)
+{
+ return close(fd);
+}
diff --git a/core/org.eclipse.cdt.core.macosx/library/spawner.c b/core/org.eclipse.cdt.core.macosx/library/spawner.c
new file mode 100644
index 00000000000..4624d763cdd
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/library/spawner.c
@@ -0,0 +1,218 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <jni.h>
+
+#include "exec0.h"
+#include <Spawner.h>
+
+
+#define DEBUGIT 0
+
+
+/*
+ * Header for class org_eclipse_cdt_utils_spawner_Spawner
+ */
+
+
+#if DEBUGIT
+static void print_array(char **c_array)
+{
+ if (c_array) {
+ char **p = c_array;
+ for (; *p; p++) {
+ if (*p) {
+ fprintf(stderr, " %s", *p);
+ }
+ }
+ } else {
+ fprintf(stderr, "null");
+ }
+ fprintf(stderr, "\n");
+}
+#endif
+
+
+static char **alloc_c_array(JNIEnv * env, jobjectArray j_array)
+{
+ int i;
+ jint c_array_size = (*env)->GetArrayLength(env, j_array);
+ char **c_array = calloc(c_array_size + 1, sizeof(*c_array));
+
+ if (c_array == NULL)
+ return NULL;
+
+ for (i = 0; i < c_array_size; i++) {
+ jstring j_str =
+ (jstring) (*env)->GetObjectArrayElement(env, j_array, i);
+ const char *c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
+ c_array[i] = (char *) strdup(c_str);
+ (*env)->ReleaseStringUTFChars(env, j_str, c_str);
+ (*env)->DeleteLocalRef(env, j_str);
+ }
+
+ return c_array;
+}
+
+
+static void free_c_array(char **c_array)
+{
+ if (c_array) {
+ char **p = c_array;
+ for (; *p; p++) {
+ if (*p) {
+ free(*p);
+ }
+ }
+ free(c_array);
+ }
+}
+
+
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_Spawner_exec1(JNIEnv * env, jobject jobj,
+ jobjectArray jcmd,
+ jobjectArray jenv,
+ jstring jdir)
+{
+ const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL);
+ char **cmd;
+ char **envp;
+ pid_t pid = -1;
+
+ cmd = alloc_c_array(env, jcmd);
+ if (cmd == NULL)
+ goto bail_out;
+
+ envp = alloc_c_array(env, jenv);
+ if (envp == NULL)
+ goto bail_out;
+
+#if DEBUGIT
+ fprintf(stderr, "command:");
+ print_array(cmd);
+ fprintf(stderr, "Envp:");
+ print_array(envp);
+ fprintf(stderr, "dirpath: %s\n", dirpath);
+#endif
+
+ pid = exec0(cmd[0], cmd, envp, dirpath, NULL);
+ if (pid < 0)
+ goto bail_out;
+
+ bail_out:
+ (*env)->ReleaseStringUTFChars(env, jdir, dirpath);
+ if (cmd)
+ free_c_array(cmd);
+ if (envp)
+ free_c_array(envp);
+ return pid;
+}
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: exec0
+ * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv * env, jobject jobj,
+ jobjectArray jcmd,
+ jobjectArray jenv,
+ jstring jdir,
+ jintArray jchannels)
+{
+ jint *channels = (*env)->GetIntArrayElements(env, jchannels, 0);
+ const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL);
+ char **cmd;
+ char **envp;
+ int fd[3];
+ pid_t pid = -1;
+
+ if (channels == NULL)
+ goto bail_out;
+
+ cmd = alloc_c_array(env, jcmd);
+ if (cmd == NULL)
+ goto bail_out;
+
+ envp = alloc_c_array(env, jenv);
+ if (envp == NULL)
+ goto bail_out;
+
+#if DEBUGIT
+ fprintf(stderr, "command:");
+ print_array(cmd);
+ fprintf(stderr, "Envp:");
+ print_array(envp);
+ fprintf(stderr, "dirpath: %s\n", dirpath);
+#endif
+
+ pid = exec0(cmd[0], cmd, envp, dirpath, fd);
+ if (pid < 0)
+ goto bail_out;
+
+ channels[0] = fd[0];
+ channels[1] = fd[1];
+ channels[2] = fd[2];
+
+ bail_out:
+ (*env)->ReleaseIntArrayElements(env, jchannels, channels, 0);
+ (*env)->ReleaseStringUTFChars(env, jdir, dirpath);
+ if (cmd)
+ free_c_array(cmd);
+ if (envp)
+ free_c_array(envp);
+ return pid;
+}
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: raise
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv * env, jobject jobj,
+ jint pid, jint sig)
+{
+ int status = -1;
+
+ switch (sig) {
+ case 0: /* NOOP */
+ status = kill(pid, 0);
+ break;
+
+ case 2: /* INTERRUPT */
+ status = kill(pid, SIGINT);
+ break;
+
+ case 9: /* KILL */
+ status = kill(pid, SIGKILL);
+ break;
+
+ case 15: /* TERM */
+ status = kill(pid, SIGTERM);
+ break;
+
+ default:
+ status = kill(pid, sig); /* WHAT ?? */
+ break;
+ }
+
+ return status;
+}
+
+
+
+/*
+ * Class: org_eclipse_cdt_utils_spawner_Spawner
+ * Method: waitFor
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv * env,
+ jobject jobj, jint pid)
+{
+ return wait0(pid);
+}
diff --git a/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libpty.jnilib b/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libpty.jnilib
new file mode 100644
index 00000000000..8f240a93186
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libpty.jnilib
Binary files differ
diff --git a/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libspawner.jnilib b/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libspawner.jnilib
new file mode 100644
index 00000000000..a7c51580ace
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/os/macosx/ppc/libspawner.jnilib
Binary files differ
diff --git a/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessInfo.java b/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessInfo.java
new file mode 100644
index 00000000000..fde4e814c77
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessInfo.java
@@ -0,0 +1,45 @@
+package org.eclipse.cdt.internal.core.macosx;
+
+import org.eclipse.cdt.core.IProcessInfo;
+
+/**
+ * @author alain
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ProcessInfo implements IProcessInfo {
+
+ int pid;
+ String name;
+
+ public ProcessInfo(String pidString, String name) {
+ try {
+ pid = Integer.parseInt(pidString);
+ } catch (NumberFormatException e) {
+ }
+ this.name = name;
+ }
+
+ public ProcessInfo(int pid, String name) {
+ this.pid = pid;
+ this.name = name;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.IProcessInfo#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.IProcessInfo#getPid()
+ */
+ public int getPid() {
+ return pid;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessList.java b/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessList.java
new file mode 100644
index 00000000000..65b6237d723
--- /dev/null
+++ b/core/org.eclipse.cdt.core.macosx/src/org/eclipse/cdt/internal/core/macosx/ProcessList.java
@@ -0,0 +1,68 @@
+package org.eclipse.cdt.internal.core.macosx;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.eclipse.cdt.core.IProcessInfo;
+import org.eclipse.cdt.core.IProcessList;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+
+/**
+ * Insert the type's description here.
+ * @see IProcessList
+ */
+public class ProcessList implements IProcessList {
+
+ ProcessInfo[] empty = new ProcessInfo[0];
+
+ public ProcessList() {
+ }
+
+ /**
+ * Insert the method's description here.
+ * @see IProcessList#getProcessList
+ */
+ public IProcessInfo [] getProcessList() {
+ Process ps;
+ BufferedReader psOutput;
+ String[] args = {"/bin/ps", "-a", "-o", "pid,command"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ try {
+ ps = ProcessFactory.getFactory().exec(args);
+ psOutput = new BufferedReader(new InputStreamReader(ps.getInputStream()));
+ } catch(Exception e) {
+ return new IProcessInfo[0];
+ }
+
+ //Read the output and parse it into an array list
+ ArrayList procInfo = new ArrayList();
+
+ try {
+ String lastline;
+ while ((lastline = psOutput.readLine()) != null) {
+ //The format of the output should be
+ //PID space name
+
+ lastline = lastline.trim();
+ int index = lastline.indexOf(' ');
+ if (index != -1) {
+ String pidString = lastline.substring(0, index).trim();
+ try {
+ int pid = Integer.parseInt(pidString);
+ String arg = lastline.substring(index + 1);
+ procInfo.add(new ProcessInfo(pid, arg));
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+
+ } catch(Exception e) {
+ /* Ignore */
+ }
+
+ ps.destroy();
+ return (IProcessInfo [])procInfo.toArray(new IProcessInfo[procInfo.size()]);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/plugin.properties b/core/org.eclipse.cdt.core/plugin.properties
index 348b612ccdc..de645980556 100644
--- a/core/org.eclipse.cdt.core/plugin.properties
+++ b/core/org.eclipse.cdt.core/plugin.properties
@@ -30,6 +30,7 @@ GNUElfParser.name=GNU Elf Parser
PEWindowsParser.name=PE Windows Parser
CygwinPEParser.name=Cygwin PE Parser
XCOFF32Parser.name=AIX XCOFF32 Parser
+MachOParser.name=Mach-O Parser
CDTGNUCErrorParser.name=CDT GNU C/C++ Error Parser
CDTGNUAssemblerErrorParser.name=CDT GNU Assembler Error Parser
@@ -50,3 +51,4 @@ fragmentName.linux = C/C++ Development Tools Core for Linux
fragmentName.qnx = C/C++ Development Tools Core for QNX
fragmentName.solaris = C/C++ Development Tools Core for Solaris
fragmentName.win32 = C/C++ Development Tools Core for Windows
+fragmentName.macosx = C/C++ Development Tools Core for MacOS X
diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml
index 6230a2bc10c..a64d15b2ebd 100644
--- a/core/org.eclipse.cdt.core/plugin.xml
+++ b/core/org.eclipse.cdt.core/plugin.xml
@@ -123,6 +123,20 @@
</run>
</cextension>
</extension>
+ <extension
+ id="MachO"
+ name="%MachOParser.name"
+ point="org.eclipse.cdt.core.BinaryParser">
+ <cextension>
+ <filter
+ name = "visibility"
+ value = "private">
+ </filter>
+ <run
+ class="org.eclipse.cdt.utils.macho.parser.MachOParser">
+ </run>
+ </cextension>
+ </extension>
<!-- =================================================================================== -->
<!-- Define the list of Error Parser provided by the CDT -->
<!-- =================================================================================== -->
@@ -371,6 +385,10 @@
enabled="true"
pattern="*.exe">
</ignore>
+ <ignore
+ enabled="true"
+ pattern="*.dylib">
+ </ignore>
</extension>
<!-- =================================================================================== -->
<!-- =================================================================================== -->
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/AR.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/AR.java
new file mode 100644
index 00000000000..cd36b08d449
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/AR.java
@@ -0,0 +1,336 @@
+package org.eclipse.cdt.utils.macho;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Vector;
+
+import org.eclipse.cdt.core.CCorePlugin;
+
+/**
+ * The <code>AR</code> class is used for parsing standard archive (ar) files.
+ *
+ * Each object within the archive is represented by an ARHeader class. Each of
+ * of these objects can then be turned into an Elf object for performing Elf
+ * class operations.
+ * @see ARHeader
+ */
+public class AR {
+
+ protected String filename;
+ protected ERandomAccessFile efile;
+ protected long strtbl_pos = -1;
+ private ARHeader[] headers;
+
+ public void dispose() {
+ try {
+ if (efile != null) {
+ efile.close();
+ efile = null;
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * The <code>ARHeader</code> class is used to store the per-object file
+ * archive headers. It can also create an Mach-O object for inspecting
+ * the object file data.
+ */
+ public class ARHeader {
+
+ private String object_name;
+ private String modification_time;
+ private String uid;
+ private String gid;
+ private String mode;
+ private long size;
+ private long file_offset;
+ private long macho_offset;
+
+ /**
+ * Remove the padding from the archive header strings.
+ */
+ private String removeBlanks(String str) {
+ while (str.charAt(str.length() - 1) == ' ')
+ str = str.substring(0, str.length() - 1);
+ return str;
+ }
+
+ /**
+ * Look up the name stored in the archive's string table based
+ * on the offset given.
+ *
+ * Maintains <code>efile</code> file location.
+ *
+ * @param offset
+ * Offset into the string table for first character of the name.
+ * @throws IOException
+ * <code>offset</code> not in string table bounds.
+ */
+ private String nameFromStringTable(long offset) throws IOException {
+ StringBuffer name = new StringBuffer(0);
+ long pos = efile.getFilePointer();
+
+ try {
+ if (strtbl_pos != -1) {
+ byte temp;
+ efile.seek(strtbl_pos + offset);
+ while ((temp = efile.readByte()) != '\n')
+ name.append((char) temp);
+ }
+ } finally {
+ efile.seek(pos);
+ }
+
+ return name.toString();
+ }
+
+ /**
+ * Creates a new archive header object.
+ *
+ * Assumes that efile is already at the correct location in the file.
+ *
+ * @throws IOException
+ * There was an error processing the header data from the file.
+ */
+ public ARHeader() throws IOException {
+ byte[] object_name = new byte[16];
+ byte[] modification_time = new byte[12];
+ byte[] uid = new byte[6];
+ byte[] gid = new byte[6];
+ byte[] mode = new byte[8];
+ byte[] size = new byte[10];
+ byte[] trailer = new byte[2];
+
+ //
+ // Read in the archive header data. Fixed sizes.
+ //
+ efile.read(object_name);
+ efile.read(modification_time);
+ efile.read(uid);
+ efile.read(gid);
+ efile.read(mode);
+ efile.read(size);
+ efile.read(trailer);
+
+ //
+ // Save this location so we can create the Mach-O object later.
+ //
+ macho_offset = efile.getFilePointer();
+
+ //
+ // Convert the raw bytes into strings and numbers.
+ //
+ this.object_name = removeBlanks(new String(object_name));
+ this.modification_time = new String(modification_time);
+ this.uid = new String(uid);
+ this.gid = new String(gid);
+ this.mode = new String(mode);
+ this.size = Long.parseLong(removeBlanks(new String(size)));
+
+ //
+ // If the name is of the format "#1/<number>", real name directly follows the
+ // header.
+ //
+ if (this.object_name.length() > 3
+ && this.object_name.charAt(0) == '#'
+ && this.object_name.charAt(1) == '1'
+ && this.object_name.charAt(2) == '/') {
+ try {
+ int len = Integer.parseInt(this.object_name.substring(3));
+ byte[] real_name = new byte[len];
+ efile.read(real_name);
+ this.object_name = new String(real_name);
+ long pos = efile.getFilePointer();
+ efile.seek(macho_offset);
+ macho_offset = pos;
+ } catch (java.lang.Exception e) {
+ }
+ }
+
+ //
+ // Strip the trailing / from the object name.
+ //
+ int len = this.object_name.length();
+ if (len > 2 && this.object_name.charAt(len - 1) == '/') {
+ this.object_name = this.object_name.substring(0, len - 1);
+ }
+
+ }
+
+ /** Get the name of the object file */
+ public String getObjectName() {
+ return object_name;
+ }
+
+ /** Get the size of the object file . */
+ public long getSize() {
+ return size;
+ }
+
+ public String getArchiveName() {
+ return filename;
+ }
+
+ /**
+ * Create an new MachO object for the object file.
+ *
+ * @throws IOException
+ * Not a valid MachO object file.
+ * @return A new MachO object.
+ * @see MachO#MachO( String, long )
+ */
+ public MachO getMachO() throws IOException {
+ return new MachO(filename, macho_offset);
+ }
+
+ public MachO getMachO(boolean filter_on) throws IOException {
+ return new MachO(filename, macho_offset, filter_on);
+ }
+
+ public byte[] getObjectData() throws IOException {
+ byte[] temp = new byte[(int) size];
+ if (efile != null) {
+ efile.seek(macho_offset);
+ efile.read(temp);
+ } else {
+ efile = new ERandomAccessFile(filename, "r"); //$NON-NLS-1$
+ efile.seek(macho_offset);
+ efile.read(temp);
+ efile.close();
+ efile = null;
+ }
+ return temp;
+ }
+ }
+
+ public static boolean isARHeader(byte[] ident) {
+ if (ident.length < 7
+ || ident[0] != '!'
+ || ident[1] != '<'
+ || ident[2] != 'a'
+ || ident[3] != 'r'
+ || ident[4] != 'c'
+ || ident[5] != 'h'
+ || ident[6] != '>')
+ return false;
+ return true;
+ }
+
+ /**
+ * Creates a new <code>AR</code> object from the contents of
+ * the given file.
+ *
+ * @param filename The file to process.
+ * @throws IOException The file is not a valid archive.
+ */
+ public AR(String filename) throws IOException {
+ this.filename = filename;
+ efile = new ERandomAccessFile(filename, "r"); //$NON-NLS-1$
+ String hdr = efile.readLine();
+ if (hdr == null || hdr.compareTo("!<arch>") != 0) { //$NON-NLS-1$
+ efile.close();
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.invalidArchive")); //$NON-NLS-1$
+ }
+ }
+
+ /** Load the headers from the file (if required). */
+ private void loadHeaders() throws IOException {
+ if (headers != null)
+ return;
+
+ Vector v = new Vector();
+ try {
+ //
+ // Check for EOF condition
+ //
+ while (efile.getFilePointer() < efile.length()) {
+ ARHeader header = new ARHeader();
+ String name = header.getObjectName();
+
+ long pos = efile.getFilePointer();
+
+ v.add(header);
+
+ //
+ // Compute the location of the next header in the archive.
+ //
+ pos += header.getSize();
+ if ((pos % 2) != 0)
+ pos++;
+
+ efile.seek(pos);
+ }
+ } catch (IOException e) {
+ }
+ // strtbl_pos = ???;
+ headers = (ARHeader[]) v.toArray(new ARHeader[0]);
+ }
+
+ /**
+ * Get an array of all the object file headers for this archive.
+ *
+ * @throws IOException
+ * Unable to process the archive file.
+ * @return An array of headers, one for each object within the archive.
+ * @see ARHeader
+ */
+ public ARHeader[] getHeaders() throws IOException {
+ loadHeaders();
+ return headers;
+ }
+
+ private boolean stringInStrings(String str, String[] set) {
+ for (int i = 0; i < set.length; i++)
+ if (str.compareTo(set[i]) == 0)
+ return true;
+ return false;
+ }
+
+ public String[] extractFiles(String outdir, String[] names) throws IOException {
+ Vector names_used = new Vector();
+ String object_name;
+ int count;
+
+ loadHeaders();
+
+ count = 0;
+ for (int i = 0; i < headers.length; i++) {
+ object_name = headers[i].getObjectName();
+ if (names != null && !stringInStrings(object_name, names))
+ continue;
+
+ object_name = "" + count + "_" + object_name; //$NON-NLS-1$ //$NON-NLS-2$
+ count++;
+
+ byte[] data = headers[i].getObjectData();
+ File output = new File(outdir, object_name);
+ names_used.add(object_name);
+
+ RandomAccessFile rfile = new RandomAccessFile(output, "rw"); //$NON-NLS-1$
+ rfile.write(data);
+ rfile.close();
+ }
+
+ return (String[]) names_used.toArray(new String[0]);
+ }
+
+ public String[] extractFiles(String outdir) throws IOException {
+ return extractFiles(outdir, null);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/ERandomAccessFile.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/ERandomAccessFile.java
new file mode 100644
index 00000000000..7d6eee5bc2f
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/ERandomAccessFile.java
@@ -0,0 +1,80 @@
+package org.eclipse.cdt.utils.macho;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+public class ERandomAccessFile extends RandomAccessFile {
+ private boolean isle;
+ private long ptr_offset;
+ int val[] = new int[4];
+
+ public ERandomAccessFile(String file, String mode) throws IOException {
+ super(file, mode);
+ }
+
+ public ERandomAccessFile(File file, String mode) throws IOException {
+ super(file, mode);
+ }
+
+ public void setEndian(boolean le)
+ {
+ isle = le;
+ }
+
+ public final short readShortE() throws IOException {
+ val[0] = read();
+ val[1] = read();
+ if ((val[0] | val[1]) < 0)
+ throw new EOFException();
+ if ( isle ) {
+ return (short)((val[1] << 8) + val[0]);
+ } else {
+ return (short)((val[0] << 8) + val[1]);
+ }
+ }
+
+ public final int readIntE() throws IOException
+ {
+ val[0] = read();
+ val[1] = read();
+ val[2] = read();
+ val[3] = read();
+ if ((val[0] | val[1] | val[2] | val[3]) < 0)
+ throw new EOFException();
+ if ( isle ) {
+ return ((val[3] << 24) + (val[2] << 16) + (val[1] << 8) + val[0]);
+ } else {
+ return ((val[0] << 24) + (val[1] << 16) + (val[2] << 8) + val[3]);
+ }
+ }
+
+ public final long readLongE() throws IOException
+ {
+ return (long)readIntE();
+ }
+
+ public void setFileOffset( long offset ) throws IOException {
+ ptr_offset = offset;
+ super.seek( offset );
+ }
+
+ public long getFilePointer() throws IOException {
+ long ptr = super.getFilePointer();
+ ptr = ptr - ptr_offset;
+ return ptr;
+ }
+
+ public void seek( long pos ) throws IOException {
+ long real_pos = pos + ptr_offset;
+ super.seek( real_pos );
+ }
+}
+
+
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachO.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachO.java
new file mode 100644
index 00000000000..ab1b869f654
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachO.java
@@ -0,0 +1,1561 @@
+package org.eclipse.cdt.utils.macho;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Vector;
+import java.util.Comparator;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.utils.CPPFilt;
+
+// test checkin
+public class MachO {
+ protected ERandomAccessFile efile;
+
+ protected MachOhdr mhdr;
+ protected LoadCommand[] loadcommands;
+ protected boolean cppFiltEnabled = true;
+ protected CPPFilt cppFilt;
+ protected String file;
+ protected boolean debugsym = false; /* contains debugging symbols */
+
+ private Symbol[] symbols; /* symbols from SymtabCommand */
+ private Symbol[] local_symbols; /* local symbols from DySymtabCommand */
+ private boolean dynsym = false; /* set if DynSymtabCommand is present */
+ private Line[] lines; /* line table */
+ private Section[] sections; /* sections from SegmentCommand */
+ private SymtabCommand symtab; /* SymtabCommand that contains the symbol table */
+
+ protected String EMPTY_STRING = ""; //$NON-NLS-1$
+
+
+ public class MachOhdr {
+
+ /* values of magic */
+ public final static int MH_MAGIC = 0xfeedface; /* the mach magic number */
+ public final static int MH_CIGAM = 0xcefaedfe;
+
+ /* values of cputype */
+ public final static int CPU_TYPE_ANY = -1;
+ public final static int CPU_TYPE_VAX = 1;
+ public final static int CPU_TYPE_MC680x0 = 6;
+ public final static int CPU_TYPE_I386 = 7;
+ public final static int CPU_TYPE_MC98000 = 10;
+ public final static int CPU_TYPE_HPPA = 11;
+ public final static int CPU_TYPE_MC88000 = 13;
+ public final static int CPU_TYPE_SPARC = 14;
+ public final static int CPU_TYPE_I860 = 15;
+ public final static int CPU_TYPE_POWERPC = 18;
+
+ /* values of cpusubtype */
+ public final static int CPU_SUBTYPE_MULTIPLE = -1;
+ public final static int CPU_SUBTYPE_LITTLE_ENDIAN = 0;
+ public final static int CPU_SUBTYPE_BIG_ENDIAN = 1;
+ public final static int CPU_SUBTYPE_VAX_ALL = 0;
+ public final static int CPU_SUBTYPE_VAX780 = 1;
+ public final static int CPU_SUBTYPE_VAX785 = 2;
+ public final static int CPU_SUBTYPE_VAX750 = 3;
+ public final static int CPU_SUBTYPE_VAX730 = 4;
+ public final static int CPU_SUBTYPE_UVAXI = 5;
+ public final static int CPU_SUBTYPE_UVAXII = 6;
+ public final static int CPU_SUBTYPE_VAX8200 = 7;
+ public final static int CPU_SUBTYPE_VAX8500 = 8;
+ public final static int CPU_SUBTYPE_VAX8600 = 9;
+ public final static int CPU_SUBTYPE_VAX8650 = 10;
+ public final static int CPU_SUBTYPE_VAX8800 = 11;
+ public final static int CPU_SUBTYPE_UVAXIII = 12;
+ public final static int CPU_SUBTYPE_MC680x0_ALL = 1;
+ public final static int CPU_SUBTYPE_MC68030 = 1;
+ public final static int CPU_SUBTYPE_MC68040 = 2;
+ public final static int CPU_SUBTYPE_MC68030_ONLY = 3;
+ public final static int CPU_SUBTYPE_I386_ALL = 3;
+ public final static int CPU_SUBTYPE_386 = 3;
+ public final static int CPU_SUBTYPE_486 = 4;
+ public final static int CPU_SUBTYPE_486SX = 132;
+ public final static int CPU_SUBTYPE_586 = 5;
+ public final static int CPU_SUBTYPE_PENT = 5;
+ public final static int CPU_SUBTYPE_PENTPRO = 32;
+ public final static int CPU_SUBTYPE_PENTII_M3 = 54;
+ public final static int CPU_SUBTYPE_PENTII_M5 = 86;
+ 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_R2600 = 2;
+ public final static int CPU_SUBTYPE_MIPS_R2800 = 3;
+ public final static int CPU_SUBTYPE_MIPS_R2000a = 4;
+ public final static int CPU_SUBTYPE_MIPS_R2000 = 5;
+ public final static int CPU_SUBTYPE_MIPS_R3000a = 6;
+ public final static int CPU_SUBTYPE_MIPS_R3000 = 7;
+ public final static int CPU_SUBTYPE_MC98000_ALL = 0;
+ public final static int CPU_SUBTYPE_MC98601 = 1;
+ public final static int CPU_SUBTYPE_HPPA_ALL = 0;
+ public final static int CPU_SUBTYPE_HPPA_7100 = 0;
+ public final static int CPU_SUBTYPE_HPPA_7100LC = 1;
+ public final static int CPU_SUBTYPE_MC88000_ALL = 0;
+ public final static int CPU_SUBTYPE_MC88100 = 1;
+ public final static int CPU_SUBTYPE_MC88110 = 2;
+ public final static int CPU_SUBTYPE_SPARC_ALL = 0;
+ public final static int CPU_SUBTYPE_I860_ALL = 0;
+ public final static int CPU_SUBTYPE_I860_860 = 1;
+ public final static int CPU_SUBTYPE_POWERPC_ALL = 0;
+ public final static int CPU_SUBTYPE_POWERPC_601 = 1;
+ public final static int CPU_SUBTYPE_POWERPC_602 = 2;
+ public final static int CPU_SUBTYPE_POWERPC_603 = 3;
+ public final static int CPU_SUBTYPE_POWERPC_603e = 4;
+ public final static int CPU_SUBTYPE_POWERPC_603ev = 5;
+ public final static int CPU_SUBTYPE_POWERPC_604 = 6;
+ public final static int CPU_SUBTYPE_POWERPC_604e = 7;
+ public final static int CPU_SUBTYPE_POWERPC_620 = 8;
+ public final static int CPU_SUBTYPE_POWERPC_750 = 9;
+ public final static int CPU_SUBTYPE_POWERPC_7400 = 10;
+ public final static int CPU_SUBTYPE_POWERPC_7450 = 11;
+ public final static int CPU_SUBTYPE_POWERPC_970 = 100;
+
+ /* values of filetype */
+ public final static int MH_OBJECT = 0x1; /* relocatable object file */
+ public final static int MH_EXECUTE = 0x2; /* demand paged executable file */
+ public final static int MH_FVMLIB = 0x3; /* fixed VM shared library file */
+ public final static int MH_CORE = 0x4; /* core file */
+ public final static int MH_PRELOAD = 0x5; /* preloaded executable file */
+ public final static int MH_DYLIB = 0x6; /* dynamically bound shared library */
+ 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_DYLIB_STUB = 0x9; /* shared library stub for static linking only, no section contents */
+
+ /* values of flags */
+ public final static int MH_NOUNDEFS = 0x1; /* the object file has no undefined references */
+ public final static int MH_INCRLINK = 0x2; /* the object file is the output of an incremental link against a base file and can't be link edited again */
+ public final static int MH_DYLDLINK = 0x4; /* the object file is input for the dynamic linker and can't be staticly link edited again */
+ public final static int MH_BINDATLOAD = 0x8; /* the object file's undefined references are bound by the dynamic linker when loaded. */
+ public final static int MH_PREBOUND = 0x10; /* the file has its dynamic undefined references prebound. */
+ public final static int MH_SPLIT_SEGS = 0x20; /* the file has its read-only and read-write segments split */
+ public final static int MH_LAZY_INIT = 0x40; /* the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) */
+ public final static int MH_TWOLEVEL = 0x80; /* the image is using two-level 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_NOFIXPREBINDING = 0x400; /* do not have dyld notify the prebinding agent about this executable */
+
+ public int magic; /* mach magic number identifier */
+ public int cputype; /* cpu specifier */
+ public int cpusubtype; /* machine specifier */
+ public int filetype; /* type of file */
+ public int ncmds; /* number of load commands */
+ public int sizeofcmds; /* the size of all the load commands */
+ public int flags; /* flags */
+
+ protected MachOhdr() throws IOException {
+ efile.seek(0);
+ efile.setEndian(false);
+ magic = efile.readIntE();
+ if ( magic == MH_CIGAM )
+ efile.setEndian(true);
+ else if ( magic != MH_MAGIC )
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
+ cputype = efile.readIntE();
+ cpusubtype = efile.readIntE();
+ filetype = efile.readIntE();
+ ncmds = efile.readIntE();
+ sizeofcmds = efile.readIntE();
+ flags = efile.readIntE();
+ }
+
+ protected MachOhdr(byte [] bytes) throws IOException {
+ boolean isle = false;
+ int offset = 0;
+ magic = makeInt(bytes, offset, isle); offset += 4;
+ if ( magic == MH_CIGAM )
+ isle = true;
+ else if ( magic != MH_MAGIC )
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.notMACHO")); //$NON-NLS-1$
+ cputype = makeInt(bytes, offset, isle); offset += 4;
+ cpusubtype = makeInt(bytes, offset, isle); offset += 4;
+ filetype = makeInt(bytes, offset, isle); offset += 4;
+ ncmds = makeInt(bytes, offset, isle); offset += 4;
+ sizeofcmds = makeInt(bytes, offset, isle); offset += 4;
+ flags = makeInt(bytes, offset, isle); offset += 4;
+ }
+
+ private final short makeShort(byte [] val, int offset, boolean isle) throws IOException {
+ if (val.length < offset + 2)
+ throw new IOException();
+ if ( isle ) {
+ return (short)(((val[offset + 1] & 0xff) << 8) + (val[offset + 0] & 0xff));
+ } else {
+ return (short)(((val[offset + 0] & 0xff) << 8) + (val[offset + 1] & 0xff));
+ }
+ }
+
+ private final int makeInt(byte [] val, int offset, boolean isle) throws IOException
+ {
+ if (val.length < offset + 4)
+ throw new IOException();
+ if ( isle ) {
+ return (((val[offset + 3] & 0xff) << 24) |
+ ((val[offset + 2] & 0xff) << 16) |
+ ((val[offset + 1] & 0xff) << 8) |
+ (val[offset + 0] & 0xff));
+ } else {
+ return (int)(((val[offset + 0] & 0xff) << 24) |
+ ((val[offset + 1] & 0xff) << 16) |
+ ((val[offset + 2] & 0xff) << 8) |
+ (val[offset + 3] & 0xff));
+ }
+ }
+
+ }
+
+ public class LoadCommand {
+ public final static int LC_REQ_DYLD = 0x80000000;
+
+ /* values of cmd */
+ public final static int LC_SEGMENT = 0x1; /* segment of this file to be mapped */
+ public final static int LC_SYMTAB = 0x2; /* link-edit stab symbol table info */
+ public final static int LC_SYMSEG = 0x3; /* link-edit gdb symbol table info (obsolete) */
+ public final static int LC_THREAD = 0x4; /* thread */
+ public final static int LC_UNIXTHREAD = 0x5; /* unix thread (includes a stack) */
+ public final static int LC_LOADFVMLIB = 0x6; /* load a specified fixed VM shared library */
+ public final static int LC_IDFVMLIB = 0x7; /* fixed VM shared library identification */
+ public final static int LC_IDENT = 0x8; /* object identification info (obsolete) */
+ public final static int LC_FVMFILE = 0x9; /* fixed VM file inclusion (internal use) */
+ public final static int LC_PREPAGE = 0xa; /* prepage command (internal use) */
+ public final static int LC_DYSYMTAB = 0xb; /* dynamic link-edit symbol table info */
+ public final static int LC_LOAD_DYLIB = 0xc; /* load a dynamically linked shared library */
+ public final static int LC_ID_DYLIB = 0xd; /* dynamically linked shared lib ident */
+ public final static int LC_LOAD_DYLINKER = 0xe; /* load a dynamic linker */
+ public final static int LC_ID_DYLINKER = 0xf; /* dynamic linker identification */
+ public final static int LC_PREBOUND_DYLIB = 0x10; /* modules prebound for a dynamically linked shared library */
+ public final static int LC_ROUTINES = 0x11; /* image routines */
+ public final static int LC_SUB_FRAMEWORK = 0x12; /* sub framework */
+ public final static int LC_SUB_UMBRELLA = 0x13; /* sub umbrella */
+ public final static int LC_SUB_CLIENT = 0x14; /* sub client */
+ 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_PREBIND_CKSUM = 0x17; /* prebind checksum */
+ /*
+ * load a dynamically linked shared library that is allowed to be missing
+ * (all symbols are weak imported).
+ */
+ public final static int LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD);
+
+ public int cmd;
+ public int cmdsize;
+ }
+
+ public class LCStr {
+ public long offset;
+ public long ptr;
+ }
+
+ public class SegmentCommand extends LoadCommand {
+ /* values of flags */
+ public final static long SG_HIGHVM = 0x1;
+ public final static long SG_FVMLIB = 0x2;
+ public final static long SG_NORELOC = 0x4;
+
+ /* VM protection values */
+ public final static int VM_PROT_NONE = 0x00;
+ public final static int VM_PROT_READ = 0x01; /* read permission */
+ public final static int VM_PROT_WRITE = 0x02; /* write permission */
+ public final static int VM_PROT_EXECUTE = 0x04; /* execute permission */
+ public final static int VM_PROT_DEFAULT = (VM_PROT_READ|VM_PROT_WRITE);
+ public final static int VM_PROT_ALL = (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+ public final static int VM_PROT_NO_CHANGE = 0x08;
+ public final static int VM_PROT_COPY = 0x10;
+ public final static int VM_PROT_WANTS_COPY = 0x10;
+
+ public String segname; /* segment name */
+ public int vmaddr; /* memory address of this segment */
+ public int vmsize; /* memory size of this segment */
+ public int fileoff; /* file offset of this segment */
+ public int filesize; /* amount to map from the file */
+ public int maxprot; /* maximum VM protection */
+ public int initprot; /* initial VM protection */
+ public int nsects; /* number of sections in segment */
+ public int flags; /* flags */
+
+ public boolean prot(int val) {
+ return (initprot & val) == val;
+ }
+ }
+
+ public class Section {
+
+ public final static int SECTION_TYP = 0x000000ff; /* 256 section types */
+ public final static int SECTION_ATTRIBUTES = 0xffffff00; /* 24 section attributes */
+ public final static int SECTION_ATTRIBUTES_USR =0xff000000; /* User setable attributes */
+
+ /* values of flags */
+ public final static int S_REGULAR = 0x0; /* regular section */
+ public final static int S_ZEROFILL = 0x1; /* zero fill on demand section */
+ public final static int S_CSTRING_LITERALS = 0x2; /* section with only literal C strings*/
+ public final static int S_4BYTE_LITERALS = 0x3; /* section with only 4 byte literals */
+ public final static int S_8BYTE_LITERALS = 0x4; /* section with only 8 byte literals */
+ public final static int S_LITERAL_POINTERS = 0x5; /* section with only pointers to literals */
+ public final static int S_NON_LAZY_SYMBOL_POINTERS = 0x6; /* section with only non-lazy symbol pointers */
+ public final static int S_LAZY_SYMBOL_POINTERS = 0x7; /* section with only lazy symbol pointers */
+ public final static int S_SYMBOL_STUBS = 0x8; /* section with only symbol stubs, byte size of stub in the reserved2 field */
+ public final static int S_MOD_INIT_FUNC_POINTERS = 0x9; /* section with only function pointers for initialization*/
+ public final static int S_MOD_TERM_FUNC_POINTERS = 0xa; /* section with only function pointers for termination */
+ public final static int S_COALESCED = 0xb; /* section contains symbols that are to be coalesced */
+ public final static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000; /* section contains only true machine instructions */
+ public final static int S_ATTR_NO_TOC = 0x40000000; /* section contains coalesced symbols that are not to be in a ranlib table of contents */
+ public final static int S_ATTR_STRIP_STATIC_SYMS = 0x20000000; /* ok to strip static symbols in this section in files with the MH_DYLDLINK flag */
+ public final static int SECTION_ATTRIBUTES_SYS = 0x00ffff00; /* system setable attributes */
+ public final static int S_ATTR_SOME_INSTRUCTIONS = 0x00000400; /* section contains some machine instructions */
+ public final static int S_ATTR_EXT_RELOC = 0x00000200; /* section has external relocation entries */
+ public final static int S_ATTR_LOC_RELOC = 0x00000100; /* section has local relocation entries */
+
+ public String sectname; /* name of this section */
+ public String segname; /* name segment this section goes in */
+ public SegmentCommand segment; /* segment this section goes in */
+ public int addr; /* memory address of this section */
+ public int size; /* size in bytes of this section */
+ public int offset; /* file offset of this section */
+ public int align; /* section alignment (power of 2) */
+ public int reloff; /* file offset of relocation entries */
+ public int nreloc; /* number of relocation entries */
+ public int flags; /* flags (section type and attributes)*/
+ public int reserved1; /* reserved */
+ public int reserved2; /* reserved */
+
+ public int flags(int mask) {
+ return flags & mask;
+ }
+ }
+
+ public class FVMLib {
+ public int name; /* library's target pathname */
+ public int minor_version; /* library's minor version number */
+ public int header_addr; /* library's header address */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class FVMLibCommand extends LoadCommand {
+ public FVMLib fvmlib; /* the library identification */
+ }
+
+ public class DyLib {
+ public int name; /* library's path name */
+ public int timestamp; /* library's build time stamp */
+ public int current_version; /* library's current version number */
+ public int compatibility_version; /* library's compatibility vers number*/
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class DyLibCommand extends LoadCommand {
+ public DyLib dylib; /* the library identification */
+ }
+
+ public class SubFrameworkCommand extends LoadCommand {
+ public int umbrella; /* the umbrella framework name */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class SubClientCommand extends LoadCommand {
+ public int client; /* the client name */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class SubUmbrellaCommand extends LoadCommand {
+ public int sub_umbrella; /* the sub_umbrella framework name */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class SubLibraryCommand extends LoadCommand {
+ public int sub_library; /* the sub_library name */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class PreboundDyLibCommand extends LoadCommand {
+ public int name; /* library's path name */
+ public int nmodules; /* number of modules in library */
+ public int linked_modules; /* bit vector of linked modules */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class DyLinkerCommand extends LoadCommand {
+ public int name; /* dynamic linker's path name */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ public class ThreadCommand extends LoadCommand {
+ }
+
+ public class RoutinesCommand extends LoadCommand {
+ public int init_address; /* address of initialization routine */
+ public int init_module; /* index into the module table that the init routine is defined in */
+ public int reserved1;
+ public int reserved2;
+ public int reserved3;
+ public int reserved4;
+ public int reserved5;
+ public int reserved6;
+ }
+
+ public class SymtabCommand extends LoadCommand {
+ public int symoff; /* symbol table offset */
+ public int nsyms; /* number of symbol table entries */
+ public int stroff; /* string table offset */
+ public int strsize; /* string table size in bytes */
+ }
+
+ public class DySymtabCommand extends LoadCommand {
+ public int ilocalsym; /* index to local symbols */
+ public int nlocalsym; /* number of local symbols */
+ public int iextdefsym; /* index to externally defined symbols */
+ public int nextdefsym; /* number of externally defined symbols */
+ public int iundefsym; /* index to undefined symbols */
+ public int nundefsym; /* number of undefined symbols */
+ public int tocoff; /* file offset to table of contents */
+ public int ntoc; /* number of entries in table of contents */
+ public int modtaboff; /* file offset to module table */
+ public int nmodtab; /* number of module table entries */
+ public int extrefsymoff; /* offset to referenced symbol table */
+ public int nextrefsyms; /* number of referenced symbol table entries */
+ public int indirectsymoff; /* file offset to the indirect symbol table */
+ public int nindirectsyms; /* number of indirect symbol table entries */
+ public int extreloff; /* offset to external relocation entries */
+ public int nextrel; /* number of external relocation entries */
+ public int locreloff; /* offset to local relocation entries */
+ public int nlocrel; /* number of local relocation entries */
+ }
+
+ public class DyLibTableOfContents {
+ public final static int INDIRECT_SYMBOL_LOCAL = 0x80000000;
+ public final static int INDIRECT_SYMBOL_ABS = 0x40000000;
+ public int symbol_index; /* the defined external symbol (index into the symbol table) */
+ public int module_index; /* index into the module table this symbol is defined in */
+ }
+
+ public class DyLibModule {
+ public int module_name; /* the module name (index into string table) */
+ public int iextdefsym; /* index into externally defined symbols */
+ public int nextdefsym; /* number of externally defined symbols */
+ public int irefsym; /* index into reference symbol table */
+ public int nrefsym; /* number of reference symbol table entries */
+ public int ilocalsym; /* index into symbols for local symbols */
+ public int nlocalsym; /* number of local symbols */
+ public int iextrel; /* index into 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 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 int objc_module_info_size; /* for this module size of the (__OBJC,__module_info) section */
+ }
+
+ public class DyLibReference {
+ public int isym; /* index into the symbol table */
+ public int flags; /* flags to indicate the type of reference */
+ }
+
+ public class TwoLevelHintsCommand extends LoadCommand {
+ public int offset; /* offset to the hint table */
+ public int nhints; /* number of hints in the hint table */
+ public TwoLevelHint[] hints;
+ }
+
+ public class TwoLevelHint {
+ public int isub_image; /* index into the sub images */
+ public int itoc; /* index into the table of contents */
+ }
+
+ public class PrebindCksumCommand extends LoadCommand {
+ public int cksum; /* the check sum or zero */
+ }
+
+ public class SymSegCommand extends LoadCommand {
+ public int offset; /* symbol segment offset */
+ public int size; /* symbol segment size in bytes */
+ }
+
+ public class IdentCommand extends LoadCommand {
+ }
+
+ public class FVMFileCommand extends LoadCommand {
+ public int name; /* files pathname */
+ public int header_addr; /* files virtual address */
+ public String lc_str_name = null;
+
+ public String toString() {
+ if ( lc_str_name == null ) {
+ return EMPTY_STRING;
+ }
+ return lc_str_name;
+ }
+ }
+
+ private void commonSetup( String file, long offset, boolean filton )
+ throws IOException
+ {
+ this.cppFiltEnabled = filton;
+
+ try {
+ efile = new ERandomAccessFile(file, "r"); //$NON-NLS-1$
+ efile.setFileOffset( offset );
+ mhdr = new MachOhdr();
+ this.file = file;
+ } finally {
+ if ( mhdr == null ) {
+ dispose();
+ }
+ }
+ }
+
+ protected String string_from_macho_symtab(MachO.SymtabCommand symtab, int index) throws IOException {
+ StringBuffer str = new StringBuffer();
+ byte tmp;
+ if ( index > symtab.strsize ) {
+ return EMPTY_STRING;
+ }
+ efile.seek(symtab.stroff + index);
+ while( true ) {
+ tmp = efile.readByte();
+ if ( tmp == 0 )
+ break;
+ str.append((char)tmp);
+ }
+ return str.toString();
+ }
+
+ public class Symbol implements Comparable {
+ /* n_type bit masks */
+ public final static int N_STAB = 0xe0;
+ public final static int N_PEXT = 0x10;
+ public final static int N_EXT = 0x01;
+ public final static int N_TYPE = 0x0e; /* type mask */
+ /* Values of N_TYPE bits */
+ public final static int N_UNDF = 0x0;
+ public final static int N_ABS = 0x2;
+ public final static int N_SECT = 0xe;
+ public final static int N_PBUD = 0xc;
+ public final static int N_INDR = 0xa;
+ /* Values of n_type if N_STAB bits are set (stabs) */
+ public final static int N_GSYM = 0x20; /* global symbol: name,,NO_SECT,type,0 */
+ public final static int N_FNAME = 0x22; /* procedure name (f77 kludge): name,,NO_SECT,0,0 */
+ public final static int N_FUN = 0x24; /* procedure: name,,n_sect,linenumber,address */
+ public final static int N_STSYM = 0x26; /* static symbol: name,,n_sect,type,address */
+ public final static int N_LCSYM = 0x28; /* .lcomm symbol: name,,n_sect,type,address */
+ public final static int N_BNSYM = 0x2e; /* begin nsect sym: 0,,n_sect,0,address */
+ public final static int N_OPT = 0x3c; /* emitted with gcc2_compiled and in gcc source */
+ public final static int N_RSYM = 0x40; /* register sym: name,,NO_SECT,type,register */
+ public final static int N_SLINE = 0x44; /* src line: 0,,n_sect,linenumber,address */
+ public final static int N_ENSYM = 0x4e; /* end nsect sym: 0,,n_sect,0,address */
+ public final static int N_SSYM = 0x60; /* structure elt: name,,NO_SECT,type,struct_offset */
+ public final static int N_SO = 0x64; /* source file name: name,,n_sect,0,address */
+ public final static int N_LSYM = 0x80; /* local sym: name,,NO_SECT,type,offset */
+ public final static int N_BINCL = 0x82; /* include file beginning: name,,NO_SECT,0,sum */
+ public final static int N_SOL = 0x84; /* #included file name: name,,n_sect,0,address */
+ public final static int N_PARAMS = 0x86; /* compiler parameters: name,,NO_SECT,0,0 */
+ public final static int N_VERSION = 0x88; /* compiler version: name,,NO_SECT,0,0 */
+ public final static int N_OLEVEL = 0x8A; /* compiler -O level: name,,NO_SECT,0,0 */
+ public final static int N_PSYM = 0xa0; /* parameter: name,,NO_SECT,type,offset */
+ public final static int N_EINCL = 0xa2; /* include file end: name,,NO_SECT,0,0 */
+ public final static int N_ENTRY = 0xa4; /* alternate entry: name,,n_sect,linenumber,address */
+ public final static int N_LBRAC = 0xc0; /* left bracket: 0,,NO_SECT,nesting level,address */
+ public final static int N_EXCL = 0xc2; /* deleted include file: name,,NO_SECT,0,sum */
+ public final static int N_RBRAC = 0xe0; /* right bracket: 0,,NO_SECT,nesting level,address */
+ public final static int N_BCOMM = 0xe2; /* begin common: name,,NO_SECT,0,0 */
+ public final static int N_ECOMM = 0xe4; /* end common: name,,n_sect,0,0 */
+ public final static int N_ECOML = 0xe8; /* end common (local name): 0,,n_sect,0,address */
+ public final static int N_LENG = 0xfe; /* second stab entry with length information */
+ /* Values of n_sect */
+ public final static int NO_SECT = 0;
+ public final static int MAX_SECT = 255;
+ /* Values of n_desc */
+ public final static int REFERENCE_TYPE = 0xf; /* reference type mask */
+ public final static int REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0x0;
+ public final static int REFERENCE_FLAG_UNDEFINED_LAZY = 0x1;
+ public final static int REFERENCE_FLAG_DEFINED = 0x2;
+ public final static int REFERENCE_FLAG_PRIVATE_DEFINED = 0x3;
+ public final static int REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 0x4;
+ public final static int REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 0x5;
+ public final static int REFERENCED_DYNAMICALLY = 0x10;
+ public final static int N_DESC_DISCARDED = 0x20;
+ public final static int N_WEAK_REF = 0x40;
+ public final static int N_WEAK_DEF = 0x80;
+
+ public long n_strx;
+ public long n_value;
+ public short n_desc;
+ public byte n_type;
+ public byte n_sect;
+
+ private String name = null; /* symbol name */
+ private Line line = null; /* symbol line information */
+
+ private String cppFilt(String in) {
+ if (cppFiltEnabled) {
+ try {
+ if (in.indexOf("__") != -1 || in.indexOf("_._") != -1) { //$NON-NLS-1$ //$NON-NLS-2$
+ if (cppFilt == null) {
+ cppFilt = new CPPFilt();
+ }
+ return cppFilt.getFunction(in);
+ }
+ } catch (IOException e) {
+ return in;
+ }
+ }
+ return in;
+ }
+
+ public Symbol() {
+ }
+
+ public boolean n_type_mask(int mask) {
+ return (n_type & mask) != 0;
+ }
+
+ public boolean n_type(int val) {
+ return (n_type & N_TYPE) == val;
+ }
+
+ public boolean n_desc(int val) {
+ return (n_type & REFERENCE_TYPE) == val;
+ }
+
+ public int compareTo(Object obj) {
+ long thisVal = 0;
+ long anotherVal = 0;
+ if ( obj instanceof Symbol ) {
+ Symbol sym = (Symbol)obj;
+ thisVal = this.n_value;
+ anotherVal = sym.n_value;
+ } else if ( obj instanceof Long ) {
+ Long val = (Long)obj;
+ anotherVal = val.longValue();
+ thisVal = (long)this.n_value;
+ }
+ return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
+ }
+
+ public String toString() {
+ if (n_strx == 0 || symtab == null) {
+ return EMPTY_STRING;
+ }
+ if ( name == null ) {
+ try {
+ name = cppFilt(string_from_macho_symtab(symtab, (int)n_strx));
+ } catch (IOException e ) {
+ return EMPTY_STRING;
+ }
+ }
+ return name;
+ }
+
+ private Line getLine(long value) {
+ if (!debugsym) {
+ return null;
+ }
+ for (int l = 0; l < lines.length; l++) {
+ Line line = lines[l];
+ if (value <= line.address)
+ return line;
+ }
+ return null;
+ }
+
+ /**
+ * Returns line information in the form of filename:line
+ * and if the information is not available may return null
+ * _or_ may return ??:??
+ */
+ public String lineInfo() {
+ if (!debugsym) {
+ return null;
+ }
+ if (line == null) {
+ long value = n_value;
+ // We try to get the nearest match
+ // since the symbol may not exactly align with debug info.
+ // In C line number 0 is invalid, line starts at 1 for file, we use
+ // this for validation.
+ for (int i = 0; i <= 20; i += 4, value += i) {
+ Line l = getLine(value);
+ if (l != null && l.lineno != 0) {
+ line = l;
+ break; // bail out
+ }
+ }
+ }
+ if (line != null)
+ return Integer.toString(line.lineno);
+ return null;
+ }
+
+ public String lineInfo(long vma) {
+ Line l = getLine(vma);
+ if (l != null)
+ return Integer.toString(l.lineno);
+ return null;
+ }
+
+ /**
+ * If the function is available from the symbol information,
+ * this will return the function name. May return null if
+ * the function can't be determined.
+ */
+ public String getFunction() {
+ if (line == null) {
+ lineInfo();
+ }
+ if (line != null)
+ return line.function;
+ return null;
+ }
+
+ /**
+ * If the filename is available from the symbol information,
+ * this will return the base filename information. May
+ * return null if the filename can't be determined.
+ */
+ public String getFilename() {
+ if (line == null) {
+ lineInfo();
+ }
+ if (line != null)
+ return line.file;
+ return null;
+ }
+
+ /**
+ * Returns the line number of the function which is closest
+ * associated with the address if it is available.
+ * from the symbol information. If it is not available,
+ * then -1 is returned.
+ */
+ public int getFuncLineNumber() {
+ if ( line == null ) {
+ lineInfo();
+ }
+ if (line == null) {
+ return -1;
+ }
+ return line.lineno;
+ }
+
+ /**
+ * Returns the line number of the file if it is available
+ * from the symbol information. If it is not available,
+ * then -1 is returned.
+ */
+ public int getLineNumber(long vma) {
+ Line l = getLine(vma);
+ if (l == null)
+ return -1;
+ return l.lineno;
+ }
+ }
+
+ /**
+ * We have to implement a separate compararator since when we do the
+ * binary search down below we are using a Long and a Symbol object
+ * and the Long doesn't know how to compare against a Symbol so if
+ * we compare Symbol vs Long it is ok, but not if we do Long vs Symbol.
+ */
+ class SymbolComparator implements Comparator {
+ long val1, val2;
+ public int compare(Object o1, Object o2) {
+
+ if(o1 instanceof Long) {
+ val1 = ((Long)o1).longValue();
+ } else if(o1 instanceof Symbol) {
+ val1 = ((Symbol)o1).n_value;
+ } else {
+ return -1;
+ }
+
+ if(o2 instanceof Long) {
+ val2 = ((Long)o2).longValue();
+ } else if(o2 instanceof Symbol) {
+ val2 = ((Symbol)o2).n_value;
+ } else {
+ return -1;
+ }
+ return (val1 == val2) ? 0
+ : ((val1 < val2) ? -1 : 1);
+ }
+ }
+
+ /**
+ * Simple class to implement a line table
+ */
+ public class Line implements Comparable {
+ public long address;
+ public int lineno;
+ public String file;
+ public String function;
+
+ public int compareTo(Object obj) {
+ long thisVal = 0;
+ long anotherVal = 0;
+ if ( obj instanceof Line ) {
+ Line l = (Line)obj;
+ thisVal = this.address;
+ anotherVal = l.address;
+ } else if ( obj instanceof Long ) {
+ Long val = (Long)obj;
+ anotherVal = val.longValue();
+ thisVal = this.address;
+ }
+ return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
+ }
+
+ public boolean equals(Object obj) {
+ Line line = (Line)obj;
+ return (line.lineno == lineno && line.address == address);
+ }
+ }
+
+ //A hollow entry, to be used with caution in controlled situations
+ protected MachO () {
+ }
+
+ public MachO (String file, long offset) throws IOException {
+ commonSetup( file, offset, true );
+ }
+
+ public MachO (String file) throws IOException {
+ commonSetup( file, 0, true );
+ }
+
+ public MachO (String file, long offset, boolean filton) throws IOException {
+ commonSetup( file, offset, filton );
+ }
+
+ public MachO (String file, boolean filton) throws IOException {
+ commonSetup( file, 0, filton );
+ }
+
+ public boolean cppFilterEnabled() {
+ return cppFiltEnabled;
+ }
+
+ public void setCppFilter( boolean enabled ) {
+ cppFiltEnabled = enabled;
+ }
+
+ public MachOhdr getMachOhdr() throws IOException {
+ return mhdr;
+ }
+
+ public class Attribute {
+ public static final int MACHO_TYPE_OBJ = 1;
+ public static final int MACHO_TYPE_EXE = 2;
+ public static final int MACHO_TYPE_CORE = 3;
+ public static final int MACHO_TYPE_SHLIB = 4;
+
+ public static final int DEBUG_TYPE_NONE = 0;
+ public static final int DEBUG_TYPE_STABS = 1;
+ public static final int DEBUG_TYPE_DWARF = 2;
+
+ String cpu;
+ int type;
+ int debugType;
+ boolean bDebug;
+ boolean isle;
+
+ public String getCPU() {
+ return cpu;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public boolean hasDebug() {
+ return debugType != DEBUG_TYPE_NONE;
+ }
+
+ public int getDebugType() {
+ return debugType;
+ }
+
+ public boolean isLittleEndian() {
+ return isle;
+ }
+ }
+
+ public Attribute getAttributes() throws IOException {
+ Attribute attrib = new Attribute();
+
+ switch( mhdr.filetype ) {
+ case MachO.MachOhdr.MH_OBJECT:
+ attrib.type = Attribute.MACHO_TYPE_OBJ;
+ break;
+ case MachO.MachOhdr.MH_EXECUTE:
+ case MachO.MachOhdr.MH_PRELOAD:
+ case MachO.MachOhdr.MH_BUNDLE:
+ case MachO.MachOhdr.MH_DYLINKER:
+ attrib.type = Attribute.MACHO_TYPE_EXE;
+ break;
+ case MachO.MachOhdr.MH_CORE:
+ attrib.type = Attribute.MACHO_TYPE_CORE;
+ break;
+ case MachO.MachOhdr.MH_DYLIB:
+ case MachO.MachOhdr.MH_FVMLIB:
+ attrib.type = Attribute.MACHO_TYPE_SHLIB;
+ break;
+ }
+
+ switch (mhdr.cputype) {
+ case MachO.MachOhdr.CPU_TYPE_I386 :
+ attrib.cpu = "x86"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_POWERPC :
+ attrib.cpu = "ppc"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_VAX :
+ attrib.cpu = "vax"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_MC680x0 :
+ attrib.cpu = "m68k"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_MC98000 :
+ attrib.cpu = "98000"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_MC88000 :
+ attrib.cpu = "88000"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_HPPA :
+ attrib.cpu = "hp"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_SPARC:
+ attrib.cpu = "sparc"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_I860:
+ attrib.cpu = "i860"; //$NON-NLS-1$
+ break;
+ case MachO.MachOhdr.CPU_TYPE_ANY:
+ default:
+ attrib.cpu = "any"; //$NON-NLS-1$
+ }
+
+ switch (mhdr.magic) {
+ case MachO.MachOhdr.MH_CIGAM :
+ attrib.isle = true;
+ break;
+ case MachO.MachOhdr.MH_MAGIC :
+ attrib.isle = false;
+ break;
+ }
+
+ if (debugsym) {
+ attrib.debugType = Attribute.DEBUG_TYPE_STABS;
+ }
+
+ return attrib;
+ }
+
+ public static Attribute getAttributes(String file) throws IOException {
+ MachO macho = new MachO(file);
+ Attribute attrib = macho.getAttributes();
+ macho.dispose();
+ return attrib;
+ }
+
+ public static Attribute getAttributes(byte [] array) throws IOException {
+
+ MachO emptyMachO = new MachO();
+ emptyMachO.mhdr = emptyMachO.new MachOhdr(array);
+ //emptyMachO.sections = new MachO.Section[0];
+ Attribute attrib = emptyMachO.getAttributes();
+ emptyMachO.dispose();
+
+ return attrib;
+ }
+
+ public static boolean isMachOHeader(byte[] bytes) {
+ boolean isle = false;
+ int offset = 0;
+ int magic = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
+ return (magic == MachO.MachOhdr.MH_MAGIC || magic == MachO.MachOhdr.MH_CIGAM);
+ }
+
+ public void dispose() {
+ if (cppFilt != null) {
+ cppFilt.dispose();
+ }
+ try {
+ if (efile != null) {
+ efile.close();
+ efile = null;
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Make sure we do not leak the fds.
+ */
+ protected void finalize() throws Throwable {
+ try {
+ dispose();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void loadSymbolTable() throws IOException {
+ if (loadcommands == null) {
+ return;
+ }
+ DySymtabCommand dysymtab = null;
+ for (int c = 0; c < loadcommands.length; c++) {
+ switch (loadcommands[c].cmd) {
+ case LoadCommand.LC_SYMTAB:
+ symtab = (SymtabCommand)loadcommands[c];
+ efile.seek(symtab.symoff);
+ ArrayList symList = new ArrayList(symtab.nsyms);
+ for (int s = 0; s < symtab.nsyms; s++) {
+ Symbol symbol = new Symbol();
+ symbol.n_strx = efile.readIntE();
+ symbol.n_type = (byte)efile.readUnsignedByte();
+ symbol.n_sect = (byte)efile.readUnsignedByte();
+ symbol.n_desc = efile.readShortE();
+ symbol.n_value = efile.readIntE();
+ symList.add(symbol);
+ if ((symbol.n_type & Symbol.N_STAB) != 0) {
+ debugsym = true;
+ }
+ }
+ symbols = (Symbol[])symList.toArray(new Symbol[0]);
+ break;
+
+ case LoadCommand.LC_DYSYMTAB:
+ dysymtab = (DySymtabCommand)loadcommands[c];
+ break;
+ }
+ }
+ if (dysymtab != null) {
+ ArrayList symList = new ArrayList(dysymtab.nlocalsym);
+ for (int s = dysymtab.ilocalsym; s < dysymtab.nlocalsym; s++) {
+ symList.add(symbols[s]);
+ }
+ local_symbols = (Symbol[])symList.toArray(new Symbol[0]);
+ }
+ }
+
+ private void loadLineTable() {
+ if (symbols == null) {
+ return;
+ }
+ /* count number of source line entries */
+ int nlines = 0;
+ for (int s = 0; s < symbols.length; s++) {
+ if (symbols[s].n_type == Symbol.N_SLINE || symbols[s].n_type == Symbol.N_FUN) {
+ nlines++;
+ }
+ }
+ if (nlines == 0) {
+ return;
+ }
+
+ /* now create line table, sorted on address */
+ ArrayList lineList = new ArrayList(nlines);
+ for (int s = 0; s < symbols.length; s++) {
+ Symbol sym = symbols[s];
+ if (sym.n_type == Symbol.N_SLINE || sym.n_type == Symbol.N_FUN) {
+ Line lentry = new Line();
+ lentry.address = sym.n_value;
+ lentry.lineno = sym.n_desc;
+
+ int l = lineList.indexOf(lentry);
+ if (l >= 0)
+ lentry = (Line)lineList.get(l);
+ else
+ lineList.add(lentry);
+
+ if (sym.n_type == Symbol.N_FUN) {
+ String func = sym.toString();
+ if (func != null) {
+ int colon = func.indexOf(':');
+ if (colon > 0)
+ lentry.function = func.substring(0, colon);
+ else
+ lentry.function = func;
+ } else {
+ lentry.function = EMPTY_STRING;
+ }
+ }
+ }
+ }
+ lineList.trimToSize();
+ lines = (Line[])lineList.toArray(new Line[0]);
+ Arrays.sort(lines);
+
+ /* now check for file names */
+ for (int s = 0; s < symbols.length; s++) {
+ Symbol sym = symbols[s];
+ if (sym.n_type == Symbol.N_SO) {
+ for (int l = 0; l < lines.length; l++) {
+ if (sym.n_value <= lines[l].address) {
+ lines[l].file = sym.toString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ private Section[] getSections(SegmentCommand seg) throws IOException {
+ if ( seg.nsects == 0 ) {
+ return new Section[0];
+ }
+ Section[] sections = new Section[seg.nsects];
+ for ( int i = 0; i < seg.nsects; i++ ) {
+ Section section = new Section();
+ byte[] sectname = new byte[16];
+ byte[] segname = new byte[16];
+ efile.readFully(sectname);
+ section.sectname = new String(sectname, 0, 16);
+ efile.readFully(segname);
+ section.segment = seg;
+ section.segname = new String(segname, 0, 16);
+ section.addr = efile.readIntE();
+ section.size = efile.readIntE();
+ section.offset = efile.readIntE();
+ section.align = efile.readIntE();
+ section.reloff = efile.readIntE();
+ section.nreloc = efile.readIntE();
+ section.flags = efile.readIntE();
+ section.reserved1 = efile.readIntE();
+ section.reserved2 = efile.readIntE();
+ sections[i] = section;
+ }
+ return sections;
+ }
+
+ private TwoLevelHint[] getTwoLevelHints(int nhints) throws IOException {
+ if ( nhints == 0 ) {
+ return new TwoLevelHint[0];
+ }
+ TwoLevelHint[] tlhints = new TwoLevelHint[nhints];
+ for ( int i = 0; i < nhints; i++ ) {
+ int field = efile.readIntE();
+ tlhints[i] = new TwoLevelHint();
+ tlhints[i].isub_image = (field & 0xff000000) >> 24;
+ tlhints[i].itoc = field & 0x00ffffff;
+ }
+ return tlhints;
+ }
+
+ private String getLCStr(int len) throws IOException {
+ if (len == 0)
+ return EMPTY_STRING;
+ StringBuffer str = new StringBuffer();
+ for (; len > 0; len--) {
+ byte tmp = efile.readByte();
+ if (tmp == 0)
+ break;
+ str.append((char)tmp);
+ }
+ return str.toString();
+ }
+
+ private void loadLoadCommands() throws IOException {
+ if ( loadcommands == null ) {
+ if ( mhdr.ncmds == 0 ) {
+ loadcommands = new LoadCommand[0];
+ return;
+ }
+ loadcommands = new LoadCommand[mhdr.ncmds];
+ for ( int i = 0; i < mhdr.ncmds; i++ ) {
+ int cmd = efile.readIntE();
+ int len;
+ switch (cmd) {
+ case LoadCommand.LC_SEGMENT:
+ SegmentCommand seg = new SegmentCommand();
+ byte[] segname = new byte[16];
+ seg.cmd = cmd;
+ seg.cmdsize = efile.readIntE();
+ efile.readFully(segname);
+ seg.segname = new String(segname, 0, 16);
+ seg.vmaddr = efile.readIntE();
+ seg.vmsize = efile.readIntE();
+ seg.fileoff = efile.readIntE();
+ seg.filesize = efile.readIntE();
+ seg.maxprot = efile.readIntE();
+ seg.initprot = efile.readIntE();
+ seg.nsects = efile.readIntE();
+ seg.flags = efile.readIntE();
+ sections = getSections(seg);
+ loadcommands[i] = seg;
+ break;
+
+ case LoadCommand.LC_SYMTAB:
+ SymtabCommand stcmd = new SymtabCommand();
+ stcmd.cmd = cmd;
+ stcmd.cmdsize = efile.readIntE();
+ stcmd.symoff = efile.readIntE();
+ stcmd.nsyms = efile.readIntE();
+ stcmd.stroff = efile.readIntE();
+ stcmd.strsize = efile.readIntE();
+ loadcommands[i] = stcmd;
+ break;
+
+ case LoadCommand.LC_SYMSEG:
+ SymSegCommand sscmd = new SymSegCommand();
+ sscmd.cmd = cmd;
+ sscmd.cmdsize = efile.readIntE();
+ sscmd.offset = efile.readIntE();
+ sscmd.size = efile.readIntE();
+ loadcommands[i] = sscmd;
+ break;
+
+ case LoadCommand.LC_THREAD:
+ case LoadCommand.LC_UNIXTHREAD:
+ ThreadCommand thcmd = new ThreadCommand();
+ thcmd.cmd = cmd;
+ thcmd.cmdsize = efile.readIntE();
+ efile.skipBytes(thcmd.cmdsize - 8 /* sizeof(ThreadCommand) */);
+ loadcommands[i] = thcmd;
+ break;
+
+ case LoadCommand.LC_LOADFVMLIB:
+ case LoadCommand.LC_IDFVMLIB:
+ FVMLibCommand fvmcmd = new FVMLibCommand();
+ fvmcmd.cmd = cmd;
+ fvmcmd.cmdsize = efile.readIntE();
+ fvmcmd.fvmlib = new FVMLib();
+ fvmcmd.fvmlib.name = efile.readIntE();
+ fvmcmd.fvmlib.minor_version = efile.readIntE();
+ fvmcmd.fvmlib.header_addr = efile.readIntE();
+ len = fvmcmd.cmdsize - 20 /* sizeof FVMLibCommand */;
+ fvmcmd.fvmlib.lc_str_name = getLCStr(len);
+ len -= fvmcmd.fvmlib.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = fvmcmd;
+ break;
+
+ case LoadCommand.LC_IDENT:
+ IdentCommand icmd = new IdentCommand();
+ icmd.cmd = cmd;
+ icmd.cmdsize = efile.readIntE();
+ loadcommands[i] = icmd;
+ break;
+
+ case LoadCommand.LC_FVMFILE:
+ FVMFileCommand fcmd = new FVMFileCommand();
+ fcmd.cmd = cmd;
+ fcmd.cmdsize = efile.readIntE();
+ fcmd.name = efile.readIntE();
+ fcmd.header_addr = efile.readIntE();
+ len = fcmd.cmdsize - 16 /* sizeof FVMFileCommand */;
+ fcmd.lc_str_name = getLCStr(len);
+ len -= fcmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = fcmd;
+ break;
+
+ case LoadCommand.LC_DYSYMTAB:
+ DySymtabCommand dscmd = new DySymtabCommand();
+ dscmd.cmd = cmd;
+ dscmd.cmdsize = efile.readIntE();
+ dscmd.ilocalsym = efile.readIntE();
+ dscmd.nlocalsym = efile.readIntE();
+ dscmd.iextdefsym = efile.readIntE();
+ dscmd.nextdefsym = efile.readIntE();
+ dscmd.iundefsym = efile.readIntE();
+ dscmd.nundefsym = efile.readIntE();
+ dscmd.tocoff = efile.readIntE();
+ dscmd.ntoc = efile.readIntE();
+ dscmd.modtaboff = efile.readIntE();
+ dscmd.nmodtab = efile.readIntE();
+ dscmd.extrefsymoff = efile.readIntE();
+ dscmd.nextrefsyms = efile.readIntE();
+ dscmd.indirectsymoff = efile.readIntE();
+ dscmd.nindirectsyms = efile.readIntE();
+ dscmd.extreloff = efile.readIntE();
+ dscmd.nextrel = efile.readIntE();
+ dscmd.locreloff = efile.readIntE();
+ dscmd.nlocrel = efile.readIntE();
+ loadcommands[i] = dscmd;
+ dynsym = true;
+ break;
+
+ case LoadCommand.LC_LOAD_DYLIB:
+ case LoadCommand.LC_ID_DYLIB:
+ DyLibCommand dylcmd = new DyLibCommand();
+ dylcmd.cmd = cmd;
+ dylcmd.cmdsize = efile.readIntE();
+ dylcmd.dylib = new DyLib();
+ dylcmd.dylib.name = efile.readIntE();
+ dylcmd.dylib.timestamp = efile.readIntE();
+ dylcmd.dylib.current_version = efile.readIntE();
+ dylcmd.dylib.compatibility_version = efile.readIntE();
+ len = dylcmd.cmdsize - 24 /* sizeof DyLibCommand */;
+ dylcmd.dylib.lc_str_name = getLCStr(len);
+ len -= dylcmd.dylib.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = dylcmd;
+ break;
+
+ case LoadCommand.LC_LOAD_DYLINKER:
+ case LoadCommand.LC_ID_DYLINKER:
+ DyLinkerCommand dylkcmd = new DyLinkerCommand();
+ dylkcmd.cmd = cmd;
+ dylkcmd.cmdsize = efile.readIntE();
+ dylkcmd.name = efile.readIntE();
+ len = dylkcmd.cmdsize - 12 /* sizeof(DyLinkerCommand) */;
+ dylkcmd.lc_str_name = getLCStr(len);
+ len -= dylkcmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = dylkcmd;
+ break;
+
+ case LoadCommand.LC_PREBOUND_DYLIB:
+ PreboundDyLibCommand pbcmd = new PreboundDyLibCommand();
+ pbcmd.cmd = cmd;
+ pbcmd.cmdsize = efile.readIntE();
+ pbcmd.name = efile.readIntE();
+ pbcmd.nmodules = efile.readIntE();
+ pbcmd.linked_modules = efile.readIntE();
+ len = pbcmd.cmdsize - 20 /* sizeof(PreboundDyLibCommand) */;
+ pbcmd.lc_str_name = getLCStr(len);
+ len -= pbcmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = pbcmd;
+ break;
+
+ case LoadCommand.LC_ROUTINES:
+ RoutinesCommand rcmd = new RoutinesCommand();
+ rcmd.cmd = cmd;
+ rcmd.cmdsize = efile.readIntE();
+ rcmd.init_address = efile.readIntE();
+ rcmd.init_module = efile.readIntE();
+ rcmd.reserved1 = efile.readIntE();
+ rcmd.reserved2 = efile.readIntE();
+ rcmd.reserved3 = efile.readIntE();
+ rcmd.reserved4 = efile.readIntE();
+ rcmd.reserved5 = efile.readIntE();
+ rcmd.reserved6 = efile.readIntE();
+ loadcommands[i] = rcmd;
+ break;
+
+ case LoadCommand.LC_SUB_FRAMEWORK:
+ SubFrameworkCommand subfcmd = new SubFrameworkCommand();
+ subfcmd.cmd = cmd;
+ subfcmd.cmdsize = efile.readIntE();
+ subfcmd.umbrella = efile.readIntE();
+ len = subfcmd.cmdsize - 12 /* sizeof(SubFrameworkCommand) */ ;
+ subfcmd.lc_str_name = getLCStr(len);
+ len -= subfcmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = subfcmd;
+ break;
+
+ case LoadCommand.LC_SUB_UMBRELLA:
+ SubUmbrellaCommand subucmd = new SubUmbrellaCommand();
+ subucmd.cmd = cmd;
+ subucmd.cmdsize = efile.readIntE();
+ subucmd.sub_umbrella = efile.readIntE();
+ len = subucmd.cmdsize - 12 /* sizeof(SubUmbrellaCommand) */;
+ subucmd.lc_str_name = getLCStr(len);
+ len -= subucmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = subucmd;
+ break;
+
+ case LoadCommand.LC_SUB_CLIENT:
+ SubClientCommand subccmd = new SubClientCommand();
+ subccmd.cmd = cmd;
+ subccmd.cmdsize = efile.readIntE();
+ subccmd.client = efile.readIntE();
+ len = subccmd.cmdsize - 12 /* sizeof(SubClientCommand) */;
+ subccmd.lc_str_name = getLCStr(len);
+ len -= subccmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = subccmd;
+ break;
+
+ case LoadCommand.LC_SUB_LIBRARY:
+ SubLibraryCommand sublcmd = new SubLibraryCommand();
+ sublcmd.cmd = cmd;
+ sublcmd.cmdsize = efile.readIntE();
+ sublcmd.sub_library = efile.readIntE();
+ len = sublcmd.cmdsize - 12 /* sizeof(SubLibraryCommand) */;
+ sublcmd.lc_str_name = getLCStr(len);
+ len -= sublcmd.lc_str_name.length() + 1;
+ efile.skipBytes(len);
+ loadcommands[i] = sublcmd;
+ break;
+
+ case LoadCommand.LC_TWOLEVEL_HINTS:
+ TwoLevelHintsCommand tlhcmd = new TwoLevelHintsCommand();
+ tlhcmd.cmd = cmd;
+ tlhcmd.cmdsize = efile.readIntE();
+ tlhcmd.offset = efile.readIntE();
+ tlhcmd.nhints = efile.readIntE();
+ loadcommands[i] = tlhcmd;
+ break;
+
+ case LoadCommand.LC_PREBIND_CKSUM:
+ PrebindCksumCommand pbccmd = new PrebindCksumCommand();
+ pbccmd.cmd = cmd;
+ pbccmd.cmdsize = efile.readIntE();
+ pbccmd.cksum = efile.readIntE();
+ loadcommands[i] = pbccmd;
+ break;
+ }
+ }
+ }
+ }
+
+ public void loadBinary() throws IOException {
+ if ( loadcommands == null ) {
+ loadLoadCommands();
+ loadSymbolTable();
+ loadLineTable();
+ }
+ }
+
+ public Symbol[] getSymbols() {
+ return symbols;
+ }
+
+ public Symbol[] getDynamicSymbols() {
+ if (dynsym) {
+ return symbols;
+ }
+ return null;
+ }
+
+ public Symbol[] getSymtabSymbols() {
+ return symbols;
+ }
+
+ public Symbol[] getLocalSymbols() {
+ if (local_symbols == null) {
+ return symbols;
+ }
+ return local_symbols;
+ }
+
+ public Line[] getLineTable() {
+ return lines;
+ }
+
+ public Section[] getSections() {
+ return sections;
+ }
+
+ public DyLib[] getDyLibs(int type) {
+ Vector v = new Vector();
+
+ for (int i = 0; i < loadcommands.length; i++) {
+ if (loadcommands[i].cmd == type) {
+ DyLibCommand dl = (DyLibCommand)loadcommands[i];
+ v.add(dl.dylib);
+ }
+ }
+ return (DyLib[]) v.toArray(new DyLib[0]);
+ }
+
+ /* return the address of the function that address is in */
+ public Symbol getSymbol( long vma ) {
+ if ( symbols == null ) {
+ return null;
+ }
+
+ //@@@ If this works, move it to a single instance in this class.
+ SymbolComparator symbol_comparator = new SymbolComparator();
+
+ int ndx = Arrays.binarySearch(symbols, new Long(vma), symbol_comparator);
+ if ( ndx > 0 )
+ return symbols[ndx];
+ if ( ndx == -1 ) {
+ return null;
+ }
+ ndx = -ndx - 1;
+ return symbols[ndx-1];
+ }
+
+ public long swapInt( long val ) {
+ if ( mhdr.magic == MachOhdr.MH_CIGAM ) {
+ short tmp[] = new short[4];
+ tmp[0] = (short)(val & 0x00ff);
+ tmp[1] = (short)((val >> 8) & 0x00ff);
+ tmp[2] = (short)((val >> 16) & 0x00ff);
+ tmp[3] = (short)((val >> 24) & 0x00ff);
+ return (long)((tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3]);
+ }
+ return val;
+ }
+
+ public int swapShort( short val ) {
+ if ( mhdr.magic == MachOhdr.MH_CIGAM ) {
+ short tmp[] = new short[2];
+ tmp[0] = (short)(val & 0x00ff);
+ tmp[1] = (short)((val >> 8) & 0x00ff);
+ return (short)((tmp[0] << 8) + tmp[1]);
+ }
+ return val;
+ }
+
+ public String getFilename() {
+ return file;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachOHelper.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachOHelper.java
new file mode 100644
index 00000000000..8a33d32f13e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/MachOHelper.java
@@ -0,0 +1,315 @@
+package org.eclipse.cdt.utils.macho;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Vector;
+
+/**
+ * <code>MachOHelper</code> is a wrapper class for the <code>MachO</code> class
+ * to provide higher level API for sorting/searching the MachO data.
+ *
+ * @see MachO
+ */
+public class MachOHelper {
+
+ private MachO macho;
+ private MachO.MachOhdr hdr;
+ private MachO.Attribute attrib;
+ private MachO.Symbol[] dynsyms;
+ private MachO.Symbol[] symbols;
+ private MachO.Section[] sections;
+ private MachO.DyLib[] needed;
+ private MachO.DyLib[] sonames;
+
+ public void dispose() {
+ if (macho != null) {
+ macho.dispose();
+ macho = null;
+ }
+ }
+
+ public class Sizes {
+ public long text;
+ public long data;
+ public long bss;
+ public long total;
+ public Sizes(long t, long d, long b) {
+ text = t;
+ data = d;
+ bss = b;
+ total = text + data + bss;
+ }
+ }
+
+ private void loadBinary() throws IOException {
+ if (symbols == null) {
+ macho.loadBinary();
+ symbols = macho.getSymtabSymbols();
+ dynsyms = macho.getDynamicSymbols();
+ sections = macho.getSections();
+ needed = macho.getDyLibs(MachO.LoadCommand.LC_LOAD_DYLIB);
+ sonames = macho.getDyLibs(MachO.LoadCommand.LC_ID_DYLIB);
+
+ if (dynsyms == null)
+ dynsyms = symbols;
+ }
+ }
+
+ /** Common code used by all constructors */
+ private void commonSetup() throws IOException {
+ hdr = macho.getMachOhdr();
+ attrib = macho.getAttributes();
+ }
+
+ /**
+ * Create a new <code>MachOHelper</code> using an existing <code>MachO</code>
+ * object.
+ * @param macho An existing MachO object to wrap.
+ * @throws IOException Error processing the MachO file.
+ */
+ public MachOHelper(MachO macho) throws IOException {
+ this.macho = macho;
+ commonSetup();
+ }
+
+ /**
+ * Create a new <code>MachOHelper</code> based on the given filename.
+ *
+ * @param filename The file to use for creating a new MachO object.
+ * @throws IOException Error processing the MachO file.
+ * @see MachO#MachO( String )
+ */
+ public MachOHelper(String filename) throws IOException {
+ macho = new MachO(filename);
+ commonSetup();
+ }
+
+ public MachOHelper(String filename, boolean filton) throws IOException {
+ macho = new MachO(filename, filton);
+ commonSetup();
+ }
+
+ /** Give back the MachO object that this helper is wrapping */
+ public MachO getMachO() {
+ return macho;
+ }
+
+ public MachO.Symbol[] getExternalFunctions() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ MachO.Symbol sym = dynsyms[i];
+ if ((sym.n_type_mask(MachO.Symbol.N_PEXT)
+ || sym.n_type_mask(MachO.Symbol.N_EXT))
+ && sym.n_desc(MachO.Symbol.REFERENCE_FLAG_UNDEFINED_LAZY)) {
+ String name = sym.toString();
+ if (name != null && name.trim().length() > 0)
+ v.add(sym);
+ }
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ public MachO.Symbol[] getExternalObjects() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ MachO.Symbol sym = dynsyms[i];
+ if ((sym.n_type_mask(MachO.Symbol.N_PEXT)
+ || sym.n_type_mask(MachO.Symbol.N_EXT))
+ && sym.n_desc(MachO.Symbol.REFERENCE_FLAG_UNDEFINED_NON_LAZY)) {
+ String name = sym.toString();
+ if (name != null && name.trim().length() > 0)
+ v.add(sym);
+ }
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ public MachO.Symbol[] getUndefined() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ if (dynsyms[i].n_type(MachO.Symbol.N_UNDF))
+ v.add(dynsyms[i]);
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ /*
+ * TODO: I'm not sure if this are correct. Need to check
+ */
+ public MachO.Symbol[] getLocalFunctions() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ MachO.Symbol sym = dynsyms[i];
+ if ((!sym.n_type_mask(MachO.Symbol.N_PEXT)
+ && !sym.n_type_mask(MachO.Symbol.N_EXT))
+ && sym.n_desc(MachO.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)) {
+ String name = sym.toString();
+ if (name != null && name.trim().length() > 0)
+ v.add(sym);
+ }
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ /*
+ * TODO: I'm not sure if this are correct. Need to check
+ */
+ public MachO.Symbol[] getLocalObjects() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ MachO.Symbol sym = dynsyms[i];
+ if ((!sym.n_type_mask(MachO.Symbol.N_PEXT)
+ && !sym.n_type_mask(MachO.Symbol.N_EXT))
+ && sym.n_desc(MachO.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)) {
+ String name = sym.toString();
+ if (name != null && name.trim().length() > 0)
+ v.add(sym);
+ }
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ public MachO.Symbol[] getCommonObjects() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < dynsyms.length; i++) {
+ MachO.Symbol sym = dynsyms[i];
+ if (sym.n_type_mask(MachO.Symbol.N_EXT)
+ && sym.n_type(MachO.Symbol.N_UNDF)
+ && sym.n_value != 0) {
+ v.add(symbols[i]);
+ }
+ }
+
+ MachO.Symbol[] ret = (MachO.Symbol[]) v.toArray(new MachO.Symbol[0]);
+ Arrays.sort(ret, new SymbolSortCompare());
+ return ret;
+ }
+
+ public String[] getNeeded() throws IOException {
+ Vector v = new Vector();
+
+ loadBinary();
+
+ for (int i = 0; i < needed.length; i++) {
+ v.add(needed[i].toString());
+ }
+ return (String[]) v.toArray(new String[0]);
+ }
+
+ public String getSoname() throws IOException {
+ String soname = ""; //$NON-NLS-1$
+
+ loadBinary();
+
+ for (int i = 0; i < sonames.length; i++) {
+ soname = sonames[i].toString();
+ }
+ return soname;
+ }
+
+ private String getSubUsage(String full, String name) {
+ int start, end;
+ //boolean has_names = false;
+ //boolean has_languages = false;
+ start = 0;
+ end = 0;
+
+ for (int i = 0; i < full.length(); i++) {
+ if (full.charAt(i) == '%') {
+ if (full.charAt(i + 1) == '-') {
+ if (start == 0) {
+ int eol = full.indexOf('\n', i + 2);
+ String temp = full.substring(i + 2, eol);
+ if (temp.compareTo(name) == 0)
+ start = eol;
+
+ //has_names = true;
+ } else if (end == 0) {
+ end = i - 1;
+ }
+ }
+
+ //if( full.charAt( i+1 ) == '=' )
+ //has_languages = true;
+ }
+ }
+
+ if (end == 0)
+ end = full.length();
+
+ if (start == 0)
+ return full;
+
+ return full.substring(start, end);
+ }
+
+ public String getQnxUsage() throws IOException {
+ return new String(""); //$NON-NLS-1$
+ }
+
+ public Sizes getSizes() throws IOException {
+ long text, data, bss;
+
+ text = 0;
+ data = 0;
+ bss = 0;
+
+ loadBinary();
+
+ for (int i = 0; i < sections.length; i++) {
+ MachO.SegmentCommand seg = sections[i].segment;
+ if (sections[i].flags(MachO.Section.SECTION_TYP) != MachO.Section.S_ZEROFILL) {
+ if (seg.prot(MachO.SegmentCommand.VM_PROT_EXECUTE)) {
+ text += sections[i].size;
+ } else if (!seg.prot(MachO.SegmentCommand.VM_PROT_WRITE)) {
+ data += sections[i].size;
+ }
+ } else {
+ if (seg.prot(MachO.SegmentCommand.VM_PROT_WRITE)) {
+ bss += sections[i].size;
+ }
+ }
+ }
+
+ return new Sizes(text, data, bss);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/SymbolSortCompare.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/SymbolSortCompare.java
new file mode 100644
index 00000000000..c64a25ccdf6
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/SymbolSortCompare.java
@@ -0,0 +1,24 @@
+package org.eclipse.cdt.utils.macho;
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+import java.util.Comparator;
+
+public class SymbolSortCompare implements Comparator {
+ public int compare( Object o1, Object o2 ) {
+ String s1 = o1.toString().toLowerCase();
+ String s2 = o2.toString().toLowerCase();
+
+ while( s1.length() > 0 && s1.charAt( 0 ) == '_' )
+ s1 = s1.substring( 1 );
+
+ while( s2.length() > 0 && s2.charAt( 0 ) == '_' )
+ s2 = s2.substring( 1 );
+
+ return s1.compareTo( s2 );
+ }
+}
+
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/ARMember.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/ARMember.java
new file mode 100644
index 00000000000..910da6d567d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/ARMember.java
@@ -0,0 +1,83 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+***********************************************************************/
+package org.eclipse.cdt.utils.macho.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.utils.Addr2line;
+import org.eclipse.cdt.utils.CPPFilt;
+import org.eclipse.cdt.utils.Symbol;
+import org.eclipse.cdt.utils.macho.AR;
+import org.eclipse.cdt.utils.macho.MachO;
+import org.eclipse.cdt.utils.macho.MachOHelper;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * ARMember
+ */
+public class ARMember extends MachOBinaryObject {
+ AR.ARHeader header;
+
+ public ARMember(IBinaryParser parser, IPath p, AR.ARHeader h) throws IOException {
+ super(parser, p);
+ header = h;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getContents()
+ */
+ public InputStream getContents() {
+ InputStream stream = null;
+ if (path != null && header != null) {
+ try {
+ stream = new ByteArrayInputStream(header.getObjectData());
+ } catch (IOException e) {
+ }
+ }
+ if (stream == null) {
+ stream = super.getContents();
+ }
+ return stream;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
+ */
+ public String getName() {
+ if (header != null) {
+ return header.getObjectName();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ protected MachOHelper getMachOHelper() throws IOException {
+ if (header != null) {
+ return new MachOHelper(header.getMachO());
+ }
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.noFileAssociation")); //$NON-NLS-1$
+ }
+
+ protected void addSymbols(MachO.Symbol[] array, int type, Addr2line addr2line, CPPFilt cppfilt, List list) {
+ for (int i = 0; i < array.length; i++) {
+ Symbol sym = new Symbol(this);
+ sym.type = type;
+ sym.name = array[i].toString();
+ sym.addr = array[i].n_value;
+ list.add(sym);
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/BinaryArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/BinaryArchive.java
new file mode 100644
index 00000000000..a7b3e1e1710
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/BinaryArchive.java
@@ -0,0 +1,80 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+***********************************************************************/
+package org.eclipse.cdt.utils.macho.parser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
+import org.eclipse.cdt.utils.BinaryFile;
+import org.eclipse.cdt.utils.macho.AR;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ */
+public class BinaryArchive extends BinaryFile implements IBinaryArchive {
+
+ ArrayList children;
+
+ public BinaryArchive(IBinaryParser parser, IPath p) throws IOException {
+ super(parser, p);
+ new AR(p.toOSString()).dispose(); // check file type
+ children = new ArrayList(5);
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#getObjects()
+ */
+ public IBinaryObject[] getObjects() {
+ if (hasChanged()) {
+ children.clear();
+ AR ar = null;
+ try {
+ ar = new AR(getPath().toOSString());
+ AR.ARHeader[] headers = ar.getHeaders();
+ for (int i = 0; i < headers.length; i++) {
+ IBinaryObject bin = new ARMember(getBinaryParser(), getPath(), headers[i]);
+ children.add(bin);
+ }
+ } catch (IOException e) {
+ //e.printStackTrace();
+ }
+ if (ar != null) {
+ ar.dispose();
+ }
+ children.trimToSize();
+ }
+ return (IBinaryObject[]) children.toArray(new IBinaryObject[0]);
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
+ */
+ public int getType() {
+ return IBinaryFile.ARCHIVE;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#add(IBinaryObject[])
+ */
+ public void add(IBinaryObject[] objs) throws IOException {
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryArchive#delete(IBinaryObject[])
+ */
+ public void delete(IBinaryObject[] objs) throws IOException {
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOBinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOBinaryObject.java
new file mode 100644
index 00000000000..b26aba18d41
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOBinaryObject.java
@@ -0,0 +1,170 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+***********************************************************************/
+package org.eclipse.cdt.utils.macho.parser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
+import org.eclipse.cdt.core.IBinaryParser.ISymbol;
+import org.eclipse.cdt.utils.*;
+import org.eclipse.cdt.utils.BinaryObjectAdapter;
+import org.eclipse.cdt.utils.CPPFilt;
+import org.eclipse.cdt.utils.macho.MachO;
+import org.eclipse.cdt.utils.macho.MachOHelper;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/*
+ * MachOBinaryObject
+ */
+public class MachOBinaryObject extends BinaryObjectAdapter {
+
+ private BinaryObjectInfo info;
+ private ISymbol[] symbols;
+
+ public MachOBinaryObject(IBinaryParser parser, IPath path) {
+ super(parser, path);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getType()
+ */
+ public int getType() {
+ return IBinaryFile.OBJECT;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbols()
+ */
+ public ISymbol[] getSymbols() {
+ // Call the hasChanged first, to initialize the timestamp
+ if (hasChanged() || symbols == null) {
+ try {
+ loadAll();
+ } catch (IOException e) {
+ symbols = NO_SYMBOLS;
+ }
+ }
+ return symbols;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getBinaryObjectInfo()
+ */
+ protected BinaryObjectInfo getBinaryObjectInfo() {
+ // Call the hasChanged first, to initialize the timestamp
+ if (hasChanged() || info == null) {
+ try {
+ loadInfo();
+ } catch (IOException e) {
+ info = new BinaryObjectInfo();
+ }
+ }
+ return info;
+ }
+
+ protected MachOHelper getMachOHelper() throws IOException {
+ return new MachOHelper(getPath().toOSString());
+ }
+
+ protected void loadAll() throws IOException {
+ MachOHelper helper = null;
+ try {
+ helper = getMachOHelper();
+ loadInfo(helper);
+ loadSymbols(helper);
+ } finally {
+ if (helper != null) {
+ helper.dispose();
+ }
+ }
+ }
+
+ protected void loadInfo() throws IOException {
+ MachOHelper helper = null;
+ try {
+ helper = getMachOHelper();
+ loadInfo(helper);
+ } finally {
+ if (helper != null) {
+ helper.dispose();
+ }
+ }
+ }
+
+ protected void loadInfo(MachOHelper helper) throws IOException {
+ info = new BinaryObjectInfo();
+ info.needed = helper.getNeeded();
+ MachOHelper.Sizes sizes = helper.getSizes();
+ info.bss = sizes.bss;
+ info.data = sizes.data;
+ info.text = sizes.text;
+
+ info.soname = helper.getSoname();
+
+ MachO.Attribute attribute = helper.getMachO().getAttributes();
+ info.isLittleEndian = attribute.isLittleEndian();
+ info.hasDebug = attribute.hasDebug();
+ info.cpu = attribute.getCPU();
+ }
+
+ protected void loadSymbols(MachOHelper helper) throws IOException {
+ ArrayList list = new ArrayList();
+ // Hack should be remove when Elf is clean
+ helper.getMachO().setCppFilter(false);
+
+ CPPFilt cppfilt = getCPPFilt();
+
+ addSymbols(helper.getExternalFunctions(), ISymbol.FUNCTION, cppfilt, list);
+ addSymbols(helper.getLocalFunctions(), ISymbol.FUNCTION, cppfilt, list);
+ addSymbols(helper.getExternalObjects(), ISymbol.VARIABLE, cppfilt, list);
+ addSymbols(helper.getLocalObjects(), ISymbol.VARIABLE, cppfilt, list);
+ list.trimToSize();
+
+ if (cppfilt != null) {
+ cppfilt.dispose();
+ }
+
+ symbols = (ISymbol[])list.toArray(NO_SYMBOLS);
+ Arrays.sort(symbols);
+ list.clear();
+ }
+
+ protected void addSymbols(MachO.Symbol[] array, int type, CPPFilt cppfilt, List list) {
+ for (int i = 0; i < array.length; i++) {
+ Symbol sym = new Symbol(this);
+ sym.type = type;
+ sym.name = array[i].toString();
+ if (cppfilt != null) {
+ try {
+ sym.name = cppfilt.getFunction(sym.name);
+ } catch (IOException e1) {
+ cppfilt = null;
+ }
+ }
+ sym.addr = array[i].n_value;
+ sym.size = 0;
+ sym.filename = null;
+ sym.startLine = 0;
+ sym.endLine = sym.startLine;
+ String filename = array[i].getFilename();
+ sym.filename = (filename != null) ? new Path(filename) : null; //$NON-NLS-1$
+ sym.startLine = array[i].getLineNumber(sym.addr);
+ sym.endLine = array[i].getLineNumber(sym.addr + sym.size - 1);
+ list.add(sym);
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOParser.java
new file mode 100644
index 00000000000..e0710e11efb
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/macho/parser/MachOParser.java
@@ -0,0 +1,147 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003,2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+***********************************************************************/
+package org.eclipse.cdt.utils.macho.parser;
+
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.utils.ToolsProvider;
+import org.eclipse.cdt.utils.macho.AR;
+import org.eclipse.cdt.utils.macho.MachO;
+import org.eclipse.cdt.utils.macho.MachO.Attribute;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ */
+public class MachOParser extends ToolsProvider implements IBinaryParser {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath)
+ */
+ public IBinaryFile getBinary(IPath path) throws IOException {
+ return getBinary(null, path);
+ }
+
+
+ public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException {
+ if (path == null) {
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.nullPath")); //$NON-NLS-1$
+ }
+
+ IBinaryFile binary = null;
+ try {
+ MachO.Attribute attribute = null;
+ if (hints != null && hints.length > 0) {
+ try {
+ attribute = MachO.getAttributes(hints);
+ } catch (EOFException eof) {
+ // continue, the array was to small.
+ }
+ }
+
+ //Take a second run at it if the data array failed.
+ if(attribute == null) {
+ attribute = MachO.getAttributes(path.toOSString());
+ }
+
+ if (attribute != null) {
+ switch (attribute.getType()) {
+ case Attribute.MACHO_TYPE_EXE :
+ binary = createBinaryExecutable(path);
+ break;
+
+ case Attribute.MACHO_TYPE_SHLIB :
+ binary = createBinaryShared(path);
+ break;
+
+ case Attribute.MACHO_TYPE_OBJ :
+ binary = createBinaryObject(path);
+ break;
+
+ case Attribute.MACHO_TYPE_CORE :
+ binary = createBinaryCore(path);
+ break;
+ }
+ }
+ } catch (IOException e) {
+ binary = createBinaryArchive(path);
+ }
+ return binary;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.model.IBinaryParser#getFormat()
+ */
+ public String getFormat() {
+ return "MACHO"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath)
+ */
+ public boolean isBinary(byte[] array, IPath path) {
+ return MachO.isMachOHeader(array) || AR.isARHeader(array);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IBinaryParser#getBufferSize()
+ */
+ public int getHintBufferSize() {
+ return 128;
+ }
+
+ /**
+ * @param path
+ * @return
+ */
+ protected IBinaryArchive createBinaryArchive(IPath path) throws IOException {
+ return new BinaryArchive(this, path);
+ }
+
+ protected IBinaryObject createBinaryObject(IPath path) throws IOException {
+ return new MachOBinaryObject(this, path);
+ }
+
+ protected IBinaryExecutable createBinaryExecutable(IPath path) throws IOException {
+ return new MachOBinaryObject(this, path) {
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.utils.macho.parser.MachOBinaryObject#getType()
+ */
+ public int getType() {
+ return IBinaryFile.EXECUTABLE;
+ }
+ };
+ }
+
+ protected IBinaryShared createBinaryShared(IPath path) throws IOException {
+ return new MachOBinaryObject(this, path) {
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.utils.macho.parser.MachOBinaryObject#getType()
+ */
+ public int getType() {
+ return IBinaryFile.SHARED;
+ }
+ };
+ }
+
+ protected IBinaryObject createBinaryCore(IPath path) throws IOException {
+ return new MachOBinaryObject(this, path) {
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.utils.macho.parser.MachOBinaryObject#getType()
+ */
+ public int getType() {
+ return IBinaryFile.CORE;
+ }
+ };
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index 73d37a915b8..0a09461f250 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -703,6 +703,11 @@
parserID="org.eclipse.cdt.core.XCOFF32"
id="XcoffBinaryParserPage">
</parserPage>
+ <parserPage
+ class="org.eclipse.cdt.ui.dialogs.MachOBinaryParserPage"
+ parserID="org.eclipse.cdt.core.MachO"
+ id="MachOBinaryParserPage">
+ </parserPage>
</extension>
<extension
point="org.eclipse.ui.workingSets">
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/MachOBinaryParserPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/MachOBinaryParserPage.java
new file mode 100644
index 00000000000..b993af0e719
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/dialogs/MachOBinaryParserPage.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.ui.dialogs;
+
+import java.io.File;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.ICDescriptor;
+import org.eclipse.cdt.core.ICExtensionReference;
+import org.eclipse.cdt.internal.ui.CUIMessages;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ */
+public class MachOBinaryParserPage extends AbstractCOptionPage {
+
+ public final static String PREF_CPPFILT_PATH = CUIPlugin.PLUGIN_ID + ".cppfilt"; //$NON-NLS-1$
+
+ protected Text fCPPFiltCommandText;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performApply(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void performApply(IProgressMonitor monitor) throws CoreException {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+
+ String cppfilt = fCPPFiltCommandText.getText().trim();
+
+ monitor.beginTask(CUIMessages.getString("BinaryParserPage.task.savingAttributes"), 1); //$NON-NLS-1$
+ IProject proj = getContainer().getProject();
+ if (proj != null) {
+ String parserID = ""; //$NON-NLS-1$
+ ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(proj);
+ ICExtensionReference[] cext = cdesc.get(CCorePlugin.BINARY_PARSER_UNIQ_ID);
+ if (cext.length > 0) {
+ IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CUIPlugin.PLUGIN_ID, "BinaryParserPage"); //$NON-NLS-1$
+ IConfigurationElement[] infos = point.getConfigurationElements();
+ for (int i = 0; i < infos.length; i++) {
+ String id = infos[i].getAttribute("parserID"); //$NON-NLS-1$
+ String clazz = infos[i].getAttribute("class"); //$NON-NLS-1$
+ String ego = getRealBinaryParserPage().getClass().getName();
+ if (clazz != null && clazz.equals(ego)) {
+ parserID = id;
+ break;
+ }
+ }
+ for (int i = 0; i < cext.length; i++) {
+ if (cext[i].getID().equals(parserID)) {
+
+ String orig = cext[i].getExtensionData("c++filt"); //$NON-NLS-1$
+ if (orig == null || !orig.equals(cppfilt)) {
+ cext[i].setExtensionData("c++filt", cppfilt); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ } else {
+ Preferences store = getContainer().getPreferences();
+ if (store != null) {
+ store.setValue(PREF_CPPFILT_PATH, cppfilt);
+ }
+ }
+ }
+
+ /**
+ * If this class is inherited from then this method MUST be implemented
+ * in the derived class.
+ */
+ protected Object getRealBinaryParserPage() {
+ return this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performDefaults()
+ */
+ public void performDefaults() {
+ String addr2line = null;
+ String cppfilt = null;
+ IProject proj = getContainer().getProject();
+ Preferences store = getContainer().getPreferences();
+ if (store != null) {
+ if (proj != null) {
+ cppfilt = store.getString(PREF_CPPFILT_PATH);
+ } else {
+ cppfilt = store.getDefaultString(PREF_CPPFILT_PATH);
+ }
+ fCPPFiltCommandText.setText((cppfilt == null || cppfilt.length() == 0) ? "c++filt" : cppfilt); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ Group comp = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ comp.setText(CUIMessages.getString("BinaryParserBlock.binaryParserOptions")); //$NON-NLS-1$
+ comp.setLayout(new GridLayout(2, true));
+ comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ ((GridLayout) comp.getLayout()).makeColumnsEqualWidth = false;
+
+ Label label = ControlFactory.createLabel(comp, CUIMessages.getString("BinaryParserPage.label.addr2lineCommand")); //$NON-NLS-1$
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+
+ Button button = ControlFactory.createPushButton(comp, CUIMessages.getString("BinaryParserPage.label.browse")); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ //updateLaunchConfigurationDialog();
+ }
+
+ });
+
+ label = ControlFactory.createLabel(comp, CUIMessages.getString("BinaryParserPage.label.cppfiltCommand")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+
+ fCPPFiltCommandText = ControlFactory.createTextField(comp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fCPPFiltCommandText.setLayoutData(gd);
+ fCPPFiltCommandText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ //updateLaunchConfigurationDialog();
+ }
+ });
+ button = ControlFactory.createPushButton(comp, CUIMessages.getString("BinaryParserPage.label.browse")); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(SelectionEvent evt) {
+ handleCPPFiltButtonSelected();
+ //updateLaunchConfigurationDialog();
+ }
+
+ private void handleCPPFiltButtonSelected() {
+ FileDialog dialog = new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(CUIMessages.getString("BinaryParserPage.label.cppfiltCommand")); //$NON-NLS-1$
+ String command = fCPPFiltCommandText.getText().trim();
+ int lastSeparatorIndex = command.lastIndexOf(File.separator);
+ if (lastSeparatorIndex != -1) {
+ dialog.setFilterPath(command.substring(0, lastSeparatorIndex));
+ }
+ String res = dialog.open();
+ if (res == null) {
+ return;
+ }
+ fCPPFiltCommandText.setText(res);
+ }
+ });
+
+ setControl(comp);
+ initialziedValues();
+ }
+
+ private void initialziedValues() {
+ String cppfilt = null;
+ IProject proj = getContainer().getProject();
+ if (proj != null) {
+ try {
+ ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(proj);
+ ICExtensionReference[] cext = cdesc.get(CCorePlugin.BINARY_PARSER_UNIQ_ID);
+ if (cext.length > 0) {
+ cppfilt = cext[0].getExtensionData("c++filt"); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ }
+ } else {
+ Preferences store = getContainer().getPreferences();
+ if (store != null) {
+ cppfilt = store.getString(PREF_CPPFILT_PATH);
+ }
+ }
+ fCPPFiltCommandText.setText((cppfilt == null || cppfilt.length() == 0) ? "c++filt" : cppfilt); //$NON-NLS-1$
+ }
+
+}

Back to the top