Logo Search packages:      
Sourcecode: radare version File versions

flags.c

/*
 * Copyright (C) 2006, 2007, 2008
 *       pancake <youterm.com>
 *
 * radare is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * radare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with radare; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "main.h"
#include "radare.h"
#include "flags.h"
#include "utils.h"
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct list_head flags;
static int flag_ptr = -1;

#define FLAG_SPACES 32
// XXX optimize... FLAG SPACES MUST BE A LINKED LIST TOO!
static struct flags_spaces_t {
      const char *name;
} flag_spaces[FLAG_SPACES];

static u64 flag_from_i = 0;
int flag_space_idx = -1;
int flag_space_idx2 = -1;

void flag_from(const char *str)
{
      if (str[0]) {
            flag_from_i = get_math(str);
      } else
            cons_printf("0x%08llx\n", flag_from_i);
}

void flag_init()
{
      INIT_LIST_HEAD(&flags);
}

const const char *flag_space_get(int idx)
{
      if (idx==-1)
            return nullstr;
      if (idx>255||flag_spaces[idx].name[0]=='\0')
            return nullstr;
      return flag_spaces[idx].name;
}

void flag_help()
{
      eprintf("Usage: f[?|d|-] [flag-name]\n"
      " fortune      ; show fortune message! :D\n"
      " ff [addr]    ; flag from this address\n"
      " fb [addr]    ; increment flag offset with new base address\n"
      " fd           ; print flag delta offset\n"
      " fc cmd       ; set command to be executed on flag at current seek\n"
      " fi pfx1 pfx2 ; flag interpolation between hit0_ and hit1_ for.example\n"
      " fg text[*]   ; grep for flag or all flags matching text* (like f | grep foo)\n"
      " fh text[*]   ; used for \"section_\"\n"
      " fn name      ; new flag (ignores dupped names)\n"
      " fu name      ; new flag if no one exists here (shy)\n"
      " fm name      ; move flag to another flag space\n"
      " fN [name]    ; Set a numered flag as name_%%d. No arg resets the counter\n"
      " fs spacename ; create/list/switch flag spaces\n"
      " fr old new   ; rename a flag or more with '*'\n"
      " f sym.main   ; flag current offset as sym.main\n"
      " f foo @ 0x23 ; flag 0x23 offset as foo\n"
      " f foo 12 0x23; the same as above, but faster (size=12, off=0x23)\n"
      " f -sym.main  ; remove sym.main\n"
      " f -*         ; remove all flags\n"
      " f -sym.*     ; remove all flags starting with 'sym.'\n");
}

int flag_interpolation(const char *from, const char *to)
{
      int ret = 0;
      u64 tmp = 0;
      const char *str = NULL;
      struct list_head *pos, *pos2;

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            tmp = 0;
            if (!memcmp(from, flag->name, strlen(from))) {
                  list_for_each(pos2, &flags) {
                        flag_t *flag2 = (flag_t *)list_entry(pos2, flag_t, list);
                        if (!memcmp(from, flag->name, strlen(to))) {
                              if (flag2->offset>flag->offset && (tmp == 0 || flag2->offset < tmp)) {
                                    tmp = flag2->offset;
                                    str = flag2->name;
                              }
                        }
                  }

                  if (tmp != 0) {
                        printf("%s (0x%08llx) -> %s (0x%08llx)   ; size = %lld\n",
                              flag->name, flag->offset, str, tmp, tmp-flag->offset);
                  }
            }
      }
      return ret;
}

flag_t *flag_get_by_addr(u64 addr);
void flag_rebase(const char *text)
{
      flag_t *f = flag_get_by_addr(config.seek);
      if (f) {
            u64 base;
            if (text[0]=='-')
                  f->offset -= get_math(text+1);
            else f->offset += get_math(text);
//printf("REBASING to 0x%08llx\n", f->offset);
      } //else {
      //    eprintf("No flag found at 0x%08llx this address\n", config.seek);
      //}
}

void flag_cmd(const char *text)
{
      flag_t *flag = flag_by_offset(config.seek);
      if (text == NULL || text[0] == '\0' || text[0]=='?') {
            cons_printf("Usage: fc <cmd> @ <offset>\n");
            cons_printf("   > fc pd 20 @ 0x8049104\n");
      } else
      if (flag != NULL) {
            flag->cmd = estrdup((char*)flag->cmd, text);
            cons_printf("flag_cmd(%s) = '%s'\n", flag->name, text);
      }
}

flag_t *flag_get_by_addr(u64 addr)
{
      struct list_head *pos;
      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (flag->offset == addr)
                  return flag;
      }
      return NULL;
}

flag_t *flag_get_i(int id)
{
      struct list_head *pos;
      int i = 0;

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (i++ == id)
                  return flag;
      }

      return NULL;
}

void flag_show(flag_t *flag, int cmd_flag)
{
      // TODO: use flags[i]->format over flags[i]->data and flags[i]->length
      cons_printf("0x%08llx\t %lld\t %s\n",
            flag->offset, flag->length, flag->name);
      if (cmd_flag && flag->cmd!=NULL && *flag->cmd) {
            u64 seek = config.seek;
            radare_seek(flag->offset, SEEK_SET);
            radare_cmd_raw(flag->cmd, 0);
            radare_seek(seek, SEEK_SET);
            cons_newline();
      }
}

void flag_grep_help()
{
      eprintf("Usage: fg[n|p] [string]\n");
      eprintf("  fg       - List flags matching a string\n");
      eprintf("  fgn, fgp - List next/previous flag matching string\n");
      eprintf("  fgn imp.\n");
}

void flag_grep_np(const char *str, u64 addr, int next)
{
      struct list_head *pos;
      flag_t *fag = NULL;
      u64 newaddr;

      newaddr  = next?0:0xffffffffffffffffLL;

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (config.interrupted) break;
            if (next) {
                  if (str_grep(flag->name, str)) {
                        if (flag->offset < addr && flag->offset > newaddr) {
                              newaddr = flag->offset;
                              fag = flag;
                        }
                  }
            } else {
                  if (str_grep(flag->name, str)) {
                        if (flag->offset > addr && flag->offset < newaddr) {
                              newaddr = flag->offset;
                              fag = flag;
                        }
                  }
            }
      }

      if (fag)
            cons_printf("0x%08llx %s\n", fag->offset, fag->name);
}

// TODO: USE GLOB OR SO...
void flag_grep(const char *grepstr) // TODO: add u64 arg to grep only certain address
{
      int cmd_flag = config_get_i("cmd.flag"); /* boolean */
      char *grep;
      char *mask;
      struct list_head *pos;

      grep = alloca(strlen(grepstr)+1);
      strcpy(grep, grepstr);
      mask = strchr(grep, '*');

      if (mask)
            mask[0]='\0';

      // TODO: Use str_grep here
      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (config.interrupted) break;
            if (mask) {
                  if (strstr(flag->name, grep))
                        flag_show(flag, cmd_flag);
            } else {
                  if (!strcmp(flag->name, grep))
                        flag_show(flag, cmd_flag);
            }
      }
}

