/** * @brief Stores the data collected from a "/proc/meminfo" * * @param dpg Struct that polled data is added to. * @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful. * @return DTOP_POLL_OK - Poll of dpg successful. */ int dtop_meminfo_poll(struct dtop_data_point_gatherer *dpg) { char *data; int *line_len = malloc(sizeof(int) * ((struct dtop_meminfo_vars *) (dpg->priv))->line_count); int read; struct dt_procdict dict; int i, j, n, sum; read = dt_read_file(dpg->file, &data, DTOP_MEM_SIZE); if (read == 0 || data == 0) return DTOP_POLL_IO_ERR; sum = 0; /* Assigns each line read from the file, a length */ for (n = 0; n < ((struct dtop_meminfo_vars *) (dpg->priv))->line_count; n++) { line_len[n] = dt_read_line(((struct dtop_meminfo_vars *) (dpg->priv))->line[n], DTOP_MEM_LINE, data, DTOP_MEM_SIZE, sum); if (n <= (((struct dtop_meminfo_vars *) (dpg->priv))->line_count - 1)) { sum += (line_len[n] + 1); } } /* Stores dp names and values in dictionary */ for (i = 0; i < dpg->data_points_len; i++) dt_meminfo_parse(((struct dtop_meminfo_vars *) (dpg->priv))->line[i], line_len[i], i, &dict); /* Assigns the dp value to the dp struct */ for (j = 0; j < dpg->data_points_len; j++) { i = dt_find_dict_idx(dpg->data_points[j].name, &dict); if (i >= 0 && i < dict.max) { sscanf(dict.val[i], "%" PRIu64, &(dpg->data_points[i].data.d_ulong)); dpg->data_points[i].data.d_ulong *= 1024; if (dpg->data_points[i]. initial_data_populated == NOT_POPULATED) { dpg->data_points[i].initial_data.d_ulong = dpg->data_points[i].data.d_ulong; dpg->data_points[i].initial_data_populated = POPULATED; } } } dt_free(&data); free(line_len); return DTOP_POLL_OK; }
void dt_dof_fini(dtrace_hdl_t *dtp) { dt_dof_t *ddo = &dtp->dt_dof; dt_free(dtp, ddo->ddo_xlimport); dt_free(dtp, ddo->ddo_xlexport); dt_buf_destroy(dtp, &ddo->ddo_secs); dt_buf_destroy(dtp, &ddo->ddo_strs); dt_buf_destroy(dtp, &ddo->ddo_ldata); dt_buf_destroy(dtp, &ddo->ddo_udata); dt_buf_destroy(dtp, &ddo->ddo_probes); dt_buf_destroy(dtp, &ddo->ddo_args); dt_buf_destroy(dtp, &ddo->ddo_offs); dt_buf_destroy(dtp, &ddo->ddo_enoffs); dt_buf_destroy(dtp, &ddo->ddo_rels); dt_buf_destroy(dtp, &ddo->ddo_xlms); }
void * dtrace_getopt_dof(dtrace_hdl_t *dtp) { dof_hdr_t *dof; dof_sec_t *sec; dof_optdesc_t *dofo; int i, nopts = 0, len = sizeof (dof_hdr_t) + roundup(sizeof (dof_sec_t), sizeof (uint64_t)); for (i = 0; i < DTRACEOPT_MAX; i++) { if (dtp->dt_options[i] != DTRACEOPT_UNSET) nopts++; } len += sizeof (dof_optdesc_t) * nopts; if ((dof = dt_zalloc(dtp, len)) == NULL || dof_hdr(dtp, DOF_VERSION, dof) != 0) { dt_free(dtp, dof); return (NULL); } dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */ dof->dofh_loadsz = len; dof->dofh_filesz = len; /* * Fill in the option section header... */ sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t)); sec->dofs_type = DOF_SECT_OPTDESC; sec->dofs_align = sizeof (uint64_t); sec->dofs_flags = DOF_SECF_LOAD; sec->dofs_entsize = sizeof (dof_optdesc_t); dofo = (dof_optdesc_t *)((uintptr_t)sec + roundup(sizeof (dof_sec_t), sizeof (uint64_t))); sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof; sec->dofs_size = sizeof (dof_optdesc_t) * nopts; for (i = 0; i < DTRACEOPT_MAX; i++) { if (dtp->dt_options[i] == DTRACEOPT_UNSET) continue; dofo->dofo_option = i; dofo->dofo_strtab = DOF_SECIDX_NONE; dofo->dofo_value = dtp->dt_options[i]; dofo++; } return (dof); }
/** * @brief Scans "/proc/meminfo in order to autodetect dps. * * Searches through "/proc/meminfo" file for all available data * points to create as dp structs. * * @param storage dtop_meminfo_vars struct where relevant variables are stored. */ int dtop_meminfo_search(struct dtop_meminfo_vars *storage) { int i, k, n, sum; char *data; int *line_len = malloc(sizeof(int) * storage->line_count); int read; struct dt_procdict dict; struct dtop_data_point *data_points; storage->line = malloc(storage->line_count * sizeof(*storage->line)); for (i = 0; i < storage->line_count; i++) storage->line[i] = malloc(sizeof(char) * DTOP_MEM_LINE); read = dt_read_file("/proc/meminfo", &data, DTOP_MEM_SIZE); if (read == 0 || data == 0) return DTOP_POLL_IO_ERR; sum = 0; /* Assigns each line read from the file, a length */ for (n = 0; n < storage->line_count; n++) { line_len[n] = dt_read_line(storage->line[n], DTOP_MEM_LINE, data, DTOP_MEM_SIZE, sum); if (n < (storage->line_count - 1)) sum += (line_len[n] + 1); } /* Stores dp names in dictionary */ for (i = 0; i < (storage->line_count); i++) dt_parse_proc_same_line_key_and_val(storage->line[i], line_len[i], i, &dict); data_points = malloc (storage->line_count * sizeof(struct dtop_data_point)); k = 0; /* Creates a dtop_data_point struct for each dp found in the file */ for (i = 0; i < dict.max; i++) { data_points[i].name = dict.key[i]; data_points[i].prefix = NULL; data_points[i].type = DTOP_ULONG; k++; } /* Calls dpg constructor, dpg will point to the dp struct */ construct_meminfo_file_dpg(data_points, storage); free(line_len); dt_free(&data); return DTOP_POLL_OK; }
void dt_proc_hash_destroy(dtrace_hdl_t *dtp) { dt_proc_hash_t *dph = dtp->dt_procs; dt_proc_t *dpr; while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL) dt_proc_destroy(dtp, dpr->dpr_proc); dtp->dt_procs = NULL; dt_free(dtp, dph); }
static int dt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) { dt_dof_t *ddo = &dtp->dt_dof; uint_t i, nx = dtp->dt_xlatorid; assert(ddo->ddo_hdl == dtp); ddo->ddo_pgp = pgp; ddo->ddo_nsecs = 0; ddo->ddo_strsec = DOF_SECIDX_NONE; dt_free(dtp, ddo->ddo_xlimport); dt_free(dtp, ddo->ddo_xlexport); ddo->ddo_xlimport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); ddo->ddo_xlexport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); if (nx != 0 && (ddo->ddo_xlimport == NULL || ddo->ddo_xlexport == NULL)) return (-1); /* errno is set for us */ for (i = 0; i < nx; i++) { ddo->ddo_xlimport[i] = DOF_SECIDX_NONE; ddo->ddo_xlexport[i] = DOF_SECIDX_NONE; } dt_buf_reset(dtp, &ddo->ddo_secs); dt_buf_reset(dtp, &ddo->ddo_strs); dt_buf_reset(dtp, &ddo->ddo_ldata); dt_buf_reset(dtp, &ddo->ddo_udata); dt_buf_reset(dtp, &ddo->ddo_probes); dt_buf_reset(dtp, &ddo->ddo_args); dt_buf_reset(dtp, &ddo->ddo_offs); dt_buf_reset(dtp, &ddo->ddo_enoffs); dt_buf_reset(dtp, &ddo->ddo_rels); dt_buf_reset(dtp, &ddo->ddo_xlms); return (0); }
void * dt_buf_claim(dtrace_hdl_t *dtp, dt_buf_t *bp) { void *buf = bp->dbu_buf; if (bp->dbu_err != 0) { dt_free(dtp, buf); buf = NULL; } bp->dbu_buf = bp->dbu_ptr = NULL; bp->dbu_len = 0; return (buf); }
void dt_optimize(dt_t *dt) { dt_t *dtn; if (dt) { for (; 1; dt = dtn) { dtn = dt->DTnext; if (!dtn) break; switch (dt->dt) { case DT_azeros: if (dtn->dt == DT_1byte && dtn->DTonebyte == 0) { dt->DTazeros += 1; goto L1; } else if (dtn->dt == DT_azeros) { dt->DTazeros += dtn->DTazeros; goto L1; } break; case DT_1byte: if (dt->DTonebyte == 0) { if (dtn->dt == DT_1byte && dtn->DTonebyte == 0) { dt->DTazeros = 2; goto L1; } else if (dtn->dt == DT_azeros) { dt->DTazeros = 1 + dtn->DTazeros; L1: dt->dt = DT_azeros; dt->DTnext = dtn->DTnext; dtn->DTnext = NULL; dt_free(dtn); dtn = dt; } } break; } } } }
/*PRINTFLIKE3*/ static struct ps_prochandle * dt_proc_error(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *format, ...) { va_list ap; va_start(ap, format); dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); va_end(ap); if (dpr->dpr_proc != NULL) Prelease(dpr->dpr_proc, 0); dt_free(dtp, dpr); (void) dt_set_errno(dtp, EDT_COMPILER); return (NULL); }
static void dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts) { int state = Pstate(dpr->dpr_proc); dt_bkpt_t *dbp, *nbp; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) { if (delbkpts && dbp->dbp_active && state != PS_LOST && state != PS_UNDEAD) { (void) Pdelbkpt(dpr->dpr_proc, dbp->dbp_addr, dbp->dbp_instr); } nbp = dt_list_next(dbp); dt_list_delete(&dpr->dpr_bps, dbp); dt_free(dpr->dpr_hdl, dbp); } }
dt_inttab_t * dt_inttab_create(dtrace_hdl_t *dtp) { uint_t len = _dtrace_intbuckets; dt_inttab_t *ip; assert((len & (len - 1)) == 0); if ((ip = dt_zalloc(dtp, sizeof (dt_inttab_t))) == NULL || (ip->int_hash = dt_zalloc(dtp, sizeof (void *) * len)) == NULL) { dt_free(dtp, ip); return (NULL); } ip->int_hdl = dtp; ip->int_hashlen = len; return (ip); }
void dt_buf_write(dtrace_hdl_t *dtp, dt_buf_t *bp, const void *buf, size_t len, size_t align) { size_t off = (size_t)(bp->dbu_ptr - bp->dbu_buf); size_t adj = roundup(off, align) - off; if (bp->dbu_err != 0) { (void) dt_set_errno(dtp, bp->dbu_err); return; /* write silently fails */ } if (bp->dbu_ptr + adj + len > bp->dbu_buf + bp->dbu_len) { size_t new_len = bp->dbu_len * 2; uchar_t *new_buf; uint_t r = 1; while (bp->dbu_ptr + adj + len > bp->dbu_buf + new_len) { new_len *= 2; r++; } if ((new_buf = dt_zalloc(dtp, new_len)) == NULL) { bp->dbu_err = dtrace_errno(dtp); return; } bcopy(bp->dbu_buf, new_buf, off); dt_free(dtp, bp->dbu_buf); bp->dbu_buf = new_buf; bp->dbu_ptr = new_buf + off; bp->dbu_len = new_len; bp->dbu_resizes += r; } bp->dbu_ptr += adj; bcopy(buf, bp->dbu_ptr, len); bp->dbu_ptr += len; }
/*ARGSUSED*/ static int dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) { dtrace_optval_t size; void *p; if (arg == NULL || dt_optval_parse(arg, &size) != 0) return (dt_set_errno(dtp, EDT_BADOPTVAL)); if (size > SIZE_MAX) size = SIZE_MAX; if ((p = dt_zalloc(dtp, size)) == NULL) { do { size /= 2; } while ((p = dt_zalloc(dtp, size)) == NULL); } dt_free(dtp, p); return (0); }
/************************* * Finish and return completed data structure. */ dt_t *DtBuilder::finish() { /* Merge all the 0s at the start of the list * so we can later check for dtallzeros() */ if (head && head->dt == DT_azeros) { while (1) { dt_t *dtn = head->DTnext; if (!(dtn && dtn->dt == DT_azeros)) break; // combine head and dtn head->DTazeros += dtn->DTazeros; head->DTnext = dtn->DTnext; dtn->DTnext = NULL; dt_free(dtn); } } return head; }
/* * Create a new priority queue. * * size is the maximum number of items that will be stored in the priority * queue at one time. */ dt_pq_t * dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg) { dt_pq_t *p; assert(size > 1); if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL) return (NULL); p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0])); if (p->dtpq_items == NULL) { dt_free(dtp, p); return (NULL); } p->dtpq_hdl = dtp; p->dtpq_size = size; p->dtpq_last = 1; p->dtpq_value = value_cb; p->dtpq_arg = cb_arg; return (p); }
void dt_optimize(dt_t *dt) { dt_t *dtn; if (dt) { for (; 1; dt = dtn) { dtn = dt->DTnext; if (!dtn) break; if (dt->dt == DT_azeros) { if (dtn->dt == DT_azeros) { dt->DTazeros += dtn->DTazeros; dt->dt = DT_azeros; dt->DTnext = dtn->DTnext; dtn->DTnext = NULL; dt_free(dtn); dtn = dt; } } } } }
int dt_provider_xref(dtrace_hdl_t *dtp, dt_provider_t *pvp, id_t id) { size_t oldsize = BT_SIZEOFMAP(pvp->pv_xrmax); size_t newsize = BT_SIZEOFMAP(dtp->dt_xlatorid); assert(id >= 0 && id < dtp->dt_xlatorid); if (newsize > oldsize) { ulong_t *xrefs = dt_zalloc(dtp, newsize); if (xrefs == NULL) return (-1); bcopy(pvp->pv_xrefs, xrefs, oldsize); dt_free(dtp, pvp->pv_xrefs); pvp->pv_xrefs = xrefs; pvp->pv_xrmax = dtp->dt_xlatorid; } BT_SET(pvp->pv_xrefs, id); return (0); }
static int dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func) { dtrace_hdl_t *dtp = pp->dpp_dtp; dt_pcb_t *pcb = pp->dpp_pcb; dt_proc_t *dpr = pp->dpp_dpr; fasttrap_probe_spec_t *ftp; uint64_t off; char *end; uint_t nmatches = 0; ulong_t sz; int glob, err; int isdash = strcmp("-", func) == 0; pid_t pid; #if defined(sun) pid = Pstatus(pp->dpp_pr)->pr_pid; #else pid = proc_getpid(pp->dpp_pr); #endif dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj, func, pp->dpp_name); sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 : (symp->st_size - 1) * sizeof (ftp->ftps_offs[0])); if ((ftp = dt_alloc(dtp, sz)) == NULL) { dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz); return (1); /* errno is set for us */ } ftp->ftps_pid = pid; (void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func)); dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid, pp->dpp_obj); if (!isdash && gmatch("return", pp->dpp_name)) { if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp, pp->dpp_stret) < 0) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_CREATEFAIL, "failed to create return probe " "for '%s': %s", func, dtrace_errmsg(dtp, dtrace_errno(dtp)))); } nmatches++; } if (!isdash && gmatch("entry", pp->dpp_name)) { if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_CREATEFAIL, "failed to create entry probe " "for '%s': %s", func, dtrace_errmsg(dtp, dtrace_errno(dtp)))); } nmatches++; } glob = strisglob(pp->dpp_name); if (!glob && nmatches == 0) { off = strtoull(pp->dpp_name, &end, 16); if (*end != '\0') { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME, "'%s' is an invalid probe name", pp->dpp_name)); } if (off >= symp->st_size) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF, "offset 0x%llx outside of function '%s'", (u_longlong_t)off, func)); } err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp, symp, off); if (err == DT_PROC_ERR) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_CREATEFAIL, "failed to create probe at " "'%s+0x%llx': %s", func, (u_longlong_t)off, dtrace_errmsg(dtp, dtrace_errno(dtp)))); } if (err == DT_PROC_ALIGN) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN, "offset 0x%llx is not aligned on an instruction", (u_longlong_t)off)); } nmatches++; } else if (glob && !isdash) { if (dt_pid_create_glob_offset_probes(pp->dpp_pr, pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) { return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_CREATEFAIL, "failed to create offset probes in '%s': %s", func, dtrace_errmsg(dtp, dtrace_errno(dtp)))); } nmatches++; } pp->dpp_nmatches += nmatches; dt_free(dtp, ftp); return (0); }
dtrace_difo_t * dt_as(dt_pcb_t *pcb) { dtrace_hdl_t *dtp = pcb->pcb_hdl; dt_irlist_t *dlp = &pcb->pcb_ir; uint_t *labels = NULL; dt_irnode_t *dip; dtrace_difo_t *dp; dt_ident_t *idp; size_t n = 0; uint_t i; uint_t kmask, kbits, umask, ubits; uint_t krel = 0, urel = 0, xlrefs = 0; /* * Select bitmasks based upon the desired symbol linking policy. We * test (di_extern->di_flags & xmask) == xbits to determine if the * symbol should have a relocation entry generated in the loop below. * * DT_LINK_KERNEL = kernel symbols static, user symbols dynamic * DT_LINK_PRIMARY = primary kernel symbols static, others dynamic * DT_LINK_DYNAMIC = all symbols dynamic * DT_LINK_STATIC = all symbols static * * By 'static' we mean that we use the symbol's value at compile-time * in the final DIF. By 'dynamic' we mean that we create a relocation * table entry for the symbol's value so it can be relocated later. */ switch (dtp->dt_linkmode) { case DT_LINK_KERNEL: kmask = 0; kbits = -1u; umask = DT_IDFLG_USER; ubits = DT_IDFLG_USER; break; case DT_LINK_PRIMARY: kmask = DT_IDFLG_USER | DT_IDFLG_PRIM; kbits = 0; umask = DT_IDFLG_USER; ubits = DT_IDFLG_USER; break; case DT_LINK_DYNAMIC: kmask = DT_IDFLG_USER; kbits = 0; umask = DT_IDFLG_USER; ubits = DT_IDFLG_USER; break; case DT_LINK_STATIC: kmask = umask = 0; kbits = ubits = -1u; break; default: xyerror(D_UNKNOWN, "internal error -- invalid link mode %u\n", dtp->dt_linkmode); } assert(pcb->pcb_difo == NULL); pcb->pcb_difo = dt_zalloc(dtp, sizeof (dtrace_difo_t)); if ((dp = pcb->pcb_difo) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * dlp->dl_len); if (dp->dtdo_buf == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); if ((labels = dt_alloc(dtp, sizeof (uint_t) * dlp->dl_label)) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); /* * Make an initial pass through the instruction list, filling in the * instruction buffer with valid instructions and skipping labeled nops. * While doing this, we also fill in our labels[] translation table * and we count up the number of relocation table entries we will need. */ for (i = 0, dip = dlp->dl_list; dip != NULL; dip = dip->di_next) { if (dip->di_label != DT_LBL_NONE) labels[dip->di_label] = i; if (dip->di_label == DT_LBL_NONE || dip->di_instr != DIF_INSTR_NOP) dp->dtdo_buf[i++] = dip->di_instr; if (dip->di_extern == NULL) continue; /* no external references needed */ switch (DIF_INSTR_OP(dip->di_instr)) { case DIF_OP_SETX: idp = dip->di_extern; if ((idp->di_flags & kmask) == kbits) krel++; else if ((idp->di_flags & umask) == ubits) urel++; break; case DIF_OP_XLATE: case DIF_OP_XLARG: xlrefs++; break; default: xyerror(D_UNKNOWN, "unexpected assembler relocation " "for opcode 0x%x\n", DIF_INSTR_OP(dip->di_instr)); } } assert(i == dlp->dl_len); dp->dtdo_len = dlp->dl_len; /* * Make a second pass through the instructions, relocating each branch * label to the index of the final instruction in the buffer and noting * any other instruction-specific DIFO flags such as dtdo_destructive. */ for (i = 0; i < dp->dtdo_len; i++) { dif_instr_t instr = dp->dtdo_buf[i]; uint_t op = DIF_INSTR_OP(instr); if (op == DIF_OP_CALL) { if (DIF_INSTR_SUBR(instr) == DIF_SUBR_COPYOUT || DIF_INSTR_SUBR(instr) == DIF_SUBR_COPYOUTSTR) dp->dtdo_destructive = 1; continue; } if (op >= DIF_OP_BA && op <= DIF_OP_BLEU) { assert(DIF_INSTR_LABEL(instr) < dlp->dl_label); dp->dtdo_buf[i] = DIF_INSTR_BRANCH(op, labels[DIF_INSTR_LABEL(instr)]); } } dt_free(dtp, labels); pcb->pcb_asvidx = 0; /* * Allocate memory for the appropriate number of variable records and * then fill in each variable record. As we populate the variable * table we insert the corresponding variable names into the strtab. */ (void) dt_idhash_iter(dtp->dt_tls, dt_countvar, &n); (void) dt_idhash_iter(dtp->dt_globals, dt_countvar, &n); (void) dt_idhash_iter(pcb->pcb_locals, dt_countvar, &n); if (n != 0) { dp->dtdo_vartab = dt_alloc(dtp, n * sizeof (dtrace_difv_t)); dp->dtdo_varlen = (uint32_t)n; if (dp->dtdo_vartab == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); (void) dt_idhash_iter(dtp->dt_tls, dt_copyvar, pcb); (void) dt_idhash_iter(dtp->dt_globals, dt_copyvar, pcb); (void) dt_idhash_iter(pcb->pcb_locals, dt_copyvar, pcb); } /* * Allocate memory for the appropriate number of relocation table * entries based upon our kernel and user counts from the first pass. */ if (krel != 0) { dp->dtdo_kreltab = dt_alloc(dtp, krel * sizeof (dof_relodesc_t)); dp->dtdo_krelen = krel; if (dp->dtdo_kreltab == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); } if (urel != 0) { dp->dtdo_ureltab = dt_alloc(dtp, urel * sizeof (dof_relodesc_t)); dp->dtdo_urelen = urel; if (dp->dtdo_ureltab == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); } if (xlrefs != 0) { dp->dtdo_xlmtab = dt_zalloc(dtp, sizeof (dt_node_t *) * xlrefs); dp->dtdo_xlmlen = xlrefs; if (dp->dtdo_xlmtab == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); } /* * If any relocations are needed, make another pass through the * instruction list and fill in the relocation table entries. */ if (krel + urel + xlrefs != 0) { uint_t knodef = pcb->pcb_cflags & DTRACE_C_KNODEF; uint_t unodef = pcb->pcb_cflags & DTRACE_C_UNODEF; dof_relodesc_t *krp = dp->dtdo_kreltab; dof_relodesc_t *urp = dp->dtdo_ureltab; dt_node_t **xlp = dp->dtdo_xlmtab; i = 0; /* dtdo_buf[] index */ for (dip = dlp->dl_list; dip != NULL; dip = dip->di_next) { dof_relodesc_t *rp; ssize_t soff; uint_t nodef; if (dip->di_label != DT_LBL_NONE && dip->di_instr == DIF_INSTR_NOP) continue; /* skip label declarations */ i++; /* advance dtdo_buf[] index */ if (DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLATE || DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLARG) { assert(dp->dtdo_buf[i - 1] == dip->di_instr); dt_as_xlate(pcb, dp, i - 1, (uint_t) (xlp++ - dp->dtdo_xlmtab), dip->di_extern); continue; } if ((idp = dip->di_extern) == NULL) continue; /* no relocation entry needed */ if ((idp->di_flags & kmask) == kbits) { nodef = knodef; rp = krp++; } else if ((idp->di_flags & umask) == ubits) { nodef = unodef; rp = urp++; } else continue; if (!nodef) dt_as_undef(idp, i); assert(DIF_INSTR_OP(dip->di_instr) == DIF_OP_SETX); soff = dt_strtab_insert(pcb->pcb_strtab, idp->di_name); if (soff == -1L) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); if (soff > DIF_STROFF_MAX) longjmp(pcb->pcb_jmpbuf, EDT_STR2BIG); rp->dofr_name = (dof_stridx_t)soff; rp->dofr_type = DOF_RELO_SETX; rp->dofr_offset = DIF_INSTR_INTEGER(dip->di_instr) * sizeof (uint64_t); rp->dofr_data = 0; } assert(krp == dp->dtdo_kreltab + dp->dtdo_krelen); assert(urp == dp->dtdo_ureltab + dp->dtdo_urelen); assert(xlp == dp->dtdo_xlmtab + dp->dtdo_xlmlen); assert(i == dp->dtdo_len); } /* * Allocate memory for the compiled string table and then copy the * chunks from the string table into the final string buffer. */ if ((n = dt_strtab_size(pcb->pcb_strtab)) != 0) { if ((dp->dtdo_strtab = dt_alloc(dtp, n)) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); (void) dt_strtab_write(pcb->pcb_strtab, (dt_strtab_write_f *)dt_copystr, pcb); dp->dtdo_strlen = (uint32_t)n; } /* * Allocate memory for the compiled integer table and then copy the * integer constants from the table into the final integer buffer. */ if ((n = dt_inttab_size(pcb->pcb_inttab)) != 0) { if ((dp->dtdo_inttab = dt_alloc(dtp, n * sizeof (uint64_t))) == NULL) longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); dt_inttab_write(pcb->pcb_inttab, dp->dtdo_inttab); dp->dtdo_intlen = (uint32_t)n; } /* * Fill in the DIFO return type from the type associated with the * node saved in pcb_dret, and then clear pcb_difo and pcb_dret * now that the assembler has completed successfully. */ dt_node_diftype(dtp, pcb->pcb_dret, &dp->dtdo_rtype); pcb->pcb_difo = NULL; pcb->pcb_dret = NULL; if (pcb->pcb_cflags & DTRACE_C_DIFV) dt_dis(dp, stderr); return (dp); }
/* * Pop the topmost PCB from the PCB stack and destroy any data structures that * are associated with it. If 'err' is non-zero, destroy any intermediate * state that is left behind as part of a compilation that has failed. */ void dt_pcb_pop(dtrace_hdl_t *dtp, int err) { dt_pcb_t *pcb = yypcb; uint_t i; assert(pcb != NULL); assert(pcb == dtp->dt_pcb); while (pcb->pcb_dstack.ds_next != NULL) (void) dt_scope_pop(); dt_scope_destroy(&pcb->pcb_dstack); dt_irlist_destroy(&pcb->pcb_ir); dt_node_link_free(&pcb->pcb_list); dt_node_link_free(&pcb->pcb_hold); if (err != 0) { dt_xlator_t *dxp, *nxp; dt_provider_t *pvp, *nvp; if (pcb->pcb_prog != NULL) dt_program_destroy(dtp, pcb->pcb_prog); if (pcb->pcb_stmt != NULL) dtrace_stmt_destroy(dtp, pcb->pcb_stmt); if (pcb->pcb_ecbdesc != NULL) dt_ecbdesc_release(dtp, pcb->pcb_ecbdesc); for (dxp = dt_list_next(&dtp->dt_xlators); dxp; dxp = nxp) { nxp = dt_list_next(dxp); if (dxp->dx_gen == dtp->dt_gen) dt_xlator_destroy(dtp, dxp); } for (pvp = dt_list_next(&dtp->dt_provlist); pvp; pvp = nvp) { nvp = dt_list_next(pvp); if (pvp->pv_gen == dtp->dt_gen) dt_provider_destroy(dtp, pvp); } (void) dt_idhash_iter(dtp->dt_aggs, dt_pcb_pop_ident, dtp); dt_idhash_update(dtp->dt_aggs); (void) dt_idhash_iter(dtp->dt_globals, dt_pcb_pop_ident, dtp); dt_idhash_update(dtp->dt_globals); (void) dt_idhash_iter(dtp->dt_tls, dt_pcb_pop_ident, dtp); dt_idhash_update(dtp->dt_tls); (void) ctf_discard(dtp->dt_cdefs->dm_ctfp); (void) ctf_discard(dtp->dt_ddefs->dm_ctfp); } if (pcb->pcb_pragmas != NULL) dt_idhash_destroy(pcb->pcb_pragmas); if (pcb->pcb_locals != NULL) dt_idhash_destroy(pcb->pcb_locals); if (pcb->pcb_idents != NULL) dt_idhash_destroy(pcb->pcb_idents); if (pcb->pcb_inttab != NULL) dt_inttab_destroy(pcb->pcb_inttab); if (pcb->pcb_strtab != NULL) dt_strtab_destroy(pcb->pcb_strtab); if (pcb->pcb_regs != NULL) dt_regset_destroy(pcb->pcb_regs); for (i = 0; i < pcb->pcb_asxreflen; i++) dt_free(dtp, pcb->pcb_asxrefs[i]); dt_free(dtp, pcb->pcb_asxrefs); dt_difo_free(dtp, pcb->pcb_difo); free(pcb->pcb_filetag); free(pcb->pcb_sflagv); dtp->dt_pcb = pcb->pcb_prev; bzero(pcb, sizeof (dt_pcb_t)); yyinit(dtp->dt_pcb); }
static void dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) { dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); dt_proc_hash_t *dph = dtp->dt_procs; dt_proc_notify_t *npr, **npp; int rflag; assert(dpr != NULL); /* * If neither PR_KLC nor PR_RLC is set, then the process is stopped by * an external debugger and we were waiting in dt_proc_waitrun(). * Leave the process in this condition using PRELEASE_HANG. */ printf("dt_proc_destroy flags=%d\n", Pstatus(dpr->dpr_proc)->pr_flags); if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) { dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid); rflag = PRELEASE_HANG; } else { dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); rflag = 0; /* apply kill or run-on-last-close */ } if (dpr->dpr_tid) { /* * Set the dpr_quit flag to tell the daemon thread to exit. We * send it a SIGCANCEL to poke it out of PCWSTOP or any other * long-term /proc system call. Our daemon threads have POSIX * cancellation disabled, so EINTR will be the only effect. We * then wait for dpr_done to indicate the thread has exited. * * We can't use pthread_kill() to send SIGCANCEL because the * interface forbids it and we can't use pthread_cancel() * because with cancellation disabled it won't actually * send SIGCANCEL to the target thread, so we use _lwp_kill() * to do the job. This is all built on evil knowledge of * the details of the cancellation mechanism in libc. */ (void) pthread_mutex_lock(&dpr->dpr_lock); dpr->dpr_quit = B_TRUE; #if defined(sun) (void) _lwp_kill(dpr->dpr_tid, SIGCANCEL); #else (void) pthread_kill(dpr->dpr_tid, SIGUSR1); #endif /* * If the process is currently idling in dt_proc_stop(), re- * enable breakpoints and poke it into running again. */ if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { dt_proc_bpenable(dpr); dpr->dpr_stop &= ~DT_PROC_STOP_IDLE; (void) pthread_cond_broadcast(&dpr->dpr_cv); } while (!dpr->dpr_done) (void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock); (void) pthread_mutex_unlock(&dpr->dpr_lock); } /* * Before we free the process structure, remove this dt_proc_t from the * lookup hash, and then walk the dt_proc_hash_t's notification list * and remove this dt_proc_t if it is enqueued. */ (void) pthread_mutex_lock(&dph->dph_lock); (void) dt_proc_lookup(dtp, P, B_TRUE); npp = &dph->dph_notify; while ((npr = *npp) != NULL) { if (npr->dprn_dpr == dpr) { *npp = npr->dprn_next; dt_free(dtp, npr); } else { npp = &npr->dprn_next; } } (void) pthread_mutex_unlock(&dph->dph_lock); /* * Remove the dt_proc_list from the LRU list, release the underlying * libproc handle, and free our dt_proc_t data structure. */ if (dpr->dpr_cacheable) { assert(dph->dph_lrucnt != 0); dph->dph_lrucnt--; } dt_list_delete(&dph->dph_lrulist, dpr); Prelease(dpr->dpr_proc, rflag); dt_free(dtp, dpr); }
static int dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max) { int maxformat; dtrace_fmtdesc_t fmt; void *result; if (rec->dtrd_format == 0) return (0); if (rec->dtrd_format <= *max && (*data)[rec->dtrd_format - 1] != NULL) { return (0); } bzero(&fmt, sizeof (fmt)); fmt.dtfd_format = rec->dtrd_format; fmt.dtfd_string = NULL; fmt.dtfd_length = 0; if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) return (dt_set_errno(dtp, errno)); if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL) return (dt_set_errno(dtp, EDT_NOMEM)); if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { free(fmt.dtfd_string); return (dt_set_errno(dtp, errno)); } while (rec->dtrd_format > (maxformat = *max)) { int new_max = maxformat ? (maxformat << 1) : 1; size_t nsize = new_max * sizeof (void *); size_t osize = maxformat * sizeof (void *); void **new_data = dt_zalloc(dtp, nsize); if (new_data == NULL) { dt_free(dtp, fmt.dtfd_string); return (dt_set_errno(dtp, EDT_NOMEM)); } bcopy(*data, new_data, osize); free(*data); *data = new_data; *max = new_max; } switch (rec->dtrd_action) { case DTRACEACT_DIFEXPR: result = fmt.dtfd_string; break; case DTRACEACT_PRINTA: result = dtrace_printa_create(dtp, fmt.dtfd_string); dt_free(dtp, fmt.dtfd_string); break; default: result = dtrace_printf_create(dtp, fmt.dtfd_string); dt_free(dtp, fmt.dtfd_string); break; } if (result == NULL) return (-1); (*data)[rec->dtrd_format - 1] = result; return (0); }
/* * dt_free_w_debug * * Wrapper for the dt_free function used in debug mode to print out info on * what memory has been freed and from where. * * DT_FREE resolves to this when DEBUG is defined. * * Parameters: object - The object to be freed. * file - The value of __FILE__ in the calling function. * line - The line number of the calling function. */ void dt_free_w_debug(void *object, char *file, int line) { dt_free(object); DT_MEM_LOG("Freed object: %s(%i)\n", file, line); }
int main(void) { struct dt_node *root, *c1, *c2, *gc1, *gc2, *gc3, *ggc1, *i; const struct dt_property *p; struct dt_property *p2; unsigned int n; root = dt_new_root("root"); assert(!list_top(&root->properties, struct dt_property, list)); c1 = dt_new(root, "c1"); assert(!list_top(&c1->properties, struct dt_property, list)); c2 = dt_new(root, "c2"); assert(!list_top(&c2->properties, struct dt_property, list)); gc1 = dt_new(c1, "gc1"); assert(!list_top(&gc1->properties, struct dt_property, list)); gc2 = dt_new(c1, "gc2"); assert(!list_top(&gc2->properties, struct dt_property, list)); gc3 = dt_new(c1, "gc3"); assert(!list_top(&gc3->properties, struct dt_property, list)); ggc1 = dt_new(gc1, "ggc1"); assert(!list_top(&ggc1->properties, struct dt_property, list)); for (n = 0, i = dt_first(root); i; i = dt_next(root, i), n++) { assert(!list_top(&i->properties, struct dt_property, list)); dt_add_property_cells(i, "visited", 1); } assert(n == 6); for (n = 0, i = dt_first(root); i; i = dt_next(root, i), n++) { p = list_top(&i->properties, struct dt_property, list); assert(strcmp(p->name, "visited") == 0); assert(p->len == sizeof(u32)); assert(fdt32_to_cpu(*(u32 *)p->prop) == 1); } assert(n == 6); dt_add_property_cells(c1, "some-property", 1, 2, 3); p = dt_find_property(c1, "some-property"); assert(p); assert(strcmp(p->name, "some-property") == 0); assert(p->len == sizeof(u32) * 3); assert(fdt32_to_cpu(*(u32 *)p->prop) == 1); assert(fdt32_to_cpu(*((u32 *)p->prop + 1)) == 2); assert(fdt32_to_cpu(*((u32 *)p->prop + 2)) == 3); /* Test freeing a single node */ assert(!list_empty(&gc1->children)); dt_free(ggc1); assert(list_empty(&gc1->children)); /* Test rodata logic. */ assert(!is_rodata("hello")); assert(is_rodata(__rodata_start)); strcpy(__rodata_start, "name"); ggc1 = dt_new(root, __rodata_start); assert(ggc1->name == __rodata_start); /* Test string node. */ dt_add_property_string(ggc1, "somestring", "someval"); assert(dt_has_node_property(ggc1, "somestring", "someval")); assert(!dt_has_node_property(ggc1, "somestrin", "someval")); assert(!dt_has_node_property(ggc1, "somestring", "someva")); assert(!dt_has_node_property(ggc1, "somestring", "somevale")); /* Test resizing property. */ p = p2 = __dt_find_property(c1, "some-property"); assert(p); n = p2->len; while (p2 == p) { n *= 2; dt_resize_property(&p2, n); } assert(dt_find_property(c1, "some-property") == p2); list_check(&c1->properties, "properties after resizing"); dt_del_property(c1, p2); list_check(&c1->properties, "properties after delete"); /* No leaks for valgrind! */ dt_free(root); return 0; }
void dtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof) { dt_free(dtp, dof); }
int main(int argc, char **argv) { struct dt_dentry *probe; struct cfwk_dir curdir; int full = 0; int lookup = 0; char *host; int i; char *oldtree = NULL; FILE *oldfile; char *port = NULL; char *server_cp = NULL; CURLcode rcode; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; if (argv[i][1] == '-' && argv[i][2] == 0) { i++; break; } switch (argv[i][1]) { case 'f': full = 1; break; case 'p': port = &argv[i][2]; break; case 'l': lookup = 1; break; case 'C': i++; if (i >= argc) usage(argv[0], ESTAT_FAILURE); server_cp = argv[i]; break; case 'u': i++; if (i >= argc) usage(argv[0], ESTAT_FAILURE); oldtree = argv[i]; break; case 'h': usage(argv[0], ESTAT_SUCCESS); default: usage(argv[0], ESTAT_FAILURE); } } if (i + 1 != argc) usage(argv[0], ESTAT_FAILURE); if ((rcode = curl_global_init(CURL_GLOBAL_NOTHING)) != CURLE_OK) { LOG_ERR("curl_global_init() returned non-zero: %s\n", curl_easy_strerror(rcode)); exit(ESTAT_FAILURE); } host = argv[i]; if (cfwk_open(&curdir, host, port, server_cp) < 0) exit(ESTAT_NOCONNECT); if (lookup) { probe = cfwk_walker.readdir(&curdir); cfwk_close(&curdir); if (probe != NULL) { dt_free(probe); exit(ESTAT_SUCCESS); } else exit(ESTAT_FAILURE); } if (full) dt_full(&cfwk_walker, &curdir); else if (oldtree) { if ((oldfile = fopen(oldtree, "r")) == NULL) { LOG_ERRNO("Can't open file %s\n", oldtree); exit(ESTAT_FAILURE); } dt_diff(oldfile, &cfwk_walker, &curdir); fclose(oldfile); } else dt_reverse(&cfwk_walker, &curdir); cfwk_close(&curdir); curl_global_cleanup(); return ESTAT_SUCCESS; }
int main(void) { const struct dt_property *names, *ranges; struct mem_region *r; unsigned int i, l, c; uint64_t *rangep; const char *name; void *buf; /* Use malloc for the heap, so valgrind can find issues. */ skiboot_heap.start = (long)real_malloc(TEST_HEAP_SIZE); skiboot_heap.len = TEST_HEAP_SIZE; skiboot_os_reserve.len = skiboot_heap.start; dt_root = dt_new_root(""); dt_add_property_cells(dt_root, "#address-cells", 2); dt_add_property_cells(dt_root, "#size-cells", 2); buf = real_malloc(1024*1024); add_mem_node((unsigned long)buf, 1024*1024); /* Now convert. */ mem_region_init(); /* create our reservations */ for (i = 0; i < ARRAY_SIZE(test_regions); i++) mem_reserve(test_regions[i].name, test_regions[i].addr, 0x1000); /* release unused */ mem_region_release_unused(); /* and create reservations */ mem_region_add_dt_reserved(); /* ensure we can't create further reservations */ r = new_region("test.4", 0x5000, 0x1000, NULL, REGION_RESERVED); assert(!add_region(r)); /* check dt properties */ names = dt_find_property(dt_root, "reserved-names"); ranges = dt_find_property(dt_root, "reserved-ranges"); assert(names && ranges); /* walk through names & ranges properies, ensuring that the test * regions are all present */ for (name = names->prop, rangep = (uint64_t *)ranges->prop, c = 0; name < names->prop + names->len; name += l, rangep += 2) { uint64_t addr; addr = dt_get_number(rangep, 2); l = strlen(name) + 1; for (i = 0; i < ARRAY_SIZE(test_regions); i++) { if (strcmp(test_regions[i].name, name)) continue; assert(test_regions[i].addr == addr); assert(!test_regions[i].found); test_regions[i].found = true; c++; } } assert(c == ARRAY_SIZE(test_regions)); dt_free(dt_root); real_free(buf); real_free((void *)(long)skiboot_heap.start); return 0; }
dt_xlator_t * dt_xlator_create(dtrace_hdl_t *dtp, const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst, const char *name, dt_node_t *members, dt_node_t *nodes) { dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t)); dtrace_typeinfo_t ptr = *dst; dt_xlator_t **map; dt_node_t *dnp; uint_t kind; if (dxp == NULL) return (NULL); dxp->dx_hdl = dtp; dxp->dx_id = dtp->dt_xlatorid++; dxp->dx_gen = dtp->dt_gen; dxp->dx_arg = -1; if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) { dt_free(dtp, dxp); return (NULL); } dt_list_append(&dtp->dt_xlators, dxp); bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id); dt_free(dtp, dtp->dt_xlatormap); dtp->dt_xlatormap = map; dtp->dt_xlatormap[dxp->dx_id] = dxp; if (dt_type_pointer(&ptr) == -1) { ptr.dtt_ctfp = NULL; ptr.dtt_type = CTF_ERR; } dxp->dx_ident = dt_ident_create(name ? name : "T", DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0, _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); if (dxp->dx_ident == NULL) goto err; /* no memory for identifier */ dxp->dx_ident->di_ctfp = src->dtt_ctfp; dxp->dx_ident->di_type = src->dtt_type; /* * If an input parameter name is given, this is a static translator * definition: create an idhash and identifier for the parameter. */ if (name != NULL) { dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0); if (dxp->dx_locals == NULL) goto err; /* no memory for identifier hash */ dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident); } dxp->dx_souid.di_name = "translator"; dxp->dx_souid.di_kind = DT_IDENT_XLSOU; dxp->dx_souid.di_flags = DT_IDFLG_REF; dxp->dx_souid.di_id = dxp->dx_id; dxp->dx_souid.di_attr = _dtrace_defattr; dxp->dx_souid.di_ops = &dt_idops_thaw; dxp->dx_souid.di_data = dxp; dxp->dx_souid.di_ctfp = dst->dtt_ctfp; dxp->dx_souid.di_type = dst->dtt_type; dxp->dx_souid.di_gen = dtp->dt_gen; dxp->dx_ptrid.di_name = "translator"; dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR; dxp->dx_ptrid.di_flags = DT_IDFLG_REF; dxp->dx_ptrid.di_id = dxp->dx_id; dxp->dx_ptrid.di_attr = _dtrace_defattr; dxp->dx_ptrid.di_ops = &dt_idops_thaw; dxp->dx_ptrid.di_data = dxp; dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp; dxp->dx_ptrid.di_type = ptr.dtt_type; dxp->dx_ptrid.di_gen = dtp->dt_gen; /* * If a deferred pragma is pending on the keyword "translator", run all * the deferred pragmas on dx_souid and then copy results to dx_ptrid. * See the code in dt_pragma.c for details on deferred ident pragmas. */ if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL && dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) { dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid); dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr; dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers; } dxp->dx_src_ctfp = src->dtt_ctfp; dxp->dx_src_type = src->dtt_type; dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type); dxp->dx_dst_ctfp = dst->dtt_ctfp; dxp->dx_dst_type = dst->dtt_type; dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type); kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base); assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION); /* * If no input parameter is given, we're making a dynamic translator: * create member nodes for every member of the output type. Otherwise * retain the member and allocation node lists presented by the parser. */ if (name == NULL) { if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base, dt_xlator_create_member, dxp) != 0) goto err; } else { dxp->dx_members = members; dxp->dx_nodes = nodes; } /* * Assign member IDs to each member and allocate space for DIFOs * if and when this translator is eventually compiled. */ for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { dnp->dn_membxlator = dxp; dnp->dn_membid = dxp->dx_nmembers++; } dxp->dx_membdif = dt_zalloc(dtp, sizeof (dtrace_difo_t *) * dxp->dx_nmembers); if (dxp->dx_membdif == NULL) { dxp->dx_nmembers = 0; goto err; } return (dxp); err: dt_xlator_destroy(dtp, dxp); return (NULL); }
int dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp, const char *fname, const char *rname, uint32_t offset, int isenabled) { dtrace_hdl_t *dtp = pvp->pv_hdl; dt_probe_instance_t *pip; uint32_t **offs; uint_t *noffs, *maxoffs; assert(fname != NULL); for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { if (strcmp(pip->pi_fname, fname) == 0 && ((rname == NULL && pip->pi_rname == NULL) || (rname != NULL && pip->pi_rname != NULL && strcmp(pip->pi_rname, rname) == 0))) break; } if (pip == NULL) { if ((pip = dt_zalloc(dtp, sizeof (*pip))) == NULL) return (-1); if ((pip->pi_offs = dt_zalloc(dtp, sizeof (uint32_t))) == NULL) goto nomem; if ((pip->pi_enoffs = dt_zalloc(dtp, sizeof (uint32_t))) == NULL) goto nomem; if ((pip->pi_fname = strdup(fname)) == NULL) goto nomem; if (rname != NULL && (pip->pi_rname = strdup(rname)) == NULL) goto nomem; pip->pi_noffs = 0; pip->pi_maxoffs = 1; pip->pi_nenoffs = 0; pip->pi_maxenoffs = 1; pip->pi_next = prp->pr_inst; prp->pr_inst = pip; } if (isenabled) { offs = &pip->pi_enoffs; noffs = &pip->pi_nenoffs; maxoffs = &pip->pi_maxenoffs; } else { offs = &pip->pi_offs; noffs = &pip->pi_noffs; maxoffs = &pip->pi_maxoffs; } if (*noffs == *maxoffs) { uint_t new_max = *maxoffs * 2; uint32_t *new_offs = dt_alloc(dtp, sizeof (uint32_t) * new_max); if (new_offs == NULL) return (-1); bcopy(*offs, new_offs, sizeof (uint32_t) * *maxoffs); dt_free(dtp, *offs); *maxoffs = new_max; *offs = new_offs; } dt_dprintf("defined probe %s %s:%s %s() +0x%x (%s)\n", isenabled ? "(is-enabled)" : "", pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, fname, offset, rname != NULL ? rname : fname); assert(*noffs < *maxoffs); (*offs)[(*noffs)++] = offset; return (0); nomem: dt_free(dtp, pip->pi_fname); dt_free(dtp, pip->pi_enoffs); dt_free(dtp, pip->pi_offs); dt_free(dtp, pip); return (dt_set_errno(dtp, EDT_NOMEM)); }
/* * The #pragma depends_on directive can be used to express a dependency on a * module, provider or library which if not present will cause processing to * abort. */ static void dt_pragma_depends(const char *prname, dt_node_t *cnp) { dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *nnp = cnp ? cnp->dn_list : NULL; int found; dt_lib_depend_t *dld; char lib[MAXPATHLEN]; size_t plen; char *provs, *cpy, *tok; if (cnp == NULL || nnp == NULL || cnp->dn_kind != DT_NODE_IDENT || nnp->dn_kind != DT_NODE_IDENT) { xyerror(D_PRAGMA_MALFORM, "malformed #pragma %s " "<class> <name>\n", prname); } if (strcmp(cnp->dn_string, "provider") == 0) { /* * First try to get the provider list using the * debug.dtrace.providers sysctl, since that'll work even if * we're not running as root. */ provs = NULL; if (sysctlbyname("debug.dtrace.providers", NULL, &plen, NULL, 0) || ((provs = dt_alloc(dtp, plen)) == NULL) || sysctlbyname("debug.dtrace.providers", provs, &plen, NULL, 0)) found = dt_provider_lookup(dtp, nnp->dn_string) != NULL; else { found = B_FALSE; for (cpy = provs; (tok = strsep(&cpy, " ")) != NULL; ) if (strcmp(tok, nnp->dn_string) == 0) { found = B_TRUE; break; } if (found == B_FALSE) found = dt_provider_lookup(dtp, nnp->dn_string) != NULL; } if (provs != NULL) dt_free(dtp, provs); } else if (strcmp(cnp->dn_string, "module") == 0) { dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string); found = mp != NULL && dt_module_getctf(dtp, mp) != NULL; } else if (strcmp(cnp->dn_string, "library") == 0) { if (yypcb->pcb_cflags & DTRACE_C_CTL) { assert(dtp->dt_filetag != NULL); dt_pragma_depends_finddep(dtp, nnp->dn_string, lib, sizeof (lib)); dld = dt_lib_depend_lookup(&dtp->dt_lib_dep, dtp->dt_filetag); assert(dld != NULL); if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies, lib)) != 0) { xyerror(D_PRAGMA_DEPEND, "failed to add dependency %s:%s\n", lib, dtrace_errmsg(dtp, dtrace_errno(dtp))); } } else { /* * By this point we have already performed a topological * sort of the dependencies; we process this directive * as satisfied as long as the dependency was properly * loaded. */ if (dtp->dt_filetag == NULL) xyerror(D_PRAGMA_DEPEND, "main program may " "not explicitly depend on a library"); dld = dt_lib_depend_lookup(&dtp->dt_lib_dep, dtp->dt_filetag); assert(dld != NULL); dt_pragma_depends_finddep(dtp, nnp->dn_string, lib, sizeof (lib)); dld = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted, lib); assert(dld != NULL); if (!dld->dtld_loaded) xyerror(D_PRAGMA_DEPEND, "program requires " "library \"%s\" which failed to load", lib); } found = B_TRUE; } else { xyerror(D_PRAGMA_INVAL, "invalid class %s " "specified by #pragma %s\n", cnp->dn_string, prname); } if (!found) { xyerror(D_PRAGMA_DEPEND, "program requires %s %s\n", cnp->dn_string, nnp->dn_string); } }