AndroidStudio NDK 无法调试问题

在 AndroidStudio 中设置了 symbol path,但是调试时,始终无法找到符号表。在 console 窗口中执行 image list -o -f ,列出符号表所在路径,一个工程的 symbol 路径正确,新编译的工程 symbol 总是错误的。无意中看到了 SlickEdit 中的 ndk-build 输出,还是 r10d 版本,而命令行编译是用是 r13b 版本。用两个不同 ndk 版本编译,造成了符号表无法加载的问题。同时,也知道了为何 art 线程总是意外崩溃。

QT 的两个链接问题

qt-creator 无法显示链接错误

很早就碰到这个问题,一直没有解决。在 qt-creator compile output 窗口中,仅显示 LINK 错误号,没有错误信息。

用命令行编译看看提示信息是什么。

D:\Qt\Qt5.7.0\5.7\msvc2015\bin\qtenv2.bat
"D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
cd /d E:\code\qt\my-project
"D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\nmake.exe" -f Makefile.Debug

看结果发现,LINK 错误信息中有中文,造成解析错误。下载安装 VS2015 英文语言包,安装并切换成英文,可解决此问题。

LINK 错误,提示找不到 signal 和 metaobject。

排除了各种可能,一直无法解决

  • 没有写 Q_OBJECT
  • 命名空间错误
  • 没有链接 obj 文件
  • 删除中间文件重新编译

最后浏览工程文件时发现,头文件和源文件都是 cpp 文件。修改 pro 文件,把头文件修改正确就行了。

找不到链接库问题

微软抓包工具 NetworkMonitor,自带 SDK,包括头文件和库文件。开发中,用到了这个工具。像往常一样,在代码中包含头文件,在链接选项中添加库文件,但是链接一直出错,提示找不到函数定义。

1>Linking...
 unresolved external symbol _NmCloseHandle@4 referenced in function 
 unresolved external symbol _NmCreateFrameParser@12 referenced in function
 unresolved external symbol _NmAddProperty@12 referenced in function 
 unresolved external symbol _NmConfigConversation@12 referenced in function 
 unresolved external symbol _NmCreateFrameParserConfiguration@16 referenced
 unresolved external symbol _NmLoadNplParser@20 referenced in function 
 unresolved external symbol _NmGetPropertyValueById@32 referenced in 
 unresolved external symbol _NmGetPropertyInfo@12 referenced in function
 unresolved external symbol _NmParseFrame@24 referenced in function _wmain
 unresolved external symbol _NmGetFrame@12 referenced in function _wmain
 unresolved external symbol _NmGetFrameCount@8 referenced in function _wmain

是否没有连接到指定文件 NmApi.lib?

代码里用了 #pragma comment(lib, "NmApi.lib") 来指定链接库,没有指定具体目录,是否目录不对?把 NmApi.lib 换了几个目录,没有解决问题。

修改链接方式,在工程的 Link 选项中指定链接文件,带上指定目录,还是不行。试着修改 lib 文件名称,会提示没有找到,说明链接文件是找到了,但是没有找到对应函数实现。

是否头文件或链接库有问题?

检查头文件,用了 extern C 说明接口调用是 C 风格的。lib 文件里有否有对应函数的定义呢,用 dumpblin 查看,显示结果是有定义的。

E:\code\test\TestNmApi\TestNmApi>dumpbin /exports NmApi.lib
Microsoft (R) COFF/PE Dumper Version 14.00.23026.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file NmApi_x64.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  NmAddDriverCaptureFilter
                  NmAddField
                  NmAddFilter
                  NmAddFrame
                  NmAddOlpBlockToFilter
                  ...
                  NmSetNplProfileAttributeByGuid
                  NmStartCapture
                  NmStopCapture

 Summary

         BD .debug$S
         14 .idata$2
         14 .idata$3
          8 .idata$4
          8 .idata$5
          A .idata$6

是否头文件与库文件函数的 name mangling 不对应?

注意到头文件中,函数前都加了修饰符 WINAPI,定义为 __stdcall,不同的修饰符会使用不同的 namemangling,尝试将 WINAPI 重新定义为 __fastcall __cdecl,都不行。__stdcall 的 name mangling 会在函数前加下划线 ,而 lib 库的导出函数并没有下划线!找到问题了,怎么解决呢?

从 DLL 重新生成 LIB

函数定义已经在那里了,只是 lib 定义不对,那么重新生成 liib 是否可以解决问题?从 stackoverflow 上找来一段脚本,可以从 dll 生成 lib 文件。

dumpbin /exports sqlite3.dll > exports.txt
echo LIBRARY SQLITE3 > sqlite3.def
echo EXPORTS >> sqlite3.def
for /f "skip=19 tokens=4" %A in (exports.txt) do echo %A >> sqlite3.def

lib /def:sqlite3.def /out:sqlite3.lib /machine:x86

很顺利地生成了 lib 文件,dumpbin 查看 lib 导出函数,name mangling 也对了,函数前都加上了下划线。启动链接程序,还是出错。发现 name mangling 还是略有不同,导出函数的名称不带参数个数,尝试把 WINAPI 定义为空,再次启动链接,链接成功。但是运行程序直接就崩溃了。

原来是 64 位程序问题

无计可施了,对比 NetMonitor 安装文件,突然注意到有 64 位和 32 位之分。马上想到安装的 64 位版本,而我编译的是 32 位版本,问题应该就在这个。32 位版本在这台 PC 上无法安装,用 7-zip 解压,得到了对应的 lib 文件。再次链接调试,终于成功了。原来 64 位程序的 name mangling 是不带修饰符的。