Bug 13974 - sdt.h is incompatible with clang
Summary: sdt.h is incompatible with clang
Status: RESOLVED FIXED
Alias: None
Product: systemtap
Classification: Unclassified
Component: translator (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-04-12 17:35 UTC by Josh Stone
Modified: 2014-05-28 19:42 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Josh Stone 2012-04-12 17:35:58 UTC
A simple sdt test with clang fails to build:

$ cat foosdt.c 
#include <sys/sdt.h>
void foo(void)
{
    STAP_PROBE(foo, foo);
}

$ clang -c foosdt.c 
foosdt.c:4:6: error: unknown flag
    STAP_PROBE(foo, foo);
    ^
In file included from foosdt.c:1:
/usr/local/include/sys/sdt.h:254:3: note: instantiated from:
  _SDT_PROBE(provider, name, 0, ())
  ^
/usr/local/include/sys/sdt.h:36:27: note: instantiated from:
    __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \
                          ^
/usr/local/include/sys/sdt.h:176:3: note: instantiated from:
  _SDT_ASM_3(           .pushsection .note.stapsdt,_SDT_ASM_AUTOGROUP,"note") \
  ^
/usr/local/include/sys/sdt.h:43:31: note: instantiated from:
# define _SDT_ASM_3(a, b, c)            _SDT_S(a) "," _SDT_S(b) "," \
                                        ^
<scratch space>:4:2: note: instantiated from:
".pushsection .note.stapsdt"
 ^
<inline asm>:2:31: note: instantiated into assembly here
.pushsection .note.stapsdt,"?","note"
                              ^
foosdt.c:4:6: error: .popsection without corresponding .pushsection
    STAP_PROBE(foo, foo);
    ^
In file included from foosdt.c:1:
/usr/local/include/sys/sdt.h:254:3: note: instantiated from:
  _SDT_PROBE(provider, name, 0, ())
  ^
/usr/local/include/sys/sdt.h:36:27: note: instantiated from:
    __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \
                          ^
/usr/local/include/sys/sdt.h:188:3: note: instantiated from:
  _SDT_ASM_1(           .popsection)
  ^
/usr/local/include/sys/sdt.h:41:26: note: instantiated from:
# define _SDT_ASM_1(x)                  _SDT_S(x) "\n"
                                        ^
<scratch space>:24:2: note: instantiated from:
".popsection"
 ^
<inline asm>:14:12: note: instantiated into assembly here
.popsection
           ^
foosdt.c:4:6: error: expected '@' or '%' before type
    STAP_PROBE(foo, foo);
    ^
In file included from foosdt.c:1:
/usr/local/include/sys/sdt.h:254:3: note: instantiated from:
  _SDT_PROBE(provider, name, 0, ())
  ^
/usr/local/include/sys/sdt.h:38:27: note: instantiated from:
    __asm__ __volatile__ (_SDT_ASM_BASE);                                   \
                          ^
/usr/local/include/sys/sdt.h:192:3: note: instantiated from:
  _SDT_ASM_5(           .pushsection .stapsdt.base,"aG","progbits",           \
  ^
/usr/local/include/sys/sdt.h:45:36: note: instantiated from:
# define _SDT_ASM_5(a, b, c, d, e)      _SDT_S(a) "," _SDT_S(b) "," \
                                        ^
<scratch space>:27:2: note: instantiated from:
".pushsection .stapsdt.base"
 ^
<inline asm>:2:33: note: instantiated into assembly here
.pushsection .stapsdt.base,"aG","progbits",.stapsdt.base,comdat
                                ^
foosdt.c:4:6: error: .popsection without corresponding .pushsection
    STAP_PROBE(foo, foo);
    ^
In file included from foosdt.c:1:
/usr/local/include/sys/sdt.h:254:3: note: instantiated from:
  _SDT_PROBE(provider, name, 0, ())
  ^
/usr/local/include/sys/sdt.h:38:27: note: instantiated from:
    __asm__ __volatile__ (_SDT_ASM_BASE);                                   \
                          ^
/usr/local/include/sys/sdt.h:198:3: note: instantiated from:
  _SDT_ASM_1(           .popsection)                                          \
  ^
/usr/local/include/sys/sdt.h:41:26: note: instantiated from:
# define _SDT_ASM_1(x)                  _SDT_S(x) "\n"
                                        ^
<scratch space>:37:2: note: instantiated from:
".popsection"
 ^
<inline asm>:7:12: note: instantiated into assembly here
.popsection
           ^
4 errors generated.
Comment 1 Josh Stone 2012-04-12 17:44:50 UTC
(In reply to comment #0)
> foosdt.c:4:6: error: unknown flag
[...]
> <inline asm>:2:31: note: instantiated into assembly here
> .pushsection .note.stapsdt,"?","note"
>                               ^

This error is due to our compiler-dependent test for sdt-config.h:

> /* includes/sys/sdt-config.h.  Generated from sdt-config.h.in by configure.
> 
>    This file just defines _SDT_ASM_SECTION_AUTOGROUP_SUPPORT to 0 or 1 to
>    indicate whether the assembler supports "?" in .pushsection directives.  */
>
> #define _SDT_ASM_SECTION_AUTOGROUP_SUPPORT 1

My installed header was created for gcc, which does support this flag, but clearly clang does not.  I'm not sure how we could deal with multiple system compilers in general.  Perhaps we'd have to add #ifdef to sdt-config.h to match the compiler which was tested, and assume 0 if encountering something else?

With sdt-config.h configured directly with clang, there's a different error at the same place, and the rest of the errors are still the same.

> foosdt.c:4:6: error: expected '@' or '%' before type
[...]
> <inline asm>:2:31: note: instantiated into assembly here
> .pushsection .note.stapsdt,"","note"
>                               ^
Comment 2 Mark Wielaard 2013-09-11 18:05:38 UTC
BTW. It might a good idea to add some configure check before using a feature like SDT probes. Even really old g++ versions have been observed to have trouble with using probe macros in C++ contructors or destructors for example.

This configure snippet seems to find all troubling C++ compilers (for C any gcc version seems to be fine, only clang seems to have issues):

dnl ===================================================================
dnl Check if SDT probes (for systemtap, gdb, dtrace) are available
dnl ===================================================================

# We need at least the sys/sdt.h include header.
AC_CHECK_HEADER([sys/sdt.h], [SDT_H_FOUND='TRUE'], [SDT_H_FOUND='FALSE'])
if test "$SDT_H_FOUND" = "TRUE"; then
  # Found sys/sdt.h header, now make sure the c++ compiler works.
  # Old g++ versions had problems with probes in constructors/destructors.
  AC_MSG_CHECKING([working sys/sdt.h and c++ support])
  AC_LANG_PUSH([C++])
  AC_LINK_IFELSE([AC_LANG_PROGRAM([[
    #include <sys/sdt.h>
    class ProbeClass
    {
    private:
      int& ref;
      const char *name;

    public:
      ProbeClass(int& v, const char *n) : ref(v), name(n)
      {
        DTRACE_PROBE2(_test_, cons, name, ref);
      }

      void method(int min)
      {
        DTRACE_PROBE3(_test_, meth, name, ref, min);
        ref -= min;
      }

      ~ProbeClass()
      {
        DTRACE_PROBE2(_test_, dest, name, ref);
      }
    };
  ]],[[
    int i = 64;
    DTRACE_PROBE1(_test_, call, i);
    ProbeClass inst = ProbeClass(i, "call");
    inst.method(24);
  ]])], [AC_MSG_RESULT([yes]); AC_DEFINE([USE_SDT_PROBES])],
        [AC_MSG_RESULT([no, sdt.h or c++ compiler too old])])
  AC_LANG_POP([C++])
fi
AC_CONFIG_HEADERS([config_probes.h])

Where config_probes.h.in might be something like:

#ifndef CONFIG_PROBES_H
#define CONFIG_PROBES_H

/* Whether we have and can use sys/sdt.h for probes.  */
#define USE_SDT_PROBES 0

#endif
Comment 3 Josh Stone 2013-09-21 00:19:05 UTC
Martin C. Martin filed a couple bugs with LLVM:
  http://llvm.org/bugs/show_bug.cgi?id=17198
  http://llvm.org/bugs/show_bug.cgi?id=17270

The first is now fixed with llvm-mc gaining support for the "?" flag.

The second gave us a hint that led me to use %note instead of "note", with %%-quoting as needed for operand expansion.  This is pushed in commit a31190f5.

So I think we can call this FIXED, but let's keep a careful eye on that %note form to make sure it doesn't create problems anywhere else...
Comment 4 Josh Stone 2013-09-26 19:43:42 UTC
(In reply to Josh Stone from comment #3)
> The second gave us a hint that led me to use %note instead of "note", with
> %%-quoting as needed for operand expansion.  This is pushed in commit
> a31190f5.

I'm actually going to revert this.  The difficulty of '%' is that it must be escaped for asm() blocks that have operands, but must not be escaped in asm() blocks without operands, nor for pure ASM source files.  But we have a SDT_PROBE_ASM construct available for others to use in their own asm(), where we have no idea if escaping is needed.  It turns out glibc uses this, and we broke their build on Fedora rawhide due to bad %-escaping.

We can't use @note because GAS says that's a comment on ARM, so we're left back at "note" being the most straightforward.  I'll revert the change, but at least now we have some documented justification for the chosen syntax.

Besides, LLVM finished up 17270 with support for the "note" syntax, so anyone interested in SDT there can use an LLVM snapshot or wait for their next release.
Comment 5 Jackie Rosen 2014-02-16 17:44:55 UTC Comment hidden (spam)