TEMU/Tracecap, 64-bit Ubuntu 12.04 build walk-through

2021 views
Skip to first unread message

Stephen McCamant

unread,
Mar 22, 2013, 4:19:34 PM3/22/13
to bitblaz...@googlegroups.com
Given the recent series of questions about compiling TEMU and Tracecap
under various circumstances, I thought it would be useful to repost
some patches and describe a walk-through of how to compile TEMU and
Tracecap on a more modern Linux system. For this I'll use a 64-bit
Ubuntu 12.04 system, which doesn't have GCC 3.4 easily available.

First, here's how you can build TEMU-1.0 with a patch to enable GCC 4
and 64-bit host support:

wget http://bitblaze.cs.berkeley.edu/release/temu-1.0/temu-1.0.tar.gz
tar xvzf temu-1.0.tar.gz
cd temu-1.0
patch -p0 <../temu-release2009-gcc4.patch
./configure --target-list=i386-softmmu --proj-name=sample_plugin --prefix=$(pwd)/install --disable-gcc-check
make
make install

I think this patch has been posted to the mailing list before, but
I'll attach it to this message as well. This should give you a version
of TEMU where the sample_plugin runs.

Next, you can download the additional source-code release and merge
its updated files (including Tracecap source) into your TEMU tree:

cd ..
wget http://bitblaze.cs.berkeley.edu/release/additional/bitblaze-additional-2010-06.tar.gz
tar xvzf bitblaze-additional-2010-06.tar.gz
mv bitblaze bitblaze-additional-2010-06
cd temu-1.0
rsync -rav ../bitblaze-additional-2010-06/temu/ .

Tracecap further depends on two open-source libraries, Sleuthkit and
llconf. For Sleuthkit, we download version 2.04 and apply a patch that
comes with the additional source-code release. We also need to fix two
more build problems that post-date that release, namely that Sleuthkit
doesn't know that Linux 3.x is compatible with Linux 2.x, and a name
conflict related to its endian.h header, which are handled by another
attached patch:

cd shared
mv sleuthkit/sleuthkit-2.04.patch .
rmdir sleuthkit
# Download sleuthkit-2.04.tar.gz from
# http://sourceforge.net/projects/sleuthkit/files/sleuthkit/2.04/
tar xvzf sleuthkit-2.04.tar.gz
cd sleuthkit-2.04
patch -p1 <../sleuthkit-2.04.patch
patch -p0 <../../../sleuthkit-linux3.patch
make
cd ..
ln -s sleuthkit-2.04 sleuthkit

Then llconf is a little bit easier, but you need to add the -fPIC
option to enable linking it into Tracecap's shared library on 64-bit:

wget http://llconf.googlecode.com/files/llconf-0.4.6.tar.gz
tar xvzf llconf-0.4.6.tar.gz
cd llconf-0.4.6
CFLAGS="-fPIC" ./configure --prefix=$(pwd)/install
make
make install
cd ..
ln -s llconf-0.4.6 llconf
cd ..

Then you can reconfigure TEMU and compile with Tracecap as the plugin:

./configure --target-list=i386-softmmu --proj-name=tracecap --prefix=$(pwd)/install --disable-gcc-check
make clean
make

Hope this helps,

-- Stephen

temu-release2009-gcc4.patch
sleuthkit-linux3.patch

Frank Loyd

unread,
Mar 27, 2013, 4:20:41 AM3/27/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
Hello, thanks for your instructions, but i have got error("make[1]: no rule  to make target install; make *** [install] error 2 "). i use patch temu-release2009-gcc4.patch, and it happens at once than i do "make install" after patching


Index: dyngen-exec.h
===================================================================
--- dyngen-exec.h        (previous revision)
+++ dyngen-exec.h        (working copy)
@@ -194,7 +194,12 @@
 #endif
 
 /* force GCC to generate only one epilog at the end of the function */
+#if defined(__i386__) || defined(__x86_64__)
+/* Also add 4 bytes of padding so that we can replace the ret with a jmp.  */
+#define FORCE_RET() asm volatile ("nop;nop;nop;nop");
+#else
 #define FORCE_RET() __asm__ __volatile__("" : : : "memory");
+#endif
 
 #ifndef OPPROTO
 #define OPPROTO
@@ -251,11 +256,18 @@
 #endif
 
 #if defined(__i386__)
-#define EXIT_TB() asm volatile ("ret")
-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
+/* Dyngen will replace hlt instructions with a ret instruction.  Inserting a
+   ret directly would confuse dyngen.  */
+#define EXIT_TB() asm volatile ("hlt")
+/* Dyngen will replace cli with 0x9e (jmp).
+   We generate the offset manually.  */
+#define GOTO_LABEL_PARAM(n) \
+  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
 #elif defined(__x86_64__)
-#define EXIT_TB() asm volatile ("ret")
-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
+/* The same as i386.  */
+#define EXIT_TB() asm volatile ("hlt")
+#define GOTO_LABEL_PARAM(n) \
+  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
 #elif defined(__powerpc__)
 #define EXIT_TB() asm volatile ("blr")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
Index: Makefile.target
===================================================================
--- Makefile.target        (previous revision)
+++ Makefile.target        (working copy)
@@ -82,6 +82,10 @@
 else
 QEMU_SYSTEM=qemu-fast
 endif
+ifeq ($(TARGET_ARCH), x86_64)
+# XXX globally save %ebx, %esi, %edi on entry to generated function
+OP_CFLAGS+= -fcall-used-ebx -fcall-used-esi -fcall-used-edi
+endif
 
 ifdef CONFIG_USER_ONLY
 PROGS=$(QEMU_USER)
@@ -117,7 +121,7 @@
 
 ifeq ($(ARCH),i386)
 HELPER_CFLAGS+=-fomit-frame-pointer
-OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
+OP_CFLAGS+=-fomit-frame-pointer
 ifdef TARGET_GPROF
 USE_I386_LD=y
 endif
Index: softmmu_header.h
===================================================================
--- softmmu_header.h        (previous revision)
+++ softmmu_header.h        (working copy)
@@ -86,7 +86,7 @@
 #endif
 
 #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
-    (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU) && (TAINT_ENABLED==0)
+    (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU) && (__GNUC__ < 4) && (TAINT_ENABLED==0)
 
 #define CPU_TLB_ENTRY_BITS 4
 
@@ -128,7 +128,7 @@
                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
                   "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
-                  : "%eax", "%ecx", "%edx", "memory", "cc");
+                  : "%eax", "%edx", "memory", "cc");
     return res;
 }
 
@@ -175,13 +175,14 @@
                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
                   "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
-                  : "%eax", "%ecx", "%edx", "memory", "cc");
+                  : "%eax", "%edx", "memory", "cc");
     return res;
 }
 #endif
 
-static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
+static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE val)
 {
+    RES_TYPE v = val;
     asm volatile ("movl %0, %%edx\n"
                   "movl %0, %%eax\n"
                   "shrl %3, %%edx\n"
@@ -218,16 +219,14 @@
                   "2:\n"
                   :
                   : "r" (ptr),
-/* NOTE: 'q' would be needed as constraint, but we could not use it
-   with T1 ! */
-                  "r" (v),
+                  "q" (v),
                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
                   "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
-                  : "%eax", "%ecx", "%edx", "memory", "cc");
+                  : "%eax", "%edx", "memory", "cc");
 }
 
 #else
