Пример #1
0
static dr_emit_flags_t
event_analyze_bb(void *drcontext, void *tag, instrlist_t *bb,
                 bool for_trace, bool translating, void **user_data)
{
    instr_t *instr;
    trace_head_entry_t *e = NULL;
    if (translating)
        return DR_EMIT_DEFAULT;
    for (instr  = instrlist_first_app(bb);
         instr != NULL;
         instr  = instr_get_next_app(instr)) {
        /* Blocks containing calls are trace heads. */
        if (instr_is_call(instr)) {
            dr_mark_trace_head(drcontext, tag);
            hashtable_lock(&head_table);
            e = hashtable_lookup(&head_table, tag);
            if (e == NULL) {
                e = create_trace_head_entry(tag);
                if (!hashtable_add(&head_table, tag, (void *)e))
                    DR_ASSERT(false);
            } else
                e->refcount++;
            e->is_trace_head = true;
            hashtable_unlock(&head_table);
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: marking bb "PFX" as call trace head\n", tag);
#endif
            /* Doesn't matter what's in rest of the bb. */
            return DR_EMIT_DEFAULT;
        } else if (instr_is_return(instr)) {
            hashtable_lock(&head_table);
            e = hashtable_lookup(&head_table, tag);
            if (e == NULL) {
                e = create_trace_head_entry(tag);
                if (!hashtable_add(&head_table, tag, (void *)e))
                    DR_ASSERT(false);
            } else
                e->refcount++;
            e->has_ret = true;
            hashtable_unlock(&head_table);
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: marking bb "PFX" as return trace head\n", tag);
#endif
        }
    }
    return DR_EMIT_DEFAULT;
}
Пример #2
0
bool
hashtable_remove_range(hashtable_t *table, void *start, void *end)
{
    bool res = false;
    uint i;
    hash_entry_t *e, *prev_e, *next_e;
    if (table->synch)
        hashtable_lock(table);
    for (i = 0; i < HASHTABLE_SIZE(table->table_bits); i++) {
        for (e = table->table[i], prev_e = NULL; e != NULL; e = next_e) {
            next_e = e->next;
            if (e->key >= start && e->key < end) {
                if (prev_e == NULL)
                    table->table[i] = e->next;
                else
                    prev_e->next = e->next;
                if (table->str_dup)
                    hash_free(e->key, strlen((const char *)e->key) + 1);
                if (table->free_payload_func != NULL)
                    (table->free_payload_func)(e->payload);
                hash_free(e, sizeof(*e));
                table->entries--;
                res = true;
            } else
                prev_e = e;
        }
    }
    if (table->synch)
        hashtable_unlock(table);
    return res;
}
Пример #3
0
static void onUnload( void* ctx, const module_data_t* m ) {
  dr_printf( "In onUnload(%s, %p-%p)\n", m->full_path, m->start, m->end );

  dr_mutex_lock( outMutex );
  dr_fprintf( outFile, "m %p %p %s\n", (void*)m->start,
                                       (void*)m->end,
                                       m->full_path );
  dr_mutex_unlock( outMutex );

  hashtable_lock( &wraps );
  hashtable_remove_range( &wraps, (void*)m->start, (void*)m->end );
  hashtable_unlock( &wraps );
}
Пример #4
0
/* To keep the size of our hashtable down. */
static void
event_fragment_deleted(void *drcontext, void *tag)
{
    trace_head_entry_t *e;
    hashtable_lock(&head_table);
    e = hashtable_lookup(&head_table, tag);
    if (e != NULL) {
        e->refcount--;
        if (e->refcount == 0)
            hashtable_remove(&head_table, tag);
    }
    hashtable_unlock(&head_table);
}
Пример #5
0
/** Installs wrapper for a given symbol. */
static void wrapSymbol( const char* sym,
                        module_data_t* module,
                        size_t offset,
                        struct demangle_component* qual,
                        struct demangle_component* info ) {
  app_pc pc = module->start + offset;
  if( offset == 0 || pc == 0 ) {
    dr_printf( "Skipping symbol %s\n", sym );
    return;
  }

  size_t size;
  char* className = cplus_demangle_print( DMGL_NO_OPTS, qual, 64, &size );

  hashtable_lock( &wraps );
  struct wrap* wrap = ( struct wrap* )hashtable_lookup( &wraps, (void*)pc );
  if( wrap == NULL ) {
    // Not wrapped yet.
    if( !drwrap_wrap( pc, &wrapperPre, NULL ) ) {
      dr_printf( "drwrap_wrap(%s %s of kind %i = +%p = %p) failed\n",
                 className,
                 info->type == DEMANGLE_COMPONENT_CTOR ? "ctor" : "dtor",
                 info->type == DEMANGLE_COMPONENT_CTOR ? info->u.s_ctor.kind :
                                                         info->u.s_dtor.kind,
                 (void*)offset,
                 (void*)pc );
      exit( 1 );
    }

    wrap = alloc_wrap();
    memset( wrap, 0, sizeof( struct wrap ) );
    wrap->address = pc;
    hashtable_add( &wraps, (void*)pc, wrap );
  } else {
    // Already wrapped - do nothing.
  }
  char* eventType = "?";
  if( info->type == DEMANGLE_COMPONENT_CTOR ) {
    switch( info->u.s_ctor.kind ) {
    case gnu_v3_complete_object_allocating_ctor:
      wrap->flags |= FLAG_ALLOCATING_CONSTRUCTOR;
      eventType = "A";
      break;
    case gnu_v3_complete_object_ctor:
      wrap->flags |= FLAG_COMPLETE_OBJECT_CONSTRUCTOR;
      eventType = "C";
      break;
    case gnu_v3_base_object_ctor:
      wrap->flags |= FLAG_BASE_OBJECT_CONSTRUCTOR;
      eventType = "B";
      break;
    }
  } else {
    switch( info->u.s_dtor.kind ) {
    case gnu_v3_deleting_dtor:
      wrap->flags |= FLAG_DEALLOCATING_DESTRUCTOR;
      eventType ="a";
      break;
    case gnu_v3_complete_object_dtor:
      wrap->flags |= FLAG_COMPLETE_OBJECT_DESTRUCTOR;
      eventType = "c";
      break;
    case gnu_v3_base_object_dtor:
      wrap->flags |= FLAG_BASE_OBJECT_DESTRUCTOR;
      eventType = "b";
      break;
    }
  }
  hashtable_unlock( &wraps );

  dr_mutex_lock( outMutex );
  dr_fprintf( outFile, "%s %p %s\n", eventType, (void*)pc, className );
  dr_mutex_unlock( outMutex );

  free( className );
}
Пример #6
0
/* Ask whether to end trace prior to adding next_tag fragment.
 * Return values:
 *   CUSTOM_TRACE_DR_DECIDES = use standard termination criteria
 *   CUSTOM_TRACE_END_NOW   = end trace
 *   CUSTOM_TRACE_CONTINUE  = do not end trace
 */
