# Getting Started with Picolibc on Hexagon This document walks through compiling and running your first picolibc program on Hexagon, from checking toolchain prerequisites to a working hello world on each supported target. ## Prerequisites You need a Hexagon toolchain that includes: - `hexagon-clang` (clang with the Hexagon backend) - `hexagon-link` or `eld` (the ELD linker) - Picolibc sysroots packaged under `target/picolibc/` in the toolchain tree Check your toolchain is on PATH: hexagon-clang --version # Should print clang version and "Target: hexagon-..." Copy to clipboard Verify picolibc targets are available: # H2 target hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ --print-file-name=libc.a # Should print a real path, not just "libc.a" # Bare-metal target hexagon-clang --target=hexagon-unknown-none-elf --cstdlib=picolibc \ --print-file-name=libc.a Copy to clipboard If either prints only `libc.a` (not found), your toolchain does not include that sysroot. Check with your toolchain maintainer. * * * ## Hello World: H2 target The H2 hypervisor is the most common hosted environment for Hexagon picolibc programs. Full details are in [H2 + Picolibc](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-h2.html); this section gives the minimal end-to-end flow. ### 1. Write the program /* hello.c */ #include int main(void) { printf("Hello from picolibc on H2!\n"); return 0; } Copy to clipboard ### 2. Set toolchain root TOOLCHAIN=/path/to/your/hexagon/toolchain Copy to clipboard ### 3. Compile ${TOOLCHAIN}/Tools/bin/hexagon-clang \ --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T ${TOOLCHAIN}/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o hello hello.c Copy to clipboard Mandatory flags summary: | Flag | Why | | --- | --- | | `--target=hexagon-unknown-h2-elf` | Selects H2 ABI, sysroot, and runtime libraries | | `--cstdlib=picolibc` | Selects picolibc instead of the default libc | | `-Wl,--section-start=.start=0x2000000` | H2 boots by jumping to 0x2000000 | | `-T ` | Provides memory layout; not auto-applied by the driver | > > > [!NOTE] > For a simpler way to compile H2 programs, use the `h2-picolibc.cfg` clang > configuration file in `${TOOLCHAIN}/Tools/bin/`. The configuration supplies > the target, picolibc selection, H2 lock support, entry-point address, and > linker-script path. > > > ${TOOLCHAIN}/Tools/bin/hexagon-clang \ > --target=hexagon-unknown-h2-elf \ > --config=h2-picolibc.cfg \ > -o hello hello.c > Copy to clipboard ### 4. Run on the simulator hexagon-sim \ ${TOOLCHAIN}/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter \ -- hello Copy to clipboard Expected output: Hello from picolibc on H2! Copy to clipboard * * * ## Hello World: bare-metal with semihosting For targets without H2, picolibc can use QEMU semihosting for I/O (stdio, file access, exit). Full details are in [Bare-Metal + Picolibc](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-baremetal.html). ### 1. Write the program /* hello.c */ #include int main(void) { printf("Hello from picolibc on bare-metal!\n"); return 0; } Copy to clipboard ### 2. Compile hexagon-clang \ --target=hexagon-unknown-none-elf \ --cstdlib=picolibc \ -mv68 \ -G0 \ -T picolibc.ld \ -o hello hello.c Copy to clipboard ### 3. Run under QEMU qemu-system-hexagon \ -cpu v68 \ -machine virt \ -nographic \ -kernel hello Copy to clipboard Expected output: Hello from picolibc on bare-metal! Copy to clipboard * * * ## Common errors and fixes ### `error: no such file or directory: 'picolibc/...'` The `--cstdlib=picolibc` flag was accepted but the sysroot files are missing. Check your toolchain installation or use `--print-file-name=libc.a` as shown in the prerequisites section. ### `ld: error: undefined symbol: main` Your file compiled but the symbol is misspelled or the wrong file was passed. Verify with `hexagon-readelf -s hello.o | grep main`. ### `ld: error: ... section `.start` not found` The `-T` linker script flag is missing or points to the wrong file. The clang driver does not add the H2 picolibc linker script automatically. ### Program starts then crashes immediately (H2) The entry point address is wrong. Ensure `-Wl,--section-start=.start=0x2000000` is present. Without it the linker places `.start` at the default address and H2 jumps to the wrong location. ### `ld: error: ... -G0` / small-data section mismatch Only add `-G0` when the application must disable UGP-relative small-data accesses. H2 itself is built with `-G0` because it manages UGP, but H2 applications may use UGP in user mode. Ensure all application objects use the same small-data setting. * * * ## Next steps - [H2 + Picolibc](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-h2.html) — heap sizing, stack sizing, TLS, memory layout - [Bare-Metal + Picolibc](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-baremetal.html) — linker scripts, custom memory maps, no-semihosting stubs - [Semihosting](https://docs.qualcomm.com/doc/80-N3040-23/topic/semihosting.html) — TRAP0 interface details, syscall opcodes, QEMU integration Last Published: Oct 06, 2026 [Previous Topic Key flags at a glance](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/README.md) [Next Topic H2 + Picolibc Usage Guide](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/picolibc-h2.md)