Index: target-ppc/exec.h
===================================================================
--- target-ppc/exec.h        (previous revision)
+++ target-ppc/exec.h        (working copy)
@@ -37,11 +37,7 @@
 #define FT1 (env->ft1)
 #define FT2 (env->ft2)
 
-#if defined (DEBUG_OP)
-#define RETURN() __asm__ __volatile__("nop");
-#else
-#define RETURN() __asm__ __volatile__("");
-#endif
+#define RETURN() FORCE_RET()
 
 #include "cpu.h"
 #include "exec-all.h"
Index: cpu-exec.c
===================================================================
--- cpu-exec.c        (previous revision)
+++ cpu-exec.c        (working copy)
@@ -668,6 +668,15 @@
                               : /* no outputs */
                               : "r" (gen_func)
                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
+#elif defined(TARGET_X86_64) && defined(__i386__)
+                asm volatile ("push %%ebx\n"
+                              "push %%esi\n"
+                              "push %%edi\n"
+                              "call *%0\n"
+                              "pop %%edi\n"
+                              "pop %%esi\n"
+                              "pop %%ebx\n"
+                              : : "r" (gen_func) : "ebx", "esi", "edi");
 #elif defined(__ia64)
                 struct fptr {
                         void *ip;
Index: dyngen.c
===================================================================
--- dyngen.c        (previous revision)
+++ dyngen.c        (working copy)
@@ -32,6 +32,8 @@
 
 #include "config-host.h"
 
+//#define DEBUG_OP
+
 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
    compilation */
 #if defined(CONFIG_WIN32)
@@ -1429,6 +1431,677 @@
 #endif
 
 
+#if defined(HOST_I386) || defined(HOST_X86_64)
+
+/* This byte is the first byte of an instruction.  */
+#define FLAG_INSN     (1 << 0)
+/* This byte has been processed as part of an instruction.  */
+#define FLAG_SCANNED  (1 << 1)
+/* This instruction is a return instruction.  Gcc cometimes generates prefix
+   bytes, so may be more than one byte long.  */
+#define FLAG_RET      (1 << 2)
+/* This is either the target of a jump, or the preceeding instruction uses
+   a pc-relative offset.  */
+#define FLAG_TARGET   (1 << 3)
+/* This is a magic instruction that needs fixing up.  */
+#define FLAG_EXIT     (1 << 4)
+/* This instruction clobbers the stack pointer.  */
+/* XXX only supports push, pop, add/sub $imm,%esp  */
+#define FLAG_STACK    (1 << 5)
+#define MAX_EXITS     5
+
+static void
+bad_opcode(const char *name, uint32_t op)
+{
+    error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
+}
+
+/* Mark len bytes as scanned,  Returns insn_size + len.  Reports an error
+   if these bytes have already been scanned.  */
+static int
+eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
+{
+    while (len > 0) {
+        /* This should never occur in sane code.  */
+        if (flags[insn + insn_size] & FLAG_SCANNED)
+            error ("Overlapping instructions in %s", name);
+        flags[insn + insn_size] |= FLAG_SCANNED;
+        insn_size++;
+        len--;
+    }
+    return insn_size;
+}
+
+static void
+trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
+                 int len)
+{
+    uint8_t *ptr;
+    uint8_t op;
+    int modrm;
+    int is_prefix;
+    int op_size;
+    int addr_size;
+    int insn_size;
+    int is_ret;
+    int is_condjmp;
+    int is_jmp;
+    int is_exit;
+    int is_pcrel;
+    int is_stack;
+    int immed;
+    int seen_rexw;
+    int32_t disp;
+
+    ptr = start_p + insn;
+    /* nonzero if this insn has a ModR/M byte.  */
+    modrm = 1;
+    /* The size of the immediate value in this instruction.  */
+    immed = 0;
+    /* The operand size.  */
+    op_size = 4;
+    /* The address size */
+    addr_size = 4;
+    /* The total length of this instruction.  */
+    insn_size = 0;
+    is_prefix = 1;
+    is_ret = 0;
+    is_condjmp = 0;
+    is_jmp = 0;
+    is_exit = 0;
+    seen_rexw = 0;
+    is_pcrel = 0;
+    is_stack = 0;
+
+    while (is_prefix) {
+        op = ptr[insn_size];
+        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
+        is_prefix = 0;
+        switch (op >> 4) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+            if (op == 0x0f) {
+                /* two-byte opcode.  */
+                op = ptr[insn_size];
+                insn_size = eat_bytes(name, flags, insn, insn_size, 1);
+                switch (op >> 4) {
+                case 0:
+                    if ((op & 0xf) > 3)
+                      modrm = 0;
+                    break;
+                case 1: /* vector move or prefetch */
+                case 2: /* various moves and vector compares.  */
+                case 4: /* cmov */
+                case 5: /* vector instructions */
+                case 6:
+                case 13:
+                case 14:
+                case 15:
+                    break;
+                case 7: /* mmx */
+                    if (op & 0x77) /* emms */
+                      modrm = 0;
+                    break;
+                case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
+                    modrm = 0;
+                    break;
+                case 8: /* long conditional jump */
+                    is_condjmp = 1;
+                    immed = op_size;
+                    modrm = 0;
+                    break;
+                case 9: /* setcc */
+                    break;
+                case 10:
+                    switch (op & 0x7) {
+                    case 0: /* push fs/gs */
+                    case 1: /* pop fs/gs */
+                        is_stack = 1;
+                    case 2: /* cpuid/rsm */
+                        modrm = 0;
+                        break;
+                    case 4: /* shld/shrd immediate */
+                        immed = 1;
+                        break;
+                    default: /* Normal instructions with a ModR/M byte.  */
+                        break;
+                    }
+                    break;
+                case 11:
+                    switch (op & 0xf) {
+                    case 10: /* bt, bts, btr, btc */
+                        immed = 1;
+                        break;
+                    default:
+                        /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
+                           undefined, and movsx */
+                        break;
+                    }
+                    break;
+                case 12:
+                    if (op & 8) {
+                        /* bswap */
+                        modrm = 0;
+                    } else {
+                        switch (op & 0x7) {
+                        case 2:
+                        case 4:
+                        case 5:
+                        case 6:
+                            immed = 1;
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+                    break;
+                }
+            } else if ((op & 0x07) <= 0x3) {
+                /* General arithmentic ax.  */
+            } else if ((op & 0x07) <= 0x5) {
+                /* General arithmetic ax, immediate.  */
+                if (op & 0x01)
+                    immed = op_size;
+                else
+                    immed = 1;
+                modrm = 0;
+            } else if ((op & 0x23) == 0x22) {
+                /* Segment prefix.  */
+                is_prefix = 1;
+            } else {
+                /* Segment register push/pop or DAA/AAA/DAS/AAS.  */
+                modrm = 0;
+            }
+            break;
+
+#if defined(HOST_X86_64)
+        case 4: /* rex prefix.  */
+            is_prefix = 1;
+            /* The address/operand size is actually 64-bit, but the immediate
+               values in the instruction are still 32-bit.  */
+            op_size = 4;
+            addr_size = 4;
+            if (op & 8)
+                seen_rexw = 1;
+            break;
+#else
+        case 4: /* inc/dec register.  */
+#endif
+        case 5: /* push/pop general register.  */
+            modrm = 0;
+            is_stack = 1;
+            break;
+
+        case 6:
+            switch (op & 0x0f) {
+            case 0: /* pusha */
+            case 1: /* popa */
+                modrm = 0;
+                is_stack = 1;
+                break;
+            case 2: /* bound */
+            case 3: /* arpl */
+                break;
+            case 4: /* FS */
+            case 5: /* GS */
+                is_prefix = 1;
+                break;
+            case 6: /* opcode size prefix.  */
+                op_size = 2;
+                is_prefix = 1;
+                break;
+            case 7: /* Address size prefix.  */
+                addr_size = 2;
+                is_prefix = 1;
+                break;
+            case 8: /* push immediate */
+                immed = op_size;
+                modrm = 0;
+                is_stack = 1;
+                break;
+            case 10: /* push 8-bit immediate */
+                immed = 1;
+                modrm = 0;
+                is_stack = 1;
+                break;
+            case 9: /* imul immediate */
+                immed = op_size;
+                break;
+            case 11: /* imul 8-bit immediate */
+                immed = 1;
+                break;
+            case 12: /* insb */
+            case 13: /* insw */
+            case 14: /* outsb */
+            case 15: /* outsw */
+                modrm = 0;
+                break;
+            }
+            break;
+
+        case 7: /* Short conditional jump.  */
+            is_condjmp = 1;
+            immed = 1;
+            modrm = 0;
+            break;
+          
+        case 8:
+            if ((op & 0xf) <= 3) {
+                /* arithmetic immediate.  */
+                if ((op & 3) == 1)
+                    immed = op_size;
+                else
+                    immed = 1;
+                if (op == 0x81 || op == 0x83) {
+                    /* add, sub */
+                    op = ptr[insn_size];
+                    switch ((op >> 3) & 7) {
+                    case 0:
+                    case 5:
+                        is_stack = (op & 7) == 4;
+                        break;
+                    }
+                }
+            }
+            else if ((op & 0xf) == 0xf) {
+                /* pop general.  */
+                is_stack = 1;
+            }
+            /* else test, xchg, mov, lea.  */
+            break;
+
+        case 9:
+            /* Various single-byte opcodes with no modrm byte.  */
+            modrm = 0;
+            if (op == 10) {
+                /* Call */
+                immed = 4;
+            }
+            break;
+
+        case 10:
+            switch ((op & 0xe) >> 1) {
+            case 0: /* mov absoliute immediate.  */
+            case 1:
+                if (seen_rexw)
+                    immed = 8;
+                else
+                    immed = addr_size;
+                break;
+            case 4: /* test immediate.  */
+                if (op & 1)
+                    immed = op_size;
+                else
+                    immed = 1;
+                break;
+            default: /* Various string ops.  */
+                break;
+            }
+            modrm = 0;
+            break;
+
+        case 11: /* move immediate to register */
+            if (op & 8) {
+                if (seen_rexw)
+                    immed = 8;
+                else
+                    immed = op_size;
+            } else {
+                immed = 1;
+            }
+            modrm = 0;
+            break;
+
+          case 12:
+            switch (op & 0xf) {
+            case 0: /* shift immediate */
+            case 1:
+                immed = 1;
+                break;
+            case 2: /* ret immediate */
+                immed = 2;
+                modrm = 0;
+                bad_opcode(name, op);
+                break;
+            case 3: /* ret */
+                modrm = 0;
+                is_ret = 1;
+            case 4: /* les */
+            case 5: /* lds */
+                break;
+            case 6: /* mov immediate byte */
+                immed = 1;
+                break;
+            case 7: /* mov immediate */
+                immed = op_size;
+                break;
+            case 8: /* enter */
+                /* TODO: Is this right?  */
+                immed = 3;
+                modrm = 0;
+                break;
+            case 10: /* retf immediate */
+                immed = 2;
+                modrm = 0;
+                bad_opcode(name, op);
+                break;
+            case 13: /* int */
+                immed = 1;
+                modrm = 0;
+                break;
+            case 11: /* retf */
+            case 15: /* iret */
+                modrm = 0;
+                bad_opcode(name, op);
+                break;
+            default: /* leave, int3 or into */
+                modrm = 0;
+                break;
+            }
+            break;
+
+        case 13:
+            if ((op & 0xf) >= 8) {
+                /* Coprocessor escape.  For our purposes this is just a normal
+                   instruction with a ModR/M byte.  */
+            } else if ((op & 0xf) >= 4) {
+                /* AAM, AAD or XLAT */
+                modrm = 0;
+            }
+            /* else shift instruction */
+            break;
+
+        case 14:
+            switch ((op & 0xc) >> 2) {
+            case 0: /* loop or jcxz */
+                is_condjmp = 1;
+                immed = 1;
+                break;
+            case 1: /* in/out immed */
+                immed = 1;
+                break;
+            case 2: /* call or jmp */
+                switch (op & 3) {
+                case 0: /* call */
+                    immed = op_size;
+                    break;
+                case 1: /* long jump */
+                    immed = 4;
+                    is_jmp = 1;
+                    break;
+                case 2: /* far jmp */
+                    bad_opcode(name, op);
+                    break;
+                case 3: /* short jmp */
+                    immed = 1;
+                    is_jmp = 1;
+                    break;
+                }
+                break;
+            case 3: /* in/out register */
+                break;
+            }
+            modrm = 0;
+            break;
+
+        case 15:
+            switch ((op & 0xe) >> 1) {
+            case 0:
+            case 1:
+                is_prefix = 1;
+                break;
+            case 2:
+            case 4:
+            case 5:
+            case 6:
+                modrm = 0;
+                /* Some privileged insns are used as markers.  */
+                switch (op) {
+                case 0xf4: /* hlt: Exit translation block.  */
+                    is_exit = 1;
+                    break;
+                case 0xfa: /* cli: Jump to label.  */
+                    is_exit = 1;
+                    immed = 4;
+                    break;
+                case 0xfb: /* sti: TB patch jump.  */
+                    /* Mark the insn for patching, but continue sscanning.  */
+                    flags[insn] |= FLAG_EXIT;
+                    immed = 4;
+                    break;
+                }
+                break;
+            case 3: /* unary grp3 */
+                if ((ptr[insn_size] & 0x38) == 0) {
+                    if (op == 0xf7)
+                        immed = op_size;
+                    else
+                        immed = 1; /* test immediate */
+                }
+                break;
+            case 7: /* inc/dec grp4/5 */
+                /* TODO: This includes indirect jumps.  We should fail if we
+                   encounter one of these. */
+                break;
+            }
+            break;
+        }
+    }
+
+    if (modrm) {
+        if (addr_size != 4)
+            error("16-bit addressing mode used in %s", name);
+
+        disp = 0;
+        modrm = ptr[insn_size];
+        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
+        modrm &= 0xc7;
+        switch ((modrm & 0xc0) >> 6) {
+        case 0:
+            if (modrm == 5)
+              disp = 4;
+            break;
+        case 1:
+            disp = 1;
+            break;
+        case 2:
+            disp = 4;
+            break;
+        }
+        if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
+            /* SIB byte */
+            if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
+                disp = 4;
+                is_pcrel = 1;
+            }
+            insn_size = eat_bytes(name, flags, insn, insn_size, 1);
+        }
+        insn_size = eat_bytes(name, flags, insn, insn_size, disp);
+    }
+    insn_size = eat_bytes(name, flags, insn, insn_size, immed);
+    if (is_condjmp || is_jmp) {
+        if (immed == 1) {
+            disp = (int8_t)*(ptr + insn_size - 1);
+        } else {
+            disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
+                   | (((int32_t)*(ptr + insn_size - 2)) << 16)
+                   | (((int32_t)*(ptr + insn_size - 3)) << 8)
+                   | *(ptr + insn_size - 4);
+        }
+        disp += insn_size;
+        /* Jumps to external symbols point to the address of the offset
+           before relocation.  */
+        /* ??? These are probably a tailcall.  We could fix them up by
+           replacing them with jmp to EOB + call, but it's easier to just
+           prevent the compiler generating them.  */
+        if (disp == 1)
+            error("Unconditional jump (sibcall?) in %s", name);
+        disp += insn;
+        if (disp < 0 || disp > len)
+            error("Jump outside instruction in %s", name);
+
+        if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
+            error("Overlapping instructions in %s", name);
+
+        flags[disp] |= (FLAG_INSN | FLAG_TARGET);
+        is_pcrel = 1;
+    }
+    if (is_pcrel) {
+        /* Mark the following insn as a jump target.  This will stop
+           this instruction being moved.  */
+        flags[insn + insn_size] |= FLAG_TARGET;
+    }
+    if (is_ret)
+      flags[insn] |= FLAG_RET;
+
+    if (is_exit)
+      flags[insn] |= FLAG_EXIT;
+
+    if (is_stack)
+      flags[insn] |= FLAG_STACK;
+
+    if (!(is_jmp || is_ret || is_exit))
+      flags[insn + insn_size] |= FLAG_INSN;
+}
+
+/* Scan a function body.  Returns the position of the return sequence.
+   Sets *patch_bytes to the number of bytes that need to be copied from that
+   location.  If no patching is required (ie. the return is the last insn)
+   *patch_bytes will be set to -1.  *plen is the number of code bytes to copy.
+ */
+static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
+                         int *patch_bytes, int *exit_addrs)
+{
+    char *flags;
+    int more;
+    int insn;
+    int retpos;
+    int bytes;
+    int num_exits;
+    int len;
+    int last_insn;
+    int stack_clobbered;
+
+    len = *plen;
+    flags = malloc(len + 1);
+    memset(flags, 0, len + 1);
+    flags[0] |= FLAG_INSN;
+    more = 1;
+    while (more) {
+        more = 0;
+        for (insn = 0; insn < len; insn++) {
+            if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
+                trace_i386_insn(name, start_p, flags, insn, len);
+                more = 1;
+            }
+        }
+    }
+
+    /* Strip any unused code at the end of the function.  */
+    while (len > 0 && flags[len - 1] == 0)
+      len--;
+
+    retpos = -1;
+    num_exits = 0;
+    last_insn = 0;
+    stack_clobbered = 0;
+    for (insn = 0; insn < len; insn++) {
+        if (flags[insn] & FLAG_RET) {
+            /* ??? In theory it should be possible to handle multiple return
+               points.  In practice it's not worth the effort.  */
+            if (retpos != -1)
+                error("Multiple return instructions in %s", name);
+            retpos = insn;
+        }
+        if (flags[insn] & FLAG_EXIT) {
+            if (0 && stack_clobbered)
+                error("Stack clobbered in %s", name);
+            if (num_exits == MAX_EXITS)
+                error("Too many block exits in %s", name);
+            exit_addrs[num_exits] = insn;
+            num_exits++;
+        }
+        if (flags[insn] & FLAG_INSN)
+            last_insn = insn;
+        if (flags[insn] & FLAG_STACK)
+            stack_clobbered = 1;
+    }
+
+    exit_addrs[num_exits] = -1;
+    if (retpos == -1) {
+        if (num_exits == 0) {
+            error ("No return instruction found in %s", name);
+        } else {
+            retpos = len;
+            last_insn = len;
+        }
+    }
+    
+    /* If the return instruction is the last instruction we can just
+       remove it.  */
+    if (retpos == last_insn)
+        *patch_bytes = -1;
+    else
+        *patch_bytes = 0;
+
+    /* Back up over any nop instructions.  */
+    while (retpos > 0
+           && (flags[retpos] & FLAG_TARGET) == 0
+           && (flags[retpos - 1] & FLAG_INSN) != 0
+           && start_p[retpos - 1] == 0x90) {
+        retpos--;
+    }
+
+    if (*patch_bytes == -1) {
+        *plen = retpos;
+        free (flags);
+        return retpos;
+    }
+    *plen = len;
+
+    /* The ret is in the middle of the function.  Find four more bytes that
+       so the ret can be replaced by a jmp. */
+    /* ??? Use a short jump where possible. */
+    bytes = 4;
+    insn = retpos + 1;
+    /* We can clobber everything up to the next jump target.  */
+    while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
+        insn++;
+        bytes--;
+    }
+    if (bytes > 0) {
+        /* ???: Strip out nop blocks.  */
+        /* We can't do the replacement without clobbering anything important.
+           Copy preceeding instructions(s) to give us some space.  */
+        while (retpos > 0) {
+            /* If this byte is the target of a jmp we can't move it.  */
+            if (flags[retpos] & FLAG_TARGET)
+                break;
+
+            (*patch_bytes)++;
+            bytes--;
+            retpos--;
+
+            /* Break out of the loop if we have enough space and this is either
+               the first byte of an instruction or a pad byte.  */
+            if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
+                && bytes <= 0) {
+                break;
+            }
+        }
+    }
+
+    if (bytes > 0)
+        error("Unable to replace ret with jmp in %s\n", name);
+
+    free(flags);
+    return retpos;
+}
+
+#endif
+
 #define MAX_ARGS 3
 
 /* generate op code */
