示例#1
0
eresi_Addr lookup_libc_offset(char *libc, char *function)
{
  elfshobj_t *f;
  elfsh_Rela *r;
  elfsh_Sym *s;
  int i;
  char *cmpname;
  f = elfutils_read_elf_file(libc);

  elfshsect_t *dynsym, *strtab;
  dynsym =  elfsh_get_section_by_name(f,".dynsym", NULL, NULL, NULL);

  // lookup strtab
  strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(dynsym->shdr), NULL, NULL);

  // get symbol
  elfsh_Sym *table;
  table = (elfsh_Sym *) dynsym->data;
  eresi_Addr numsym = elfsh_get_section_size(dynsym->shdr)/sizeof(elfsh_Sym);

  char *strs = strtab->data;

  for (i = 0; i < numsym; i++) {
    //look at each entry
    s = &(table[i]);
    cmpname = strs + s->st_name;
    if(strcmp(function, cmpname) == 0){
      return s->st_value;
    }
  }
  return 0;  
}
示例#2
0
文件: map.c 项目: kejiewei/eresi
/**
 * Called from elfsh_fixup_symtab
 * When trying to inject part of the libc, some bss symbols have a wrong sctndx 
 * @param symtab
 * @return
 */
elfshsect_t   *elfsh_fixup_sctndx(elfshsect_t *symtab)
{
  int	        index;
  elfsh_Sym     *sym;
  elfsh_SAddr	offset;
  elfsh_Shdr	*shdr;
  elfshsect_t	*sct;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  //return (symtab); // XXX

  sym = symtab->data;
  shdr = symtab->parent->sht + symtab->index;

  for (index = 0; index < shdr->sh_size / sizeof(elfsh_Sym); index++)
  {
    if (elfsh_get_symbol_link(sym + index) != SHN_COMMON)
    {
      if (elfsh_get_symbol_type(sym + index) == STT_SECTION)
        continue;

      sct = elfsh_get_parent_section(symtab->parent, 
                                     elfsh_get_symbol_value(sym + index), 
                                     &offset);

      if (sct == NULL)
      {
        sct = elfsh_get_section_by_index(symtab->parent, 
                                         elfsh_get_symbol_link(sym + index), 
                                         NULL, 
                                         NULL);
        if (sct && elfsh_get_section_type(sct->shdr) == SHT_NOBITS)
        {

#if	__DEBUG_MAP__
          printf(" [*] Symbol [%s] sctndx changed from %u to SHN_COMMON\n", 
                 elfsh_get_symbol_name(symtab->parent, sym + index), 
                 elfsh_get_symbol_link(sym + index));
#endif

          elfsh_set_symbol_link(sym + index, SHN_COMMON);
          continue;
        }

      }

      if (sct && elfsh_get_section_type(sct->shdr) == SHT_NOBITS)
      {
        elfsh_set_symbol_link(sym + index, SHN_COMMON);
#if	__DEBUG_MAP__		  
        printf(" [*] Symbol [%s] sctndx changed to SHN_COMMON\n", 
               elfsh_get_symbol_name(symtab->parent, sym + index));
#endif
      }
    }
  }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, symtab);
}
示例#3
0
/**
 * Relocate the object
 * @param file
 * @param rel
 * @param stage
 * @return
 */
int		elfsh_relocate_object(elfshobj_t *file, elfshobj_t *rel, u_char stage)
{
    elfshsect_t	*sect;
    elfshsect_t	*reltab;
    char		sctname[BUFSIZ];
    u_int		index;
    u_int		found;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    /* Last pass : relocate each inserted section */
    for (found = index = 0; index < rel->hdr->e_shnum; index++)
    {
        sect = elfsh_get_section_by_index(rel, index, NULL, NULL);
        if (sect == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant get section in ET_REL",  -1);

        /* Check if the section is mapped */
        if (elfsh_get_section_allocflag(sect->shdr) && sect->shdr->sh_size &&
                sect->shdr->sh_type == SHT_PROGBITS)
        {

            /* Find the associate relocation section */
            snprintf(sctname, sizeof(sctname), "%s%s",
                     (IS_REL(sect) ? ".rel" : ".rela"), sect->name);
            reltab = elfsh_get_section_by_name(rel, sctname, NULL, NULL, NULL);
            if (reltab == NULL)
                continue;
            found++;

            /* Find the injected instance of this allocatable section in the ET_EXEC */
            snprintf(sctname, sizeof(sctname), "%s%s", sect->parent->name, sect->name);
            sect = elfsh_get_section_by_name(file, sctname, NULL, NULL, NULL);
            if (sect == NULL)
                PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                             "Cant get section in ET_EXEC",  -1);
            if (elfsh_relocate_etrel_section(sect, reltab, stage) < 0)
                PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                             "Unable to relocate section", -1);
        }
    }

    /* Note that we might have done no relocation if no table was available */
    /* This can happen on very simple .o files */
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
示例#4
0
文件: remap.c 项目: kejiewei/eresi
/**
 * Remap a section using its extra relocation entries 
 * @param cur
 * @param diff
 * @return
 */
int		elfsh_reloc_raw(elfshsect_t *cur, eresi_Addr diff)
{
  u_int		index;
  eresi_Addr	addr;
  elfshsect_t	*target;
  char		*str;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  if (cur == NULL || cur->shdr == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", -1);

  if (elfsh_readmem(cur) == NULL || cur->rel == NULL)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);

  /* Read the actual section and find valid references */
  for (index = 0; index < cur->srcref; index++)
    switch (cur->rel[index].type)
      {

	/* Relocate by : section[idx_dst].vaddr + off_dst */
      case ELFSH_RELOC_SECTBASE:
	target = elfsh_get_section_by_index(cur->parent, 
					    cur->rel[index].idx_dst,
					    NULL, NULL);
	if (target == NULL)
	  PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			    "Invalid IDX_DST",  -1);

	str = elfsh_readmem(cur) + cur->rel[index].off_src;
	addr = target->shdr->sh_addr + cur->rel[index].off_dst + diff;
	memcpy(str, &addr, sizeof(eresi_Addr));

	/* Do not relocate */
      case ELFSH_RELOC_FP:
      default:
	break;
      }

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (cur->srcref));
}
示例#5
0
文件: strtab.c 项目: kejiewei/eresi
/**
 * Retreive strtab 
 * @param file
 * @param index
 * @return
 */
elfshsect_t	*elfsh_get_strtab(elfshobj_t *file, int index)
{
  elfshsect_t	*s;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sanity checks */
  if (file == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", NULL);

  s = file->secthash[ELFSH_SECTION_STRTAB];
  if (s)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, s);
  
  /* Read the string table */
  if (index > 0)
    s = elfsh_get_section_by_index(file, index, NULL, NULL);
  else
    s = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_STRTAB,
				  NULL, NULL, NULL);
  
  /* Section is present */
  if (s != NULL)
    {
      file->secthash[ELFSH_SECTION_STRTAB] = s;
      s->shdr->sh_link = file->secthash[ELFSH_SECTION_SYMTAB]->index;
      if (s->data == NULL)
	{
	  s->data = elfsh_load_section(file, s->shdr);
	  if (s->data == NULL)
	    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			      "Unable to load STRTAB", NULL);
	} 
      PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (s));
    }

  /* Section is not present */
  s = elfsh_rebuild_strtab(file);
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (s));
}
示例#6
0
/**
 * Inject a ET_REL object into a ET_EXEC object
 * @param file
 * @param rel
 * @return
 */
