Bug 22572

Summary: systemtap 3.2 failed to compile on ARM
Product: systemtap Reporter: Gustavo Moreira <gmoreira>
Component: runtimeAssignee: Jafeer Uddin <juddin>
Status: RESOLVED WONTFIX    
Severity: normal CC: dsmith, fche, mark, wcohen
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed: 2017-12-08 00:00:00

Description Gustavo Moreira 2017-12-08 01:37:31 UTC
The host OS is a Debian wheeze on ARM. I tried using different combinations systemtap/gcc/g++/kernels but I always have the same error. Basically, I tried:
- Systemtap git master and release 3.2
- gcc/g++-4.6 and gcc/g++-4.7
- Kernel 3.2.0-4-versatile and custom 3.2.93-versatile

The Systemtap package available in the wheeze apt is not an option because it is too old (v1.7). Anyway, I tried that Systemtap version and it's working with my current setup but failing with my current systemtap script because it doesn't have some of the Systemtap functions I'm using on it.

The isolated issue is when it tries to compile stap-staptree.o, basically:
$ make stap-staptree.o
  CXX      stap-staptree.o
In file included from staptree.cxx:10:0:
staptree.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = print_format::format_component; _Args = {print_format::format_component}]’:
/usr/include/c++/4.7/bits/stl_uninitialized.h:77:3:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<print_format::format_component*>; _ForwardIterator = print_format::format_component*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.7/bits/stl_uninitialized.h:119:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<print_format::format_component*>; _ForwardIterator = print_format::format_component*]’
/usr/include/c++/4.7/bits/stl_uninitialized.h:260:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<print_format::format_component*>; _ForwardIterator = print_format::format_component*; _Tp = print_format::format_component]’
/usr/include/c++/4.7/bits/stl_uninitialized.h:283:69:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = print_format::format_component*; _ForwardIterator = print_format::format_component*; _Allocator = std::allocator<print_format::format_component>]’
/usr/include/c++/4.7/bits/vector.tcc:410:6:   required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {const print_format::format_component&}; _Tp = print_format::format_component; _Alloc = std::allocator<print_format::format_component>]’
/usr/include/c++/4.7/bits/stl_vector.h:891:4:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = print_format::format_component; _Alloc = std::allocator<print_format::format_component>; std::vector<_Tp, _Alloc>::value_type = print_format::format_component]’
staptree.cxx:904:33:   required from here
staptree.h:516:10: error: invalid conversion from ‘unsigned char’ to ‘print_format::width_type’ [-fpermissive]
staptree.h:516:10: error: invalid conversion from ‘unsigned char’ to ‘print_format::precision_type’ [-fpermissive]
staptree.h:516:10: error: invalid conversion from ‘unsigned char’ to ‘print_format::conversion_type’ [-fpermissive]
In file included from /usr/include/c++/4.7/memory:66:0,
                 from staptree.h:14,
                 from staptree.cxx:10:
/usr/include/c++/4.7/bits/stl_construct.h:77:7: note: synthesized method ‘print_format::format_component::format_component(print_format::format_component&&)’ first required here 
make: *** [stap-staptree.o] Error 

