Files updated, added and removed in order to turn the ERASER branch into HEAD


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1086 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/lackey/lk_main.c b/lackey/lk_main.c
new file mode 100644
index 0000000..4592cc6
--- /dev/null
+++ b/lackey/lk_main.c
@@ -0,0 +1,224 @@
+/*--------------------------------------------------------------------*/
+/*--- Simple skin for counting UInstrs, using a C helper.          ---*/
+/*---                                                  vg_lackey.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an x86 protected-mode emulator 
+   designed for debugging and profiling binaries on x86-Unixes.
+
+   Copyright (C) 2002 Nicholas Nethercote
+      njn25@cam.ac.uk
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_skin.h"
+
+//#define uInstr0   VG_(newUInstr0)
+//#define uLiteral  VG_(setLiteralField)
+
+/* Nb: use ULongs because the numbers can get very big */
+static ULong n_dlrr_calls   = 0;
+static ULong n_BBs          = 0;
+static ULong n_UInstrs      = 0;
+static ULong n_x86_instrs   = 0;
+static ULong n_Jccs         = 0;
+static ULong n_Jccs_untaken = 0;
+
+static void add_one_dlrr_call(void)
+{
+   n_dlrr_calls++;
+}
+
+/* See comment above SK_(instrument) for reason why n_x86_instrs is
+   incremented here. */
+static void add_one_BB(void)
+{
+   n_BBs++;
+   n_x86_instrs++;
+}
+
+static void add_one_UInstr(void)
+{
+   n_UInstrs++;
+}
+
+static void add_one_x86_instr(void)
+{
+   n_x86_instrs++;
+}
+
+static void add_one_Jcc(void)
+{
+   n_Jccs++;
+}
+
+static void add_one_Jcc_untaken(void)
+{
+   n_Jccs_untaken++;
+}
+
+void SK_(pre_clo_init)(VgNeeds* needs, VgTrackEvents* not_used)
+{
+   needs->name        = "lackey";
+   needs->description = "a UInstr counter";
+
+   //VG_(register_compact_helper)((Addr) & add_one_dlrr_call);
+   VG_(register_compact_helper)((Addr) & add_one_BB);
+   VG_(register_compact_helper)((Addr) & add_one_x86_instr);
+   VG_(register_compact_helper)((Addr) & add_one_UInstr);
+   VG_(register_compact_helper)((Addr) & add_one_Jcc);
+   VG_(register_compact_helper)((Addr) & add_one_Jcc_untaken);
+}
+
+void SK_(post_clo_init)(void)
+{
+}
+
+/* Note: x86 instructions are marked by an INCEIP at the end of each one,
+   except for the final one in the basic block which ends in an
+   unconditional JMP.  Sometimes the final unconditional JMP is preceded by
+   a conditional JMP (Jcc), and thus it isn't reached.  Eg:
+
+      <code a>
+      INCEIP ...
+
+      <code b>
+      Jcc ...
+      JMP ...     (will not be reached if Jcc succeeds)
+
+   If we simplemindedly added calls to add_one_x86_instr() before INCEIPs
+   and unconditional JMPs, we'd sometimes miss the final call (when a
+   preceding conditional JMP succeeds), underestimating the x86 instruction
+   count.
+
+      <code a>
+      call add_one_x86_instr()
+      INCEIP ...
+
+      <code b>
+      Jcc ...
+      call add_one_x86_instr()
+      JMP ...
+
+   Instead we add a call before each INCEIP, and also one at the start of the
+   block, but not one at the end, viz:
+
+      call add_one_x86_instr()
+
+      <code a>
+      call add_one_x86_instr()
+      INCEIP ...
+
+      <code b>
+      Jcc ...
+      JMP ...
+
+   Which gives us the right answer.  And just to avoid two C calls, we fold
+   the basic-block-beginning call in with add_one_BB().  Phew.
+*/ 
+UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
+{
+   UCodeBlock* cb;
+   Int         i;
+   UInstr*     u;
+   Char        fnname[100];
+
+   cb = VG_(allocCodeBlock)();
+   cb->nextTemp = cb_in->nextTemp;
+
+   /* Count call to dlrr(), if this BB is dlrr()'s entry point */
+   if (VG_(get_fnname_if_entry)(orig_addr, fnname, 100) &&
+       0 == VG_(strcmp)(fnname, "_dl_runtime_resolve")) 
+   {
+      VG_(callHelper_0_0)(cb, (Addr) & add_one_dlrr_call);
+   }
+
+   /* Count basic block */
+   VG_(callHelper_0_0)(cb, (Addr) & add_one_BB);
+
+   for (i = 0; i < cb_in->used; i++) {
+      u = &cb_in->instrs[i];
+
+      switch (u->opcode) {
+         case NOP: case CALLM_S: case CALLM_E:
+            break;
+   
+         case INCEIP:
+            /* Count x86 instr */
+            VG_(callHelper_0_0)(cb, (Addr) & add_one_x86_instr);
+            VG_(copyUInstr)(cb, u);
+            break;
+
+         case JMP:
+            if (u->cond != CondAlways) {
+               /* Count Jcc */
+               VG_(callHelper_0_0)(cb, (Addr) & add_one_Jcc);
+               VG_(copyUInstr)(cb, u);
+               /* Count non-taken Jcc */
+               VG_(callHelper_0_0)(cb, (Addr) & add_one_Jcc_untaken);
+            } else {
+               VG_(copyUInstr)(cb, u);
+            }
+            break;
+            
+         default:
+            /* Count UInstr */
+            VG_(callHelper_0_0)(cb, (Addr) & add_one_UInstr);
+            VG_(copyUInstr)(cb, u);
+            break;
+      }
+   }
+
+   VG_(freeCodeBlock)(cb_in);
+   return cb;
+}
+
+void SK_(fini)(void)
+{
+    VG_(message)(Vg_UserMsg,
+                 "Counted %d calls to _dl_runtime_resolve()", n_dlrr_calls);
+
+    VG_(message)(Vg_UserMsg, "");
+    VG_(message)(Vg_UserMsg, "Executed:");
+    VG_(message)(Vg_UserMsg, "  BBs:         %u", n_BBs);
+    VG_(message)(Vg_UserMsg, "  x86 instrs:  %u", n_x86_instrs);
+    VG_(message)(Vg_UserMsg, "  UInstrs:     %u", n_UInstrs);
+
+    VG_(message)(Vg_UserMsg, "");
+    VG_(message)(Vg_UserMsg, "Jccs:");
+    VG_(message)(Vg_UserMsg, "  total:       %u", n_Jccs);
+    VG_(message)(Vg_UserMsg, "  %% taken:     %u%%",
+                             (n_Jccs - n_Jccs_untaken)*100 / n_Jccs);
+
+    VG_(message)(Vg_UserMsg, "");
+    VG_(message)(Vg_UserMsg, "Ratios:");
+    VG_(message)(Vg_UserMsg, "  x86 instrs : BB        = %3u : 10",
+                             10 * n_x86_instrs / n_BBs);
+    VG_(message)(Vg_UserMsg, "     UInstrs : BB        = %3u : 10",
+                             10 * n_UInstrs / n_BBs);
+    VG_(message)(Vg_UserMsg, "     UInstrs : x86_instr = %3u : 10",
+                             10 * n_UInstrs / n_x86_instrs);
+
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                              vg_lackey.c ---*/
+/*--------------------------------------------------------------------*/
+