# Stripping binaries

**URL:** <https://discuss.ocaml.org/t/stripping-binaries/2308>\
**Category:** Community\
**Created:** [July 18, 2018, 1:36pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308 "2018-07-18T13:36:51Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)\
**Post date:** [July 18, 2018, 1:36pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/1 "2018-07-18T13:36:51Z")

</div>

Hi, I’d like to get recommendations from the community regarding stripping binaries. My use case is a program (for Unix and Mac OS X), built with dune/ocamlopt, the source code of which does not rely on dynamic linking nor on the FFI. However it relies on several opam packages and on the Unix module too, so I wondered whether I should be wary of something here. Are there good practices to rely upon? Or can I just run the standard `strip` command on my binary?

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [July 18, 2018, 4:26pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/2 "2018-07-18T16:26:36Z")

</div>

Stripping binaries was very important back in the days when disk space was very limited. These days, I think it’s an antipattern. Why do you want to do it?

---

<div class="post-metadata">

**Author:** ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)\
**Post date:** [July 18, 2018, 7:58pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/3 "2018-07-18T19:58:53Z")

</div>

Because disk space **is** limited for some people, for socio-economical or regulatory reasons for instance. But please let’s not debate on this topic here; I’m only asking for technical advice.

---

<div class="post-metadata">