@@ -1442,6 +2115,11 @@
     uint8_t args_present[MAX_ARGS];
     const char *sym_name, *p;
     EXE_RELOC *rel;
+#if defined(HOST_I386) || defined(HOST_X86_64)
+    int patch_bytes;
+    int retpos;
+    int exit_addrs[MAX_EXITS];
+#endif
 
     /* Compute exact size excluding prologue and epilogue instructions.
      * Increment start_offset to skip epilogue instructions, then compute
@@ -1452,33 +2130,12 @@
     p_end = p_start + size;
     start_offset = offset;
 #if defined(HOST_I386) || defined(HOST_X86_64)
-#ifdef CONFIG_FORMAT_COFF
     {
-        uint8_t *p;
-        p = p_end - 1;
-        if (p == p_start)
-            error("empty code for %s", name);
-        while (*p != 0xc3) {
-            p--;
-            if (p <= p_start)
-                error("ret or jmp expected at the end of %s", name);
-        }
-        copy_size = p - p_start;
-    }
-#else
-    {
         int len;
         len = p_end - p_start;
-        if (len == 0)
-            error("empty code for %s", name);
-        if (p_end[-1] == 0xc3) {
-            len--;
-        } else {
-            error("ret or jmp expected at the end of %s", name);
-        }
+        retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
         copy_size = len;
     }
-#endif
 #elif defined(HOST_PPC)
     {
         uint8_t *p;
@@ -1710,6 +2367,13 @@
     }
 
     if (gen_switch == 2) {
+#if defined(HOST_I386) || defined(HOST_X86_64)
+        if (patch_bytes != -1)
+            copy_size += patch_bytes;
+#ifdef DEBUG_OP
+        copy_size += 2;
+#endif
+#endif
         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
     } else if (gen_switch == 1) {
 
@@ -1915,7 +2579,43 @@
 #error unsupport object format
 #endif
                 }
+               }
+                /* Replace the marker instructions with the actual opcodes.  */
+                for (i = 0; exit_addrs[i] != -1; i++) {
+                    int op;
+                    switch (p_start[exit_addrs[i]])
+                      {
+                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
+                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
+                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
+                      default: error("Internal error");
+                      }
+                    fprintf(outfile,
+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
+                            exit_addrs[i], op);
                 }
