Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add acg - printing class hierarchy graph ##anal #17362

Merged
merged 13 commits into from
Aug 7, 2020

Conversation

HoundThe
Copy link
Contributor

@HoundThe HoundThe commented Jul 27, 2020

Your checklist for this pull request

  • I've read the guidelines for contributing to this repository
  • I made sure to follow the project's coding style
  • I've added tests that prove my fix is effective or that my feature works (if possible)
  • I've updated the documentation and the radare2 book with the relevant information (if needed)

Detailed description

So I was thinking about adding ability to print out class hierarchy graph, based on class information in anal/classes
I've made a rough idea, I still need to look into agraph implementation more so I can make it look better, maybe add other options, this was made just by looking at the agraph interface to sketch it out. What do you think?

PS: I know dogs don't come out of cats

Example now:

[0x00001120]> acl
Bat
Bird
Cat
Dog
Kappa
Mammal
[0x00001120]> acb Bat Bird
[0x00001120]> acb Bat Mammal
[0x00001120]> acb Kappa Cat
[0x00001120]> acb Dog Cat
[0x00001120]> acb Cat Mammal
[0x00001120]> acg
┌────────────────────┐    ┌────────────────────┐
│  Bird              │    │  Mammal            │
└────────────────────┘    └────────────────────┘
    v                           t
     └                      ───╯  f
      └                 ───╯      │
       └            ───╯          │
        └       ───╯              │
         └   ──╯                  │
    ┌────────────────────┐    ┌────────────────────┐
    │  Bat               │    │  Cat               │
    └────────────────────┘    └────────────────────┘
                                    t f
                                 ──╯   └─
                             ───╯        └─
                         ───╯              └─
                      ──╯                    └─
                 ┌────────────────────┐    ┌────────────────────┐
                 │  Dog               │    │  Kappa             │
                 └────────────────────┘    └────────────────────┘

@HoundThe HoundThe requested a review from trufae as a code owner July 27, 2020 16:16
@HoundThe HoundThe changed the title Add acg - printing class hierarchy graph Add acg - printing class hierarchy graph ##anal Jul 27, 2020
@github-actions github-actions bot added the command New commands requests, behaviour changes, removal label Jul 27, 2020
@XVilka
Copy link
Contributor

XVilka commented Jul 28, 2020

Idea is good. I recommend to try it on a real binaries with a huge inheritance tree, to check how it might look like. Also it might be of particular interest for Cutter folks @ITAYC0HEN @karliss

@XVilka XVilka removed the request for review from radare July 28, 2020 06:05
@karliss
Copy link
Contributor

karliss commented Jul 28, 2020

For this to to be usable by Cutter it needs to expose proper API.
Ideally I would like to see something like this, it would be nice to refactor the existing graph functions to use similar structure at some time in future as well.

  • r_anal_class_get_inheritance_graph -> creates and returns RAGraph*
  • r_core_agraph_print refactored or split into two functions so that it can be passed any RAgraph* instead of reading global graph instance from core->graph
  • r2 command would looks something like
graph = r_anal_class_get_inheritance_graph()
r_core_agraph_print(graph, input); // input potentially containing extra arguments for choosing output type
r_agraph_free(graph);

The benefits to such structure that all r2 graph output modes are easily available and it also makes the C API more usable.
As a general principle what I would like to see more in R2 to is better separation of core logic from UI code - console printing, r2 command argument parsing, default values based on global variables representing text UI state.

@ITAYC0HEN
Copy link
Contributor

I very much like the idea!! If it will be under the ag commands and implement the required information of a graph we can rather easily parse them and present them to the user

@karliss
Copy link
Contributor

karliss commented Jul 28, 2020

Correction it might be better for r_anal_class_get_inheritance_graph to return RGraph or something similar which is abstract representation of graph without any drawing logic. RAGraph should be created from RGraph when you decide to draw something unless unless it gets used in format that don't require Ascii graphic output like dot, gml or json.

@karliss
Copy link
Contributor

karliss commented Jul 28, 2020

Most of the refactoring I mentioned should probably be done in separate PR, but some of the smaller things to make more of the modes for acg and make it easier to update it's code once graph refactoring is done could be done within this PR.

I don't think all of the graph commands need be bellow ag. As long as interface is consistent it can be anywhere. Placing everything under ag is also limited by number of available characters and logical naming limiting even sooner.

Copy link
Contributor

@XVilka XVilka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the changes suggested by @karliss.

@HoundThe
Copy link
Contributor Author

HoundThe commented Aug 2, 2020

Looking at it now, I think maybe creating RAGraph as a start and then parsing the info from that might be better I guess? Or making both, RAGraph and RGraph and using the API you want. Transforming RGraph to RAGraph every time for acg seems a bit unnecessary. But transforming RAGraph into RGraph might be very easy as RAGraph contains RGraph that you can just take and use with the nodes that have RANode as the generic data.

