17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 26*a386cc11SRobert Mustacchi /* 27*a386cc11SRobert Mustacchi * Copyright (c) 2013 by Delphix. All rights reserved. 28*a386cc11SRobert Mustacchi * Copyright (c) 2013 Joyent, Inc. All rights reserved. 29*a386cc11SRobert Mustacchi */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <strings.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <assert.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <dt_impl.h> 377c478bd9Sstevel@tonic-gate #include <dt_parser.h> 387c478bd9Sstevel@tonic-gate #include <dt_as.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate void 417c478bd9Sstevel@tonic-gate dt_irlist_create(dt_irlist_t *dlp) 427c478bd9Sstevel@tonic-gate { 437c478bd9Sstevel@tonic-gate bzero(dlp, sizeof (dt_irlist_t)); 447c478bd9Sstevel@tonic-gate dlp->dl_label = 1; 457c478bd9Sstevel@tonic-gate } 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate void 487c478bd9Sstevel@tonic-gate dt_irlist_destroy(dt_irlist_t *dlp) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate dt_irnode_t *dip, *nip; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate for (dip = dlp->dl_list; dip != NULL; dip = nip) { 537c478bd9Sstevel@tonic-gate nip = dip->di_next; 547c478bd9Sstevel@tonic-gate free(dip); 557c478bd9Sstevel@tonic-gate } 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate void 597c478bd9Sstevel@tonic-gate dt_irlist_append(dt_irlist_t *dlp, dt_irnode_t *dip) 607c478bd9Sstevel@tonic-gate { 617c478bd9Sstevel@tonic-gate if (dlp->dl_last != NULL) 627c478bd9Sstevel@tonic-gate dlp->dl_last->di_next = dip; 637c478bd9Sstevel@tonic-gate else 647c478bd9Sstevel@tonic-gate dlp->dl_list = dip; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate dlp->dl_last = dip; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate if (dip->di_label == DT_LBL_NONE || dip->di_instr != DIF_INSTR_NOP) 697c478bd9Sstevel@tonic-gate dlp->dl_len++; /* don't count forward refs in instr count */ 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate uint_t 737c478bd9Sstevel@tonic-gate dt_irlist_label(dt_irlist_t *dlp) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate return (dlp->dl_label++); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 797c478bd9Sstevel@tonic-gate static int 807c478bd9Sstevel@tonic-gate dt_countvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate size_t *np = data; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if (idp->di_flags & (DT_IDFLG_DIFR | DT_IDFLG_DIFW)) 857c478bd9Sstevel@tonic-gate (*np)++; /* include variable in vartab */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate return (0); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 917c478bd9Sstevel@tonic-gate static int 927c478bd9Sstevel@tonic-gate dt_copyvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate dt_pcb_t *pcb = data; 957c478bd9Sstevel@tonic-gate dtrace_difv_t *dvp; 967c478bd9Sstevel@tonic-gate ssize_t stroff; 977c478bd9Sstevel@tonic-gate dt_node_t dn; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if (!(idp->di_flags & (DT_IDFLG_DIFR | DT_IDFLG_DIFW))) 1007c478bd9Sstevel@tonic-gate return (0); /* omit variable from vartab */ 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate dvp = &pcb->pcb_difo->dtdo_vartab[pcb->pcb_asvidx++]; 1037c478bd9Sstevel@tonic-gate stroff = dt_strtab_insert(pcb->pcb_strtab, idp->di_name); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (stroff == -1L) 1067c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 1077c478bd9Sstevel@tonic-gate if (stroff > DIF_STROFF_MAX) 1087c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_STR2BIG); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate dvp->dtdv_name = (uint_t)stroff; 1117c478bd9Sstevel@tonic-gate dvp->dtdv_id = idp->di_id; 1127c478bd9Sstevel@tonic-gate dvp->dtdv_flags = 0; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate dvp->dtdv_kind = (idp->di_kind == DT_IDENT_ARRAY) ? 1157c478bd9Sstevel@tonic-gate DIFV_KIND_ARRAY : DIFV_KIND_SCALAR; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_LOCAL) 1187c478bd9Sstevel@tonic-gate dvp->dtdv_scope = DIFV_SCOPE_LOCAL; 1197c478bd9Sstevel@tonic-gate else if (idp->di_flags & DT_IDFLG_TLS) 1207c478bd9Sstevel@tonic-gate dvp->dtdv_scope = DIFV_SCOPE_THREAD; 1217c478bd9Sstevel@tonic-gate else 1227c478bd9Sstevel@tonic-gate dvp->dtdv_scope = DIFV_SCOPE_GLOBAL; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_DIFR) 1257c478bd9Sstevel@tonic-gate dvp->dtdv_flags |= DIFV_F_REF; 1267c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_DIFW) 1277c478bd9Sstevel@tonic-gate dvp->dtdv_flags |= DIFV_F_MOD; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate bzero(&dn, sizeof (dn)); 130*a386cc11SRobert Mustacchi dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE); 1311a7c1b72Smws dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW); 1347c478bd9Sstevel@tonic-gate return (0); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate static ssize_t 1387c478bd9Sstevel@tonic-gate dt_copystr(const char *s, size_t n, size_t off, dt_pcb_t *pcb) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate bcopy(s, pcb->pcb_difo->dtdo_strtab + off, n); 1417c478bd9Sstevel@tonic-gate return (n); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1441a7c1b72Smws /* 1451a7c1b72Smws * Rewrite the xlate/xlarg instruction at dtdo_buf[i] so that the instruction's 1461a7c1b72Smws * xltab index reflects the offset 'xi' of the assigned dtdo_xlmtab[] location. 1471a7c1b72Smws * We track the cumulative references to translators and members in the pcb's 1481a7c1b72Smws * pcb_asxrefs[] array, a two-dimensional array of bitmaps indexed by the 1491a7c1b72Smws * global translator id and then by the corresponding translator member id. 1501a7c1b72Smws */ 1511a7c1b72Smws static void 1521a7c1b72Smws dt_as_xlate(dt_pcb_t *pcb, dtrace_difo_t *dp, 1531a7c1b72Smws uint_t i, uint_t xi, dt_node_t *dnp) 1541a7c1b72Smws { 1551a7c1b72Smws dtrace_hdl_t *dtp = pcb->pcb_hdl; 1561a7c1b72Smws dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator; 1571a7c1b72Smws 1581a7c1b72Smws assert(i < dp->dtdo_len); 1591a7c1b72Smws assert(xi < dp->dtdo_xlmlen); 1601a7c1b72Smws 1611a7c1b72Smws assert(dnp->dn_kind == DT_NODE_MEMBER); 1621a7c1b72Smws assert(dnp->dn_membexpr->dn_kind == DT_NODE_XLATOR); 1631a7c1b72Smws 1641a7c1b72Smws assert(dxp->dx_id < dtp->dt_xlatorid); 1651a7c1b72Smws assert(dnp->dn_membid < dxp->dx_nmembers); 1661a7c1b72Smws 1671a7c1b72Smws if (pcb->pcb_asxrefs == NULL) { 1681a7c1b72Smws pcb->pcb_asxreflen = dtp->dt_xlatorid; 1691a7c1b72Smws pcb->pcb_asxrefs = 1701a7c1b72Smws dt_zalloc(dtp, sizeof (ulong_t *) * pcb->pcb_asxreflen); 1711a7c1b72Smws if (pcb->pcb_asxrefs == NULL) 1721a7c1b72Smws longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 1731a7c1b72Smws } 1741a7c1b72Smws 1751a7c1b72Smws if (pcb->pcb_asxrefs[dxp->dx_id] == NULL) { 1761a7c1b72Smws pcb->pcb_asxrefs[dxp->dx_id] = 1771a7c1b72Smws dt_zalloc(dtp, BT_SIZEOFMAP(dxp->dx_nmembers)); 1781a7c1b72Smws if (pcb->pcb_asxrefs[dxp->dx_id] == NULL) 1791a7c1b72Smws longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 1801a7c1b72Smws } 1811a7c1b72Smws 1821a7c1b72Smws dp->dtdo_buf[i] = DIF_INSTR_XLATE( 1831a7c1b72Smws DIF_INSTR_OP(dp->dtdo_buf[i]), xi, DIF_INSTR_RD(dp->dtdo_buf[i])); 1841a7c1b72Smws 1851a7c1b72Smws BT_SET(pcb->pcb_asxrefs[dxp->dx_id], dnp->dn_membid); 1861a7c1b72Smws dp->dtdo_xlmtab[xi] = dnp; 1871a7c1b72Smws } 1881a7c1b72Smws 1897c478bd9Sstevel@tonic-gate static void 1907c478bd9Sstevel@tonic-gate dt_as_undef(const dt_ident_t *idp, uint_t offset) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate const char *kind, *mark = (idp->di_flags & DT_IDFLG_USER) ? "``" : "`"; 1937c478bd9Sstevel@tonic-gate const dtrace_syminfo_t *dts = idp->di_data; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_USER) 1967c478bd9Sstevel@tonic-gate kind = "user"; 1977c478bd9Sstevel@tonic-gate else if (idp->di_flags & DT_IDFLG_PRIM) 1987c478bd9Sstevel@tonic-gate kind = "primary kernel"; 1997c478bd9Sstevel@tonic-gate else 2007c478bd9Sstevel@tonic-gate kind = "loadable kernel"; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate yylineno = idp->di_lineno; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate xyerror(D_ASRELO, "relocation remains against %s symbol %s%s%s (offset " 2057c478bd9Sstevel@tonic-gate "0x%x)\n", kind, dts->dts_object, mark, dts->dts_name, offset); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate dtrace_difo_t * 2097c478bd9Sstevel@tonic-gate dt_as(dt_pcb_t *pcb) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = pcb->pcb_hdl; 2127c478bd9Sstevel@tonic-gate dt_irlist_t *dlp = &pcb->pcb_ir; 2137c478bd9Sstevel@tonic-gate uint_t *labels = NULL; 2147c478bd9Sstevel@tonic-gate dt_irnode_t *dip; 2157c478bd9Sstevel@tonic-gate dtrace_difo_t *dp; 2167c478bd9Sstevel@tonic-gate dt_ident_t *idp; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate size_t n = 0; 2197c478bd9Sstevel@tonic-gate uint_t i; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate uint_t kmask, kbits, umask, ubits; 2221a7c1b72Smws uint_t krel = 0, urel = 0, xlrefs = 0; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Select bitmasks based upon the desired symbol linking policy. We 2261a7c1b72Smws * test (di_extern->di_flags & xmask) == xbits to determine if the 2277c478bd9Sstevel@tonic-gate * symbol should have a relocation entry generated in the loop below. 2287c478bd9Sstevel@tonic-gate * 2297c478bd9Sstevel@tonic-gate * DT_LINK_KERNEL = kernel symbols static, user symbols dynamic 2307c478bd9Sstevel@tonic-gate * DT_LINK_PRIMARY = primary kernel symbols static, others dynamic 2317c478bd9Sstevel@tonic-gate * DT_LINK_DYNAMIC = all symbols dynamic 2327c478bd9Sstevel@tonic-gate * DT_LINK_STATIC = all symbols static 2337c478bd9Sstevel@tonic-gate * 2347c478bd9Sstevel@tonic-gate * By 'static' we mean that we use the symbol's value at compile-time 2357c478bd9Sstevel@tonic-gate * in the final DIF. By 'dynamic' we mean that we create a relocation 2367c478bd9Sstevel@tonic-gate * table entry for the symbol's value so it can be relocated later. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate switch (dtp->dt_linkmode) { 2397c478bd9Sstevel@tonic-gate case DT_LINK_KERNEL: 2407c478bd9Sstevel@tonic-gate kmask = 0; 2417c478bd9Sstevel@tonic-gate kbits = -1u; 2427c478bd9Sstevel@tonic-gate umask = DT_IDFLG_USER; 2437c478bd9Sstevel@tonic-gate ubits = DT_IDFLG_USER; 2447c478bd9Sstevel@tonic-gate break; 2457c478bd9Sstevel@tonic-gate case DT_LINK_PRIMARY: 2467c478bd9Sstevel@tonic-gate kmask = DT_IDFLG_USER | DT_IDFLG_PRIM; 2477c478bd9Sstevel@tonic-gate kbits = 0; 2487c478bd9Sstevel@tonic-gate umask = DT_IDFLG_USER; 2497c478bd9Sstevel@tonic-gate ubits = DT_IDFLG_USER; 2507c478bd9Sstevel@tonic-gate break; 2517c478bd9Sstevel@tonic-gate case DT_LINK_DYNAMIC: 2527c478bd9Sstevel@tonic-gate kmask = DT_IDFLG_USER; 2537c478bd9Sstevel@tonic-gate kbits = 0; 2547c478bd9Sstevel@tonic-gate umask = DT_IDFLG_USER; 2557c478bd9Sstevel@tonic-gate ubits = DT_IDFLG_USER; 2567c478bd9Sstevel@tonic-gate break; 2577c478bd9Sstevel@tonic-gate case DT_LINK_STATIC: 2587c478bd9Sstevel@tonic-gate kmask = umask = 0; 2597c478bd9Sstevel@tonic-gate kbits = ubits = -1u; 2607c478bd9Sstevel@tonic-gate break; 2617c478bd9Sstevel@tonic-gate default: 2627c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "internal error -- invalid link mode %u\n", 2637c478bd9Sstevel@tonic-gate dtp->dt_linkmode); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2661a7c1b72Smws assert(pcb->pcb_difo == NULL); 2671a7c1b72Smws pcb->pcb_difo = dt_zalloc(dtp, sizeof (dtrace_difo_t)); 2681a7c1b72Smws 2691a7c1b72Smws if ((dp = pcb->pcb_difo) == NULL) 2707c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 2717c478bd9Sstevel@tonic-gate 2721a7c1b72Smws dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * dlp->dl_len); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate if (dp->dtdo_buf == NULL) 2757c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 2767c478bd9Sstevel@tonic-gate 2771a7c1b72Smws if ((labels = dt_alloc(dtp, sizeof (uint_t) * dlp->dl_label)) == NULL) 2787c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Make an initial pass through the instruction list, filling in the 2827c478bd9Sstevel@tonic-gate * instruction buffer with valid instructions and skipping labeled nops. 2837c478bd9Sstevel@tonic-gate * While doing this, we also fill in our labels[] translation table 2847c478bd9Sstevel@tonic-gate * and we count up the number of relocation table entries we will need. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate for (i = 0, dip = dlp->dl_list; dip != NULL; dip = dip->di_next) { 2877c478bd9Sstevel@tonic-gate if (dip->di_label != DT_LBL_NONE) 2887c478bd9Sstevel@tonic-gate labels[dip->di_label] = i; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (dip->di_label == DT_LBL_NONE || 2917c478bd9Sstevel@tonic-gate dip->di_instr != DIF_INSTR_NOP) 2927c478bd9Sstevel@tonic-gate dp->dtdo_buf[i++] = dip->di_instr; 2937c478bd9Sstevel@tonic-gate 2941a7c1b72Smws if (dip->di_extern == NULL) 2951a7c1b72Smws continue; /* no external references needed */ 2967c478bd9Sstevel@tonic-gate 2971a7c1b72Smws switch (DIF_INSTR_OP(dip->di_instr)) { 2981a7c1b72Smws case DIF_OP_SETX: 2991a7c1b72Smws idp = dip->di_extern; 3007c478bd9Sstevel@tonic-gate if ((idp->di_flags & kmask) == kbits) 3017c478bd9Sstevel@tonic-gate krel++; 3027c478bd9Sstevel@tonic-gate else if ((idp->di_flags & umask) == ubits) 3037c478bd9Sstevel@tonic-gate urel++; 3041a7c1b72Smws break; 3051a7c1b72Smws case DIF_OP_XLATE: 3061a7c1b72Smws case DIF_OP_XLARG: 3071a7c1b72Smws xlrefs++; 3081a7c1b72Smws break; 3091a7c1b72Smws default: 3101a7c1b72Smws xyerror(D_UNKNOWN, "unexpected assembler relocation " 3111a7c1b72Smws "for opcode 0x%x\n", DIF_INSTR_OP(dip->di_instr)); 3121a7c1b72Smws } 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate assert(i == dlp->dl_len); 3167c478bd9Sstevel@tonic-gate dp->dtdo_len = dlp->dl_len; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * Make a second pass through the instructions, relocating each branch 3207c478bd9Sstevel@tonic-gate * label to the index of the final instruction in the buffer and noting 3217c478bd9Sstevel@tonic-gate * any other instruction-specific DIFO flags such as dtdo_destructive. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate for (i = 0; i < dp->dtdo_len; i++) { 3247c478bd9Sstevel@tonic-gate dif_instr_t instr = dp->dtdo_buf[i]; 3257c478bd9Sstevel@tonic-gate uint_t op = DIF_INSTR_OP(instr); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate if (op == DIF_OP_CALL) { 3287c478bd9Sstevel@tonic-gate if (DIF_INSTR_SUBR(instr) == DIF_SUBR_COPYOUT || 3297c478bd9Sstevel@tonic-gate DIF_INSTR_SUBR(instr) == DIF_SUBR_COPYOUTSTR) 3307c478bd9Sstevel@tonic-gate dp->dtdo_destructive = 1; 3317c478bd9Sstevel@tonic-gate continue; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (op >= DIF_OP_BA && op <= DIF_OP_BLEU) { 3357c478bd9Sstevel@tonic-gate assert(DIF_INSTR_LABEL(instr) < dlp->dl_label); 3367c478bd9Sstevel@tonic-gate dp->dtdo_buf[i] = DIF_INSTR_BRANCH(op, 3377c478bd9Sstevel@tonic-gate labels[DIF_INSTR_LABEL(instr)]); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3411a7c1b72Smws dt_free(dtp, labels); 3421a7c1b72Smws pcb->pcb_asvidx = 0; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * Allocate memory for the appropriate number of variable records and 3467c478bd9Sstevel@tonic-gate * then fill in each variable record. As we populate the variable 3477c478bd9Sstevel@tonic-gate * table we insert the corresponding variable names into the strtab. 3487c478bd9Sstevel@tonic-gate */ 3497c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_tls, dt_countvar, &n); 3507c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_globals, dt_countvar, &n); 3517c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(pcb->pcb_locals, dt_countvar, &n); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (n != 0) { 3541a7c1b72Smws dp->dtdo_vartab = dt_alloc(dtp, n * sizeof (dtrace_difv_t)); 3557c478bd9Sstevel@tonic-gate dp->dtdo_varlen = (uint32_t)n; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (dp->dtdo_vartab == NULL) 3587c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_tls, dt_copyvar, pcb); 3617c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_globals, dt_copyvar, pcb); 3627c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(pcb->pcb_locals, dt_copyvar, pcb); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Allocate memory for the appropriate number of relocation table 3677c478bd9Sstevel@tonic-gate * entries based upon our kernel and user counts from the first pass. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate if (krel != 0) { 3701a7c1b72Smws dp->dtdo_kreltab = dt_alloc(dtp, 3711a7c1b72Smws krel * sizeof (dof_relodesc_t)); 3727c478bd9Sstevel@tonic-gate dp->dtdo_krelen = krel; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate if (dp->dtdo_kreltab == NULL) 3757c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (urel != 0) { 3791a7c1b72Smws dp->dtdo_ureltab = dt_alloc(dtp, 3801a7c1b72Smws urel * sizeof (dof_relodesc_t)); 3817c478bd9Sstevel@tonic-gate dp->dtdo_urelen = urel; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate if (dp->dtdo_ureltab == NULL) 3847c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3871a7c1b72Smws if (xlrefs != 0) { 3881a7c1b72Smws dp->dtdo_xlmtab = dt_zalloc(dtp, sizeof (dt_node_t *) * xlrefs); 3891a7c1b72Smws dp->dtdo_xlmlen = xlrefs; 3901a7c1b72Smws 3911a7c1b72Smws if (dp->dtdo_xlmtab == NULL) 3921a7c1b72Smws longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 3931a7c1b72Smws } 3941a7c1b72Smws 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * If any relocations are needed, make another pass through the 3977c478bd9Sstevel@tonic-gate * instruction list and fill in the relocation table entries. 3987c478bd9Sstevel@tonic-gate */ 3991a7c1b72Smws if (krel + urel + xlrefs != 0) { 4007c478bd9Sstevel@tonic-gate uint_t knodef = pcb->pcb_cflags & DTRACE_C_KNODEF; 4017c478bd9Sstevel@tonic-gate uint_t unodef = pcb->pcb_cflags & DTRACE_C_UNODEF; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate dof_relodesc_t *krp = dp->dtdo_kreltab; 4047c478bd9Sstevel@tonic-gate dof_relodesc_t *urp = dp->dtdo_ureltab; 4051a7c1b72Smws dt_node_t **xlp = dp->dtdo_xlmtab; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate i = 0; /* dtdo_buf[] index */ 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate for (dip = dlp->dl_list; dip != NULL; dip = dip->di_next) { 4107c478bd9Sstevel@tonic-gate dof_relodesc_t *rp; 4117c478bd9Sstevel@tonic-gate ssize_t soff; 4127c478bd9Sstevel@tonic-gate uint_t nodef; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate if (dip->di_label != DT_LBL_NONE && 4157c478bd9Sstevel@tonic-gate dip->di_instr == DIF_INSTR_NOP) 4167c478bd9Sstevel@tonic-gate continue; /* skip label declarations */ 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate i++; /* advance dtdo_buf[] index */ 4197c478bd9Sstevel@tonic-gate 4201a7c1b72Smws if (DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLATE || 4211a7c1b72Smws DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLARG) { 4221a7c1b72Smws assert(dp->dtdo_buf[i - 1] == dip->di_instr); 4231a7c1b72Smws dt_as_xlate(pcb, dp, i - 1, (uint_t) 4241a7c1b72Smws (xlp++ - dp->dtdo_xlmtab), dip->di_extern); 4251a7c1b72Smws continue; 4261a7c1b72Smws } 4271a7c1b72Smws 4281a7c1b72Smws if ((idp = dip->di_extern) == NULL) 4297c478bd9Sstevel@tonic-gate continue; /* no relocation entry needed */ 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if ((idp->di_flags & kmask) == kbits) { 4327c478bd9Sstevel@tonic-gate nodef = knodef; 4337c478bd9Sstevel@tonic-gate rp = krp++; 4347c478bd9Sstevel@tonic-gate } else if ((idp->di_flags & umask) == ubits) { 4357c478bd9Sstevel@tonic-gate nodef = unodef; 4367c478bd9Sstevel@tonic-gate rp = urp++; 4377c478bd9Sstevel@tonic-gate } else 4387c478bd9Sstevel@tonic-gate continue; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate if (!nodef) 4417c478bd9Sstevel@tonic-gate dt_as_undef(idp, i); 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate assert(DIF_INSTR_OP(dip->di_instr) == DIF_OP_SETX); 4447c478bd9Sstevel@tonic-gate soff = dt_strtab_insert(pcb->pcb_strtab, idp->di_name); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate if (soff == -1L) 4477c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 4487c478bd9Sstevel@tonic-gate if (soff > DIF_STROFF_MAX) 4497c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_STR2BIG); 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate rp->dofr_name = (dof_stridx_t)soff; 4527c478bd9Sstevel@tonic-gate rp->dofr_type = DOF_RELO_SETX; 4537c478bd9Sstevel@tonic-gate rp->dofr_offset = DIF_INSTR_INTEGER(dip->di_instr) * 4547c478bd9Sstevel@tonic-gate sizeof (uint64_t); 4557c478bd9Sstevel@tonic-gate rp->dofr_data = 0; 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate assert(krp == dp->dtdo_kreltab + dp->dtdo_krelen); 4597c478bd9Sstevel@tonic-gate assert(urp == dp->dtdo_ureltab + dp->dtdo_urelen); 4601a7c1b72Smws assert(xlp == dp->dtdo_xlmtab + dp->dtdo_xlmlen); 4617c478bd9Sstevel@tonic-gate assert(i == dp->dtdo_len); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Allocate memory for the compiled string table and then copy the 4667c478bd9Sstevel@tonic-gate * chunks from the string table into the final string buffer. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate if ((n = dt_strtab_size(pcb->pcb_strtab)) != 0) { 4691a7c1b72Smws if ((dp->dtdo_strtab = dt_alloc(dtp, n)) == NULL) 4707c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate (void) dt_strtab_write(pcb->pcb_strtab, 4737c478bd9Sstevel@tonic-gate (dt_strtab_write_f *)dt_copystr, pcb); 4747c478bd9Sstevel@tonic-gate dp->dtdo_strlen = (uint32_t)n; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Allocate memory for the compiled integer table and then copy the 4797c478bd9Sstevel@tonic-gate * integer constants from the table into the final integer buffer. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate if ((n = dt_inttab_size(pcb->pcb_inttab)) != 0) { 4821a7c1b72Smws if ((dp->dtdo_inttab = dt_alloc(dtp, 4831a7c1b72Smws n * sizeof (uint64_t))) == NULL) 4847c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate dt_inttab_write(pcb->pcb_inttab, dp->dtdo_inttab); 4877c478bd9Sstevel@tonic-gate dp->dtdo_intlen = (uint32_t)n; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * Fill in the DIFO return type from the type associated with the 4927c478bd9Sstevel@tonic-gate * node saved in pcb_dret, and then clear pcb_difo and pcb_dret 4937c478bd9Sstevel@tonic-gate * now that the assembler has completed successfully. 4947c478bd9Sstevel@tonic-gate */ 4951a7c1b72Smws dt_node_diftype(dtp, pcb->pcb_dret, &dp->dtdo_rtype); 4967c478bd9Sstevel@tonic-gate pcb->pcb_difo = NULL; 4977c478bd9Sstevel@tonic-gate pcb->pcb_dret = NULL; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if (pcb->pcb_cflags & DTRACE_C_DIFV) 5001a7c1b72Smws dt_dis(dp, stderr); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate return (dp); 5037c478bd9Sstevel@tonic-gate } 504