Пример #1
0
void valgrind_resume (struct thread_resume *resume_info)
{
   dlog(1,
        "resume_info step %d sig %d stepping %d\n", 
        resume_info->step,
        resume_info->sig,
        stepping);
   if (valgrind_stopped_by_watchpoint()) {
      dlog(1, "clearing watchpoint stopped_data_address %p\n",
           C2v(stopped_data_address));
      VG_(set_watchpoint_stop_address) ((Addr) 0);
   }
   vki_signal_to_deliver.si_signo = resume_info->sig;
   /* signal was reported to GDB, GDB told us to resume execution.
      So, reset the signal to report to 0. */
   VG_(memset) (&vki_signal_to_report, 0, sizeof(vki_signal_to_report));
   
   stepping = resume_info->step;
   resume_pc = (*the_low_target.get_pc) ();
   if (resume_pc != stop_pc) {
      dlog(1,
           "stop_pc %p changed to be resume_pc %s\n",
           C2v(stop_pc), sym(resume_pc));
   }
   regcache_invalidate();
}
Пример #2
0
Bool VG_(gdbserver_point) (PointKind kind, Bool insert,
                           CORE_ADDR addr, int len)
{
   Bool res;
   GS_Watch *g;
   Word g_ix;
   Bool is_code = kind == software_breakpoint || kind == hardware_breakpoint;

   dlog(1, "%s %s at addr %p %s\n",
        (insert ? "insert" : "remove"), 
        VG_(ppPointKind) (kind),
        C2v(addr), 
        sym(addr, is_code));

   if (is_code) {
      breakpoint (insert, addr);
      return True;
   }

   vg_assert (kind == access_watchpoint 
              || kind == read_watchpoint 
              || kind == write_watchpoint);

   if (tool_watchpoint == NULL)
      return False;

   res = (*tool_watchpoint) (kind, insert, addr, len);
   if (!res) 
      return False; /* error or unsupported */

   // Protocol says insert/remove must be idempotent.
   // So, we just ignore double insert or (supposed) double delete.

   g = lookup_gs_watch (addr, len, kind, &g_ix);
   if (insert) {
      if (g == NULL) {
         g = VG_(arena_malloc)(VG_AR_CORE, "gdbserver_point watchpoint",
                               sizeof(GS_Watch));
         g->addr = addr;
         g->len  = len;
         g->kind = kind;
         VG_(addToXA)(gs_watches, &g);
      } else {
         dlog(1, 
              "VG_(gdbserver_point) addr %p len %d kind %s already inserted\n",
               C2v(addr), len, VG_(ppPointKind) (kind));
      }
   } else {
      if (g != NULL) {
         VG_(removeIndexXA) (gs_watches, g_ix);
         VG_(arena_free) (VG_AR_CORE, g);
      } else {
         dlog(1, 
              "VG_(gdbserver_point) addr %p len %d kind %s already deleted?\n",
              C2v(addr), len, VG_(ppPointKind) (kind));
      }
   }  
   return True;
}
static
void set_pc ( CORE_ADDR newpc )
{
  Bool mod;
  supply_register_by_name ("pc", &newpc, &mod);
  if (mod)
    dlog(1, "set pc to %p\n", C2v (newpc));
  else
    dlog(1, "set pc not changed %p\n", C2v (newpc));
}
Пример #4
0
/* protocol spec tells the below must be idempotent. */
static void breakpoint (Bool insert, CORE_ADDR addr)
{
   GS_Address *g;

   g = VG_(HT_lookup) (gs_addresses, (UWord)HT_addr(addr));
   if (insert) {
      /* insert a breakpoint at addr or upgrade its kind */
      if (g == NULL) {
         add_gs_address (addr, GS_break, "m_gdbserver breakpoint insert");
      } else {
         /* already gdbserved. Normally, it must be because of a jump.
            However, due to idempotent or if connection with gdb was
            lost (kept breaks from the previous gdb), if already existing,
            we just upgrade its kind. */
         g->kind = GS_break;
      }
   } else {
      /* delete a breakpoint at addr or downgrade its kind */
      if (g != NULL && g->kind == GS_break) {
         if (valgrind_single_stepping()) {
            /* keep gdbserved instrumentation while single stepping */
            g->kind = GS_jump;
         } else {
            remove_gs_address (g, "m_gdbserver breakpoint remove");
         }
      } else {
         dlog (1, "remove break addr %p %s\n",
               C2v(addr), (g == NULL ? 
                           "NULL" : 
                           (g->kind == GS_jump ? "GS_jump" : "GS_break")));
      }
   }
}
Пример #5
0
int valgrind_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
{
   Bool is_valid_client_memory;
   void *targetaddr = C2v (memaddr);
   dlog(2, "writing memory %p size %d\n", targetaddr, len);
   is_valid_client_memory 
      = VG_(am_is_valid_for_client) ((Addr)targetaddr, len, VKI_PROT_WRITE);
   if (is_valid_client_memory
       || (hostvisibility 
           && VG_(am_is_valid_for_valgrind) ((Addr) targetaddr, 
                                             len, VKI_PROT_READ))) {
      if (len > 0) {
         VG_(memcpy) (targetaddr, myaddr, len);
         if (is_valid_client_memory && VG_(tdict).track_post_mem_write) {
            /* Inform the tool of the post memwrite.  Note that we do the
               minimum necessary to avoid complains from e.g.
               memcheck. The idea is that the debugger is as least
               intrusive as possible.  So, we do not inform of the pre
               mem write (and in any case, this would cause problems with
               memcheck that does not like our CorePart in
               pre_mem_write. */
            ThreadState *tst = 
               (ThreadState *) inferior_target_data (current_inferior);
            ThreadId tid = tst->tid;
            VG_(tdict).track_post_mem_write( Vg_CoreClientReq, tid,
                                             (Addr) targetaddr, len );
         }
      }
      return 0;
   } else {
      dlog(1, "error writing memory %p size %d\n", targetaddr, len);
      return -1;
   }
}
Пример #6
0
void valgrind_resume (struct thread_resume *resume_info)
{
   dlog(1,
        "resume_info step %d sig %d stepping %d\n", 
        resume_info->step,
        resume_info->sig,
        stepping);
   if (valgrind_stopped_by_watchpoint()) {
      dlog(1, "clearing watchpoint stopped_data_address %p\n",
           C2v(stopped_data_address));
      VG_(set_watchpoint_stop_address) ((Addr) 0);
   }
   vki_signal_to_deliver = resume_info->sig;
   
   stepping = resume_info->step;
   resume_pc = (*the_low_target.get_pc) ();
   if (resume_pc != stop_pc) {
      dlog(1,
           "stop_pc %p changed to be resume_pc %s\n",
           C2v(stop_pc), sym(resume_pc));
   }
   regcache_invalidate();
}
Пример #7
0
Bool VG_(gdbserver_point) (PointKind kind, Bool insert,
                           CORE_ADDR addr, int len)
{
   Bool res;
   GS_Watch *g;
   Bool is_code = kind == software_breakpoint || kind == hardware_breakpoint;

   dlog(1, "%s %s at addr %p %s\n",
        (insert ? "insert" : "remove"), 
        VG_(ppPointKind) (kind),
        C2v(addr), 
        sym(addr, is_code));

   if (is_code) {
      breakpoint (insert, addr);
      return True;
   }

   vg_assert (kind == access_watchpoint 
              || kind == read_watchpoint 
              || kind == write_watchpoint);

   if (tool_watchpoint == NULL)
      return False;

   res = (*tool_watchpoint) (kind, insert, addr, len);
   if (!res) 
      return False; /* error or unsupported */

   g = VG_(HT_lookup) (gs_watches, (UWord)addr);
   if (insert) {
      if (g == NULL) {
         g = VG_(arena_malloc)(VG_AR_CORE, "gdbserver_point watchpoint",
                               sizeof(GS_Watch));
         g->addr = addr;
         g->len  = len;
         g->kind = kind;
         VG_(HT_add_node)(gs_watches, g);
      } else {
         g->kind = kind;
      }
   } else {
      vg_assert (g != NULL);
      VG_(HT_remove) (gs_watches, g->addr);
      VG_(arena_free) (VG_AR_CORE, g);
   }  
   return True;
}
Пример #8
0
int valgrind_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
   const void *sourceaddr = C2v (memaddr);
   dlog(2, "reading memory %p size %d\n", sourceaddr, len);
   if (VG_(am_is_valid_for_client) ((Addr) sourceaddr, 
                                    len, VKI_PROT_READ)
       || (hostvisibility 
           && VG_(am_is_valid_for_valgrind) ((Addr) sourceaddr, 
                                             len, VKI_PROT_READ))) {
      VG_(memcpy) (myaddr, sourceaddr, len);
      return 0;
   } else {
      dlog(1, "error reading memory %p size %d\n", sourceaddr, len);
      return -1;
   }
}
Пример #9
0
/* Returns the reason for which gdbserver instrumentation is needed */
static VgVgdb VG_(gdbserver_instrumentation_needed) (VexGuestExtents* vge)
{
   GS_Address* g;
   int e;

   if (!gdbserver_called)
      return Vg_VgdbNo;

   if (valgrind_single_stepping()) {
      dlog(2, "gdbserver_instrumentation_needed due to single stepping\n");
      return Vg_VgdbYes;
   }

   if (VG_(clo_vgdb) == Vg_VgdbYes && VG_(HT_count_nodes) (gs_addresses) == 0)
      return Vg_VgdbNo;

   /* We assume we do not have a huge nr of breakpoints.
      Otherwise, we need something more efficient e.g.
      a sorted list of breakpoints or associate extents to it or ...
   */
   VG_(HT_ResetIter) (gs_addresses);
   while ((g = VG_(HT_Next) (gs_addresses))) {
      for (e = 0; e < vge->n_used; e++) {
         if (g->addr >= HT_addr(vge->base[e]) 
             && g->addr < HT_addr(vge->base[e]) + vge->len[e]) {
            dlog(2,
                 "gdbserver_instrumentation_needed %p %s reason %s\n",
                 C2v(g->addr), sym(g->addr, /* is_code */ True),
                 (g->kind == GS_jump ? "GS_jump" : "GS_break"));
            return Vg_VgdbYes;
         }
      }
   }

   if (VG_(clo_vgdb) == Vg_VgdbFull) {
      dlog(4, "gdbserver_instrumentation_needed"
           " due to VG_(clo_vgdb) == Vg_VgdbFull\n");
      return Vg_VgdbFull;
   }


   return Vg_VgdbNo;
}
Пример #10
0
Addr thumb_pc (Addr pc)
{
   
   if (pc & 1) {
      dlog (1, "%p = thumb (bit0 is set)\n", C2v (pc));
      return pc;
   }

   
   
   
   
   

   if (pc & 2) {
      dlog (1, "bit0 not set, bit1 set => %p = thumb\n", C2v (pc));
      return pc | 1;
   }

   
   {
      Char fnname[200]; 
      Addr entrypoint;
      Addr ptoc; 
      
      
      
      
      if (VG_(get_fnname_raw) (pc | 1, fnname, 200)) {
         if (VG_(lookup_symbol_SLOW)( "*", fnname, &entrypoint, &ptoc )) {
            dlog (1, "fnname %s lookupsym %p => %p %s.\n",
                  fnname, C2v(entrypoint), C2v(pc),
                  (entrypoint & 1 ? "thumb" : "arm"));
            if (entrypoint & 1)
               return pc | 1;
            else
               return pc;
            
         } else {
            dlog (1, "%p fnname %s lookupsym failed?. Assume arm\n",
                  C2v (pc), fnname);
            return pc;
         }
      } else {
         
         dlog (1, "%p unknown fnname?. Assume arm\n", C2v (pc));
         return pc;
      }
   }
}
Пример #11
0
Addr thumb_pc (Addr pc)
{
    // If the thumb bit (bit 0) is already set, we trust it.
    if (pc & 1) {
        dlog (1, "%p = thumb (bit0 is set)\n", C2v (pc));
        return pc;
    }

    // Here, bit 0 is not set.
    // For a pc aligned on 4 bytes, we have to use the debug
    // info to determine the thumb-ness.
    // else (aligned on 2 bytes), we trust this is a thumb
    // address and we set the thumb bit.

    if (pc & 2) {
        dlog (1, "bit0 not set, bit1 set => %p = thumb\n", C2v (pc));
        return pc | 1;
    }

    // pc aligned on 4 bytes. We need to use debug info.
    {
        HChar fnname[200]; // ??? max size
        SymAVMAs avmas;
        // If this is a thumb instruction, we need to ask
        // the debug info with the bit0 set
        // (why can't debug info do that for us ???)
        // (why if this is a 4 bytes thumb instruction ???)
        if (VG_(get_fnname_raw) (pc | 1, fnname, 200)) {
            if (VG_(lookup_symbol_SLOW)( "*", fnname, &avmas )) {
                dlog (1, "fnname %s lookupsym %p => %p %s.\n",
                      fnname, C2v(avmas.main), C2v(pc),
                      (avmas.main & 1 ? "thumb" : "arm"));
                if (avmas.main & 1)
                    return pc | 1;
                else
                    return pc;

            } else {
                dlog (1, "%p fnname %s lookupsym failed?. Assume arm\n",
                      C2v (pc), fnname);
                return pc;
            }
        } else {
            // Can't find function name. We assume this is arm
            dlog (1, "%p unknown fnname?. Assume arm\n", C2v (pc));
            return pc;
        }
    }
}
Пример #12
0
Bool VG_(is_watched)(PointKind kind, Addr addr, Int szB)
{
   Word n_elems;
   GS_Watch* g;
   Word i;
   Bool watched = False;
   const ThreadId tid = VG_(running_tid);

   if (!gdbserver_called)
      return False;

   n_elems = VG_(sizeXA) (gs_watches);

   Addr to = addr + szB; // semi-open interval [addr, to[

   vg_assert (kind == access_watchpoint 
              || kind == read_watchpoint 
              || kind == write_watchpoint);
   dlog(1, "tid %d VG_(is_watched) %s addr %p szB %d\n",
        tid, VG_(ppPointKind) (kind), C2v(addr), szB);

   for (i = 0; i < n_elems; i++) {
      g = index_gs_watches(i);
      switch (g->kind) {
      case software_breakpoint:
      case hardware_breakpoint:
         break;
      case access_watchpoint:
      case read_watchpoint:
      case write_watchpoint:
         if (to <= g->addr || addr >= (g->addr + g->len))
            /* If no overlap, examine next watchpoint: */
            continue;

         watched = True; /* We have an overlap */

         /* call gdbserver if access kind reported by the tool
            matches the watchpoint kind. */
         if (kind == access_watchpoint
             || g->kind == access_watchpoint
             || g->kind == kind) {
            /* Watchpoint encountered.
               If this is a read watchpoint, we directly call gdbserver
               to report it to gdb.
               Otherwise, for a write watchpoint, we have to finish
               the instruction so as to modify the value.
               If we do not finish the instruction, then gdb sees no
               value change and continues.
               For a read watchpoint, we better call gdbserver directly:
               in case the current block is not gdbserved, Valgrind
               will execute instructions till the next block. */

            /* set the watchpoint stop address to the first read or written. */
            if (g->addr <= addr) {
               VG_(set_watchpoint_stop_address) (addr);
            } else {
               VG_(set_watchpoint_stop_address) (g->addr);
            }

            if (kind == write_watchpoint) {
               /* Let Valgrind stop as early as possible after this instruction
                  by switching to Single Stepping mode. */
               valgrind_set_single_stepping (True);
               invalidate_current_ip (tid, "m_gdbserver write watchpoint");
            } else {
               call_gdbserver (tid, watch_reason);
               VG_(set_watchpoint_stop_address) ((Addr) 0);
            }
            return True; // we are watched here.
         }
         break;
      default:
         vg_assert (0);
      }
   }
   return watched;
}