codiff: Improve the comparision of anonymous struct members
I.e. 'union {};', 'struct {};' members were always appearing as having been removed, as we normally do lookup by member name, to find out if its offset, size, type, etc changed. For unnamed members, try a different heuristic, i.e. look for the nth anonymous member, this way we're just trying to compare the first unnamed member of, say, struct OLD with the first unnamed member of struct NEW, etc. For OLD == NEW, this works well, for OLD != NEW because some non anonymous field got added, removed or moved around, ditto, and when the number of unnamed fields gets decreased, then we can mix things up, and compare the previously first in A with the previously first in B. For the current intended use case of: 1) compile a .c file into a .o file with debugging info, say FILE.o 2) use 'pfunct --compile FILE.o > regenerated-FILE.c' 3) compile regenerated-FILE.c into regenerated-FILE.o with debugging info 4) codiff --struct FILE.o regenerated-FILE.o and find out if they match This gets us moving forward as we'll spot differences with this algo. For the future we can use a few more heuristics or stop using search by name members, instead traversing both structs in tandem, spotting the differences by comparing the fields that way. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
6b1e43f2c1
commit
75f32a24c7
41
codiff.c
41
codiff.c
|
@ -181,21 +181,42 @@ static int check_print_change(const struct class_member *old,
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct class_member *class__find_pair_member(const struct class *structure, const struct cu *cu,
|
||||||
|
const struct class_member *pair_member, const struct cu *pair_cu,
|
||||||
|
int *nr_anonymousp)
|
||||||
|
{
|
||||||
|
const char *member_name = class_member__name(pair_member, pair_cu);
|
||||||
|
struct class_member *member;
|
||||||
|
|
||||||
|
if (member_name)
|
||||||
|
return class__find_member_by_name(structure, cu, member_name);
|
||||||
|
|
||||||
|
int nr_anonymous = ++*nr_anonymousp;
|
||||||
|
|
||||||
|
/* Unnamed struct or union, lets look for the first unammed matchin tag.type */
|
||||||
|
|
||||||
|
type__for_each_member(&structure->type, member) {
|
||||||
|
if (member->tag.tag == pair_member->tag.tag && /* Both are class/union/struct (unnamed) */
|
||||||
|
class_member__name(member, cu) == member_name && /* Both are NULL? */
|
||||||
|
--nr_anonymous == 0)
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int check_print_members_changes(const struct class *structure,
|
static int check_print_members_changes(const struct class *structure,
|
||||||
const struct cu *cu,
|
const struct cu *cu,
|
||||||
const struct class *new_structure,
|
const struct class *new_structure,
|
||||||
const struct cu *new_cu,
|
const struct cu *new_cu,
|
||||||
int print)
|
int print)
|
||||||
{
|
{
|
||||||
int changes = 0;
|
int changes = 0, nr_anonymous = 0;
|
||||||
struct class_member *member;
|
struct class_member *member;
|
||||||
uint16_t nr_twins_found = 0;
|
uint16_t nr_twins_found = 0;
|
||||||
|
|
||||||
type__for_each_member(&structure->type, member) {
|
type__for_each_member(&structure->type, member) {
|
||||||
const char *member_name = class_member__name(member, cu);
|
struct class_member *twin = class__find_pair_member(new_structure, new_cu, member, cu, &nr_anonymous);
|
||||||
struct class_member *twin =
|
|
||||||
class__find_member_by_name(new_structure, new_cu,
|
|
||||||
member_name);
|
|
||||||
if (twin != NULL) {
|
if (twin != NULL) {
|
||||||
twin->tag.visited = 1;
|
twin->tag.visited = 1;
|
||||||
++nr_twins_found;
|
++nr_twins_found;
|
||||||
|
@ -434,21 +455,19 @@ static void show_nr_members_changes(const struct class *structure,
|
||||||
const struct cu *new_cu)
|
const struct cu *new_cu)
|
||||||
{
|
{
|
||||||
struct class_member *member;
|
struct class_member *member;
|
||||||
|
int nr_anonymous = 0;
|
||||||
|
|
||||||
/* Find the removed ones */
|
/* Find the removed ones */
|
||||||
type__for_each_member(&structure->type, member) {
|
type__for_each_member(&structure->type, member) {
|
||||||
struct class_member *twin =
|
struct class_member *twin = class__find_pair_member(new_structure, new_cu, member, cu, &nr_anonymous);
|
||||||
class__find_member_by_name(new_structure, new_cu,
|
|
||||||
class_member__name(member, cu));
|
|
||||||
if (twin == NULL)
|
if (twin == NULL)
|
||||||
show_changed_member('-', member, cu);
|
show_changed_member('-', member, cu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nr_anonymous = 0;
|
||||||
/* Find the new ones */
|
/* Find the new ones */
|
||||||
type__for_each_member(&new_structure->type, member) {
|
type__for_each_member(&new_structure->type, member) {
|
||||||
struct class_member *twin =
|
struct class_member *twin = class__find_pair_member(structure, cu, member, new_cu, &nr_anonymous);
|
||||||
class__find_member_by_name(structure, cu,
|
|
||||||
class_member__name(member, new_cu));
|
|
||||||
if (twin == NULL)
|
if (twin == NULL)
|
||||||
show_changed_member('+', member, new_cu);
|
show_changed_member('+', member, new_cu);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue