Bug 372165 - Heaptrack errors on random executables
Summary: Heaptrack errors on random executables
Status: RESOLVED FIXED
Alias: None
Product: Heaptrack
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Arch Linux Linux
: NOR normal
Target Milestone: ---
Assignee: Milian Wolff
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-11-06 23:21 UTC by Aleix Pol
Modified: 2018-03-08 22:23 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aleix Pol 2016-11-06 23:21:39 UTC
When running any KDE application I tried, I get the following errors:
Module backtrace error (code -1): failed to read executable information
Module backtrace error (code -1): failed to read executable information
Module backtrace error (code -1): failed to read executable information
Module backtrace error (code -1): failed to read executable information
Module backtrace error (code -1): failed to read executable information

Any idea what's going on?
Comment 1 Milian Wolff 2017-02-26 21:12:10 UTC
Fixed since some time now

commit 5b53e3a02f7173c868323b10ac3e03deb7ff4ff7
Author: Milian Wolff <mail@milianw.de>
Date:   Tue Nov 15 23:26:53 2016 +0100

    Fix use-after-free in usage of libbacktrace.
    
    We passed the c_str of a temporary std::string to libbacktrace,
    which stored that in internal data structures. Later on, that dangling
    pointer was accessed leading to subtle bugs which for odd reasons
    did not became apparent until recently. Running the interpreter
    through valgrind easily showed the problem though.
    
    This fixes the 'failed to read executable information' error messages
    emitted by heaptrack, and also ensures the profile data attributes
    costs to the correct modules.
    
    CCMAIL: apol@kde.org
Comment 2 Jan Wielemaker 2018-02-23 21:51:28 UTC
Found this really promising package!  Tested on Ubuntu 17.10, which prints the backtrace error from the original report.  Compiled from source (git 6e31841708b351b9f53e59d384e94df014d927ed, Feb 8, 2018).  This version fixes the problem when I compile my program using -O2, but it keeps failing if I add either `-g` or my default `-gdwarf-2 -g3` the latest version still prints this
message.  Program and heaptrack compiled with gcc 7.2.0 on amd64.
Comment 3 Milian Wolff 2018-02-26 12:42:29 UTC
@Jan: can you provide a MWE for me to reproduce the issue?
Comment 4 Jan Wielemaker 2018-02-26 14:24:00 UTC
@Millian: I thought I knew all abbreviations when it concerns bug
reports, but MWE is not one of them.  First of all, everything works just fine using the default package on Fedora 26.  I got beautiful results from a program running for a couple of hours, using 130Gb memory and thanks to the gui (which got a bit slow, but was still usable) I could find the issue rather easily.  Thanks!  Finally a sensible memory analyzer for Linux!

I got the problem on Ubuntu 17.10, compiling SWI-Prolog from source as explained in http://www.swi-prolog.org/build/unix.html and uncomment in `build` the statement `export COFLAGS="-O2 -gdwarf-2 -g3"`.  Then simply run `heaptrack swipl` and you get the errors.

Sad thing is that I tried some small and simple programs, but then all works just fine.
Comment 5 Milian Wolff 2018-02-26 19:59:19 UTC
Minimal Working Example