+                /* Fix up the return instruction.  */
+                if (patch_bytes != -1) {
+                    if (patch_bytes) {
+                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
+                                "gen_code_ptr + %d, %d);\n",
+                                copy_size, retpos, patch_bytes);
+                    }
+                    fprintf(outfile,
+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
+                            retpos);
+                    fprintf(outfile,
+                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
+                            retpos + 1, copy_size - (retpos + 5));
+                    
+                    copy_size += patch_bytes;
+                }
+#ifdef DEBUG_OP
+                fprintf(outfile,
+                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
+                        copy_size);
+                copy_size += 2;
+#endif
             }
 #elif defined(HOST_X86_64)
             {
@@ -1949,6 +2649,42 @@
                     }
                 }
                 }
+                /* Replace the marker instructions with the actual opcodes.  */
+                for (i = 0; exit_addrs[i] != -1; i++) {
+                    int op;
+                    switch (p_start[exit_addrs[i]])
+                      {
+                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
+                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
+                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
+                      default: error("Internal error");
+                      }
+                    fprintf(outfile,
+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
+                            exit_addrs[i], op);
+                }
+                /* Fix up the return instruction.  */
+                if (patch_bytes != -1) {
+                    if (patch_bytes) {
+                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
+                                "gen_code_ptr + %d, %d);\n",
+                                copy_size, retpos, patch_bytes);
+                    }
+                    fprintf(outfile,
+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
+                            retpos);
+                    fprintf(outfile,
+                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
+                            retpos + 1, copy_size - (retpos + 5));
+                    
+                    copy_size += patch_bytes;
+                }
+#ifdef DEBUG_OP
+                fprintf(outfile,
+                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
+                        copy_size);
+                copy_size += 2;
+#endif
             }
 #elif defined(HOST_PPC)
             {
Index: exec-all.h
===================================================================
--- exec-all.h        (previous revision)
+++ exec-all.h        (working copy)
@@ -317,14 +317,15 @@
 
 #elif defined(__i386__) && defined(USE_DIRECT_JUMP)
 
-/* we patch the jump instruction directly */
+/* we patch the jump instruction directly.  Use sti in place of the actual
+   jmp instruction so that dyngen can patch in the correct result.  */
 #define GOTO_TB(opname, tbparam, n)\
 do {\
     asm volatile (".section .data\n"\
                   ASM_OP_LABEL_NAME(n, opname) ":\n"\
                   ".long 1f\n"\
                   ASM_PREVIOUS_SECTION \
-                  "jmp " ASM_NAME(__op_jmp) #n "\n"\
+                  "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
                   "1:\n");\
 } while (0)
 
Index: target-i386/helper.c
===================================================================
--- target-i386/helper.c        (previous revision)
+++ target-i386/helper.c        (working copy)
@@ -3667,8 +3667,15 @@
         nb_xmm_regs = 8 << data64;
         addr = ptr + 0xa0;
         for(i = 0; i < nb_xmm_regs; i++) {
+#if defined(__i386__) && __GNUC__ >= 4
+            env->xmm_regs[i].XMM_L(0) = ldl(addr);
+            env->xmm_regs[i].XMM_L(1) = ldl(addr + 4);
+            env->xmm_regs[i].XMM_L(2) = ldl(addr + 8);
+            env->xmm_regs[i].XMM_L(3) = ldl(addr + 12);
+#else
             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
+#endif
             addr += 16;
         }
     }