flag_t *flag_get(const char *name)
{
      struct list_head *pos;
      if (name==NULL || (name[0]>='0'&& name[0]<='9'))
            return NULL;
      list_for_each_prev(pos, &flags) {
            flag_t *flag = list_entry(pos, flag_t, list);
            if (!strcmp(name, flag->name))
                  return flag;
      }
      return NULL;
}

u64 flag_get_addr(const char *name)
{
      flag_t *foo = flag_get(name);
      if (foo)
            return foo->offset;
      return 0;
}

u64 flag_delta_between(u64 from, u64 to)
{
      struct list_head *pos;

      list_for_each(pos, &flags) {
            flag_t *flag = list_entry(pos, flag_t, list);
            if (flag->offset > from && flag->offset <= to) {
                  return flag->offset - from;
            }
      }
      return 0;
}

flag_t *flag_get_next(int delta)
{
      flag_t *nice = NULL;
      struct list_head *pos;

      if (delta == 1) {
            list_for_each(pos, &flags) {
                  flag_t *flag = list_entry(pos, flag_t, list);
                  if (flag->offset > config.seek)  {
                        if (nice) {
                              if (flag->offset < nice->offset)
                                    nice = flag;
                        } else {
                              nice = flag;
                        }
                  }
            }
      } else { //if (delta == -1) {
            list_for_each(pos, &flags) {
                  flag_t *flag = list_entry(pos, flag_t, list);
                  if (flag->offset < config.seek)  {
                        if (nice) {
                              if (flag->offset > nice->offset)
                                    nice = flag;
                        } else {
                              nice = flag;
                        }
                  }
            }
      }
      return nice;
}

