<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60668>60668</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Optimized HWASan code produces incorrect assembly
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
PiJoules
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
PiJoules
</td>
</tr>
</table>
<pre>
The following code:
```
struct AndroidSizeClassConfig {
static constexpr unsigned Classes[] = {
0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00090, 0x000b0,
0x000c0, 0x000e0, 0x00120, 0x00160, 0x001c0, 0x00250, 0x00320, 0x00450,
0x00670, 0x00830, 0x00a10, 0x00c30, 0x01010, 0x01210, 0x01bd0, 0x02210,
0x02d90, 0x03790, 0x04010, 0x04810, 0x05a10, 0x07310, 0x08210, 0x10010,
};
};
static const unsigned NumClasses =
sizeof(AndroidSizeClassConfig::Classes) / sizeof(AndroidSizeClassConfig::Classes[0]);
void func(unsigned);
void printMap() {
for (unsigned I = 0; I < NumClasses; I++) {
func(AndroidSizeClassConfig::Classes[I]);
}
}
```
Compiled with `clang++ --target=aarch64-unknown-linux-gnu -O1 -fvisibility=hidden -fsanitize=hwaddress -fsanitize=undefined -std=c++17 -fno-exceptions -fno-rtti -c /tmp/reproducer.cc -S -o -` results in:
```
adrp x23, :pg_hi21_nc:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
adrp x19, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE
adrp x21, :pg_hi21_nc:.L__unnamed_1
movk x23, #:prel_g3:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan+4294967296
movk x19, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296
movk x21, #:prel_g3:.L__unnamed_1+4294967296
mov x22, xzr
add x23, x23, :lo12:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
mov x24, #4611686018427387904
add x19, x19, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
add x21, x21, :lo12:.L__unnamed_1
.LBB0_1: // =>This Inner Loop Header: Depth=1
add x8, x23, x22
add x2, x8, x24
cmp x2, x19
b.lo .LBB0_3
...
.LBB0_3: // in Loop: Header=BB0_1 Depth=1
mov x0, x21
mov x1, x19
stp x8, x2, [sp] // 16-byte Folded Spill
bl __ubsan_handle_pointer_overflow
...
.weak _ZN22AndroidSizeClassConfig7ClassesE
.hidden _ZN22AndroidSizeClassConfig7ClassesE
.set _ZN22AndroidSizeClassConfig7ClassesE, .L_ZN22AndroidSizeClassConfig7ClassesE.hwasan+4611686018427387904
```
This can incorrectly result in `__ubsan_handle_pointer_overflow` called incorrectly if another definition of `_ZN22AndroidSizeClassConfig7ClassesE` is provided in a separate object file and wins during linking. This is because of how the awkward codegen attempts to get the tagged address for `AndroidSizeClassConfig::Classes` into `x2`:
```
// The relevant bits
// x23 will have the *untagged* address for _ZN22AndroidSizeClassConfig7ClassesE
adrp x23, :pg_hi21_nc:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
movk x23, #:prel_g3:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan+4294967296
mov x22, xzr
add x23, x23, :lo12:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
// x24 will have the tag (0x4) which is hardcoded here
mov x24, #4611686018427387904
add x8, x23, x22
// Add the tag onto the untagged pointer
add x2, x8, x24
// Do the comparison from here...
```
Now this would technically/arithmetically be fine only if the prevailing definition for `_ZN22AndroidSizeClassConfig7ClassesE` was this object file's definition, but because `_ZN22AndroidSizeClassConfig7ClassesE` is weak, any other object file defining it could win at link time and have a different tag. This means the `x2` produced here will never use the prevailing tag defined elsewhere and is very susceptible to triggering ubsan for pointer comparisons if the prevailing tag happens to be larger than this object file's tag.
The IR for this snippet looks correct:
```
define hidden void @_Z8printMapv() local_unnamed_addr #0 {
...
%7 = phi i64 [ 0, %0 ], [ %15, %13 ]
%8 = getelementptr inbounds [32 x i32], ptr @_ZN22AndroidSizeClassConfig7ClassesE, i64 0, i64 %7
%9 = shl nuw nsw i64 %7, 2
%10 = add i64 %9, ptrtoint (ptr @_ZN22AndroidSizeClassConfig7ClassesE to i64), !nosanitize !8
%11 = icmp ult i64 %10, ptrtoint (ptr @_ZN22AndroidSizeClassConfig7ClassesE to i64), !nosanitize !8
br i1 %11, label %12, label %13, !prof !9, !nosanitize !8
12: ; preds = %6
tail call void @__ubsan_handle_pointer_overflow(ptr nonnull @0, i64 ptrtoint (ptr @_ZN22AndroidSizeClassConfig7ClassesE to i64), i64 %10) #4, !nosanitize !8
br label %13, !nosanitize !8
...
}
```
and the unoptimized assembly looks correct:
```
// The tagged symbol is used here
ldur w9, [x29, #-20] // 4-byte Folded Reload
adrp x8, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE
movk x8, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296
add x8, x8, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
add x8, x8, w9, uxtw #2
mov x9, x8
str x9, [sp, #32] // 8-byte Folded Spill
cbz x8, .LBB0_9
...
.LBB0_9: // in Loop: Header=BB0_1 Depth=1
ldr x2, [sp, #32] // 8-byte Folded Reload
adrp x0, :pg_hi21_nc:.L__unnamed_2
movk x0, #:prel_g3:.L__unnamed_2+4294967296
add x0, x0, :lo12:.L__unnamed_2
adrp x1, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE
movk x1, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296
add x1, x1, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
bl __ubsan_handle_pointer_overflow
```
So it seems to me perhaps something in the llvm backend is incorrectly assuming:
```
adrp x8, :pg_hi21_nc:_ZN22AndroidSizeClassConfig7ClassesE
movk x8, #:prel_g3:_ZN22AndroidSizeClassConfig7ClassesE+4294967296
add x8, x8, :lo12:_ZN22AndroidSizeClassConfig7ClassesE
```
could be replaced with
```
adrp x23, :pg_hi21_nc:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
movk x23, #:prel_g3:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan+4294967296
mov x22, xzr
add x23, x23, :lo12:.L_ZN22AndroidSizeClassConfig7ClassesE.hwasan
mov x24, #4611686018427387904
add x8, x23, x22
add x2, x8, x24
```
which is valid but only if _ZN22AndroidSizeClassConfig7ClassesE is non-interposable, which it is.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWV9v6jgW_zTpyxEocUKAhz60Zaq5q7t3VnNHWmlekJMciLeOHdkO0H76lR2TBBpaeqd3nqaqWpPY579_5w9Ua7YViLfB7D4g5D_sX7LhqANCgtnqhjamlOr2-PQmk8Xz7R8lwkZyLvdMbCGXBQbxXRCugvD4Nw39r_uojWpyA3eiUJIV39kLPnCq9YMUG7aFYH7fbgPQhhqWQy6FNnioFTTCCVeAO4DayjhbQRCvhsfsT3gIw5CEAXlol3G_TPrlrF-m_XLeL5f9MrPLVyzyfgN2y6hnHPV0o34v6RnH_d5kNsYi7cVZ9FrQqFvm3dMo7J5GpF9mxXFJ2qdnLEjRqRnPu2XSE0sW3XLWM57H3XLRcYvCcMgimK-C2DvmZO0Dofdv79tvTeXdax3rCWn2gnITkMV41NiAi--OUUGWEJDHj52Z3YfBbBWQ5ZmMO8kK2DQiD8jiKOKFXbViwvyb1gFZOBH6iNxIBYPz8MWFbBjE9275MNDZPQvIvftdnoa1F-M6db6cqeN80Tli7F62fx9kVTOOBeyZKSFIw5xTsW0lgsnEULVFE8QrSlVepsmkEU9C7sWEM9EcJlvRwOS3CCabHdMsY5yZ5yBelawoUMBko6lghr2gfbanRaFQ69PHjShww6yVJtoUQbzKW97RHCYbISd4yLE2TArdflbGMJjk1uOmqgPyqLBWsmhyVNM8h8l3mEiYBGkICnXDjQYm3sYnoIWqrb0PJLZRHcR39XZdMhKtRR7Ed9Ov6z-_ETLuhrn3wC_Tck81Fecko-UYyWsIvhIuuiDcuhGCVliso-FFB6jk7mmoFontYYV8vY0_rBa5T8gyWaZzskw9m46-1_GM_lU6vkXWK_xa7IHCI-d77aElQyyZw4s6fU-LAgbW6X3PZUR-0OuvWCdegySNonSRhtEiIfN4MV-GyQVpWlv2YeOl-UDAvNIvavWLXul3HjjTr_f34ToK4o7IpZ-APFrEtXgd__JHyTR8EQIVfJWyhl-RFqgslRXWpgziVXRBtMXA8tZPr3YdWt_5fWc2y6vaa3g02cnrbMoltCrFXr_pdKhofL2iAEw45eyRo34rZ61LSnZBEB7NP_46GhVem_rERM53s3td2_rnspxROsmeDcKj5AUW8L1mnJ9Zhbf_1-sm01SsSyoKjutaMmFQreUO1YbL_RAuO7PBdI_U3s2PR-PUZ4TrT041muu2kwf4MJZduo-jKdIFeE4FMJFLpTA3_NlnFxsXQRq-Z800hJxym2WHJNgGqJCmRAUuBzKb5kBuHMVrNE9DYBpqJXescLSBgsaaKmoQZPY_zA1sGEegwuZ3oaFolC3aORNPTGyn4FRjGjLMaaPRMi_lHkyJQPdPe6oKV-BvUQA1BqvaaDAStmjcHkO3WyzgmNhd3ZOG1xQsVnRhpN1-INbeb6ZoH96281DIcUeFgYwZfRpkfteBxLBnnENJd-jEDMhdI1pZA3J3Iu6PAOunVws9Jjz9zGzt0fJvy4cXvJOcecfQra2Ww0NiK-B9yfLShmRJVWFjr4ASFX5ehh1NOqOi3hVFJ6C0wWo_HAMJ_CW_ZMWRxHUszFvqq5ZeLquaKqalgI2SlVO2Q9xROPrmLijTsJcNL8BgXgpm4eU5II9UMVNWaNoHkCHY4hqkaPHGcqwV7ijjFgcGsOPv7rW4s6e6FWIAMwGZ6wFJq3vWmA5bPoZqNtVYClQ8Q4uRQ0BruYgtMAO5M8Peop9xyAaGVS3muRijULDNBhUKY13pQa9CKnSLDh6CwPcRbcC1QSpwhwqs9GeWszFxbFyQa9y7M5Yn07BD9Qy60a5zyThayDSKbbfo0NflCmdwH0ODINAjXrK8SlrXKBz4ZgjcdmUKTEnFuBesnqcpDOHL746n268Fq2s0wKV80uBT0tsY3GoLPpG7DjhIwvWfi2MfvPONMJc55V1tacHWXtCw7237ggICMpu75rguGbA0sUUOhO2dnoXgelpX-djP0cy_iGL3pqexcDS2aJBjhcLURgETmWxEoe3pmMABWEw8PfvayX5ddWHlCo8LK_GA89Jx1iUH0exB6H2_iTwAGeyMQrfVIoTfsvSyGBsFFgI_IJcNBJZaxGxtEgl5bKrtp8WQceQYM1svu5Kl5d6OcH4y-0wBi1oh7EZOM-TuIzn96HNeVCtb_pDoTbLtX5eVLtXtF36C-N5erEK3M0QyO2ZHQxl3JVof2O-UdK25hBSi4dwe6CLkU0w6cNLS5bd37fzamKN7-9zy5ljIIlmb7mRtWMVebJmnNVYZf_4IagwqN5839XOVSW5hstGjyZ0XjbL_90t_9w_HKIsnJBxrgDyT5KT5-R25pMWF2m3xF6cyw4qtp_dJE5BBLeEriMWnTQMG9Fr7Ngezt5KTCxXW0h84a0_V4G3bmLYGcBh7dMjivW40z14GYrVt-XK0WV_-1GadF14fMq7PRV6L60MufG98R84HYOF78y_yTvT0VDruI9OfV3OX4-jyk-_I6DjvM-6IH6H81TuS8SunImN4-V3aUlQjVq5GqxBqVCWtNWhZoSldrSocpHK-qyCj-RO21eJwJEC1biomttdOrD8Txz4XxMYQ50e8M2rttuTPEBTWnOb-24u3LHYe3P8073_DMPvd-S5cbJXHvN6NBnaUs8L1lse-9qoCi2lbr03cna6lppltlh6OEwcDTE9vitu4WMZLeoO3UTpPw3S-WMxuyts8SSMkdLMhxYYuN0U0z2ezdJ7GBQ0xipIbdktCEockCgkhSTKbLjd5FpMsTmgeR0myCZIQK8r41N7_qVTbG6Z1g7dpmKaLG1e9af8tvMA9uJf-a3h1a89MsmargyTkTBvdUzHMcLz9ravSfv3v3Xcq3Nju2NEOMKYr4m4axW9LY2ptscZlsy0zZZNNc1kF5NHS9_8mtZK2vQzIo5NKB-TRSf3_AAAA__8aEk1e">