Index: target-i386/ops_sse.h
===================================================================
--- target-i386/ops_sse.h        (previous revision)
+++ target-i386/ops_sse.h        (working copy)
@@ -34,6 +34,12 @@
 #define Q(n) XMM_Q(n)
 #define SUFFIX _xmm
 #endif
+#if defined(__i386__) && __GNUC__ >= 4
+#define RegCopy(d, s) __builtin_memcpy(&(d), &(s), sizeof(d))
+#endif
+#ifndef RegCopy
+#define RegCopy(d, s) d = s
+#endif
 
 void OPPROTO glue(op_psrlw, SUFFIX)(void)
 {
@@ -592,7 +598,7 @@
     r.W(1) = s->W((order >> 2) & 3);
     r.W(2) = s->W((order >> 4) & 3);
     r.W(3) = s->W((order >> 6) & 3);
-    *d = r;
+    RegCopy(*d, r);
 }
 #else
 void OPPROTO op_shufps(void)
Index: target-i386/translate.c
===================================================================
--- target-i386/translate.c        (previous revision)
+++ target-i386/translate.c        (working copy)
@@ -1177,7 +1177,15 @@
     gen_ ## op(s, ot);                                                        \
     gen_op_dec_ECX[s->aflag]();                                               \
     gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
-    gen_op_string_jnz_sub[nz][ot](l2);\
+    if (s->jmp_opt)                                                              \
+        gen_op_string_jnz_sub[nz][ot](l2);                                      \
+    else {                                                                      \
+        gen_op_setz_T0_cc();                                                      \
+        if (nz)                                                                      \
+            gen_op_jnz_T0_label(l2);                                              \
+        else                                                                      \
+            gen_op_jz_T0_label(l2);                                              \
+    }                                                                              \
     if (!s->jmp_opt)                                                          \
         gen_op_jz_ecx[s->aflag](l2);                                          \
     gen_jmp(s, cur_eip);                                                      \