libr/anal/meson.build Outdated Show resolved Hide resolved
libr/anal/meson.build Outdated Show resolved Hide resolved
libr/anal/class.c Outdated Show resolved Hide resolved
libr/core/cmd_anal.c Show resolved Hide resolved
libr/core/cmd_anal.c Outdated Show resolved Hide resolved
libr/include/r_anal.h Outdated Show resolved Hide resolved
libr/anal/class.c Show resolved Hide resolved
libr/anal/class.c Outdated Show resolved Hide resolved
libr/anal/class.c Outdated Show resolved Hide resolved
@XVilka
Copy link
Contributor

XVilka commented Aug 5, 2020

It looks better now. Could you please add a test?

libr/include/r_anal.h Outdated Show resolved Hide resolved
libr/include/r_anal.h Outdated Show resolved Hide resolved
libr/include/r_anal.h Outdated Show resolved Hide resolved
@github-actions github-actions bot added the API New API requests, changes, removal label Aug 5, 2020
@HoundThe HoundThe requested review from karliss and trufae August 5, 2020 16:25
@github-actions github-actions bot added the r2r Regression tests label Aug 5, 2020
libr/anal/class.c Outdated Show resolved Hide resolved
libr/anal/class.c Show resolved Hide resolved
test/unit/test_agraph.c Show resolved Hide resolved
@@ -7,6 +7,15 @@
extern "C" {
#endif

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong to me, from an API point of view. It is not generic IMO. actually, it assumes the graph needs to be drawn and that it has an offset a body and a title, which may very well not be true. Also, by having this thing here it seems like all nodes of the rgraph are of this type, which is again not true.

IMHO this should go somewhere else. Anal maybe.

As I previously said, I like to think about this as simple data structures, like RList, RVector or similar. We don't have particular data definitions in the header files rlist.h, r_vector.h and I don't see why we should have this here in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D Ye, that's true also, then I am unsure where to move it, I guess there isn't much of other option than r_anal.h middleground

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r_anal.h is the right option i think, since the RGraph is returned from a r_anal method it should be that module to define the data contained within. In the same way as RBin defines RBinSymbol when it returns a RList of symbols of a binary.

Also, IMHO it would be better to have a sort of RAnalClass structure rather than a "generic" graph-drawing structure (at least for now). It may make sense to think about something much more generic for drawing graphs once we realize we have multiple points in the code where this is required. The fact is that in r2 maybe the title is just the class name, but we can't know if Cutter, for example, would like to also show something else in the graph title (maybe it wants to show both the demangled and mangled name? or maybe make it configurable? I don't know, but IMO it's better to return the class data and let the actual users of the API handle the drawing in the way it prefers, rather than forcing a view of the data to the users of the r_anal_class_get_inheritance_graph function). Also, note that maybe I want the relationships between the classes but I actually don't want to draw them, so forcing a draw-like structure does not seem the best option from API PoV.

Copy link
Contributor

@karliss karliss Aug 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drawable graph is better than old situation of no API/getting drawn graph and creating AGraph even when it isn't necessary. In most cases Cutter doesn't need to reinvent the wheel and can use whatever r2 decides is the best tittle, body is.

If you want class hierarchy information for non drawing purposes using class specific structures there is already API for that -> r_anal_class_base_get_all, r_anal_class_get_all and the other related methods.

If you really don't like RGraphNodeInfo in rgraph then it can be split into 3 parts: rgraph, drawable graph, ragraph.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand it right, r_anal_class_base_get_all just returns the list of classes identified, not their relationships. On the other hand, r_anal_class_get_inheritance_graph as it is now just returns a "drawing graph", but no direct access to the class info. One would have to then do additional calls to get the classes info from RGraphNodeInfo. What's worse is that you would have to assume that, for example, the title of the node is the class name or something like that.

I'm very against RGraphNodeInfo in r_graph, yeah. The same as I don't see a RListNodeInfo in r_list or a RTreeNodeInfo in r_tree or something else in other places. All of these data structures may require some drawing, sure, but it is not the responsibility of r_graph(nor r_list, nor r_tree, etc.) to provide a particular way to draw the provided info (think about the RAGraph drawn with VV. You can see that in multiple ways by pressing p/P keys. If the logic of what to put in the body of the nodes would be in r_util/r_graph you would have to do a mess to change even a small thing). Those data structures should just provide the structure. In this case I think you have chosen a graph because there are relationships between classes like multiple parent/children.

We may want to have a RGraphDrawable structure or something as a "subclass" of RGraph, but personally I would go that way only if there is more than one case where this is actually needed. If right now this is only used by the class usecase, it seems a bit overkill to me.

@XVilka XVilka merged commit b44b8cb into radareorg:master Aug 7, 2020
@XVilka
Copy link
Contributor

XVilka commented Aug 7, 2020

Sorry, seems page wasn't updated. @HoundThe please send addressing @ret2libc feedback in a separate PR.

ret2libc added a commit to ret2libc/radare2 that referenced this pull request Aug 31, 2020
ret2libc added a commit to ret2libc/radare2 that referenced this pull request Aug 31, 2020
@karliss karliss mentioned this pull request Sep 10, 2020
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API New API requests, changes, removal command New commands requests, behaviour changes, removal r2r Regression tests RAnal RGraph waiting-for-review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants