Ejemplo n.º 1
0
BOOL CALLBACK MyEnumSymbolsCallback( SYMBOL_INFO* SymInfo, ULONG SymbolSize, PVOID UserContext )
{
    struct lookup_uc *tmp = (struct lookup_uc *) UserContext;
    GElf_Sym *symp = (GElf_Sym *) tmp->cd;

    if (SymInfo != NULL) {
        if (isfunction(tmp->ps, SymInfo)) {
            symp->st_name = 0;
            symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
            symp->st_other = 0;
            symp->st_shndx = 1;
            symp->st_value = SymInfo->Address;
            symp->st_size = SymInfo->Size;
        } else {
            symp->st_name = 0;
            symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE));
            symp->st_other = 0;
            symp->st_shndx = SHN_UNDEF;
            symp->st_value = SymInfo->Address;
            symp->st_size = SymInfo->Size;
        }
    }

    return TRUE;
}
Ejemplo n.º 2
0
BOOL CALLBACK SymEnumSymbolsProc(PSYMBOL_INFO s, ULONG SymbolSize, PVOID UserContext)
{
    GElf_Sym symp;
    struct lookup_uc *tmp = (struct lookup_uc *) UserContext;

    if (s != NULL) {
        if (isfunction(tmp->ps, s)) {
            symp.st_name = 0;
            symp.st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
            symp.st_other = 0;
            symp.st_shndx = 1;
            symp.st_value = s->Address;
            symp.st_size = s->Size;
        } else {
            symp.st_name = 0;
            symp.st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE));
            symp.st_other = 0;
            symp.st_shndx = SHN_UNDEF;
            symp.st_value = s->Address;
            symp.st_size = s->Size;

        }
        tmp->count++;
        tmp->f(tmp->cd, &symp, s->Name);
    }

    return TRUE;
}
Ejemplo n.º 3
0
int
cmd_nmadd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	uintptr_t opt_e = 0, opt_s = 0;
	uint_t opt_f = FALSE, opt_o = FALSE;

	GElf_Sym sym;
	int i;

	if (!(flags & DCMD_ADDRSPEC))
		return (DCMD_USAGE);

	i = mdb_getopts(argc, argv,
	    'f', MDB_OPT_SETBITS, TRUE, &opt_f,
	    'o', MDB_OPT_SETBITS, TRUE, &opt_o,
	    'e', MDB_OPT_UINTPTR, &opt_e,
	    's', MDB_OPT_UINTPTR, &opt_s, NULL);

	if (i != (argc - 1) || argv[i].a_type != MDB_TYPE_STRING ||
	    argv[i].a_un.a_str[0] == '-' || argv[i].a_un.a_str[0] == '+')
		return (DCMD_USAGE);

	if (opt_e && opt_e < addr) {
		mdb_warn("end (%p) is less than start address (%p)\n",
		    (void *)opt_e, (void *)addr);
		return (DCMD_USAGE);
	}

	if (mdb_gelf_symtab_lookup_by_name(mdb.m_prsym,
	    argv[i].a_un.a_str, &sym, NULL) == -1) {
		bzero(&sym, sizeof (sym));
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
	}

	if (opt_f)
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
	if (opt_o)
		sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
	if (opt_e)
		sym.st_size = (GElf_Xword)(opt_e - addr);
	if (opt_s)
		sym.st_size = (GElf_Xword)(opt_s);
	sym.st_value = (GElf_Addr)addr;

	mdb_gelf_symtab_insert(mdb.m_prsym, argv[i].a_un.a_str, &sym);

	mdb_iob_printf(mdb.m_out, "added %s, value=%llr size=%llr\n",
	    argv[i].a_un.a_str, sym.st_value, sym.st_size);

	return (DCMD_OK);
}
Ejemplo n.º 4
0
int Plookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf, size_t size, GElf_Sym *symp)
{
    SYMBOL_INFO *s;

    s = (SYMBOL_INFO *) malloc(sizeof(SYMBOL_INFO) + size-1);
    if (s == NULL)
        return -1;

    s->SizeOfStruct = sizeof(SYMBOL_INFO);
    s->MaxNameLen = size;

    if (SymFromAddr(P->phandle, addr, 0, s) == TRUE) {
        isfunction(P, s);
        symp->st_name = 0;
        symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
        symp->st_other = 0;
        symp->st_shndx = 1;
        symp->st_value = s->Address;
        symp->st_size = s->Size;
        strncpy(buf, s->Name, size);
        return 0;

    }

    return dw_lookup_by_addr(P, addr, buf, size, symp);
}
Ejemplo n.º 5
0
static int dw_lookup_by_name(struct ps_prochandle *P, const char *oname, const char *sname, GElf_Sym *symp)
{
    IMAGE_SYMBOL Sym;
    int ret = -1, fd;
    Pe_object *pe;
    proc_mod_t *mod;

    mod = findmodulebyname(P, oname);
    if (mod == NULL)
        return -1;

    fd = _open(mod->fullname, _O_RDONLY|_O_BINARY, 0);

    if (fd != -1 && (pe = pe_init(fd)) != NULL) {
        char s[MAX_SYM_NAME];

        if (pe_getarch(pe) == PE_ARCH_I386) {
            s[0] = '_';
            strcpy(&s[1], sname);
        } else {
            strcpy(s, sname);
        }

        if (pe_getsymbyname(pe, s, &Sym) != NULL) {
            symp->st_name = 0;
            symp->st_other = 0;
            if (ISFCN(Sym.Type)) {
                symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
                symp->st_shndx = 1;
            } else {
                symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE));
                symp->st_shndx = SHN_UNDEF;
            }
            symp->st_value = Sym.Value + mod->imgbase + pe_getsecva(pe, Sym.SectionNumber);
            /* If size is zero libdtrace will reject the function. Allow creation of entry probe */
            symp->st_size = 1;
            ret = 0;
        }
    }

    if (pe != NULL)
        pe_end(pe);
    if (fd != -1)
        close(fd);

    return ret;
}
Ejemplo n.º 6
0
static GElf_Sym *
gelf_getsym_macho(Elf_Data * data, int ndx, int nent, GElf_Sym * dst, const char *base) 
{
	const struct nlist *nsym = ((const struct nlist *)(data->d_buf)) + ndx;
	const char *name = base + nsym->n_un.n_strx;
	char *tmp;

	if (0 == nsym->n_un.n_strx) // iff a null, "", name.
		name = "null name"; // return NULL;

	if ((tmp = demangleSymbolCString(name)))
		name = tmp;

	if ('_' == name[0])
		name++; // Lop off omnipresent underscore to match DWARF convention

	dst->st_name = (GElf_Sxword)(name - base);
	dst->st_value = nsym->n_value;
	dst->st_size = 0;
	dst->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_NOTYPE));
	dst->st_other = 0;
	dst->st_shndx = SHN_MACHO; /* Mark underlying file as Mach-o */
	
	if (nsym->n_type & N_STAB) {
	
		switch(nsym->n_type) {
		case N_FUN:
			dst->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
			break;
		case N_GSYM:
			dst->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT));
			break;
		default:
			break;
		}
		
	} else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) ||
		(N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) {

		dst->st_info = GELF_ST_INFO((STB_GLOBAL), (nsym->n_desc)); 
	} else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) &&
				nsym->n_sect == NO_SECT) {
		dst->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */
	} 
		
	return dst;
}
Ejemplo n.º 7
0
static int dw_iter_by_addr(struct ps_prochandle *P, const char *object_name, int which,
                           int mask, proc_sym_f *func, void *cd)
{
    int fd = 0, ret = -1, i, index = 0;
    Pe_object *pe;
    proc_mod_t *mod = findmodulebyname(P, object_name);

    fd = _open(mod->fullname, _O_RDONLY|_O_BINARY, 0);

    if (fd == -1 )
        return -1;

    if  ((pe = pe_init(fd)) != NULL) {
        IMAGE_SYMBOL *Sym = pe_getsymarr(pe, &index);
        char name[MAX_SYM_NAME];

        if (Sym == NULL)
            goto end;
        ret = 0;
        for (i = 0; i < index; i++) {
            GElf_Sym symp;
            char *n = NULL;

            if (ISFCN(Sym[i].Type) == 0)
                continue;
            symp.st_name = 0;
            symp.st_other = 0;
            symp.st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
            symp.st_shndx = 1;
            symp.st_value = Sym[i].Value+mod->imgbase+pe_getsecva(pe, Sym[i].SectionNumber);
            /* If size is zero libdtrace will reject the probe.Allow creation of entry probe */
            symp.st_size = 1;
            if (pe_getsymname(pe, &Sym[i], name, MAX_SYM_NAME) == NULL)
                continue;

            if (pe_getarch(pe) == PE_ARCH_I386)
                func(cd, &symp, &name[1]);
            else
                func(cd, &symp, name);
        }
    }
end:
    if (pe != NULL)
        pe_end(pe);
    if (fd != -1)
        close(fd);
    return ret;
}
Ejemplo n.º 8
0
static int dw_lookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf, size_t size, GElf_Sym *symp)
{
    proc_mod_t *mod = NULL;
    int fd, ret = -1, index, i;
    Pe_object *pe;

    mod = findmodulebyaddr(P, addr);
    if (mod == NULL)
        return -1;

    fd = _open(mod->fullname, _O_RDONLY|_O_BINARY, 0);

    if (fd == -1 )
        return -1;

    if ((pe = pe_init(fd)) != NULL) {
        IMAGE_SYMBOL *Sym = pe_getsymarr(pe, &index);
        char name[MAX_SYM_NAME];

        int secno, addr1, mark = -1, prev = 0, va;

        if (Sym == NULL)
            goto end;

        if ((secno = pe_getsecnofromaddr(pe, addr - mod->imgbase))== 0)
            goto end;

        va = pe_getsecva(pe, secno);
        addr1 = addr - (mod->imgbase + va);
        if (addr1 <= 0)
            goto end;
        for (i = 0; i < index; i++) {
            if (ISFCN(Sym[i].Type) == 0 || Sym[i].SectionNumber != secno)
                continue;
            if (addr1 == Sym[i].Value) {
                mark = i;
                break;
            } else if (addr1 > Sym[i].Value) {
                if (prev < Sym[i].Value) {
                    prev = Sym[i].Value;
                    mark = i;
                }
            }
        }
        if (mark >= 0) {
            symp->st_name = 0;
            symp->st_other = 0;
            symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
            symp->st_shndx = 1;
            symp->st_value = Sym[mark].Value + mod->imgbase
                             + pe_getsecva(pe, Sym[mark].SectionNumber);
            /* If size is zero libdtrace will reject the function. Allow creation of entry probe */
            symp->st_size = 1;

            if (pe_getsymname(pe, &Sym[mark], name, MAX_SYM_NAME) == NULL)
                goto end;
            if (pe_getarch(pe) == PE_ARCH_I386) {
                strncpy(buf, &name[1], size);
            } else {
                strncpy(buf, name, size);
            }

            ret = 0;
        }
    }
end:
    if (pe != NULL)
        pe_end(pe);
    if (fd != -1)
        close(fd);

    return ret;
}
Ejemplo n.º 9
0
/*
 * Exported interface to look up a symbol by name.  We return the GElf_Sym and
 * complete symbol information for the matching symbol.
 */