@@ -1277,6 +1285,7 @@
     gen_op_setle_T0_cc,
 };
 
+#ifndef TAINT_ENABLED
 static GenOpFunc *gen_setcc_sub[4][8] = {
     [OT_BYTE] = {
         NULL,
@@ -1322,6 +1331,9 @@
 #endif
 };
 
+#endif //TAINT_ENABLED
+
+
 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
     gen_op_fadd_ST0_FT0,
     gen_op_fmul_ST0_FT0,
@@ -2002,6 +2014,7 @@
     inv = b & 1;
     jcc_op = (b >> 1) & 7;
     switch(s->cc_op) {
+#ifndef TAINT_ENABLED
         /* we optimize the cmp/jcc case */
     case CC_OP_SUBB:
     case CC_OP_SUBW:
@@ -2048,8 +2061,11 @@
             goto slow_jcc;
         }
         break;
+#endif //TAINT_ENABLED
     default:
+#ifndef TAINT_ENABLED
     slow_jcc:
+#endif //TAINT_ENABLED
         if (s->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s->cc_op);
         func = gen_setcc_slow[jcc_op];
Index: cpu-all.h
===================================================================
--- cpu-all.h        (previous revision)
+++ cpu-all.h        (working copy)
@@ -369,7 +369,13 @@
 
 static inline void stq_le_p(void *ptr, uint64_t v)
 {
+#if defined(__i386__) && __GNUC__ >= 4
+    const union { uint64_t v; uint32_t p[2]; } x = { .v = v };
+    ((uint32_t *)ptr)[0] = x.p[0];
+    ((uint32_t *)ptr)[1] = x.p[1];
+#else
     *(uint64_t *)ptr = v;
+#endif
 }
 
 /* float access */


--- src/makedefs.orig        2013-03-22 14:06:55.975047520 -0500
+++ src/makedefs        2013-03-22 14:07:07.419247218 -0500
@@ -33,6 +33,8 @@
                   ;;
       Linux.2*)   DEFS="-DLINUX2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
                   ;;
+      Linux.3*)   DEFS="-DLINUX2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
+                  ;;
     Darwin.5.*)   CC=cc DEFS="-DDARWIN"
                   ;;
 Darwin.[6-8].*)   DEFS="-DDARWIN"
--- src/imgtools/img_tools.h.orig        2013-03-22 14:14:21.018764240 -0500
+++ src/imgtools/img_tools.h        2013-03-22 14:14:28.718896984 -0500
@@ -13,7 +13,6 @@
 extern "C" {
 #endif
 
-#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>

Stephen McCamant

unread,
Mar 27, 2013, 10:52:56 AM3/27/13
to bitblaz...@googlegroups.com
>>>>> "FL" == Frank Loyd <frank...@gmail.com> writes:

FL> Hello, thanks for your instructions, but i have got
FL> error("make[1]: no rule to make target install; make *** [install]
FL> error 2 "). i use patch temu-release2009-gcc4.patch, and it
FL> happens at once than i do "make install" after patching

This "error" can be safely ignored: it just results because there's no
"install" target in the Tracecap Makefile. Note it's our suggestion to
just run TEMU from the build directory in any case.

If the presence of the error still bothers you, you can make it go
away by adding an empty "install" target to the Makefile, as in the
appended patch.

Hope this helps,

-- Stephen

--- tracecap/Makefile.orig 2013-03-27 09:34:51.810366503 -0500
+++ tracecap/Makefile 2013-03-27 09:35:30.863017131 -0500
@@ -65,6 +65,9 @@
clean:
rm -f *.o *.so *.a *~ $(PLUGIN) ../shared/*.o ../shared/hooks/*.o *.d ../*.d ../shared/*d ../shared/*/*.d ini/main.ini

+install:
+ @# Unsupported, nothing to do. Just run from this directory.
+
# Include automatically generated dependency files
-include $(wildcard *.d ../*.d ../shared/*d ../shared/*/*.d)

Frank Loyd

unread,
Apr 1, 2013, 3:00:25 AM4/1/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
i understood:) but thanks, i have another problem, i can't find sleuthkit-2.04.patch and sleuthkit-linux3.patch

Frank Loyd

unread,
Apr 2, 2013, 8:47:57 AM4/2/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
i have found sleuthkit-2.04.patch, where is sleuthkit-linux3.patch, and what about fedora 17, why do you use ubuntu?)

David Urbina

unread,
Apr 2, 2013, 4:52:12 PM4/2/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
Hi Frank,

Stephen already copied sleuthkit-linux3.patch in his walk-through, but i copy it here again for your convenience:

=================================================================

--- src/makedefs.orig        2013-03-22 14:06:55.975047520 -0500
+++ src/makedefs        2013-03-22 14:07:07.419247218 -0500
@@ -33,6 +33,8 @@
                   ;;
       Linux.2*)   DEFS="-DLINUX2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
                   ;;
+      Linux.3*)   DEFS="-DLINUX2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
+                  ;;
     Darwin.5.*)   CC=cc DEFS="-DDARWIN"
                   ;;
 Darwin.[6-8].*)   DEFS="-DDARWIN"

--- src/imgtools/img_tools.h.orig        2013-03-22 14:14:21.018764240 -0500
+++ src/imgtools/img_tools.h        2013-03-22 14:14:28.718896984 -0500
@@ -13,7 +13,6 @@
 extern "C" {
 #endif
 
-#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
===================================================================

Copy the segment to a new file named "sleuthkit-linux3.patch" and run it as Stephen mentioned. if you get into trouble try modifying the files ("src/makedefs" and "src/imgtools/img_tools.h") by hand as the segment suggests.

Hope this helps.

Best,

Stephen McCamant

unread,
Apr 3, 2013, 11:25:30 AM4/3/13
to bitblaz...@googlegroups.com
>>>>> "FL" == Frank Loyd <frank...@gmail.com> writes:

FL> i have found sleuthkit-2.04.patch, where is
FL> sleuthkit-linux3.patch, and what about fedora 17, why do you use
FL> ubuntu?)

I hope David's answer covered your question about
sleuthkit-linux3.patch.

As for the choice of Linux distributions, it isn't our intent to make
BitBlaze specific to any particular one: plenty of people have used
the tools successfully on a variety of distributions. But for the
purpose of giving instructions, it helps to use one specific
distribution so that we can isolate problems related to system
dependencies from other problems. Most of the changes needed to get
TEMU working with Ubuntu 12.04 are related to updates to generic
software like the kernel, GCC, and glibc, so most of the changes would
be the same for another more modern distribution such as Fedora
17. But if you run into more build or execution failures while running
under Fedora we'd be interested in hearing about them and potentially
suggesting fixes.

The reasons we've happened to use Ubuntu are just historical. At
Berkeley, each of us grad students and postdocs generally installed
our own Linux machines, so for instance I used Debian, and at least
one other grad student used Fedora. But Ubuntu was most popular
overall among the students, it's what we used for the shared compute
servers, and it's also popular in the wild, so it seemed like a
natural choice for the supported distribution for TEMU and Vine 1.0.
By contrast here a Minnesota the department has standardized on
Ubuntu, most recently 12.04, for all the department-administered
machines, so it's what I got on my desktop without any explicit
choice.