I'll see if/when I get around to test it with swi-prolog, I'll leave this task open for now.
Comment 6 Jan Wielemaker 2018-02-26 20:10:20 UTC
It is more a MFE (Minimal Failing Example) :)  As I have access to a machine on which it all works I'm not in a hurry.  Sorry for the not-so-minimal example and thanks again for this stuff.
Comment 7 Milian Wolff 2018-03-08 20:48:52 UTC
waiting for reproducible test case
Comment 8 Milian Wolff 2018-03-08 22:00:29 UTC
found one myself by chance!
Comment 9 Milian Wolff 2018-03-08 22:03:05 UTC
==27827== Syscall param openat(filename) points to unaddressable byte(s)
==27827==    at 0x580A0EE: open (in /usr/lib/libc-2.26.so)
==27827==    by 0x11AD03: backtrace_open (posix.c:67)
==27827==    by 0x11AA76: fileline_initialize (fileline.c:117)
==27827==    by 0x11AC0A: backtrace_pcinfo (fileline.c:183)
==27827==    by 0x10DA52: resolveAddress (heaptrack_interpret.cpp:129)
==27827==    by 0x10DA52: resolve (heaptrack_interpret.cpp:245)
==27827==    by 0x10DA52: addIp (heaptrack_interpret.cpp:304)
==27827==    by 0x10DA52: main (heaptrack_interpret.cpp:435)
==27827==  Address 0x15164b90 is 0 bytes inside a block of size 31 free'd
==27827==    at 0x4C2E60B: operator delete(void*) (vg_replace_malloc.c:576)
==27827==    by 0x10CEF5: deallocate (new_allocator.h:125)
==27827==    by 0x10CEF5: deallocate (alloc_traits.h:462)
==27827==    by 0x10CEF5: _M_destroy (basic_string.h:226)
==27827==    by 0x10CEF5: _M_dispose (basic_string.h:221)
==27827==    by 0x10CEF5: ~basic_string (basic_string.h:647)
==27827==    by 0x10CEF5: main (heaptrack_interpret.cpp:413)
==27827==  Block was alloc'd at
==27827==    at 0x4C2D54F: operator new(unsigned long) (vg_replace_malloc.c:334)
==27827==    by 0x4F5E76F: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.tcc:265)
==27827==    by 0x10D76D: assign (basic_string.h:1347)
==27827==    by 0x10D76D: operator= (basic_string.h:685)
==27827==    by 0x10D76D: intern (heaptrack_interpret.cpp:269)
==27827==    by 0x10D76D: main (heaptrack_interpret.cpp:414)
Comment 10 Milian Wolff 2018-03-08 22:23:05 UTC
commit 9590221b9b035a5fa7cf407228a69fa1f91b20a8
Author: Milian Wolff <milian.wolff@kdab.com>
Date:   Thu Mar 8 23:16:16 2018 +0100

    Don't hand pointer to temporary strings to libbacktrace API
    
    Fixes errors in the form of:
    Module backtrace error (code -1): failed to read executable information
    
    Valgrind reported:
    ==27827== Syscall param openat(filename) points to unaddressable byte(s)
    ==27827==    at 0x580A0EE: open (in /usr/lib/libc-2.26.so)
    ==27827==    by 0x11AD03: backtrace_open (posix.c:67)
    ==27827==    by 0x11AA76: fileline_initialize (fileline.c:117)
    ==27827==    by 0x11AC0A: backtrace_pcinfo (fileline.c:183)
    ==27827==    by 0x10DA52: resolveAddress (heaptrack_interpret.cpp:129)
    ==27827==    by 0x10DA52: resolve (heaptrack_interpret.cpp:245)
    ==27827==    by 0x10DA52: addIp (heaptrack_interpret.cpp:304)
    ==27827==    by 0x10DA52: main (heaptrack_interpret.cpp:435)
    ==27827==  Address 0x15164b90 is 0 bytes inside a block of size 31 free'd
    ==27827==    at 0x4C2E60B: operator delete(void*) (vg_replace_malloc.c:576)
    ==27827==    by 0x10CEF5: deallocate (new_allocator.h:125)
    ==27827==    by 0x10CEF5: deallocate (alloc_traits.h:462)
    ==27827==    by 0x10CEF5: _M_destroy (basic_string.h:226)
    ==27827==    by 0x10CEF5: _M_dispose (basic_string.h:221)
    ==27827==    by 0x10CEF5: ~basic_string (basic_string.h:647)
    ==27827==    by 0x10CEF5: main (heaptrack_interpret.cpp:413)
    ==27827==  Block was alloc'd at
    ==27827==    at 0x4C2D54F: operator new(unsigned long) (vg_replace_malloc.c:334)
    ==27827==    by 0x4F5E76F: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.tcc:265)
    ==27827==    by 0x10D76D: assign (basic_string.h:1347)
    ==27827==    by 0x10D76D: operator= (basic_string.h:685)
    ==27827==    by 0x10D76D: intern (heaptrack_interpret.cpp:269)
    ==27827==    by 0x10D76D: main (heaptrack_interpret.cpp:414)
    
    The issue was that we copied the interned string to a temporary,
    and then handed a pointer to the data of the temporary to
    libbacktrace. It is actually a wonder that this isn't blowing up
    more often... Now we don't copy to a temporary and hand out
    the pointer to the interned string data directly, preventing
    this error from arising.
    
    BUG: 372165