Compare commits
No commits in common. "main" and "gh-pages" have entirely different histories.
17 changed files with 808 additions and 381 deletions
16
CHANGES.md
16
CHANGES.md
|
@ -1,16 +0,0 @@
|
|||
## v0.3.0 (2022-01-28)
|
||||
|
||||
* Exceptions from Owee are caught in `query_abi` and `query_manifest`
|
||||
|
||||
## v0.2.0 (2021-12-16)
|
||||
|
||||
* Rename binary from solo5-elftool to osolo5-elftool so it can co-exist with
|
||||
the C binary
|
||||
* Implement `query_abi` and `osolo5-elftool query-abi`
|
||||
* Return a result error instead of an assertion exception on unknown manifest
|
||||
entry types
|
||||
* Remove noop tests
|
||||
|
||||
## v0.1.0 (2021-12-15)
|
||||
|
||||
* Initial public release
|
23
LICENSE.md
23
LICENSE.md
|
@ -1,23 +0,0 @@
|
|||
Copyright (c) 2021, Reynir Björnsson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
0
README
Normal file
0
README
Normal file
|
@ -1,8 +0,0 @@
|
|||
## Solo5-elftool - OCaml Solo5 elftool for querying solo5 manifests
|
||||
|
||||
Solo5 embeds a manifest of which devices a unikernel expects.
|
||||
Solo5-elftool can be used to read and inspect this manifest.
|
||||
|
||||
One advantage over calling out to Solo5's `solo5-elftool` is that a user of the library can read the manifest from an ELF executable held in memory; no need to write the executable to disk first!
|
||||
|
||||
|
4
bin/dune
4
bin/dune
|
@ -1,4 +0,0 @@
|
|||
(executable
|
||||
(public_name osolo5-elftool)
|
||||
(name main)
|
||||
(libraries solo5-elftool owee cstruct cmdliner))
|
37
bin/main.ml
37
bin/main.ml
|
@ -1,37 +0,0 @@
|
|||
let query_manifest file =
|
||||
Owee_buf.map_binary file
|
||||
|> Solo5_elftool.query_manifest
|
||||
|> Result.iter (fun mft ->
|
||||
Fmt.pr "%a\n" Solo5_elftool.pp_mft mft)
|
||||
|
||||
let query_abi file =
|
||||
Owee_buf.map_binary file
|
||||
|> Solo5_elftool.query_abi
|
||||
|> Result.iter (Fmt.pr "%a\n" Solo5_elftool.pp_abi)
|
||||
|
||||
let file =
|
||||
let doc = "Solo5 executable" in
|
||||
Cmdliner.Arg.(required & pos 0 (some file) None &
|
||||
info ~doc ~docv:"EXECUTABLE" [])
|
||||
|
||||
let query_manifest_cmd =
|
||||
let doc = "query solo5 manifest" in
|
||||
Cmdliner.Term.(
|
||||
pure query_manifest $ file,
|
||||
info ~doc "query-manifest")
|
||||
|
||||
let query_abi_cmd =
|
||||
let doc = "query solo5 abi" in
|
||||
Cmdliner.Term.(
|
||||
pure query_abi $ file,
|
||||
info ~doc "query-abi")
|
||||
|
||||
let default_cmd =
|
||||
Cmdliner.Term.(
|
||||
ret (pure (fun man_format -> `Help (man_format, None)) $ man_format),
|
||||
info "osolo5-elftool")
|
||||
|
||||
let () =
|
||||
ignore (Cmdliner.Term.eval_choice
|
||||
default_cmd
|
||||
[query_manifest_cmd; query_abi_cmd])
|
2
doc/highlight.pack.js
Normal file
2
doc/highlight.pack.js
Normal file
File diff suppressed because one or more lines are too long
19
doc/index.html
Normal file
19
doc/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>index</title>
|
||||
<link rel="stylesheet" href="./odoc.css"/>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
|
||||
</head>
|
||||
<body>
|
||||
<main class="content">
|
||||
<div class="by-name">
|
||||
<h2>OCaml package documentation</h2>
|
||||
<ol>
|
||||
<li><a href="solo5-elftool/index.html">solo5-elftool</a> <span class="version">0.3.1</span></li>
|
||||
</ol>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
783
doc/odoc.css
Normal file
783
doc/odoc.css
Normal file
|
@ -0,0 +1,783 @@
|
|||
@charset "UTF-8";
|
||||
/* Copyright (c) 2016 The odoc contributors. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file.
|
||||
odoc 2.1.0 */
|
||||
|
||||
/* Fonts */
|
||||
@import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500');
|
||||
@import url('https://fonts.googleapis.com/css?family=Noticia+Text:400,400i,700');
|
||||
@import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,500,500i,600,600i,700,700i');
|
||||
|
||||
:root,
|
||||
.light:root {
|
||||
--main-background: #FFFFFF;
|
||||
|
||||
--color: #333333;
|
||||
--link-color: #2C94BD;
|
||||
--anchor-hover: #555;
|
||||
--anchor-color: #d5d5d5;
|
||||
--xref-shadow: #cc6666;
|
||||
--header-shadow: #ddd;
|
||||
--by-name-version-color: #aaa;
|
||||
--by-name-nav-link-color: #222;
|
||||
--target-background: rgba(187, 239, 253, 0.3);
|
||||
--target-shadow: rgba(187, 239, 253, 0.8);
|
||||
--pre-border-color: #eee;
|
||||
--code-background: #f6f8fa;
|
||||
|
||||
--li-code-background: #f6f8fa;
|
||||
--li-code-color: #0d2b3e;
|
||||
--toc-color: #1F2D3D;
|
||||
--toc-before-color: #777;
|
||||
--toc-background: #f6f8fa;
|
||||
--toc-list-border: #ccc;
|
||||
|
||||
--spec-summary-border-color: #5c9cf5;
|
||||
--spec-summary-background: var(--code-background);
|
||||
--spec-summary-hover-background: #ebeff2;
|
||||
--spec-details-after-background: rgba(0, 4, 15, 0.05);
|
||||
--spec-details-after-shadow: rgba(204, 204, 204, 0.53);
|
||||
}
|
||||
|
||||
.dark:root {
|
||||
--main-background: #202020;
|
||||
--code-background: #222;
|
||||
--line-numbers-background: rgba(0, 0, 0, 0.125);
|
||||
--navbar-background: #202020;
|
||||
|
||||
--color: #bebebe;
|
||||
--dirname-color: #666;
|
||||
--underline-color: #444;
|
||||
--visited-color: #002800;
|
||||
--visited-number-color: #252;
|
||||
--unvisited-color: #380000;
|
||||
--unvisited-number-color: #622;
|
||||
--somevisited-color: #303000;
|
||||
--highlight-color: #303e3f;
|
||||
--line-number-color: rgba(230, 230, 230, 0.3);
|
||||
--unvisited-margin-color: #622;
|
||||
--border: #333;
|
||||
--navbar-border: #333;
|
||||
--code-color: #ccc;
|
||||
|
||||
--li-code-background: #373737;
|
||||
--li-code-color: #999;
|
||||
--toc-color: #777;
|
||||
--toc-background: #252525;
|
||||
|
||||
--hljs-link: #999;
|
||||
--hljs-keyword: #cda869;
|
||||
--hljs-regexp: #f9ee98;
|
||||
--hljs-title: #dcdcaa;
|
||||
--hljs-type: #ac885b;
|
||||
--hljs-meta: #82aaff;
|
||||
--hljs-variable: #cf6a4c;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--main-background: #202020;
|
||||
--code-background: #333;
|
||||
--line-numbers-background: rgba(0, 0, 0, 0.125);
|
||||
--navbar-background: #202020;
|
||||
|
||||
--meter-unvisited-color: #622;
|
||||
--meter-visited-color: #252;
|
||||
--meter-separator-color: black;
|
||||
|
||||
--color: #bebebe;
|
||||
--dirname-color: #666;
|
||||
--underline-color: #444;
|
||||
--visited-color: #002800;
|
||||
--visited-number-color: #252;
|
||||
--unvisited-color: #380000;
|
||||
--unvisited-number-color: #622;
|
||||
--somevisited-color: #303000;
|
||||
--highlight-color: #303e3f;
|
||||
--line-number-color: rgba(230, 230, 230, 0.3);
|
||||
--unvisited-margin-color: #622;
|
||||
--border: #333;
|
||||
--navbar-border: #333;
|
||||
--code-color: #ccc;
|
||||
--by-name-nav-link-color: var(--color);
|
||||
|
||||
--li-code-background: #373737;
|
||||
--li-code-color: #999;
|
||||
--toc-color: #777;
|
||||
--toc-before-color: #777;
|
||||
--toc-background: #252525;
|
||||
--toc-list-border: #ccc;
|
||||
--spec-summary-hover-background: #ebeff2;
|
||||
--spec-details-after-background: rgba(0, 4, 15, 0.05);
|
||||
--spec-details-after-shadow: rgba(204, 204, 204, 0.53);
|
||||
|
||||
--hljs-link: #999;
|
||||
--hljs-keyword: #cda869;
|
||||
--hljs-regexp: #f9ee98;
|
||||
--hljs-title: #dcdcaa;
|
||||
--hljs-type: #ac885b;
|
||||
--hljs-meta: #82aaff;
|
||||
--hljs-variable: #cf6a4c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset a few things. */
|
||||
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
body {
|
||||
text-align: left;
|
||||
background: #FFFFFF;
|
||||
color: var(--color);
|
||||
background-color: var(--main-background);
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 100ex;
|
||||
margin-left: calc(10vw + 20ex);
|
||||
margin-right: 4ex;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 50px;
|
||||
font-family: "Noticia Text", Georgia, serif;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
nav {
|
||||
font-family: "Fira Sans", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Basic markup elements */
|
||||
|
||||
b, strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
em, i em.odd{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
em.odd, i em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
sup {
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
sub {
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
sup, sub {
|
||||
font-size: 12px;
|
||||
line-height: 0;
|
||||
margin-left: 0.2ex;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style-position: outside
|
||||
}
|
||||
|
||||
ul>li {
|
||||
margin-left: 22px;
|
||||
}
|
||||
|
||||
ol>li {
|
||||
margin-left: 27.2px;
|
||||
}
|
||||
|
||||
li>*:first-child {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
/* Text alignements, this should be forbidden. */
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Links and anchors */
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
box-shadow: 0 1px 0 0 var(--link-color);
|
||||
}
|
||||
|
||||
/* Linked highlight */
|
||||
*:target {
|
||||
background-color: var(--target-background) !important;
|
||||
box-shadow: 0 0px 0 1px var(--target-shadow) !important;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
*:hover > a.anchor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
a.anchor:before {
|
||||
content: "#";
|
||||
}
|
||||
|
||||
a.anchor:hover {
|
||||
box-shadow: none;
|
||||
text-decoration: none;
|
||||
color: var(--anchor-hover);
|
||||
}
|
||||
|
||||
a.anchor {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
/* top: 0px; */
|
||||
/* margin-left: -3ex; */
|
||||
margin-left: -1.3em;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
padding-right: 0.4em;
|
||||
padding-left: 0.4em;
|
||||
/* To remain selectable */
|
||||
color: var(--anchor-color);
|
||||
}
|
||||
|
||||
.spec > a.anchor {
|
||||
margin-left: -2.3em;
|
||||
padding-right: 0.9em;
|
||||
}
|
||||
|
||||
.xref-unresolved {
|
||||
color: #2C94BD;
|
||||
}
|
||||
.xref-unresolved:hover {
|
||||
box-shadow: 0 1px 0 0 var(--xref-shadow);
|
||||
}
|
||||
|
||||
/* Section and document divisions.
|
||||
Until at least 4.03 many of the modules of the stdlib start at .h7,
|
||||
we restart the sequence there like h2 */
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h7, .h8, .h9, .h10 {
|
||||
font-family: "Fira Sans", Helvetica, Arial, sans-serif;
|
||||
font-weight: 400;
|
||||
padding-top: 0.1em;
|
||||
line-height: 1.2;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 2.441em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 1.953em;
|
||||
box-shadow: 0 1px 0 0 var(--header-shadow);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.563em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
small, .font_small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
h1 code, h1 tt {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
h2 code, h2 tt {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
h3 code, h3 tt {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
h3 code, h3 tt {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.12em;
|
||||
}
|
||||
|
||||
/* Comment delimiters, hidden but accessible to screen readers and
|
||||
selected for copy/pasting */
|
||||
|
||||
/* Taken from bootstrap */
|
||||
/* See also https://stackoverflow.com/a/27769435/4220738 */
|
||||
.comment-delim {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Preformatted and code */
|
||||
|
||||
tt, code, pre {
|
||||
font-family: "Fira Mono", courier;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0.1em;
|
||||
border: 1px solid var(--pre-border-color);
|
||||
border-radius: 5px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p code,
|
||||
li code {
|
||||
background-color: var(--li-code-background);
|
||||
color: var(--li-code-color);
|
||||
border-radius: 3px;
|
||||
padding: 0 0.3ex;
|
||||
}
|
||||
|
||||
p a > code {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Code blocks (e.g. Examples) */
|
||||
|
||||
pre code {
|
||||
font-size: 0.893rem;
|
||||
}
|
||||
|
||||
/* Code lexemes */
|
||||
|
||||
.keyword {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.arrow { white-space: nowrap }
|
||||
|
||||
/* Module member specification */
|
||||
|
||||
.spec {
|
||||
background-color: var(--spec-summary-background);
|
||||
border-radius: 3px;
|
||||
border-left: 4px solid var(--spec-summary-border-color);
|
||||
border-right: 5px solid transparent;
|
||||
padding: 0.35em 0.5em;
|
||||
}
|
||||
|
||||
.def-doc {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Spacing between items */
|
||||
div.odoc-spec,.odoc-include {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.spec.type .variant {
|
||||
margin-left: 2ch;
|
||||
}
|
||||
.spec.type .variant p {
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
}
|
||||
.spec.type .record {
|
||||
margin-left: 2ch;
|
||||
}
|
||||
.spec.type .record p {
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.def {
|
||||
margin-top: 0;
|
||||
text-indent: -2ex;
|
||||
padding-left: 2ex;
|
||||
}
|
||||
|
||||
div.def+div.def-doc {
|
||||
margin-left: 1ex;
|
||||
margin-top: 2.5px
|
||||
}
|
||||
|
||||
div.def-doc>*:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Collapsible inlined include and module */
|
||||
|
||||
.odoc-include details {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.odoc-include.shadowed-include {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.odoc-include details:after {
|
||||
z-index: -100;
|
||||
display: block;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border-radius: 0 1ex 1ex 0;
|
||||
right: -20px;
|
||||
top: 1px;
|
||||
bottom: 1px;
|
||||
width: 15px;
|
||||
background: var(--spec-details-after-background, rgba(0, 4, 15, 0.05));
|
||||
box-shadow: 0 0px 0 1px var(--spec-details-after-shadow, rgba(204, 204, 204, 0.53));
|
||||
}
|
||||
|
||||
.odoc-include summary {
|
||||
position: relative;
|
||||
margin-bottom: 1em;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.odoc-include summary:hover {
|
||||
background-color: var(--spec-summary-hover-background);
|
||||
}
|
||||
|
||||
/* FIXME: Does not work in Firefox. */
|
||||
.odoc-include summary::-webkit-details-marker {
|
||||
color: #888;
|
||||
transform: scaleX(-1);
|
||||
position: absolute;
|
||||
top: calc(50% - 5px);
|
||||
height: 11px;
|
||||
right: -29px;
|
||||
}
|
||||
|
||||
/* Records and variants FIXME */
|
||||
|
||||
div.def table {
|
||||
text-indent: 0em;
|
||||
padding: 0;
|
||||
margin-left: -2ex;
|
||||
}
|
||||
|
||||
td.def {
|
||||
padding-left: 2ex;
|
||||
}
|
||||
|
||||
td.def-doc *:first-child {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
/* Lists of @tags */
|
||||
|
||||
.at-tags { list-style-type: none; margin-left: -3ex; }
|
||||
.at-tags li { padding-left: 3ex; text-indent: -3ex; }
|
||||
.at-tags .at-tag { text-transform: capitalize }
|
||||
|
||||
/* Lists of modules */
|
||||
|
||||
.modules { list-style-type: none; margin-left: -3ex; }
|
||||
.modules li { padding-left: 3ex; text-indent: -3ex; margin-top: 5px }
|
||||
.modules .synopsis { padding-left: 1ch; }
|
||||
|
||||
/* Odig package index */
|
||||
|
||||
.packages { list-style-type: none; margin-left: -3ex; }
|
||||
.packages li { padding-left: 3ex; text-indent: -3ex }
|
||||
.packages li a.anchor { padding-right: 0.5ch; padding-left: 3ch; }
|
||||
.packages .version { font-size: 10px; color: var(--by-name-version-color); }
|
||||
.packages .synopsis { padding-left: 1ch }
|
||||
|
||||
.by-name nav a {
|
||||
text-transform: uppercase;
|
||||
font-size: 18px;
|
||||
margin-right: 1ex;
|
||||
color: var(--by-name-nav-link-color,);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.by-tag nav a {
|
||||
margin-right: 1ex;
|
||||
color: var(--by-name-nav-link-color);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.by-tag ol { list-style-type: none; }
|
||||
.by-tag ol.tags li { margin-left: 1ch; display: inline-block }
|
||||
.by-tag td:first-child { text-transform: uppercase; }
|
||||
|
||||
/* Odig package page */
|
||||
|
||||
.package nav {
|
||||
display: inline;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.package .version {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.package.info {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.package.info td:first-child {
|
||||
font-style: italic;
|
||||
padding-right: 2ex;
|
||||
}
|
||||
|
||||
.package.info ul {
|
||||
list-style-type: none;
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.package.info li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
margin-right: 1ex;
|
||||
}
|
||||
|
||||
#info-authors li, #info-maintainers li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Sidebar and TOC */
|
||||
|
||||
.odoc-toc:before {
|
||||
display: block;
|
||||
content: "Contents";
|
||||
text-transform: uppercase;
|
||||
font-size: 1em;
|
||||
margin: 1.414em 0 0.5em;
|
||||
font-weight: 500;
|
||||
color: var(--toc-before-color);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.odoc-toc {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
max-width: 30ex;
|
||||
min-width: 26ex;
|
||||
width: 20%;
|
||||
background: var(--toc-background);
|
||||
overflow: auto;
|
||||
color: var(--toc-color);
|
||||
padding-left: 2ex;
|
||||
padding-right: 2ex;
|
||||
}
|
||||
|
||||
.odoc-toc ul li a {
|
||||
font-family: "Fira Sans", sans-serif;
|
||||
font-size: 0.95em;
|
||||
color: var(--color);
|
||||
font-weight: 400;
|
||||
line-height: 1.6em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.odoc-toc ul li a:hover {
|
||||
box-shadow: none;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* First level titles */
|
||||
|
||||
.odoc-toc>ul>li>a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.odoc-toc li ul {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.odoc-toc ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.odoc-toc ul li {
|
||||
margin: 0;
|
||||
}
|
||||
.odoc-toc>ul>li {
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.odoc-toc ul li li {
|
||||
border-left: 1px solid var(--toc-list-border);
|
||||
margin-left: 5px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
/* Mobile adjustements. */
|
||||
|
||||
@media only screen and (max-width: 95ex) {
|
||||
.odoc-content {
|
||||
margin: auto;
|
||||
padding: 2em;
|
||||
}
|
||||
.odoc-toc {
|
||||
position: static;
|
||||
width: auto;
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
border: none;
|
||||
padding: 0.2em 1em;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print adjustements. */
|
||||
|
||||
@media print {
|
||||
body {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
body nav:first-child {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* Syntax highlighting (based on github-gist) */
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: var(--code-background);
|
||||
padding: 0.5em;
|
||||
color: var(--color);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title {
|
||||
color: #458;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Copyright (c) 2016 The odoc contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
---------------------------------------------------------------------------*/
|
0
doc/solo5-elftool/Solo5_elftool/.dummy
Normal file
0
doc/solo5-elftool/Solo5_elftool/.dummy
Normal file
2
doc/solo5-elftool/Solo5_elftool/index.html
Normal file
2
doc/solo5-elftool/Solo5_elftool/index.html
Normal file
File diff suppressed because one or more lines are too long
2
doc/solo5-elftool/index.html
Normal file
2
doc/solo5-elftool/index.html
Normal file
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (solo5-elftool.index)</title><link rel="stylesheet" href="../odoc.css"/><meta charset="utf-8"/><meta name="generator" content="odoc 2.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – solo5-elftool</nav><header class="odoc-preamble"><h1 id="solo5-elftool-index"><a href="#solo5-elftool-index" class="anchor"></a>solo5-elftool index</h1></header><nav class="odoc-toc"><ul><li><a href="#library-solo5-elftool">Library solo5-elftool</a></li></ul></nav><div class="odoc-content"><h2 id="library-solo5-elftool"><a href="#library-solo5-elftool" class="anchor"></a>Library solo5-elftool</h2><p>The entry point of this library is the module: <a href="Solo5_elftool/index.html"><code>Solo5_elftool</code></a>.</p></div></body></html>
|
|
@ -1,2 +0,0 @@
|
|||
(lang dune 2.9)
|
||||
(name solo5-elftool)
|
4
lib/dune
4
lib/dune
|
@ -1,4 +0,0 @@
|
|||
(library
|
||||
(public_name solo5-elftool)
|
||||
(name solo5_elftool)
|
||||
(libraries owee cstruct fmt))
|
|
@ -1,211 +0,0 @@
|
|||
type mft_type =
|
||||
| Dev_block_basic
|
||||
| Dev_net_basic
|
||||
| Reserved_first
|
||||
|
||||
type mft_entry =
|
||||
| Dev_block_basic of string
|
||||
| Dev_net_basic of string
|
||||
|
||||
type mft = {
|
||||
version : int;
|
||||
entries : mft_entry list;
|
||||
}
|
||||
|
||||
type abi_target =
|
||||
| Hvt
|
||||
| Spt
|
||||
| Virtio
|
||||
| Muen
|
||||
| Genode
|
||||
| Xen
|
||||
|
||||
type abi = {
|
||||
target : abi_target;
|
||||
version : int32;
|
||||
}
|
||||
|
||||
let mft_type_of_int : int32 -> (mft_type, _) result = function
|
||||
| 1l -> Ok Dev_block_basic
|
||||
| 2l -> Ok Dev_net_basic
|
||||
| 1073741824l -> Ok Reserved_first
|
||||
| v -> Error (`Msg ("unknown manifest entry type: " ^ Int32.to_string v))
|
||||
|
||||
let abi_target_of_int : int32 -> (abi_target, _) result = function
|
||||
| 1l -> Ok Hvt
|
||||
| 2l -> Ok Spt
|
||||
| 3l -> Ok Virtio
|
||||
| 4l -> Ok Muen
|
||||
| 5l -> Ok Genode
|
||||
| 6l -> Ok Xen
|
||||
| v -> Error (`Msg ("unknown abi target: " ^ Int32.to_string v))
|
||||
|
||||
let pp_mft_entry ppf = function
|
||||
| Dev_block_basic name ->
|
||||
Fmt.pf ppf {|{@[<1>@ "name": %S,@ "type": "BLOCK_BASIC"@]@ }|} name
|
||||
| Dev_net_basic name ->
|
||||
Fmt.pf ppf {|{@[<1>@ "name": %S,@ "type": "NET_BASIC"@]@ }|} name
|
||||
|
||||
let pp_mft ppf { version; entries } =
|
||||
Fmt.pf ppf
|
||||
{|{@[<1>@ "type": "solo5.manifest",@ "version": %d,@ "devices": [@[<1>@ %a@]@ ]@]@ }|}
|
||||
version Fmt.(list ~sep:(append (any ",") sp) pp_mft_entry) entries
|
||||
|
||||
let pp_abi_target ppf = function
|
||||
| Hvt -> Format.fprintf ppf "hvt"
|
||||
| Spt -> Format.fprintf ppf "spt"
|
||||
| Virtio -> Format.fprintf ppf "virtio"
|
||||
| Muen -> Format.fprintf ppf "muen"
|
||||
| Genode -> Format.fprintf ppf "genode"
|
||||
| Xen -> Format.fprintf ppf "xen"
|
||||
|
||||
let pp_abi ppf { version; target } =
|
||||
Fmt.pf ppf
|
||||
{|{@[<1>@ "type": "solo5.abi",@ "target": "%a",@ "version": %lu@ @]@ }|}
|
||||
pp_abi_target target version
|
||||
|
||||
let ( let* ) = Result.bind
|
||||
let guard m b = if not b then Error (`Msg m) else Ok ()
|
||||
|
||||
let sizeof_mft_entry = 104
|
||||
let mft_max_entries = 64l
|
||||
|
||||
let parse_mft_entry buf =
|
||||
(* invariant: Cstruct.length buf = sizeof_mft_entry *)
|
||||
let name_raw = Cstruct.sub buf 0 68 in
|
||||
let typ = Cstruct.LE.get_uint32 buf 68 in
|
||||
let u = Cstruct.sub buf 72 16 in
|
||||
let b = Cstruct.sub buf 88 8 in
|
||||
let attached = Cstruct.get_uint8 buf 96 <> 0 in
|
||||
let* name =
|
||||
Cstruct.cut ~sep:(Cstruct.create 1) name_raw
|
||||
|> Option.map (fun (name, _) -> Cstruct.to_string name)
|
||||
|> Option.to_result ~none:(`Msg "unterminated device name")
|
||||
in
|
||||
let* () = guard "non-zero mft_entry.u" (Cstruct.for_all ((=) '\000') u) in
|
||||
let* () = guard "non-zero mft_entry.b" (Cstruct.for_all ((=) '\000') b) in
|
||||
let* () = guard "non-zero mft_entry.attached" (not attached) in
|
||||
let* typ = mft_type_of_int typ in
|
||||
match typ with
|
||||
| Reserved_first ->
|
||||
let* () = guard "non-zero RESERVED_FIRST" (Cstruct.for_all ((=) '\000') name_raw) in
|
||||
Ok `Reserved_first
|
||||
| Dev_block_basic ->
|
||||
Ok (`Dev_block_basic name)
|
||||
| Dev_net_basic ->
|
||||
Ok (`Dev_net_basic name)
|
||||
|
||||
let parse_mft buf =
|
||||
let buf = Cstruct.of_string buf in
|
||||
let* () = guard "manifest too small"
|
||||
(Cstruct.length buf >= 4 + 8 + sizeof_mft_entry)
|
||||
in
|
||||
(* Solo5 defines a struct mft1_note consisting of the ELF note header
|
||||
* followed by a struct mft for reading and writing the ELF note. The note
|
||||
* header is 20 bytes long, so to get 8-byte alignment the note header is
|
||||
* padded with 4 bytes. See {[solo5/mft_abi.h]}. *)
|
||||
let buf = Cstruct.shift buf 4 in
|
||||
let version = Cstruct.LE.get_uint32 buf 0
|
||||
and entries = Cstruct.LE.get_uint32 buf 4
|
||||
in
|
||||
let* () = guard "unsupported manifest version" (version = 1l) in
|
||||
let* () = guard "zero manifest entries" (Int32.unsigned_compare entries 0l > 0) in
|
||||
(* this implicitly checks [Int32.to_int entries > 0] *)
|
||||
let* () = guard "too many manifest entries"
|
||||
(Int32.unsigned_compare entries mft_max_entries <= 0)
|
||||
in
|
||||
(* We have checked that entries interpreted unsigned is between 0 and
|
||||
* mft_max_entries, so this is safely equivalent to:
|
||||
* (Option.get (Int32.unsigned_to_int entries) *)
|
||||
let entries = Int32.to_int entries in
|
||||
let buf = Cstruct.shift buf 8 in
|
||||
let* () = guard "unexpected note size"
|
||||
(Cstruct.length buf = entries * sizeof_mft_entry)
|
||||
in
|
||||
let* () =
|
||||
match parse_mft_entry (Cstruct.sub buf 0 sizeof_mft_entry) with
|
||||
| Ok `Reserved_first -> Ok ()
|
||||
| _ -> Error (`Msg "expected RESERVED_FIRST")
|
||||
in
|
||||
let buf = Cstruct.shift buf sizeof_mft_entry in
|
||||
let entries =
|
||||
Array.init (entries - 1)
|
||||
(fun i -> Cstruct.sub buf (i * sizeof_mft_entry) sizeof_mft_entry)
|
||||
in
|
||||
let* entries =
|
||||
Array.fold_left
|
||||
(fun r buf ->
|
||||
let* acc = r in
|
||||
let* mft_entry = parse_mft_entry buf in
|
||||
match mft_entry with
|
||||
| `Dev_block_basic name -> Ok (Dev_block_basic name :: acc)
|
||||
| `Dev_net_basic name -> Ok (Dev_net_basic name :: acc)
|
||||
| `Reserved_first -> Error (`Msg "found RESERVED_FIRST not as first entry"))
|
||||
(Ok [])
|
||||
entries
|
||||
|> Result.map List.rev
|
||||
in
|
||||
Ok { version = Int32.to_int version; entries }
|
||||
|
||||
let parse_abi buf =
|
||||
let buf = Cstruct.of_string buf in
|
||||
let* () = guard "abi manifest size mismatch" (Cstruct.length buf = 4 * 4) in
|
||||
let target = Cstruct.LE.get_uint32 buf 0 in
|
||||
let version = Cstruct.LE.get_uint32 buf 4 in
|
||||
let reserved0 = Cstruct.LE.get_uint32 buf 8 in
|
||||
let reserved1 = Cstruct.LE.get_uint32 buf 12 in
|
||||
let* target = abi_target_of_int target in
|
||||
let* () = guard "non-zero reserved0" (reserved0 = 0l) in
|
||||
let* () = guard "non-zero reserved1" (reserved1 = 0l) in
|
||||
(* XXX: should we check version = 1l ? *)
|
||||
Ok { target; version }
|
||||
|
||||
let ( let* ) = Result.bind
|
||||
|
||||
let note_name = "Solo5"
|
||||
let typ_mft1 = 0x3154464d
|
||||
let typ_abi1 = 0x31494241
|
||||
|
||||
let query_manifest_exn buf =
|
||||
let _header, sections = Owee_elf.read_elf buf in
|
||||
let* section =
|
||||
Owee_elf.find_section sections ".note.solo5.manifest"
|
||||
|> Option.to_result ~none:(`Msg "section .note.solo5.manifest not found")
|
||||
in
|
||||
let body = Owee_elf.section_body buf section in
|
||||
let cursor = Owee_buf.cursor body in
|
||||
let descsz =
|
||||
Owee_elf_notes.read_desc_size cursor
|
||||
~expected_owner:note_name
|
||||
~expected_type:typ_mft1
|
||||
in
|
||||
let desc = Owee_buf.Read.fixed_string cursor descsz in
|
||||
let* () = guard "extra data" (Owee_buf.at_end cursor) in
|
||||
parse_mft desc
|
||||
|
||||
let query_manifest buf =
|
||||
try query_manifest_exn buf with
|
||||
| Out_of_memory -> raise Out_of_memory
|
||||
| e -> Error (`Msg ("query manifest failure: " ^ Printexc.to_string e))
|
||||
|
||||
let query_abi_exn buf =
|
||||
let _header, sections = Owee_elf.read_elf buf in
|
||||
let* section =
|
||||
Owee_elf.find_section sections ".note.solo5.abi"
|
||||
|> Option.to_result ~none:(`Msg "section .note.solo5.abi not found")
|
||||
in
|
||||
let body = Owee_elf.section_body buf section in
|
||||
let cursor = Owee_buf.cursor body in
|
||||
let descsz =
|
||||
Owee_elf_notes.read_desc_size cursor
|
||||
~expected_owner:note_name
|
||||
~expected_type:typ_abi1
|
||||
in
|
||||
let desc = Owee_buf.Read.fixed_string cursor descsz in
|
||||
let* () = guard "extra data" (Owee_buf.at_end cursor) in
|
||||
parse_abi desc
|
||||
|
||||
let query_abi buf =
|
||||
try query_abi_exn buf with
|
||||
| Out_of_memory -> raise Out_of_memory
|
||||
| e -> Error (`Msg ("query abi failure: " ^ Printexc.to_string e))
|
|
@ -1,43 +0,0 @@
|
|||
(** An entry in the manifest representing a device. *)
|
||||
type mft_entry =
|
||||
| Dev_block_basic of string
|
||||
| Dev_net_basic of string
|
||||
|
||||
(** The Solo5 manifest *)
|
||||
type mft = {
|
||||
version : int;
|
||||
(** [version] is at the moment always 1. *)
|
||||
entries : mft_entry list;
|
||||
(** [entries] in the manifest. *)
|
||||
}
|
||||
|
||||
(** The known solo5 targets *)
|
||||
type abi_target =
|
||||
| Hvt
|
||||
| Spt
|
||||
| Virtio
|
||||
| Muen
|
||||
| Genode
|
||||
| Xen
|
||||
|
||||
(** abi taget and abi version *)
|
||||
type abi = {
|
||||
target : abi_target; (** abi target *)
|
||||
version : int32; (** abi version *)
|
||||
}
|
||||
|
||||
val pp_mft_entry : Format.formatter -> mft_entry -> unit
|
||||
val pp_mft : Format.formatter -> mft -> unit
|
||||
(** Pretty-prints the manifest as JSON in a similar style as the Solo5 command
|
||||
* line tool {[solo5-elftool query-manifest]}. *)
|
||||
|
||||
val pp_abi_target : Format.formatter -> abi_target -> unit
|
||||
val pp_abi : Format.formatter -> abi -> unit
|
||||
(** Pretty-prints the manifest as JSON in a similar style as the Solo5 command
|
||||
* line tool {[solo5-elftool query-abi]}. *)
|
||||
|
||||
val query_manifest : Owee_buf.t -> (mft, [> `Msg of string ]) result
|
||||
(** [query_manifest buf] is the solo5 manifest of [buf], or an error message. *)
|
||||
|
||||
val query_abi : Owee_buf.t -> (abi, [> `Msg of string ]) result
|
||||
(** [query_abi buf] is the solo5 abi of [buf], or an error message. *)
|
|
@ -1,33 +0,0 @@
|
|||
opam-version: "2.0"
|
||||
homepage: "https://git.robur.io/robur/ocaml-solo5-elftool"
|
||||
dev-repo: "git+https://git.robur.io/robur/ocaml-solo5-elftool.git"
|
||||
bug-reports: "https://github.com/robur-coop/ocaml-solo5-elftool/issues"
|
||||
doc: "https://robur-coop.github.io/ocaml-solo5-elftool/doc"
|
||||
maintainer: [ "team@robur.coop" ]
|
||||
authors: [ "Reynir Björnsson <reynir@reynir.dk>" ]
|
||||
license: "BSD-2-Clause"
|
||||
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
["dune" "build" "-p" name "-j" jobs]
|
||||
]
|
||||
|
||||
depends: [
|
||||
"ocaml" {>= "4.08.0"}
|
||||
"dune" {>= "2.9"}
|
||||
"owee" {>= "0.4"}
|
||||
"cstruct" {>= "6.0.0"}
|
||||
"fmt" {>= "0.8.7"}
|
||||
"cmdliner"
|
||||
]
|
||||
|
||||
conflicts: [
|
||||
"result" {< "1.5"}
|
||||
]
|
||||
|
||||
synopsis: "OCaml Solo5 elftool for querying solo5 manifests"
|
||||
description: """
|
||||
OCaml Solo5 elftool is a library and executable for reading solo5 device
|
||||
manifests from solo5 ELF executables.
|
||||
"""
|
||||
x-maintenance-intent: [ "(latest)" ]
|
Loading…
Reference in a new issue