int
dtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name,
    GElf_Sym *symp, dtrace_syminfo_t *sip)
{
	dt_module_t *dmp;
	dt_ident_t *idp;
	uint_t n, id;
	GElf_Sym sym;

	uint_t mask = 0; /* mask of dt_module flags to match */
	uint_t bits = 0; /* flag bits that must be present */

	if (object != DTRACE_OBJ_EVERY &&
	    object != DTRACE_OBJ_KMODS &&
	    object != DTRACE_OBJ_UMODS) {
		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
			return (-1); /* dt_errno is set for us */

		if (dt_module_load(dtp, dmp) == -1)
			return (-1); /* dt_errno is set for us */
		n = 1;

	} else {
		if (object == DTRACE_OBJ_KMODS)
			mask = bits = DT_DM_KERNEL;
		else if (object == DTRACE_OBJ_UMODS)
			mask = DT_DM_KERNEL;

		dmp = dt_list_next(&dtp->dt_modlist);
		n = dtp->dt_nmods;
	}

	if (symp == NULL)
		symp = &sym;

	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
		if ((dmp->dm_flags & mask) != bits)
			continue; /* failed to match required attributes */

		if (dt_module_load(dtp, dmp) == -1)
			continue; /* failed to load symbol table */

		if (dmp->dm_ops->do_symname(dmp, name, symp, &id) != NULL) {
			if (sip != NULL) {
				sip->dts_object = dmp->dm_name;
				sip->dts_name = (const char *)
				    dmp->dm_strtab.cts_data + symp->st_name;
				sip->dts_id = id;
			}
			return (0);
		}

		if (dmp->dm_extern != NULL &&
		    (idp = dt_idhash_lookup(dmp->dm_extern, name)) != NULL) {
			if (symp != &sym) {
				symp->st_name = (uintptr_t)idp->di_name;
				symp->st_info =
				    GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
				symp->st_other = 0;
				symp->st_shndx = SHN_UNDEF;
				symp->st_value = 0;
				symp->st_size =
				    ctf_type_size(idp->di_ctfp, idp->di_type);
			}

			if (sip != NULL) {
				sip->dts_object = dmp->dm_name;
				sip->dts_name = idp->di_name;
				sip->dts_id = idp->di_id;
			}

			return (0);
		}
	}

	return (dt_set_errno(dtp, EDT_NOSYM));
}
Ejemplo n.º 10
0
static int
dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
{
	dt_pid_probe_t *pp = arg;
	dtrace_hdl_t *dtp = pp->dpp_dtp;
	dt_pcb_t *pcb = pp->dpp_pcb;
	dt_proc_t *dpr = pp->dpp_dpr;
	GElf_Sym sym;

	if (obj == NULL)
		return (0);

#if defined(sun)
	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#endif
	

	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
		pp->dpp_obj = obj;
	else
		pp->dpp_obj++;
#if defined(sun)
	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym,
	    NULL) == 0)
		pp->dpp_stret[0] = sym.st_value;
	else
		pp->dpp_stret[0] = 0;

	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym,
	    NULL) == 0)
		pp->dpp_stret[1] = sym.st_value;
	else
		pp->dpp_stret[1] = 0;

	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym,
	    NULL) == 0)
		pp->dpp_stret[2] = sym.st_value;
	else
		pp->dpp_stret[2] = 0;

	if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym,
	    NULL) == 0)
		pp->dpp_stret[3] = sym.st_value;
	else
		pp->dpp_stret[3] = 0;