Cheers,
Gus
Comment 1 Gustavo Moreira 2017-12-08 07:29:25 UTC
I've tried to compile every single release version from SystemTap 1.7 to 3.2. 
From 1.7 to 2.9 it compiles ok. The issue seems to be from 3.0 on (basically, 3.0, 3.1 and 3.2).
Comment 2 Mark Wielaard 2017-12-08 07:41:04 UTC
You might want to try with gcc 4.8 or higher to get full C++11 support.
gcc 4.7 is more than 5 years old now.
Comment 3 David Smith 2017-12-08 17:23:29 UTC
(In reply to Gustavo Moreira from comment #1)
> I've tried to compile every single release version from SystemTap 1.7 to
> 3.2. 
> From 1.7 to 2.9 it compiles ok. The issue seems to be from 3.0 on
> (basically, 3.0, 3.1 and 3.2).

According to the NEWS file:

====
* What's new in version 3.1, 2017-02-17

- Systemtap now needs C++11 to build.
====

The configure script tries to check for C++11 support, by seeing if your compiler supports the '-std=c++0x' option. In your config.log file, what is HAVE_CXX11 set to?
Comment 4 Frank Ch. Eigler 2017-12-08 18:11:41 UTC
Just a guess - does this hypothetical patch fix your build?

diff --git a/staptree.h b/staptree.h
index a376a436b88b..84d4fec63db9 100644
--- a/staptree.h
+++ b/staptree.h
@@ -518,10 +518,10 @@ struct print_format: public expression
     unsigned base;
     unsigned width;
     unsigned precision;
-    unsigned flags : 8;
-    width_type widthtype : 8;
-    precision_type prectype : 8;
-    conversion_type type : 8;
+    unsigned flags;
+    width_type widthtype;
+    precision_type prectype;
+    conversion_type type;
     interned_string literal_string;
     bool is_empty() const
     {
Comment 5 Torsten.Polle 2017-12-08 22:32:53 UTC
Hi,

I had a similar problem with gcc 4.5.2 and fixed it as follows.

--------------------------------- staptree.h ----------------------------------
index a376a43..d1e2da4 100644
@@ -519,9 +519,9 @@ struct print_format: public expression
     unsigned width;
     unsigned precision;
     unsigned flags : 8;
-    width_type widthtype : 8;
-    precision_type prectype : 8;
-    conversion_type type : 8;
+    unsigned char widthtype : 8;
+    unsigned char prectype : 8;
+    unsigned char type : 8;
     interned_string literal_string;
     bool is_empty() const
     {

Additionally, I build staprun for an ARM target with arm-unknown-linux-gnueabi-gcc (crosstool-NG 1.12.1 - buildroot 2011.08) 4.4.3. Here I need an additional patch.

Hack: std::string is missing.
    
Provide std::string as part of util.h as it missing in string.h.

------------------------------------ util.h ------------------------------------
index e642c5e..e4fdae4 100644
@@ -144,6 +144,15 @@ inline std::string lex_cast(IN const & in)
 
 #if __cplusplus < 201103L
 // Older C++0x only had the "long long" implementations, so we cast up.
+#  if (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
+namespace std {
+    static std::string to_string(size_t n) {
+        std::ostringstream s;
+        s << n;
+        return s.str();
+    }
+}
+#  endif
 #define INT_TO_STRING(IN) \
   LEX_CAST_TO_STRING(signed IN, long long) \
   LEX_CAST_TO_STRING(unsigned IN, unsigned long long)


Kind Regards,
Torsten
Comment 6 Gustavo Moreira 2017-12-11 00:51:23 UTC
(In reply to David Smith from comment #3)
> > ...
> > From 1.7 to 2.9 it compiles ok. The issue seems to be from 3.0 on
> > (basically, 3.0, 3.1 and 3.2).
> 
> According to the NEWS file:
> 
> ====
> * What's new in version 3.1, 2017-02-17
> 
> - Systemtap now needs C++11 to build.
> ====
> 
> The configure script tries to check for C++11 support, by seeing if your
> compiler supports the '-std=c++0x' option. In your config.log file, what is
> HAVE_CXX11 set to?

Thank you for your quick response.

Weird because the configure script ended up assuming that the C++ compiler supports the 2011 ISO C++ standard:

...
checking whether g++ supports C++11 features by default... no
checking whether g++ supports C++11 features with -std=c++11... no
checking whether g++ supports C++11 features with -std=c++0x... no
checking whether g++ supports C++11 features with +std=c++11... no
checking whether g++ supports C++11 features with -h std=c++11... no
configure: No compiler with C++11 support was found
checking whether C++ compiler accepts -std=c++0x... yes
configure: Compiling with -std=c++0x
...

$ grep CXX11 systemtap*/config.log
systemtap-3.1/config.log:HAVE_CXX11='1'
systemtap-3.2/config.log:HAVE_CXX11='1'
systemtap/config.log:HAVE_CXX11='1'

* systemtap/config.log is the latest git master.
** NB: systemtap-3.0 doesn't check for CXX11, and it doesn't compile due to the same issue.

Actually, I've tested the following code and it works:

test.cpp:
 enum AnEnum { BLAH1 = 1, BLAH2 = 2 };

 struct St
 {
     AnEnum Field : 8;
 };  

 main() {
     St st;
 }


$ g++ -std=c++11 test.cpp; echo $?
0
$ g++ -std=c++0x test.cpp; echo $?
0


Anyway, C++11 features were being developed from GCC 4.3 to 4.8.1, so with that I'm just testing one of the features already supported in 4.7.
Comment 7 Gustavo Moreira 2017-12-11 01:08:22 UTC
(In reply to Torsten.Polle from comment #5)
> Hi,
> 
> I had a similar problem with gcc 4.5.2 and fixed it as follows.
> 
> --------------------------------- staptree.h
> ----------------------------------
> index a376a43..d1e2da4 100644
> @@ -519,9 +519,9 @@ struct print_format: public expression
>      unsigned width;
>      unsigned precision;
>      unsigned flags : 8;
> -    width_type widthtype : 8;
> -    precision_type prectype : 8;
> -    conversion_type type : 8;
> +    unsigned char widthtype : 8;
> +    unsigned char prectype : 8;
> +    unsigned char type : 8;
>      interned_string literal_string;
>      bool is_empty() const
>      {
> 
> Additionally, I build staprun for an ARM target with
> arm-unknown-linux-gnueabi-gcc (crosstool-NG 1.12.1 - buildroot 2011.08)
> 4.4.3. Here I need an additional patch.
> 
> Hack: std::string is missing.
>     
> Provide std::string as part of util.h as it missing in string.h.
> 
> ------------------------------------ util.h
> ------------------------------------
> index e642c5e..e4fdae4 100644
> @@ -144,6 +144,15 @@ inline std::string lex_cast(IN const & in)
>  
>  #if __cplusplus < 201103L
>  // Older C++0x only had the "long long" implementations, so we cast up.
> +#  if (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
> +namespace std {
> +    static std::string to_string(size_t n) {
> +        std::ostringstream s;
> +        s << n;
> +        return s.str();
> +    }
> +}
> +#  endif
>  #define INT_TO_STRING(IN) \
>    LEX_CAST_TO_STRING(signed IN, long long) \
>    LEX_CAST_TO_STRING(unsigned IN, unsigned long long)
> 
> 
> Kind Regards,
> Torsten

Thanks Torsten, awesome. 

I wonder why it's failing, because it's not due to the CXX11's "Strongly-typed enums" feature. Actually, I've tested it separately and this feature works with G++ 4.7 (have a look to my response to David@). It seems to be failing inside STL. 

PS: The 8bit bit-field is redundant for char type, but yeah it doesn't hurt ;)

Thanks again,
Gus
Comment 8 Gustavo Moreira 2017-12-11 01:44:55 UTC
(In reply to Frank Ch. Eigler from comment #4)
> Just a guess - does this hypothetical patch fix your build?
> 
> diff --git a/staptree.h b/staptree.h
> index a376a436b88b..84d4fec63db9 100644
> --- a/staptree.h
> +++ b/staptree.h
> @@ -518,10 +518,10 @@ struct print_format: public expression
>      unsigned base;
>      unsigned width;
>      unsigned precision;
> -    unsigned flags : 8;
> -    width_type widthtype : 8;
> -    precision_type prectype : 8;
> -    conversion_type type : 8;
> +    unsigned flags;
> +    width_type widthtype;
> +    precision_type prectype;
> +    conversion_type type;
>      interned_string literal_string;
>      bool is_empty() const
>      {

Thanks Frank, yeah patching it that way also works. 

Same concern I asked to Torsten@ and David@ :
"I wonder why it's failing, because it's not due to the CXX11's "Strongly-typed enums" feature. Actually, I've tested it separately and this feature works with G++ 4.7 (have a look to my response to David@). It seems to be failing inside STL."

Cheers,
Gus
Comment 9 Frank Ch. Eigler 2017-12-11 13:44:18 UTC
Understanding that this is probably a bug in an older toolchain, the only choice we have is whether we support it (with its mystery bugs/limitations) or not.  IMHO if we can easily support it, we should.
Comment 10 William Cohen 2024-01-18 01:12:26 UTC
Going to close this issue as currently supported distributions are using newer versions of GCC that should support C++11 (GCC-4.8.1 https://gcc.gnu.org/projects/cxx-status.html#cxx11).