Fixed ivar offset checking to take account for alignment.

main
theraven 16 years ago
parent 6a94efd4cf
commit 9dc0343c21

@ -756,38 +756,51 @@ __objc_compute_ivar_offsets (Class class)
} }
else else
{ {
if (class->ivars != 0) if (NULL == class->ivars)
{ {
Class super = class_superclass_of_class(class); return;
int start = class->ivars->ivar_list[0].ivar_offset; }
/* Quick and dirty test */ Class super = class_superclass_of_class(class);
if (Nil != super && start != super->instance_size) int start = class->ivars->ivar_list[0].ivar_offset;
{ /* Quick and dirty test. If the first ivar comes straight after the last
while (NULL == super->ivars) * class, then it's fine. */
{ if (Nil == super || start == super->instance_size)
super = class_superclass_of_class(super); {
} return;
struct objc_ivar *ivar = }
&super->ivars->ivar_list[super->ivars->ivar_count-1]; /* Find the last superclass with at least one ivar. */
if (start != (ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type))) while (NULL == super->ivars)
{ {
/* Panic if this class has an instance variable that overlaps the super = class_superclass_of_class(super);
* superclass. */ }
fprintf(stderr, struct objc_ivar *ivar =
"Error: Instance variables in %s overlap superclass %s", &super->ivars->ivar_list[super->ivars->ivar_count-1];
class->name, super->name); if (start == (ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type)))
fprintf(stderr, {
"Offset of first instance variable, %s, is %d", return;
class->ivars->ivar_list[0].ivar_name, start); }
fprintf(stderr, /* The classes don't line up, but don't panic; check that the
"Last instance variable in superclass, %s, ends at offset %d", * difference is not just padding for alignment */
ivar->ivar_name, int align = objc_alignof_type(class->ivars->ivar_list[0].ivar_type);
ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type)); if (start > ivar->ivar_offset &&
fprintf(stderr, "This probably means that you are subclassing a class from a library, which has changed in a binary-incompatible way.\n"); start - ivar->ivar_offset < align)
abort(); {
} return;
}
} }
/* Panic if this class has an instance variable that overlaps the
* superclass. */
fprintf(stderr,
"Error: Instance variables in %s overlap superclass %s",
class->name, super->name);
fprintf(stderr,
"Offset of first instance variable, %s, is %d",
class->ivars->ivar_list[0].ivar_name, start);
fprintf(stderr,
"Last instance variable in superclass, %s, ends at offset %d",
ivar->ivar_name,
ivar->ivar_offset + objc_sizeof_type(ivar->ivar_type));
fprintf(stderr, "This probably means that you are subclassing a class from a library, which has changed in a binary-incompatible way.\n");
abort();
} }
} }

Loading…
Cancel
Save