support building Avian as a self-contained dynamic library

This commit is contained in:
Joel Dice 2008-03-30 21:43:43 -06:00
parent 91494d9081
commit 357bd29460
12 changed files with 186 additions and 93 deletions

View File

@ -56,7 +56,8 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self
common-cflags = $(warnings) -fno-rtti -fno-exceptions \
-I$(JAVA_HOME)/include -idirafter $(src) -I$(native-build) \
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\"
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
-DBOOT_CLASSPATH=\"[classpathJar]\"
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
-I$(JAVA_HOME)/include/linux -I$(src) -pthread
@ -65,7 +66,7 @@ cflags = $(build-cflags)
common-lflags = -lm -lz
lflags = $(common-lflags) -lpthread -ldl -rdynamic
lflags = $(common-lflags) -lpthread -ldl
system = posix
asm = x86
@ -74,6 +75,11 @@ object-arch = i386:x86-64
object-format = elf64-x86-64
pointer-size = 8
so-prefix = lib
so-suffix = .so
shared = -shared
ifeq ($(arch),i386)
object-arch = i386
object-format = elf32-i386
@ -86,6 +92,8 @@ ifeq ($(platform),darwin)
lflags = $(common-lflags) -ldl -framework CoreFoundation
strip-all = -S -x
binaryToMacho = $(native-build)/binaryToMacho
so-suffix = .jnilib
shared = -dynamiclib
endif
ifeq ($(platform),windows)
@ -95,6 +103,9 @@ ifeq ($(platform),windows)
system = windows
object-format = pe-i386
so-prefix =
so-suffix = .dll
cxx = i586-mingw32msvc-g++
cc = i586-mingw32msvc-gcc
dlltool = i586-mingw32msvc-dlltool
@ -181,9 +192,12 @@ vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(native-build))
vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(native-build))
vm-objects = $(vm-cpp-objects) $(vm-asm-objects)
driver-sources = $(src)/main.cpp
driver-source = $(src)/main.cpp
driver-object = $(native-build)/main.o
driver-dynamic-object = $(native-build)/main-dynamic.o
driver-object = $(call cpp-objects,$(driver-sources),$(src),$(native-build))
boot-source = $(src)/boot.cpp
boot-object = $(native-build)/boot.o
generator-headers = $(src)/constants.h
generator-sources = $(src)/type-generator.cpp
@ -191,8 +205,10 @@ generator-objects = \
$(call cpp-objects,$(generator-sources),$(src),$(native-build))
generator = $(native-build)/generator
libvm = $(native-build)/lib$(name).a
vm = $(native-build)/$(name)
static-library = $(native-build)/lib$(name).a
executable = $(native-build)/$(name)
dynamic-library = $(native-build)/$(so-prefix)$(name)$(so-suffix)
executable-dynamic = $(native-build)/$(name)-dynamic
classpath-sources = $(shell find $(classpath) -name '*.java')
classpath-classes = \
@ -212,26 +228,27 @@ flags = -cp $(test-build)
args = $(flags) $(input)
.PHONY: build
build: $(vm) $(libvm) $(classpath-dep) $(test-dep)
build: $(static-library) $(executable) $(dynamic-library) \
$(executable-dynamic) $(classpath-dep) $(test-dep)
$(test-classes): $(classpath-dep)
.PHONY: run
run: build
$(vm) $(args)
$(executable) $(args)
.PHONY: debug
debug: build
gdb --args $(vm) $(args)
gdb --args $(executable) $(args)
.PHONY: vg
vg: build
$(vg) $(vm) $(args)
$(vg) $(executable) $(args)
.PHONY: test
test: build
/bin/bash $(test)/test.sh 2>/dev/null \
$(vm) $(mode) "$(flags)" \
$(executable) $(mode) "$(flags)" \
$(call class-names,$(test-build),$(test-classes))
.PHONY: javadoc
@ -293,7 +310,15 @@ $(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-object)
$(driver-object): $(native-build)/%.o: $(src)/%.cpp
$(driver-object): $(driver-source)
$(compile-object)
$(driver-dynamic-object): $(driver-source)
@echo "compiling $(@)"
@mkdir -p $(dir $(@))
$(cxx) $(cflags) -DBOOT_LIBRARY=\"$(name)\" -c $(<) -o $(@)
$(boot-object): $(boot-source)
$(compile-object)
$(build)/classpath.jar: $(classpath-dep)
@ -307,7 +332,7 @@ $(binaryToMacho): $(src)/binaryToMacho.cpp
$(classpath-object): $(build)/classpath.jar $(binaryToMacho)
ifeq ($(platform),darwin)
$(binaryToMacho) $(build)/classpath.jar \
__binary_classpath_jar_start __binary_classpath_jar_size > $(@)
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
else
(wd=$$(pwd); \
cd $(build); \
@ -324,23 +349,37 @@ $(generator-objects): $(native-build)/%.o: $(src)/%.cpp
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
$(compile-object)
$(libvm): $(vm-objects) $(jni-objects)
$(static-library): $(vm-objects) $(jni-objects)
@echo "creating $(@)"
rm -rf $(@)
$(ar) cru $(@) $(^)
$(ranlib) $(@)
$(vm): $(vm-objects) $(classpath-object) $(jni-objects) $(driver-object)
$(executable): \
$(vm-objects) $(classpath-object) $(jni-objects) $(driver-object) \
$(boot-object)
@echo "linking $(@)"
ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^)
$(dlltool) -k -d $(@).def -e $(@).exp
$(cc) $(@).exp $(^) $(lflags) -o $(@)
else
$(cc) $(^) $(lflags) -o $(@)
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
endif
$(strip) $(strip-all) $(@)
$(dynamic-library): \
$(vm-objects) $(classpath-object) $(dynamic-object) $(jni-objects) \
$(boot-object)
@echo "linking $(@)"
$(cc) $(^) $(shared) $(lflags) -o $(@)
$(strip) $(@)
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
@echo "linking $(@)"
$(cc) $(^) $(lflags) -o $(@)
$(strip) $(strip-all) $(@)
$(generator): $(generator-objects)
@echo "linking $(@)"
$(build-cc) $(^) -o $(@)

