diff --git a/makefile b/makefile index 67b4e7e738..85375afbd0 100755 --- a/makefile +++ b/makefile @@ -908,7 +908,9 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ranlib) $(@) $(bootimage-object) $(codeimage-object): $(bootimage-generator) - $(<) $(classpath-build) $(bootimage-object) $(codeimage-object) + $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ + -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ + -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ diff --git a/readme.txt b/readme.txt index 17bb8730aa..7ae4a46e62 100644 --- a/readme.txt +++ b/readme.txt @@ -554,8 +554,16 @@ systems with case-insensitive filesystems such as Windows and OS X) Step 6: Build the boot and code images. - $ ../build/linux-i386-bootimage/bootimage-generator stage2 \ - bootimage-bin.o codeimage-bin.o + $ ../build/linux-i386-bootimage/bootimage-generator + -cp stage2 \ + -bootimage bootimage-bin.o \ + -codeimage codeimage-bin.o + +Note that you can override the default names for the start and end +symbols in the boot/code image by also passing: + + -bootimage-symbols my_bootimage_start:my_bootimage_end \ + -codeimage-symbols my_codeimage_start:my_codeimage_end Step 7: Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 27f0e2aa8a..a58f6a6af5 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1285,7 +1285,9 @@ targetThunk(BootImage::Thunk t) void writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput, BootImage* image, uint8_t* code, const char* className, - const char* methodName, const char* methodSpec) + const char* methodName, const char* methodSpec, + const char* bootimageStart, const char* bootimageEnd, + const char* codeimageStart, const char* codeimageEnd) { Zone zone(t->m->system, t->m->heap, 64 * 1024); @@ -1658,14 +1660,14 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp // } SymbolInfo bootimageSymbols[] = { - SymbolInfo(0, "_binary_bootimage_bin_start"), - SymbolInfo(bootimageData.length, "_binary_bootimage_bin_end") + SymbolInfo(0, bootimageStart), + SymbolInfo(bootimageData.length, bootimageEnd) }; platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); - compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); - compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); + compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); @@ -1686,28 +1688,251 @@ writeBootImage(Thread* t, uintptr_t* arguments) const char* methodName = reinterpret_cast(arguments[5]); const char* methodSpec = reinterpret_cast(arguments[6]); + const char* bootimageStart = reinterpret_cast(arguments[7]); + const char* bootimageEnd = reinterpret_cast(arguments[8]); + const char* codeimageStart = reinterpret_cast(arguments[9]); + const char* codeimageEnd = reinterpret_cast(arguments[10]); + writeBootImage2 (t, bootimageOutput, codeOutput, image, code, className, methodName, - methodSpec); + methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd); return 1; } +class Arg; + +class ArgParser { +public: + Arg* first; + Arg** last; + + ArgParser(): + first(0), + last(&first) {} + + bool parse(int ac, const char** av); + void printUsage(const char* exe); +}; + +class Arg { +public: + Arg* next; + bool required; + const char* name; + const char* desc; + + const char* value; + + Arg(ArgParser& parser, bool required, const char* name, const char* desc): + next(0), + required(required), + name(name), + desc(desc), + value(0) + { + *parser.last = this; + parser.last = &next; + } +}; + +bool ArgParser::parse(int ac, const char** av) { + Arg* state = 0; + + for(int i = 1; i < ac; i++) { + if(state) { + if(state->value) { + fprintf(stderr, "duplicate parameter %s: '%s' and '%s'\n", state->name, state->value, av[i]); + return false; + } + state->value = av[i]; + state = 0; + } else { + if(av[i][0] != '-') { + fprintf(stderr, "expected -parameter\n"); + return false; + } + for(Arg* arg = first; arg; arg = arg->next) { + if(strcmp(arg->name, &av[i][1]) == 0) { + state = arg; + } + } + if(!state) { + fprintf(stderr, "unrecognized parameter %s\n", av[i]); + return false; + } + } + } + + if(state) { + fprintf(stderr, "expected argument after -%s\n", state->name); + return false; + } + + for(Arg* arg = first; arg; arg = arg->next) { + if(arg->required && !arg->value) { + fprintf(stderr, "expected value for %s\n", arg->name); + return false; + } + } + + return true; +} + +void ArgParser::printUsage(const char* exe) { + fprintf(stderr, "usage:\n%s \\\n", exe); + for(Arg* arg = first; arg; arg = arg->next) { + const char* lineEnd = arg->next ? " \\" : ""; + if(arg->required) { + fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } + } +} + +class Arguments { +public: + + const char* classpath; + + const char* bootimage; + const char* codeimage; + + char* entryClass; + char* entryMethod; + char* entrySpec; + + char* bootimageStart; + char* bootimageEnd; + + char* codeimageStart; + char* codeimageEnd; + + bool maybeSplit(const char* src, char*& destA, char*& destB) { + if(src) { + const char* split = strchr(src, ':'); + if(!split) { + return false; + } + + destA = strndup(src, split - src); + destB = strdup(split + 1); + } + return true; + } + + Arguments(int ac, const char** av): + entryClass(0), + entryMethod(0), + entrySpec(0), + bootimageStart(strdup("_binary_bootimage_bin_start")), + bootimageEnd(strdup("_binary_bootimage_bin_end")), + codeimageStart(strdup("_binary_codeimage_bin_start")), + codeimageEnd(strdup("_binary_codeimage_bin_end")) + { + ArgParser parser; + Arg classpath(parser, true, "cp", ""); + Arg bootimage(parser, true, "bootimage", ""); + Arg codeimage(parser, true, "codeimage", ""); + Arg entry(parser, false, "entry", "[.[]]"); + Arg bootimageSymbols(parser, false, "bootimage-symbols", ":"); + Arg codeimageSymbols(parser, false, "codeimage-symbols", ":"); + + if(!parser.parse(ac, av)) { + parser.printUsage(av[0]); + exit(1); + } + + this->classpath = classpath.value; + this->bootimage = bootimage.value; + this->codeimage = codeimage.value; + + if(entry.value) { + if(const char* entryClassEnd = strchr(entry.value, '.')) { + entryClass = strndup(entry.value, entryClassEnd - entry.value); + if(const char* entryMethodEnd = strchr(entryClassEnd, '(')) { + entryMethod = strndup(entryClassEnd + 1, entryMethodEnd - entryClassEnd - 1); + entrySpec = strdup(entryMethodEnd); + } else { + entryMethod = strdup(entryClassEnd + 1); + } + } else { + entryClass = strdup(entry.value); + } + } + + if(!maybeSplit(bootimageSymbols.value, bootimageStart, bootimageEnd) || + !maybeSplit(codeimageSymbols.value, codeimageStart, codeimageEnd)) + { + fprintf(stderr, "wrong format for symbols\n"); + parser.printUsage(av[0]); + exit(1); + } + + } + + ~Arguments() { + if(entryClass) { + free(entryClass); + } + if(entryMethod) { + free(entryMethod); + } + if(entrySpec) { + free(entrySpec); + } + if(bootimageStart) { + free(bootimageStart); + } + if(bootimageEnd) { + free(bootimageEnd); + } + if(codeimageStart) { + free(codeimageStart); + } + if(codeimageEnd) { + free(codeimageEnd); + } + } + + void dump() { + printf( + "classpath = %s\n" + "bootimage = %s\n" + "codeimage = %s\n" + "entryClass = %s\n" + "entryMethod = %s\n" + "entrySpec = %s\n" + "bootimageStart = %s\n" + "bootimageEnd = %s\n" + "codeimageStart = %s\n" + "codeimageEnd = %s\n", + classpath, + bootimage, + codeimage, + entryClass, + entryMethod, + entrySpec, + bootimageStart, + bootimageEnd, + codeimageStart, + codeimageEnd); + } +}; + } // namespace int main(int ac, const char** av) { - if (ac < 4 or ac > 7) { - fprintf(stderr, "usage: %s " - " [ [ []]]\n", av[0]); - return -1; - } + Arguments args(ac, av); + // args.dump(); System* s = makeSystem(0); Heap* h = makeHeap(s, HeapCapacity * 2); Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX); - Finder* f = makeFinder(s, h, av[1], 0); + Finder* f = makeFinder(s, h, args.classpath, 0); Processor* p = makeProcessor(s, h, false); // todo: currently, the compiler cannot compile code with jumps or @@ -1728,25 +1953,31 @@ main(int ac, const char** av) enter(t, Thread::ActiveState); enter(t, Thread::IdleState); - FileOutputStream bootimageOutput(av[2]); + FileOutputStream bootimageOutput(args.bootimage); if (!bootimageOutput.isValid()) { - fprintf(stderr, "unable to open %s\n", av[2]); + fprintf(stderr, "unable to open %s\n", args.bootimage); return -1; } - FileOutputStream codeOutput(av[3]); + FileOutputStream codeOutput(args.codeimage); if (!codeOutput.isValid()) { - fprintf(stderr, "unable to open %s\n", av[3]); + fprintf(stderr, "unable to open %s\n", args.codeimage); return -1; } - uintptr_t arguments[] = { reinterpret_cast(&bootimageOutput), - reinterpret_cast(&codeOutput), - reinterpret_cast(&image), - reinterpret_cast(code), - reinterpret_cast(ac > 4 ? av[4] : 0), - reinterpret_cast(ac > 5 ? av[5] : 0), - reinterpret_cast(ac > 6 ? av[6] : 0) }; + uintptr_t arguments[] = { + reinterpret_cast(&bootimageOutput), + reinterpret_cast(&codeOutput), + reinterpret_cast(&image), + reinterpret_cast(code), + reinterpret_cast(args.entryClass), + reinterpret_cast(args.entryMethod), + reinterpret_cast(args.entrySpec), + reinterpret_cast(args.bootimageStart), + reinterpret_cast(args.bootimageEnd), + reinterpret_cast(args.codeimageStart), + reinterpret_cast(args.codeimageEnd) + }; run(t, writeBootImage, arguments);