<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/97334>97334</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[lldb] Setting conditional breakpoints by location inside templated functions is hard.
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
mvanotti
</td>
</tr>
</table>
<pre>
In lldb it is hard to set up a conditional breakpoint in a templated function, if the condition depends on the template type.
See the following example:
```c++
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/random.h>
template <typename T>
T Read(uint8_t data[], size_t n) {
T result;
assert(n >= sizeof(T));
memcpy(&result, &data[0], sizeof(T));
return result;
}
struct FooStruct {
uint64_t foo;
bool bar;
};
int main(void) {
uint8_t data[0x100] = {0};
if (getrandom(data, sizeof(data), 0) == -1) {
perror("getrandom");
exit(EXIT_FAILURE);
}
FooStruct foo = Read<FooStruct>(data, sizeof(data));
if (foo.bar) {
fprintf(stderr, "foo.bar is true\n");
}
uint64_t u64_result = Read<uint64_t>(data, sizeof(data));
if (u64_result) {
fprintf(stderr, "u64_result is: %" PRIu64 "\n", u64_result);
}
return 0;
}
```
let's say we want to set a breakpoint on line 18 to check if `result` is not zero:
```
(lldb) breakpoint set --file repro.cc --line 18 --condition "result != 0"
Breakpoint 1: 2 locations.
(lldb) run
Process 131954 launched: '/home/user/test/repro' (x86_64)
Process 131954 stopped
* thread #1, name = 'repro', stop reason = breakpoint 1.1
frame #0: 0x0000555555555ae3 repro`FooStruct Read<FooStruct>(data="'a\b\U00000016\xd6-\x8bK\xb4Gl\xb9\xf6U\U00000002|yGo\xc9\U00000017\xdd\xd1\xd6\U00000016]\U00000012\xc0\U00000006\xa7\U00000006kU\xb4\x9c\xf7\xf7fC\xcfз\U0000007f刺\xa1\"\U00000014lP\x94\xf2\xc9z\xc9|_M\U0000000f\xd9*b\x9d\xaf\xa1D肐\xae\U0000001e,\xbf\U00000019f\xea\xec\x81\xceP\x9f\U0000007f\xa4\xbbn\xe0\xb9&\xdeT\b>\xfeK\xef\xc6b\U00000015Q\xd9ǵt\xff\xaa\xc8", n=256) at repro.cc:18:3
15 assert(n >= sizeof(T));
16 memcpy(&result, &data[0], sizeof(T));
17
-> 18 return result;
19 }
20
21 struct FooStruct {
error: stopped due to an error evaluating condition of breakpoint 1.1: "result != 0"
Couldn't parse conditional expression:
error: <user expression 0>:1:8: invalid operands to binary expression ('FooStruct' and 'int')
1 | result != 0
| ~~~~~~ ^ ~
```
This will throw an error when we evaluate it, which is less than ideal. It is understandable that it fails, but it is a bit hard to specify the correct breakpoint location here.
The issue is a bit worse if using the LLDB Python API: When you specify the breakpoint by location (file + line), you have no way to specify which version of the template you want to use (or which function name?). Instead, you would have to disable all the other breakpoints afterwards.
The workaround I found is to look up all the locations, from there call GetAddress(), then get the function name, and disable the breakpoint if the function name does not match what you expect.
I'm not sure what the right fix would look like here.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykWFuPozzS_jXOTSkRmHC6yEUOnVHrm0-anenR7l3LQNF4m9jINp3OXLy_fVWGJKRP2lcbtaDBVU89dXDZRlgrnxTiisUbFu9moneNNqvDi1DaOTkrdHVa3Sto26oA6UBaaISpwGmw6KDvQECpVSWd1Eq0UBgUz52WyoFUIMDhoWuFwwrqXpUkxPgWZA2uwasiVNihqixo5QfOWuBOHS5YsGPBerj-QvQStW5bfZTqCfBVHLoWWTRKsCQY_krGN_Q3vOWRVGXbVwgs2gpr0bhFw6K7j4alcmTYfipgXVVo3X41XmH91bBUn5unYf3VaCuLL4aNVE-fD58s43sjVKUPUyF_vYSdRVsKgBIHhIeL0AP8RFExnvVSuezRQSWcGOqGkmrlH3x0oBjPgaVj3AEewKDtW8eizdQWwJAExjMFZCLaeQRdM549MJ7TX3RBOeCh7E6MZ4wnIx7fAuPJyCGYkPgQ4gxk0PVGveOU7qZi1pm-dLDX-tfw38Qfcj5ZPjqotZ4QpHqAQpgbyFvjNCkOQirGsxctqzdxehPU4DUMyCmgwLB0E0zxgGYQ49kTuiGVjGdebxqB4UVO7wJvK9oR1jx8YxigQ2O08cHlE0h-mwIAfJWUr7t_3T887tf333__vLsVeRNGmESw1tq74kso2l4GKPVfkc_fOV1rvaBAv_Wi7oxUjpStq9CYoUD4KE6dy5keWbxV71x7x_uS5D5ZPg61MmV_Hv775K94_y3_CQNpWbQGxmPGOfz4ed8nS5K4uLSFG_ivHBynQfDBDDj3z6lCi47x1IIVJzgiHIVy5yVATHu-VtBKhRBmNFw2WD57x5NgZJUElAilHfxBo69N-0PTPKNlhwI1MUE25_NatggGO6MXZQnz-dnqfH5dVBjn59TxkLIXUJQ89OaKF1JMObS6FKRlF--Mm14N734YXaK1EEZhHi-hFb0qG6yGpKSM7xt9QMb3vUXD-N6hddRsiSXjKaX_NUsekyXl5iNA63TXYXUmsAbXGBQVMB6FlF3fj30_4OkZ1Ree0x0YFJacjnbTaIWLcFJhxgPwKCDKwWsQBEF8_gmMhoCyJLhO2y-ma7TzRZcKFm8LFm9_B_4XJizevlbJnG5Z8X90K5bfWn_P6Vonv6_iAWfp9vRN00CZT2BSD1P5azhA3hrZTR65Vw8msJ6FSKdvnn8PXOial55JOlzrrdev2S5gm4lOWrO7mGUZ26w9HPEYJtzZ8LL94eE8aD3QyP-MzqTbx_-fEKi9Fznj68LreN9EPSDv2F3GMs7ywD_jxAYy7vkV9eRl7vVQ-Kt3JvNRKnEgVN94QZCeYlEorxGM6eBDtvDBJzG6826gTxp6tTKZ5jb-x-jDNmWb2HnpAd0TKbOxDykW7Xic0OwR7jJPWbQOMxato0tJhjHV5d_bCkCYeKX_eUtAUCnA8DBn0R01EPp9vEcg8RwmvRQAeHDWp4cQAD7fOgyLbLQ-T3OoeqQuKRT4IcAX0fbC0ab22sR0_XY6-27zaWfb6r6tFOOpg04Yize7c3ztDFpLu_Bz572womXNopnI0OpwRzlj0ZrSBlK9iFZWoDukPYIl9oVUwpymWj4j6bVj8BSEoiaWSuV8x8qvLSkElm7hrTOXYfDDf_kfsPgO4K8vVqmHRlo4yralxqmP18geG1S0bo0RRpC-Vo6NLBtaj1pqwq4RCmSFol3AvT_p9KpCY51QlShaOncIR2egWsjWkn7Ru_FMJKCQ7noy6rCU9Wk84xiDpZsm8bzUQIPm9nTz0CBIa3u8Yh41JVHW0FsqDIL8_n23gR8n12gF6x_3lJl_koMn3d-YnpgsTlertIWi1ZPxjV-sxz0iaTfiBUFpOIrT1I8hTi9o7FiRN2c0UjxvCHpLuJkPOemcD31-6WLRnvF8AffKOn-QGIweqWIH005DJa0PtvBZRNCuQTNxxYKoHZqjMJV9F7ujNs_C6F5VcA-1v0tfpa3Wz_6wOqJeVnsiURt9oLcGoSSBb-jWVUXl7EvZR8dRgJ_QDYfPG6_41tf3mfibyI9H3RsVqDQOm6CDcGUDRyosCgW-dli6G7fuGU8PXtb2BgdRAjTyqXFQy9cxft7DVj7jUFWzahVVeZSLGa7CNMyzOEt4OmtWyyxKwzjiZRDluSi44Ms8COK0SMMsTMJwJlc84MsgDcIwiwKeLKp4WRZ1GmKVhSXGnC0DPAjZLtr25bDQ5mnmS3aVp1G0nLWiwNb6zwmcKzwO9ewXzd3MrEhnXvRPli2DVlpnryhOutZ_h_D7rngHv9DdNsOb7wv2pqilsrLCDz432PMni8WsN-2qca6jXTTje8b3T9I1fbEo6bSzJyLjbd4Z_W-k3rX39OnMPLj3suL_CQAA__8awhkI">