Add Centipede support.
diff --git a/WORKSPACE b/WORKSPACE
index 72e82b7..f944db9 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -20,7 +20,10 @@
 
 load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
 
-rules_fuzzing_dependencies(jazzer = True)
+rules_fuzzing_dependencies(
+    centipede = True,
+    jazzer = True,
+)
 
 load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
 
diff --git a/fuzzing/engines/BUILD b/fuzzing/engines/BUILD
index ab38bc4..e9dfa8b 100644
--- a/fuzzing/engines/BUILD
+++ b/fuzzing/engines/BUILD
@@ -15,6 +15,7 @@
 load("//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
 load("//fuzzing:java_defs.bzl", "java_fuzzing_engine")
 load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
 
 # libFuzzer specification.
 ##########################
@@ -51,6 +52,27 @@
     visibility = ["//visibility:public"],
 )
 
+# Centipede specification.
+##########################
+
+string_flag(
+    name = "llvm_symbolizer",
+    build_setting_default = "llvm-symbolizer",
+    visibility = ["//visibility:public"],
+)
+
+cc_fuzzing_engine(
+    name = "centipede",
+    display_name = "Centipede",
+    launcher = "centipede_launcher.sh",
+    launcher_data = {
+        "@centipede//:centipede": "CENTIPEDE_PATH",
+        ":llvm_symbolizer": "LLVM_SYMBOLIZER_PATH",
+    },
+    library = "@centipede//:fuzz_target_runner",
+    visibility = ["//visibility:public"],
+)
+
 # The replay engine specification.
 ##################################
 
diff --git a/fuzzing/engines/centipede_launcher.sh b/fuzzing/engines/centipede_launcher.sh
new file mode 100644
index 0000000..8c0334d
--- /dev/null
+++ b/fuzzing/engines/centipede_launcher.sh
@@ -0,0 +1,31 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+command_line="$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${CENTIPEDE_PATH})"
+# command_line+=("--alsologtostderr")
+command_line+=("--workdir=${FUZZER_OUTPUT_ROOT}")
+command_line+=("--symbolizer_path=${LLVM_SYMBOLIZER_PATH}")
+
+if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
+    >&2 echo "WARNING: Seed corpus not supported yet."
+fi
+if (( FUZZER_IS_REGRESSION )); then
+    >&2 echo "ERROR: Regression mode not supported yet."
+    exit 1
+fi
+
+command_line+=("--binary=${FUZZER_BINARY}")
+
+echo "${command_line[@]}"
+exec "${command_line[@]}" "$@"
diff --git a/fuzzing/instrum_opts.bzl b/fuzzing/instrum_opts.bzl
index b497155..f60f5a1 100644
--- a/fuzzing/instrum_opts.bzl
+++ b/fuzzing/instrum_opts.bzl
@@ -35,6 +35,7 @@
     "libfuzzer": instrum_defaults.libfuzzer,
     "jazzer": instrum_defaults.jazzer,
     "honggfuzz": instrum_defaults.honggfuzz,
+    "centipede": instrum_defaults.centipede,
     "oss-fuzz": oss_fuzz_opts,
 }
 
diff --git a/fuzzing/private/common.bzl b/fuzzing/private/common.bzl
index 27c8107..1d52f19 100644
--- a/fuzzing/private/common.bzl
+++ b/fuzzing/private/common.bzl
@@ -34,7 +34,10 @@
     script_content = script_template.format(
         environment = "\n".join([
             "export %s='%s'" % (var, file.short_path)
-            for var, file in binary_info.engine_info.launcher_environment.items()
+            for var, file in binary_info.engine_info.launcher_environment_files.items()
+        ] + [
+            "export %s='%s'" % (var, value)
+            for var, value in binary_info.engine_info.launcher_environment_vars.items()
         ]),
         launcher = ctx.executable._launcher.short_path,
         binary_path = ctx.executable.binary.short_path,
diff --git a/fuzzing/private/engine.bzl b/fuzzing/private/engine.bzl
index 9d8656d..f4b428c 100644
--- a/fuzzing/private/engine.bzl
+++ b/fuzzing/private/engine.bzl
@@ -14,6 +14,8 @@
 
 """The implementation of the {cc, java}_fuzzing_engine rules."""
 
+load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
+
 FuzzingEngineInfo = provider(
     doc = """
 Provider for storing the language-independent part of the specification of a fuzzing engine.
@@ -22,7 +24,8 @@
         "display_name": "A string representing the human-readable name of the fuzzing engine.",
         "launcher": "A file representing the shell script that launches the fuzz target.",
         "launcher_runfiles": "The runfiles needed by the launcher script on the fuzzing engine side, such as helper tools and their data dependencies.",
-        "launcher_environment": "A dictionary from environment variables to files used by the launcher script.",
+        "launcher_environment_files": "A dictionary from environment variables to files used by the launcher script.",
+        "launcher_environment_vars": "A dictionary from environment variables to values used by the launcher script.",
     },
 )
 
@@ -32,22 +35,31 @@
 
     launcher_runfiles = ctx.runfiles(files = [ctx.file.launcher])
     env_vars = {}
+    env_files = {}
     for data_label, data_env_var in ctx.attr.launcher_data.items():
-        data_files = data_label.files.to_list()
-        if data_env_var:
-            if data_env_var in env_vars:
-                fail("Multiple data dependencies map to variable '%s'." % data_env_var)
-            if len(data_files) != 1:
-                fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
-            env_vars[data_env_var] = data_files[0]
-        launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
-        launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)
+        if data_env_var in env_vars or data_env_var in env_files:
+            fail("Multiple data dependencies map to variable '%s'." % data_env_var)
+
+        # We assume data dependencies are either build setting value, or targets representing exactly one file.
+        if BuildSettingInfo in data_label:
+            if not data_env_var:
+                fail("Build setting '%s' must map to an environment variable" % data_label)
+            env_vars[data_env_var] = data_label[BuildSettingInfo].value
+        else:
+            data_files = data_label.files.to_list()
+            if data_env_var:
+                if len(data_files) != 1:
+                    fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
+                env_files[data_env_var] = data_files[0]
+            launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
+            launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)
 
     return FuzzingEngineInfo(
         display_name = ctx.attr.display_name,
         launcher = ctx.file.launcher,
         launcher_runfiles = launcher_runfiles,
-        launcher_environment = env_vars,
+        launcher_environment_files = env_files,
+        launcher_environment_vars = env_vars,
     )
 
 def _cc_fuzzing_engine_impl(ctx):
diff --git a/fuzzing/private/instrum_opts.bzl b/fuzzing/private/instrum_opts.bzl
index a2f21a9..b4fffe5 100644
--- a/fuzzing/private/instrum_opts.bzl
+++ b/fuzzing/private/instrum_opts.bzl
@@ -105,6 +105,19 @@
             "-fno-sanitize=fuzzer",
         ],
     ),
+    centipede = _make_opts(
+        copts = [
+            "-gline-tables-only",
+            "-fno-builtin",
+            "-fsanitize-coverage=trace-pc-guard,pc-table,trace-loads,trace-cmp",
+        ],
+        linkopts = [
+            # "-Wl,--warn-backrefs-exclude=*/centipede/*runner*.o",
+
+            # TODO(sbucur): Should be added to centipede/runner.cc linkopts.
+            "-lpthread",
+        ],
+    ),
     asan = _make_opts(
         copts = ["-fsanitize=address"],
         linkopts = ["-fsanitize=address"],
diff --git a/fuzzing/repositories.bzl b/fuzzing/repositories.bzl
index 5ca94e6..80b9719 100644
--- a/fuzzing/repositories.bzl
+++ b/fuzzing/repositories.bzl
@@ -18,12 +18,17 @@
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
 load("//fuzzing/private/oss_fuzz:repository.bzl", "oss_fuzz_repository")
 
-def rules_fuzzing_dependencies(oss_fuzz = True, honggfuzz = True, jazzer = False):
+def rules_fuzzing_dependencies(
+        oss_fuzz = True,
+        honggfuzz = True,
+        centipede = False,
+        jazzer = False):
     """Instantiates the dependencies of the fuzzing rules.
 
     Args:
       oss_fuzz: Include OSS-Fuzz dependencies.
       honggfuzz: Include Honggfuzz dependencies.
+      centipede: Include Centipede dependencies.
       jazzer: Include Jazzer repository. Instantiating all Jazzer dependencies
         additionally requires invoking jazzer_dependencies() in
         @jazzer//:repositories.bzl and jazzer_init() in @jazzer//:init.bzl.
@@ -78,6 +83,25 @@
             strip_prefix = "honggfuzz-e0670137531242d66c9cf8a6dee677c055a8aacb",
         )
 
+    if centipede:
+        maybe(
+            http_archive,
+            name = "centipede",
+            sha256 = "f52b8ae44e183b8f9501e382316de28d4c5b8d333af65d76def2d1b4b0b4a9a5",
+            url = "https://github.com/google/centipede/archive/d98e302e10a21aff0bbfae96b68ff61ab8f9d1ab.zip",
+            strip_prefix = "centipede-d98e302e10a21aff0bbfae96b68ff61ab8f9d1ab",
+        )
+
+        # TODO(sbucur): This should be provided by Centipede as an initialization library.
+        boringssl_ver = "18637c5f37b87e57ebde0c40fe19c1560ec88813"
+        maybe(
+            http_archive,
+            name = "boringssl",
+            sha256 = "7514826d98f032c16531de9f4c05e7bd05e07545ca39201d1616fa7ba3deadbc",
+            strip_prefix = "boringssl-%s" % boringssl_ver,
+            url = "https://github.com/google/boringssl/archive/%s.tar.gz" % boringssl_ver,
+        )
+
     if jazzer:
         maybe(
             http_archive,