diff --git a/ChangeLog b/ChangeLog index bcde86a..a4d42ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Sun Sep 28 07:06:37 2008 Minero Aoki + + * net/loveruby/cflat/compiler/Compiler.java: implement -shared. + + * net/loveruby/cflat/compiler/Options.java: new option -shared. + + * net/loveruby/cflat/compiler/CodeGeneratorOptions.java: ditto. + + * net/loveruby/cflat/compiler/SourceFile.java: new method + #linkedFileName. + Sun Sep 28 05:07:30 2008 Minero Aoki * implement PIC generation. diff --git a/ToDo b/ToDo index bb83835..6432c2e 100644 --- a/ToDo +++ b/ToDo @@ -7,10 +7,9 @@ * Label -> Symbol * all Symbols should be got from objects * named/unnamed Label -* -shared * bin/cbc: resolve symbolic link * remove all FIXME -? -fPIE, -pie +* -fPIE, -pie == Done @@ -252,3 +251,4 @@ - -O (jump elimination) - useless label elimination - -fPIC (PIC generation) +- -shared diff --git a/net/loveruby/cflat/compiler/CodeGeneratorOptions.java b/net/loveruby/cflat/compiler/CodeGeneratorOptions.java index 87cae52..699b233 100644 --- a/net/loveruby/cflat/compiler/CodeGeneratorOptions.java +++ b/net/loveruby/cflat/compiler/CodeGeneratorOptions.java @@ -5,11 +5,13 @@ import java.util.*; class CodeGeneratorOptions { protected int optimizeLevel; protected boolean generatePIC; + protected boolean generatePIE; protected boolean verboseAsm; public CodeGeneratorOptions() { optimizeLevel = 0; generatePIC = false; + generatePIE = false; verboseAsm = false; } @@ -38,6 +40,10 @@ class CodeGeneratorOptions { return verboseAsm; } + public boolean isPositionIndependent() { + return generatePIC || generatePIE; + } + public void generatePIC() { this.generatePIC = true; } @@ -45,4 +51,12 @@ class CodeGeneratorOptions { public boolean isPICRequired() { return generatePIC; } + + public void generatePIE() { + this.generatePIE = true; + } + + public boolean isPIERequired() { + return generatePIE; + } } diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index 105b98a..56ec6f8 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -59,7 +59,12 @@ public class Compiler { compileFile(src, opts); } if (! opts.isLinkRequired()) System.exit(0); - generateExecutable(opts); + if (! opts.isGeneratingSharedLibrary()) { + generateExecutable(opts); + } + else { + generateSharedLibrary(opts); + } System.exit(0); } catch (CompileException ex) { @@ -201,15 +206,25 @@ public class Compiler { invoke(cmd, opts.isVerboseMode()); } + static final protected String DYNAMIC_LINKER = "/lib/ld-linux.so.2"; + static final protected String C_RUNTIME_INIT = "/usr/lib/crti.o"; + static final protected String C_RUNTIME_START = "/usr/lib/crt1.o"; + static final protected String C_RUNTIME_START_PIE = "/usr/lib/Scrt1.o"; + static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o"; + protected void generateExecutable(Options opts) throws IPCException { List cmd = new ArrayList(); cmd.add("ld"); - // FIXME: -dynamic-linker required only on dynamic linking cmd.add("-dynamic-linker"); - cmd.add("/lib/ld-linux.so.2"); + cmd.add(DYNAMIC_LINKER); + if (opts.isGeneratingPIE()) { + cmd.add("-pie"); + } if (! opts.noStartFiles()) { - cmd.add("/usr/lib/crt1.o"); - cmd.add("/usr/lib/crti.o"); + cmd.add(opts.isGeneratingPIE() + ? C_RUNTIME_START_PIE + : C_RUNTIME_START); + cmd.add(C_RUNTIME_INIT); } cmd.addAll(opts.ldArgs()); if (! opts.noDefaultLibs()) { @@ -217,13 +232,33 @@ public class Compiler { cmd.add("-lcbc"); } if (! opts.noStartFiles()) { - cmd.add("/usr/lib/crtn.o"); + cmd.add(C_RUNTIME_FINI); } cmd.add("-o"); cmd.add(opts.exeFileName()); invoke(cmd, opts.isVerboseMode()); } + protected void generateSharedLibrary(Options opts) throws IPCException { + List cmd = new ArrayList(); + cmd.add("ld"); + cmd.add("-shared"); + if (! opts.noStartFiles()) { + cmd.add(C_RUNTIME_INIT); + } + cmd.addAll(opts.ldArgs()); + if (! opts.noDefaultLibs()) { + cmd.add("-lc"); + cmd.add("-lcbc"); + } + if (! opts.noStartFiles()) { + cmd.add(C_RUNTIME_FINI); + } + cmd.add("-o"); + cmd.add(opts.soFileName()); + invoke(cmd, opts.isVerboseMode()); + } + protected void invoke(List cmdArgs, boolean debug) throws IPCException { if (debug) { dumpCommand(cmdArgs.iterator()); diff --git a/net/loveruby/cflat/compiler/Options.java b/net/loveruby/cflat/compiler/Options.java index cc59e44..f2b81c1 100644 --- a/net/loveruby/cflat/compiler/Options.java +++ b/net/loveruby/cflat/compiler/Options.java @@ -15,6 +15,8 @@ class Options { protected boolean debugParser; protected CodeGeneratorOptions genOptions; protected List asOptions; // List + protected boolean generatingSharedLibrary; + protected boolean generatingPIE; protected List ldArgs; // List protected boolean noStartFiles = false; protected boolean noDefaultLibs = false; @@ -24,6 +26,8 @@ class Options { this.loader = loader; this.genOptions = new CodeGeneratorOptions(); this.asOptions = new ArrayList(); + this.generatingSharedLibrary = false; + this.generatingPIE = false; this.ldArgs = new ArrayList(); } @@ -71,11 +75,18 @@ class Options { } public String exeFileName() { - if (outputFileName != null) return outputFileName; + return getOutputFileName(""); + } + + public String soFileName() { + return getOutputFileName(".so"); + } + + protected String getOutputFileName(String newExt) { List srcs = sourceFiles(); if (srcs.size() == 1) { SourceFile src = (SourceFile)srcs.get(0); - return src.exeFileName(this); + return src.linkedFileName(this, newExt); } else { return "a.out"; @@ -123,6 +134,10 @@ class Options { return this.asOptions; } + public boolean isGeneratingSharedLibrary() { + return this.generatingSharedLibrary; + } + // List public List ldArgs() { return this.ldArgs; @@ -171,15 +186,14 @@ class Options { else if (arg.startsWith("-o")) { outputFileName = getOptArg(arg, args); } - else if (arg.equals("-fpic")) { + else if (arg.equals("-fpic") + || arg.equals("-fPIC")) { genOptions.generatePIC(); } - else if (arg.equals("-fPIC")) { - genOptions.generatePIC(); + else if (arg.equals("-fpie") + || arg.equals("-fPIE")) { + genOptions.generatePIE(); } - // FIXME: PIE - //else if (arg.equals("-fpie")) - //else if (arg.equals("-fPIE")) else if (arg.startsWith("-O")) { String type = arg.substring(2); if (! type.matches("^([0123s]|)$")) { @@ -200,10 +214,11 @@ class Options { ldArgs.add(new LdOption(arg)); } else if (arg.equals("-shared")) { - // FIXME: ?? any more work is required?? - ldArgs.add(new LdOption(arg)); + generatingSharedLibrary = true; + } + else if (arg.equals("-pie")) { + generatingPIE = true; } - //else if (arg.equals("-pie")) else if (arg.startsWith("-L")) { ldArgs.add(new LdOption("-L" + getOptArg(arg, args))); } @@ -338,7 +353,7 @@ class Options { out.println(" -Os Equivalent to -O."); out.println(" -O0 Disables optimization (default)."); out.println(" -fPIC Generates PIC assembly."); - //out.println(" -fPIE Generates PIE assembly."); + out.println(" -fPIE Generates PIE assembly."); out.println(" --verbose-asm Generate assembly with verbose comments."); out.println(""); out.println("Assembler Options:"); @@ -350,7 +365,7 @@ class Options { out.println(" -L PATH Adds PATH as library directory."); out.println(" -shared Generates shared library rather than executable."); out.println(" -static Linkes only with static libraries."); - //out.println(" -pie Generates PIE."); + out.println(" -pie Generates PIE."); out.println(" -nostartfiles Do not link startup files."); out.println(" -nodefaultlibs Do not link default libraries."); out.println(" -nostdlib Enables -nostartfiles and -nodefaultlibs."); diff --git a/net/loveruby/cflat/compiler/SourceFile.java b/net/loveruby/cflat/compiler/SourceFile.java index 37a1a32..71aab33 100644 --- a/net/loveruby/cflat/compiler/SourceFile.java +++ b/net/loveruby/cflat/compiler/SourceFile.java @@ -59,8 +59,8 @@ class SourceFile implements LdArg { return or(opts.outputFileNameFor("-c"), replaceExt(".o")); } - public String exeFileName(Options opts) { - return or(opts.outputFileName, replaceExt("")); + public String linkedFileName(Options opts, String newExt) { + return or(opts.outputFileName, replaceExt(newExt)); } protected String or(String x, String y) {