flag_t *flag_get_reset()
{
      flag_ptr = 0;
      return flag_get_next(flag_ptr);
}

// TODO : use flag size
int flags_between(u64 from, u64 to)
{
      int n=0;
      struct list_head *pos;
      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (flag->offset >= from && flag->offset <= to)
                  n++;
      }
      return n;
}

int flag_rename(char *foo, char *bar)
{
      int n = 0;
      int ini = 0;
      int end = strlen(foo);
      int sz = end-ini;
      int glob_end = 0;
      struct list_head *pos;

      if (foo[0]=='*')
            ini = 1;
      if (foo[end-1]=='*') {
            glob_end = 1;
            foo[end]='\0';
            sz--;
            end --;
      }

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (ini) {
                  char *str = strstr(flag->name, foo+ini);
                  if (str) {
                        str = strdup(str);
                        sprintf(flag->name, "%s%s", bar, str);
                        free(str);
                  }
            } else
            if (!_strnstr(foo+ini, flag->name, sz)) {
                  if (glob_end) {
                        char *str = strdup(flag->name+sz);
                        sprintf(flag->name, "%s%s", bar, str);
                        free(str);
                  } else {
                        if (flag->name[end]=='\0')
                              strcpy(flag->name, bar);
                  }
                  n++;
            }
      }
      return n;
}

int flag_rename_str(char *text)
{
      int n = 0;
      char *arg = text?strchr(text, ' '):NULL;
      if (arg) {
            arg[0]='\0';
            n = flag_rename(text, arg+1);
            cons_printf("%d flags renamed\n", n);
            arg[0]=' ';
      } else {
            cons_printf("Usage: fr old-name new-name\n");
            cons_printf("> fr hit0_* hit_search\n");
      }
      return n;
}

/* deprecated ?!?! */
void flags_setenv()
{
      int i;
      char var[1024];
      char *ptr = environ[0];

      for(i=0;(ptr = environ[i]);i++) {
            if (config.interrupted) break;
            if (!memcmp("flag_", environ[i], 5)) {
                  int len = strchr(environ[i],'=') - environ[i];
                  if (len>0) {
                        memset(var, '\0', 1024);
                        memcpy(var, environ[i], len);
                        unsetenv(var);
                  }
            }
      }
}

flag_t *flag_by_offset(u64 offset)
{
      struct list_head *pos;

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (flag->offset == offset)
                  return flag;
            if (config.interrupted) break;
      }

      return NULL;
}

const char *flag_name_by_offset(u64 offset)
{
      struct list_head *pos;

      //if (offset > config.vaddr)
      offset=offset-config.paddr+config.vaddr;
      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (flag->offset == offset)
                  return flag->name;
            if (config.interrupted) break;
      }

      return nullstr;
}

/* TODO
 * idx = -1 : return all flags at given seek separated by comma
 * idx =  0 : just return the first one found
 * idx =  1 : continue searching for flag after the first one
 */
int string_flag_offset(char *buf, u64 seek, int idx)
{
      int delta = (int)config_get_i("cfg.delta");
      flag_t *ref = NULL;
      struct list_head *pos;

      buf[0]='\0';

      list_for_each(pos, &flags) {
            if (config.interrupted) break;
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (flag->offset == seek) {
                  ref = flag;
                  if (idx==-1) {
                        if (buf[0])
                              strcat(buf, ",");
                        strcat(buf, ref->name);
                  } else break;
            } else
            if (!flag->offset)
                  continue;
            else
            if (flag->offset <= seek && (!ref || flag->offset > ref->offset))
                  ref = flag;
      }
      if (idx==-1)
            return 1;

      if (ref) {
            long ul = (seek-ref->offset);
            if (ul == 0)
                  strcpy(buf, ref->name);
            else
            if (ul >-delta && ul<delta)
                  sprintf(buf, "%s+0x%lx", ref->name, ul);
            else return 0;
            return 1;
      }

      return 0;
}

void print_flag_offset(u64 seek)
{
      char buf[256];

      if ( string_flag_offset(buf, seek, -1) )
            cons_strcat(buf);
}

void flag_do_empty(flag_t *flag)
{
      if (flag == NULL)
            return;

      flag->name[0]='\0';
}

int flag_is_empty(flag_t *flag)
{
      if (flag == NULL || flag->name[0]=='\0')
            return 1;

      return 0;
}

