<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/80287>80287</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[Bug][Clang][ARM] Wrong assembly code generation, "LR" corrupted.
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
P1119r1m
</td>
</tr>
</table>
<pre>
The Clang compiler generates code for a function that overwrites the `lr` register without saving its data on stack beforehand.
This bug was detected on a large software component and the problem was minimized to a PoC (see `example.c`).
Clang versions info:
- llvmorg-17-note - bug wasn't detected
- llvmorg-17.0.2 - bug detected
- llvmorg-17.0.6 - bug detected
Host OS: Ubuntu 20.04.3 LTS
In disassembler the bug looks like this (generated `example.c.o.objdump`):
```
00000010 <BUGGY_FUNCTION>:
; if (!ctx) {
10: cmp r0, #0
14: beq 0x48 <BUGGY_FUNCTION+0x38> @ imm = #0x2c <-- Goto 0x48 if "(!ctx)" is True.
; ctx->cmd_c = func_2;
18: ldr r12, [pc, #0x40] @ 0x60 <BUGGY_FUNCTION+0x50> <-- Continue if "(!ctx)" is False.
1c: mov r1, r0
20: mov r0, #0
; ctx->cmd_a = func_0;
24: add lr, r1, #8 <-- ERROR. THIS LOOKS CRAZY!!! "lr" WAS NOT STORED ON THE STACK!
; ctx->cmd_c = func_2;
28: ldr r12, [pc, r12]
... < SOME OTHER CODE > ...
44: bx lr <-- ERROR. BRANCH TO "lr" ADDRESS THAT WAS PREVIOUSLY CORRUPTED!!!
48: push {r11, lr}
... < SOME OTHER CODE > ...
```
Steps to reproduce.
- example.c
```
void __attribute__((optnone)) printer(int line) {}
#define INFO() printer(__LINE__);
extern int func_0(void);
extern int func_1(void);
extern int func_2(void);
typedef int (*f_ptr_t)(void);
typedef struct operation {
double double_0;
f_ptr_t cmd_a;
f_ptr_t cmd_b;
f_ptr_t cmd_c;
f_ptr_t cmd_d;
} operation_t;
int BUGGY_FUNCTION(operation_t *ctx)
{
// INFO(); // UNCOMMENT TO FIX ASSEMBLY CODE GENERATION!!!
if (!ctx) {
INFO()
return -1;
}
ctx->cmd_a = func_0;
ctx->cmd_b = func_1;
ctx->cmd_c = func_2;
ctx->cmd_d = (void *)0;
return 0;
}
```
- reproduce.sh
```
#!/bin/bash
SDK_BIN_PATH=<PUT YOUR BIN PATH LOCATION HERE>
CC="${SDK_BIN_PATH}/arm-secureos-gnueabi-clang"
OBJDUMP="${SDK_BIN_PATH}/arm-secureos-gnueabi-objdump"
INPUT_FILE=example.c
OBJ_FILE=example.c.o
OBJDUMP_FILE=example.c.o.objdump
echo "Compile and objdump..." \
&& "${CC}" -ggdb -Os -fPIE -c "${INPUT_FILE}" -o "${OBJ_FILE}" \
&& "${OBJDUMP}" -dS "${OBJ_FILE}" | tee "${OBJDUMP_FILE}"
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycV12zqjoS_TXxpQsqBBV98EEBz_aevWWX4tw582LxETX3AGGSsI9nfv1UAip6t_eLsqKSle61upOmSaRkx4rSGRot0CgYJI06cTF7dxxnKpxykPL85yw-UfCLpDpCxsuaFVTAkVZUJIpKyHhO4cAFJHBoqkwxXoE6JQr4BxU_BNMYdaKAxrgQaIxB0COTigr4wdSJNwpk8sGqIzAlIU9UArwCqZLsO6T0wAU9JVVuIxwgPI9PTELaHOFHIiGnimaK5hqfQJGIIwXJD-pHIqghyitaKUiq3PivBU8LWpqlJatYyf5Hc1AcEnjnPiAykdSwpOekrAtqZ2iMEZl2rtuxjcIHFZLxSgKrDhy53ZwFRfFRcnG0HM-quKJgXbhWiHjqSvj3cBvbpEP_IWj8KagdX7hUEG2RO4dd2lSqAYJtPLRdeI23feCqgpzJREpapjqVOjjaaMH5dwkF-05B6TgjMrlkOb-Li81tnv6WN2XdRugagW4c4-5j_mJzORiQ6y92X7582y93az9eRWvkhrel7gL0xQ7aLyJOps6ITAF5ixZgZsHBWp--EJ5mZY3wVGBEdPrczh84wx4mpf9FeIrPw8kn_skCn90JckNAQwysLAG5gTF1Jhk8XMj1LQu-cMXBmDNMSZ8sIgSYhFg01L5XlamzhdwwK_N9Znzok7InyL0XN9HEEZ4WudDCHGKUjRZ1dpF4HmI0Cq6UhhjwefxZaLW0EdbSrtR9XilWNfQ582VSyAv1jlLWi2XJPwwtTUbgPozgjnkHeUjJJ2FIbmHAD2Eg_fwlea4DIoxPpzM7-Swz4WYTbWyIX1ZbeI2ir1vwN_P_fEPEaT9as7ZD4Nf5FtZRDNs42oQBRGuIX0LYxnP_q4b-g8yRSY_y59nT_0dBu8i2bU0attFbCFH8Em7Aj4IQdLps-y4Bw7vNfDaxuBe82MzX_gvE0U3gPAg24XYL8cs8NmrfN-G_VtFu-_oN_Giz2b3HYXANTOdu2NdQN_KE8BR5C-GYqBcCeX-H_UMRaMetorXUJVfQWvC8yehdcbXgVnqf15MPznLY7xOlBEsbRfd7s5MnvFYVr6jZzVOoBasUFYhMWKWgYGbCVJOLjG4kbk4PrKKwWi8jY6m_eL9_Xa1D7WJ6TXk70rOiogJtvdvFZKKp9ZGPGOcvYMgnmHZUP2ua04OBGqLzw75WYq-M5D9ZJJVoMgW81vVcP6LvCmvOm7Sg3dfDgeycgDm1T2fSpzPZ05n8xtULbtT26kGDFvxY3iY9OCAy7-pYZ63nEJElIstedvXJ7m7u1n709hauY316lqt_w3y7Dd8W5pQEIXwJ1-Fm3vq7Pyt__qCCvsf2vqCqERVYzl1ArvvxrxbIHia9YZxnmKdVq4fJu-ee2UM6mohMe0474rifrj845VbveOsq8vQkI-KaqC5TVukxuUdvg6_7xWq9f5_HL8gNkOu_72L4Fu02sFitQd-G18g3CYKXcBPqfqLfq_l6lX7QDZG3uLPmBYgsE1FakmaNoFxax6qhScqsTDd4epExES1-CXZv7__AzqVBuljqWq_1-y7eL1evIXKDh2IXLX753YzN73h8Mn_txPqlKTtx_TDw22bddMAdTNdnQgCN_EsKxoiM4arO940mAtbxmKdgRRKsw_sqBCu7gXoqOjC_TV5ltFNPPV1C21nIt89NeD4o3Zo_LO1hHrbXIJ-5-dSdJgM6czw89qbOZOwOTrMDHdPRyJs43mE6pZ47zmjieW6eZtnEo7k7YDOCyRAT7Dhk5GDXdslh6rjucJQP8ZgeJmiIaZmwwtZ9uc3FccCkbOhsgsnEGxRJSgtp3qUIuW6lUTAQM4230uYo0RAXTCp5s6CYKswL2KI56h5htDCvGe3P-eZNd3y_Cl4doWvaf7YvXV13znjV9kXkdaPjlXEhmlrR3B40opidlKql7rNNzTsydWpSO-MlIkvNoPuyasF_o5lCZGkESUSWRtP_AwAA__-gztYw">