int		elfsh_inject_etrel(elfshobj_t *file, elfshobj_t *rel)
{
    u_int		mod;
    u_int		pgsize;
    u_int		index;
    elfshsect_t	*sect;
    elfshsect_t	*hooks;
    int		ret = 0;
    static int	depth = 0;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    /* Sanity checks */
    if (file == NULL || file->hdr == NULL || rel == NULL || rel->hdr == NULL)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Invalid NULL parameter", -1);
    if (rel->hdr->e_type != ET_REL ||
            (file->hdr->e_type != ET_EXEC && file->hdr->e_type != ET_DYN))
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Bad parameter types", -1);

#if	__DEBUG_RELADD__
    if (rel->pending)
    {
        printf("[DEBUG_RELADD] BUG BUG BUG \n");
        exit(0);
    }
    printf("[DEBUG_RELADD] INJECTING %s in %s (depth %d)\n",
           rel->name,
           file->name,
           depth++);
#endif


    /* Set pending injection flag */
    rel->pending = 1;

    /* If not already done */
    elfsh_setup_hooks();

    /* First physically insert all BSS in the file and fuse
    ** the module's BSS with the last one */
    if (elfsh_fuse_bss(file, rel) < 0)
    {
        rel->pending = 0;
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Cant fuze BSS sections", -1);
    }

    /* First pass : find and inject all allocatable sections */
    for (index = 0; index < rel->hdr->e_shnum; index++)
    {

        /* Get the current section */
        sect = elfsh_get_section_by_index(rel, index, NULL, NULL);
        if (sect == NULL)
        {
            rel->pending = 0;
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant read section in ET_REL",  -1);
        }

        /* Check if the current section need to be mapped */
        if (elfsh_get_section_allocflag(sect->shdr) &&
                sect->shdr->sh_size && sect->shdr->sh_type == SHT_PROGBITS)
        {
            mod = 0;

            if (elfsh_inject_etrel_section(file, sect, mod) < 0)
            {
                rel->pending = 0;
                PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                             "Unable to inject ET_REL section", -1);
            }
        }
    }

    /* compute the inject modulo */
    mod = elfsh_get_pagesize(file);
    //mod = sizeof(eresi_Addr);

    /* Do a copy of the procedure linkage table for eventual redirection */
    if (!elfsh_static_file(file) && elfsh_copy_plt(file, mod) < 0)
    {
        rel->pending = 0;
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to copy PLT", -1);
    }

    /* Create an additional hook table for non-plt function redirection */
    hooks = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_HOOKS, 0, 0, 0);
    if (!hooks)
    {
        int mode;

        /* get injection mode */
        ELFSH_SELECT_INJECTION(file,NULL,mode);

        pgsize = elfsh_get_pagesize(file);
        pgsize *= 4; /* We need a lot more than a page to trace big binaries like ssh */
        hooks = elfsh_insert_section(file,
                                     ELFSH_SECTION_NAME_HOOKS,
                                     NULL,
                                     mode,
                                     pgsize - 1, pgsize);
        if (!hooks)
        {
            rel->pending = 0;
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cannot inject .hooks", -1);
        }
        hooks->curend = 0;
    }

#if __DEBUG_RELADD__
    printf("[DEBUG_RELADD] Entering intermediate symbol injection loop\n");
#endif

    /* Intermediate pass 2 : Inject ET_REL symbol table into host file */
    if (elfsh_fuse_etrel_symtab(file, rel) < 0)
    {
        rel->pending = 0;
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to fuze symbol tables", -1);
    }

#if __DEBUG_RELADD__
    printf("[DEBUG_RELADD] Entering final relocation loop\n");

    elfsh_print_sectlist(file, "before relocation");
#endif

    /* Now call the relocation on the object's sections */
    ret = elfsh_relocate_object(file, rel, ELFSH_RELOC_STAGE1);
    rel->pending = 0;
    depth--;
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (ret));
}
示例#7
0
/**
 * The intermediate pass of theglobal algorithm for ET_REL injection
 * We fuze symbol tables from the ET_REL and the host binary
 *
 * @param file
 * @param rel
 * @return
 */