David Urbina

unread,
Apr 3, 2013, 2:28:13 PM4/3/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
Hi Stephen,

I followed your walk-through successfully. Now I am trying to take some traces in Windows XP following this steps:

=========================================================
0) Start TEMU and put the program in whatever state you want to start tracing from 
1) Load the tracecap plugin: 
(temu) load_plugin "<path_to_tracecap.so>"
2) List the processes running in the guest as you will need the PID for tracing
(temu) guest_ps
3) Load the hooks for memory allocations (note the arguments are two empty strings)
(temu) load_hooks "" ""
4) Enable emulation (here is when things get slow)
(temu) enable_emulation
5) Start the trace
(temu) trace <pid> "<output_path_for_trace>"
6) Stop the trace
(temu) trace_stop
7) Disable emulation
(temu) disable_emulation
8) Unload plugin (kind of like a reset button, you can skip 6 if you do 7 as this step will disable emulation)
================================================================

Step 3) complains that group_alloc.so cannot be found. I changed my directoty to "/shared/hooks/hook_plugins" and tried running make but it was unsuccessful because could not find "module.h".

I added -I$(SRC_PATH)/shared/llconf/install/include to the CFLAGS, what apparently "fixed" the previous error but now i am getting:

gcc -I../../../ -I../../ -I.. -I../../../i386-softmmu -I/home/david/Downloads/temu-1.0/shared/llconf/install/include -g -Wall -fPIC -O2 -D_GNU_SOURCE -c -o sample_hook.o sample_hook.c
In file included from hook_plugin.h:27:0,
                 from plugin.h:22,
                 from sample_hook.c:10:
../reg_ids.h: In function ‘reg_name_from_id’:
../reg_ids.h:82:21: error: ‘NULL’ undeclared (first use in this function)
../reg_ids.h:82:21: note: each undeclared identifier is reported only once for each function it appears in
In file included from ../../../TEMU_main.h:36:0,
                 from ../../../TEMU_lib.h:19,
                 from ../../../tracecap/tracecap.h:20,
                 from ../../../tracecap/my_stub_def.h:15,
                 from sample_hook.c:16:
../../../taintcheck.h: At top level:
../../../taintcheck.h:145:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:146:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:149:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:150:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:152:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:153:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:154:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:155:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:156:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:157:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:158:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:159:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:160:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:194:1: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:211:2: warning: ‘fastcall’ attribute ignored [-Wattributes]
../../../taintcheck.h:214:2: warning: ‘fastcall’ attribute ignored [-Wattributes]
sample_hook.c: In function ‘getsockname_ret’:
sample_hook.c:164:3: warning: implicit declaration of function ‘free’ [-Wimplicit-function-declaration]
sample_hook.c:164:10: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default]
make: *** [sample_hook.o] Error 1


And here... I am pretty well stuck... I would appreciate any insights.

FYI, I did run successfully Temu in ubuntu 10.04, but I would like to give it a try in 12.04.

Thanks for you time.

Frank Loyd

unread,
Apr 4, 2013, 1:48:20 AM4/4/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
thanks, it work:)

Frank Loyd

unread,
Apr 4, 2013, 2:13:33 AM4/4/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
thanks for detail describe of installation. For a start, i'll use it on ubuntu, after that try install fedora and tell about result
Message has been deleted

Zhang Mike

unread,
May 5, 2013, 11:54:45 PM5/5/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
When I used your tutorial(patched gcc4 as you did) to install the temu to my ubuntu13 it output this error always, and I also tried to use -ldl command in the make file[BASE_LDFLAGS += -ldl]  before make command, but it seems that there's no effect, the error always here.
Can you give me any opinion to help to solve this problem?
I'll be appreciated your helps, thanks!

gcc  -ldl -g -export-dynamic -o qemu vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o block-raw-posix.o lsi53c895a.o usb-ohci.o eeprom93xx.o eepro100.o ne2000.o pcnet.o rtl8139.o ide.o pckbd.o ps2.o vga.o sb16.o es1370.o dma.o fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o usb-uhci.o vmmouse.o vmport.o vmware_vga.o gdbstub.o ../libqemu_common.a libqemu.a  -lm -lz -L/usr/lib/i386-linux-gnu -lSDL  -lrt -lpthread -lutil
../libqemu_common.a(scsi-generic.o): In function `memset':
/usr/include/i386-linux-gnu/bits/string3.h:81: warning: memset used with constant zero length parameter; this could be due to transposed parameters
/usr/bin/ld: libqemu.a(TEMU_main.o): undefined reference to symbol 'dlopen@@GLIBC_2.1'
/usr/bin/ld: note: 'dlopen@@GLIBC_2.1' is defined in DSO /usr/lib/i386-linux-gnu/libdl.so so try adding it to the linker command line
/usr/lib/i386-linux-gnu/libdl.so: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
make[1]: *** [qemu] Error 1
make[1]: Leaving directory `/home/ubuntu/Downloads/bitblaze/temu-1.0/i386-softmmu'
make: *** [subdir-i386-softmmu] Error 2

Zhang Mike

unread,
May 6, 2013, 1:12:13 AM5/6/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
ok, now I think I solved this problem.
add "VL_LIBS+=-ldl" after "VL_LIBS+=-lutil"Ln546 in file temu-1.0/MakeFile.target.

Hope this can also help others.

Stephen McCamant

unread,
May 6, 2013, 1:45:18 PM5/6/13
to bitblaz...@googlegroups.com
>>>>> "ZM" == Zhang Mike <telne...@gmail.com> writes:

ZM> ok, now I think I solved this problem.
ZM> *add "VL_LIBS+=-ldl" after "VL_LIBS+=-lutil"Ln546 in file
ZM> temu-1.0/MakeFile.target*.

I'm glad you managed to figure this out. Let me fill in a few more
details of what I think was going on, in case it's helpful for others
who are following along or coming back to this discussion later.

Specifically the Ubuntu version you're using here must be 13.04, since
13.10 isn't released yet. It's generally best to give the full version
number when describing your Ubuntu installation: because the major
version number is just the year, the two releases in a given year can
be quite different (e.g., 12.10 is just as different from 12.04 as it
is from 13.04).

You were correct in figuring out that the way to fix the error:

/usr/bin/ld: libqemu.a(TEMU_main.o): undefined reference to symbol 'dlopen@@GLIBC_2.1'
/usr/bin/ld: note: 'dlopen@@GLIBC_2.1' is defined in DSO /lib/i386-linux-gnu/libdl.so.2 so try adding it to the linker command line

was to add the option "-ldl" the "gcc" command line that was
preforming linking. TEMU needs this library to dynamically load
plugins. With older versions of the linker it was included
automatically because some other library used it (libSDL, I
think). But the new behavior of the linker requires it to be specified
explicitly (which is supposed to be less error-prone going
forward). The error message "/lib/i386-linux-gnu/libdl.so.2: could not
read symbols: Invalid operation" seems to be a red herring: there's
nothing wrong with that file.

