Skip to content

objinfo: tell when the object file comes from a different OCaml version#463

Merged
gasche merged 3 commits intoocaml:trunkfrom
gasche:robust-ocamlobjinfo
Dec 3, 2019
Merged

objinfo: tell when the object file comes from a different OCaml version#463
gasche merged 3 commits intoocaml:trunkfrom
gasche:robust-ocamlobjinfo

Conversation

@gasche
Copy link
Copy Markdown
Member

@gasche gasche commented Feb 8, 2016

When passed an object file that comes from a different OCaml version,
objinfo will currently just detect that the magic number is not what
it expects, and claim it is not a valid file. This is irritating.

The current patch implements some more advanced handling of magic
number in a new Misc.Magic_number module, inspired by js_of_ocaml
Misc.MagicNumber module
https://github.com/ocsigen/js_of_ocaml/blob/151b811/compiler/util.cppo.ml#L277-L347
that lets us easily tell the difference between "not a valid magic number"
and "a valid magic number, but with another version".

The error message output by objinfo now looks like this:

$ ./objinfo ./ocamldep.cmo
File ./ocamldep.cmo
Wrong magic number:
this tool only supports object files produced by compiler version
    4.03.0+dev12-2015-11-20,
and this object file (cmo) seems to come from an older version.

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Feb 8, 2016

Once we have some logic in the compiler codebase that understand magic numbers, we can use it in other places than (ocaml)objinfo. In particular, when the compiler itself reads a compiled object file, it currently has the same irritating behaviour of not recognizing that object file from other OCaml versions are a bit more valid than random text files with the wrong extension, and we could easily fix that. Depending on the feedback on this PR, I may try to do this it as well.

There is no Changes entry for this one. I'm not quite sure where I should put it, and if I understand correctly objinfo is not currently installed along with the compiler so it's arguably not an user-facing change that needs to be documented.

@gasche gasche force-pushed the robust-ocamlobjinfo branch from cc404a3 to 4abca28 Compare February 8, 2016 21:16
@damiendoligez
Copy link
Copy Markdown
Member

Look for read_cmi in typing/cmi_format.ml.

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Feb 9, 2016

Oh, I hadn't seen that the cmi reading part had this same logic. But I think this could be generalized to other areas of the compiler (all those that read object files), for example driver/pparse.ml (I'm not familiar with the workflow of the people passing binary AST files, but I would assume that version mismatches do happen), asmcomp/compilenv, bytecomp/byte{link,librarian}, dynlink, and toplevel/topdirs (load directive).

@damiendoligez
Copy link
Copy Markdown
Member

I agree it's a good idea to generalize it, especially if you share the implementation.

@whitequark
Copy link
Copy Markdown
Member

It is installed:

$ which ocamlobjinfo
/home/whitequark/.opam/4.02.3/bin/ocamlobjinfo

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Feb 9, 2016

So I started working a bit more on this PR, but:

I'll thus wait for the release branching.

@damiendoligez damiendoligez modified the milestones: long-term, 4.04-or-later Feb 10, 2016
@damiendoligez damiendoligez removed this from the 4.04 milestone Aug 2, 2016
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Oct 28, 2016

I had forgotten about this PR; I would like to work on it more sometime after the release.

@gasche gasche added this to the 4.05-or-later milestone Oct 28, 2016
@mshinwell
Copy link
Copy Markdown
Contributor

@gasche Would you have time to bring this up-to-date?

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 27, 2016

@mshinwell thanks for your hard triaging work today :-)

@gasche gasche force-pushed the robust-ocamlobjinfo branch 3 times, most recently from ac96f66 to 97fcd5f Compare December 27, 2016 23:17
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 27, 2016

I rebased my patch against trunk. I should also look at Damien's remark on using in in typing/Cmi_format.read_cmi and other places; this is nice but it also increases the invasiveness of the patch a bit.

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 27, 2016

There seems to be a minor double-close_in bug in the current read_cmi: it is my impression that the Error exception path results in ic being closed twice.

@gasche gasche force-pushed the robust-ocamlobjinfo branch 2 times, most recently from 2212e4c to 67444ec Compare December 28, 2016 05:22
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 28, 2016

So I tried to use the new functions in a few places in the compiler -- namely typing/Cmi_format.read_cmi and asmcomp/Compilenv.read_unit_info. I would be interested in feedback before trying to convert the other use sites -- ideally, I would like an approval to merge in principle.

A difficulty that made this quite more difficult than I expected is that all use-sites have already their own error-reporting logic, and that it is not trivial to integrate the Magic_number explicit approach without either changing the error-reporting logic or ending up with code that is roughly as long as what was before (because the concision gain is lost in re-routing exceptions of one kind into another). I had to do several iterations of convenience functions in the Magic_number module to end up with something worthwhile.

Changing the error-reporting logic results in better-quality error messages (which was the goal in the first place), but it requires changing the exception types for the affected modules. We have to think about this, because it means that it can break compiler-libs-using code. Luckily, the changes made will break programs at compile-time, not runtime.

For each of the two updated sites I thus did two iterations:

  • the first one is to just use the functions of Magic_number, with no changes to the error reporting logic:
    read_cmi is updated in 3f36680, and read_unit_info in 7eeb8f2
  • the second one changes the error-reporting logic to provide consistent information among all Magic_number users: read_cmi is updated in 2212e4c (besides regularity we do not gain much as it already supported older/newer recommendations), read_unit_info is updated in 47012bb.