int		elfsh_fuse_etrel_symtab(elfshobj_t *file, elfshobj_t *rel)
{
    elfshsect_t	*sect;
    elfsh_Sym	newsym;
    elfsh_Half	type;
    u_int		index;
    char		sctname[BUFSIZ];
    elfsh_Sym	*sym;
    int		symnbr;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    sym = elfsh_get_symtab(rel, &symnbr);
    for (index = 0; index < symnbr; index++)
    {
        type = elfsh_get_symbol_type(sym + index);

        /* Avoid non-injectable symbols */
        if (type != STT_FUNC && type != STT_OBJECT)
            continue;

        if (sym[index].st_shndx >= rel->hdr->e_shnum)
            continue;

        /* Find target section in ET_REL */
        sect = elfsh_get_section_by_index(rel, sym[index].st_shndx, NULL, NULL);
        if (sect == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant find extracted section in ET_REL\n", -1);

        /* Filter symbols using source section */
        if (sect->shdr->sh_type != SHT_PROGBITS || !sect->shdr->sh_size ||
                !elfsh_get_section_allocflag(sect->shdr))
            continue;

        /* Find corresponding inserted section in ET_EXEC */
        snprintf(sctname, sizeof(sctname), "%s%s", rel->name, sect->name);
        sect = elfsh_get_section_by_name(file, sctname, NULL, NULL, NULL);
        if (sect == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant find inserted section in ET_EXEC\n", -1);

#if __DEBUG_RELADD__
        printf("[DEBUG_RELADD] Injected ET_REL symbol %-20s ["XFMT"] \n",
               elfsh_get_symbol_name(rel, sym + index),
               (eresi_Addr) (sect->shdr->sh_addr + sym[index].st_value));
#endif

        /* Add symbol in host file */
        newsym = elfsh_create_symbol(sect->shdr->sh_addr + sym[index].st_value,
                                     sym[index].st_size,
                                     elfsh_get_symbol_type(sym + index),
                                     elfsh_get_symbol_bind(sym + index),
                                     0, sect->index);

        if (elfsh_insert_symbol(file->secthash[ELFSH_SECTION_SYMTAB], &newsym,
                                elfsh_get_symbol_name(rel, sym + index)) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Unable to insert ET_REL symbol", -1);
    }

    /* Resynchronize sorted instances of symbol table */
    if (elfsh_sync_sorted_symtab(file->secthash[ELFSH_SECTION_SYMTAB]) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to synchronize host symtab", -1);

    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
示例#8
0
/**
 * Relocate the just injected section
 * @param enew
 * @param reltab
 * @param stage
 * @return
 */
static int	elfsh_relocate_etrel_section(elfshsect_t	*enew,
        elfshsect_t	*reltab,
        u_char		stage)
{
    elfsh_Rel	*cur;
    volatile u_int		index;
    elfsh_Sym	*sym;
    volatile u_int		size;
    eresi_Addr	*dword;
    eresi_Addr   	addr;
    char		*name;
    char		tmpname[BUFSIZ];
    elfshsect_t	*sect;
    u_int		entsz;
    elfshsect_t   *plt;
    void		*data;
    elfsh_Half	symtype;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    /* ET_REL object is not mapped we use unconditionaly
       the ondisk relocation tables for such operation */
    data = reltab->data;

#if __DEBUG_RELADD__
    fprintf(stderr, "[DEBUG_RELADD] Using reloc table from %s [%s] data at %p \n",
            reltab->parent->name, reltab->name, data);
#endif

    /* Loop on the relocation table entries */
    size = (reltab->shdr->sh_type == SHT_RELA ?
            sizeof(elfsh_Rela) : sizeof(elfsh_Rel));
    size = reltab->shdr->sh_size / size;

    plt = elfsh_get_plt(enew->parent, NULL);
    if (NULL == plt && elfsh_dynamic_file(enew->parent))
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to get plt", -1);

    entsz = elfsh_get_pltentsz(enew->parent);
    if (entsz < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to get pltentsz", -1);

    for (index = 0; index < size; index++)
    {

#if __DEBUG_RELADD__
        fprintf(stderr, "[DEBUG_RELADD] relocation loop stage %u for section %s index %u \n",
                stage, enew->name, index);
#endif

        /* We try a enew relocation now that the ET_REL dependence is mapped */
retry:

        /* Get symbol value in ET_REL */
        cur = (reltab->shdr->sh_type == SHT_RELA ?
               (void *) (((elfsh_Rela *) data) + index) :
               (void *) (((elfsh_Rel  *) data) + index));
        sym  = elfsh_get_symbol_from_reloc(reltab->parent, cur);
        name = elfsh_get_symname_from_reloc(reltab->parent, cur);

        if (sym == NULL || name == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Unable to find symbol in ET_REL", -1);

        /* Grab a pointer on the dword that need to be relocated */
        dword = (eresi_Addr *) ((char *) elfsh_readmem(enew) + cur->r_offset);

        /*
        ** If symbol type is NOTYPE, we use ET_EXEC symtab, else if
        ** symbol link is COMMON, we use ET_REL symbol inserted in ET_EXEC
        ** during BSS sizescan in bss.c:elfsh_find_bsslen()
        */
        symtype = elfsh_get_symbol_type(sym);
        if (elfsh_get_symbol_bind(sym) != STB_LOCAL && /* patch BEOS */
                (symtype == STT_NOTYPE || elfsh_get_symbol_link(sym) == SHN_COMMON))
        {
            if (stage == ELFSH_RELOC_STAGE2 && !strstr(name, "old_"))
                continue;

            /* If the symbol is not found and we are still in
               the first stage relocation, just pass it */
            sym = elfsh_get_metasym_by_name(enew->parent, name);
            if (!sym)
            {
                switch (elfsh_find_relocsym(enew, reltab, &sym, name, stage, symtype))
                {
                case 2:
#if	__DEBUG_STATIC__
                    fprintf(stderr, "[DEBUG_STATIC] RETRY\n");
#endif
                    goto retry;
                    break;
                case 0:
                    continue;
                case 1:
                    break;
                case -1:
                default:
                    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                                 "Unable to satisfy symbol in ET_REL", -1);
                }
            }

            addr = sym->st_value;

#if	__DEBUG_RELADD__
            fprintf(stderr, "[DEBUG_RELADD] Relocate using existing symbol %-20s " AFMT "]\n",
                    name, (eresi_Addr) addr);
#endif

        }


        /* Compute addr giving the injected section's vaddr in ET_EXEC */
        else
        {

            /* All the following relocs are computed in stage 1 */
            if (stage == ELFSH_RELOC_STAGE2)
                continue;

            /* Find target section in ET_REL */
            sect = elfsh_get_section_by_index(reltab->parent, sym->st_shndx,
                                              NULL, NULL);
            if (sect == NULL)
                PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                             "Cant find extracted section in ET_REL", -1);

#if	__DEBUG_RELADD__
            fprintf(stderr, "[DEBUG_RELADD] Found -%s- section (idx = %u), now looking at "
                    "injected base address\n", sect->name, sect->index);
#endif

            /* Find corresponding inserted section in ET_EXEC */
            snprintf(tmpname, sizeof(tmpname), "%s%s", reltab->parent->name, sect->name);
            sect = elfsh_get_section_by_name(enew->parent, tmpname, NULL, NULL, NULL);

            if (sect == NULL)
            {

#if   	__DEBUG_RELADD__
                elfsh_print_sectlist(reltab->parent, "HEH");
                fprintf(stderr, "[DEBUG_RELADD] Did not found %s section (sym = %s) \n",
                        tmpname, name);
#endif

                PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                             "Cant find inserted section in ET_EXEC", -1);
            }

            /* Compute pointer value */
            addr = sect->shdr->sh_addr;
            addr += ((elfsh_get_symbol_type(sym) == STT_SECTION &&
                      !FILE_IS_SPARC(sect->parent) &&
                      !FILE_IS_ALPHA64(sect->parent) &&
                      !FILE_IS_MIPS(sect->parent)) ?
                     *dword : sym->st_value);

#if __DEBUG_RELADD__
            fprintf(stderr, "[DEBUG_RELADD] Relocate using section %-20s base [-> " AFMT "] \n",
                    sect->name, (eresi_Addr) addr);
#endif


        }

        /* Perform relocation */
        if (elfsh_relocate_entry(enew, cur, dword, addr, reltab) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Unable to relocate entry", -1);

    }
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
示例#9
0
/** 
 * Print the chosen symbol table 
 * @param file
 * @param sect
 * @param tab
 * @param num
 * @param regx
 * @param get_symname
 * @return
 */
int		ds(elfshobj_t	*file,
		   elfshsect_t	*sect,
		   u_int        num,
		   regex_t	*regx,
		   char		*(*get_symname)(elfshobj_t *f, elfsh_Sym *s))
{
  elfsh_Sym	*table;
  char		*name;
  char		*type;
  char		*bind;
  u_int		typenum;
  u_int		bindnum;
  u_int		foff;
  u_int		index;
  char		*sect_name;
  char		buff[512];
  char		off[50];
  char		type_unk[ERESI_MEANING + 1];
  char		bind_unk[ERESI_MEANING + 1];

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sort the table if necessary */
  if (world.state.sort != NULL)
    switch (*world.state.sort)
      {
      case ELFSH_SORT_BY_ADDR:
	table = sect->altdata;
	break;
      case ELFSH_SORT_BY_SIZE:
	table = sect->terdata;
	break;
      default:
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			  "Unknown sort mode", -1);
      }

  /* Avoid reading inexistant memory in the process for .symtab */
  else
    table = (elfsh_Sym *) (sect->shdr->sh_addr ? elfsh_readmem(sect) : sect->data);

  /* Browse symtab */
  for (index = 0; index < num; index++)
    {

      /* Retreive names */
      typenum = elfsh_get_symbol_type(table + index);
      bindnum = elfsh_get_symbol_bind(table + index);
      type = (char *) (typenum > ELFSH_SYMTYPE_MAX ? 
		       revm_build_unknown(type_unk, "type", typenum) : 
		       elfsh_sym_type[typenum].desc);
      bind = (char *) (bindnum >= ELFSH_SYMBIND_MAX ?
		       revm_build_unknown(bind_unk, "type", bindnum) : 
		       elfsh_sym_bind[bindnum].desc);
      name = get_symname(world.curjob->curfile, table + index);
      sect_name = NULL;
      sect = elfsh_get_parent_section(world.curjob->curfile, 
				      table[index].st_value, 
				      NULL);
      if (sect == NULL && table[index].st_shndx)
	sect = elfsh_get_section_by_index(world.curjob->curfile, 
					  table[index].st_shndx,
					  NULL, NULL);
      if (sect != NULL)
	sect_name = elfsh_get_section_name(world.curjob->curfile, sect);

      /* Fixup names */
      if (name == NULL || *name == 0)
	name = ELFSH_NULL_STRING;
      if (type == NULL || *type == 0)
	type = ELFSH_NULL_STRING;
      if (bind == NULL || *bind == 0)
	bind = ELFSH_NULL_STRING;
      if (sect_name == NULL)
	sect_name = ELFSH_NULL_STRING;
      foff = (!table[index].st_value ? 0 : 
	      elfsh_get_foffset_from_vaddr(world.curjob->curfile, 
					   table[index].st_value));
					
      if (sect && sect->shdr->sh_addr != table[index].st_value)
	snprintf(off, sizeof(off), " + %s", 
		 revm_colornumber("%u", (u_int) (table[index].st_value - sect->shdr->sh_addr)));
      else
	*off = '\0';



      /* Different output depending on the quiet flag */
      if (!world.state.revm_quiet)
	{
	  snprintf(buff, sizeof(buff), 
		   " %s %s %s %s %s%s "
		   "%s%s %s%s %s%s => %s%s\n",
		   revm_colornumber("[%03u]", index), 
		   revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), 
		   revm_colortypestr_fmt("%-8s", type), 
		   revm_colorstr_fmt("%-40s", name),
		   revm_colorfieldstr("size:"),
		   revm_colornumber("%010u", elfsh_get_symbol_size(table + index)), 				  
		   revm_colorfieldstr("foffset:"),
		   revm_colornumber("%06u", foff),
		   revm_colorfieldstr("scope:"),
		   revm_colortypestr_fmt("%-6s", bind), 
		   revm_colorfieldstr("sctndx:"),
		   revm_colornumber("%02u", elfsh_get_symbol_link(table + index)),
		   revm_colorstr(sect_name), off);
	}

      else
	{
	  snprintf(buff, sizeof(buff), 
		   " %s %s %s %s %s%s %s%s %s%-6s\n",
		   revm_colornumber("[%03u]", index), 
		   revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base),
		   revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-15s", name), 
		   revm_colorfieldstr("sz:"),
		   revm_colornumber("%06u", elfsh_get_symbol_size(table + index)),
		   revm_colorfieldstr("foff:"),
		   revm_colornumber("%06u", foff),
		   revm_colorfieldstr("scop:"),
		   revm_colortypestr_fmt("%-6s", bind));
	}
      
      if (regx == NULL || 
	  (regx != NULL && regexec(regx, buff, 0, 0, 0) == 0))
	{
	  /* If the user ask quit, we just break */
	  if (revm_output(buff) == -1)
	    break;
	}

      revm_endline();
    }

  revm_endline();
  revm_output("\n");
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}