Re: Hitachi djprobe mechanism

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Hitachi djprobe mechanism

Mathieu Lacage
hi,

I was interested enough that I hacked together the attached patch (I
used gcc svn HEAD and binutils cvs HEAD). It seems to work nicely with
-O0 but it seems to break on the simple testcase below with -O2/-O3 on
x86. i.e., it reports a bb boundary at 0x11 and I cannot see why there
would be a bb boundary there.

Also, I noticed that if you want to use this code for djprobe insertion
location verification, you will need to parse the resulting binary
anyway to detect the call sites which are not really bb boundaries and
are thus not reported by the patch as bb boundaries but which are
forbidden boundary locations for djprobe insertion.

I will do a lot more testing in a few days but I thought it might be
useful to send an early report.

regards,
Mathieu

#include <stdio.h>
static int foo (void)
{
        if (3) {
                int i = 0;
                while (i < 100) {
                        printf ("test\n");
                        i++;
                }
        }
        return 8;
}

int main (int argc, char *argv[])
{
        foo ();
        return 0;
}

Here, I get the following list of basic blocks with the debugging
information:
ad: 0x0
ad: 0x11
ad: 0x20
ad: 0x32
while the assembly output does not seem to contain any jump to 0x11:
00000000 <main>:
   0:   8d 4c 24 04             lea    0x4(%esp),%ecx
   4:   83 e4 f0                and    $0xfffffff0,%esp
   7:   ff 71 fc                pushl  0xfffffffc(%ecx)
   a:   55                      push   %ebp
   b:   89 e5                   mov    %esp,%ebp
   d:   53                      push   %ebx
   e:   31 db                   xor    %ebx,%ebx
  10:   51                      push   %ecx
  11:   83 ec 10                sub    $0x10,%esp
  14:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
  1a:   8d bf 00 00 00 00       lea    0x0(%edi),%edi
  20:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
  27:   43                      inc    %ebx
  28:   e8 fc ff ff ff          call   29 <main+0x29>
  2d:   83 fb 64                cmp    $0x64,%ebx
  30:   75 ee                   jne    20 <main+0x20>
  32:   83 c4 10                add    $0x10,%esp
  35:   31 c0                   xor    %eax,%eax
  37:   59                      pop    %ecx
  38:   5b                      pop    %ebx
  39:   5d                      pop    %ebp
  3a:   8d 61 fc                lea    0xfffffffc(%ecx),%esp
  3d:   c3                      ret



>> Richard Henderson has done some work in both gcc and the assembler to
>> emit
>> DWARF basic block markers.  The compiler knows what the jump targets
>> are in
>> code it generates.  For inline assembly, the assembler supports
>> emitting a
>>  
>
Reply | Threaded
Open this post in threaded view
|

Re: Hitachi djprobe mechanism

Mathieu Lacage
of course, it is better with the patch really attached

sorry,
Mathieu

mathieu lacage wrote:

> hi,
>
> I was interested enough that I hacked together the attached patch (I
> used gcc svn HEAD and binutils cvs HEAD). It seems to work nicely with
> -O0 but it seems to break on the simple testcase below with -O2/-O3 on
> x86. i.e., it reports a bb boundary at 0x11 and I cannot see why there
> would be a bb boundary there.
>
> Also, I noticed that if you want to use this code for djprobe
> insertion location verification, you will need to parse the resulting
> binary anyway to detect the call sites which are not really bb
> boundaries and are thus not reported by the patch as bb boundaries but
> which are forbidden boundary locations for djprobe insertion.
>
> I will do a lot more testing in a few days but I thought it might be
> useful to send an early report.
>
> regards,
> Mathieu
>
> #include <stdio.h>
> static int foo (void)
> {
>        if (3) {
>                int i = 0;
>                while (i < 100) {
>                        printf ("test\n");
>                        i++;
>                }
>        }
>        return 8;
> }
>
> int main (int argc, char *argv[])
> {
>        foo ();
>        return 0;
> }
>
> Here, I get the following list of basic blocks with the debugging
> information:
> ad: 0x0
> ad: 0x11
> ad: 0x20
> ad: 0x32
> while the assembly output does not seem to contain any jump to 0x11:
> 00000000 <main>:
>   0:   8d 4c 24 04             lea    0x4(%esp),%ecx
>   4:   83 e4 f0                and    $0xfffffff0,%esp
>   7:   ff 71 fc                pushl  0xfffffffc(%ecx)
>   a:   55                      push   %ebp
>   b:   89 e5                   mov    %esp,%ebp
>   d:   53                      push   %ebx
>   e:   31 db                   xor    %ebx,%ebx
>  10:   51                      push   %ecx
>  11:   83 ec 10                sub    $0x10,%esp
>  14:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
>  1a:   8d bf 00 00 00 00       lea    0x0(%edi),%edi
>  20:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
>  27:   43                      inc    %ebx
>  28:   e8 fc ff ff ff          call   29 <main+0x29>
>  2d:   83 fb 64                cmp    $0x64,%ebx
>  30:   75 ee                   jne    20 <main+0x20>
>  32:   83 c4 10                add    $0x10,%esp
>  35:   31 c0                   xor    %eax,%eax
>  37:   59                      pop    %ecx
>  38:   5b                      pop    %ebx
>  39:   5d                      pop    %ebp
>  3a:   8d 61 fc                lea    0xfffffffc(%ecx),%esp
>  3d:   c3                      ret
>
>
>
>>> Richard Henderson has done some work in both gcc and the assembler
>>> to emit
>>> DWARF basic block markers.  The compiler knows what the jump targets
>>> are in
>>> code it generates.  For inline assembly, the assembler supports
>>> emitting a
>>>  
>>
>>
>

Index: gcc/final.c
===================================================================
--- gcc/final.c (revision 106485)
+++ gcc/final.c (working copy)
@@ -129,6 +129,8 @@
 static rtx debug_insn;
 rtx current_output_insn;
 
+int current_start_basic_block = 0;
+
 /* Line number of last NOTE.  */
 static int last_linenum;
 
@@ -1744,6 +1746,7 @@
   else
     *seen |= SEEN_BB;
 
+  current_start_basic_block = 1;
   break;
 
  case NOTE_INSN_EH_REGION_BEG:
@@ -2071,8 +2074,21 @@
    note in a row.  */
  if (notice_source_line (insn))
   {
-    (*debug_hooks->source_line) (last_linenum, last_filename);
+    if (current_start_basic_block)
+      {
+ current_start_basic_block = 0;
+ (*debug_hooks->source_line) (last_linenum, last_filename, LINE_FLAG_BASIC_BLOCK);
+      }
+    else
+      {
+ (*debug_hooks->source_line) (last_linenum, last_filename, 0);
+      }
   }
+ else if (current_start_basic_block)
+  {
+    current_start_basic_block = 0;
+    (*debug_hooks->source_line) (last_linenum, last_filename, LINE_FLAG_BASIC_BLOCK);
+  }
 
  if (GET_CODE (body) == ASM_INPUT)
   {
@@ -2498,6 +2514,7 @@
  current_output_insn = debug_insn = 0;
       }
     }
+
   return NEXT_INSN (insn);
 }
 
Index: gcc/debug.c
===================================================================
--- gcc/debug.c (revision 106485)
+++ gcc/debug.c (working copy)
@@ -33,7 +33,7 @@
   debug_nothing_int_int,         /* begin_block */
   debug_nothing_int_int,         /* end_block */
   debug_true_tree,         /* ignore_block */
-  debug_nothing_int_charstar,         /* source_line */
+  debug_nothing_int_charstar_int, /* source_line */
   debug_nothing_int_charstar,         /* begin_prologue */
   debug_nothing_int_charstar,         /* end_prologue */
   debug_nothing_int_charstar,         /* end_epilogue */
@@ -94,6 +94,13 @@
 }
 
 void
+debug_nothing_int_charstar_int (unsigned int line ATTRIBUTE_UNUSED,
+ const char *text ATTRIBUTE_UNUSED,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+}
+
+void
 debug_nothing_int (unsigned int line ATTRIBUTE_UNUSED)
 {
 }
Index: gcc/debug.h
===================================================================
--- gcc/debug.h (revision 106485)
+++ gcc/debug.h (working copy)
@@ -59,7 +59,7 @@
   bool (* ignore_block) (tree);
 
   /* Record a source file location at (FILE, LINE).  */
-  void (* source_line) (unsigned int line, const char *file);
+  void (* source_line) (unsigned int line, const char *file, unsigned int flags);
 
   /* Called at start of prologue code.  LINE is the first line in the
      function.  This has been given the same prototype as source_line,
@@ -129,12 +129,16 @@
   int start_end_main_source_file;
 };
 
+
+#define LINE_FLAG_BASIC_BLOCK ((unsigned int)1)
+
 extern const struct gcc_debug_hooks *debug_hooks;
 
 /* The do-nothing hooks.  */
 extern void debug_nothing_void (void);
 extern void debug_nothing_charstar (const char *);
 extern void debug_nothing_int_charstar (unsigned int, const char *);
+extern void debug_nothing_int_charstar_int (unsigned int, const char *, unsigned int flags);
 extern void debug_nothing_int (unsigned int);
 extern void debug_nothing_int_int (unsigned int, unsigned int);
 extern void debug_nothing_tree (tree);
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c (revision 106485)
+++ gcc/dwarf2out.c (working copy)
@@ -69,7 +69,7 @@
 #include "input.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
-static void dwarf2out_source_line (unsigned int, const char *);
+static void dwarf2out_source_line (unsigned int, const char *, unsigned int flags);
 #endif
 
 /* DWARF2 Abbreviation Glossary:
@@ -2510,7 +2510,7 @@
      prologue case, not the eh frame case.  */
 #ifdef DWARF2_DEBUGGING_INFO
   if (file)
-    dwarf2out_source_line (line, file);
+    dwarf2out_source_line (line, file, 0);
 #endif
 }
 
@@ -13534,7 +13534,7 @@
    'line_info_table' for later output of the .debug_line section.  */
 
 static void
-dwarf2out_source_line (unsigned int line, const char *filename)
+dwarf2out_source_line (unsigned int line, const char *filename, unsigned int flags)
 {
   if (debug_info_level >= DINFO_LEVEL_NORMAL
       && line != 0)
@@ -13553,7 +13553,14 @@
   file_num = maybe_emit_file (file_num);
 
   /* Emit the .loc directive understood by GNU as.  */
-  fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line);
+  if (flags & LINE_FLAG_BASIC_BLOCK)
+    {
+      fprintf (asm_out_file, "\t.loc %d %d 0 basic_block\n", file_num, line);
+    }
+  else
+    {
+      fprintf (asm_out_file, "\t.loc %d %d 0 ;#test\n", file_num, line);
+    }
 
   /* Indicate that line number info exists.  */
   line_info_table_in_use++;
Reply | Threaded
Open this post in threaded view
|

Re: Hitachi djprobe mechanism

rasman
In reply to this post by Mathieu Lacage




OK, that's fine as long as we have an option of force the interrupt form of
probe so that we can handle odd cases where necessary.

- -
Richard J Moore
IBM Linux Technology Centre


                                                                           
             Roland McGrath                                                
             <roland@redhat.                                              
             com>                                                       To
                                      Richard J Moore/UK/IBM@IBMGB        
             09/10/2005                                                 cc
             00:23                    [hidden email]        
                                                                       bcc
                                                                           
                                                                   Subject
                                      Re: Hitachi djprobe mechanism        
                                                                           
                                                                           




Richard Henderson has done some work in both gcc and the assembler to emit
DWARF basic block markers.  The compiler knows what the jump targets are in
code it generates.  For inline assembly, the assembler supports emitting a
marker for every assembler label, and the compiler emits the assembler
directive to enable the assembler's automatic markers around the inline
assembly code it copies out of your `asm' statements.  When the tools with
this support are available (not yet), this will cover everything we see in
the kernel, and most user applications built in normal ways, when they are
built with DWARF info.

The basic block markers are in the standard DWARF format specification.
(They are an optional part of the same encoding that provides source line
number information.)  Other compilers that, like gcc, have not heretofore
implemented this, can do so just as well as we can.

Of course hand-crafted or specially-generated code could always use
computed jumps to locations not marked with assembler labels.  It just
seems very unlikely.  In the case of the kernel, we can be sure enough what
the set of code is and know that there isn't any funny business beyond the
ken of our automatic tools.  For the most general worst case, probably one
does have to be so conservative that you can only use jmp insertion on
unusually large instructions.