#else
	pp->dpp_stret[0] = 0;
	pp->dpp_stret[1] = 0;
	pp->dpp_stret[2] = 0;
	pp->dpp_stret[3] = 0;
#endif

	dt_dprintf("%s stret %llx %llx %llx %llx\n", obj,
	    (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1],
	    (u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]);

	/*
	 * If pp->dpp_func contains any globbing meta-characters, we need
	 * to iterate over the symbol table and compare each function name
	 * against the pattern.
	 */
	if (!strisglob(pp->dpp_func)) {
		/*
		 * If we fail to lookup the symbol, try interpreting the
		 * function as the special "-" function that indicates that the
		 * probe name should be interpreted as a absolute virtual
		 * address. If that fails and we were matching a specific
		 * function in a specific module, report the error, otherwise
		 * just fail silently in the hopes that some other object will
		 * contain the desired symbol.
		 */
		if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj,
		    pp->dpp_func, &sym, NULL) != 0) {
			if (strcmp("-", pp->dpp_func) == 0) {
				sym.st_name = 0;
				sym.st_info =
				    GELF_ST_INFO(STB_LOCAL, STT_FUNC);
				sym.st_other = 0;
				sym.st_value = 0;
#if defined(sun)
				sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel ==
				    PR_MODEL_ILP32 ? -1U : -1ULL;
#else
				sym.st_size = ~((Elf64_Xword) 0);
#endif

			} else if (!strisglob(pp->dpp_mod)) {
				return (dt_pid_error(dtp, pcb, dpr, NULL,
				    D_PROC_FUNC,
				    "failed to lookup '%s' in module '%s'",
				    pp->dpp_func, pp->dpp_mod));
			} else {
				return (0);
			}
		}

		/*
		 * Only match defined functions of non-zero size.
		 */
		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC ||
		    sym.st_shndx == SHN_UNDEF || sym.st_size == 0)
			return (0);

		/*
		 * We don't instrument PLTs -- they're dynamically rewritten,
		 * and, so, inherently dicey to instrument.
		 */
