allow passing bootimage / codeimage start and end symbol names to the bootimage-generator

The usage statement for the bootimage-generator now looks like this:
build/linux-x86_64-bootimage/bootimage-generator \
  -cp <classpath> \
  -bootimage <bootimage file> \
  -codeimage <codeimage file> \
  [-entry <class name>[.<method name>[<method spec>]]] \
  [-bootimage-symbols <start symbol name>:<end symbol name>] \
  [-codeimage-symbols <start symbol name>:<end symbol name>]
This commit is contained in:
Joshua Warner 2012-05-10 14:36:30 -06:00
parent 24061251cf
commit 3dcf886bbe
3 changed files with 267 additions and 26 deletions

View File

@ -908,7 +908,9 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \
$(ranlib) $(@) $(ranlib) $(@)
$(bootimage-object) $(codeimage-object): $(bootimage-generator) $(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) \ executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \

View File

@ -554,8 +554,16 @@ systems with case-insensitive filesystems such as Windows and OS X)
Step 6: Build the boot and code images. Step 6: Build the boot and code images.
$ ../build/linux-i386-bootimage/bootimage-generator stage2 \ $ ../build/linux-i386-bootimage/bootimage-generator
bootimage-bin.o codeimage-bin.o -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 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 method. Note the bootimageBin function, which will be called by the

View File

@ -1285,7 +1285,9 @@ targetThunk(BootImage::Thunk t)
void void
writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput, writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput,
BootImage* image, uint8_t* code, const char* className, 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); Zone zone(t->m->system, t->m->heap, 64 * 1024);
@ -1658,14 +1660,14 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
// } // }
SymbolInfo bootimageSymbols[] = { SymbolInfo bootimageSymbols[] = {
SymbolInfo(0, "_binary_bootimage_bin_start"), SymbolInfo(0, bootimageStart),
SymbolInfo(bootimageData.length, "_binary_bootimage_bin_end") SymbolInfo(bootimageData.length, bootimageEnd)
}; };
platform->writeObject(bootimageOutput, Slice<SymbolInfo>(bootimageSymbols, 2), Slice<const uint8_t>(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); platform->writeObject(bootimageOutput, Slice<SymbolInfo>(bootimageSymbols, 2), Slice<const uint8_t>(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord);
compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); compilationHandler.symbols.add(SymbolInfo(0, codeimageStart));
compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd));
platform->writeObject(codeOutput, Slice<SymbolInfo>(compilationHandler.symbols), Slice<const uint8_t>(code, image->codeSize), Platform::Executable, TargetBytesPerWord); platform->writeObject(codeOutput, Slice<SymbolInfo>(compilationHandler.symbols), Slice<const uint8_t>(code, image->codeSize), Platform::Executable, TargetBytesPerWord);
@ -1686,28 +1688,251 @@ writeBootImage(Thread* t, uintptr_t* arguments)
const char* methodName = reinterpret_cast<const char*>(arguments[5]); const char* methodName = reinterpret_cast<const char*>(arguments[5]);
const char* methodSpec = reinterpret_cast<const char*>(arguments[6]); const char* methodSpec = reinterpret_cast<const char*>(arguments[6]);
const char* bootimageStart = reinterpret_cast<const char*>(arguments[7]);
const char* bootimageEnd = reinterpret_cast<const char*>(arguments[8]);
const char* codeimageStart = reinterpret_cast<const char*>(arguments[9]);
const char* codeimageEnd = reinterpret_cast<const char*>(arguments[10]);
writeBootImage2 writeBootImage2
(t, bootimageOutput, codeOutput, image, code, className, methodName, (t, bootimageOutput, codeOutput, image, code, className, methodName,
methodSpec); methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd);
return 1; 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", "<classpath>");
Arg bootimage(parser, true, "bootimage", "<bootimage file>");
Arg codeimage(parser, true, "codeimage", "<codeimage file>");
Arg entry(parser, false, "entry", "<class name>[.<method name>[<method spec>]]");
Arg bootimageSymbols(parser, false, "bootimage-symbols", "<start symbol name>:<end symbol name>");
Arg codeimageSymbols(parser, false, "codeimage-symbols", "<start symbol name>:<end symbol name>");
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 } // namespace
int int
main(int ac, const char** av) main(int ac, const char** av)
{ {
if (ac < 4 or ac > 7) { Arguments args(ac, av);
fprintf(stderr, "usage: %s <classpath> <bootimage file> <code file>" // args.dump();
" [<class name> [<method name> [<method spec>]]]\n", av[0]);
return -1;
}
System* s = makeSystem(0); System* s = makeSystem(0);
Heap* h = makeHeap(s, HeapCapacity * 2); Heap* h = makeHeap(s, HeapCapacity * 2);
Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX); 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); Processor* p = makeProcessor(s, h, false);
// todo: currently, the compiler cannot compile code with jumps or // 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::ActiveState);
enter(t, Thread::IdleState); enter(t, Thread::IdleState);
FileOutputStream bootimageOutput(av[2]); FileOutputStream bootimageOutput(args.bootimage);
if (!bootimageOutput.isValid()) { if (!bootimageOutput.isValid()) {
fprintf(stderr, "unable to open %s\n", av[2]); fprintf(stderr, "unable to open %s\n", args.bootimage);
return -1; return -1;
} }
FileOutputStream codeOutput(av[3]); FileOutputStream codeOutput(args.codeimage);
if (!codeOutput.isValid()) { if (!codeOutput.isValid()) {
fprintf(stderr, "unable to open %s\n", av[3]); fprintf(stderr, "unable to open %s\n", args.codeimage);
return -1; return -1;
} }
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(&bootimageOutput), uintptr_t arguments[] = {
reinterpret_cast<uintptr_t>(&codeOutput), reinterpret_cast<uintptr_t>(&bootimageOutput),
reinterpret_cast<uintptr_t>(&image), reinterpret_cast<uintptr_t>(&codeOutput),
reinterpret_cast<uintptr_t>(code), reinterpret_cast<uintptr_t>(&image),
reinterpret_cast<uintptr_t>(ac > 4 ? av[4] : 0), reinterpret_cast<uintptr_t>(code),
reinterpret_cast<uintptr_t>(ac > 5 ? av[5] : 0), reinterpret_cast<uintptr_t>(args.entryClass),
reinterpret_cast<uintptr_t>(ac > 6 ? av[6] : 0) }; reinterpret_cast<uintptr_t>(args.entryMethod),
reinterpret_cast<uintptr_t>(args.entrySpec),
reinterpret_cast<uintptr_t>(args.bootimageStart),
reinterpret_cast<uintptr_t>(args.bootimageEnd),
reinterpret_cast<uintptr_t>(args.codeimageStart),
reinterpret_cast<uintptr_t>(args.codeimageEnd)
};
run(t, writeBootImage, arguments); run(t, writeBootImage, arguments);