📄 dt_module.c
字号:
(dp = elf_getdata(sp, NULL)) != NULL) { (void) strlcpy(dmp->dm_file, dp->d_buf, sizeof (dmp->dm_file)); } } dmp->dm_flags |= DT_DM_KERNEL; dmp->dm_modid = (int)OBJFS_MODID(st.st_ino); if (dmp->dm_info.objfs_info_primary) dmp->dm_flags |= DT_DM_PRIMARY; dt_dprintf("opened %d-bit module %s (%s) [%d]\n", bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);}/* * Unload all the loaded modules and then refresh the module cache with the * latest list of loaded modules and their address ranges. */voiddtrace_update(dtrace_hdl_t *dtp){ dt_module_t *dmp; DIR *dirp; for (dmp = dt_list_next(&dtp->dt_modlist); dmp != NULL; dmp = dt_list_next(dmp)) dt_module_unload(dtp, dmp); /* * Open /system/object and attempt to create a libdtrace module for * each kernel module that is loaded on the current system. */ if (!(dtp->dt_oflags & DTRACE_O_NOSYS) && (dirp = opendir(OBJFS_ROOT)) != NULL) { struct dirent *dp, *ep; ep = alloca(sizeof (struct dirent) + PATH_MAX + 1); bzero(ep, sizeof (struct dirent) + PATH_MAX + 1); while (readdir_r(dirp, ep, &dp) == 0 && dp != NULL) { if (dp->d_name[0] != '.') dt_module_update(dtp, dp->d_name); } (void) closedir(dirp); } /* * Look up all the macro identifiers and set di_id to the latest value. * This code collaborates with dt_lex.l on the use of di_id. We will * need to implement something fancier if we need to support non-ints. */ dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid(); dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid(); dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid(); dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid(); dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0); dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid(); dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid(); dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0); dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid(); dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid(); /* * Cache the pointers to the modules representing the base executable * and the run-time linker in the dtrace client handle. We should * probably have a more generic way of inquiring as to their names. */ dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix"); dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld"); /* * If this is the first time we are initializing the module list, * remove the module for genunix from the module list and then move it * to the front of the module list. We do this so that type and symbol * queries encounter genunix and thereby optimize for the common case * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below. */ if (dtp->dt_exec != NULL && dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) { dt_list_delete(&dtp->dt_modlist, dtp->dt_exec); dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec); }}static dt_module_t *dt_module_from_object(dtrace_hdl_t *dtp, const char *object){ int err = EDT_NOMOD; dt_module_t *dmp; switch ((uintptr_t)object) { case (uintptr_t)DTRACE_OBJ_EXEC: dmp = dtp->dt_exec; break; case (uintptr_t)DTRACE_OBJ_RTLD: dmp = dtp->dt_rtld; break; case (uintptr_t)DTRACE_OBJ_CDEFS: dmp = dtp->dt_cdefs; break; case (uintptr_t)DTRACE_OBJ_DDEFS: dmp = dtp->dt_ddefs; break; default: dmp = dt_module_create(dtp, object); err = EDT_NOMEM; } if (dmp == NULL) (void) dt_set_errno(dtp, err); return (dmp);}/* * Exported interface to look up a symbol by name. We return the GElf_Sym and * complete symbol information for the matching symbol. */intdtrace_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));}/* * Exported interface to look up a symbol by address. We return the GElf_Sym * and complete symbol information for the matching symbol. */intdtrace_lookup_by_addr(dtrace_hdl_t *dtp, GElf_Addr addr, GElf_Sym *symp, dtrace_syminfo_t *sip){ dt_module_t *dmp; uint_t id; const dtrace_vector_t *v = dtp->dt_vector; if (v != NULL) return (v->dtv_lookup_by_addr(dtp->dt_varg, addr, symp, sip)); for (dmp = dt_list_next(&dtp->dt_modlist); dmp != NULL; dmp = dt_list_next(dmp)) { if (addr - dmp->dm_text_va < dmp->dm_text_size || addr - dmp->dm_data_va < dmp->dm_data_size || addr - dmp->dm_bss_va < dmp->dm_bss_size) break; } if (dmp == NULL) return (dt_set_errno(dtp, EDT_NOSYMADDR)); if (dt_module_load(dtp, dmp) == -1) return (-1); /* dt_errno is set for us */ if (symp != NULL) { if (dmp->dm_ops->do_symaddr(dmp, addr, symp, &id) == NULL) return (dt_set_errno(dtp, EDT_NOSYMADDR)); } if (sip != NULL) { sip->dts_object = dmp->dm_name; if (symp != NULL) { sip->dts_name = (const char *) dmp->dm_strtab.cts_data + symp->st_name; sip->dts_id = id; } else { sip->dts_name = NULL; sip->dts_id = 0; } } return (0);}intdtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name, dtrace_typeinfo_t *tip){ dtrace_typeinfo_t ti; dt_module_t *dmp; int found = 0; ctf_id_t id; uint_t n; 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 (tip == NULL) tip = &ti; for (; n > 0; n--, dmp = dt_list_next(dmp)) { if ((dmp->dm_flags & mask) != bits) continue; /* failed to match required attributes */ /* * If we can't load the CTF container, continue on to the next * module. If our search was scoped to only one module (n = 1) * then return immediately, leaving dt_errno set to the error * from dt_module_getctf() on the module given by the caller. */ if (dt_module_getctf(dtp, dmp) == NULL) { if (n == 1) return (-1); continue; } /* * Look up the type in the module's CTF container. If our * match is a forward declaration tag, save this choice in * 'tip' and keep going in the hope that we will locate the * underlying structure definition. Otherwise just return. */ if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) { tip->dtt_object = dmp->dm_name; tip->dtt_ctfp = dmp->dm_ctfp; tip->dtt_type = id; if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve( dmp->dm_ctfp, id)) != CTF_K_FORWARD) return (0); found++; } } if (found == 0) return (dt_set_errno(dtp, EDT_NOTYPE)); return (0);}intdtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp, const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip){ dt_module_t *dmp; tip->dtt_object = NULL; tip->dtt_ctfp = NULL; tip->dtt_type = CTF_ERR; if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL) return (dt_set_errno(dtp, EDT_NOMOD)); if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) { dt_ident_t *idp = dt_idhash_lookup(dmp->dm_extern, sip->dts_name); if (idp == NULL) return (dt_set_errno(dtp, EDT_NOSYM)); tip->dtt_ctfp = idp->di_ctfp; tip->dtt_type = idp->di_type; } else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) { if (dt_module_getctf(dtp, dmp) == NULL) return (-1); /* errno is set for us */ tip->dtt_ctfp = dmp->dm_ctfp; tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id); if (tip->dtt_type == CTF_ERR) { dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp); return (dt_set_errno(dtp, EDT_CTF)); } } else { tip->dtt_ctfp = DT_FPTR_CTFP(dtp); tip->dtt_type = DT_FPTR_TYPE(dtp); } tip->dtt_object = dmp->dm_name; return (0);}static dtrace_objinfo_t *dt_module_info(const dt_module_t *dmp, dtrace_objinfo_t *dto){ dto->dto_name = dmp->dm_name; dto->dto_file = dmp->dm_file; dto->dto_id = dmp->dm_modid; dto->dto_flags = 0; if (dmp->dm_flags & DT_DM_KERNEL) dto->dto_flags |= DTRACE_OBJ_F_KERNEL; if (dmp->dm_flags & DT_DM_PRIMARY) dto->dto_flags |= DTRACE_OBJ_F_PRIMARY; dto->dto_text_va = dmp->dm_text_va; dto->dto_text_size = dmp->dm_text_size; dto->dto_data_va = dmp->dm_data_va; dto->dto_data_size = dmp->dm_data_size; dto->dto_bss_va = dmp->dm_bss_va; dto->dto_bss_size = dmp->dm_bss_size; return (dto);}intdtrace_object_iter(dtrace_hdl_t *dtp, dtrace_obj_f *func, void *data){ const dt_module_t *dmp = dt_list_next(&dtp->dt_modlist); dtrace_objinfo_t dto; int rv; for (; dmp != NULL; dmp = dt_list_next(dmp)) { if ((rv = (*func)(dtp, dt_module_info(dmp, &dto), data)) != 0) return (rv); } return (0);}intdtrace_object_info(dtrace_hdl_t *dtp, const char *object, dtrace_objinfo_t *dto){ dt_module_t *dmp; if (object == DTRACE_OBJ_EVERY || object == DTRACE_OBJ_KMODS || object == DTRACE_OBJ_UMODS || dto == NULL) return (dt_set_errno(dtp, EINVAL)); 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 */ (void) dt_module_info(dmp, dto); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -