diff --git a/Cargo.lock b/Cargo.lock
index 1e2fff381ca2..b5b845185a89 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,10 +1,16 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+[[package]]
+name = "adler32"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
+
 [[package]]
 name = "aho-corasick"
-version = "0.7.7"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f56c476256dc249def911d6f7580b5fc7e875895b5d7ee88f5d602208035744"
+checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
 dependencies = [
  "memchr",
 ]
@@ -85,9 +91,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
 
 [[package]]
 name = "backtrace"
-version = "0.3.43"
+version = "0.3.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f"
+checksum = "e4036b9bf40f3cf16aba72a3d65e8a520fc4bafcdc7079aea8f848c58c5b5536"
 dependencies = [
  "backtrace-sys",
  "cfg-if",
@@ -159,8 +165,8 @@ dependencies = [
  "lazycell",
  "log",
  "peeking_take_while",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
  "regex",
  "rustc-hash",
  "shlex",
@@ -213,9 +219,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
 
 [[package]]
 name = "byteorder"
-version = "1.3.2"
+version = "1.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 
 [[package]]
 name = "c2-chacha"
@@ -354,7 +360,7 @@ dependencies = [
  "log",
  "serde",
  "smallvec",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "thiserror",
 ]
 
@@ -392,7 +398,7 @@ dependencies = [
  "cranelift-codegen",
  "log",
  "smallvec",
- "target-lexicon",
+ "target-lexicon 0.10.0",
 ]
 
 [[package]]
@@ -403,7 +409,7 @@ checksum = "564ee82268bc25b914fcf331edfc2452f2d9ca34f976b187b4ca668beba250c8"
 dependencies = [
  "cranelift-codegen",
  "raw-cpuid",
- "target-lexicon",
+ "target-lexicon 0.10.0",
 ]
 
 [[package]]
@@ -421,6 +427,15 @@ dependencies = [
  "wasmparser 0.48.2",
 ]
 
+[[package]]
+name = "crc32fast"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "crossbeam-deque"
 version = "0.7.2"
@@ -472,8 +487,8 @@ version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc"
 dependencies = [
- "quote",
- "syn",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -491,8 +506,8 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dab2f0544254a47cabc58956cc7ebda74c3b796bb2761e3fe8f29fdde632ad95"
 dependencies = [
- "proc-macro2",
- "syn",
+ "proc-macro2 1.0.8",
+ "syn 1.0.14",
  "synstructure",
 ]
 
@@ -543,9 +558,9 @@ dependencies = [
  "byteorder",
  "lazy_static",
  "owning_ref",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -618,12 +633,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "74b9ed6159e4a6212c61d9c6a86bee01876b192a64accecf58d5b5ae3b667b52"
 dependencies = [
  "anyhow",
- "goblin",
+ "goblin 0.1.3",
  "indexmap",
  "log",
- "scroll",
+ "scroll 0.10.1",
  "string-interner",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "thiserror",
 ]
 
@@ -643,9 +658,9 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
  "synstructure",
 ]
 
@@ -694,6 +709,18 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "flate2"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "miniz_oxide",
+]
+
 [[package]]
 name = "gcc"
 version = "0.3.55"
@@ -726,9 +753,9 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -760,6 +787,28 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
+[[package]]
+name = "goblin"
+version = "0.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f55d53401eb2fd30afd025c570b1946b6966344acf21b42e31286f3bf89e6a8"
+dependencies = [
+ "log",
+ "plain",
+ "scroll 0.9.2",
+]
+
+[[package]]
+name = "goblin"
+version = "0.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3fa261d919c1ae9d1e4533c4a2f99e10938603c4208d56c05bec7a872b661b0"
+dependencies = [
+ "log",
+ "plain",
+ "scroll 0.9.2",
+]
+
 [[package]]
 name = "goblin"
 version = "0.1.3"
@@ -768,7 +817,7 @@ checksum = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da"
 dependencies = [
  "log",
  "plain",
- "scroll",
+ "scroll 0.10.1",
 ]
 
 [[package]]
@@ -782,9 +831,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
+checksum = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
 dependencies = [
  "libc",
 ]
@@ -806,9 +855,9 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
 
 [[package]]
 name = "indexmap"
-version = "1.3.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b54058f0a6ff80b6803da8faf8997cde53872b38f4023728f6830b06cd3c0dc"
+checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
 dependencies = [
  "autocfg 1.0.0",
 ]
@@ -830,9 +879,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
  "unindent",
 ]
 
@@ -853,9 +902,9 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -969,9 +1018,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.3.0"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
+checksum = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978"
 
 [[package]]
 name = "memmap"
@@ -992,6 +1041,15 @@ dependencies = [
  "rustc_version",
 ]
 
+[[package]]
+name = "miniz_oxide"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
+dependencies = [
+ "adler32",
+]
+
 [[package]]
 name = "more-asserts"
 version = "0.2.1"
@@ -1094,6 +1152,19 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "object"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df4af347f5ac3d0e83e78c26be33cd10e8e874dcb68517a909ad802ba50a90b5"
+dependencies = [
+ "flate2",
+ "goblin 0.0.22",
+ "parity-wasm",
+ "scroll 0.9.2",
+ "uuid",
+]
+
 [[package]]
 name = "opaque-debug"
 version = "0.2.3"
@@ -1119,6 +1190,12 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "parity-wasm"
+version = "0.38.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20d7e522a7f994cc4ae32970b1ce0d99ecf91b8e1df080517a26faa6d2e2ee62"
+
 [[package]]
 name = "paste"
 version = "0.1.6"
@@ -1136,9 +1213,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1172,27 +1249,27 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875077759af22fa20b610ad4471d8155b321c89c3f2785526c9839b099be4e0a"
+checksum = "052b3c9af39c7e5e94245f820530487d19eb285faedcb40e0c3275132293f242"
 dependencies = [
  "proc-macro-error-attr",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
  "rustversion",
- "syn",
+ "syn 1.0.14",
 ]
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5717d9fa2664351a01ed73ba5ef6df09c01a521cb42cb65a061432a826f3c7a"
+checksum = "d175bef481c7902e63e3165627123fff3502f06ac043d3ef42d08c1246da9253"
 dependencies = [
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
  "rustversion",
- "syn",
+ "syn 1.0.14",
  "syn-mid",
 ]
 
@@ -1202,9 +1279,18 @@ version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "0.4.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
+dependencies = [
+ "unicode-xid 0.1.0",
 ]
 
 [[package]]
@@ -1213,7 +1299,7 @@ version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
 dependencies = [
- "unicode-xid",
+ "unicode-xid 0.2.0",
 ]
 
 [[package]]
@@ -1243,9 +1329,9 @@ version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1254,10 +1340,10 @@ version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda"
 dependencies = [
- "proc-macro2",
+ "proc-macro2 1.0.8",
  "pyo3-derive-backend",
- "quote",
- "syn",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1278,13 +1364,22 @@ dependencies = [
  "rand_core",
 ]
 
+[[package]]
+name = "quote"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
+dependencies = [
+ "proc-macro2 0.4.30",
+]
+
 [[package]]
 name = "quote"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 dependencies = [
- "proc-macro2",
+ "proc-macro2 1.0.8",
 ]
 
 [[package]]
@@ -1449,12 +1544,9 @@ checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
 
 [[package]]
 name = "rustc-hash"
-version = "1.0.1"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
-dependencies = [
- "byteorder",
-]
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "rustc_version"
@@ -1471,9 +1563,9 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1484,9 +1576,19 @@ checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
 
 [[package]]
 name = "scopeguard"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "scroll"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383"
+dependencies = [
+ "rustc_version",
+ "scroll_derive 0.9.5",
+]
 
 [[package]]
 name = "scroll"
@@ -1494,7 +1596,18 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1"
 dependencies = [
- "scroll_derive",
+ "scroll_derive 0.10.1",
+]
+
+[[package]]
+name = "scroll_derive"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb"
+dependencies = [
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "syn 0.15.44",
 ]
 
 [[package]]
@@ -1503,9 +1616,9 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1538,16 +1651,16 @@ version = "1.0.104"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.46"
+version = "1.0.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b01d7f0288608a01dca632cf1df859df6fd6ffa885300fc275ce2ba6221953"
+checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
 dependencies = [
  "itoa",
  "ryu",
@@ -1624,9 +1737,20 @@ checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64"
 dependencies = [
  "heck",
  "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
+]
+
+[[package]]
+name = "syn"
+version = "0.15.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
+dependencies = [
+ "proc-macro2 0.4.30",
+ "quote 0.6.13",
+ "unicode-xid 0.1.0",
 ]
 
 [[package]]
@@ -1635,9 +1759,9 @@ version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
 dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "unicode-xid 0.2.0",
 ]
 
 [[package]]
@@ -1646,9 +1770,9 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1657,10 +1781,21 @@ version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
+ "unicode-xid 0.2.0",
+]
+
+[[package]]
+name = "target-lexicon"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb"
+dependencies = [
+ "failure",
+ "failure_derive",
+ "serde_json",
 ]
 
 [[package]]
@@ -1700,7 +1835,7 @@ dependencies = [
  "cfg-if",
  "os_pipe",
  "pretty_env_logger",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "tempfile",
  "wasi-common",
  "wasmtime",
@@ -1719,22 +1854,22 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "205684fd018ca14432b12cce6ea3d46763311a571c3d294e71ba3f01adcf1aad"
+checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57e4d2e50ca050ed44fb58309bdce3efa79948f84f9993ad1978de5eebdce5a7"
+checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1799,6 +1934,12 @@ version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
 
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+
 [[package]]
 name = "unicode-xid"
 version = "0.2.0"
@@ -1820,6 +1961,12 @@ dependencies = [
  "traitobject",
 ]
 
+[[package]]
+name = "uuid"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
+
 [[package]]
 name = "vec_map"
 version = "0.8.1"
@@ -1859,9 +2006,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8757b0da38353d55a9687f4dee68a8f441f980dd36e16ab07d6e6c673f505f76"
 dependencies = [
  "heck",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -1944,11 +2091,12 @@ dependencies = [
  "rayon",
  "region",
  "rustc-demangle",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "wasi-common",
  "wasmparser 0.51.2",
  "wasmtime-environ",
  "wasmtime-jit",
+ "wasmtime-profiling",
  "wasmtime-runtime",
  "wat",
  "winapi",
@@ -1974,7 +2122,7 @@ dependencies = [
  "pretty_env_logger",
  "rayon",
  "structopt",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "tempfile",
  "test-programs",
  "wasi-common",
@@ -1985,6 +2133,7 @@ dependencies = [
  "wasmtime-interface-types",
  "wasmtime-jit",
  "wasmtime-obj",
+ "wasmtime-profiling",
  "wasmtime-runtime",
  "wasmtime-wasi",
  "wasmtime-wast",
@@ -1999,7 +2148,7 @@ dependencies = [
  "faerie",
  "gimli 0.19.0",
  "more-asserts",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "thiserror",
  "wasmparser 0.51.2",
  "wasmtime-environ",
@@ -2030,7 +2179,7 @@ dependencies = [
  "rayon",
  "serde",
  "sha2",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "tempfile",
  "thiserror",
  "toml",
@@ -2092,11 +2241,12 @@ dependencies = [
  "cranelift-wasm",
  "more-asserts",
  "region",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "thiserror",
  "wasmparser 0.51.2",
  "wasmtime-debug",
  "wasmtime-environ",
+ "wasmtime-profiling",
  "wasmtime-runtime",
  "winapi",
 ]
@@ -2111,6 +2261,20 @@ dependencies = [
  "wasmtime-environ",
 ]
 
+[[package]]
+name = "wasmtime-profiling"
+version = "0.1.0"
+dependencies = [
+ "gimli 0.19.0",
+ "goblin 0.0.24",
+ "lazy_static",
+ "libc",
+ "object",
+ "scroll 0.9.2",
+ "serde",
+ "target-lexicon 0.4.0",
+]
+
 [[package]]
 name = "wasmtime-py"
 version = "0.9.0"
@@ -2118,7 +2282,7 @@ dependencies = [
  "anyhow",
  "pyo3",
  "region",
- "target-lexicon",
+ "target-lexicon 0.10.0",
  "wasmparser 0.51.2",
  "wasmtime",
  "wasmtime-interface-types",
@@ -2139,6 +2303,7 @@ dependencies = [
  "region",
  "thiserror",
  "wasmtime-environ",
+ "wasmtime-profiling",
  "winapi",
 ]
 
@@ -2157,9 +2322,9 @@ dependencies = [
 name = "wasmtime-rust-macro"
 version = "0.9.0"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
+ "syn 1.0.14",
 ]
 
 [[package]]
@@ -2201,13 +2366,22 @@ dependencies = [
  "leb128",
 ]
 
+[[package]]
+name = "wast"
+version = "8.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9df3d716118a503b2f6bbb6ff46b21997ab0cc167b01de7a188e45e4b01e8d"
+dependencies = [
+ "leb128",
+]
+
 [[package]]
 name = "wat"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5795e34a4b39893653dec97e644fac85c31398e0ce1abecc48967aac83d9e8ce"
+checksum = "4a927b35badc29c97d97e82689eef7f72fc936d884b3391804c1bb6cd2bdccbb"
 dependencies = [
- "wast 7.0.0",
+ "wast 8.0.0",
 ]
 
 [[package]]
@@ -2224,8 +2398,8 @@ name = "wig"
 version = "0.9.2"
 dependencies = [
  "heck",
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.8",
+ "quote 1.0.2",
  "witx",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 05b072f92600..5d62b5b9c335 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,7 @@ wasmtime-environ = { path = "crates/environ" }
 wasmtime-interface-types = { path = "crates/interface-types" }
 wasmtime-jit = { path = "crates/jit" }
 wasmtime-obj = { path = "crates/obj" }
+wasmtime-profiling = { path = "crates/profiling" }
 wasmtime-wast = { path = "crates/wast" }
 wasmtime-wasi = { path = "crates/wasi" }
 wasi-common = { path = "crates/wasi-common" }
@@ -75,6 +76,7 @@ lightbeam = [
     "wasmtime-wast/lightbeam",
     "wasmtime/lightbeam",
 ]
+jitdump = ["wasmtime-profiling/jitdump"]
 test_programs = ["test-programs/test_programs"]
 
 [badges]
diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml
index 8dd7873c731d..143240f47129 100644
--- a/crates/api/Cargo.toml
+++ b/crates/api/Cargo.toml
@@ -12,6 +12,7 @@ edition = "2018"
 wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
 wasmtime-environ = { path = "../environ", version = "0.9.0" }
 wasmtime-jit = { path = "../jit", version = "0.9.0" }
+wasmtime-profiling = { path = "../profiling" }
 wasmparser = "0.51.2"
 target-lexicon = { version = "0.10.0", default-features = false }
 anyhow = "1.0.19"
diff --git a/crates/api/src/module.rs b/crates/api/src/module.rs
index c8f159e551c1..dd463d2fc55d 100644
--- a/crates/api/src/module.rs
+++ b/crates/api/src/module.rs
@@ -253,6 +253,7 @@ impl Module {
             &mut store.compiler_mut(),
             binary,
             store.engine().config().debug_info,
+            store.engine().config().profiler.as_ref(),
         )?;
 
         let names = Arc::new(Names {
diff --git a/crates/api/src/runtime.rs b/crates/api/src/runtime.rs
index 705491807991..09dea30bd777 100644
--- a/crates/api/src/runtime.rs
+++ b/crates/api/src/runtime.rs
@@ -3,11 +3,12 @@ use std::cell::RefCell;
 use std::fmt;
 use std::path::Path;
 use std::rc::Rc;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 use wasmparser::{OperatorValidatorConfig, ValidatingParserConfig};
 use wasmtime_environ::settings::{self, Configurable};
 use wasmtime_environ::CacheConfig;
 use wasmtime_jit::{native, CompilationStrategy, Compiler};
+use wasmtime_profiling::{JitDumpAgent, ProfilingAgent, ProfilingStrategy};
 
 // Runtime Environment
 
@@ -25,6 +26,7 @@ pub struct Config {
     pub(crate) debug_info: bool,
     pub(crate) strategy: CompilationStrategy,
     pub(crate) cache_config: CacheConfig,
+    pub(crate) profiler: Option<Arc<Mutex<Box<dyn ProfilingAgent + Send>>>>,
 }
 
 impl Config {
@@ -58,6 +60,7 @@ impl Config {
             flags,
             strategy: CompilationStrategy::Auto,
             cache_config: CacheConfig::new_cache_disabled(),
+            profiler: None,
         }
     }
 
@@ -212,6 +215,20 @@ impl Config {
         Ok(self)
     }
 
+    /// Creates a default profiler based on the profiling strategy choosen
+    ///
+    /// Profiler creation calls the type's default initializer where the purpose is
+    /// really just to put in place the type used for profiling.
+    pub fn profiler(&mut self, profile: ProfilingStrategy) -> Result<&mut Self> {
+        match profile {
+            ProfilingStrategy::JitDumpProfiler => {
+                self.profiler = { Some(Arc::new(Mutex::new(Box::new(JitDumpAgent::default())))) }
+            }
+            _ => self.profiler = { None },
+        };
+        Ok(self)
+    }
+
     /// Configures whether the debug verifier of Cranelift is enabled or not.
     ///
     /// When Cranelift is used as a code generation backend this will configure
diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml
index 2212663384c5..9c9b35016309 100644
--- a/crates/jit/Cargo.toml
+++ b/crates/jit/Cargo.toml
@@ -19,6 +19,7 @@ cranelift-frontend = "0.58.0"
 wasmtime-environ = { path = "../environ", version = "0.9.0" }
 wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
 wasmtime-debug = { path = "../debug", version = "0.9.0" }
+wasmtime-profiling = { path = "../profiling" }
 region = "2.0.0"
 thiserror = "1.0.4"
 target-lexicon = { version = "0.10.0", default-features = false }
diff --git a/crates/jit/src/code_memory.rs b/crates/jit/src/code_memory.rs
index 2eb4806364a4..4670f40dfc67 100644
--- a/crates/jit/src/code_memory.rs
+++ b/crates/jit/src/code_memory.rs
@@ -5,6 +5,7 @@ use region;
 use std::mem::ManuallyDrop;
 use std::{cmp, mem};
 use wasmtime_environ::{Compilation, CompiledFunction};
+use wasmtime_profiling::ProfilingAgent;
 use wasmtime_runtime::{Mmap, VMFunctionBody};
 
 struct CodeMemoryEntry {
@@ -230,4 +231,22 @@ impl CodeMemory {
 
         Ok(())
     }
+
+    /// Calls the module_load for a given ProfilerAgent. Includes
+    /// all memory address and length for the given module.
+    /// TODO: Properly handle the possibilities of multiple mmapped regions
+    /// which may, amongst other things, influence being more specific about
+    /// the module name.
+    pub fn profiler_module_load(
+        &mut self,
+        profiler: &mut Box<dyn ProfilingAgent + Send>,
+        module_name: &str,
+        dbg_image: Option<&[u8]>,
+    ) -> () {
+        for CodeMemoryEntry { mmap: m, table: _t } in &mut self.entries {
+            if m.len() > 0 {
+                profiler.module_load(module_name, m.as_ptr(), m.len(), dbg_image);
+            }
+        }
+    }
 }
diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs
index 0a0174983807..0e4c8a77b176 100644
--- a/crates/jit/src/compiler.rs
+++ b/crates/jit/src/compiler.rs
@@ -20,6 +20,7 @@ use wasmtime_environ::{
     Compiler as _C, FunctionBodyData, Module, ModuleMemoryOffset, ModuleVmctxInfo, Relocations,
     Traps, Tunables, VMOffsets,
 };
+use wasmtime_profiling::ProfilingAgent;
 use wasmtime_runtime::{
     InstantiationError, SignatureRegistry, TrapRegistration, TrapRegistry, VMFunctionBody,
     VMSharedSignatureIndex,
@@ -235,6 +236,16 @@ impl Compiler {
         self.code_memory.publish();
     }
 
+    pub(crate) fn profiler_module_load(
+        &mut self,
+        profiler: &mut Box<dyn ProfilingAgent + Send>,
+        module_name: &str,
+        dbg_image: Option<&[u8]>,
+    ) -> () {
+        self.code_memory
+            .profiler_module_load(profiler, module_name, dbg_image);
+    }
+
     /// Shared signature registry.
     pub fn signatures(&self) -> &SignatureRegistry {
         &self.signatures
diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs
index f6b33e41ffe3..9c1982712853 100644
--- a/crates/jit/src/instantiate.rs
+++ b/crates/jit/src/instantiate.rs
@@ -9,7 +9,7 @@ use crate::link::link_module;
 use crate::resolver::Resolver;
 use std::io::Write;
 use std::rc::Rc;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 use thiserror::Error;
 use wasmtime_debug::read_debuginfo;
 use wasmtime_environ::entity::{BoxedSlice, PrimaryMap};
@@ -17,6 +17,7 @@ use wasmtime_environ::wasm::{DefinedFuncIndex, SignatureIndex};
 use wasmtime_environ::{
     CompileError, DataInitializer, DataInitializerLocation, Module, ModuleEnvironment,
 };
+use wasmtime_profiling::ProfilingAgent;
 use wasmtime_runtime::{
     GdbJitImageRegistration, InstanceHandle, InstantiationError, TrapRegistration, VMFunctionBody,
     VMSharedSignatureIndex,
@@ -61,6 +62,7 @@ impl<'data> RawCompiledModule<'data> {
         compiler: &mut Compiler,
         data: &'data [u8],
         debug_info: bool,
+        profiler: Option<&Arc<Mutex<Box<dyn ProfilingAgent + Send>>>>,
     ) -> Result<Self, SetupError> {
         let environ = ModuleEnvironment::new(compiler.frontend_config(), compiler.tunables());
 
@@ -103,6 +105,21 @@ impl<'data> RawCompiledModule<'data> {
         // Make all code compiled thus far executable.
         compiler.publish_compiled_code();
 
+        // Initialize profiler and load the wasm module
+        match profiler {
+            Some(_) => {
+                let region_name = String::from("wasm_module");
+                let mut profiler = profiler.unwrap().lock().unwrap();
+                match &dbg_image {
+                    Some(dbg) => {
+                        compiler.profiler_module_load(&mut profiler, &region_name, Some(&dbg))
+                    }
+                    _ => compiler.profiler_module_load(&mut profiler, &region_name, None),
+                };
+            }
+            _ => (),
+        };
+
         let dbg_jit_registration = if let Some(img) = dbg_image {
             let mut bytes = Vec::new();
             bytes.write_all(&img).expect("all written");
@@ -139,8 +156,9 @@ impl CompiledModule {
         compiler: &mut Compiler,
         data: &'data [u8],
         debug_info: bool,
+        profiler: Option<&Arc<Mutex<Box<dyn ProfilingAgent + Send>>>>,
     ) -> Result<Self, SetupError> {
-        let raw = RawCompiledModule::<'data>::new(compiler, data, debug_info)?;
+        let raw = RawCompiledModule::<'data>::new(compiler, data, debug_info, profiler)?;
 
         Ok(Self::from_parts(
             raw.module,
@@ -246,7 +264,7 @@ impl OwnedDataInitializer {
 
 /// Create a new wasm instance by compiling the wasm module in `data` and instatiating it.
 ///
-/// This is equivalent to createing a `CompiledModule` and calling `instantiate()` on it,
+/// This is equivalent to creating a `CompiledModule` and calling `instantiate()` on it,
 /// but avoids creating an intermediate copy of the data initializers.
 ///
 /// # Unsafety
@@ -258,7 +276,9 @@ pub unsafe fn instantiate(
     data: &[u8],
     resolver: &mut dyn Resolver,
     debug_info: bool,
+    profiler: Option<&Arc<Mutex<Box<dyn ProfilingAgent + Send>>>>,
 ) -> Result<InstanceHandle, SetupError> {
-    let instance = CompiledModule::new(compiler, data, debug_info)?.instantiate(resolver)?;
+    let instance =
+        CompiledModule::new(compiler, data, debug_info, profiler)?.instantiate(resolver)?;
     Ok(instance)
 }
diff --git a/crates/profiling/Cargo.toml b/crates/profiling/Cargo.toml
new file mode 100644
index 000000000000..f504cf4b22c3
--- /dev/null
+++ b/crates/profiling/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "wasmtime-profiling"
+version = "0.1.0"
+authors = ["The Wasmtime Project Developers"]
+description = "Runtime library support for Wasmtime"
+license = "Apache-2.0 WITH LLVM-exception"
+categories = ["wasm"]
+keywords = ["webassembly", "wasm"]
+repository = "https://github.com/bytecodealliance/wasmtime"
+readme = "README.md"
+edition = "2018"
+
+[dependencies]
+libc = { version = "0.2.60", default-features = false }
+goblin = "0.0.24"
+serde = { version = "1.0.99", features = ["derive"] }
+scroll = "0.9.2"
+gimli = "0.19.0"
+object = "0.12.0"
+target-lexicon = "0.4.0"
+lazy_static = "1.4"
+
+[badges]
+maintenance = { status = "actively-developed" }
+
+[features]
+jitdump = []
diff --git a/crates/profiling/src/jitdump.rs b/crates/profiling/src/jitdump.rs
new file mode 100644
index 000000000000..266ad6ee4414
--- /dev/null
+++ b/crates/profiling/src/jitdump.rs
@@ -0,0 +1,702 @@
+//! Support for jitdump files which can be used by perf for profiling jitted code.
+//! Spec definitions for the output format is as described here:
+//! https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/Documentation/jitdump-specification.txt
+//!
+//! Usage Example:
+//!     Record
+//!         sudo perf record -k 1 -e instructions:u target/debug/wasmtime -g --jitdump test.wasm
+//!     Combine
+//!         sudo perf inject -v -j -i perf.data -o perf.jit.data
+//!     Report
+//!         sudo perf report -i perf.jit.data -F+period,srcline
+//! Note: For descriptive results, the WASM file being executed should contain dwarf debug data
+use libc::c_int;
+#[cfg(not(target_os = "windows"))]
+use libc::{c_void, clock_gettime, mmap, open, sysconf};
+use object::Object;
+use scroll::{IOwrite, SizeWith, NATIVE};
+use serde::{Deserialize, Serialize};
+use std::error::Error;
+#[cfg(not(target_os = "windows"))]
+use std::ffi::CString;
+use std::fmt::Debug;
+use std::fs::File;
+use std::io::Write;
+#[cfg(not(target_os = "windows"))]
+use std::os::unix::io::FromRawFd;
+use std::{borrow, mem, process};
+use target_lexicon::Architecture;
+
+#[cfg(target_pointer_width = "64")]
+use goblin::elf64 as elf;
+
+#[cfg(target_pointer_width = "32")]
+use goblin::elf32 as elf;
+
+/// Defines jitdump record types
+#[repr(u32)]
+pub enum RecordId {
+    /// Value 0: JIT_CODE_LOAD: record describing a jitted function
+    JitCodeLoad = 0,
+    /// Value 1: JIT_CODE_MOVE: record describing an already jitted function which is moved
+    _JitCodeMove = 1,
+    /// Value 2: JIT_CODE_DEBUG_INFO: record describing the debug information for a jitted function
+    JitCodeDebugInfo = 2,
+    /// Value 3: JIT_CODE_CLOSE: record marking the end of the jit runtime (optional)
+    _JitCodeClose = 3,
+    /// Value 4: JIT_CODE_UNWINDING_INFO: record describing a function unwinding information
+    _JitCodeUnwindingInfo = 4,
+}
+
+/// Each record starts with this fixed size record header which describes the record that follows
+#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, IOwrite, SizeWith)]
+#[repr(C)]
+pub struct RecordHeader {
+    /// uint32_t id: a value identifying the record type (see below)
+    id: u32,
+    /// uint32_t total_size: the size in bytes of the record including the header.
+    record_size: u32,
+    /// uint64_t timestamp: a timestamp of when the record was created.
+    timestamp: u64,
+}
+
+/// The CodeLoadRecord is used for describing jitted functions
+#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, IOwrite, SizeWith)]
+#[repr(C)]
+pub struct CodeLoadRecord {
+    /// Fixed sized header that describes this record
+    header: RecordHeader,
+    /// uint32_t pid: OS process id of the runtime generating the jitted code
+    pid: u32,
+    /// uint32_t tid: OS thread identification of the runtime thread generating the jitted code
+    tid: u32,
+    /// uint64_t vma: virtual address of jitted code start
+    virtual_address: u64,
+    /// uint64_t code_addr: code start address for the jitted code. By default vma = code_addr
+    address: u64,
+    /// uint64_t code_size: size in bytes of the generated jitted code
+    size: u64,
+    /// uint64_t code_index: unique identifier for the jitted code (see below)
+    index: u64,
+}
+
+/// Describes source line information for a jitted function
+#[derive(Serialize, Deserialize, Debug, Default)]
+#[repr(C)]
+pub struct DebugEntry {
+    /// uint64_t code_addr: address of function for which the debug information is generated
+    address: u64,
+    /// uint32_t line: source file line number (starting at 1)
+    line: u32,
+    /// uint32_t discrim: column discriminator, 0 is default
+    discriminator: u32,
+    /// char name[n]: source file name in ASCII, including null termination
+    filename: String,
+}
+
+/// Describes debug information for a jitted function. An array of debug entries are
+/// appended to this record during writting. Note, this record must preceed the code
+/// load record that describes the same jitted function.
+#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, IOwrite, SizeWith)]
+#[repr(C)]
+pub struct DebugInfoRecord {
+    /// Fixed sized header that describes this record
+    header: RecordHeader,
+    /// uint64_t code_addr: address of function for which the debug information is generated
+    address: u64,
+    /// uint64_t nr_entry: number of debug entries for the function appended to this record
+    count: u64,
+}
+
+/// Fixed-sized header for each jitdump file
+#[derive(Serialize, Deserialize, Debug, Default, IOwrite, SizeWith)]
+#[repr(C)]
+pub struct FileHeader {
+    /// uint32_t magic: a magic number tagging the file type. The value is 4-byte long and represents the
+    /// string "JiTD" in ASCII form. It is 0x4A695444 or 0x4454694a depending on the endianness. The field can
+    /// be used to detect the endianness of the file
+    magic: u32,
+    /// uint32_t version: a 4-byte value representing the format version. It is currently set to 2
+    version: u32,
+    /// uint32_t total_size: size in bytes of file header
+    size: u32,
+    /// uint32_t elf_mach: ELF architecture encoding (ELF e_machine value as specified in /usr/include/elf.h)
+    e_machine: u32,
+    /// uint32_t pad1: padding. Reserved for future use
+    pad1: u32,
+    /// uint32_t pid: JIT runtime process identification (OS specific)
+    pid: u32,
+    /// uint64_t timestamp: timestamp of when the file was created
+    timestamp: u64,
+    /// uint64_t flags: a bitmask of flags
+    flags: u64,
+}
+
+/// Interface for driving the creation of jitdump files
+#[derive(Debug, Default)]
+pub struct JitDumpAgent {
+    /// File instance for the jit dump file
+    pub jitdump_file: Option<File>,
+    /// Unique identifier for jitted code
+    pub code_index: u64,
+    /// Flag for experimenting with dumping code load record
+    /// after each function (true) or after each module. This
+    /// flag is currently set to true.
+    pub dump_funcs: bool,
+}
+
+impl JitDumpAgent {
+    /// Intialize a JitDumpAgent and write out the header
+    pub fn init(&mut self) -> Result<(), Box<dyn Error>> {
+        #[cfg(target_os = "windows")]
+        return Err("Target OS not supported.");
+        #[cfg(not(target_os = "windows"))]
+        {
+            let filename = format!("./jit-{}.dump", process::id());
+            let mut jitdump_file;
+            unsafe {
+                let filename_c = CString::new(filename)?;
+                let fd = open(
+                    filename_c.as_ptr(),
+                    libc::O_CREAT | libc::O_TRUNC | libc::O_RDWR,
+                    0666,
+                );
+                let pgsz = sysconf(libc::_SC_PAGESIZE) as usize;
+                mmap(
+                    0 as *mut c_void,
+                    pgsz,
+                    libc::PROT_EXEC | libc::PROT_READ,
+                    libc::MAP_PRIVATE,
+                    fd,
+                    0,
+                );
+                jitdump_file = File::from_raw_fd(fd);
+            }
+            JitDumpAgent::write_file_header(&mut jitdump_file)?;
+            self.jitdump_file = Some(jitdump_file);
+            self.code_index = 0;
+            self.dump_funcs = true;
+            Ok(())
+        }
+    }
+
+    /// Returns timestamp from a single source
+    #[allow(unused_variables)]
+    fn get_time_stamp(timestamp: &mut u64) -> c_int {
+        #[cfg(not(target_os = "windows"))]
+        {
+            unsafe {
+                let mut ts = mem::MaybeUninit::zeroed().assume_init();
+                clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
+                // TODO: What does it mean for either sec or nsec to be negative?
+                *timestamp = (ts.tv_sec * 1000000000 + ts.tv_nsec) as u64;
+            }
+        }
+        return 0;
+    }
+
+    /// Returns the ELF machine architecture.
+    #[allow(dead_code)]
+    fn get_e_machine() -> u32 {
+        match target_lexicon::HOST.architecture {
+            Architecture::X86_64 => elf::header::EM_X86_64 as u32,
+            Architecture::I686 => elf::header::EM_386 as u32,
+            Architecture::Arm => elf::header::EM_ARM as u32,
+            Architecture::Armv4t => elf::header::EM_ARM as u32,
+            Architecture::Armv5te => elf::header::EM_ARM as u32,
+            Architecture::Armv7 => elf::header::EM_ARM as u32,
+            Architecture::Armv7s => elf::header::EM_ARM as u32,
+            Architecture::Aarch64 => elf::header::EM_AARCH64 as u32,
+            _ => unimplemented!("unrecognized architecture"),
+        }
+    }
+
+    #[allow(dead_code)]
+    fn write_file_header(file: &mut File) -> Result<(), JitDumpError> {
+        let mut header: FileHeader = Default::default();
+        let mut timestamp: u64 = 0;
+        JitDumpAgent::get_time_stamp(&mut timestamp);
+        header.timestamp = timestamp;
+
+        let e_machine = JitDumpAgent::get_e_machine();
+        if e_machine != elf::header::EM_NONE as u32 {
+            header.e_machine = e_machine;
+        }
+
+        if cfg!(target_endian = "little") {
+            header.magic = 0x4A695444
+        } else {
+            header.magic = 0x4454694a
+        }
+        header.version = 1;
+        header.size = mem::size_of::<FileHeader>() as u32;
+        header.pad1 = 0;
+        header.pid = process::id();
+        header.flags = 0;
+
+        file.iowrite_with(header, NATIVE)?;
+        Ok(())
+    }
+
+    fn write_code_load_record(
+        &mut self,
+        record_name: &str,
+        cl_record: CodeLoadRecord,
+        code_buffer: &[u8],
+    ) -> Result<(), JitDumpError> {
+        let mut jitdump_file = self.jitdump_file.as_ref().unwrap();
+        jitdump_file.iowrite_with(cl_record, NATIVE)?;
+        jitdump_file.write_all(record_name.as_bytes())?;
+        jitdump_file.write_all(b"\0")?;
+        jitdump_file.write_all(code_buffer)?;
+        Ok(())
+    }
+
+    /// Write DebugInfoRecord to open jit dump file.
+    /// Must be written before the corresponding CodeLoadRecord.
+    fn write_debug_info_record(&mut self, dir_record: DebugInfoRecord) -> Result<(), JitDumpError> {
+        self.jitdump_file
+            .as_ref()
+            .unwrap()
+            .iowrite_with(dir_record, NATIVE)?;
+        Ok(())
+    }
+
+    /// Write DebugInfoRecord to open jit dump file.
+    /// Must be written before the corresponding CodeLoadRecord.
+    fn write_debug_info_entries(
+        &mut self,
+        die_entries: Vec<DebugEntry>,
+    ) -> Result<(), JitDumpError> {
+        for entry in die_entries.iter() {
+            let mut jitdump_file = self.jitdump_file.as_ref().unwrap();
+            jitdump_file.iowrite_with(entry.address, NATIVE)?;
+            jitdump_file.iowrite_with(entry.line, NATIVE)?;
+            jitdump_file.iowrite_with(entry.discriminator, NATIVE)?;
+            jitdump_file.write_all(entry.filename.as_bytes())?;
+            jitdump_file.write_all(b"\0")?;
+        }
+        Ok(())
+    }
+
+    /// Sent when a method is compiled and loaded into memory by the VM.
+    pub fn module_load(
+        &mut self,
+        module_name: &str,
+        addr: *const u8,
+        len: usize,
+        dbg_image: Option<&[u8]>,
+    ) -> () {
+        let pid = process::id();
+        let tid = pid; // ThreadId does appear to track underlying thread. Using PID.
+
+        if let Some(img) = &dbg_image {
+            if let Err(err) = self.dump_from_debug_image(img, module_name, addr, len, pid, tid) {
+                println!(
+                    "Jitdump: module_load failed dumping from debug image: {:?}\n",
+                    err
+                );
+            }
+        } else {
+            let mut timestamp: u64 = 0;
+            JitDumpAgent::get_time_stamp(&mut timestamp);
+            self.dump_code_load_record(module_name, addr, len, timestamp, pid, tid);
+        }
+    }
+
+    fn dump_code_load_record(
+        &mut self,
+        method_name: &str,
+        addr: *const u8,
+        len: usize,
+        timestamp: u64,
+        pid: u32,
+        tid: u32,
+    ) -> () {
+        let name_len = method_name.len() + 1;
+        let size_limit = mem::size_of::<CodeLoadRecord>();
+
+        let rh = RecordHeader {
+            id: RecordId::JitCodeLoad as u32,
+            record_size: size_limit as u32 + name_len as u32 + len as u32,
+            timestamp: timestamp,
+        };
+
+        let clr = CodeLoadRecord {
+            header: rh,
+            pid: pid,
+            tid: tid,
+            virtual_address: addr as u64,
+            address: addr as u64,
+            size: len as u64,
+            index: self.code_index,
+        };
+        self.code_index += 1;
+
+        unsafe {
+            let code_buffer: &[u8] = std::slice::from_raw_parts(addr, len);
+            if let Err(err) = self.write_code_load_record(method_name, clr, code_buffer) {
+                println!("Jitdump: write_code_load_failed_record failed: {:?}\n", err);
+            }
+        }
+    }
+
+    /// Attempts to dump debuginfo data structures, adding method and line level
+    /// for the jitted function.
+    pub fn dump_from_debug_image(
+        &mut self,
+        dbg_image: &[u8],
+        module_name: &str,
+        addr: *const u8,
+        len: usize,
+        pid: u32,
+        tid: u32,
+    ) -> Result<(), JitDumpError> {
+        let file = object::File::parse(&dbg_image).unwrap();
+        let endian = if file.is_little_endian() {
+            gimli::RunTimeEndian::Little
+        } else {
+            gimli::RunTimeEndian::Big
+        };
+
+        let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, JitDumpError> {
+            Ok(file
+                .section_data_by_name(id.name())
+                .unwrap_or(borrow::Cow::Borrowed(&[][..])))
+        };
+
+        let load_section_sup = |_| Ok(borrow::Cow::Borrowed(&[][..]));
+        let dwarf_cow = gimli::Dwarf::load(&load_section, &load_section_sup)?;
+        let borrow_section: &dyn for<'a> Fn(
+            &'a borrow::Cow<[u8]>,
+        )
+            -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
+            &|section| gimli::EndianSlice::new(&*section, endian);
+
+        let dwarf = dwarf_cow.borrow(&borrow_section);
+
+        let mut iter = dwarf.units();
+        while let Some(header) = iter.next()? {
+            let unit = match dwarf.unit(header) {
+                Ok(unit) => unit,
+                Err(_err) => {
+                    return Ok(());
+                }
+            };
+            self.dump_entries(unit, &dwarf, module_name, addr, len, pid, tid)?;
+            // TODO: Temp exit to avoid duplicate addresses being covered by only
+            // processing the top unit
+            break;
+        }
+        if !self.dump_funcs {
+            let mut timestamp: u64 = 0;
+            JitDumpAgent::get_time_stamp(&mut timestamp);
+            self.dump_code_load_record(module_name, addr, len, timestamp, pid, tid);
+        }
+        Ok(())
+    }
+
+    fn dump_entries<R: Reader>(
+        &mut self,
+        unit: gimli::Unit<R>,
+        dwarf: &gimli::Dwarf<R>,
+        module_name: &str,
+        addr: *const u8,
+        len: usize,
+        pid: u32,
+        tid: u32,
+    ) -> Result<(), JitDumpError> {
+        let mut depth = 0;
+        let mut entries = unit.entries();
+        while let Some((delta_depth, entry)) = entries.next_dfs()? {
+            if self.dump_funcs {
+                let record_header = RecordHeader {
+                    id: RecordId::JitCodeLoad as u32,
+                    record_size: 0,
+                    timestamp: 0,
+                };
+
+                let mut clr = CodeLoadRecord {
+                    header: record_header,
+                    pid: pid,
+                    tid: tid,
+                    virtual_address: 0,
+                    address: 0,
+                    size: 0,
+                    index: 0,
+                };
+                let mut clr_name: String = String::from(module_name);
+                let mut get_debug_entry = false;
+                depth += delta_depth;
+                assert!(depth >= 0);
+
+                if entry.tag() == gimli::constants::DW_TAG_subprogram {
+                    get_debug_entry = true;
+
+                    let mut attrs = entry.attrs();
+                    while let Some(attr) = attrs.next()? {
+                        if let Some(n) = attr.name().static_string() {
+                            if n == "DW_AT_low_pc" {
+                                clr.address = match attr.value() {
+                                    gimli::AttributeValue::Addr(address) => address,
+                                    _ => 0,
+                                };
+                                clr.virtual_address = clr.address;
+                            } else if n == "DW_AT_high_pc" {
+                                clr.size = match attr.value() {
+                                    gimli::AttributeValue::Udata(data) => data,
+                                    _ => 0,
+                                };
+                            } else if n == "DW_AT_name" {
+                                clr_name = match attr.value() {
+                                    gimli::AttributeValue::DebugStrRef(offset) => {
+                                        if let Ok(s) = dwarf.debug_str.get_str(offset) {
+                                            clr_name.push_str("::");
+                                            clr_name.push_str(&s.to_string_lossy()?);
+                                            clr_name
+                                        } else {
+                                            clr_name.push_str("::");
+                                            clr_name.push_str("?");
+                                            clr_name
+                                        }
+                                    }
+                                    _ => {
+                                        clr_name.push_str("??");
+                                        clr_name
+                                    }
+                                };
+                            }
+                        }
+                    }
+                }
+                if get_debug_entry {
+                    //  TODO: Temp check to make sure well only formed data is processed.
+                    if clr.address == 0 {
+                        continue;
+                    }
+                    //  TODO: Temp check to make sure well only formed data is processed.
+                    if clr_name == "?" {
+                        continue;
+                    }
+                    if clr.address == 0 || clr.size == 0 {
+                        clr.address = addr as u64;
+                        clr.virtual_address = addr as u64;
+                        clr.size = len as u64;
+                    }
+                    clr.header.record_size = mem::size_of::<CodeLoadRecord>() as u32
+                        + (clr_name.len() + 1) as u32
+                        + clr.size as u32;
+                    clr.index = self.code_index;
+                    self.code_index += 1;
+                    self.dump_debug_info(&unit, &dwarf, clr.address, clr.size, None)?;
+
+                    let mut timestamp: u64 = 0;
+                    JitDumpAgent::get_time_stamp(&mut timestamp);
+                    clr.header.timestamp = timestamp;
+
+                    unsafe {
+                        let code_buffer: &[u8] =
+                            std::slice::from_raw_parts(clr.address as *const u8, clr.size as usize);
+                        let _ = self.write_code_load_record(&clr_name, clr, code_buffer);
+                    }
+                }
+            } else {
+                let mut func_name: String = String::from("?");
+                let mut func_addr = 0;
+                let mut func_size = 0;
+
+                let mut get_debug_entry = false;
+                depth += delta_depth;
+                assert!(depth >= 0);
+                if entry.tag() == gimli::constants::DW_TAG_subprogram {
+                    get_debug_entry = true;
+
+                    let mut attrs = entry.attrs();
+                    while let Some(attr) = attrs.next()? {
+                        if let Some(n) = attr.name().static_string() {
+                            if n == "DW_AT_low_pc" {
+                                func_addr = match attr.value() {
+                                    gimli::AttributeValue::Addr(address) => address,
+                                    _ => 0,
+                                };
+                            } else if n == "DW_AT_high_pc" {
+                                func_size = match attr.value() {
+                                    gimli::AttributeValue::Udata(data) => data,
+                                    _ => 0,
+                                };
+                            } else if n == "DW_AT_name" {
+                                func_name = match attr.value() {
+                                    gimli::AttributeValue::DebugStrRef(offset) => {
+                                        if let Ok(s) = dwarf.debug_str.get_str(offset) {
+                                            func_name.clear();
+                                            func_name.push_str(&s.to_string_lossy()?);
+                                            func_name
+                                        } else {
+                                            func_name.push_str("?");
+                                            func_name
+                                        }
+                                    }
+                                    _ => {
+                                        func_name.push_str("??");
+                                        func_name
+                                    }
+                                };
+                            }
+                        }
+                    }
+                }
+                if get_debug_entry {
+                    //  TODO: Temp check to make sure well only formed data is processed.
+                    if func_addr == 0 {
+                        continue;
+                    }
+                    //  TODO: Temp check to make sure well only formed data is processed.
+                    if func_name == "?" {
+                        continue;
+                    }
+                    self.dump_debug_info(
+                        &unit,
+                        &dwarf,
+                        func_addr,
+                        func_size,
+                        Some(func_name.as_str()),
+                    )?;
+                }
+            }
+        }
+        Ok(())
+    }
+
+    fn dump_debug_info<R: Reader>(
+        &mut self,
+        unit: &gimli::Unit<R>,
+        dwarf: &gimli::Dwarf<R>,
+        address: u64,
+        size: u64,
+        file_suffix: Option<&str>,
+    ) -> Result<(), JitDumpError> {
+        let mut timestamp: u64 = 0;
+        JitDumpAgent::get_time_stamp(&mut timestamp);
+        if let Some(program) = unit.line_program.clone() {
+            let mut debug_info_record = DebugInfoRecord {
+                header: RecordHeader {
+                    id: RecordId::JitCodeDebugInfo as u32,
+                    record_size: 0,
+                    timestamp: timestamp,
+                },
+                address: address,
+                count: 0,
+            };
+
+            let mut debug_entries = Vec::new();
+            let mut debug_entries_total_filenames_len = 0;
+            let mut rows = program.rows();
+            while let Some((header, row)) = rows.next_row()? {
+                let row_file_index = row.file_index() - 1;
+                let myfile = dwarf
+                    .attr_string(
+                        &unit,
+                        header.file_names()[row_file_index as usize].path_name(),
+                    )
+                    .unwrap();
+                let filename = myfile.to_string_lossy()?;
+                let line = row.line().unwrap_or(0);
+                let column = match row.column() {
+                    gimli::ColumnType::Column(column) => column,
+                    gimli::ColumnType::LeftEdge => 0,
+                };
+
+                if (row.address() < address) || (row.address() > (address + size)) {
+                    continue;
+                }
+                let mut debug_entry = DebugEntry {
+                    address: row.address(),
+                    line: line as u32,
+                    discriminator: column as u32,
+                    filename: filename.to_string(),
+                };
+
+                if let Some(suffix) = file_suffix {
+                    debug_entry.filename.push_str("::");
+                    debug_entry.filename.push_str(suffix);
+                }
+
+                debug_entries_total_filenames_len += debug_entry.filename.len() + 1;
+                debug_entries.push(debug_entry);
+            }
+
+            debug_info_record.count = debug_entries.len() as u64;
+
+            let debug_entries_size = (debug_info_record.count
+                * (mem::size_of::<DebugEntry>() as u64 - mem::size_of::<String>() as u64))
+                + debug_entries_total_filenames_len as u64;
+            debug_info_record.header.record_size =
+                mem::size_of::<DebugInfoRecord>() as u32 + debug_entries_size as u32;
+
+            let _ = self.write_debug_info_record(debug_info_record);
+            let _ = self.write_debug_info_entries(debug_entries);
+        }
+        Ok(())
+    }
+}
+
+use crate::ProfilingAgent;
+impl ProfilingAgent for JitDumpAgent {
+    fn module_load(
+        &mut self,
+        module_name: &str,
+        addr: *const u8,
+        len: usize,
+        dbg_image: Option<&[u8]>,
+    ) -> () {
+        if self.jitdump_file.is_none() {
+            if JitDumpAgent::init(self).ok().is_some() {
+                JitDumpAgent::module_load(self, module_name, addr, len, dbg_image);
+            } else {
+                println!("Jitdump: Failed to initialize JitDumpAgent\n");
+            }
+        } else {
+            JitDumpAgent::module_load(self, module_name, addr, len, dbg_image);
+        }
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum JitDumpError {
+    GimliError(gimli::Error),
+    IOError,
+}
+
+impl Error for JitDumpError {
+    fn description(&self) -> &str {
+        match *self {
+            JitDumpError::GimliError(ref err) => err.description(),
+            JitDumpError::IOError => "An I/O error occurred.",
+        }
+    }
+}
+
+impl std::fmt::Display for JitDumpError {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
+        Debug::fmt(self, f)
+    }
+}
+
+impl From<gimli::Error> for JitDumpError {
+    fn from(err: gimli::Error) -> Self {
+        JitDumpError::GimliError(err)
+    }
+}
+
+impl From<std::io::Error> for JitDumpError {
+    fn from(_err: std::io::Error) -> Self {
+        JitDumpError::IOError
+    }
+}
+
+trait Reader: gimli::Reader<Offset = usize> + Send + Sync {}
+
+impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where
+    Endian: gimli::Endianity + Send + Sync
+{
+}
diff --git a/crates/profiling/src/lib.rs b/crates/profiling/src/lib.rs
new file mode 100644
index 000000000000..7e6c851a103a
--- /dev/null
+++ b/crates/profiling/src/lib.rs
@@ -0,0 +1,65 @@
+use std::error::Error;
+use std::fmt;
+
+#[cfg(feature = "jitdump")]
+mod jitdump;
+
+#[cfg(feature = "jitdump")]
+pub use crate::jitdump::JitDumpAgent;
+
+#[cfg(not(feature = "jitdump"))]
+pub type JitDumpAgent = NullProfilerAgent;
+
+/// Select which profiling technique to use
+#[derive(Debug, Clone, Copy)]
+pub enum ProfilingStrategy {
+    /// No profiler support
+    NullProfiler,
+
+    /// Collect profile for jitdump file format
+    JitDumpProfiler,
+}
+
+/// Common interface for profiling tools.
+pub trait ProfilingAgent {
+    /// Notify the profiler of a new module loaded into memory
+    fn module_load(
+        &mut self,
+        module_name: &str,
+        addr: *const u8,
+        len: usize,
+        dbg_image: Option<&[u8]>,
+    ) -> ();
+}
+
+/// Default agent for unsupported profiling build.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct NullProfilerAgent {}
+
+#[derive(Debug)]
+struct NullProfilerAgentError;
+
+impl fmt::Display for NullProfilerAgentError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "A profiler agent is not supported by this build")
+    }
+}
+
+// This is important for other errors to wrap this one.
+impl Error for NullProfilerAgentError {
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        // Generic error, underlying cause isn't tracked.
+        None
+    }
+}
+
+impl ProfilingAgent for NullProfilerAgent {
+    fn module_load(
+        &mut self,
+        _module_name: &str,
+        _addr: *const u8,
+        _len: usize,
+        _dbg_image: Option<&[u8]>,
+    ) -> () {
+    }
+}
diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml
index 6f8e8c86086d..e6ac4792fb70 100644
--- a/crates/runtime/Cargo.toml
+++ b/crates/runtime/Cargo.toml
@@ -11,6 +11,7 @@ readme = "README.md"
 edition = "2018"
 
 [dependencies]
+wasmtime-profiling = { path = "../profiling" }
 wasmtime-environ = { path = "../environ", version = "0.9.0" }
 region = "2.0.0"
 libc = { version = "0.2.60", default-features = false }
diff --git a/src/lib.rs b/src/lib.rs
index 9a1e161ff97f..1e64ecb98fff 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -31,6 +31,7 @@ use anyhow::{bail, Result};
 use std::path::PathBuf;
 use structopt::StructOpt;
 use wasmtime::{Config, Strategy};
+use wasmtime_profiling::ProfilingStrategy;
 
 pub use obj::compile_to_obj;
 
@@ -43,6 +44,13 @@ fn pick_compilation_strategy(cranelift: bool, lightbeam: bool) -> Result<Strateg
     })
 }
 
+fn pick_profiling_strategy(jitdump: bool) -> Result<ProfilingStrategy> {
+    Ok(match jitdump {
+        true => ProfilingStrategy::JitDumpProfiler,
+        false => ProfilingStrategy::NullProfiler,
+    })
+}
+
 fn init_file_per_thread_logger(prefix: &'static str) {
     file_per_thread_logger::initialize(prefix);
 
@@ -120,6 +128,10 @@ struct CommonOptions {
     #[structopt(long, conflicts_with = "cranelift")]
     lightbeam: bool,
 
+    /// Generate jitdump file (supported on --features=profiling build)
+    #[structopt(long)]
+    jitdump: bool,
+
     /// Run optimization passes on translated functions
     #[structopt(short = "O", long)]
     optimize: bool,
@@ -136,7 +148,8 @@ impl CommonOptions {
             .wasm_reference_types(self.enable_reference_types || self.enable_all)
             .wasm_multi_value(self.enable_multi_value || self.enable_all)
             .wasm_threads(self.enable_threads || self.enable_all)
-            .strategy(pick_compilation_strategy(self.cranelift, self.lightbeam)?)?;
+            .strategy(pick_compilation_strategy(self.cranelift, self.lightbeam)?)?
+            .profiler(pick_profiling_strategy(self.jitdump)?)?;
         if self.optimize {
             config.cranelift_opt_level(wasmtime::OptLevel::Speed);
         }
diff --git a/tests/instantiate.rs b/tests/instantiate.rs
index 7b21cdf78465..b9bd6e1064eb 100644
--- a/tests/instantiate.rs
+++ b/tests/instantiate.rs
@@ -24,7 +24,7 @@ fn test_environ_translate() {
     let cache_config = CacheConfig::new_cache_disabled();
     let mut compiler = Compiler::new(isa, CompilationStrategy::Auto, cache_config);
     unsafe {
-        let instance = instantiate(&mut compiler, &data, &mut resolver, false);
+        let instance = instantiate(&mut compiler, &data, &mut resolver, false, None);
         assert!(instance.is_ok());
     }
 }