View File

@ -165,12 +165,12 @@ setting the classpath to "[bootJar]".
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(size)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
bootJar(unsigned* size)
{
*size = reinterpret_cast<uintptr_t>(SYMBOL(size));
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}

View File

@ -30,10 +30,10 @@ pad(unsigned n)
void
writeObject(FILE* out, const uint8_t* data, unsigned size,
const char* dataName, const char* sizeName)
const char* startName, const char* endName)
{
unsigned dataNameLength = strlen(dataName) + 1;
unsigned sizeNameLength = strlen(sizeName) + 1;
unsigned startNameLength = strlen(startName) + 1;
unsigned endNameLength = strlen(endName) + 1;
mach_header header = {
MH_MAGIC, // magic
@ -42,7 +42,7 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
MH_OBJECT, // filetype,
2, // ncmds
sizeof(segment_command)
+ sizeof(section)
+ (sizeof(section) * 2)
+ sizeof(symtab_command), // sizeofcmds
0 // flags
};
@ -55,23 +55,23 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
pad(size), // vmsize
sizeof(mach_header)
+ sizeof(segment_command)
+ sizeof(section)
+ (sizeof(section) * 2)
+ sizeof(symtab_command), // fileoff
pad(size), // filesize
7, // maxprot
7, // initprot
1, // nsects
2, // nsects
0 // flags
};
section sect = {
section sect1 = {
"__const", // sectname
"__TEXT", // segname
0, // addr
pad(size), // size
sizeof(mach_header)
+ sizeof(segment_command)
+ sizeof(section)
+ (sizeof(section) * 2)
+ sizeof(symtab_command), // offset
0, // align
0, // reloff
@ -81,12 +81,30 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
0, // reserved2
};
section sect2 = {
"__const", // sectname
"__TEXT", // segname
0, // addr
0, // size
sizeof(mach_header)
+ sizeof(segment_command)
+ (sizeof(section) * 2)
+ sizeof(symtab_command)
+ size, // offset
0, // align
0, // reloff
0, // nreloc
S_REGULAR, // flags
0, // reserved1
0, // reserved2
};
symtab_command symbolTable = {
LC_SYMTAB, // cmd
sizeof(symtab_command), // cmdsize
sizeof(mach_header)
+ sizeof(segment_command)
+ sizeof(section)
+ (sizeof(section) * 2)
+ sizeof(symtab_command)
+ pad(size), // symoff
2, // nsyms
@ -96,7 +114,7 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
+ sizeof(symtab_command)
+ pad(size)
+ (sizeof(struct nlist) * 2), // stroff
1 + dataNameLength + sizeNameLength, // strsize
1 + startNameLength + endNameLength, // strsize
};
struct nlist symbolList[] = {
@ -108,17 +126,18 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
0 // n_value
},
{
reinterpret_cast<char*>(1 + dataNameLength), // n_un
N_ABS | N_EXT, // n_type
NO_SECT, // n_sect
reinterpret_cast<char*>(1 + startNameLength), // n_un
N_SECT | N_EXT, // n_type
2, // n_sect
0, // n_desc
size // n_value
0 // n_value
}
};
fwrite(&header, 1, sizeof(header), out);
fwrite(&segment, 1, sizeof(segment), out);
fwrite(&sect, 1, sizeof(sect), out);
fwrite(&sect1, 1, sizeof(sect1), out);
fwrite(&sect2, 1, sizeof(sect2), out);
fwrite(&symbolTable, 1, sizeof(symbolTable), out);
fwrite(data, 1, size, out);
@ -127,8 +146,8 @@ writeObject(FILE* out, const uint8_t* data, unsigned size,
fwrite(&symbolList, 1, sizeof(symbolList), out);
fputc(0, out);
fwrite(dataName, 1, dataNameLength, out);
fwrite(sizeName, 1, sizeNameLength, out);
fwrite(startName, 1, startNameLength, out);
fwrite(endName, 1, endNameLength, out);
}
} // namespace
@ -138,7 +157,7 @@ main(int argc, const char** argv)
{
if (argc != 4) {
fprintf(stderr,
"usage: %s <input file> <data symbol name> <size symbol name>\n",
"usage: %s <input file> <start symbol name> <end symbol name>\n",
argv[0]);
return -1;
}

29
src/boot.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "stdint.h"
#include "stdlib.h"
// since we don't link against libstdc++, we must implement some dummy
// functions:
extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_classpath_jar_##x
#else
# define EXPORT __attribute__ ((visibility("default")))
# define SYMBOL(x) _binary_classpath_jar_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
classpathJar(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
}

View File

@ -440,14 +440,15 @@ class JarElement: public Element {
class BuiltinElement: public JarElement {
public:
BuiltinElement(System* s, const char* name, unsigned nameLength):
JarElement(s, name, nameLength)
BuiltinElement(System* s, const char* name, unsigned nameLength,
const char* libraryName):
JarElement(s, name, nameLength),
libraryName(libraryName)
{ }
virtual void init() {
if (index == 0) {
System::Library* library;
if (s->success(s->load(&library, 0, false))) {
if (s->success(s->load(&library, libraryName, true))) {
void* p = library->resolve(name);
if (p) {
uint8_t* (*function)(unsigned*);
@ -461,14 +462,21 @@ class BuiltinElement: public JarElement {
index = JarIndex::open(s, region);
}
}
library->disposeAll();
}
}
}
virtual void dispose() {
JarElement::dispose();
library->disposeAll();
}
System::Library* library;
const char* libraryName;
};
Element*
parsePath(System* s, const char* path)
parsePath(System* s, const char* path, const char* bootLibrary)
{
class Tokenizer {
public:
@ -509,7 +517,7 @@ parsePath(System* s, const char* path)
name[token.length - 2] = 0;
e = new (allocate(s, sizeof(BuiltinElement)))
BuiltinElement(s, name, token.length - 2);
BuiltinElement(s, name, token.length - 2, bootLibrary);
} else {
char* name = static_cast<char*>(allocate(s, token.length + 1));
memcpy(name, token.s, token.length);
@ -548,9 +556,9 @@ parsePath(System* s, const char* path)
class MyFinder: public Finder {
public:
MyFinder(System* system, const char* path):
MyFinder(System* system, const char* path, const char* bootLibrary):
system(system),
path_(parsePath(system, path)),
path_(parsePath(system, path, bootLibrary)),
pathString(copy(system, &pathStringLength, path))
{ }
@ -600,9 +608,9 @@ class MyFinder: public Finder {
namespace vm {
Finder*
makeFinder(System* s, const char* path)
makeFinder(System* s, const char* path, const char* bootLibrary)
{
return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path);
return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path, bootLibrary);
}
} // namespace vm

View File

@ -27,7 +27,7 @@ class Finder {
};
Finder*
makeFinder(System* s, const char* path);
makeFinder(System* s, const char* path, const char* bootLibrary);
} // namespace vm

View File

@ -1986,28 +1986,38 @@ JNI_GetDefaultJavaVMInitArgs(void* args)
return 0;
}
#define BUILTINS_PROPERTY "vm.builtins"
#define BUILTINS_PROPERTY "avian.builtins"
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
extern "C" JNIEXPORT jint JNICALL
JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
{
JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args);
System* s = makeSystem();
Heap* h = makeHeap(s, a->maxHeapSize);
Finder* f = makeFinder(s, a->classpath);
Processor* p = makeProcessor(s, h);
*m = new (h->allocate(sizeof(Machine), false)) Machine(s, h, f, p);
const char* builtins = 0;
const char* bootLibrary = 0;
if (a->properties) {
for (const char** p = a->properties; *p; ++p) {
if (strncmp(*p, BUILTINS_PROPERTY "=", sizeof(BUILTINS_PROPERTY)) == 0) {
(*m)->builtins = (*p) + sizeof(BUILTINS_PROPERTY);
if (strncmp(*p, BUILTINS_PROPERTY "=",
sizeof(BUILTINS_PROPERTY)) == 0)
{
builtins = (*p) + sizeof(BUILTINS_PROPERTY);
} else if (strncmp(*p, BOOTSTRAP_PROPERTY "=",
sizeof(BOOTSTRAP_PROPERTY)) == 0)
{
bootLibrary = (*p) + sizeof(BOOTSTRAP_PROPERTY);
}
}
}
System* s = makeSystem();
Heap* h = makeHeap(s, a->maxHeapSize);
Finder* f = makeFinder(s, a->classpath, bootLibrary);
Processor* p = makeProcessor(s, h);
*m = new (h->allocate(sizeof(Machine), false))
Machine(s, h, f, p, bootLibrary, builtins);
*t = p->makeThread(*m, 0, 0);
enter(*t, Thread::ActiveState);

View File

@ -1644,7 +1644,8 @@ class HeapClient: public Heap::Client {
namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor):
Processor* processor, const char* bootLibrary,
const char* builtins):
vtable(&javaVMVTable),
system(system),
heapClient(new (heap->allocate(sizeof(HeapClient), false))
@ -1655,7 +1656,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
rootThread(0),
exclusive(0),
jniReferences(0),
builtins(0),
builtins(builtins),
activeCount(0),
liveCount(0),
fixedFootprint(0),
@ -1688,7 +1689,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
not system->success(system->make(&heapLock)) or
not system->success(system->make(&classLock)) or
not system->success(system->make(&referenceLock)) or
not system->success(system->load(&libraries, 0, false)))
not system->success(system->load(&libraries, bootLibrary, true)))
{
system->abort();
}

View File

@ -1121,7 +1121,8 @@ class Machine {
ImmortalAllocation
};
Machine(System* system, Heap* heap, Finder* finder, Processor* processor);
Machine(System* system, Heap* heap, Finder* finder, Processor* processor,
const char* bootLibrary, const char* builtins);
~Machine() {
dispose();

View File

@ -14,37 +14,12 @@
#include "stdint.h"
#include "jni.h"
// since we don't link against libstdc++, we must implement some dummy
// functions:
extern "C" void __cxa_pure_virtual(void) { abort(); }
void operator delete(void*) { abort(); }
#ifdef __MINGW32__
# define PATH_SEPARATOR ';'
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_classpath_jar_##x
#else
# define PATH_SEPARATOR ':'
# define EXPORT __attribute__ ((visibility("default")))
# define SYMBOL(x) _binary_classpath_jar_##x
#endif
#define BOOT_CLASSPATH "[classpathJar]"
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(size)[];
EXPORT const uint8_t*
classpathJar(unsigned* size)
{
*size = reinterpret_cast<uintptr_t>(SYMBOL(size));
return SYMBOL(start);
}
}
#ifdef JNI_VERSION_1_6
// todo: use JavaVMInitArgs instead
typedef struct JDK1_1InitArgs {
@ -121,14 +96,25 @@ main(int ac, const char** av)
vmArgs.classpath = classpath;
#endif
const char* properties[propertyCount + 1];
properties[propertyCount] = 0;
#ifdef BOOT_LIBRARY
const int BootPropertyCount = 1;
#else
const int BootPropertyCount = 0;
#endif
const char* properties[propertyCount + BootPropertyCount + 1];
properties[propertyCount + BootPropertyCount] = 0;
for (int i = 1; i < ac; ++i) {
if (strncmp(av[i], "-D", 2) == 0) {
properties[--propertyCount] = av[i] + 2;
}
}
#ifdef BOOT_LIBRARY
properties[propertyCount + BootPropertyCount - 1]
= "avian.bootstrap=" BOOT_LIBRARY;
#endif
vmArgs.properties = const_cast<char**>(properties);
if (class_ == 0) {

View File

@ -687,18 +687,18 @@ class MySystem: public System {
bool alreadyAllocated = false;
bool isMain = false;
unsigned nameLength = (name ? strlen(name) : 0);
if (mapName) {
if (mapName and name) {
unsigned size = nameLength + 3 + sizeof(SO_SUFFIX);
char buffer[size];
snprintf(buffer, size, "lib%s" SO_SUFFIX, name);
p = dlopen(buffer, RTLD_LAZY);
p = dlopen(buffer, RTLD_LAZY | RTLD_LOCAL);
} else {
if (!name) {
pathOfExecutable(this, &name, &nameLength);
alreadyAllocated = true;
isMain = true;
}
p = dlopen(name, RTLD_LAZY);
p = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
}
if (p) {

View File

@ -623,7 +623,7 @@ class MySystem: public System {
{
HMODULE handle;
unsigned nameLength = (name ? strlen(name) : 0);
if (mapName) {
if (mapName and name) {
unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX);
char buffer[size];
snprintf(buffer, size, SO_PREFIX "%s" SO_SUFFIX, name);