# H2 + Picolibc Usage Guide ## Quick Reference ### Minimal Compilation Command hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Required flags**: - `--target=hexagon-unknown-h2-elf`: Use H2 - `--cstdlib=picolibc`: Use picolibc instead of standard libc - `-Wl,--section-start=.start=0x2000000`: Place entry point at 32 MB (H2 requirement) - `-T `: Explicitly pass the H2+Picolibc template linker script — **the clang driver does NOT add this automatically; linking will fail without it** For the linker-script layout and symbols, see [Linker Script](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-h2.html#linker-script-required). **What the target flag automatically provides**: - Links H2 libraries (`-lh2 -lsyscall_wrapper -lc -lclang_rt.builtins`) - Uses correct startup file (`crt0-noflash-hosted.o`) - Sets up heap (64 KB default) and stack (4 KB default) > > > [!TIP] > For a simpler way to compile H2 programs, use the `h2-picolibc.cfg` clang > configuration file in `${TOOLCHAIN}/Tools/bin/`. It supplies the canonical > 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 ### With Custom Heap/Stack hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__heap_size_min=0x4000000 \ -Wl,--defsym=__stack_size=0x4000 \ -o myprogram myprogram.c Copy to clipboard ### G0 application variant H2 itself is built with `-G0` because it manages UGP. Applications run in user mode and may use UGP, so `-G0` is not part of the canonical application command. Add `-G0` only when the application must disable UGP-relative small-data accesses, and use the same setting for every application object. * * * ## Overview This document describes how to use Picolibc with the H2 hypervisor for Hexagon, including proper compilation flags, linker script configuration, heap management, and memory layout requirements. ## What is H2? H2 is a lightweight hypervisor for Hexagon DSP that provides: - Virtual memory management - Thread management - Process isolation - System call interface When using Picolibc with H2, special considerations are needed for: - Entry point placement - Memory layout - Heap configuration - Thread-Local Storage (TLS) - Stack setup ## First program For a minimal source file, compile command, and simulator invocation, start with [Getting Started](https://docs.qualcomm.com/doc/80-N3040-23/topic/getting-started.html#hello-world-h2-target). This guide covers the H2-specific configuration and reference material that follow. ## Compilation and Linking ### Basic Command hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Required flags**: - `--target=hexagon-unknown-h2-elf`: Selects H2 target - `--cstdlib=picolibc`: Selects Picolibc as the C standard library - `-Wl,--section-start=.start=0x2000000`: Explicitly places entry point at 32 MB - `-T `: Passes the H2+Picolibc template linker script — **not added automatically by the clang driver** ### Compiler Target Flag --target=hexagon-unknown-h2-elf --cstdlib=picolibc Copy to clipboard **Purpose**: `--target=hexagon-unknown-h2-elf` selects the H2 target and `--cstdlib=picolibc` selects Picolibc as the C standard library. These flags automatically configure: - Correct Picolibc headers from H2-specific sysroot - Correct Picolibc libraries for H2 - H2-specific runtime support - Proper ABI conventions ### What the Target Flag Automatically Configures When you use `--target=hexagon-unknown-h2-elf --cstdlib=picolibc`, the compiler automatically: 1. **Sets up include paths**: /path/to/toolchain/Tools/lib/clang/23/include /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/include Copy to clipboard 2. **Selects the correct startup file and multilib**: crt0-noflash-hosted.o Copy to clipboard The driver selects the appropriate target library directory; do not hard-code a multilib directory in application build scripts. 3. **Links required libraries** (in order): --start-group -lh2 # H2 hypervisor library -lsyscall_wrapper # System call wrapper library -lc # Picolibc C library -lclang_rt.builtins # Compiler runtime builtins --end-group Copy to clipboard 4. **Configures linker settings**: - Uses `hexagon-link` (ELD linker) - Sets `-march=hexagon -mcpu=hexagonv68` - **Does NOT automatically apply the H2+Picolibc linker script** — you must pass it explicitly with `-T` 5. **Sets compiler flags**: - `-target-cpu hexagonv68` - `-mrelocation-model static` - `-fno-signed-char` - `-fshort-enums` ### Required Linker Flag: Entry Point -Wl,--section-start=.start=0x2000000 Copy to clipboard **Purpose**: Explicitly places the `.start` section (containing `_start` entry point) at address `0x2000000` (32 MB). **Why this is required**: - H2 hypervisor boots and jumps to this fixed address - The `.start` section contains the `_start` symbol (program entry point) - This must match H2’s boot sequence expectations - **This flag is mandatory** - the linker script alone does not set this address **What happens without it**: - Entry point will be placed at the default address (not `0x2000000`) - H2 will jump to the wrong location - Program will fail to start or crash immediately **Address breakdown**: - `0x2000000` = 32 MB = 33,554,432 bytes - This is where H2 expects to find the first instruction of your program ### Optional Compiler Flag: `-G0` -G0 Copy to clipboard **Purpose**: Disables the small data section (GP-relative addressing). **When to use it**: - H2 is built with `-G0` because it manages UGP. - H2 applications run in user mode and may use UGP, so they can omit `-G0`. - Add `-G0` only when an application deliberately disables UGP-relative small-data accesses; compile all of that application’s objects consistently. **What `-G0` means**: - No small data section (`.sdata`, `.sbss`) - All data uses absolute addressing (not GP-relative) - Small data threshold is set to 0 bytes - The `_SDA_BASE_` symbol is not used Without `-G0`, the compiler may use UGP-relative small-data accesses. That is supported for H2 applications in user mode. ### Linker Script (Required) The H2+Picolibc linker script **must be passed explicitly** using the `-T` flag. The clang driver does **not** add it automatically — linking will fail without it. -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template Copy to clipboard **Location**: `/path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template` **Purpose**: The H2+Picolibc linker script provides: - Memory layout compatible with H2 - Symbols expected by Picolibc runtime - Heap and stack configuration - TLS (Thread-Local Storage) setup - Proper section ordering **Key features of the linker script**: 1. Defines `.start` section for entry point (address set by `-Wl,--section-start`) 2. Heap symbols for malloc/free (`__heap_start`, `__heap_end`) 3. Stack symbols for runtime (`__stack`, `__stack_size`) 4. TLS space allocation for main thread 5. BSS initialization markers (`__bss_start`, `__bss_end`) **Important**: The linker script defines the `.start` section structure, but **you must explicitly set its address** using `-Wl,--section-start=.start=0x2000000`. The linker script does not hardcode this address. ## H2 Runtime Libraries The H2+Picolibc toolchain automatically links several libraries required for H2 operation: ### Library Linking Order --start-group -lh2 # H2 hypervisor library -lsyscall_wrapper # System call wrapper library -lc # Picolibc C library -lclang_rt.builtins # Compiler runtime builtins --end-group Copy to clipboard **Note**: The `--start-group` and `--end-group` flags allow circular dependencies between libraries to be resolved. ### Library Descriptions #### 1. libh2.a - H2 Hypervisor Library **Purpose**: Provides the H2 hypervisor runtime support. **Functionality**: - Virtual memory management - Thread creation and management - Process isolation - H2-specific system calls - Event handling - Hardware abstraction **Location**: Selected by the H2 target’s multilib configuration. #### 2. libsyscall\_wrapper.a - System Call Wrapper Library **Purpose**: Provides wrapper functions for H2 system calls. **Functionality**: - Translates POSIX-style calls to H2 system calls - Handles system call ABI - Error code translation - Bridges Picolibc to H2 kernel **Common functions**: - `open()`, `close()`, `read()`, `write()` - `malloc()` / `free()` (heap management) - `exit()`, `_exit()` - Thread management functions **Location**: Selected by the H2 target’s multilib configuration. #### 3. libc.a - Picolibc C Library **Purpose**: Standard C library implementation. **Functionality**: - Standard C functions (stdio, stdlib, string, etc.) - Memory allocation (malloc, free, realloc, calloc) - String operations (strcpy, strcmp, strlen, etc.) - I/O operations (printf, scanf, fopen, etc.) - Math functions (via libm) **Location**: Selected by the H2 target’s multilib configuration. #### 4. libclang\_rt.builtins.a - Compiler Runtime Builtins **Purpose**: Compiler-generated runtime support functions. **Functionality**: - Software floating-point operations - Integer division and modulo (if not in hardware) - 64-bit integer operations - Memory operations (memcpy, memset, memmove) - Stack protection functions - Other compiler intrinsics **Location**: Selected by the H2 target’s multilib configuration. **Note**: For H2+Picolibc, the builtins library is located in the target-specific directory, not in the clang resource directory. ### Startup File #### crt0-noflash-hosted.o **Purpose**: C runtime startup code for H2 hosted environment. **Functionality**: - Entry point (`_start`) at `0x02000000` - Stack pointer initialization - BSS section zeroing - Data section initialization (if needed) - TLS initialization for main thread - Call C++ constructors (`.init_array`) - Call `main()` function - Call C++ destructors (`.fini_array`) on exit - Exit to H2 via system call **Naming**: - `noflash`: No flash memory initialization (RAM-based) - `hosted`: Runs in H2 hosted environment (not bare metal) **Location**: Selected by the H2 target’s multilib configuration. **Note**: This is different from bare-metal `crt0.o` which would handle flash-to-RAM copying and bare-metal initialization. ### H2 Booter #### booter **Purpose**: H2 hypervisor booter executable that loads and runs H2 applications. **Functionality**: - Initializes H2 hypervisor environment - Sets up virtual memory - Loads application at `0x2000000` - Transfers control to application entry point - Provides system call interface to applications **Location**: `/path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter` **Usage**: Run with `hexagon-sim`: hexagon-sim /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram Copy to clipboard ## Memory Layout ### Address Space The H2+Picolibc linker script defines the following memory layout, from the entry point at the bottom of the address space up through the stack: ![block-beta columns 1 s1\[".start (0x02000000) — Entry point (_start)"\] s2\[".init — Initialization code"\] s3\[".text — Program code"\] s4\[".rodata — Read-only data (constants)"\] s5\[".eh_frame — Exception handling info"\] s6\[".tdata — TLS initialized data"\] s7\[".tbss — TLS uninitialized data"\] s8\[".tls_space — TLS space for main thread"\] s9\[".data — Initialized data"\] s10\[".sdata — Small data (GP-relative)"\] s11\[".sbss — Small BSS"\] s12\[".bss — Uninitialized data"\] s13\[".heap — Dynamic memory (malloc)"\] s14\[".stack — Program stack"\] classDef mem fill:#EAF0FE,stroke:#3253DC,stroke-width:1.5px,color:#1E3BAE; class s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14 mem](data:image/png;base64,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) ### Section Alignment Key sections are aligned to 4KB (4096 bytes) boundaries: - `.init` section: 4KB aligned - `.rodata` section: 4KB aligned - `.tls_space` section: 4KB aligned - `.data` section: 4KB aligned - `.sdata` section: 4KB aligned This alignment is required for: - H2 page table management - Memory protection - Cache efficiency ## Heap Configuration ### Heap Symbols The linker script defines these symbols for heap management: extern char __heap_start; // Start of heap region extern char __heap_end; // End of heap region extern size_t HEAP_SIZE; // Total heap size Copy to clipboard ### Linker Script Heap Definition From `static-executable-h2-picolibc.lcs.template`: /* Picolibc looks for __heap* and __stack* symbols */ /* Allow a minimum heap size to be specified */ __heap_start = .; .heap (NOLOAD) : { . += (DEFINED(__heap_size_min) ? __heap_size_min : 0x10000); } __heap_end = .; HEAP_SIZE = __heap_end - __heap_start; Copy to clipboard **Key points**: 1. **Default heap size**: `0x10000` (64 KB) 2. **Customizable**: Can override with `__heap_size_min` symbol 3. **NOLOAD**: Heap is not loaded from file (saves space) 4. **Symbols**: `__heap_start` and `__heap_end` mark boundaries ### Customizing Heap Size #### Method 1: Linker Flag hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x02000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__heap_size_min=0x100000 \ -o myprogram myprogram.c Copy to clipboard This sets heap size to 1 MB (`0x100000`). #### Method 2: Assembly File Create `heap_config.S`: .global __heap_size_min .set __heap_size_min, 0x100000 Copy to clipboard Compile with: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x02000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c heap_config.S Copy to clipboard #### Method 3: Modified Linker Script Copy and modify the linker script: .heap (NOLOAD) : { . += (DEFINED(__heap_size_min) ? __heap_size_min : 0x100000); /* 1 MB default */ } Copy to clipboard ### How Picolibc Uses Heap Symbols Picolibc’s `malloc()` implementation uses these symbols: // Simplified malloc implementation void *malloc(size_t size) { static char *heap_ptr = NULL; if (heap_ptr == NULL) { heap_ptr = &__heap_start; } if (heap_ptr + size > &__heap_end) { return NULL; // Out of memory } void *result = heap_ptr; heap_ptr += size; return result; } Copy to clipboard **Note**: Actual implementation is more sophisticated with: - Memory alignment - Free list management - Coalescing of freed blocks - Thread safety (if enabled) ## Stack Configuration ### Stack Symbols extern char __stack; // Top of stack (highest address) extern size_t __stack_size; // Stack size extern size_t STACK_SIZE; // Alias for stack size Copy to clipboard ### Linker Script Stack Definition __stack_size = 0x1000; STACK_SIZE = __stack_size; /* Define a stack region to make sure it fits in memory */ .stack (NOLOAD) : { . += (DEFINED(__stack_size) ? __stack_size : 0x00001000); } __stack = .; Copy to clipboard **Key points**: 1. **Default stack size**: `0x1000` (4 KB) 2. **Customizable**: Can override with `__stack_size` symbol 3. **Stack grows down**: `__stack` is the top (highest address) 4. **NOLOAD**: Stack is not loaded from file ### Customizing Stack Size hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x02000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__stack_size=0x4000 \ -o myprogram myprogram.c Copy to clipboard This sets stack size to 16 KB (`0x4000`). ## Thread-Local Storage (TLS) ### TLS Symbols The linker script defines symbols for TLS: extern char __tdata_start; // Start of TLS initialized data extern char __tdata_end; // End of TLS initialized data extern size_t __tdata_size; // Size of TLS initialized data extern char __tbss_start; // Start of TLS uninitialized data extern char __tbss_end; // End of TLS uninitialized data extern size_t __tbss_size; // Size of TLS uninitialized data extern size_t __tbss_offset; // Offset of .tbss from .tdata extern char __tls_base; // Base of TLS space for main thread extern size_t __tls_space_size; // Total TLS size Copy to clipboard ### TLS Memory Layout /* TLS Initialized Data */ .tdata : { _TLS_START_ = .; TLS_START = _TLS_START_; /* Picolibc uses __tdata_* symbols to locate TLS template */ __tdata_source = .; __tdata_start = __tdata_source; *(.tdata .tdata.* *.gnu.linkonce.td.*) } _TLS_DATA_END_ = .; __tdata_end = _TLS_DATA_END_; __tdata_size = __tdata_end - __tdata_source; /* TLS Uninitialized BSS */ .tbss : { __tbss_start = .; *(.tbss .tbss.* .gnu.linkonce.tb.*) . = ALIGN(8); __tbss_end = .; } _TLS_END_ = __tbss_end; TLS_END = _TLS_END_; __tbss_size = __tbss_end - __tbss_start; __tbss_offset = __tbss_start - __tdata_start; . = ALIGN(4K); /* Picolibc expects TLS space for main thread to be allocated by linker script */ .tls_space : { __tls_base = .; __tls_space_size = __tbss_end - __tdata_start; . += __tls_space_size; } Copy to clipboard **Key points**: 1. **TLS template**: `.tdata` and `.tbss` sections define the template 2. **Main thread TLS**: `.tls_space` allocates space for main thread 3. **Picolibc requirement**: Main thread TLS must be pre-allocated 4. **Alignment**: TLS sections are 8-byte aligned, space is 4KB aligned ### Using TLS Variables // Define thread-local variables __thread int my_thread_var = 42; __thread char buffer[256]; void my_function(void) { // Each thread has its own copy my_thread_var++; sprintf(buffer, "Thread var: %d", my_thread_var); } Copy to clipboard ### Hexagon TLS Architecture Hexagon implements Thread-Local Storage using the **UGP (User Global Pointer)** register: - **Thread pointer register**: The Hexagon ABI designates UGP as the per-thread TLS pointer. - **Top-pointer convention**: In Hexagon’s TLS ABI, UGP points to the **top** (end) of the TLS block (`tls_base + tls_template_size`), rather than the base. - **Addressing**: Thread-local variables are addressed via **negative offsets** from UGP (`UGP - offset`). - **Initialization**: - Main thread TLS is pre-allocated by the linker script (`.tls_space`) and initialized by `crt0.S`. - For multi-threaded applications, the thread runtime allocates `__tls_space_size` bytes per new thread, initializes the data from the template (`.tdata` copied, `.tbss` zeroed), and calls `_set_tls(thread_tls_base)` to load UGP (`ugp = tls_base + __tls_space_size`). ## Entry Point and Startup ### Entry Point Placement H2 boots from `0x2000000`. The [Linker Script](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-h2.html#linker-script-required) defines `.start`; `-Wl,--section-start=.start=0x2000000` places it at the address H2 expects. Both are required, but their complete explanation is kept in the linker-script section to avoid duplicating the canonical build guidance. ### Startup Sequence 1. **H2 boots**: Jumps to `0x02000000` 2. **\_start executes**: Entry point in `crt0.S` 3. **Stack setup**: Initialize stack pointer 4. **BSS clearing**: Zero out `.bss` section 5. **Data copying**: Copy `.data` from flash to RAM (if needed) 6. **TLS setup**: Initialize TLS for main thread 7. **Constructors**: Call C++ constructors (`.init_array`) 8. **main() call**: Jump to user’s `main()` function 9. **Destructors**: Call C++ destructors (`.fini_array`) on exit 10. **Exit**: Call H2 exit system call ## BSS and Data Initialization ### BSS Section .bss : { __bss_start = .; *(.dynbss) *(.bss.hot .bss.hot.* .gnu.linkonce.b.hot.*) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) __bss_end = .; } __bss_size = __bss_end - __bss_start; Copy to clipboard **Purpose**: Uninitialized global and static variables. **Initialization**: `crt0` zeros this region before calling `main()`. ### Data Section .data : { *(.data.hot .data.hot.* .gnu.linkonce.d.hot.*) *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } _edata = .; PROVIDE (edata = .); Copy to clipboard **Purpose**: Initialized global and static variables. **Initialization**: If loading from flash, `crt0` copies from flash to RAM. ## Complete Example ### Source Code **main.c**: #include #include #include // Thread-local variable __thread int thread_id = 0; // Global variables int global_var = 42; char global_buffer[1024]; int main(int argc, char *argv[]) { printf("H2 + Picolibc Example\n"); printf("Global var: %d\n", global_var); // Use heap char *heap_buffer = malloc(256); if (heap_buffer == NULL) { fprintf(stderr, "malloc failed\n"); return 1; } strcpy(heap_buffer, "Hello from heap!"); printf("Heap buffer: %s\n", heap_buffer); // Use TLS thread_id = 1; printf("Thread ID: %d\n", thread_id); free(heap_buffer); return 0; } Copy to clipboard ### Compilation #### Basic Compilation (Recommended) hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -O2 \ -o myprogram main.c Copy to clipboard **Flags explained**: - `--target=hexagon-unknown-h2-elf`: Use H2 target - `--cstdlib=picolibc`: Use Picolibc as the C standard library - `-Wl,--section-start=.start=0x2000000`: Place entry point at 32 MB (required by H2) - `-G0`: Optional; disable UGP-relative small-data accesses for the application - `-T `: H2+Picolibc template linker script (**required** — not added automatically) - `-O2`: Optimization level 2 **Note**: These flags automatically: - Links with `-lh2 -lsyscall_wrapper -lc -lclang_rt.builtins` - Uses `crt0-noflash-hosted.o` startup file - Sets up default heap (64 KB) and stack (4 KB) #### With Custom Heap and Stack Sizes hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -O2 \ -Wl,--defsym=__heap_size_min=0x100000 \ -Wl,--defsym=__stack_size=0x4000 \ -o myprogram main.c Copy to clipboard **Additional flags**: - `-Wl,--defsym=__heap_size_min=0x100000`: Set heap to 1 MB - `-Wl,--defsym=__stack_size=0x4000`: Set stack to 16 KB #### With Debug Symbols hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -g \ -O0 \ -o myprogram main.c Copy to clipboard **Debug flags**: - `-g`: Include debug symbols - `-O0`: No optimization (easier debugging) #### Verbose Output To see what the compiler is doing: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -v \ -o myprogram main.c Copy to clipboard **Output shows**: - Include paths being used - Libraries being linked - Linker command with all flags - Startup files being used ### Verification Check the entry point and sections: llvm-objdump -h myprogram | grep -E "\.start|\.heap|\.stack" llvm-nm myprogram | grep -E "__heap|__stack|_start" llvm-readelf -l myprogram Copy to clipboard Expected output: Sections: Idx Name Size VMA Type 0 .start 00000010 02000000 TEXT 15 .heap 00100000 02345000 BSS 16 .stack 00004000 02445000 BSS Symbols: 02000000 T _start 02345000 B __heap_start 02445000 B __heap_end 02449000 B __stack Copy to clipboard ### Running the Program To run your H2 program, use the Hexagon simulator with the H2 booter: hexagon-sim /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram Copy to clipboard **Components**: - `hexagon-sim`: Hexagon instruction set simulator - `/path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter`: H2 hypervisor booter executable - `--`: Separator between simulator arguments and booter arguments - `myprogram`: Your H2 application **What happens**: 1. `hexagon-sim` starts the Hexagon simulator 2. Simulator loads and runs the `booter` (H2 hypervisor) 3. H2 booter initializes the hypervisor environment 4. H2 loads your program at `0x2000000` 5. H2 jumps to your program’s entry point 6. Your program runs in the H2 hosted environment **Example with full path**: # Assuming toolchain is at /prj/qct/llvm/release/internal/HEXAGON/branch-23.0/linux64/latest hexagon-sim /prj/qct/llvm/release/internal/HEXAGON/branch-23.0/linux64/latest/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram Copy to clipboard **With simulator options**: # Run with timing information hexagon-sim --timing /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram # Run with verbose output hexagon-sim -v /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram # Run with specific architecture version hexagon-sim --mv68 /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram Copy to clipboard **Passing arguments to your program**: hexagon-sim /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram arg1 arg2 arg3 Copy to clipboard Your program will receive these as `argc` and `argv` in `main()`. ## Troubleshooting ### Issue: Missing linker script (`-T` flag) **Symptom**: Linking fails with undefined references to symbols defined by the linker script. **Error messages**: undefined reference to '__heap_start' undefined reference to '__heap_end' undefined reference to '__stack' undefined reference to '__tls_base' cannot open linker script file Copy to clipboard **Cause**: The clang driver does **not** automatically add the H2+Picolibc linker script. You must pass it explicitly with `-T`. **Solution**: Always include the `-T` flag pointing to the template linker script: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Verify the linker script exists**: ls /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template Copy to clipboard ### Issue: Wrong target triple **Symptom**: Compiler can’t find headers or libraries, or linker fails. **Error messages**: fatal error: 'stdio.h' file not found cannot find -lh2 undefined reference to '__heap_start' Copy to clipboard **Solution**: Ensure you’re using the correct target and cstdlib: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Verify target support**: hexagon-clang --print-targets | grep hexagon # Should show hexagon target support ls /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/ # Should show include/ and lib/ directories Copy to clipboard ### Issue: Missing section start flag **Symptom**: Program doesn’t start, H2 crashes or hangs. **Error**: Entry point is not at `0x2000000`. **Solution**: Always include the section start flag: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Verify entry point**: llvm-nm myprogram | grep _start # Should show: 02000000 T _start (not any other address) llvm-objdump -h myprogram | grep .start # Should show VMA 02000000 Copy to clipboard ### Issue: Unexpected small-data configuration **Symptom**: Application objects use an inconsistent small-data configuration. **Error messages**: relocation truncated to fit: R_HEX_GPREL16_X undefined reference to `_SDA_BASE_' incompatible library Copy to clipboard **Solution**: Choose one application small-data configuration and apply it to every application object. H2 applications may use UGP in user mode, so the default is to omit `-G0`; add it only when the application must disable UGP use: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -G0 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard **Why**: H2 itself uses `-G0` because it manages UGP. That does not require applications to disable UGP use in user mode. ### Issue: Program doesn’t start **Symptom**: H2 fails to boot or crashes immediately. **Possible causes**: 1. Entry point not at `0x02000000` 2. Wrong target triple 3. Corrupted binary **Solution**: # Verify entry point llvm-nm myprogram | grep _start # Should show: 02000000 T _start # Check .start section llvm-objdump -h myprogram | grep .start # Should show VMA 02000000 # Verify target was built correctly file myprogram # Should show: ELF 32-bit LSB executable, Qualcomm Hexagon Copy to clipboard ### Issue: malloc() returns NULL **Symptom**: `malloc()` fails even for small allocations. **Possible causes**: 1. Heap size too small (default is 64 KB) 2. Heap exhausted by previous allocations 3. Heap symbols not defined (missing `-T` linker script flag) **Solution**: # Check heap symbols llvm-nm myprogram | grep heap # Should show __heap_start and __heap_end # Increase heap size to 1 MB hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__heap_size_min=0x100000 \ -o myprogram myprogram.c # For very large heap (16 MB) hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__heap_size_min=0x1000000 \ -o myprogram myprogram.c Copy to clipboard ### Issue: Stack overflow **Symptom**: Program crashes with corrupted data or segfault. **Possible causes**: 1. Stack size too small (default is 4 KB) 2. Deep recursion 3. Large local variables **Solution**: # Increase stack size to 16 KB hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__stack_size=0x4000 \ -o myprogram myprogram.c # For larger stack (64 KB) hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__stack_size=0x10000 \ -o myprogram myprogram.c # Check stack usage in code llvm-objdump -d myprogram | grep allocframe Copy to clipboard ### Issue: TLS variables not working **Symptom**: Thread-local variables have wrong values or crash. **Possible causes**: 1. TLS space not allocated — check that `-T` linker script flag is present 2. UGP register not initialized properly 3. Conflicting use of UGP register **Solution**: # Check TLS symbols llvm-nm myprogram | grep -E "__tls|__tdata|__tbss" # Should show TLS-related symbols # Verify TLS space section llvm-objdump -h myprogram | grep tls # Should show .tdata, .tbss, and .tls_space sections # Ensure using correct target hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard ### Issue: Linker errors **Symptom**: Undefined references or missing symbols. **Common errors**: undefined reference to '__heap_start' undefined reference to '__stack' undefined reference to 'h2_syscall' cannot find -lh2 cannot find -lsyscall_wrapper Copy to clipboard **Solution**: 1. **Verify target and cstdlib**: # Use the correct target and cstdlib hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -o myprogram myprogram.c Copy to clipboard 2. **Check library paths**: # Verify H2 libraries exist hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ --print-file-name=libc.a # Should print the library selected by the target multilib. Copy to clipboard 3. **Use verbose mode to debug**: hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -v \ -o myprogram myprogram.c # Shows all linker commands and library paths Copy to clipboard ### Issue: Library version mismatch **Symptom**: Linker errors about incompatible libraries or ABI mismatch. **Error messages**: incompatible library version ABI mismatch undefined reference to versioned symbol Copy to clipboard **Solution**: # Ensure all components are from the same toolchain version hexagon-clang --version # Should show consistent version (e.g., 23.0-alpha2) # Check library versions hexagon-clang --target=hexagon-unknown-h2-elf --cstdlib=picolibc \ --print-file-name=libc.a Copy to clipboard ### Issue: Program runs but crashes or behaves incorrectly **Symptom**: Program starts but crashes during execution or produces wrong results. **Possible causes**: 1. Stack overflow (default 4 KB may be too small) 2. Heap exhausted (default 64 KB may be too small) 3. Uninitialized variables 4. Buffer overflows **Solution**: # Increase stack and heap sizes hexagon-clang --target=hexagon-unknown-h2-elf \ --cstdlib=picolibc \ -Wl,--section-start=.start=0x2000000 \ -T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template \ -Wl,--defsym=__heap_size_min=0x200000 \ -Wl,--defsym=__stack_size=0x10000 \ -o myprogram myprogram.c # Run with simulator hexagon-sim /path/to/toolchain/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram # Check for errors in simulator output Copy to clipboard ## Summary Use the [Basic Command](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-h2.html#basic-command) as the canonical application command. Before linking, confirm that it contains: - `--target=hexagon-unknown-h2-elf --cstdlib=picolibc` - `-Wl,--section-start=.start=0x2000000` - `-T /path/to/toolchain/Tools/templates/staticExecutable/static-executable-h2-picolibc.lcs.template` Use `--config=h2-picolibc.cfg` instead when the toolchain’s configuration file is available. Add `-G0` only for an application that intentionally disables UGP-relative small-data accesses. See the heap, stack, and troubleshooting sections for configuration and verification details. ## Related Documentation - [Semihosting](https://docs.qualcomm.com/doc/80-N3040-23/topic/semihosting.html) - File I/O and debugging via TRAP0 - [Getting Started](https://docs.qualcomm.com/doc/80-N3040-23/topic/getting-started.html) - Toolchain setup, compiler flags, and first program walkthrough - [Bare-Metal + Picolibc](https://docs.qualcomm.com/doc/80-N3040-23/topic/picolibc-baremetal.html) - Standalone bare-metal configuration and QEMU execution - Hexagon ABI User Guide (`80-n2040-23`) - Calling conventions, register usage, and processor ABI - Pre-built Picolibc Sysroots - Supplied under `target/picolibc/hexagon-unknown-h2-elf/` in the toolchain installation ## References ### Toolchain Paths All H2+Picolibc components are located under the toolchain installation: /path/to/toolchain/Tools/ ├── bin/ │ └── hexagon-clang # Compiler ├── lib/ │ └── clang/23/ │ └── include/ # Compiler headers ├── templates/ │ └── staticExecutable/ │ └── static-executable-h2-picolibc.lcs.template └── target/picolibc/hexagon-unknown-h2-elf/ ├── bin/ # H2 booter, selected by architecture ├── include/ # Picolibc headers └── lib/ # Target multilibs, selected by the driver Copy to clipboard ### Example Toolchain Path # Example with actual toolchain location TOOLCHAIN=/prj/qct/llvm/release/internal/HEXAGON/branch-23.0/linux64/latest # 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 myprogram myprogram.c # Run hexagon-sim ${TOOLCHAIN}/Tools/target/picolibc/hexagon-unknown-h2-elf/bin/v68/G0/booter -- myprogram Copy to clipboard ### Documentation - **Hexagon Programmer’s Reference**: [Qualcomm Developer Network](https://developer.qualcomm.com/) - **Picolibc Documentation**: [https://keithp.com/picolibc](https://keithp.com/picolibc) - **LLVM Hexagon Target**: [https://llvm.org/docs/HexagonTarget.html](https://llvm.org/docs/HexagonTarget.html) Last Published: Oct 06, 2026 [Previous Topic Next steps](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/getting-started.md)