mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
fix Method.getModifiers crash due to bootimage miscompile
When calculating field offsets in the bootimage generator, we failed to consider alignment at inheritence boundaries (i.e. the last field inherited by from a superclass should be followed by enough padding to align the first non-inherited field at a machine word boundary). This led to a mismatch between native code and Java code in terms of class layouts, including that of java.lang.reflect.Method.
This commit is contained in:
parent
1f6051bcbc
commit
bb86500155
@ -1292,9 +1292,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
|
||||
unsigned size = fieldSize(t, code);
|
||||
if (flags & ACC_STATIC) {
|
||||
while (staticOffset % size) {
|
||||
++ staticOffset;
|
||||
}
|
||||
staticOffset = pad(staticOffset, size);
|
||||
|
||||
fieldOffset(t, field) = staticOffset;
|
||||
|
||||
@ -1308,9 +1306,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
classVmFlags(t, class_) |= HasFinalMemberFlag;
|
||||
}
|
||||
|
||||
while (memberOffset % size) {
|
||||
++ memberOffset;
|
||||
}
|
||||
memberOffset = pad(memberOffset, size);
|
||||
|
||||
fieldOffset(t, field) = memberOffset;
|
||||
|
||||
@ -1335,9 +1331,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
|
||||
for (unsigned i = 0, offset = BytesPerWord; i < staticCount; ++i) {
|
||||
unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]);
|
||||
while (offset % size) {
|
||||
++ offset;
|
||||
}
|
||||
offset = pad(offset, size);
|
||||
|
||||
unsigned value = intArrayBody(t, staticValueTable, i);
|
||||
if (value) {
|
||||
|
@ -48,6 +48,7 @@ const bool DebugNativeTarget = false;
|
||||
|
||||
enum Type {
|
||||
Type_none,
|
||||
Type_pad,
|
||||
Type_object,
|
||||
Type_object_nogc,
|
||||
Type_int8_t,
|
||||
@ -517,9 +518,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
}
|
||||
|
||||
if (fieldFlags(t, field) & ACC_STATIC) {
|
||||
while (targetStaticOffset % targetSize) {
|
||||
++ targetStaticOffset;
|
||||
}
|
||||
targetStaticOffset = pad(targetStaticOffset, targetSize);
|
||||
|
||||
buildStaticOffset = fieldOffset(t, field);
|
||||
|
||||
@ -531,9 +530,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
|
||||
++ staticIndex;
|
||||
} else {
|
||||
while (targetMemberOffset % targetSize) {
|
||||
++ targetMemberOffset;
|
||||
}
|
||||
targetMemberOffset = pad(targetMemberOffset, targetSize);
|
||||
|
||||
buildMemberOffset = fieldOffset(t, field);
|
||||
|
||||
@ -1339,13 +1336,16 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
||||
|
||||
for (unsigned i = 0; i < arrayLength(t, t->m->types); ++i) {
|
||||
Type* source = types[i];
|
||||
unsigned count = 0;
|
||||
while (source[count] != Type_none) {
|
||||
++ count;
|
||||
unsigned typeCount = 0;
|
||||
unsigned fieldCount = 1;
|
||||
while (source[typeCount] != Type_none) {
|
||||
++ typeCount;
|
||||
if (source[typeCount] != Type_pad) {
|
||||
++ fieldCount;
|
||||
}
|
||||
}
|
||||
++ count;
|
||||
|
||||
THREAD_RUNTIME_ARRAY(t, Field, fields, count);
|
||||
THREAD_RUNTIME_ARRAY(t, Field, fields, fieldCount);
|
||||
|
||||
init(new (RUNTIME_ARRAY_BODY(fields)) Field, Type_object, 0,
|
||||
BytesPerWord, 0, TargetBytesPerWord);
|
||||
@ -1356,8 +1356,15 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
||||
Type type = Type_none;
|
||||
unsigned buildSize = 0;
|
||||
unsigned targetSize = 0;
|
||||
for (unsigned j = 1; j < count; ++j) {
|
||||
switch (source[j - 1]) {
|
||||
unsigned fieldOffset = 1;
|
||||
for (unsigned j = 0; j < typeCount; ++j) {
|
||||
switch (source[j]) {
|
||||
case Type_pad:
|
||||
type = Type_pad;
|
||||
buildSize = 0;
|
||||
targetSize = 0;
|
||||
break;
|
||||
|
||||
case Type_object:
|
||||
type = Type_object;
|
||||
buildSize = BytesPerWord;
|
||||
@ -1412,21 +1419,21 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
if (source[j - 1] == Type_array) {
|
||||
if (source[j] == Type_array) {
|
||||
sawArray = true;
|
||||
}
|
||||
|
||||
if (not sawArray) {
|
||||
while (buildOffset % buildSize) {
|
||||
++ buildOffset;
|
||||
}
|
||||
if (type == Type_pad) {
|
||||
buildOffset = pad(buildOffset, BytesPerWord);
|
||||
|
||||
while (targetOffset % targetSize) {
|
||||
++ targetOffset;
|
||||
}
|
||||
targetOffset = pad(targetOffset, TargetBytesPerWord);
|
||||
} else if (not sawArray) {
|
||||
buildOffset = pad(buildOffset, buildSize);
|
||||
|
||||
init(new (RUNTIME_ARRAY_BODY(fields) + j) Field, type, buildOffset,
|
||||
buildSize, targetOffset, targetSize);
|
||||
targetOffset = pad(targetOffset, targetSize);
|
||||
|
||||
init(new (RUNTIME_ARRAY_BODY(fields) + (fieldOffset++)) Field, type,
|
||||
buildOffset, buildSize, targetOffset, targetSize);
|
||||
|
||||
buildOffset += buildSize;
|
||||
targetOffset += targetSize;
|
||||
@ -1438,12 +1445,12 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
||||
unsigned buildArrayElementSize;
|
||||
unsigned targetArrayElementSize;
|
||||
if (sawArray) {
|
||||
fixedFieldCount = count - 2;
|
||||
fixedFieldCount = fieldCount - 2;
|
||||
arrayElementType = type;
|
||||
buildArrayElementSize = buildSize;
|
||||
targetArrayElementSize = targetSize;
|
||||
} else {
|
||||
fixedFieldCount = count;
|
||||
fixedFieldCount = fieldCount;
|
||||
arrayElementType = Type_none;
|
||||
buildArrayElementSize = 0;
|
||||
targetArrayElementSize = 0;
|
||||
|
@ -636,6 +636,7 @@ class MemberIterator {
|
||||
unsigned size_;
|
||||
unsigned padding_;
|
||||
unsigned alignment_;
|
||||
unsigned sawSuperclassBoundary;
|
||||
|
||||
MemberIterator(Object* type, bool skipSupers = false):
|
||||
types(derivationChain(type)),
|
||||
@ -646,7 +647,8 @@ class MemberIterator {
|
||||
offset_(BytesPerWord),
|
||||
size_(0),
|
||||
padding_(0),
|
||||
alignment_(BytesPerWord)
|
||||
alignment_(BytesPerWord),
|
||||
sawSuperclassBoundary(true)
|
||||
{
|
||||
while (skipSupers and hasMore() and this->type != type) next();
|
||||
padding_ = 0;
|
||||
@ -663,7 +665,10 @@ class MemberIterator {
|
||||
offset_ = ((offset_ + size_) + (BytesPerWord - 1))
|
||||
& ~(BytesPerWord - 1);
|
||||
alignment_ = BytesPerWord;
|
||||
sawSuperclassBoundary = true;
|
||||
member = 0;
|
||||
} else {
|
||||
sawSuperclassBoundary = false;
|
||||
}
|
||||
|
||||
type = car(types);
|
||||
@ -1833,6 +1838,10 @@ writeMap(Output* out, Object* type)
|
||||
for (MemberIterator it(type); it.hasMore();) {
|
||||
Object* m = it.next();
|
||||
|
||||
if (it.sawSuperclassBoundary) {
|
||||
out->write("Type_pad, ");
|
||||
}
|
||||
|
||||
switch (m->type) {
|
||||
case Object::Scalar: {
|
||||
out->write("Type_");
|
||||
|
Loading…
Reference in New Issue
Block a user