mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +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);
|
unsigned size = fieldSize(t, code);
|
||||||
if (flags & ACC_STATIC) {
|
if (flags & ACC_STATIC) {
|
||||||
while (staticOffset % size) {
|
staticOffset = pad(staticOffset, size);
|
||||||
++ staticOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldOffset(t, field) = staticOffset;
|
fieldOffset(t, field) = staticOffset;
|
||||||
|
|
||||||
@ -1308,9 +1306,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
classVmFlags(t, class_) |= HasFinalMemberFlag;
|
classVmFlags(t, class_) |= HasFinalMemberFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (memberOffset % size) {
|
memberOffset = pad(memberOffset, size);
|
||||||
++ memberOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldOffset(t, field) = memberOffset;
|
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) {
|
for (unsigned i = 0, offset = BytesPerWord; i < staticCount; ++i) {
|
||||||
unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]);
|
unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]);
|
||||||
while (offset % size) {
|
offset = pad(offset, size);
|
||||||
++ offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned value = intArrayBody(t, staticValueTable, i);
|
unsigned value = intArrayBody(t, staticValueTable, i);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -48,6 +48,7 @@ const bool DebugNativeTarget = false;
|
|||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Type_none,
|
Type_none,
|
||||||
|
Type_pad,
|
||||||
Type_object,
|
Type_object,
|
||||||
Type_object_nogc,
|
Type_object_nogc,
|
||||||
Type_int8_t,
|
Type_int8_t,
|
||||||
@ -517,9 +518,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_STATIC) {
|
if (fieldFlags(t, field) & ACC_STATIC) {
|
||||||
while (targetStaticOffset % targetSize) {
|
targetStaticOffset = pad(targetStaticOffset, targetSize);
|
||||||
++ targetStaticOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildStaticOffset = fieldOffset(t, field);
|
buildStaticOffset = fieldOffset(t, field);
|
||||||
|
|
||||||
@ -531,9 +530,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
|
|
||||||
++ staticIndex;
|
++ staticIndex;
|
||||||
} else {
|
} else {
|
||||||
while (targetMemberOffset % targetSize) {
|
targetMemberOffset = pad(targetMemberOffset, targetSize);
|
||||||
++ targetMemberOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildMemberOffset = fieldOffset(t, field);
|
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) {
|
for (unsigned i = 0; i < arrayLength(t, t->m->types); ++i) {
|
||||||
Type* source = types[i];
|
Type* source = types[i];
|
||||||
unsigned count = 0;
|
unsigned typeCount = 0;
|
||||||
while (source[count] != Type_none) {
|
unsigned fieldCount = 1;
|
||||||
++ count;
|
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,
|
init(new (RUNTIME_ARRAY_BODY(fields)) Field, Type_object, 0,
|
||||||
BytesPerWord, 0, TargetBytesPerWord);
|
BytesPerWord, 0, TargetBytesPerWord);
|
||||||
@ -1356,8 +1356,15 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
Type type = Type_none;
|
Type type = Type_none;
|
||||||
unsigned buildSize = 0;
|
unsigned buildSize = 0;
|
||||||
unsigned targetSize = 0;
|
unsigned targetSize = 0;
|
||||||
for (unsigned j = 1; j < count; ++j) {
|
unsigned fieldOffset = 1;
|
||||||
switch (source[j - 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:
|
case Type_object:
|
||||||
type = Type_object;
|
type = Type_object;
|
||||||
buildSize = BytesPerWord;
|
buildSize = BytesPerWord;
|
||||||
@ -1412,21 +1419,21 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source[j - 1] == Type_array) {
|
if (source[j] == Type_array) {
|
||||||
sawArray = true;
|
sawArray = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not sawArray) {
|
if (type == Type_pad) {
|
||||||
while (buildOffset % buildSize) {
|
buildOffset = pad(buildOffset, BytesPerWord);
|
||||||
++ buildOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (targetOffset % targetSize) {
|
targetOffset = pad(targetOffset, TargetBytesPerWord);
|
||||||
++ targetOffset;
|
} else if (not sawArray) {
|
||||||
}
|
buildOffset = pad(buildOffset, buildSize);
|
||||||
|
|
||||||
init(new (RUNTIME_ARRAY_BODY(fields) + j) Field, type, buildOffset,
|
targetOffset = pad(targetOffset, targetSize);
|
||||||
buildSize, targetOffset, targetSize);
|
|
||||||
|
init(new (RUNTIME_ARRAY_BODY(fields) + (fieldOffset++)) Field, type,
|
||||||
|
buildOffset, buildSize, targetOffset, targetSize);
|
||||||
|
|
||||||
buildOffset += buildSize;
|
buildOffset += buildSize;
|
||||||
targetOffset += targetSize;
|
targetOffset += targetSize;
|
||||||
@ -1438,12 +1445,12 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
unsigned buildArrayElementSize;
|
unsigned buildArrayElementSize;
|
||||||
unsigned targetArrayElementSize;
|
unsigned targetArrayElementSize;
|
||||||
if (sawArray) {
|
if (sawArray) {
|
||||||
fixedFieldCount = count - 2;
|
fixedFieldCount = fieldCount - 2;
|
||||||
arrayElementType = type;
|
arrayElementType = type;
|
||||||
buildArrayElementSize = buildSize;
|
buildArrayElementSize = buildSize;
|
||||||
targetArrayElementSize = targetSize;
|
targetArrayElementSize = targetSize;
|
||||||
} else {
|
} else {
|
||||||
fixedFieldCount = count;
|
fixedFieldCount = fieldCount;
|
||||||
arrayElementType = Type_none;
|
arrayElementType = Type_none;
|
||||||
buildArrayElementSize = 0;
|
buildArrayElementSize = 0;
|
||||||
targetArrayElementSize = 0;
|
targetArrayElementSize = 0;
|
||||||
|
@ -636,6 +636,7 @@ class MemberIterator {
|
|||||||
unsigned size_;
|
unsigned size_;
|
||||||
unsigned padding_;
|
unsigned padding_;
|
||||||
unsigned alignment_;
|
unsigned alignment_;
|
||||||
|
unsigned sawSuperclassBoundary;
|
||||||
|
|
||||||
MemberIterator(Object* type, bool skipSupers = false):
|
MemberIterator(Object* type, bool skipSupers = false):
|
||||||
types(derivationChain(type)),
|
types(derivationChain(type)),
|
||||||
@ -646,7 +647,8 @@ class MemberIterator {
|
|||||||
offset_(BytesPerWord),
|
offset_(BytesPerWord),
|
||||||
size_(0),
|
size_(0),
|
||||||
padding_(0),
|
padding_(0),
|
||||||
alignment_(BytesPerWord)
|
alignment_(BytesPerWord),
|
||||||
|
sawSuperclassBoundary(true)
|
||||||
{
|
{
|
||||||
while (skipSupers and hasMore() and this->type != type) next();
|
while (skipSupers and hasMore() and this->type != type) next();
|
||||||
padding_ = 0;
|
padding_ = 0;
|
||||||
@ -663,7 +665,10 @@ class MemberIterator {
|
|||||||
offset_ = ((offset_ + size_) + (BytesPerWord - 1))
|
offset_ = ((offset_ + size_) + (BytesPerWord - 1))
|
||||||
& ~(BytesPerWord - 1);
|
& ~(BytesPerWord - 1);
|
||||||
alignment_ = BytesPerWord;
|
alignment_ = BytesPerWord;
|
||||||
|
sawSuperclassBoundary = true;
|
||||||
member = 0;
|
member = 0;
|
||||||
|
} else {
|
||||||
|
sawSuperclassBoundary = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = car(types);
|
type = car(types);
|
||||||
@ -1833,6 +1838,10 @@ writeMap(Output* out, Object* type)
|
|||||||
for (MemberIterator it(type); it.hasMore();) {
|
for (MemberIterator it(type); it.hasMore();) {
|
||||||
Object* m = it.next();
|
Object* m = it.next();
|
||||||
|
|
||||||
|
if (it.sawSuperclassBoundary) {
|
||||||
|
out->write("Type_pad, ");
|
||||||
|
}
|
||||||
|
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case Object::Scalar: {
|
case Object::Scalar: {
|
||||||
out->write("Type_");
|
out->write("Type_");
|
||||||
|
Loading…
Reference in New Issue
Block a user