**Author:** ![hcarty](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hcarty/32/1824_2.png) [@hcarty](https://discuss.ocaml.org/u/hcarty)\
**Post date:** [July 18, 2018, 10:57pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/4 "2018-07-18T22:57:19Z")

</div>

I haven’t tried to strip OCaml binaries recently, but the last time I tried everything was fine with `ocamlopt`-compiled binaries. They should act more or less like a stripped binary compiled from C.

---

<div class="post-metadata">

**Author:** ![hannes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hannes/32/2302_2.png) [@hannes](https://discuss.ocaml.org/u/hannes)\
**Post date:** [July 19, 2018, 9:10am UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/5 "2018-07-19T09:10:49Z")

</div>

> [@grayswandyr](#):
>
> Or can I just run the standard `strip` command on my binary?

This is what I do. Sometimes I need to transport binaries over the network, and `strip` reduces roughly 33% of the binary size.

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [July 19, 2018, 9:38am UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/6 "2018-07-19T09:38:33Z")

</div>

In 2016 I did a quick benchmark comparing binary sizes and start-up time of a hello-world OCaml program. Compared the original, `strip`, as well as `upx` tool which also archives the executable to reduce the size even more. I’ve also compared a bare-bones hello-world with the one where Jane Street Core was linked.

Here’s what I’ve got:

| | Original | `strip` | `upx --best` |
| --- | --- | --- | --- |
| OCaml | 201K, 12ms | 113K, 12ms | 64K, 14ms |
| OCaml+Core | 14M, 35ms | 8.1M, 35ms | 2.3M, 75ms |

> <https://twitter.com/keleshev/status/725965940899368960>

---

<div class="post-metadata">

**Author:** ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)\
**Post date:** [July 19, 2018, 10:58am UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/7 "2018-07-19T10:58:52Z")

</div>

Oh yeah even better, I had forgotten about this one. Unfortunately, my upx’ed program core dumps when launched?! The `strip`ped program runs fine OTOH.

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [July 21, 2018, 10:33am UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/8 "2018-07-21T10:33:43Z")

</div>

Binary sizes of 14M vs 201k are absurd. Can someone explain how linking in OCaml works? Does linking always include all modules independent whether they are used or not? Or is Core so entangled that it is impossible to exclude certain modules?

---

<div class="post-metadata">

**Author:** ![Yaron\_Minsky](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yaron_minsky/32/11_2.png) [@Yaron\_Minsky](https://discuss.ocaml.org/u/Yaron_Minsky)\
**Post date:** [July 21, 2018, 12:16pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/9 "2018-07-21T12:16:16Z")

</div>

The key issue here is that OCaml overapproximates dependencies at the module level, which means that lots of functionality that isn’t use can nonetheless be linked in. There are some plans for better native dead-code elimination, but there’s nothing usable for that yet.

It’s worth noting that Base is already considerably lighter. My experiments show:

- Base: 3.9M
- Core\_kernel: 8.5M
- Core: 9.9M

In any case, as a general matter, if you don’t need the extra functionality of Core\_kernel or Core, I think Base is considerably preferable, both because it’s lighter, and because it enforces some better idioms, like hiding polymorphic comparison by default, and encouraging better more modular idioms for building things like comparison-based container types.

There are some changes coming to Base in the next release that should make it yet lighter, though I’m not sure how far those will go.

y

---

<div class="post-metadata">

**Author:** ![Yaron\_Minsky](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yaron_minsky/32/11_2.png) [@Yaron\_Minsky](https://discuss.ocaml.org/u/Yaron_Minsky)\
**Post date:** [July 21, 2018, 12:17pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/10 "2018-07-21T12:17:16Z")

</div>

To be clear, though: OCaml doesn’t include any module you don’t reference, but anything you do reference, and anything transitively referenced by the modules you directly reference, will be included, whether or not you ever touch that functionality in your code.

y

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [July 21, 2018, 12:55pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/11 "2018-07-21T12:55:52Z")

</div>

> [@Yaron\_Minsky](#):
>
> To be clear, though: OCaml doesn’t include any module you don’t reference, but anything you do reference, and anything transitively referenced by the modules you directly reference, will be included, whether or not you ever touch that functionality in your code.

That’s unfortunate. There’s no good way to trace out what’s live and what isn’t as things stand?

---

<div class="post-metadata">

**Author:** ![samoht](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/samoht/32/81_2.png) [@samoht](https://discuss.ocaml.org/u/samoht)\
**Post date:** [July 21, 2018, 1:16pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/12 "2018-07-21T13:16:46Z")

</div>

Yes it’s possible: see [https://github.com/ocaml/ocaml/pull/608](https://github.com/ocaml/ocaml/pull/608)

---

<div class="post-metadata">

**Author:** ![xavierleroy](https://avatars.discourse-cdn.com/v4/letter/x/a9adbd/32.png) [@xavierleroy](https://discuss.ocaml.org/u/xavierleroy)\
**Post date:** [July 21, 2018, 5:16pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/13 "2018-07-21T17:16:38Z")

</div>

The only case where `strip` should not be used is for bytecode executables produced by `ocamlc` in `-custom` mode. Tehse are hybrid files composed of an ELF executable followed by OCaml bytecode, which confuses the `strip` command. But `-custom` mode is rarely used nowadays.

If your executable is produced by `ocamlopt`, nothing bad will happen if you run `strip` on it.

---

<div class="post-metadata">

**Author:** ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)\
**Post date:** [July 21, 2018, 8:14pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/14 "2018-07-21T20:14:03Z")

</div>

Thanks, good to know.

---

<div class="post-metadata">

**Author:** ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)\
**Post date:** [July 21, 2018, 8:15pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/15 "2018-07-21T20:15:02Z")

</div>

This looks rather compelling!

---

<div class="post-metadata">

**Author:** ![cfcs](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cfcs/32/833_2.png) [@cfcs](https://discuss.ocaml.org/u/cfcs)\
**Post date:** [August 4, 2018, 2:56pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/16 "2018-08-04T14:56:23Z")

</div>

Just to chime in with a security angle: Stripped binaries also provide fewer useful gadgets for exploit writers, and can have a significant impact on the viability of ROP exploits, especially when the would-be stripped sections are mapped executable (? like if you’re using mirage on `solo5`, and maybe also the `-xen` target ?).

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [August 4, 2018, 8:14pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/17 "2018-08-04T20:14:19Z")

</div>

Stripped sections aren’t generally marked executable. (I am not sure they’re ever marked executable – if they were, how could you strip them? Indeed, if you can load it, it isn’t stripped.)

On your “especially”, if a stripped section isn’t loaded, how could it possibly be used for things like ROP exploits?

---

<div class="post-metadata">

**Author:** ![cfcs](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cfcs/32/833_2.png) [@cfcs](https://discuss.ocaml.org/u/cfcs)\
**Post date:** [August 5, 2018, 6:32pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/18 "2018-08-05T18:32:04Z")

</div>

No, the sections that are affected by stripping are not _generally_ (highly dependent on which parameters you pass to `strip`, for instnace whether you strip relocations or not) **marked** as executable.  
That’s why I gave an example of a case where the protection markings are not respected (`solo5`), and with my question marks I intended to convey that I don’t know how `mirage-xen` maps the sections, but I have feeling it might be the same there.

Re: my “especially”: Sorry if I was bit unclear: I’d argue that the impact of `strip`'ing is usually beneficial to security, so a stripped section (that’s not loaded) is one less section to be used in ROP attacks (when the section is mapped as executable), or data-only attacks (when the section is not mapped as executable).  
Essentially the fewer bytes or sections mapped R/R+W/R+E/R+W+E in your process space, the better.

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [August 5, 2018, 6:33pm UTC](https://discuss.ocaml.org/t/stripping-binaries/2308/19 "2018-08-05T18:33:47Z")

</div>

> [@cfcs](#):
>
> I’d argue that the impact of `strip` 'ing is usually beneficial to security,

I see no evidence for that whatsoever. Stripped sections are not loaded. If a stripped section needs to be loaded, then the executable will stop working. If it isn’t loaded, ROP attacks can’t target it in the first place. If it is loaded, that’s probably because the binary needs it or it won’t work.
