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:
Joel Dice 2014-01-06 15:19:00 -07:00
parent 1f6051bcbc
commit bb86500155
3 changed files with 45 additions and 35 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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_");