# ".cmo" specification

**URL:** <https://discuss.ocaml.org/t/cmo-specification/4112>\
**Category:** Ecosystem\
**Tags:** vm, compiler\
**Created:** [July 18, 2019, 1:13pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112 "2019-07-18T13:13:14Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ImanHosseini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/imanhosseini/32/1699_2.png) [@ImanHosseini](https://discuss.ocaml.org/u/ImanHosseini)\
**Post date:** [July 18, 2019, 1:13pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/1 "2019-07-18T13:13:14Z")

</div>

Hi,

Is there any documentation specifying “.cmo” file format? I have been searching and finding very little documentation on how the OCaml VM and bytecode works, there are some rather old but hopefully still valid docs at cadmium:  
[http://cadmium.x9c.fr/distrib/caml-instructions.pdf](http://cadmium.x9c.fr/distrib/caml-instructions.pdf) -\> the ISA of the VM

But for the specification of the “.cmo” I have found nothing. The closest I got, was peeking into the source code of the compiler and tools but it’s not a great way.

---

<div class="post-metadata">

**Author:** ![ivg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ivg/32/103_2.png) [@ivg](https://discuss.ocaml.org/u/ivg)\
**Post date:** [July 18, 2019, 4:12pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/2 "2019-07-18T16:12:11Z")

</div>

A cmo file is having the [following layout](https://github.com/ocaml/ocaml/blob/ddb4cd93cbab788a38cbc44ea7e624a6320970a3/file_formats/cmo_format.mli#L44)

```auto
     magic number (Config.cmo_magic_number)
     absolute offset of compilation unit descriptor
     block of relocatable bytecode
     debugging information if any
     compilation unit descriptor 

```

where the compilation unit descriptor is a marshaled value of type `Cmo_format.compilation_unit`.

The rest of the files are described in the same folder: [https://github.com/ocaml/ocaml/tree/trunk/file\_formats](https://github.com/ocaml/ocaml/tree/trunk/file_formats)

---

<div class="post-metadata">

**Author:** ![ImanHosseini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/imanhosseini/32/1699_2.png) [@ImanHosseini](https://discuss.ocaml.org/u/ImanHosseini)\
**Post date:** [July 24, 2019, 2:45pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/3 "2019-07-24T14:45:37Z")

</div>

Thank you Ivan, this is a great starting point (this is the source I was talking about). But still I’m having a hard time disassembling a “.cmo” file. I have made a simple hello world example to play with: [https://github.com/ImanHosseini/CMODisas](https://github.com/ImanHosseini/CMODisas)  
Looking into the “.cmo” file in HexEditor:

 ![binary](https://us1.discourse-cdn.com/flex020/uploads/ocaml/original/2X/b/b4a81550e9618b59065e97b08abe757d419f2b4d.png)  
We see a magic number (weirdly “OCP-199O009” which I don’t know where it comes from) and then the offset of compilation unit as you said. After it we expect a block of bytecode but we are not getting it I guess? I don’t know what that 0x35 is, can’t be a valid opcode.  
So as per the cadmium links in CMODisas, there is a document with bytecode specs and how the data types work. Something missing is for example, how the code is actually laid out in memory: I’d imagine for each instruction the opcode is 1 byte, and then if there are operands, each operand comes after but again nowhere in the doc says how many bytes each operand can be and/or if there are any alignment constraints.  
Also the document regarding bytecode file format speaks of sections named “CODE”/“DATA”/… which are not existent here. [in the generated “.exe” file these exist at the very end of the file]

---

<div class="post-metadata">

**Author:** ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)\
**Post date:** [July 24, 2019, 3:45pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/4 "2019-07-24T15:45:54Z")

</div>

The “OCP-1999O009” magic number corresponds to OCamlPro’s version of the compiler (more sepcifically, 4.02.1+ocp1). There is no guarantee that it is compatible with mainstream bytecode, though in practice if you find a tool that works for mainstream 4.02.1 it should work here as well. I’m curious about how you came upon such a file and why you’re trying to disassemble it, though.

---

<div class="post-metadata">

**Author:** ![XVilka](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/xvilka/32/5334_2.png) [@XVilka](https://discuss.ocaml.org/u/XVilka)\
**Post date:** [July 24, 2019, 6:34pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/5 "2019-07-24T18:34:24Z")

</div>

You might want to add the OCaml bytecode support to [radare2](https://github.com/radare/radare2) reverse engineering framework, so you will have more features helping to disassemble it effectively.  
See the [Plugins - Disassembly](https://radare.gitbooks.io/radare2book/content/plugins/dev-asm.html) and [Plugins - Analysis](https://radare.gitbooks.io/radare2book/content/plugins/dev-anal.html) radare2 book chapters. Also feel free to drop me a private message in case of the questions. And of course, it has an OCaml bindings: [https://opam.ocaml.org/packages/radare2/](https://opam.ocaml.org/packages/radare2/)

---

<div class="post-metadata">

**Author:** ![ivg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ivg/32/103_2.png) [@ivg](https://discuss.ocaml.org/u/ivg)\
**Post date:** [July 26, 2019, 2:30pm UTC](https://discuss.ocaml.org/t/cmo-specification/4112/6 "2019-07-26T14:30:49Z")

</div>

> [@ImanHosseini](#):
>
> We see a magic number (weirdly “OCP-199O009” which I don’t know where it comes from) and then the offset of compilation unit as you said. After it we expect a block of bytecode but we are not getting it I guess?

The offset after the magic word is pointing to the compilation unit entry, which is written in OCaml Marshal format (parseable only with the OCaml `input_value` function). Once you read it, you can look into the `cu_pos` and `cu_codesize` parameters which will point you to the bytecode, e.g.,

```ocaml
let ic = open_in_bin filename in
  let len_magic_number = String.length cmo_magic_number in
  let magic_number = really_input_string ic len_magic_number in
  if magic_number = cmo_magic_number then begin
    let cu_pos = input_binary_int ic in
    seek_in ic cu_pos;
    let {cu_pos; cu_codesize} = (input_value ic : compilation_unit) in
    close_in ic;
    (* do the disassembling on the cu,cu_pos+cu_codesize region *) 
  end

```

Also, there is already an OCaml disassembler, see the [tools/dumpobj.ml](https://github.com/ocaml/ocaml/blob/trunk/tools/dumpobj.ml) file. It will read the code and even print the bytecode.
