PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c

https://github.com/blacklion/GEOM-Events
C | 511 lines | 411 code | 64 blank | 36 comment | 40 complexity | 982e1c29b87f501263088054ef03cbc1 MD5 | raw file
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License, Version 1.0 only
  6. * (the "License"). You may not use this file except in compliance
  7. * with the License.
  8. *
  9. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. * or http://www.opensolaris.org/os/licensing.
  11. * See the License for the specific language governing permissions
  12. * and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL HEADER in each
  15. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. * If applicable, add the following below this CDDL HEADER, with the
  17. * fields enclosed by brackets "[]" replaced with your own identifying
  18. * information: Portions Copyright [yyyy] [name of copyright owner]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. #pragma ident "%Z%%M% %I% %E% SMI"
  27. #include <strings.h>
  28. #include <stdio.h>
  29. #include <dt_impl.h>
  30. #include <dt_ident.h>
  31. /*ARGSUSED*/
  32. static void
  33. dt_dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  34. {
  35. (void) fprintf(fp, "%-4s %%r%u, %%r%u, %%r%u", name,
  36. DIF_INSTR_R1(in), DIF_INSTR_R2(in), DIF_INSTR_RD(in));
  37. }
  38. /*ARGSUSED*/
  39. static void
  40. dt_dis_branch(const dtrace_difo_t *dp, const char *name,
  41. dif_instr_t in, FILE *fp)
  42. {
  43. (void) fprintf(fp, "%-4s %u", name, DIF_INSTR_LABEL(in));
  44. }
  45. /*ARGSUSED*/
  46. static void
  47. dt_dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  48. {
  49. (void) fprintf(fp, "%-4s [%%r%u], %%r%u", name,
  50. DIF_INSTR_R1(in), DIF_INSTR_RD(in));
  51. }
  52. /*ARGSUSED*/
  53. static void
  54. dt_dis_store(const dtrace_difo_t *dp, const char *name,
  55. dif_instr_t in, FILE *fp)
  56. {
  57. (void) fprintf(fp, "%-4s %%r%u, [%%r%u]", name,
  58. DIF_INSTR_R1(in), DIF_INSTR_RD(in));
  59. }
  60. /*ARGSUSED*/
  61. static void
  62. dt_dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  63. {
  64. (void) fprintf(fp, "%s", name);
  65. }
  66. /*ARGSUSED*/
  67. static void
  68. dt_dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  69. {
  70. (void) fprintf(fp, "%-4s %%r%u, %%r%u", name,
  71. DIF_INSTR_R1(in), DIF_INSTR_RD(in));
  72. }
  73. /*ARGSUSED*/
  74. static void
  75. dt_dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  76. {
  77. (void) fprintf(fp, "%-4s %%r%u, %%r%u", name,
  78. DIF_INSTR_R1(in), DIF_INSTR_R2(in));
  79. }
  80. /*ARGSUSED*/
  81. static void
  82. dt_dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  83. {
  84. (void) fprintf(fp, "%-4s %%r%u", name, DIF_INSTR_R1(in));
  85. }
  86. static const char *
  87. dt_dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
  88. {
  89. const dtrace_difv_t *dvp = dp->dtdo_vartab;
  90. uint_t i;
  91. for (i = 0; i < dp->dtdo_varlen; i++, dvp++) {
  92. if (dvp->dtdv_id == id && dvp->dtdv_scope == scope) {
  93. if (dvp->dtdv_name < dp->dtdo_strlen)
  94. return (dp->dtdo_strtab + dvp->dtdv_name);
  95. break;
  96. }
  97. }
  98. return (NULL);
  99. }
  100. static uint_t
  101. dt_dis_scope(const char *name)
  102. {
  103. switch (name[2]) {
  104. case 'l': return (DIFV_SCOPE_LOCAL);
  105. case 't': return (DIFV_SCOPE_THREAD);
  106. case 'g': return (DIFV_SCOPE_GLOBAL);
  107. default: return (-1u);
  108. }
  109. }
  110. static void
  111. dt_dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  112. {
  113. uint_t var = DIF_INSTR_R1(in);
  114. const char *vname;
  115. (void) fprintf(fp, "%-4s DT_VAR(%u), %%r%u, %%r%u", name,
  116. var, DIF_INSTR_R2(in), DIF_INSTR_RD(in));
  117. if ((vname = dt_dis_varname(dp, var, dt_dis_scope(name))) != NULL)
  118. (void) fprintf(fp, "\t\t! DT_VAR(%u) = \"%s\"", var, vname);
  119. }
  120. static void
  121. dt_dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  122. {
  123. uint_t var = DIF_INSTR_VAR(in);
  124. const char *vname;
  125. (void) fprintf(fp, "%-4s DT_VAR(%u), %%r%u",
  126. name, var, DIF_INSTR_RD(in));
  127. if ((vname = dt_dis_varname(dp, var, dt_dis_scope(name))) != NULL)
  128. (void) fprintf(fp, "\t\t! DT_VAR(%u) = \"%s\"", var, vname);
  129. }
  130. static void
  131. dt_dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  132. {
  133. uint_t var = DIF_INSTR_VAR(in);
  134. const char *vname;
  135. (void) fprintf(fp, "%-4s %%r%u, DT_VAR(%u)",
  136. name, DIF_INSTR_RS(in), var);
  137. if ((vname = dt_dis_varname(dp, var, dt_dis_scope(name))) != NULL)
  138. (void) fprintf(fp, "\t\t! DT_VAR(%u) = \"%s\"", var, vname);
  139. }
  140. static void
  141. dt_dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  142. {
  143. uint_t intptr = DIF_INSTR_INTEGER(in);
  144. (void) fprintf(fp, "%-4s DT_INTEGER[%u], %%r%u", name,
  145. intptr, DIF_INSTR_RD(in));
  146. if (intptr < dp->dtdo_intlen) {
  147. (void) fprintf(fp, "\t\t! 0x%llx",
  148. (u_longlong_t)dp->dtdo_inttab[intptr]);
  149. }
  150. }
  151. static void
  152. dt_dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  153. {
  154. uint_t strptr = DIF_INSTR_STRING(in);
  155. (void) fprintf(fp, "%-4s DT_STRING[%u], %%r%u", name,
  156. strptr, DIF_INSTR_RD(in));
  157. if (strptr < dp->dtdo_strlen)
  158. (void) fprintf(fp, "\t\t! \"%s\"", dp->dtdo_strtab + strptr);
  159. }
  160. /*ARGSUSED*/
  161. static void
  162. dt_dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  163. {
  164. (void) fprintf(fp, "%-4s %%r%u", name, DIF_INSTR_RD(in));
  165. }
  166. /*ARGSUSED*/
  167. static void
  168. dt_dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
  169. {
  170. uint_t subr = DIF_INSTR_SUBR(in);
  171. (void) fprintf(fp, "%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
  172. name, subr, DIF_INSTR_RD(in), dtrace_subrstr(NULL, subr));
  173. }
  174. /*ARGSUSED*/
  175. static void
  176. dt_dis_pushts(const dtrace_difo_t *dp,
  177. const char *name, dif_instr_t in, FILE *fp)
  178. {
  179. static const char *const tnames[] = { "D type", "string" };
  180. uint_t type = DIF_INSTR_TYPE(in);
  181. (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
  182. name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
  183. if (type < sizeof (tnames) / sizeof (tnames[0]))
  184. (void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
  185. }
  186. static void
  187. dt_dis_xlate(const dtrace_difo_t *dp,
  188. const char *name, dif_instr_t in, FILE *fp)
  189. {
  190. uint_t xlr = DIF_INSTR_XLREF(in);
  191. (void) fprintf(fp, "%-4s DT_XLREF[%u], %%r%u",
  192. name, xlr, DIF_INSTR_RD(in));
  193. if (xlr < dp->dtdo_xlmlen) {
  194. (void) fprintf(fp, "\t\t! DT_XLREF[%u] = %u.%s", xlr,
  195. (uint_t)dp->dtdo_xlmtab[xlr]->dn_membexpr->dn_xlator->dx_id,
  196. dp->dtdo_xlmtab[xlr]->dn_membname);
  197. }
  198. }
  199. static char *
  200. dt_dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
  201. {
  202. char kind[16], ckind[16];
  203. switch (t->dtdt_kind) {
  204. case DIF_TYPE_CTF:
  205. (void) strcpy(kind, "D type");
  206. break;
  207. case DIF_TYPE_STRING:
  208. (void) strcpy(kind, "string");
  209. break;
  210. default:
  211. (void) snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
  212. }
  213. switch (t->dtdt_ckind) {
  214. case CTF_K_UNKNOWN:
  215. (void) strcpy(ckind, "unknown");
  216. break;
  217. case CTF_K_INTEGER:
  218. (void) strcpy(ckind, "integer");
  219. break;
  220. case CTF_K_FLOAT:
  221. (void) strcpy(ckind, "float");
  222. break;
  223. case CTF_K_POINTER:
  224. (void) strcpy(ckind, "pointer");
  225. break;
  226. case CTF_K_ARRAY:
  227. (void) strcpy(ckind, "array");
  228. break;
  229. case CTF_K_FUNCTION:
  230. (void) strcpy(ckind, "function");
  231. break;
  232. case CTF_K_STRUCT:
  233. (void) strcpy(ckind, "struct");
  234. break;
  235. case CTF_K_UNION:
  236. (void) strcpy(ckind, "union");
  237. break;
  238. case CTF_K_ENUM:
  239. (void) strcpy(ckind, "enum");
  240. break;
  241. case CTF_K_FORWARD:
  242. (void) strcpy(ckind, "forward");
  243. break;
  244. case CTF_K_TYPEDEF:
  245. (void) strcpy(ckind, "typedef");
  246. break;
  247. case CTF_K_VOLATILE:
  248. (void) strcpy(ckind, "volatile");
  249. break;
  250. case CTF_K_CONST:
  251. (void) strcpy(ckind, "const");
  252. break;
  253. case CTF_K_RESTRICT:
  254. (void) strcpy(ckind, "restrict");
  255. break;
  256. default:
  257. (void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
  258. }
  259. if (t->dtdt_flags & DIF_TF_BYREF) {
  260. (void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
  261. kind, ckind, (ulong_t)t->dtdt_size);
  262. } else {
  263. (void) snprintf(buf, len, "%s (%s) (size %lu)",
  264. kind, ckind, (ulong_t)t->dtdt_size);
  265. }
  266. return (buf);
  267. }
  268. static void
  269. dt_dis_rtab(const char *rtag, const dtrace_difo_t *dp, FILE *fp,
  270. const dof_relodesc_t *rp, uint32_t len)
  271. {
  272. (void) fprintf(fp, "\n%-4s %-8s %-8s %s\n",
  273. rtag, "OFFSET", "DATA", "NAME");
  274. for (; len != 0; len--, rp++) {
  275. (void) fprintf(fp, "%-4u %-8llu %-8llu %s\n",
  276. rp->dofr_type, (u_longlong_t)rp->dofr_offset,
  277. (u_longlong_t)rp->dofr_data,
  278. &dp->dtdo_strtab[rp->dofr_name]);
  279. }
  280. }
  281. void
  282. dt_dis(const dtrace_difo_t *dp, FILE *fp)
  283. {
  284. static const struct opent {
  285. const char *op_name;
  286. void (*op_func)(const dtrace_difo_t *, const char *,
  287. dif_instr_t, FILE *);
  288. } optab[] = {
  289. { "(illegal opcode)", dt_dis_str },
  290. { "or", dt_dis_log }, /* DIF_OP_OR */
  291. { "xor", dt_dis_log }, /* DIF_OP_XOR */
  292. { "and", dt_dis_log }, /* DIF_OP_AND */
  293. { "sll", dt_dis_log }, /* DIF_OP_SLL */
  294. { "srl", dt_dis_log }, /* DIF_OP_SRL */
  295. { "sub", dt_dis_log }, /* DIF_OP_SUB */
  296. { "add", dt_dis_log }, /* DIF_OP_ADD */
  297. { "mul", dt_dis_log }, /* DIF_OP_MUL */
  298. { "sdiv", dt_dis_log }, /* DIF_OP_SDIV */
  299. { "udiv", dt_dis_log }, /* DIF_OP_UDIV */
  300. { "srem", dt_dis_log }, /* DIF_OP_SREM */
  301. { "urem", dt_dis_log }, /* DIF_OP_UREM */
  302. { "not", dt_dis_r1rd }, /* DIF_OP_NOT */
  303. { "mov", dt_dis_r1rd }, /* DIF_OP_MOV */
  304. { "cmp", dt_dis_cmp }, /* DIF_OP_CMP */
  305. { "tst", dt_dis_tst }, /* DIF_OP_TST */
  306. { "ba", dt_dis_branch }, /* DIF_OP_BA */
  307. { "be", dt_dis_branch }, /* DIF_OP_BE */
  308. { "bne", dt_dis_branch }, /* DIF_OP_BNE */
  309. { "bg", dt_dis_branch }, /* DIF_OP_BG */
  310. { "bgu", dt_dis_branch }, /* DIF_OP_BGU */
  311. { "bge", dt_dis_branch }, /* DIF_OP_BGE */
  312. { "bgeu", dt_dis_branch }, /* DIF_OP_BGEU */
  313. { "bl", dt_dis_branch }, /* DIF_OP_BL */
  314. { "blu", dt_dis_branch }, /* DIF_OP_BLU */
  315. { "ble", dt_dis_branch }, /* DIF_OP_BLE */
  316. { "bleu", dt_dis_branch }, /* DIF_OP_BLEU */
  317. { "ldsb", dt_dis_load }, /* DIF_OP_LDSB */
  318. { "ldsh", dt_dis_load }, /* DIF_OP_LDSH */
  319. { "ldsw", dt_dis_load }, /* DIF_OP_LDSW */
  320. { "ldub", dt_dis_load }, /* DIF_OP_LDUB */
  321. { "lduh", dt_dis_load }, /* DIF_OP_LDUH */
  322. { "lduw", dt_dis_load }, /* DIF_OP_LDUW */
  323. { "ldx", dt_dis_load }, /* DIF_OP_LDX */
  324. { "ret", dt_dis_ret }, /* DIF_OP_RET */
  325. { "nop", dt_dis_str }, /* DIF_OP_NOP */
  326. { "setx", dt_dis_setx }, /* DIF_OP_SETX */
  327. { "sets", dt_dis_sets }, /* DIF_OP_SETS */
  328. { "scmp", dt_dis_cmp }, /* DIF_OP_SCMP */
  329. { "ldga", dt_dis_lda }, /* DIF_OP_LDGA */
  330. { "ldgs", dt_dis_ldv }, /* DIF_OP_LDGS */
  331. { "stgs", dt_dis_stv }, /* DIF_OP_STGS */
  332. { "ldta", dt_dis_lda }, /* DIF_OP_LDTA */
  333. { "ldts", dt_dis_ldv }, /* DIF_OP_LDTS */
  334. { "stts", dt_dis_stv }, /* DIF_OP_STTS */
  335. { "sra", dt_dis_log }, /* DIF_OP_SRA */
  336. { "call", dt_dis_call }, /* DIF_OP_CALL */
  337. { "pushtr", dt_dis_pushts }, /* DIF_OP_PUSHTR */
  338. { "pushtv", dt_dis_pushts }, /* DIF_OP_PUSHTV */
  339. { "popts", dt_dis_str }, /* DIF_OP_POPTS */
  340. { "flushts", dt_dis_str }, /* DIF_OP_FLUSHTS */
  341. { "ldgaa", dt_dis_ldv }, /* DIF_OP_LDGAA */
  342. { "ldtaa", dt_dis_ldv }, /* DIF_OP_LDTAA */
  343. { "stgaa", dt_dis_stv }, /* DIF_OP_STGAA */
  344. { "sttaa", dt_dis_stv }, /* DIF_OP_STTAA */
  345. { "ldls", dt_dis_ldv }, /* DIF_OP_LDLS */
  346. { "stls", dt_dis_stv }, /* DIF_OP_STLS */
  347. { "allocs", dt_dis_r1rd }, /* DIF_OP_ALLOCS */
  348. { "copys", dt_dis_log }, /* DIF_OP_COPYS */
  349. { "stb", dt_dis_store }, /* DIF_OP_STB */
  350. { "sth", dt_dis_store }, /* DIF_OP_STH */
  351. { "stw", dt_dis_store }, /* DIF_OP_STW */
  352. { "stx", dt_dis_store }, /* DIF_OP_STX */
  353. { "uldsb", dt_dis_load }, /* DIF_OP_ULDSB */
  354. { "uldsh", dt_dis_load }, /* DIF_OP_ULDSH */
  355. { "uldsw", dt_dis_load }, /* DIF_OP_ULDSW */
  356. { "uldub", dt_dis_load }, /* DIF_OP_ULDUB */
  357. { "ulduh", dt_dis_load }, /* DIF_OP_ULDUH */
  358. { "ulduw", dt_dis_load }, /* DIF_OP_ULDUW */
  359. { "uldx", dt_dis_load }, /* DIF_OP_ULDX */
  360. { "rldsb", dt_dis_load }, /* DIF_OP_RLDSB */
  361. { "rldsh", dt_dis_load }, /* DIF_OP_RLDSH */
  362. { "rldsw", dt_dis_load }, /* DIF_OP_RLDSW */
  363. { "rldub", dt_dis_load }, /* DIF_OP_RLDUB */
  364. { "rlduh", dt_dis_load }, /* DIF_OP_RLDUH */
  365. { "rlduw", dt_dis_load }, /* DIF_OP_RLDUW */
  366. { "rldx", dt_dis_load }, /* DIF_OP_RLDX */
  367. { "xlate", dt_dis_xlate }, /* DIF_OP_XLATE */
  368. { "xlarg", dt_dis_xlate }, /* DIF_OP_XLARG */
  369. };
  370. const struct opent *op;
  371. ulong_t i = 0;
  372. char type[DT_TYPE_NAMELEN];
  373. (void) fprintf(fp, "\nDIFO 0x%p returns %s\n", (void *)dp,
  374. dt_dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
  375. (void) fprintf(fp, "%-3s %-8s %s\n",
  376. "OFF", "OPCODE", "INSTRUCTION");
  377. for (i = 0; i < dp->dtdo_len; i++) {
  378. dif_instr_t instr = dp->dtdo_buf[i];
  379. dif_instr_t opcode = DIF_INSTR_OP(instr);
  380. if (opcode >= sizeof (optab) / sizeof (optab[0]))
  381. opcode = 0; /* force invalid opcode message */
  382. op = &optab[opcode];
  383. (void) fprintf(fp, "%02lu: %08x ", i, instr);
  384. op->op_func(dp, op->op_name, instr, fp);
  385. (void) fprintf(fp, "\n");
  386. }
  387. if (dp->dtdo_varlen != 0) {
  388. (void) fprintf(fp, "\n%-16s %-4s %-3s %-3s %-4s %s\n",
  389. "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
  390. }
  391. for (i = 0; i < dp->dtdo_varlen; i++) {
  392. dtrace_difv_t *v = &dp->dtdo_vartab[i];
  393. char kind[4], scope[4], flags[16] = { 0 };
  394. switch (v->dtdv_kind) {
  395. case DIFV_KIND_ARRAY:
  396. (void) strcpy(kind, "arr");
  397. break;
  398. case DIFV_KIND_SCALAR:
  399. (void) strcpy(kind, "scl");
  400. break;
  401. default:
  402. (void) snprintf(kind, sizeof (kind),
  403. "%u", v->dtdv_kind);
  404. }
  405. switch (v->dtdv_scope) {
  406. case DIFV_SCOPE_GLOBAL:
  407. (void) strcpy(scope, "glb");
  408. break;
  409. case DIFV_SCOPE_THREAD:
  410. (void) strcpy(scope, "tls");
  411. break;
  412. case DIFV_SCOPE_LOCAL:
  413. (void) strcpy(scope, "loc");
  414. break;
  415. default:
  416. (void) snprintf(scope, sizeof (scope),
  417. "%u", v->dtdv_scope);
  418. }
  419. if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
  420. (void) snprintf(flags, sizeof (flags), "/0x%x",
  421. v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
  422. }
  423. if (v->dtdv_flags & DIFV_F_REF)
  424. (void) strcat(flags, "/r");
  425. if (v->dtdv_flags & DIFV_F_MOD)
  426. (void) strcat(flags, "/w");
  427. (void) fprintf(fp, "%-16s %-4x %-3s %-3s %-4s %s\n",
  428. &dp->dtdo_strtab[v->dtdv_name],
  429. v->dtdv_id, kind, scope, flags + 1,
  430. dt_dis_typestr(&v->dtdv_type, type, sizeof (type)));
  431. }
  432. if (dp->dtdo_xlmlen != 0) {
  433. (void) fprintf(fp, "\n%-4s %-3s %-12s %s\n",
  434. "XLID", "ARG", "MEMBER", "TYPE");
  435. }
  436. for (i = 0; i < dp->dtdo_xlmlen; i++) {
  437. dt_node_t *dnp = dp->dtdo_xlmtab[i];
  438. dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
  439. (void) fprintf(fp, "%-4u %-3d %-12s %s\n",
  440. (uint_t)dxp->dx_id, dxp->dx_arg, dnp->dn_membname,
  441. dt_node_type_name(dnp, type, sizeof (type)));
  442. }
  443. if (dp->dtdo_krelen != 0)
  444. dt_dis_rtab("KREL", dp, fp, dp->dtdo_kreltab, dp->dtdo_krelen);
  445. if (dp->dtdo_urelen != 0)
  446. dt_dis_rtab("UREL", dp, fp, dp->dtdo_ureltab, dp->dtdo_urelen);
  447. }