@damiendoligez, would have a look and give your opinion on whether you think these changes are worthwhile? If we consider that the improved error messages are not worth changing the error type declarations, I can easily roll-back to the "first iteration" approach.

@gasche gasche force-pushed the robust-ocamlobjinfo branch 4 times, most recently from 184e070 to 51d6b09 Compare December 28, 2016 08:02
Copy link
Copy Markdown
Contributor

@Drup Drup left a comment

Choose a reason for hiding this comment

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

I like the new API quite a lot. As someone who hacked into cmi files at some point. this API would be much easier to tinker with.

Something that would make it even better (for me) would be to have a function similar to check_current but of type kind list -> info -> (kind, unexpected_error) result, which would try to check for several magic kind, and return the one we got.

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Nov 14, 2019

I just rebased the PR on top of trunk. I also redesigned the API of the Magic_number module, and (following @shindere's comments on feature bloat) restricted the scope of the PR to improving objinfo.ml only. I also rebased the changes to Compilenv and Cmi_format to use the new module, to test the new API, but I will keep them for a future PR.

In his review @Drup had made criticism of the API, which relied too much on exceptions. I used exceptions to make caller-site changes less invasive. The new API is written without any exception, purely using the result type. I think the new API is sensibly better, but adapting the callsites is now more work. (I buy @Drup's argument that we don't read magic numbers very often in the compiler codebase and can afford the extra verbosity in exchange for more user-friendly failure messages.) In general I went in the direction of making the modified code as good as I could, even if it meant restructuring the code rather than just replacing a couple function calls; the changes to objinfo.ml are also a refactoring.

@Drup, would you be willing to give another round of review to the PR?

@gasche gasche force-pushed the robust-ocamlobjinfo branch from 80addc3 to 071623c Compare November 14, 2019 21:49
@gasche gasche closed this Nov 15, 2019
@gasche gasche reopened this Nov 15, 2019
@gasche gasche closed this Nov 15, 2019
@gasche gasche reopened this Nov 15, 2019
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Nov 15, 2019

(I managed to convince Travis to indeed check this PR.)

Copy link
Copy Markdown
Contributor

@Drup Drup left a comment

Choose a reason for hiding this comment

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

Looks good! As an added benefit, objinfo now understands serialized ASTs, which is nice. All my comments are minor. travis also spotted a few long-lines:

./tools/objinfo.ml:334.81: [long-line] line is over 80 columns
./utils/misc.ml:996.81: [long-line] line is over 80 columns

This was referenced Nov 28, 2019
@gasche gasche force-pushed the robust-ocamlobjinfo branch from 071623c to bd91019 Compare December 2, 2019 21:58
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 2, 2019

I rebased the PR to address @Drup's last batch of comments.

@gasche gasche force-pushed the robust-ocamlobjinfo branch from bd91019 to 443a9de Compare December 2, 2019 23:05
This module was originally inspired by js_of_ocaml Misc.MagicNumber module
https://github.com/ocsigen/js_of_ocaml/blob/151b811/compiler/util.cppo.ml#L277-L347

It provides parsing and validation function for magic numbers, that
can tell the difference between "not a valid magic number" and "a
valid magic number, but with another version", and print user-friendly
user messages about it.

It does not contain any knowledge for where to find the magic number
in an OCaml file (this depends on the file format); the parsing
function should be called with an input channel already at the right
position for whichever format is expect.
When passed an object file that comes from a different OCaml version,
objinfo will currently just detect that the magic number is not what
it expects, and claim it is not a valid file. This is irritating.

The error message output by objinfo now looks like this:

    File /home/gasche/.opam/4.08.0/lib/astring/astring.cmi
    Wrong magic number:
    this tool only supports object files produced by compiler version
    	4.11.0+dev0-2019-10-18
    This seems to be a compiled interface file (cmi) for an older version of OCaml.
@gasche gasche merged commit f572295 into ocaml:trunk Dec 3, 2019
@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 3, 2019

I went ahead and merged in trunk. Thanks again @damiendoligez and @Drup for the reviews.

This story arc is not yet complete; only ocamlobjinfo uses the new machinery as of now, all other parts of the compiler that read magic numbers could be improved by adopting it as well. I (and maybe others as well?) will send extra PRs over time.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 5, 2019

The objinfo test is now broken on Wygwin32.

File question.cmxs
Error: size of section .data unknown
Unable to read info on file question.cmxs

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 5, 2019

And by the way, this also affects the 4.10 branch.

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 5, 2019

Do you think that it is related to this PR? This PR was merged two days ago, in trunk only (I think? no reason to cherry-pick to 4.10), so I don't think it could explain a broken test on 4.10.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 5, 2019 via email

@gasche
Copy link
Copy Markdown
Member Author

gasche commented Dec 5, 2019

(I think that today, being a general strike day in France, is an excellent day to not investigate an obscure Cygin32 failure (don't count on me!), but I'm going to humor you and ask the first question that comes to mind.) Do we know when the failures started to happen?

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 5, 2019 via email

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 5, 2019

I confirm the hypothesis mentionned above.

objinfo_helper can not find the caml_header_plugin symbol for several
reasons. I have a dirty but working fix. Still discussing off-line to come
up with a cleaner one, will open a new PR ASAP. Sorry for the false positive
here.

EduardoRFS pushed a commit to esy-ocaml/ocaml that referenced this pull request May 17, 2021
Minor GC: restrict global roots scanning to one domain
mshinwell added a commit to mshinwell/ocaml that referenced this pull request Jun 2, 2021
…currences-diff

Speed up Name_occurrences.diff
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants