• 11058阅读
  • 0回复

[转载]Using gcc’s 4.8.0 Address Sanitizer with Qt [复制链接]

上一主题 下一主题
离线fanformylove
 
只看楼主 倒序阅读 楼主  发表于: 2013-04-17
source: http://blog.qt.digia.com/blog/2013/04/17/using-gccs-4-8-0-address-sanitizer-with-qt/


Using gcc’s 4.8.0 Address Sanitizer with Qt

<div qt-metadata-icons"="">Published April 17, 2013 | By <a fn="" n"="" href="http://blog.qt.digia.com/blog/author/kakoehne/" title="View all posts by Kai Koehne">Kai Koehne
One of the cool new features of gcc 4.8 is thebuilt in “Address Sanitizer”: a memory error detector for C/C++ thatwill tell you instantly when you e.g. access already deleted memory.This is actually a Google projectfrom Clang/LLVM, so for LLVM users this might be old stuff, but it wasn’t for me Since documentation on every day use is still a bit scarce on the web,I’m dumping the gist of how to put it to good use here, especially inthe Qt context …

How does it work?


It basically overwrites malloc and free, and does check the memory before every access (see the project wikifor the details). Apparently it does that in a very efficient manner,since the slow down is only about 2x compared to uninstrumentedexecution! Who knows, maybe we can enable it for the Qt-Project CIsystem at one point?
Be warned though that it only works so far on Linux and Mac. No luck for MinGW

How to enable it?


Since it is part of the compiler suite enabling it is easy: just add -fsanitize=address -fno-omit-frame-pointer to the compiler calls, and -fsanitize=addressto the linker calls. Anyhow, to catch issues where the memory isallocated, de-allocated or accessed by Qt you do not only have toinstrument your application, but also Qt. There’s a tentative patch forQt 5.2 which makes this easy:
https://codereview.qt-project.org/#change,43420
It is scheduled for the dev branch (Qt 5.2) because it’s a newfeature, but you should be fine cherry-picking it to e.g. Qt 5.0. Youcan then configure Qt with -address-sanitizer, and run qmake CONFIG+=address_sanitizer for your own applications.
If you don’t want to cherry-pick, you can also pass the additional command line arguments to qmake by explicitly setting QMAKE_CXXFLAGS, QMAKE_CFLAGS, and QMAKE_LFLAGS manually:$ qmake QMAKE_CXXFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \QMAKE_CFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \QMAKE_LFLAGS+="-fsanitize=address"

How to use it?


Just run your application! If you happen to hit a memory issue itwill abort, and show you a stack trace with module names and addresses.You will need a separate tool called asan_symbolize.py to get the symbols, and then maybe c++filt to de-mangle the C++ symbols.

Demo!$ mkdir addresssanitizertest$ echo "#include <QDebug>int main(int, char *[]) {const char *str = QString("Evil!").toLocal8Bit().constData();qDebug() << str;}" > addresssanitizertest/main.cpp$ cd addresssanitizertest && qmake -project && qmake CONFIG+=address_sanitizer
…$ ./addresssanitizertest 2>&1 | asan_symbolize.py | c++filt===================================================================32195== ERROR: AddressSanitizer: heap-use-after-free on address 0x600c0000bcd8 at pc 0x4016ce bp 0x7fff7ccd86c0 sp 0x7fff7ccd86b8READ of size 1 at 0x600c0000bcd8 thread T0#0 0x4016cd in QString::fromUtf8(char const*, int) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qstring.h:478#1 0x401b1e in QDebug::operator<<(char const*) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/io/qdebug.h:117#2 0x401282 in main /tmp/addresssanitizertest/main.cpp:6 (discriminator 1)#3 0x7fac5c1e3a14 in __libc_start_main ??:?#4 0x401118 in _start /home/abuild/rpmbuild/BUILD/glibc-2.17/csu/../sysdeps/x86_64/start.S:1230x600c0000bcd8 is located 24 bytes inside of 64-byte region [0x600c0000bcc0,0x600c0000bd00)freed by thread T0 here:#0 0x7fac5eab9c5a in __interceptor_free _asan_rtl_#1 0x7fac5d353e59 in QArrayData::deallocate(QArrayData*, unsigned long, unsigned long) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qarraydata.cpp:125 (discriminator 2)#2 0x401c21 in QTypedArrayData::deallocate(QArrayData*) /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qarraydata.h:230#3 0x401630 in QByteArray::~QByteArray() /home/kkoehne/dev/qt/qt-5.1-gcc-4.8.0-64/qtbase/include/QtCore/../../../../qt-5.1/qtbase/src/corelib/tools/qbytearray.h:396 (discriminator 1)#4 0x401231 in main /tmp/addresssanitizertest/main.cpp:5 (discriminator 1)#5 0x7fac5c1e3a14 in __libc_start_main ??:?previously allocated by thread T0 here:#0 0x7fac5eab9e7f in __interceptor_realloc _asan_rtl_#1 0x7fac5d35944e in QByteArray::reallocData(unsigned int, QFlags) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qbytearray.cpp:1472#2 0x7fac5d358d05 in QByteArray::resize(int) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qbytearray.cpp:1431#3 0x7fac5d77e452 in QUtf8::convertFromUnicode(QChar const*, int, QTextCodec::ConverterState*) /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qutfcodec.cpp:130#4 0x7fac5d780e91 in QUtf8Codec::convertFromUnicode(QChar const*, int, QTextCodec::ConverterState*) const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qutfcodec.cpp:507#5 0x7fac5d77a483 in QTextCodec::fromUnicode(QString const&) const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/codecs/qtextcodec.cpp:807#6 0x7fac5d48dd26 in QString::toLocal8Bit() const /home/kkoehne/dev/qt/qt-5.1/qtbase/src/corelib/tools/qstring.cpp:4020#7 0x401215 in main /tmp/addresssanitizertest/main.cpp:5#8 0x7fac5c1e3a14 in __libc_start_main ??:?Shadow bytes around the buggy address:0x0c01ffff9740: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c01ffff9750: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c01ffff9760: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c01ffff9770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c01ffff9780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa=>0x0c01ffff9790: fa fa fa fa fa fa fa fa fd fd fd[fd]fd fd fd fd0x0c01ffff97a0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa0x0c01ffff97b0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 000x0c01ffff97c0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa0x0c01ffff97d0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa0x0c01ffff97e0: 00 00 00 00 00 00 01 fa fa fa fa fa 00 00 00 00Shadow byte legend (one shadow byte represents 8 application bytes):Addressable:           00Partially addressable: 01 02 03 04 05 06 07Heap left redzone:     faHeap righ redzone:     fbFreed Heap region:     fdStack left redzone:    f1Stack mid redzone:     f2Stack right redzone:   f3Stack partial redzone: f4Stack after return:    f5Stack use after scope: f8Global redzone:        f9Global init order:     f6Poisoned by user:      f7ASan internal:         fe==32195== ABORTING
Have fun hunting down memory issues
快速回复
限100 字节
 
上一个 下一个