<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/126936>126936</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[llvm-link] Generating non compilable code from two valid bytecode files (only when ASAN enabled)
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
janoglezcampos
</td>
</tr>
</table>
<pre>
**CONTEXT:**
> Platform: Windows
> LLVM tested versions: 17.0.6 and 19.4.7 (msys2 builds)
> Sources lenguage: C
> Result: compiler crash
Trying to compile with llc the result of linking two bytecode files (unoptimized, address sanitizer), results in the fatal error shown above, if the bytecode files are generated without address sanitizer the error doesnt show up, compiling the bytecode files and then linking the object files works:
```
LLVM ERROR: Associative COMDAT symbol '.str.1' is not a key for its COMDAT.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: C:\\msys64\\clang64\\bin\\llc.exe .\\linked.bc
Exception Code: 0xC000001D
#0 0x00007ffd77d7d506 HandleAbort (C:\msys64\clang64\bin\libLLVM-19.dll+0xefd506)
#1 0x00007ffdfabae6d5 (C:\WINDOWS\System32\ucrtbase.dll+0x7e6d5)
#2 0x00007ffdfabaf6e1 (C:\WINDOWS\System32\ucrtbase.dll+0x7f6e1)
#3 0x00007ffd77d02153 llvm::report_fatal_error(llvm::Twine const&, bool) (C:\msys64\clang64\bin\libLLVM-19.dll+0xe82153)
#4 0x00007ffd777cb9d2 llvm::Function::getSectionPrefix() const (C:\msys64\clang64\bin\libLLVM-19.dll+0x94b9d2)
#5 0x00007ffd777cb659 llvm::TargetLoweringObjectFileCOFF::SelectSectionForGlobal(llvm::GlobalObject const*, llvm::SectionKind, llvm::TargetMachine const&) const (C:\msys64\clang64\bin\libLLVM-19.dll+0x94b659)
#6 0x00007ffd777c471d llvm::TargetLoweringObjectFile::SectionForGlobal(llvm::GlobalObject const*, llvm::SectionKind, llvm::TargetMachine const&) const (C:\msys64\clang64\bin\libLLVM-19.dll+0x94471d)
#7 0x00007ffd7788aa2e llvm::AsmPrinter::emitGlobalVariable(llvm::GlobalVariable const*) (C:\msys64\clang64\bin\libLLVM-19.dll+0xa0aa2e)
#8 0x00007ffd778891f0 llvm::AsmPrinter::doFinalization(llvm::Module&) (C:\msys64\clang64\bin\libLLVM-19.dll+0xa091f0)
#9 0x00007ffd7705afec llvm::FPPassManager::doFinalization(llvm::Module&) (C:\msys64\clang64\bin\libLLVM-19.dll+0x1dafec)
#10 0x00007ffd7705aa97 llvm::legacy::PassManagerImpl::run(llvm::Module&) (C:\msys64\clang64\bin\libLLVM-19.dll+0x1daa97)
#11 0x00007ff721d36d54 main (C:\msys64\clang64\bin\llc.exe+0x6d54)
#12 0x00007ff721d317dc WinMainCRTStartup (C:\msys64\clang64\bin\llc.exe+0x17dc)
#13 0x00007ff721d31836 mainCRTStartup (C:\msys64\clang64\bin\llc.exe+0x1836)
#14 0x00007ffdfc83259d (C:\WINDOWS\System32\KERNEL32.DLL+0x1259d)
#15 0x00007ffdfd8caf38 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x5af38)
```
**HOW TO REPRODUCE:**
1. Create two C files testA.c testB.c
```
//testA.c
char *foo = "not";
```
```
//testB.c
char *bar[] = {"and", "break"};
```
2. Generate bytecode files for both with ASAN:
```
clang -emit-llvm -O0 -fsanitize=address -c ./testA.c ./testB.c
```
3. Link both files with llvm-link:
```
llvm-link .\testA.bc .\testB.bc -o linked.bc
```
4. Compile with llc (Crashes)
```
llc .\linked.bc
```
**MORE INFO (personal investigation)**
* Code that generates de error:
```C++
//File: llvm-project\llvm\lib\CodeGen\TargetLoweringObjectFileImpl.cpp
...
static const GlobalValue *getComdatGVForCOFF(const GlobalValue *GV) {
const Comdat *C = GV->getComdat();
assert(C && "expected GV to have a Comdat!");
StringRef ComdatGVName = C->getName();
const GlobalValue *ComdatGV = GV->getParent()->getNamedValue(ComdatGVName);
if (!ComdatGV)
report_fatal_error("Associative COMDAT symbol '" + ComdatGVName +
"' does not exist.");
if (ComdatGV->getComdat() != C)
report_fatal_error("Associative COMDAT symbol '" + ComdatGVName +
"' is not a key for its COMDAT.");
return ComdatGV;
}
...
```
* Manually "fixing" the bytecode:
Generated IR:
```
; ModuleID = 'linked.bc'
source_filename = "llvm-link"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
$.str = comdat nodeduplicate
$foo = comdat nodeduplicate
$.str.1 = comdat nodeduplicate
$bar = comdat nodeduplicate
@llvm.used = appending global [2 x ptr] [ptr @asan.module_ctor, ptr @asan.module_ctor.4], section "llvm.metadata"
@llvm.compiler.used = appending global [10 x ptr] [ptr @.str, ptr @foo, ptr @__asan_global_.str, ptr @__asan_global_foo, ptr @.str.1, ptr @.str.1.2, ptr @bar, ptr @__asan_global_.str.6, ptr @__asan_global_.str.1, ptr @__asan_global_bar], section "llvm.metadata"
@llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr null }, { i32, ptr, ptr } { i32 1, ptr @asan.module_ctor.4, ptr null }]
@.str = internal constant { [4 x i8], [28 x i8] } { [4 x i8] c"not\00", [28 x i8] zeroinitializer }, comdat, align 32
@foo = dso_local global { ptr, [24 x i8] } { ptr @.str, [24 x i8] zeroinitializer }, comdat, align 32
@___asan_gen_ = private constant [14 x i8] c"./src/testA.c\00", align 1
@___asan_gen_.1 = private unnamed_addr constant [5 x i8] c".str\00", align 1
@___asan_gen_.2 = private unnamed_addr constant [4 x i8] c"foo\00", align 1
@__asan_global_.str = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint (ptr @.str to i64), i64 4, i64 32, i64 ptrtoint (ptr @___asan_gen_.1 to i64), i64 ptrtoint (ptr @___asan_gen_ to i64), i64 0, i64 0, i64 -1 }, section ".ASAN$GL", comdat($.str), align 64, !associated !0
@__asan_global_foo = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint (ptr @foo to i64), i64 8, i64 32, i64 ptrtoint (ptr @___asan_gen_.2 to i64), i64 ptrtoint (ptr @___asan_gen_ to i64), i64 0, i64 0, i64 0 }, section ".ASAN$GL", comdat($foo), align 64, !associated !1
@.str.1 = internal constant { [4 x i8], [28 x i8] } { [4 x i8] c"and\00", [28 x i8] zeroinitializer }, comdat($.str), align 32
@.str.1.2 = internal constant { [6 x i8], [26 x i8] } { [6 x i8] c"break\00", [26 x i8] zeroinitializer }, comdat($.str.1), align 32
@bar = dso_local global { [2 x ptr], [16 x i8] } { [2 x ptr] [ptr @.str.1, ptr @.str.1.2], [16 x i8] zeroinitializer }, comdat, align 32
@___asan_gen_.7 = private constant [14 x i8] c".\\src\\testB.c\00", align 1
@___asan_gen_.2.8 = private unnamed_addr constant [5 x i8] c".str\00", align 1
@___asan_gen_.3 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1
@___asan_gen_.4 = private unnamed_addr constant [4 x i8] c"bar\00", align 1
@__asan_global_.str.6 = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint (ptr @.str.1 to i64), i64 4, i64 32, i64 ptrtoint (ptr @___asan_gen_.2.8 to i64), i64 ptrtoint (ptr @___asan_gen_.7 to i64), i64 0, i64 0, i64 -1 }, section ".ASAN$GL", comdat($.str), align 64, !associated !2
@__asan_global_.str.1 = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint (ptr @.str.1.2 to i64), i64 6, i64 32, i64 ptrtoint (ptr @___asan_gen_.3 to i64), i64 ptrtoint (ptr @___asan_gen_.7 to i64), i64 0, i64 0, i64 -1 }, section ".ASAN$GL", comdat($.str.1), align 64, !associated !3
@__asan_global_bar = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint (ptr @bar to i64), i64 16, i64 32, i64 ptrtoint (ptr @___asan_gen_.4 to i64), i64 ptrtoint (ptr @___asan_gen_.7 to i64), i64 0, i64 0, i64 0 }, section ".ASAN$GL", comdat($bar), align 64, !associated !4
; Function Attrs: nounwind uwtable
define internal void @asan.module_ctor() #0 {
call void @__asan_init()
call void @__asan_version_mismatch_check_v8()
ret void
}
declare void @__asan_init()
declare void @__asan_version_mismatch_check_v8()
; Function Attrs: nounwind uwtable
define internal void @asan.module_ctor.4() #0 {
call void @__asan_init()
call void @__asan_version_mismatch_check_v8()
ret void
}
attributes #0 = { nounwind uwtable "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
!llvm.ident = !{!5, !5}
!llvm.module.flags = !{!6, !7, !8, !9}
!0 = !{ptr @.str}
!1 = !{ptr @foo}
!2 = !{ptr @.str.1}
!3 = !{ptr @.str.1.2}
!4 = !{ptr @bar}
!5 = !{!"clang version 19.1.7"}
!6 = !{i32 1, !"wchar_size", i32 2}
!7 = !{i32 8, !"PIC Level", i32 2}
!8 = !{i32 7, !"uwtable", i32 2}
!9 = !{i32 1, !"MaxTLSAlign", i32 65536}
```
(I know very little about this topic, just trying to narrow down the problem) In this case, the previous shown function (getComdatGVForCOFF) fails when evaluating `@.str.1.2`, for this global, the COMDAT name obtained is `.str.1`. From comparing with other bytecode, `@.str.1` should be defined with comdat, and not comdat($.str). So changing the following line from:
```
@.str.1 = internal constant { [4 x i8], [28 x i8] } { [4 x i8] c"and\00", [28 x i8] zeroinitializer }, comdat($.str), align 32
```
to:
```
@.str.1 = internal constant { [4 x i8], [28 x i8] } { [4 x i8] c"and\00", [28 x i8] zeroinitializer }, comdat, align 32
```
allows llc to compile the bytecode (not sure if the modifications are correct)
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWltz27iS_jXwC0osEhRJ6cEPknw5qWPHLtub2X1ygSQoYUwBKgCU5Pz6rQZAkbrYsZNNzs6UJyIJdPeH7kZ340K15nPB2DlKpii5OKONWUh1_jcVcl6z7wVdrqQ-y2X5eo7IBJHJ7O7r0-V_P6F44t5RaP_iS3xfU1NJtUTxBP_FRSk32rfc3Hy7xYZpw0q8ZkpzKTT0irIgDFJMRYmjcTAMMozIaKlfNcF5w-tSIzL2LB5lowqmcc3EvKFzBuQz3_bAdFMb-FLI5YrXTOFCUb1w0J7UKxdzbGTbijfcLHBdF9gsGFaWGMsK11y82J4bifNXwwpZMlzxmmmA1Qi5MnzJv7MSkRmmZamY1lhTwQ3_zhRAJTPPTmMuLPeKGlpjppRUWC_kRmCayzWDnryyPQ4kUcXwnAmmKCgLkMrGHEuzpI5tKZkWxnLHzQo4u3HaoZwQIEr4LLrhLhiW-d-sML7HRqoXMA-oLw39XzixRrx8eLh7AE1PtJYFp4avGZ7d3V5MnrB-XeayxohkgTYqiBDJMNdYSIMpfmGvuJIKc6N9_wCFk_uby8njJdZNvuTQK2_mWLGVVAbstTBmZYGQK0Su5twsmjwo5BKRq7petz-DlZKAHpErrnXDNCJXdpRcFHVTMjtA6w84p8WLUbRgIPvR0OIFl81y5cYaBtj-d6_kXNElpmreLJkw2rlaPEHJDCUzcM906J6Lmop5-5Jz4R7qugjYluHAv3LxwsogL1A4udwWbGW4FHgmS-vD4XYWwn_RBQonGJE4xOEWPmRVVWZZmZVJmOJ_UVHWbJKDYhAZeTQ7KB0OB6LmOVhrEI2Dsq4RmYZbVgEjN59ATNQTU9GcsrRMeqz_-vL14u6vR5TMHl-1YcuYoGTWFMrkVLMd0wyoOp7kgGeVsujzPIGq4xnvqyMkURJja_14guKJc5ZnO82e7XxAZNQ1P224YLiQQhtEUpgbuZQ1IuOf1eII5HfohnvosiIfl6SH7qoRBVjbvc2ZeWT2_V6xim8RGQESi-4n8YyHILHDkxziSZNxD88TVXNmbuSGKS7md3bSX_Gaze6urlyPR1azooV5JdV1LXNa7-nUfXLErWonoNqui6f_NxflfoMDcEuLxb5dflkLaTLutJAeaGGYReUHtLCH_Z8zdhgdcMEY-_Fne-MfjSglrAdkopf3igvDlHtnS27cwL5RxWlesxNjbpt6o_7ZSURDANSZa3QAdxxV4TtwS3nFBa35d2qnVh_qrSwbQJ_-CjgQ34Eb74ELE1qxoj_D7--p1rdU0PmfwReVgMDXRSSOwkN8dJz18NVsTotX99xD-mW5qn0AbX4HRDrOOoi9VJORqIzTMhniJeXiQ_xdMrWMgbBjSw7YRllZQN15S7mYPTw9GqpMs_qsDODSyYgPZYzi1EL_BQGjOO0E9BNIVYxikozLH6XMf18-fL28iUlwcXPjWAJVx7OfBKpyVNAqHp3m-T-PT5e3lqcwZV3vLJgAiWfYqwAtf_j7191f-OkOP1zeP9xd_Nfssr8YiAI8U4waZuvoma8pofifBIX9nQZFnzG2bKHC851QOCkWVGFEJpWUGMUXGBEipEGEoHh6COo0n-ken5wqt75x3LIpIoRCgCYQoxEhuWL0BV6zi2MRJMDXviQ_rKahpM2lWbg1xeRx8vW4cLbegAcQZgcw0fDgLsSDqq3lUXzRlveDAgedHnbPBwpD4SQO8A0XL060r9rdoma9HEDBeYxi12TrUiciL3YvU3gZSNyvVvvkwwDPDpdP4FNQVzN97CvQHhxUv3tms_5ye_dwib98vboDXiumtBS0xlysmTZ87gPouFtokoktnLFZULNbJmlc-rXQwahniEzhr_ULn-Tx3qoBZud66SIZSmbA_prBpH2rTIDYGRSrFQonQQALCW2o4YXP4m22rBsGjjdnZiaXJTXX366ksnUWGZ3sef3NRtwM4GLPzJFC68w67vW3AYovdzxdAen8FWOqNVPwDRw6RSQFv2bbFStgJXn9za6o6JphilvyyE4Az8EyeTQw2AdW4Rb2V7pkVvjMy4YP-5JPjqel3wd-TxUTHniPX2nJAHtPak8Cr7Clidp2n6BPlv-IkHdXp4gQjMj0YITWT7BVSGbX1HbhyrZcm-BITQ5Py-CEUTAoF5TmgWL827C-u8Q-BK6YaZTYsfMt2cXOmQ_mKL6loqF1_QrSKr7lYg6Q-vsKbtJd7_YsvjwcBx8UT7GrLL74EEyyLjKQDGaR3eB5hmAmWpdDhHQRjRAUToydlLgEJdJX2Zi2HxtAAbMZrEgWongSE_sPvEb7r_CUDu0_A757iMgIxZOIjAbVKPRPwn5KW_J0OHiMrMU6HEbxVb3Duh2lz-lwsIH_3f7XYC4aR2DVOQy0UbZ34Wa2kCUrm1XNC2rYrleb9d7t5PZYftwvpz-UOAxBy0GjWWm70tWKiZKLOZ7bOY1RMiV4i1dG2RSaTFcwjGFINRXB0tr1uTDg0DP8RlMwRMkFtGu3PmptGyyZoWBOryaPpd3Iex9UFJ5CBZrpIamk7L09PwOyZ8fj-aDrfuM-YbundfAhIL1PUGa8JypI32-O3my2Bcwn9OfJQPP6XZuibIp53A5iJz-78Dp9s72lxNE7Vm-bRFPXlilUW7_EMRge8Uwu3MB3k8suFqGQsImJCmM5o2Q6xFvMR16RoIBR-2Env98LF77uTGZh2NaKe1TfmZIcyjhY7zHVDrHwmWCGac3nAsfeNO3ELrV8rmVB650xsmmrDBAwPIJ14Nr7nT6J4rl1LSaeLZyV4muobTt1JdNoXwtQimpV9Ir0nk4c--iYu49PLf9GQGQvn6Hc3ROW7MuCQX6IPfkY-_2hwLR-m_vhnNyT0LMWpA4y-9xP5-TpECxqJBd236dnXajSLMW4JdpRuznzBu2B2o-4_IDkmCA8ehhErWf1YlBg1zxkeH3j9Vl0VdDQueu4U7NTBSIR9UUPBHcShae0306WP6R8EHekhNHndU9-i-7Dz6reJq8faz7qQqefrP-nwRPW2D8bPE86UBvD2uT7PuT0EHJ6CnK6B9ntBByATj8LOohOwm6LsZMJYK_K8pKjk4hPFmNvFyinuP1Czgiyj2cNewIGicM-tJsZHwvuwej3Zo_4Y-yzI_ZB9DEBw59JT7bS-3B6CtI_naBOJZefSFFg3c8GyiD7z6Yp8qYVoj9vhVOJJv28HeL_V1Y4CJtv2CE-ZYc2tP4hI4C4IzVEP2GA4W8ywKcrBrt4_bHyh-2Fnyluj7fxxBhlr0kI2YgNFyVuNsYeJIaTklVcsC5HryUvTy8V_b5ZHHa7oLTuCLwGIGn57ce3uvgrRs9LrpfUFIvnYsGKl-f1qEenmLFku-0vC7WoqWLvSny724-l_g61wXr4P644aozieWPsTSmA4Q5ZjsYFPuh2zgbFym6MxRdu32wA3kZ67RWjplFM7zohMi2Wco3IDJ62I_dQbbVyT8vl1j1ozXYPxD1tR24jtcWLSGR3SXjJRLuDGNlToSjxTp_4zr6n03hQ1XSu9wlST5D535H_HfelhT2a_lK-lREdt0MB3zaT0-RBtOsRv9UjILs-w-M-MOfb5mR_XIgQd3DlnQJH4yAKMn9GZinSHsVu38aRbooFVc-af2c-0kB7R5kdUI46yvsvM3zD1qw-STg6IMw6wnbunCIbv430lm6fbh4nEPJ6pGmSxKkn39sRH33BL0JuQCuvuObG1AzTXDYGmwXX2MgVL4DJ34022OyuHgqqlNzgUm7cvcCVknnNljBxvwhHWlDruL6ZrblstL8zWLURA5HRqROlMa4orzXeLJjAbE3rhhoQDKB7jpDa5FBJ5QTO_f0WJ9IfPdi9d5kbygUrMdfAw_taGgb4SsmlvV9IFQiwR4HSLJjqjgNAsz25KA1hFE1d4pxhF9bcxcb-YkOU9hDjRFUW4EeJiwUV8_ayYiXrWm7grYYQWSm5PHHi8I9b1PbAG_mPGdD-GPYhU7CTdjdtu9u3e3dSERmB3XWjWHshdilLXvHCHv66-7CFVMpe8ByfledxOY7H9IydR1k8jrMsGaZni_N4TDNGi5QQltEqojnJwiqvaFpUI5ZU7Iyfk5AkIYlIlJJkmAbjfMiyIszHcZLHeVShYciWlNeBjfdSzc_sbdLziKTjOD2rac5qbW9JEyLYBttW0FhycabO7TFV3sw1GoY110Z3bAw3tb1e3R1lJRfthQLwYiGFV46_YFU6p7YXKNa05uWJ68hS1K9uvkNNh5kA2hJU1Kj6_Odvzvrhrs_J_wYAAP__Jsh8FA">