void flag_list(char *arg)
{
      struct list_head *pos;

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (config.interrupted) break;

            /* filter per flag spaces */
            if ((flag_space_idx != -1) && (flag->space != flag_space_idx))
                  continue;

            /* TODO: use grep here */
            //if (!arg || !*arg || strstr(flag->name, arg)
            flag_show(flag, 0);
#if 0
            cons_printf("%03d 0x%08llx %4lld %s",
                  i++, flag->offset, flag->length, flag->name);
#endif
      // TODO: use flags[i]->format over flags[i]->data and flags[i]->length
      }
}

void flag_clear_by_addr(u64 seek)
{
      struct list_head *pos;

      _polla:
      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if (config.interrupted) break;
            if (flag->offset == seek) {
                  list_del(&flag->list);
                  free(flag);
                  pos = flags.prev;
                  goto _polla;
            }
      }
}

void flag_space_move(const char *name)
{
      flag_t *f;

      if (name == NULL || name[0] == '\0' || name[0]=='?') {
            eprintf("Usage: fm <flag_name>  - moves the selected flag to the current flagspace\n");
      } else {
            f = flag_get(name);
            f->space = flag_space_idx;
      }
}

void flag_space_set(const char *name)
{
      int i;
      for(i=0;i<FLAG_SPACES;i++) {
            if (flag_spaces[i].name != NULL)
            if (!strcmp(name, flag_spaces[i].name)) {
                  flag_space_idx = i;
                  return;
            }
      }
      /* not found */
      for(i=0;i<FLAG_SPACES;i++) {
            if (flag_spaces[i].name == NULL) {
                  flag_spaces[i].name = strdup(name);
                  flag_space_idx = i;
                  break;
            }
      }
}

void flag_space_cleanup()
{
      /* TODO: remove all flag spaces with 0 flags */
}

void flag_space_remove(const char *name)
{
      struct list_head *pos;
      int i;

      for(i=0;i<FLAG_SPACES;i++) {
            if (flag_spaces[i].name && ((!strcmp(name, flag_spaces[i].name)) || (name[0]=='*'))) {
                  free((void *)flag_spaces[i].name);
                  flag_spaces[i].name = NULL;
                  if (i == flag_space_idx) {
                        flag_space_idx = -1;
                  }

                  /* unlink related flags */
                  list_for_each(pos, &flags) {
                        flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
                        if (config.interrupted) break;
                        if (flag->space == i)
                              flag->space = -1;
                  }
                  break;
            }
      }
}

void flag_space_list()
{
      int i,j = 0;
      for(i=0;i<FLAG_SPACES;i++) {
            if (flag_spaces[i].name)
                  cons_printf("%02d %c %s\n", j++,
                        (i==flag_space_idx)?'*':' ', flag_spaces[i].name);
      }
}

void flag_space_init()
{
      static int init = 0;
      int i;
      if (init)
            return;
      init = 1;
      for(i=0;i<FLAG_SPACES;i++)
            flag_spaces[i].name = NULL;
}

void flag_space(const char *name)
{
      flag_space_init();

      if (name[0]==' ')
            name = name+1;

      switch(name[0]) {
      case '\0':
            flag_space_list();
            break;
      case '*':
            flag_space_idx = -1;
            break;
      case '-':
            flag_space_remove(name+1);
            break;
      case '?':
            cons_printf("Usage: fs [name]\n");
            cons_printf("  > fs regs     - create/switch to 'regs' flagspace\n");
            cons_printf("  > fs -regs    - remove 'regs' space\n");
            cons_printf("  > fs *        - select all spaces\n");
            cons_printf("  > fs          - list all flag spaces\n");
            break;
      default:
            flag_space_set(name);
            break;
      }
}

void flag_remove(const char *name)
{
      struct list_head *pos;
      char *str, *mask;
      int l;
      int found = 0;

      if (name == NULL || *name == '\0')
            return;

      str = strdup(name); // TODO: strdup only when no mask is used
      mask = strchr(str, '*');

      if (mask) {
            mask[0]='\0';
            l = strlen(str);
            list_for_each(pos, &flags) {
                  flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
                  if (config.interrupted) break;
                  if (!memcmp(str, flag->name, l)) {
                        list_del(&(flag->list));
                        free(flag);
                        pos = flags.next;
                        continue;
                  }
            }
      } else {
            __restart2:
            list_for_each(pos, &flags) {
                  flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
                  if (config.interrupted) break;
                  if (!strcmp(name, flag->name)) {
                        list_del(&(flag->list));
                        free(flag);
                        found = 1;
                        goto __restart2;
                  }
            }
      }

      if (!found)
            flag_clear_by_addr(get_math(str));

      free(str);
}

int flag_qsort_compare(const void *a, const void *b)
{
      if (a == NULL)
            return -1;
      if (b == NULL)
            return 1;
      return strcmp(b, a);
}

int flag_is_valid_char(const char ch)
{
      switch(ch) {
      case '*':
      case '/':
      case '+':
      case '-':
      case ' ':
      case '\n':
      case '\t':
      case '[':
      case '@':
            return 0;
      default:
            if (((ch >= '0') && (ch <= '9')))
                  return 1;
            if (!is_printable(ch))
                  return 0;
      }
      return 1;
}

#define MAX_FLAG_LEN 20
int flag_filter_name(char *name)
{
      int i;
      char *oname;
      for(;*name==' ';name=name+1);
      oname=name;
      for(i=0;*name!='\0'; name = name +1,i++) {
            if (i>MAX_FLAG_LEN) {
                  name[0]='\0';
                  break;
            }
            if (!flag_is_valid_char(*name)) {
                  strcpy(name, name+1);
                  name = name -1;
            }
      }
      return flag_is_valid_name(oname);
}

int flag_is_valid_name(const char *name)
{
      if (name[0]=='\0')
            return 0;
      for(;*name!='\0'; name = name +1) {
            if (!flag_is_valid_char(*name))
                  return 0;
      }
      return 1;
}

int flag_set(const char *name, u64 addr, int dup)
{
      const char *ptr;
      flag_t *flag = NULL;
      struct list_head *pos;

      if (!dup) {
            /* show flags as radare commands */
            if (name[0]=='*' && name[1]=='\0') {
                  list_for_each(pos, &flags) {
                        flag_t *f = (flag_t *)list_entry(pos, flag_t, list);
                        if (config.interrupted) break;
                        cons_printf("f %s @ 0x"OFF_FMTx"\n", f->name, f->offset);
                  }
                  return 2;
            } else {
                  if (!flag_is_valid_name(name)) {
                        eprintf("invalid flag name '%s'.\n", name);
                        return 2;
                  }

                  for (ptr = name + 1; *ptr != '\0'; ptr = ptr +1) {
                        if (!is_printable(*ptr)) {
                              eprintf("invalid flag name\n");
                              return 2;
                        }
                  }
            }
      }

      list_for_each(pos, &flags) {
            flag_t *f = (flag_t *)list_entry(pos, flag_t, list);
            if (config.interrupted) break;
            if (!strcmp(f->name, name)) {
                  if (dup) {
                        /* ignore dupped name+offset */
                        if (f->offset == addr)
                              return 1;
                  } else {
                        flag = f;
                        f->offset = addr + flag_from_i;
                        f->length = config.block_size;
                        f->format = last_print_format;
/*
                        memcpy(f->data, config.block, 
                              (config.block_size>sizeof(flags[i]->data))?
                              sizeof(f->data):config.block_size);

*/
                        return 1;
                  }
            }
      }

      if (flag == NULL) {
            flag = malloc(sizeof(flag_t));
            memset(flag,'\0', sizeof(flag_t));
            list_add_tail(&(flag->list), &flags);
            if (flag==NULL)
                  return 1;
      }

      strncpy(flag->name, name, FLAG_BSIZE);
      flag->name[FLAG_BSIZE-1]='\0';
      flag->offset = addr + flag_from_i;
      flag->space = flag_space_idx;
      flag->length = config.block_size;
      flag->format = last_print_format;
      flag->cmd = NULL;
#if 0
      // XXX store data in flags is ugly!
      if (radare_read(0)!=-1)
      memcpy(flag->data, config.block, 
            (config.block_size>sizeof(flag->data))?
            sizeof(flag->data):config.block_size);
#endif

      // TODO qsort(flags, nflags, sizeof(flag_t*), flag_qsort_compare);

      return 0;
}

int flag_set_undef(const char *name, u64 addr, int dup)
{
      flag_t *flag = flag_get_by_addr(addr);
      if (flag == NULL || (strlen(flag->name)<4))
            return flag_set(name, addr, dup);
      return 0;
}

