rizinorg / rizin

UNIX-like reverse engineering framework and command-line toolset.

Home Page:https://rizin.re

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dereference member from struct

rockrid3r opened this issue · comments

Is your feature request related to a problem? Please describe.
Working on #4257 currently. It is useful to be able to get offset from base type to it's member. For if we want to read b from this struct:

struct A {
    int a;
    int b;
}

we should calculate it's offset from A based on the type info of A.

There are many different structs and many different members in #4257 that needs to be processed like this. So a whole new feature dedicated specifically to this task will be useful.

Describe the solution you'd like
The simple rz_vector_foreach(btype->struct_data.members, memb_iter) will not work (generally). For example, for this struct:

struct A {
    struct {
        int b;
    }
} a;

you can do this: a->b.

So if we consider our struct as tree, then:

  • non-anonymous members are leaves
  • anonymous members are nodes, which should be investigated further!

BFS/DFS problem as I see it. Comments are welcome!

It is already implemented if I understood the question right - see functions from librz/type/path.c

Thanks, didn't see this. Still the code (taken from librz/type/path.c)

RZ_API ut64 rz_type_db_struct_member_offset(RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_NONNULL const char *member) {
	rz_return_val_if_fail(typedb && name && member, 0);
	RzBaseType *btype = rz_type_db_get_base_type(typedb, name);
	if (!btype || btype->kind != RZ_BASE_TYPE_KIND_STRUCT) {
		return 0;
	}
	RzTypeStructMember *memb;
	rz_vector_foreach(&btype->struct_data.members, memb) {
		if (!strcmp(memb->name, member)) {
			return memb->offset;
		}
	}
	return 0;
}

won't work with the described test case:

struct A {
    struct {
        int b;
    }
} a;

because struct A has only 1 member: anonymous struct. This code won't reach b.

Ah, yes, currently there is no support for anonymous structs in type paths. I am not sure if ti worth implementing because it will create unnecessary ambiguity. Keep in mind, all features in Rizin are for the reverse engineering. Simply omitting types in type paths might create confusion in some cases. We can produce something like that instead:
a->(anonymous struct 0)->b.

Ok, somewhat agree here. Maybe we shouldn't close the issue though.

C keeps that somewhat strict. This

struct A {
    struct {
        int b;
    };
    int b;
} a;

won't compile with error duplicate member 'b'. (I've ran gcc on this).

But I didn't test it that much. Maybe there are some confusions, not sure.

I will implement it locally in code for #4257 and see if it works.