cquery最近改动
cquery介绍参看使用cquery:C++ language server。
最近cquery改动比较多(终于要熬过这个圣诞了):
- 可执行文件从
build/app
变到build/release/bin/cquery
了,支持release/debug/asan
等多种waf variants,使用RPATH ./waf configure --bundled=5.0.1
可以用上最新出炉的clang+llvm 5.0.1- Riatre把Windows构建修好了 #154
- FreeBSD可以使用了 #155及third party库改动,感谢ngkaho1234把sparsepp FreeBSD kvm搞定
- 不需要在
initializationOptions
里指定resourceDir
了,感谢jiegec的#137 - 各种模板改进和function template/class template内函数引用的支持。支持了
CXCursor_OverloadedDeclRef
函数调用#174,但template call template clang-c接口没有暴露相应信息,可能无解。 textDocument/hover
信息把函数名插入到函数类型里。用了一些heuristics处理_Atomic
decltype()
throw()
__attribute(())
typeof()
,碰到-> int(*)()
这种还是没救的,数组括号也不好,但大多数情况都显示得不错的。- 加入了实验性的
--enable-comments
,检索注释。#183 #188 #191 注释和原来的声明信息一起显示,带来了UI的挑战。 - VSCode使用浮动窗口,显示多行
textDocument/hover
不成问题。但Emacs lsp-mode和LanguageClient-neovim就遇到一些困难https://github.com/autozimu/LanguageClient-neovim/issues/224 https://github.com/emacs-lsp/lsp-ui/issues/17 workspace/symbol
模糊匹配 #182- danielmartin自己的repo加了实验性的
textDocument/formatting
,格式化。这必须用clang C++ API,作者有一些顾虑。
用了一个O(n^2) sequence alignment算法,根据编辑距离、camelCase等启发因素排序候选符号(func,type,path,…)。以foo bar
为模式会返回fooBar foobar foozbar
等,而fooBar
排在前面。Emacs xref-find-apropos
会自作聪明地把模式用空格分割后当作正规表达式转义,需要覆盖掉。
libclang handleReference
null pointer dereference
下面介绍重点,libclang一字节补丁。
This is a longstanding issue bothering us, with all the 3 bundled clang+llvm versions: --bundled-clang={4.0.0,5.0.0,5.0.1}
.
topisani raised the topic in https://gitter.im/cquery-project/Lobby and I fianlly made up my mind to diagnose it.
https://github.com/jacobdufault/cquery/issues/192
|
|
By appending --log-file /tmp/cq.log
to the cquery command line, we can see the error message in /tmp/cq.log
:
|
|
errno=1
indicates CXError_Failure
,libclang uses a sigaction+setjmp
based crash recovery mechanism to recover from SIGSEGV and returns CXError_Failure
. Sadly cquery does not report enough diagnostics for this. For these files, there is no hover, definition, or references information.
https://github.com/jacobdufault/cquery/issues/219 HighCommander4 narrowed it down to a very simple reproduce:
|
|
default template argument = actor
causes the null pointer dereference.
In https://github.com/llvm-mirror/clang/blob/master/tools/libclang/CXIndexDataConsumer.cpp#L203
|
|
dyn_cast_or_null<NamedDecl>(ASTNode.Parent)
may return NULL. In some code executed later on https://github.com/llvm-mirror/clang/blob/master/tools/libclang/CXIndexDataConsumer.cpp#L935:
|
|
getContainerInfo
tries to cast DC
, which uses a field in DC
and causes a null pointer dereference.
I have sent the patch to clang upstream for review, but clang+llvm 5.0.1 was just released. The holiday season is approaching and it is unrealistic to get this submitted and get a new release in the near future. For Linux users who do not want to build clang+llvm from source, my makeshift is ./waf configure --bundled-clang=5.0.1
with
|
|
What?
Description
Let’s check the problematic function in libclang:
|
|
According to System V x86-64 ABI, the arguments of this function are passed in the following way:
|
|
cquery sets CB.indexEntityReference
to OnIndexReference
so this field is guaranteed to be non NULL.
Scroll down the assembly listing a little bit and search for the if (!CB.indexEntityReference)
condition:
|
|
This redundant if
statement produces 0x47aeca test rax,rax
. If we replace it with if (!DC)
(because DC
may be NULL and we should avoid null pointer dereference), since DC
is passed in the register R8, we may use test r8,r8
:
|
|
It is now clear that we only need to patch one byte, i.e. the aforementioned printf+dd
hack. For radare2 users, r2 -nwqc 'wx 4d @ 0x47aece' build/release/lib/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04/lib/libclang.so.5.0
.
Sadly radare2 dropped the ball when it was in need and I had to resort to printf+dd
… Its assembling of test r8,r8
was incorrect https://github.com/radare/radare2/issues/9071😢