Restore phandles from binary representations#151
Restore phandles from binary representations#151ukleinek wants to merge 8 commits intodgibson:mainfrom
Conversation
|
A possible followup improvement would be to restore phandles from |
|
Just a quick headsup: I found a dtbo file where my code crashes with |
|
OK, I think that's unrelated to my changes and just presents a situation to the decompiler that didn't happen before. Here is a reproducer: So I think some heuristic considers the property "tralala" an array of ints but that doesn't handle that it ends at offset 41 which is unaligned. |
dgibson
left a comment
There was a problem hiding this comment.
I think this is a great idea. The implementation looks mostly sound but there are a few minor issues that need addressing.
I think you do need to implement this. For one thing processing but |
|
Do you have an idea for the unaligned phandle problem? |
Sorry, I'm not sure exactly what problem you mean. |
I mean the crash reported in #151 (comment) with the follow up in the next comment. |
Ah, right, sorry. I think the basic problem is that previously the only case where we'd have phandle markers during decompile is with More specifically, it looks like |
845fb23 to
07f279e
Compare
|
This addresses the crash mentioned in #151 (comment) and a few suggestions by @dgibson (which I marked as resolved). Still missing is restoring of phandles from |
07f279e to
5c04a2d
Compare
|
OK, this got bigger now than I anticipated and also contains a few fixes, but I'm happy that I did it now and I can get it out of my head and happily use it. Quick demo: Decompiling this dtb with dtc 1.7.2 gives you: With the changes from this PR applied it gets: and if |
5c04a2d to
9827002
Compare
|
BTW, I didn't implement stripping out the |
dgibson
left a comment
There was a problem hiding this comment.
I've applied the first three patches, because they're sensible fixes independent of the rest of the series. I've made some comments on the next few, but I haven't completed a full review yet.
The topmost commit is also simple and orthogonal to the rest of the series. That one might be eligible for fast tracking, too. |
9827002 to
c21b18f
Compare
I split this into a separate PR, see #168. |
This fixes `dtc -I dts -O dts` to make the file a plugin if the source file is one. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
c21b18f to
3442d0b
Compare
|
I think I addressed all feedback. The only open discussion is if |
|
The first two patches looked fine and I was going to apply.. but the second one breaks a test case: It looks like the decompiled version is entirely missing the |
|
|
||
| if (*mi && (*mi)->offset == offset && is_type_marker((*mi)->type)) { | ||
| if (is_type_marker(type)) | ||
| return mi; |
There was a problem hiding this comment.
This avoids adding the marker if it would violate the "at most one type marker per offset" invariant. Which is fine, I guess, but you're essentially failing silently, which seems like it might lead to hard to debug problems.
There was a problem hiding this comment.
A helpful warning message is hard here because we don't know the affected property here. So would you prefer a warning message that is hard to understand à la: "Duplicate type marker at offset %u, type %d vs. type %d" offset, type, (*mi)->type? Or should I add a reference to the property to add_marker just for the purpose of the warning?
| } | ||
|
|
||
| if (*mi && (*mi)->offset == offset && type == (*mi)->type) | ||
| return mi; |
There was a problem hiding this comment.
Similar silent failure here, but this one is worse. It's valid to have several path references in a row, which will have the same offset (because they're zero-length before fixup). This logic will prevent you from adding a marker in that case.
There was a problem hiding this comment.
I don't understand that. A marker never has a length (see the definition of struct marker) and I don't see how there could be more than one REF_PATH marker at a single offset.
There was a problem hiding this comment.
Sorry, I was a bit unclear. Consider:
prop = &foo, &bar;
So we have two path references in a row. The first one will obviously have offset 0. But, before we actually expand &foo in fixup_path_references() we won't generate any data for the reference. That means the second reference will also have offset 0
| return &nm->next; | ||
| } | ||
|
|
||
| void property_add_marker(struct property *prop, |
There was a problem hiding this comment.
Is this true with add_marker in treesource.c?
There was a problem hiding this comment.
Both should be in livetree.c. They're helpers manipulating the "live" (pointer based, in-memory) version of the tree data structure.
This commit uncovers a problem that we already have since commit 915daad ("Start with empty local_fixups and fixups nodes"): I'll think about a fix. |
The fix is to fold the info contained in |
3442d0b to
4f025c1
Compare
I fixed that by sorting the respective commits before this change and expanded their commit logs to describe this detail. |
Typically the info contained in __local_fixups__ and __fixups__ is autogenerated from phandles used in the tree. However before commit 915daad ("Start with empty __local_fixups__ and __fixups__ nodes") compiling a dts that has both the __local_fixups__ and/or __fixups__ and phandles that result in entries in these nodes, the fixups were duplicated: $ cat test.dts /dts-v1/; /plugin/; / { important: node { property = <&somenode>, "string"; phandle = <0x01>; self = <&important>; }; __fixups__ { somenode = "/node:property:0"; }; __local_fixups__ { node { self = <0x00>; }; }; __symbols__ { important = "/node"; }; }; $ dtc -v Version: DTC 1.7.2 $ dtc -O dts test2.dts /dts-v1/; / { important: node { property = <&somenode>, "string"; phandle = <0x01>; self = <&important>; }; __fixups__ { somenode = "/node:property:0", "/node:property:0"; }; __local_fixups__ { node { self = <0x00>, <0x00>; }; }; __symbols__ { important = "/node"; }; }; Add a test that ensures this issue isn't reintroduced later. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
The add_marker() function is used to create a new marker and add it at the right spot to the relevant marker list. Use it in the add_string_markers() helper (which gets slightly quicker by it). Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
In the presence of (non-type) markers guess the type of each chunk between markers individually instead of only once for the whole property. Note that this only gets relevant with the next few commits that restore labels and phandles. Note further that this rework is necessary with these further changes, because phandle markers are currently not considered for type guessing and so a phandle at an offset that isn't a multiple of 4 triggers an assertion if the property was guessed to have type TYPE_UINT32. Now that guess_value_type() is only called for data chunks without markers, the function can be simplified a bit. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
If the input has a __symbols__ node, restore the named labels for the respective nodes. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
4f025c1 to
fab7c49
Compare
The __local_fixups__ node contains information about phandles. Parse it to improve the result when decompiling a device tree blob. Note that this is essential to do before the __local_fixups__ node is removed in generate_local_fixups_tree() because otherwise the information contained in that node is lost. Fixes: 915daad ("Start with empty __local_fixups__ and __fixups__ nodes") Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
The __fixups__ node contains information about labels. Parse its properties to create phandle markers which improve the resulting dts when decompiling a device tree blob. Note that this is essential to do before the __fixups__ node is removed in generate_fixups_tree() because otherwise the information contained in that node is lost. Fixes: 915daad ("Start with empty __local_fixups__ and __fixups__ nodes") Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
The need for the plugin flag is determined by the existence of __fixups__ or __local_fixups__. This is a bit simplifying because if __fixups__ or __local_fixups__ exist but don't have properties, the plugin flag isn't needed. But in practise the test should be good enough such that this corner case doesn't matter. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
fab7c49 to
64bbc33
Compare
|
There is one test failure when the top commit is missing because restoring phandles from |
Ouch, ok. I missed that nasty side effect of 915daad. Unfortunately I don't think the fix proposed in the latest version is quite sufficient. It's an important principle in dtc's design that it should generally be safe and lossless to convert dtb -> dts -> dtb. Likewise it should be "lossless" to convert dts -> dts, in the sense that going directly dts -> dtb and going dts -> dts -> dtb should result in the same output. This is exactly what those test cases are designed for. This is supposed to be true even if the input tree contains garbage. It needs the basic structure to be parseable, of course, but if the properties contain things that are semantically malformed, they should be passed through unchanged. 915daad broke that. Your latest series partially fixes this, but not completely: it will still simply delete entries it doesn't understand in the input tree. It might also re-order entries that it does understand. I can see two ways to fully fix this:
|
|
FTR: I took this patch set to the mailing list as I prefer this workflow after this PR got unwieldy. |
device trees generated with options
-@and-Lcontain information about the label names used originally and which values are phandle values. This information can be reused when compiling back to dts format to make the result much more human readable.Also dtdiff is adapted to make use of this to generate smaller diffs without hunks e.g. for a different phandle allocation.
This superseeds pull request #93.