Skip to content

Clang generates jump tables in .rodata.cst* instead of custom .rodata.<section> causing EFI runtime failures #161055

@dongjianqiang2

Description

@dongjianqiang2

When compiling u-boot with Clang, we observed that certain functions marked with a custom section attribute (e.g. .text.efi_runtime) may produce jump tables in a separate .rodata.cst* section. This behavior breaks the expected layout, because the U-Boot linker script only includes .rodata.efi_runtime* but not .rodata.cst*.

This leads to missing jump tables at runtime and ultimately boot failure.

GCC does not show this issue:
GCC emits jump tables into .rodata.efi_runtime., which naturally matches the linker script.
Clang emits jump tables into .rodata.cst
, which is excluded by the current linker script.

Reproducer: u-boot: psci.c

unsigned long invoke_psci_fn(unsigned long, unsigned long, unsigned long, unsigned long);

enum efi_reset_type {
  EFI_RESET_COLD = 0,
  EFI_RESET_WARM = 1,
  EFI_RESET_SHUTDOWN = 2,
  EFI_RESET_PLATFORM_SPECIFIC = 3,
};

typedef unsigned long efi_status_t;

__attribute__((__section__(".text.efi_runtime")))
void efi_reset_system(enum efi_reset_type reset_type,
                      efi_status_t reset_status,
                      unsigned long data_size,
                      void *reset_data) {
  if (reset_type == EFI_RESET_COLD ||
      reset_type == EFI_RESET_WARM ||
      reset_type == EFI_RESET_PLATFORM_SPECIFIC) {
    invoke_psci_fn((0x84000000 + 9), 0, 0, 0);
  } else if (reset_type == EFI_RESET_SHUTDOWN) {
    invoke_psci_fn((0x84000000 + 8), 0, 0, 0);
  }
  while (1) ;
}

The linker script only collects: u-boot: u-boot.lds

.efi_runtime : {
  __efi_runtime_start = .;
  *(.text.efi_runtime*)
  *(.rodata.efi_runtime*)
  *(.data.efi_runtime*)
  __efi_runtime_stop = .;
}

https://godbolt.org/z/nr5qahqsf

Actual behavior (Clang)

  • Jump table emitted into .rodata.cst*
  • Not captured by .efi_runtime in the linker script

Expected behavior (GCC-compatible)

  • Jump table emitted into .rodata.efi_runtime.*
  • Automatically included in .efi_runtime section by existing linker script

It seems GCC propagates the custom section naming to associated constant data (such as jump tables), while Clang defaults to placing them into .rodata.cst*.

Possible solutions:
Clang to emit jump tables into a section derived from the enclosing function’s custom section (e.g., .rodata.efi_runtime.*).
Or provide an attribute / option to control jump table section placement explicitly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clangClang issues not falling into any other categoryllvm:mcMachine (object) code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions