]> sourceware.org Git - systemtap.git/commitdiff
stapbpf PR22330 :: cleanup round 2 of n
authorSerhei Makarov <smakarov@redhat.com>
Thu, 14 Mar 2019 16:18:39 +0000 (12:18 -0400)
committerSerhei Makarov <smakarov@redhat.com>
Thu, 14 Mar 2019 16:18:39 +0000 (12:18 -0400)
bpf-internal.h
bpf-translate.cxx
stapbpf/bpfinterp.cxx
stapbpf/bpfinterp.h
stapbpf/stapbpf.cxx

index df7fa5b5b4d6ba0f6f1ebfe01729362dbc2f554b..cdfa771bb2e0286e500f490df3a9a85ed0e3c847 100644 (file)
@@ -38,23 +38,27 @@ struct vardecl;
 
 namespace bpf {
 
+// Constants for BPF code generation.
+// TODO: BPF_MAX{STRING,FORMAT}LEN,BPF_MAXMAPENTRIES,BPF_MAXSPRINTFLEN should be user-configurable.
+
 #define MAX_BPF_STACK 512
 #define BPF_REG_SIZE 8
+
 #define BPF_MAXSTRINGLEN 64
-// #define BPF_MAXSTRINGLEN 128 // TODO: Longer strings require storage allocator & PR22330 better printf().
+// #define BPF_MAXSTRINGLEN 128 // TODO: Longer strings require a smarter storage allocator.
+#define BPF_MAXFORMATLEN 256
 #define BPF_MAXPRINTFARGS 32
 // #define BPF_MAXPRINTFARGS 3 // Maximum for trace_printk() method.
-#define BPF_MAXFORMATLEN 256
+#define BPF_MAXSPRINTFARGS 3   // Maximum for sprintf() method.
+
 #define BPF_MAXMAPENTRIES 2048
-// TODO: add BPF_MAXSPRINTFLEN
-// TODO: BPF_MAX{STRING,FORMAT}LEN,BPF_MAXMAPENTRIES,BPF_MAXSPRINTFLEN should be user-configurable.
 // XXX: BPF_MAXMAPENTRIES may depend on kernel version. May need to experiment with rlimit in instantiate_maps().
 
-// TODOXXX: Constants for transport message layout. Try to reduce the size (to __u32) while keeping proper alignment.
-#define BPF_TRANSPORT_VAL __u64
-#define BPF_TRANSPORT_ARG __u64
+// Constants for transport message layout.
+// TODO: Try to reduce the size (to __u32) while keeping proper alignment.
+#define BPF_TRANSPORT_VAL uint64_t
+#define BPF_TRANSPORT_ARG uint64_t
 // XXX: BPF_TRANSPORT_ARG is for small numerical arguments, not pe_long values.
-// TODOXXX: Use sizeof(BPF_TRANSPORT_*) instead of magic numbers throughout.
 
 // Will print out bpf assembly before and after optimization:
 //#define DEBUG_CODEGEN
index 2825cf1490b6fca88756daa698e9f2ba5bc40683..a30cdfc81e36484c90f28456140b72b157c515f7 100644 (file)
@@ -1373,7 +1373,6 @@ bpf_unparser::visit_embeddedcode (embeddedcode *s)
                 {
                   value *dest = get_asm_reg(stmt, stmt.dest);
                   this_prog.mk_mov(this_ins, dest, retval);
-
                 }
               // ??? For diagnostics: check other cases with retval and stmt.dest.
             }
@@ -2748,7 +2747,6 @@ bpf_unparser::emit_string_copy(value *dest, int ofs, value *src, bool zero_pad)
   this_prog.mk_binary(this_ins, BPF_ADD, out,
                       dest, this_prog.new_imm(ofs));
 
-  
 #ifdef DEBUG_CODEGEN
   this_ins.notes.pop(); // strcpy
 #endif
@@ -2912,12 +2910,14 @@ bpf_unparser::emit_transport_msg (globals::perf_event_type msg,
         assert(false); // XXX: Should be caught earlier.
       }
 
-  // TODOXXX: add code to ensure alignment, depending on argument size.
+  // XXX: The following force-aligns all elements to double word boundary.
+  // Could probably switch to single-word alignment with more careful design.
   if (arg_size % 8 != 0)
-    arg_size += 8 - arg_size % 8; // double word -- XXX verifier forces aligned access
+    arg_size += 8 - arg_size % 8;
   int arg_ofs = -arg_size;
-  int msg_ofs = arg_ofs-sizeof(BPF_TRANSPORT_VAL); // double word -- XXX verifier forces aligned access
-  assert(msg_ofs % 8 == 0);
+  int msg_ofs = arg_ofs-sizeof(BPF_TRANSPORT_VAL);
+  if (msg_ofs % 8 != 0)
+    msg_ofs -= (8 - (-msg_ofs) % 8);
   this_prog.use_tmp_space(-msg_ofs);
 
   value *frame = this_prog.lookup_reg(BPF_REG_10);
@@ -3001,6 +3001,13 @@ bpf_unparser::emit_print_format (const std::string& format,
 
   if (!print_to_stream)
     {
+      // TODO: sprintf() has an additional constraint on arguments due
+      // to passing them in a very small number of registers.
+      if (actual.size() > BPF_MAXSPRINTFARGS)
+        throw SEMANTIC_ERROR(_NF("additional argument to sprintf",
+                                 "too many arguments to sprintf (%zu)",
+                                 actual.size(), e->args.size()), tok);
+
       // Emit an ordinary function call to sprintf.
       size_t format_bytes = format.size() + 1;
       this_prog.mk_mov(this_ins, this_prog.lookup_reg(BPF_REG_1),
index 772f163cbbef4a42d210229d1715be6454c88482..80dace5f788c4805d71814dcac950fb5a2f88a6a 100644 (file)
@@ -145,7 +145,7 @@ empty:
   return -1;
 }
 
-// TODOXXX: Adapt to MAXPRINTFARGS == 32.
+// TODO: Adapt to MAXPRINTFARGS == 32.
 uint64_t
 bpf_sprintf(std::vector<std::string> &strings, char *fstr,
             uint64_t arg1, uint64_t arg2, uint64_t arg3)
@@ -228,7 +228,7 @@ bpf_handle_transport_msg(void *buf, size_t size,
       for (unsigned i = 0; i < BPF_MAXPRINTFARGS; i++)
         if (i < ctx->printf_args.size()
             && ctx->printf_arg_types[i] == bpf::globals::STP_PRINTF_ARG_LONG)
-          fargs[i] = (void *)*(__u64*)ctx->printf_args[i]; // TODOXXX: Fixup for 32-bit systems?
+          fargs[i] = (void *)*(uint64_t*)ctx->printf_args[i]; // TODOXXX: Fixup for 32-bit systems?
         else if (i < ctx->printf_args.size())
           fargs[i] = ctx->printf_args[i];
         else
index f8c59570632782d2cdecd5cac918a33b78f7e1c6..8fc1eabd617fa30a7a202d79dc7e2ef709d22de5 100644 (file)
@@ -33,9 +33,10 @@ extern "C" {
 
 // Used by the transport layer and interpreter:
 struct bpf_transport_context {
+  // XXX: The following two fields are only used for kernel programs.
+  // pmu_fd == -1 indicates context for a userspace interpreter.
   unsigned cpu;
   int pmu_fd;
-  // TODOXXX: If pmu_fd == -1, this is a userspace context. Be sure to reflect this in diagnostics.
 
   // References to global state:
   std::vector<int> *map_fds;
index e32cd91df6f6f4fa69b9dc9c5620e6cffc63edb3..b430bada42bbe5f0ef28d6d6a1e6a420b4595e28 100644 (file)
@@ -189,9 +189,8 @@ static std::vector<perf_data> perf_probes;
 static std::vector<trace_data> tracepoint_probes;
 static std::vector<uprobe_data> uprobes;
 
-// TODOXXX: Move fatal() to bpfinterp.h and replace abort() calls in the interpreter.
-// TODOXXX: Add warn() option.
-
+// TODO: Move fatal() to bpfinterp.h and replace abort() calls in the interpreter.
+// TODO: Add warn() option.
 static void __attribute__((noreturn))
 fatal(const char *str, ...)
 {
@@ -1472,7 +1471,7 @@ perf_event_loop(pthread_t main_thread)
       if (log_level > 3)
         fprintf(stderr, "Polling for perf_event data on %d cpus...\n", ncpus);
       int ready = poll(pmu_fds, ncpus, 1000); // XXX: Consider setting timeout -1 (unlimited).
-      if (ready < 0 && errno == EINTR) // TODOXXX: Check that we really received a signal.
+      if (ready < 0 && errno == EINTR)
         goto signal_exit;
       if (ready < 0)
         fatal("Error checking for perf events: %s\n", strerror(errno));
@@ -1515,79 +1514,6 @@ perf_event_loop(pthread_t main_thread)
   return;
 }
 
-// TODOXXX PR22330: remove this older code.
-#if 0
-static void
-print_trace_output(pthread_t main_thread)
-{
-  // Output from printf statements within probe handlers is sent to
-  // debugfs via trace_printk. Get this output and copy it to output_f.
-  string modname(module_name);
-  size_t pos = modname.find_last_of("/");
-  if (pos != string::npos)
-    modname = modname.substr(pos + 1);
-
-  string start_tag = "<" + modname.erase(modname.size() - 3).erase(4, 1) + ">";
-  string end_tag = start_tag;
-  end_tag.insert(1, "/");
-
-  while (1)
-    {
-      ifstream trace_pipe(DEBUGFS "trace_pipe");
-      if (!trace_pipe)
-        fatal("error opening trace_pipe: %s\n", strerror(errno));
-
-      bool start_tag_seen = false;
-      unsigned bytes_written = 0;
-      string line, buf;
-      while (getline(trace_pipe, line))
-        {
-          line += "\n";
-          if (!start_tag_seen)
-            {
-              pos = line.find(start_tag);
-              if (pos != string::npos)
-                {
-                  start_tag_seen = true;
-                  bytes_written = 0;
-                  line = line.substr(pos + start_tag.size(), string::npos);
-                }
-            }
-          if (start_tag_seen)
-            {
-              pos = line.find(end_tag);
-              if (pos != string::npos)
-                {
-                  line = line.substr(0, pos);
-                  start_tag_seen = false;
-
-                  // exit() causes "" to be written to trace_pipe. If
-                  // "" is seen and the exit flag is set, wake up main
-                  // thread to begin program shutdown.
-                  if (line == "" && buf == "" && bytes_written == 0
-                      && get_exit_status())
-                    {
-                      pthread_kill(main_thread, SIGINT);
-                      return;
-                    }
-                }
-
-              buf += line;
-              if (fwrite(buf.c_str(), sizeof(char), buf.size(), output_f)
-                   != buf.size())
-                fatal("error writing to output file: %s\n", strerror(errno));
-              bytes_written += buf.size();
-
-              fflush(output_f);
-              buf = "";
-            }
-        }
-      // If another process opens trace_pipe then we may read EOF. In this
-      // case simply reopen the file and continue parsing.
-    }
-}
-#endif
-
 static void
 usage(const char *argv0)
 {
@@ -1709,7 +1635,6 @@ main(int argc, char **argv)
 
   // PR22330: Listen for perf_events:
   std::thread(perf_event_loop, pthread_self()).detach();
-  //std::thread(print_trace_output, pthread_self()).detach(); // TODOXXX: remove this older code.
 
   // Now that the begin probe has run and the perf_event listener is active, enable the kprobes.
   ioctl(group_fd, PERF_EVENT_IOC_ENABLE, 0);
This page took 0.043381 seconds and 5 git commands to generate.