static dr_custom_trace_action_t
query_end_trace(void *drcontext, void *trace_tag, void *next_tag)
{
    /* If this is a call trace, only end on the block AFTER a return
     *   (need to get the return inlined!).
     * If this is a standard back branch trace, end it if we see a
     *   block with a call (so that we'll go into the call trace).
     *   otherwise return 0 and let DynamoRIO determine whether to
     *   terminate the trace now.
     */
    trace_head_entry_t *e;
    hashtable_lock(&head_table);
    e = hashtable_lookup(&head_table, trace_tag);
    if (e == NULL || !e->is_trace_head) {
        e = hashtable_lookup(&head_table, next_tag);
        if (e == NULL || !e->is_trace_head) {
            hashtable_unlock(&head_table);
            return CUSTOM_TRACE_DR_DECIDES;
        } else {
            /* We've found a call: end this trace now so it won't keep going and
             * end up never entering the call trace.
             */
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: ending trace "PFX" before block "PFX" containing call\n",
                   trace_tag, next_tag);
#endif
#ifdef SHOW_RESULTS
            num_traces++;
#endif
            hashtable_unlock(&head_table);
            return CUSTOM_TRACE_END_NOW;
        }
    } else if (e->end_next > 0) {
        e->end_next--;
        if (e->end_next == 0) {
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: ending trace "PFX" before "PFX"\n",
                   trace_tag, next_tag);
#endif
#ifdef SHOW_RESULTS
            num_complete_inlines++;
            num_traces++;
#endif
            hashtable_unlock(&head_table);
            return CUSTOM_TRACE_END_NOW;
        }
    } else {
        trace_head_entry_t *nxte = hashtable_lookup(&head_table, next_tag);
        uint size = dr_fragment_size(drcontext, next_tag);
        e->size += size;
        if (e->size > INLINE_SIZE_LIMIT) {
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: ending trace "PFX" before "PFX" because reached size limit\n",
                   trace_tag, next_tag);
#endif
#ifdef SHOW_RESULTS
            num_traces++;
#endif
            hashtable_unlock(&head_table);
            return CUSTOM_TRACE_END_NOW;
        }
        if (nxte != NULL && nxte->has_ret && !nxte->is_trace_head) {
            /* End trace after NEXT block */
            e->end_next = 2;
#ifdef VERBOSE
            dr_log(drcontext, DR_LOG_ALL, 3,
                   "inline: going to be ending trace "PFX" after "PFX"\n",
                   trace_tag, next_tag);
#endif
            hashtable_unlock(&head_table);
            return CUSTOM_TRACE_CONTINUE;
        }
    }
    /* Do not end trace */
#ifdef VERBOSE
    dr_log(drcontext, DR_LOG_ALL, 3,
           "inline: NOT ending trace "PFX" after "PFX"\n", trace_tag, next_tag);
#endif
    hashtable_unlock(&head_table);
    return CUSTOM_TRACE_CONTINUE;
}