#ifdef DOODAD
		if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL)
			return (0);
#endif

		(void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func,
		    DTRACE_FUNCNAMELEN, &sym);

		return (dt_pid_per_sym(pp, &sym, pp->dpp_func));
	} else {
		uint_t nmatches = pp->dpp_nmatches;

		if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB,
		    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
			return (1);

		if (nmatches == pp->dpp_nmatches) {
			/*
			 * If we didn't match anything in the PR_SYMTAB, try
			 * the PR_DYNSYM.
			 */
			if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM,
			    BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1)
				return (1);
		}
	}

	return (0);
}
Ejemplo n.º 11
0
static GElf_Sym *
dt_module_symaddr_macho_64(dt_module_t *dmp, GElf_Addr addr,
    GElf_Sym *symp, uint_t *idp)
{
	const struct nlist_64 **asmap = (const struct nlist_64 **)dmp->dm_asmap;
	const struct nlist_64 *symtab = (const struct nlist_64 *)(dmp->dm_symtab.cts_data);
	const char *strtab = (const char *)dmp->dm_strtab.cts_data;
	const struct nlist_64 *sym;

	uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;
	Elf32_Addr v;

	if (dmp->dm_aslen == 0)
		return (NULL);

	while (hi - lo > 1) {
		mid = (lo + hi) / 2;
		if (addr >= asmap[mid]->n_value)
			lo = mid;
		else
			hi = mid;
	}

	i = addr < asmap[hi]->n_value ? lo : hi;
	sym = asmap[i];
	v = sym->n_value;

	/*
	 * If the previous entry has the same value, improve our choice.  The
	 * order of equal-valued symbols is determined by the comparison func.
	 */
	while (i-- != 0 && asmap[i]->n_value == v)
		sym = asmap[i];

	/*
	 * Either addr < asmap[0]->n_value (in which case i is zero), or
	 * i is the smallest index s.t. asmap[i]->n_value <= addr <= asmap[i+1]->n_value.
	 * We'd like a st_size bounds check: if (addr - sym->n_value < MAX(sym->st_size, 1)),
	 * but Mach-o nlist entries don't capture the size attribute, sigh.
	 * At least make sure addr isn't too small.
	 */
	if (sym->n_value <= addr) {
		const char *name = strtab + sym->n_un.n_strx;

		if ('_' == name[0])
			name++; // Lop off omnipresent underscore

		symp->st_name = (GElf_Sxword)(name - strtab);
		symp->st_info = STT_NOTYPE;
		symp->st_other = 0;
		symp->st_shndx = sym->n_sect;
		symp->st_value = sym->n_value + dt_module_slide();
		symp->st_size = 0;

		if (sym->n_type & N_STAB) { /* Detect C++ methods */
	
			switch(sym->n_type) {
			case N_FUN:
				symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
				break;
			case N_GSYM:
				symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT));
				break;
			default:
				break;
			}
		
		} else if ((N_ABS | N_EXT) == (sym->n_type & (N_TYPE | N_EXT)) ||
			(N_SECT | N_EXT) == (sym->n_type & (N_TYPE | N_EXT))) {

			symp->st_info = GELF_ST_INFO((STB_GLOBAL), (sym->n_desc)); 
		} else if ((N_UNDF | N_EXT) == (sym->n_type & (N_TYPE | N_EXT)) &&
					sym->n_sect == NO_SECT) {
			symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */
		}
		
		if (idp != NULL) {
			*idp = (uint_t)(sym - symtab);
		}

		return symp;
	}

	return (NULL);
}
Ejemplo n.º 12
0
static GElf_Sym *
dt_module_symname_macho_64(dt_module_t *dmp, const char *name,
    GElf_Sym *symp, uint_t *idp)
{
	const struct nlist_64 *symtab = (const struct nlist_64 *)(dmp->dm_symtab.cts_data);
	const char *strtab = (const char *)dmp->dm_strtab.cts_data;

	const struct nlist_64 *sym;
	const dt_sym_t *dsp;
	uint_t i, h;

	if (dmp->dm_nsymelems == 0)
		return (NULL);

	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;

	for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {
		dsp = &dmp->dm_symchains[i];
		sym = symtab + dsp->ds_symid;
		const char *sname = strtab + sym->n_un.n_strx;

		if ('_' == sname[0])
			sname++; // Lop off omnipresent underscore
			
		if (strcmp(name, sname) == 0) {
			if (idp != NULL)
				*idp = dsp->ds_symid;

			symp->st_name = (GElf_Sxword)(sname - strtab);
			symp->st_info = STT_NOTYPE; 
			symp->st_other = 0;
			symp->st_shndx = sym->n_sect;
			symp->st_value = sym->n_value + dt_module_slide();
			symp->st_size = 0;
			
			if (sym->n_type & N_STAB) { /* Detect C++ methods */
	
				switch(sym->n_type) { 
				case N_FUN:
					symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_FUNC));
					break;
				case N_GSYM:
					symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT));
					break;
				default:
					break;
				}
		
			} else if ((N_ABS | N_EXT) == (sym->n_type & (N_TYPE | N_EXT)) ||
				(N_SECT | N_EXT) == (sym->n_type & (N_TYPE | N_EXT))) {

				symp->st_info = GELF_ST_INFO((STB_GLOBAL), (sym->n_desc)); 
			} else if ((N_UNDF | N_EXT) == (sym->n_type & (N_TYPE | N_EXT)) &&
						sym->n_sect == NO_SECT) {
				symp->st_info = GELF_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */
			}
		
			return symp;
		}
	}

	return (NULL);
}