The reason your first attempts at adding the library didn't work is
that the linker is sensitive to the order in which libraries are
specified on the command line. Whenever X uses a function from the
library Y, Y needs to be specified after X on the command line. This
is the reason why you normally see libraries at the end of the linker
command line, and why Makefiles usually have different variables for
LIBS and LDFLAGS: both are passed to the linker, but $(LDFLAGS) goes
early on the command line and $(LIBS) goes near the end. So when
adding new libraries they should go in LIBS (via VL_LIBS in your fix)
and not in LDFLAGS.

Zhang Mike

unread,
May 7, 2013, 5:08:36 AM5/7/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
I'm glad to hear your voice!
And after read your comments, it more clear now, thanks!

roddam bramhini

unread,
May 10, 2013, 2:41:07 AM5/10/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
hi everyone..
Is trace file be generated in 64 bit system using tracecap???

Joel Eriksson

unread,
May 19, 2013, 10:15:19 PM5/19/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
Hi David,

Simply change "return NULL" to "return (const char *) 0" at line 82 in temu-1.0/shared/hooks/reg_ids.h.

Cheers,
Joel Eriksson
ClevCode

taint_track

unread,
Jul 25, 2013, 1:12:13 AM7/25/13
to bitblaz...@googlegroups.com, mcca...@cs.umn.edu
I'm tracecap run error Cannot determine file system type

2013년 3월 23일 토요일 오전 5시 19분 34초 UTC+9, Stephen McCamant 님의 말:

Stephen McCamant

unread,
Aug 1, 2013, 2:01:52 PM8/1/13
to bitblaz...@googlegroups.com
>>>>> "TT" == taint track <taint_track> writes:

TT> I'm tracecap run error Cannot determine file system type

This message comes from Sleuthkit, which Tracecap uses to understand
file-system structures in support of the "taint_file" command. If you
just see it when starting up Tracecap, I think you can treat it as a
harmless warning. If it seems to be preventing the "taint_file"
command from working, the problem might be that you're trying to taint
a file on a file system that Sleuthkit isn't able to parse, so you
might try using a different (e.g., older) filesystem for that volume.

Valencia Clarissa

unread,
Nov 18, 2015, 12:04:39 PM11/18/15
to BitBlaze User Discussion group, mcca...@cs.umn.edu
Hi Stephen,

I successfully run al the steps in your walkthrough, but I encounter problem in the last step "make".

The message I got as follow:
make[1]: *** No rule to make target `Documents\bitblaze\temu1.0\vl.c', needed by vl.o. Stop.

Appreciate your help. Thanks!

Stephen McCamant

unread,
Nov 18, 2015, 1:18:22 PM11/18/15
to bitblaz...@googlegroups.com
>>>>> "VC" == Valencia Clarissa <vcwi...@gmail.com> writes:

VC> Hi Stephen,
VC> I successfully run al the steps in your walkthrough, but I
VC> encounter problem in the last step "make".

VC> The message I got as follow:
VC> make[1]: *** No rule to make target `Documents\bitblaze\temu1.0\vl.c',
VC> needed by vl.o. Stop.

VC> Appreciate your help. Thanks!

It might be helpful if you could include some more context in your
problem report, such as more information about the system you're
building on, and other parts of the output of the make command.

Are you indeed using 64-bit Ubuntu 12.04 as the earlier document was
about? If so, it's strange that the path mentioned in the make error
message uses backslashes (\): Linux paths instead use forward slashes
(/). If you're instead trying to build TEMU on a system like Cygwin, I
think you would likely run into a lot of other problems. If you just
interchanged the kinds of slashes when copying the error message into
the email, you might in the future want to copy the error messages
literally (which might involve other steps like copying them into a
file if you're using a VM), since mistakes like this can confuse
people trying to help.

The error message seems to be saying that it is unable to find a file
named "vl.c", but I checked that that file is included in the TEMU 1.0
release (as "temu-1.0/vl.c" to be precise, notice the hyphen and
forward slash). If you somehow accidentally deleted it, that could
cause this problem, or maybe the directories are getting confused? The
make error also sounds like you're running "make" in a directory named
"Documents", but usually when compiling TEMU you would be in the
temu-1.0 directory.

Rameez ali

unread,
Oct 31, 2016, 11:56:19 AM10/31/16
to BitBlaze User Discussion group, mcca...@cs.umn.edu
I still get the following error on ubuntu 14.04 64-bit ,after applying the gcc4 patch 

make: *** [qemu-img-block-raw-posix.o] Error 1

any ideas ? 

Stephen McCamant

unread,
Oct 31, 2016, 5:58:02 PM10/31/16
to Rameez ali, BitBlaze User Discussion group
>>>>> "RA" == Rameez ali <meer...@gmail.com> writes:

RA> I followed your steps on ubuntu 14.04 and i got the following
RA> error
RA> make: *** [qemu-img-block-raw-posix.o] Error 1

RA> any ideas ?

I think that line probably doesn't represent the real error message;
if you look above it in the output, you should see some error messages
from the compiler, which are likely to be more specific about what the
problem is. If your compile is failing for the same reason my 14.04
system does, the errors are (warnings omitted, for space):

gcc -Wall -O2 -g -fno-strict-aliasing -I. -I.../temu-1.0-orig -MMD -MP -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I.../temu-1.0-orig/slirp -DQEMU_IMG -c -o qemu-img-block-raw-posix.o block-raw-posix.c
block-raw-posix.c:242:26: error: `SIGUSR2' undeclared here (not in a function)
static int aio_sig_num = SIGUSR2;
^
block-raw-posix.c: In function `qemu_aio_init':
block-raw-posix.c:264:22: error: storage size of `act' isn;t known
struct sigaction act;
^
block-raw-posix.c:350:17: error: `SIG_BLOCK' undeclared (first use in this function)
sigprocmask(SIG_BLOCK, &set, &wait_oset);
^
block-raw-posix.c:350:17: note: each undeclared identifier is reported only once for each function it appears in
block-raw-posix.c: In function `qemu_aio_wait_end':
block-raw-posix.c:370:17: error: `SIG_SETMASK' undeclared (first use in this function)
sigprocmask(SIG_SETMASK, &wait_oset, NULL);
^
make: *** [qemu-img-block-raw-posix.o] Error 1

If you are familiar with Unix programming, you may notice that these
are all related to things that should be declared in <signal.h>;
adding an "#include" of it seems like the easiest way to fix them.

I noticed two other changes needed to allow compilation of QEMU with
the sample plugin on my Ubuntu 14.04 system: QEMU needs the "-ldl"
library specified explicitly as a dependency of -lrt, and an empty
"-Wl" should be removed from sample_plugin/Makefile. (Perhaps we were
thinking of "-Wl,-shared", but that doesn't do the right thing on my
system because it brings in an incompatible (non-PIC) crt1.o.

I've appended these three changes in the form of a patch. Note though
that I haven't tried building Tracecap or testing the resulting
binary, so there may be more changes needed.
temu-u14.04.patch
Reply all
Reply to author
Forward
0 new messages