ergrelet / resym

Cross-platform tool that allows browsing and extracting C and C++ type declarations from PDB files.
https://ergrelet.github.io/resym/
Apache License 2.0
292 stars 20 forks source link

Reconstruct dependencies in a compiler-friendly way #6

Closed ergrelet closed 7 months ago

ergrelet commented 2 years ago

Current output has a high chance of being uncompilable.

0xeb commented 1 year ago

Correct. The exported types (into a header file) should be first sorted from the ones with least dependencies to the ones with most dependencies. Then emitted. Or just forward declare everything first, then no matter what's the order (an easier fix).

ergrelet commented 1 year ago

Exactly. I was leaning towards the second solution honestly, mainly because it can be implemented with a simple O(n) algorithm, whereas the first solution would be more complex and computation heavy.

The two downsides that I see regarding the second solution is that:

But I don't think it's worth complexifying the implementation just for these two reasons.

0xeb commented 1 year ago

Sorry, I did not get you fully, so what did you decide? """But I don't think it's worth complexifying the implementation just for these two reasons."""

So, here's the issue:

If we export the type, then one has to spend a lot of time making sure the structures are defined in the right order and often introduce forward declarations. 1) The solution is to emit the types based on dependency order and if necessary, do some forward declarations. 2) Another solution is to blindly forward declare everything

Now, I see about polluting the view...but when it comes just to browsing graphically (not exporting) then do nothing. Only on export, take one of approach (1) or (2).

Otherwise, it is okay...users will have to deal with the issue after exporting.

ergrelet commented 1 year ago

Yes I'm sorry, that wasn't clear, and I realize I assumed something that was untrue in my previous message. So, starting fresh (ignoring what I previously said), I believe we have to do what you describe in (1) if we want to have a compilable output in all cases.

As I understand it, if we do (2), something like this wouldn't compile, even with forward declarations:

struct A;
struct B;

struct A {
    B field_a;
};

struct B {
    int field_b;
};

Or maybe I misunderstood what you meant in (2).

Now about exporting. I assume that what you mean by exporting is the action of saving the reconstructed output to a file, from the GUI? If so, currently resym generates the same output everywhere (GUI, CLI and when exporting to a file from the GUI). I'd prefer to keep it that way if we can avoid any noticeable performance impact in GUI mode. Especially for types with a reasonable number of dependencies (~10,000 let's say).
If it's too impactful, I imagine we could do as you say and have separate outputs. Or maybe we could allow users to choose the way to output dependencies with a "dependency ordering" setting (e.g., NoOrder, CompilerOrder).

I hope I was clearer this time 😅

0xeb commented 1 year ago

Yes, thank you. Much clearer now.

IMHO, if we keep the UI / Console output as is (no reordering) then no clutter (due to us reordering / forward decl). Why re-order / show forward decls. from the UIs (console, GUI, etc.)? no need to clutter.

Only when we export we should aim for correctness (that's the point of it; otherwise why would I want to export if not to use).

Yes, (2) is not going to work in all cases. We have to do it correct as in (1).

0xeb commented 1 year ago

If I know Rust, I would contributed btw ;)

ergrelet commented 1 year ago

Yes, thank you. Much clearer now.

IMHO, if we keep the UI / Console output as is (no reordering) then no clutter (due to us reordering / forward decl). Why re-order / show forward decls. from the UIs (console, GUI, etc.)? no need to clutter.

Only when we export we should aim for correctness (that's the point of it; otherwise why would I want to export if not to use).

Yes, (2) is not going to work in all cases. We have to do it correct as in (1).

Right, that makes sense. I'll see how I can make that work in an intuitive way 👍

Disclaimer: it might take some time until I find some spare time to work on open issues, but I'm not forgetting them! This feature in particular is a long needed one.

If I know Rust, I would contributed btw ;)

Ah no worries, thanks for contributing by discussing at least! I appreciate it 😊

0xeb commented 1 year ago

I gave you a shoutout here: https://www.youtube.com/watch?v=mN9LopGgkjk @ ~7:20 minutes mark

ergrelet commented 1 year ago

Oh thanks a lot! That's motivating 🙏 Very cool content by the way, thanks for your videos 👍

ergrelet commented 7 months ago

Well it seems that it could be implemented with a low performance impact so all outputs are reconstructed in a compiler-friendly way when dependency reconstruction is enabled!