/* used to get section name for disasembly */
const char *flag_get_here_filter(u64 at, const char *str)
{
      static u64 sec_start=0, sec_end=0;
      static char sec_str[64];
      struct list_head *pos;
      u64 ret = 0;
      u64 nextflag = 0xFFFFFFFFFFFFFFFFFFLL;
      flag_t *f = NULL;

      if (at >=sec_start && at <sec_end) {
            /* ADDED CACHE PAWAH */
            return sec_str;
      }
      sec_str[0]='\0';

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            if ((str[0] && !strstr(flag->name, str)) || strstr(flag->name, "end"))
                  continue;
            
            if (flag->offset < nextflag && flag->offset > at) {
                  nextflag = flag->offset;
            } else
            if (at >= flag->offset && flag->offset > ret) {
                  f = flag;
                  ret = flag->offset;
            }
      }
      if (f == NULL)
            return nullstr;
      sec_start = f->offset;
      sec_end = nextflag;
      strcpy(sec_str, f->name+strlen(str));
      return sec_str;
}

//XXX ugly hack
const char *flag_get_here_filter2(u64 at, const char *str, const char *str2)
{
      static u64 sec_start=0, sec_end=0;
      static char sec_str[64];
      struct list_head *pos;
      u64 ret = 0;
      u64 nextflag = 0xFFFFFFFFFFFFFFFFFFLL;
      flag_t *f = NULL;
      char *s1,*s2,*s=NULL;

      if (at >=sec_start && at <sec_end) {
            /* ADDED CACHE PAWAH */
            return sec_str;
      }
      sec_str[0]='\0';

      list_for_each(pos, &flags) {
            flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
            s1 = strstr(flag->name, str);
            s2 = strstr(flag->name, str2);
            if ((!s1 && !s2) || strstr(flag->name, "_end"))
                  continue;
            
            if (flag->offset < nextflag && flag->offset > at) {
                  nextflag = flag->offset;
            } else
            if (at >= flag->offset && flag->offset > ret) {
                  s = s1?str:str2;
                  f = flag;
                  ret = flag->offset;
            }
      }
      if (f == NULL)
            return nullstr;
      sec_start = f->offset;
      sec_end = nextflag;
      strcpy(sec_str, f->name+((s!=NULL)?strlen(s):0));
      return sec_str;
}

