<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/161055>161055</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang generates jump tables in .rodata.cst* instead of custom .rodata.<section> causing EFI runtime failures
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
dongjianqiang2
</td>
</tr>
</table>
<pre>
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](https://github.com/u-boot/u-boot/blob/master/drivers/firmware/psci.c#L254)
```
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](https://github.com/u-boot/u-boot/blob/master/arch/arm/cpu/armv8/u-boot.lds#L31)
```
.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.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysV11z4rgS_TXipSuUkSExDzw4BPbm1uzO1Ey25tElyw3WjCx5pDYJ--tvSTYMXze7U7UpKhjU6j59utU6CO_V1iAu2OyRzZ5GoqPaukVlzfabEuaHEmbLR6Wt9ouvNRqQtmmVVmYLf949WkvwqqiGpRZmy_gSXhFs6dHtsAKqBYFER0IZ2HRGkrLGQyPcd6z6fQJk58k24DGugiByquwIgfEMx9sxjAnfaIwbVbjOkGqQ8Tk0Yg-ts1UnEb51TQskSo0elAEBHlvhBCGMna0EibH0xHh-iDGGl1p5KLEWO2UdlA7Fdw9UI-Bbi5KwAi32tqOQUIlSdB7j8pCxVuY7OvDSqZbAGr0HZaTuKvTHkGd4cyg7AmPpAtGYJTlL8ghHo6g8kIVGeR_oPU1LEAzOQJgKOk2qEYR6D2UAtBFKdw4Hd78tl1BZ9DGgr-0rUAigvO-QpQcLbBT5C-7I3sI_ZjyPpa2VrMEI6pzQeg-NIFljT9wZJQFHbIi_C9Kz8NO38oBvkcgKyn10LDvn0NB1AJbkn3FoAcfSHIDNHru7wEf41HqpxpLNnhjPaqLWh8z5mvH1VlHdlWNpG8bXw4aTh1LbkvF1IzyhY3xdObVD5xlfb5RrXoVDxteDd55-4LMp4_OA5z4ZXknemXimKtDWbEGZnf2ORdhTbAzj2dlyyP6Xv5iz9LHnAE3XQCwWeqSC9i0CewiLAKv1c_F59WX1Uiw_fngClj5BwvjyYu1r_vn3uDa5Xvvynz9fnj5-_SOu8-v1Tx_yl_XHz78XXz6tls_r52U0THtD9vB0hBlwVbg5zyPi9iSo8wUdTYviOAOKgvGM8awohqM7fMFvzAQeWOlfSb6zqjphxe89YRMGyg22fj4e8rv1dwp12NJ_fG_Tebah5Quv_no3TkTOeN6HCFvCuDtUVG3CWDwtdfoUGL-s9MMyvA4x3rPvq__P7a8qfgoPrnud8Sx5y6ZJ_APGH6Gv0jK24vHf0NAA7OEJUHv8B6kemvOXEWR_hyC-v9ZKx1toEgP07RnXTo_6y-Xw6-8DabVGSf56MPVPY135f2E4CSfr-BbMZdv1z7vsuCfG4emHdDJMqXP0p0cIAroDj0VxshI63VE82uMjS2FuZzfOYd4HOlrcvA8vbN6xuARi21Mc1_W4oNNWpdU0tm7L-PovxtfGzX6I-off9GTkkjqhf2oBxrNBygxs3cF_j7dXvM6COrh1iQXTPyyBFC11rr_AzuhV5vqm7GOsDqrjFMZvy-Vd0FqCVKnxF_Bc3txhT96RbQQpGS_uQayEfecQDyKs3AO-KU9BhtzA-0zgERsPQUe0zrZiK2gQAhdyzogmOCELwnsrlQhwpTWehKE4EUOuvpM1iDOhMBzR_hD2YqLCjeg0RZHUaiGj4xqbW-UYFEJspPyT9T6QCN7qLmrQ2CB5z07vnGxk81qriGMuFQYpUMHG2aZXi0ZqG7XaQdyyFWdZwuZzf0nEoGZDTv9XYs0D6o8uULpTVZB6Z3J4DbaNvsgGCslZfQL3GClQg03QTPjWaiUV6X1wPKoWaTVP52KEi8nDbJ5Mp7P7yahe3JdZgg-Z5HLOq2QzLQVOSz7DRJTlZFpmI7XgCZ8lc54lD3zOJ2OcJlU6S7P79KGabFLBpgk2Qumx1rsmHLZRFJuLyf0kmc1GWpSoffyBwbnsjxcPvzXcImy4K7utZ9NEK0_-pwtSpHHRV2eLBl3ssQuxf6HwlfGEogK7OfB_MGDpciCIpSsIkj7UbbV-PgrrQUT7Uef04p2pHAAOb3ets99QhskcEw4qcch5t-D_CwAA__8pf0gA">