The ELF runner is the runner responsible for launching


[](https://fuchsia.dev/docs/glossary#component)


based on standard executable files (ELF
format). It is a built-in runner and is available to all components.

## Using the ELF Runner

To use the ELF runner, the component's manifest must include a `program` block,
containing:

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
        }
    }

- The `runner` field with the value set to the string `elf`.
- The `binary` field with the value set to a binary output name in the component's package.

## Fields

Additionally, the ELF runner accepts a set of optional fields to configure
the ELF component's runtime environment.

### Arguments

Arguments (that is, `argv` in most programming languages) can be passed to a
component's process using the `args` field. This field accepts a vector of
strings (see the example below).
The arguments set will be passed in the same order as declared in the manifest.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            args: \["--verbose", "--debug"\]
        }
    }

### Forwarding stdout and stderr streams

The stdout and stderr streams of ELF components can be routed to the
[LogSink service](https://fuchsia.dev/docs/development/diagnostics/logs/recording#logsinksyslog). By default, the ELF runner only forwards these
streams if LogSink is available to the component. If your component prints
diagnostics messages to either of these streams, you should forward the streams
to the [LogSink service](https://fuchsia.dev/docs/development/diagnostics/logs/recording#logsinksyslog).

To enable this feature, add the following to your manifest file:

    {
        include: [ "syslog/client.shard.cml" ],
    }

After including this shard, all writes to stdout are logged as `INFO` messages,
and all writes to stderr are logged as `WARN` messages. Messages are split
by newlines and decoded as UTF-8 strings. Invalid byte sequences are converted
to the U+FFFD replacement character, which usually looks like `�`.

Whether or not the syslog shard is included, this feature can be disabled with
explicit flags:

        program: {
            runner: "elf",
            binary: "bin/foo",
            forward_stdout_to: "none",
            forward_stderr_to: "none",
        }

> [!NOTE]
> **Note:** There are known issues where messages from `ZX_ASSERT_...` in C/C++ components and `Error` objects returned in `main` in Rust components are lost when stdout/stderr forwarding is disabled.

### Lifecycle

Components have a [lifecycle](https://fuchsia.dev/fuchsia-src/concepts/components/v2/lifecycle). Components run by the ELF runner can
integrate with the lifecycle if you add a `lifecycle` attribute to your component
manifest. Currently `stop` is the only method in the Lifecycle protocol.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            lifecycle: { stop_event: "notify" },
        }
    }

The program should take the handle to the Lifecycle channel and serve the
[Lifecycle protocol](https://cs.opensource.google/fuchsia/fuchsia/+/main:/sdk/fidl/fuchsia.process.lifecycle/lifecycle.fidl) on that channel. The component should exit after
receiving and processing the `stop` call.

The ELF Runner monitors the process it started for the program binary of the
component. If this process exits, the ELF runner will terminate the component's
execution context, which includes the component's job and all subprocesses.

> [!NOTE]
> **Note:** For a complete lifecycle example, see [//examples/components/lifecycle](https://cs.opensource.google/fuchsia/fuchsia/+/main:/examples/components/lifecycle).

### Security

There are several privileged fields that are gated by an
[allowlist](https://cs.opensource.google/fuchsia/fuchsia/+/main:/src/security/policy/component_manager_policy.json5). Only components included in this allowlist
are able to use these fields. For all fields, the policy applies to the first
process in the component. The first process is the one created by ELF runner
for the binary declared in `program` block. All of the fields are booleans
that default to `false`.

#### Main Process Critical

The `main_process_critical` field may be used to mark the component's first
process as [critical to component manager's job](https://fuchsia.dev/reference/syscalls/job_set_critical), which will
cause component manager (and all components) to be terminated if the process
exits with a non-zero code. This will force the system to trigger a hard reboot.

#### Ambient VMO Exec

The `ambient_mark_vmo_exec` field may be used to allow the component's first
process to use [`zx_vmo_replace_as_executable`](https://fuchsia.dev/reference/syscalls/vmo_replace_as_executable) with a
`ZX_HANDLE_INVALID` as the second argument rather than a valid
`ZX_RSRC_KIND_SYSTEM` with base `ZX_RSRC_SYSTEM_VMEX_BASE`.

#### Create Raw Processes

The `job_policy_create_raw_processes` field may be used to allow a component to
create processes by using [`zx_process_create`](https://fuchsia.dev/reference/syscalls/process_create).

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            job_policy_create_raw_processes: "true"
        }
    }

#### Is Shared Process

The `is_shared_process` field may be used to pass the `ZX_PROCESS_SHARED` flag
when calling [`zx_process_create`](https://fuchsia.dev/reference/syscalls/process_create). This flag can only be used
if the component also has `job_policy_create_raw_processes` set to `true`.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            job_policy_create_raw_processes: "true",
            is_shared_process: "true"
        }
    }

#### Job with available exception channel

The `job_with_available_exception_channel` field may be used to make sure the
component is created as a direct descendent of a job that will have its
exception channel available for taking.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            job_with_available_exception_channel: "true"
        }
    }

#### Bad handle policy

The `job_policy_bad_handles` field configures the job's bad handle policy. The
supported values are `deny_exception` and `allow_exception` which correspond to
the `ZX_POL_ACTION_DENY_EXCEPTION` and `ZX_POL_ALLOW_EXCEPTION` actions
documented in
https://fuchsia.dev/reference/syscalls/job_set_policy#zx_job_pol_basic_v2_and_v1.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            job_policy_bad_handles: "deny_exception"
        }
    }

### Environment Variables

Environment variables can be set for ELF components by using the `environ`
attribute. This field must be a vector of strings where each string contains
the variable and value delimited by an equal sign. For example, the following
sample code declares variables `FAVORITE_ANIMAL` and `FAVORITE_COLOR` to `cat`
and `red`.

    {
        program: {
            runner: "elf",
            binary: "bin/echo",
            environ: \[
                "FAVORITE_ANIMAL=cat",
                "FAVORITE_COLOR=red",
            \]
        }
    }

#### Memory Attribution

The `memory_attribution` field can be set to allow the component to provide
additional memory attribution information beyond what the elf runner exports.
Most often this is useful for runners implementing memory attribution on behalf
of child components they start. In additional to setting this field to true,
the component should expose the `fuchsia.memory.attribution.Provider` FIDL
protocol from their component.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            memory_attribution: "true"
        }
    }

#### Use Next VDSO

The `use_next_vdso` field can be set to allow the component to utilize
experimental syscalls APIs available only through the "next" VDSO. These APIs
do not provide any stability guarantees.

    {
        program: {
            runner: "elf",
            binary: "bin/foo",
            use_next_vdso: "true"
        }
    }

## Further Reading

For a detailed explanation of how processes are created, please see
[Zircon program loading and dynamic linking](https://fuchsia.dev/docs/concepts/process/program_loading).
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/concepts/components/v2/elf_runner.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/concepts/components/v2/elf_runner.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/concepts/components/v2/elf_runner.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/concepts/components/v2/elf_runner.md "Edit the source code of this page")