Exemple #1
0
Fichier : XlcDL.c Projet : aosm/X11
XLCd
_XlcDynamicLoad(const char *lc_name)
{
    XLCd lcd = (XLCd)NULL;
    dynamicLoadProc lc_loader = (dynamicLoadProc)NULL;
    int count;
    XI18NObjectsList objects_list;
    char lc_dir[BUFSIZE];

    if (lc_name == NULL) return (XLCd)NULL;

    if (_XlcLocaleDirName(lc_dir, BUFSIZE, (char *)lc_name) == (char*)NULL)
	return (XLCd)NULL;

    resolve_object(lc_dir, lc_name);

    objects_list = xi18n_objects_list;
    count = lc_count;
    for (; count-- > 0; objects_list++) {
        if (objects_list->type != XLC_OBJECT ||
	    strcmp(objects_list->locale_name, lc_name)) continue;
	if (!open_object (objects_list, lc_dir))
	    continue;

	lc_loader = (dynamicLoadProc)fetch_symbol (objects_list, objects_list->open);
	if (!lc_loader) continue;
	lcd = (*lc_loader)(lc_name);
	if (lcd != (XLCd)NULL) {
	    break;
	}
	
	close_object (objects_list);
    }
    return (XLCd)lcd;
}
Exemple #2
0
static void *
object_get_from_message_arg(DBusMessage *message, char *type)
{
	char *opath;
	DBusError error;

	dbus_error_init(&error);
	if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) {
		dbus_error_free(&error);
		dbg(0,"wrong arg type\n");
		return NULL;
	}
	return resolve_object(opath, type);
}
Exemple #3
0
static void *
object_get_from_message(DBusMessage *message, char *type)
{
	return resolve_object(dbus_message_get_path(message), type);
}
Exemple #4
0
static int callback_nyx_websockets(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in,size_t len)
{
  struct per_session_data_nyx *pss =(struct per_session_data_nyx*)user;
  int n;

  node *wsd_state = (node*)libwebsocket_context_user(context);
  //node *daemon = (node*)libwebsocket_context_user(context);
  //node *wsd_state = node_GetNode(get_value(daemon));
  node *found_prot = NULL;
  node *state = NULL;
  node *block = NULL;
  //node *daemon = NULL;
  node *daemon_obj = NULL;
  node *session_uid = NULL;
  long lsession_uid = 0;
  node *sessions_num = NULL;
  node *sessions = NULL;
  long lsessions_num = 0;
  
  if(wsd_state)
  {
    state = node_GetItem(wsd_state,0);
    block = node_GetItem(wsd_state,1);
    //daemon = node_GetItem(wsd_state,2);
    node *protocols = node_GetItem(wsd_state,3);
    session_uid = node_GetItem(wsd_state,4);
    node *session_uid_value = node_GetItemByKey(session_uid,"value");
    lsession_uid = node_GetSint32(session_uid_value);
    sessions_num = node_GetItem(wsd_state,5);
    sessions = node_GetItem(wsd_state,6);
    node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
    lsessions_num = node_GetSint32(sessions_num_value);
    daemon_obj = node_GetItem(wsd_state,9);
    if(wsi)
    {
      node *protocols_items = node_GetItemByKey(protocols,"items");
      const struct libwebsocket_protocols *prot = libwebsockets_get_protocol(wsi);
      if(prot && prot->name)
      {
        node_ItemIterationReset(protocols_items);
        while(node_ItemIterationUnfinished(protocols_items))
        {
          node *proto = node_ItemIterate(protocols_items);
          if(!strcmp(get_obj_name(proto),prot->name))
          {
            found_prot = proto;
          }
        }
      }
    }
  }

  switch(reason) 
  {

    //case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
      printf("new session created:%d, num:%d\n",lsession_uid,lsessions_num);
      pss->session = NULL;
      break;

    case LWS_CALLBACK_HTTP:
      if(len < 1)
      {
        libwebsockets_return_http_status(context,wsi,HTTP_STATUS_BAD_REQUEST,NULL);
        return(-1);
      }
      if(lws_hdr_total_length(wsi,WSI_TOKEN_POST_URI))
        return(0);

      if(found_prot)
      {
        //printf("found prot in http callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
        if(!pss->session)
        {
          lsession_uid++;
          node *session_uid_value = node_GetItemByKey(session_uid,"value");
          node_SetSint32(session_uid_value,lsession_uid);
          lsessions_num++;
          node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
          node_SetSint32(sessions_num_value,lsessions_num);
          pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
          node *session_privates = node_GetItemByKey(pss->session,"privates");
          set_obj_int(session_privates,"is_http",1);
          //printf("created new session :%d actual sessions num:%d\n",lsession_uid,lsessions_num);
        }
        

        node *parameters = create_obj("parameters");
        node *base_class = get_base_class(state);
        node *prot_value = create_class_instance(base_class);
        set_obj_string(prot_value,"name","protocol");
        set_obj_string(prot_value,"value",get_obj_name(found_prot));
        node_AddItem(parameters,prot_value);
        inc_obj_refcount(prot_value);
        char *url = str_CreateEmpty();
        url = str_AddChars(url,in,len);
        node *url_value = create_class_instance(base_class);
        set_obj_string(url_value,"name","url");
        set_obj_string(url_value,"value",url);
        node_AddItem(parameters,url_value);
        inc_obj_refcount(url_value);
        free(url);
        node_AddItem(parameters,pss->session);
        inc_obj_refcount(pss->session);
        //node_AddItem(parameters,daemon_obj);
        node_AddItem(parameters,sessions);
        inc_obj_refcount(sessions);
        node *tmp_parent = node_GetParent(found_prot);
        node *bmembers = node_GetItemByKey(block,"members");
        node_SetParent(found_prot,bmembers);
        node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve
        node_SetParent(found_prot,tmp_parent);
        //dec_obj_refcount(msg_value);
        dec_obj_refcount(prot_value);
        //add_garbage(state,msg_value);//TODO check if "just survives"
        add_garbage(state,prot_value);
        dec_obj_refcount(url_value);
        add_garbage(state,url_value);
        dec_obj_refcount(pss->session);
        dec_obj_refcount(sessions);
 
        node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
        if( (node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) || (node_GetType(ret_obj_value)==NODE_TYPE_BINARY && node_GetBinaryLength(ret_obj_value)) )
        {
          //printf("returning http message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value)));
          //node *ret_obj_copy = node_CopyTree(ret_obj,True,True);
          node *ret_obj_copy = copy_class(ret_obj);
          //reset_obj_refcount(ret_obj_copy);
          set_obj_string(ret_obj_copy,"name","message");
          add_member(pss->session,ret_obj_copy);
          inc_obj_refcount(ret_obj_copy);
        }
        libwebsocket_callback_on_writable(context, wsi);
      }
      break;

    case LWS_CALLBACK_HTTP_BODY_COMPLETION:
      if(found_prot)
      {
        printf("found prot in http body complete : %d,num:%d\n",lsession_uid,lsessions_num);
        if(daemon_obj)
        {
          printf("body: found daemon_obj\n");
        }
      }
      else
        printf("body closed: prot not found\n");
      //lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
      libwebsockets_return_http_status(context,wsi,HTTP_STATUS_OK,NULL);
     return(-1);

    case LWS_CALLBACK_HTTP_FILE_COMPLETION:
      if(found_prot)
     {
        //printf("found prot in http file complete : %d,num:%d\n",lsession_uid,lsessions_num);
        lsessions_num--;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        delete_session(state,sessions,pss->session);
        pss->session = NULL;
        if(daemon_obj)
        {
          printf("http: found daemon_obj\n");
        }
      }
      else
        printf("file closed: prot not found\n");
      return(-1);

    case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
      if(found_prot)
      {
      int n;
      static const char *token_names[] = 
      {
        /*[WSI_TOKEN_GET_URI]   =*/ "GET URI",
        /*[WSI_TOKEN_POST_URI]    =*/ "POST URI",
        /*[WSI_TOKEN_OPTIONS]    =*/ "Options",
        /*[WSI_TOKEN_HOST]    =*/ "Host",
        /*[WSI_TOKEN_CONNECTION]  =*/ "Connection",
        /*[WSI_TOKEN_KEY1]    =*/ "key 1",
        /*[WSI_TOKEN_KEY2]    =*/ "key 2",
        /*[WSI_TOKEN_PROTOCOL]    =*/ "Protocol",
        /*[WSI_TOKEN_UPGRADE]   =*/ "Upgrade",
        /*[WSI_TOKEN_ORIGIN]    =*/ "Origin",
        /*[WSI_TOKEN_DRAFT]   =*/ "Draft",
        /*[WSI_TOKEN_CHALLENGE]   =*/ "Challenge",
        /* new for 04 */
        /*[WSI_TOKEN_KEY]   =*/ "Key",
        /*[WSI_TOKEN_VERSION]   =*/ "Version",
        /*[WSI_TOKEN_SWORIGIN]    =*/ "Sworigin",
        /* new for 05 */
        /*[WSI_TOKEN_EXTENSIONS]  =*/ "Extensions",
        /* client receives these */
        /*[WSI_TOKEN_ACCEPT]    =*/ "Accept",
        /*[WSI_TOKEN_NONCE]   =*/ "Nonce",
        /*[WSI_TOKEN_HTTP]    =*/ "Http",
        "Accept:",
        "Accept_Request_Headers:",
        "If-None-Match:",
        "If-Modified-Since:",
        "Accept-Encoding:",
        "Accept-Language:",
        "Pragma:",
        "Cache-Control:",
        "Authorization:",
        "Cookie:",
        "Content-Length:",
        "Content-Type:",
        "Date:",
        "Range:",
        "Referer:",
        "Uri-Args:",
        /*[WSI_TOKEN_MUXURL]  =*/ "MuxURL",
      };

      //printf("found prot in http filter callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
      if(!pss->session)
      {
        lsession_uid++;
        node *session_uid_value = node_GetItemByKey(session_uid,"value");
        node_SetSint32(session_uid_value,lsession_uid);
        lsessions_num++;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
        //node *session_privates = node_GetItemByKey(pss->session,"privates");
        //set_obj_int(session_privates,"is_http",1);
      }
      //printf("filter sess:%x\n",pss->session);


      for(n=0;n<(int)(sizeof(token_names)/sizeof(token_names[0]));n++) 
      {
        if (!lws_hdr_total_length(wsi, n))
          continue;
        char *cookies = (char*)malloc(512);
        memset(cookies,0,512);
        lws_hdr_copy(wsi,cookies,511,n);
        //printf("header:%s = [%s]\n",token_names[n],cookies);
        //fflush(stdout);
        if(pss->session && !strcmp("Cookie:",token_names[n]))
        {
          //printf("cookie found:%s = [%s]\n",token_names[n],cookies);
          //fflush(stdout);
          node *base_class = get_base_class(state);
          node *cookie_value = create_class_instance(base_class);
          set_obj_string(cookie_value,"name","cookie");
          set_obj_string(cookie_value,"value",cookies);
          add_member(pss->session,cookie_value);
          inc_obj_refcount(cookie_value);
        }
        free(cookies);
      }
      }
    break;

    case LWS_CALLBACK_HTTP_WRITEABLE: 
    case LWS_CALLBACK_SERVER_WRITEABLE:
      {
        //node_PrintTree(pss->session);
        node *message = get_member(pss->session,"message");
        node *session_privates = node_GetItemByKey(pss->session,"privates");
        node *http_only = node_GetItemByKey(session_privates,"is_http");

        while(message)
        {
          //node *session_id = get_member(pss->session,"id");
          //node *session_id_value = node_GetItemByKey(session_id,"value");
          node *message_value = node_GetItemByKey(message,"value");
          unsigned char *me = NULL;
          unsigned long me_len = 0;
          if(node_GetType(message_value)==NODE_TYPE_STRING)
          {
            me = (unsigned char*)node_GetString(message_value);
            me_len = strlen((char*)me);
          }
          else if(node_GetType(message_value)==NODE_TYPE_BINARY)
          {
            me = (unsigned char*)node_GetBinary(message_value);
            me_len = node_GetBinaryLength(message_value);
          }
          //printf("sending message now: [%s] to: %d\n",me,node_GetSint32(session_id_value));
          //fflush(stdout);
          unsigned char *buf = (unsigned char*)malloc(LWS_SEND_BUFFER_PRE_PADDING + me_len + LWS_SEND_BUFFER_POST_PADDING);
          memcpy(buf+LWS_SEND_BUFFER_PRE_PADDING,me,me_len);

          if(http_only)
            //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_HTTP);
            n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_HTTP);
          else
            //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_TEXT);
            n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_TEXT);
          free(buf);
          if(n<0)
          {
            printf("ERROR %d writing to socket, hanging up\n", n);
            return(1);
          }
          if(n<(long)me_len)
          {
            printf("Partial write\n");
            return(-1);
          }
          //node_FreeTree(pss->message);
          remove_member(pss->session,message);
          dec_obj_refcount(message);
          //printf("removing message from queue:%x (%d)\n",message,get_obj_refcount(message));
          add_garbage(state,message);
          message = get_member(pss->session,"message");          
        }
        if(http_only)
        {
          //if(lws_http_transaction_completed(wsi))
          //{
            //printf("removing http session num:%d\n",lsessions_num);
            lsessions_num--;
            node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
            node_SetSint32(sessions_num_value,lsessions_num);
            delete_session(state,sessions,pss->session);
            pss->session = NULL;
            //printf("removed http\n");
              return -1;
            //return(-1);
          //}
          //else
          //  libwebsocket_callback_on_writable(context, wsi);
        }
      }
      break;

    case LWS_CALLBACK_ESTABLISHED:
      if(found_prot)
      {
        //printf("found prot in establish callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
        if(!pss->session)
        {
          lsession_uid++;
          node *session_uid_value = node_GetItemByKey(session_uid,"value");
          node_SetSint32(session_uid_value,lsession_uid);
          lsessions_num++;
          node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
          node_SetSint32(sessions_num_value,lsessions_num);
          pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
        }
        if(daemon_obj)
        {
          node *connect_handler = get_member(daemon_obj,"connect_handler");
          if(connect_handler)
          {
            connect_handler = resolve_object(state,connect_handler);
            node *parameters = create_obj("parameters");
            node *base_class = get_base_class(state);
      
            node *prot_value = create_class_instance(base_class);
            set_obj_string(prot_value,"name","protocol");
            set_obj_string(prot_value,"value",get_obj_name(found_prot));
            node_AddItem(parameters,prot_value);
            inc_obj_refcount(prot_value);

            node_AddItem(parameters,pss->session);
            inc_obj_refcount(pss->session);
            node_AddItem(parameters,sessions);
            inc_obj_refcount(sessions);
            node *tmp_parent = node_GetParent(connect_handler);
            node *bmembers = node_GetItemByKey(block,"members");
            node_SetParent(connect_handler,bmembers);
            node *ret_obj = execute_obj(state,connect_handler,block,parameters,True,False);//,True);resolve
            node_SetParent(connect_handler,tmp_parent);
            dec_obj_refcount(prot_value);
            add_garbage(state,prot_value);
            dec_obj_refcount(pss->session);
            dec_obj_refcount(sessions);
            node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
            if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
            {
            }
          }
        }
      }
      break;

    case LWS_CALLBACK_CLOSED_HTTP:
    break;
    
    case LWS_CALLBACK_CLOSED:
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
      if(found_prot)
      {
        //printf("found prot in closed callback : uid:%d,num:%d (sess:%x)\n",lsession_uid,lsessions_num,pss->session);
        if(daemon_obj)
        {
        //printf("closed: found daemon_obj\n");
          node *disconnect_handler = get_member(daemon_obj,"disconnect_handler");
          if(disconnect_handler)
          {
            //printf("disc found\n");
            disconnect_handler = resolve_object(state,disconnect_handler);
            node *parameters = create_obj("parameters");
            node *base_class = get_base_class(state);
      
            node *prot_value = create_class_instance(base_class);
            set_obj_string(prot_value,"name","protocol");
            set_obj_string(prot_value,"value",get_obj_name(found_prot));
            node_AddItem(parameters,prot_value);
            inc_obj_refcount(prot_value);

            node_AddItem(parameters,pss->session);
            inc_obj_refcount(pss->session);
            node_AddItem(parameters,sessions);
            inc_obj_refcount(sessions);
            node *tmp_parent = node_GetParent(disconnect_handler);
            node *bmembers = node_GetItemByKey(block,"members");
            node_SetParent(disconnect_handler,bmembers);
            node *ret_obj = execute_obj(state,disconnect_handler,block,parameters,True,False);//,True);resolve
            node_SetParent(disconnect_handler,tmp_parent);
            dec_obj_refcount(prot_value);
            add_garbage(state,prot_value);
            dec_obj_refcount(pss->session);
            dec_obj_refcount(sessions);
            node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
            if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
            {
            }
          }
        }
        lsessions_num--;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        delete_session(state,sessions,pss->session);
        pss->session = NULL;
        //printf("disconnected\n");
      }
      else 
      {
        printf("closed connection without prot found\n");
        if(pss->session)
          printf("but a session was found\n");
      }
      break;

    case LWS_CALLBACK_RECEIVE:
      if(len>1024) 
      { //TODO use some variable
      lwsl_err("Server received packet bigger than %u, hanging up\n", 1024);
      return(1);
      }
      if(found_prot)
      {
      node *parameters = create_obj("parameters");
      node *base_class = get_base_class(state);
      
      node *prot_value = create_class_instance(base_class);
      set_obj_string(prot_value,"name","protocol");
      set_obj_string(prot_value,"value",get_obj_name(found_prot));
      node_AddItem(parameters,prot_value);
      inc_obj_refcount(prot_value);

      char *msg = str_CreateEmpty();
      msg = str_AddChars(msg,in,len);
      node *msg_value = create_class_instance(base_class);
      set_obj_string(msg_value,"name","message");
      set_obj_string(msg_value,"value",msg);
      node_AddItem(parameters,msg_value);
      inc_obj_refcount(msg_value);
      free(msg);

      /*node *session_value = create_class_instance(base_class);
      reset_obj_refcount(session_value);
      add_garbage(state,session_value);
      set_obj_string(session_value,"name","session_id");
      set_obj_int(session_value,"value",lsession_uid);
      set_obj_int(session_value,"item_index",2);
      node_AddItem(parameters,session_value);
      */
      node_AddItem(parameters,pss->session);
      inc_obj_refcount(pss->session);
      //node_AddItem(parameters,daemon_obj);
      //inc_obj_refcount(daemon_obj);

      node_AddItem(parameters,sessions);
      inc_obj_refcount(sessions);

      //printf("recv callback\n");
      //fflush(stdout);
      node *tmp_parent = node_GetParent(found_prot);
      node *bmembers = node_GetItemByKey(block,"members");
      node_SetParent(found_prot,bmembers);

      node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve
      node_SetParent(found_prot,tmp_parent);
      //printf("recv callback finished\n");
      //fflush(stdout);

      dec_obj_refcount(msg_value);
      dec_obj_refcount(prot_value);
      add_garbage(state,msg_value);//TODO check if "just survives"
      add_garbage(state,prot_value);

      dec_obj_refcount(pss->session);
      dec_obj_refcount(sessions);
      //dec_obj_refcount(daemon_obj);
      //printf("recv gc\n");
      //fflush(stdout);
      //node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
      //char *me = node_GetString(ret_obj_value);
      //printf("returned string:[%s]\n",me);
      node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
      if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
      {
        //printf("returning message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value)));
        //node *ret_obj_copy = node_CopyTree(ret_obj,True,True);
        node *ret_obj_copy = copy_class(ret_obj);
        //reset_obj_refcount(ret_obj_copy);
        set_obj_string(ret_obj_copy,"name","message");
        add_member(pss->session,ret_obj_copy);
        inc_obj_refcount(ret_obj_copy);
        //set_obj_string(ret_obj,"name","message");
        //add_member(pss->session,ret_obj);
        //inc_obj_refcount(ret_obj);
      }
      libwebsocket_callback_on_writable(context, wsi);
      }
      break;
    default:
      break;
  }

  return(0);
}
Exemple #5
0
bool VirtualFunctionCallAnalyzer::analyze(CallInformationPtr &call_info) {

  // Example code:
  //
  // A: mov edx, [ecx+4]
  // B: mod edi, [edx+8]
  // C: call edi
  //
  // Answer:
  //   Virtual, obj_ptr=X, vtable_ptr=Y, object_offet = 4, vtable_offset=8

  // 1. Find the abstract access for the vfunc pointer in the call instruction.
  // 2. Get the instruction that that defined the vfunc pointer.
  // 3. Find the abstract access that read the vfunc pointer.
  // 4. Extract the variable and constant portions from the vtable access.
  // 5. Find the abstract access that read the vtable pointer.
  // 6. Find the instruction that defined the vtable pointer.
  // 7. Find the abstract acccess that read the vtable pointer.
  // 8. Extract the variable and constant portions from the object access.

  GDEBUG << "Evaluating possible virtual call: " << debug_instruction(call_insn) << LEND;

  // reset the CallInformationPtr???
  call_info.reset();

  const DUAnalysis& du = pdg->get_usedef();

  // We're looking for the register or address that was read in the call insn
  const AbstractAccessVector* reads = du.get_reads(call_insn);
  // If there were no reads in the call, something's really wrong.
  if (reads == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no read of target." << LEND;
    return false;
  }

  // Step 1. Find the abstract access that obtained the virtual function pointer.  This is the
  // read that that was not the stack pointer register.
  const AbstractAccess* vfunc_aa = NULL;
  BOOST_FOREACH(const AbstractAccess& aa, *reads) {
     if (aa.is_mem()) {
        vfunc_aa = &aa;
     }
     else {
        // ESP should really be obtained from the architecture depdenent layer (e.g. RSP).
        // EIP and RIP are never in the reads/writes array (because they always are).
        if (aa.reg_name() == "esp") continue;
        vfunc_aa = &aa;
     }
  }

  if (vfunc_aa == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no read of target." << LEND;
    return false;
  }

  // Step 2. Find the instruction that defined the virtual function call.  This is the
  // instruction that references the virtual function table, including the virtual function
  // table and the offset into it.  A little trick supports calls of the form "call [reg+X]".
  SgAsmX86Instruction* vtable_insn = NULL;
  // If the instruction was "call [reg+X]"
  if (vfunc_aa->is_mem()) {
    vtable_insn = call_insn;
  }
  // If the instruction was "call reg"
  else {
    // The vtable instruction will be the latest writer to the register in the call instruction.

    // If there are no latest writers at all, fail.
    if (vfunc_aa->latest_writers.size() == 0) {
      GDEBUG << "Non virtual: " << debug_instruction(call_insn)
             << " - no latest write for vfunc_aa=" << *vfunc_aa << LEND;
      return false;
    }
    vtable_insn = isSgAsmX86Instruction(*(vfunc_aa->latest_writers.begin()));
    if (vtable_insn == NULL) {
      GDEBUG << "Non virtual: " << debug_instruction(call_insn)
             << " - latest write not an X86 insn vfunc_aa=" << *vfunc_aa << LEND;
      return false;
    }
  }

  GDEBUG << "Possible vtable instruction: " << debug_instruction(vtable_insn) << LEND;

  // Step 3.  Find the abstract access that read the virtual function pointer from the memory
  // address in the virtual function table.
  TreeNodePtr vfunc_ptr = vfunc_aa->value->get_expression();
  const AbstractAccess* vtable_aa = find_memory_access(vtable_insn, du, vfunc_ptr);
  // If we couldn't find where the vtable was written, fail.
  if (vtable_aa == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no vtable abstract access vfunc_ptr=" << *vfunc_ptr << LEND;
    return false;
  }

  // All valid vtable accesses must be memory reads.
  if (!vtable_aa->is_mem()) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - vtable access was not a memory read" << *vtable_aa << LEND;
    return false;
  }

  // Step 4.  Extract the variable and constant portions from the vtable abstract access
  // providing the vtable pointer and the offset into the vtable.
  TreeNodePtr vtable_expr = vtable_aa->memory_address->get_expression();
  AddConstantExtractor foace = AddConstantExtractor(vtable_expr);

  // There must be a variable portion for this to be a virtual function call.
  TreeNodePtr vtable_ptr = foace.variable_portion;
  if (vtable_ptr == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no variable portion in vtable_expr=" << *vtable_expr << LEND;
    return false;
  }

  // Virtual function table offsets are not allowed to be negative, but they can be zero.
  int64_t vtable_offset = foace.constant_portion;
  if (vtable_offset < 0) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - negative vtable offset in vtable_expr=" << *vtable_expr << LEND;
    return false;
  }

  // Report the likely virtual function table pointer and offset into the table.
  GDEBUG << "Possible virtual function table pointer: " << *vtable_ptr << LEND;
  GDEBUG << "Possible virtual function offset in vtable: " << vtable_offset << LEND;

  // Step 5.  Find the abstract access where the vtable pointer was read.

  // It's unclear what we should do when vtable_ptr is an ITE expression.  Currently,
  // find_memory_access() uses can_be_equal() which isn't perfect.  Cory thought it was
  // unlikely that such a situation would arise in real virtual calls, but there are some
  // examples in Lite/poly.exe involving std::basic_char_streambuf.  More investigation and
  // work is required here, probably involving an approach that might result in multiple valid
  // resolutions of the call.  For now, this is good enough, and is close to what we did
  // previously.
  const AbstractAccess* vtable_ptr_aa = find_memory_access(vtable_insn, du, vtable_ptr);
  // If the abstract access was NULL, then there's clearly no latest writer.
  if (vtable_ptr_aa == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no writer for vtable_ptr=" << *vtable_ptr << LEND;
    return false;
  }

  // Step 6.  Find the instruction that wrote the value into the vtable pointer.  This is the
  // instruction that references the object pointer and the offset into it.  Perhaps we should
  // be doing something will all of the writers, not just the first one?
  if (vtable_ptr_aa->latest_writers.size() == 0) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no latest write for vtable_aa=" << *vtable_ptr_aa << LEND;
    return false;
  }
  SgAsmX86Instruction* object_insn = isSgAsmX86Instruction(*(vtable_ptr_aa->latest_writers.begin()));
  if (object_insn == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no insn for vtable_ptr_aa=" << *vtable_ptr_aa << LEND;
    return false;
  }

  GDEBUG << "Possible object instruction:" << debug_instruction(object_insn) << LEND;

  // Step 7.  Find the abstract access that read the virtual function table pointer from the
  // memory address in the object.
  const AbstractAccess* object_aa = find_memory_access(object_insn, du, vtable_ptr);
  // If we couldn't find where the object was written, fail.
  if (object_aa == NULL) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - no object abstract access =" << debug_instruction(object_insn) << LEND;
    return false;
  }

  // All reads of the vtable pointer must be from memory (in the object).
  if (!(object_aa->is_mem())) {
    GDEBUG << "Non virtual: " << debug_instruction(call_insn)
           << " - object access not to memory =" << *object_aa << LEND;
    return false;
  }

  // Step 8. We've now got the object pointer expression, but it might be a complicated ITE
  // expression.  To really conmplete step 8, we'll need to invoke the correct logic on each of
  // the possible values.
  SymbolicValuePtr object_sv = object_aa->memory_address;

  GDEBUG << "Possible multi-valued object pointer: " << *object_sv << LEND;

  // There are probably some major changes that can be made to this logic post-NEWWAY!
  if (object_sv->contains_ite()) {
    GDEBUG << "VCall ITE: " << *object_sv << LEND;
    bool matched = false;
    BOOST_FOREACH(const TreeNodePtr& tn, object_sv->get_possible_values()) {
      GDEBUG << "VCall ITE this-ptr: " << *tn << LEND;
      // The most common non OO condition is the NULL pointer.
      if (tn->isNumber() && tn->toInt() == 0) {
        GDEBUG << "Skipping NULL pointer as possible object pointer." << LEND;
        continue;
      }

      if (resolve_object(tn, vtable_ptr, vtable_offset, call_info)) matched = true;
    }
    if (matched) return true;
  }