/* TODO: move to visual */
void flags_visual_menu()
{
      char cmd[1024];
      struct list_head *pos;
#define MAX_FORMAT 2
      int format = 0;
      const char *ptr;
      const char *fs = NULL;
      char *fs2 = NULL;
      int option = 0;
      int _option = 0;
      int delta = 7;
      int menu = 0;
      int i,j, ch;
      int hit;

      while(1) {
            cons_gotoxy(0,0);
            cons_clear();
            /* Execute visual prompt */
            ptr = config_get("cmd.vprompt");
            if (ptr&&ptr[0]) {
                  int tmp = last_print_format;
                  radare_cmd_raw(ptr, 0);
                  last_print_format = tmp;
            }

            switch(menu) {
            case 0: // flag space
                  cons_printf("\n Flag spaces:\n\n");
                  hit = 0;
                  for(j=i=0;i<FLAG_SPACES;i++) {
                        if (flag_spaces[i].name) {
                              if (option==i) {
                                    fs = flag_spaces[i].name;
                                    hit = 1;
                              }
                              if( (i >=option-delta) && ((i<option+delta)||((option<delta)&&(i<(delta<<1))))) {
                                    cons_printf(" %c %02d %c %s\n", (option==i)?'>':' ', j, (i==flag_space_idx)?'*':' ', flag_spaces[i].name);
                                    j++;
                              }
                        }
                  }
                  if (!hit && j>0) {
                        option = j-1;
                        continue;
                  }
                  break;
            case 1: // flag selection
                  cons_printf("\n Flags in flagspace '%s'. Press '?' for help.\n\n",
                        flag_spaces[flag_space_idx]);
                  hit = 0;
                  i = j = 0;
                  list_for_each(pos, &flags) {
                        flag_t *flag = (flag_t *)list_entry(pos, flag_t, list);
                        /* filter per flag spaces */
                        if ((flag_space_idx != -1) && (flag->space != flag_space_idx))
                              continue;
                        if (option==i) {
                              fs2 = flag->name;
                              hit = 1;
                        }
                        if( (i >=option-delta) && ((i<option+delta)||((option<delta)&&(i<(delta<<1))))) {
                              cons_printf(" %c  %03d 0x%08llx %4lld %s\n",
                                    (option==i)?'>':' ',
                                    i, flag->offset, flag->length, flag->name);
                              j++;
                        }
                        i++;
                  }
                  if (!hit && i>0) {
                        option = i-1;
                        continue;
                  }
                  cons_printf("\n Selected: %s\n\n", fs2);

                  switch(format) {
                  case 0: sprintf(cmd, "px @ %s", fs2); break;
                  case 1: sprintf(cmd, "pd @ %s", fs2); break;
                  case 2: sprintf(cmd, "pz @ %s", fs2); break;
                  default: format = 0; continue;
                  }
#if 0
                  /* TODO: auto seek + print + disasm + string ...analyze stuff and proper print */
                  cmd[0]='\0';
                  if (strstr(fs2, "str_")) {
                        sprintf(cmd, "pz @ %s", fs2);
                  } else
                  if (strstr(fs2, "sym_")) {
                        sprintf(cmd, "pd @ %s", fs2);
                  } else
                        sprintf(cmd, "px @ %s", fs2);
#endif
                  if (cmd[0])
                        radare_cmd_raw(cmd, 0);
            }
            cons_flush();
            ch = cons_readchar();
            ch = cons_get_arrow(ch); // get ESC+char, return 'hjkl' char
            switch(ch) {
            case 'J':
                  option+=10;
                  break;
            case 'j':
                  option++;
                  break;
            case 'k':
                  if (--option<0)
                        option = 0;
                  break;
            case 'K':
                  option-=10;
                  if (option<0)
                        option = 0;
                  break;
            case 'h':
            case 'b': // back
                  menu = 0;
                  option = _option;
                  break;
            case 'a':
                  switch(menu) {
                  case 0: // new flag space
                        break;
                  case 1: // new flag
                        break;
                  }
                  break;
            case 'd':
                  flag_remove(fs2);
                  break;
            case 'e':
                  /* TODO: prompt for addr, size, name */
                  break;
            case 'q':
                  if (menu<=0) return; menu--;
                  break;
            case '*':
            case '+':
                  radare_set_block_size_i(config.block_size+1);
                  break;
            case '/':
            case '-':
                  radare_set_block_size_i(config.block_size-1);
                  break;
            case 'P':
                  if (--format<0)
                        format = MAX_FORMAT;
                  break;
            case 'p':
                  format++;
                  break;
            case 'l':
            case ' ':
            case '\r':
            case '\n':
                  if (menu == 1) {
                        sprintf(cmd, "s %s", fs2);
                        radare_cmd_raw(cmd, 0);
                        return;
                  }
                  flag_space_set(fs);
                  menu = 1;
                  _option = option;
                  option = 0;
                  break;
            case '?':
                  cons_clear00();
                  cons_printf("\nVt: Visual Track help:\n\n");
                  cons_printf(" q     - quit menu\n");
                  cons_printf(" j/k   - down/up keys\n");
                  cons_printf(" h/b   - go back\n");
                  cons_printf(" l/' ' - accept current selection\n");
                  cons_printf(" a/d/e - add/delete/edit flag\n");
                  cons_printf(" +/-   - increase/decrease block size\n");
                  cons_printf(" p/P   - rotate print format\n");
                  cons_printf(" :     - enter command\n");
                  cons_flush();
                  cons_any_key();
                  break;
            case ':':
                  cons_set_raw(0);
#if HAVE_LIB_READLINE
                  char *ptr = (char *)readline(VISUAL_PROMPT);
                  if (ptr) {
                        strncpy(cmd, ptr, sizeof(cmd));
                        radare_cmd(cmd, 1);
                        //commands_parse(line);
                        free(ptr);
                  }
#else
                  cmd[0]='\0';
                  dl_prompt = ":> ";
                  if (cons_fgets(cmd, 1000, 0, NULL) <0)
                        cmd[0]='\0';
                  //line[strlen(line)-1]='\0';
                  radare_cmd(cmd, 1);
#endif
                  cons_set_raw(1);
                  if (cmd[0])
                        cons_any_key();
                  cons_gotoxy(0,0);
                  cons_clear();
                  continue;
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index