Author: gnn
Date: Wed Feb 11 17:27:37 2015
New Revision: 278587
URL: https://svnweb.freebsd.org/changeset/base/278587

Log:
  Clean up machine dependent code for DTrace on ARM.
  
  Submitted by: markj

Modified:
  head/sys/cddl/dev/fbt/arm/fbt_isa.c

Modified: head/sys/cddl/dev/fbt/arm/fbt_isa.c
==============================================================================
--- head/sys/cddl/dev/fbt/arm/fbt_isa.c Wed Feb 11 17:25:23 2015        
(r278586)
+++ head/sys/cddl/dev/fbt/arm/fbt_isa.c Wed Feb 11 17:27:37 2015        
(r278587)
@@ -33,114 +33,21 @@
 
 #include <sys/cdefs.h>
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/cpuvar.h>
-#include <sys/fcntl.h>
-#include <sys/filio.h>
-#include <sys/kdb.h>
-#include <sys/kernel.h>
-#include <sys/kmem.h>
-#include <sys/kthread.h>
-#include <sys/limits.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/pcpu.h>
-#include <sys/poll.h>
-#include <sys/proc.h>
-#include <sys/selinfo.h>
-#include <sys/smp.h>
-#include <sys/syscall.h>
-#include <sys/sysent.h>
-#include <sys/sysproto.h>
-#include <sys/uio.h>
-#include <sys/unistd.h>
-#include <machine/frame.h>
-#include <machine/md_var.h>
-#include <machine/stdarg.h>
 
 #include <sys/dtrace.h>
-#include <sys/dtrace_bsd.h>
 
-static MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
+#include "fbt.h"
 
-#define FBT_PATCHVAL           0xe06a0cfe // illegal instruction
+#define        FBT_PATCHVAL            0xe06a0cfe /* illegal instruction */
 
-#define FBT_PUSHM              0xe92d0000
-#define FBT_POPM               0xe8bd0000
-#define FBT_JUMP               0xea000000
-
-static d_open_t        fbt_open;
-static int     fbt_unload(void);
-static void    fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
-static void    fbt_provide_module(void *, modctl_t *);
-static void    fbt_destroy(void *, dtrace_id_t, void *);
-static void    fbt_enable(void *, dtrace_id_t, void *);
-static void    fbt_disable(void *, dtrace_id_t, void *);
-static void    fbt_load(void *);
-static void    fbt_suspend(void *, dtrace_id_t, void *);
-static void    fbt_resume(void *, dtrace_id_t, void *);
+#define        FBT_PUSHM               0xe92d0000
+#define        FBT_POPM                0xe8bd0000
+#define        FBT_JUMP                0xea000000
 
 #define        FBT_ENTRY       "entry"
 #define        FBT_RETURN      "return"
-#define        FBT_ADDR2NDX(addr)      ((((uintptr_t)(addr)) >> 4) & 
fbt_probetab_mask)
-#define        FBT_PROBETAB_SIZE       0x8000          /* 32k entries -- 128K 
total */
 
-static struct cdevsw fbt_cdevsw = {
-       .d_version      = D_VERSION,
-       .d_open         = fbt_open,
-       .d_name         = "fbt",
-};
-
-static dtrace_pattr_t fbt_attr = {
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-};
-
-static dtrace_pops_t fbt_pops = {
-       NULL,
-       fbt_provide_module,
-       fbt_enable,
-       fbt_disable,
-       fbt_suspend,
-       fbt_resume,
-       fbt_getargdesc,
-       NULL,
-       NULL,
-       fbt_destroy
-};
-
-typedef struct fbt_probe {
-       struct fbt_probe *fbtp_hashnext;
-       uint32_t        *fbtp_patchpoint;
-       int8_t          fbtp_rval;
-       uint32_t        fbtp_patchval;
-       uint32_t        fbtp_savedval;
-       uintptr_t       fbtp_roffset;
-       dtrace_id_t     fbtp_id;
-       const char      *fbtp_name;
-       modctl_t        *fbtp_ctl;
-       int             fbtp_loadcnt;
-       int             fbtp_primary;
-       int             fbtp_invop_cnt;
-       int             fbtp_symindx;
-       struct fbt_probe *fbtp_next;
-} fbt_probe_t;
-
-static struct cdev             *fbt_cdev;
-static dtrace_provider_id_t    fbt_id;
-static fbt_probe_t             **fbt_probetab;
-static int                     fbt_probetab_size;
-static int                     fbt_probetab_mask;
-static int                     fbt_verbose = 0;
-
-static int
+int
 fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
 {
        struct trapframe *frame = (struct trapframe *)stack;
@@ -152,9 +59,10 @@ fbt_invop(uintptr_t addr, uintptr_t *sta
                        fbt->fbtp_invop_cnt++;
                        cpu->cpu_dtrace_caller = addr;
 
+                       /* TODO: Need 5th parameter from stack */
                        dtrace_probe(fbt->fbtp_id, frame->tf_r0,
                            frame->tf_r1, frame->tf_r2,
-                           frame->tf_r3, 0); // TODO: Need 5th parameter from 
stack
+                           frame->tf_r3, 0);
 
                        cpu->cpu_dtrace_caller = 0;
 
@@ -165,15 +73,23 @@ fbt_invop(uintptr_t addr, uintptr_t *sta
        return (0);
 }
 
-static int
+void
+fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
+{
+
+       *fbt->fbtp_patchpoint = val;
+       cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
+}
+
+int
 fbt_provide_module_function(linker_file_t lf, int symindx,
     linker_symval_t *symval, void *opaque)
 {
        char *modname = opaque;
        const char *name = symval->name;
        fbt_probe_t *fbt, *retfbt;
+       uint32_t *instr, *limit;
        int popm;
-       u_int32_t *instr, *limit;
 
        if (strncmp(name, "dtrace_", 7) == 0 &&
            strncmp(name, "dtrace_safe_", 12) != 0) {
@@ -189,11 +105,12 @@ fbt_provide_module_function(linker_file_
        if (name[0] == '_' && name[1] == '_')
                return (0);
 
-       instr = (u_int32_t *) symval->value;
-       limit = (u_int32_t *)(symval->value + symval->size);
+       instr = (uint32_t *)symval->value;
+       limit = (uint32_t *)(symval->value + symval->size);
 
        for (; instr < limit; instr++)
-               if ((*instr & 0xffff0000) == FBT_PUSHM && (*instr & 0x4000) != 
0)
+               if ((*instr & 0xffff0000) == FBT_PUSHM &&
+                   (*instr & 0x4000) != 0)
                        break;
 
        if (instr >= limit)
@@ -218,25 +135,23 @@ fbt_provide_module_function(linker_file_
 
        popm = FBT_POPM | ((*instr) & 0x3FFF) | 0x8000;
 
-
        retfbt = NULL;
-again: 
-       for(; instr < limit; instr++)
-       {
-               if  (*instr == popm)
+again:
+       for (; instr < limit; instr++) {
+               if (*instr == popm)
                        break;
-               else if ((*instr & 0xff000000) == FBT_JUMP)
-               {
+               else if ((*instr & 0xff000000) == FBT_JUMP) {
+                       uint32_t *target, *start;
                        int offset;
-                       u_int32_t *target, *start;
+
                        offset = (*instr & 0xffffff);
                        offset <<= 8;
                        offset /= 64;
                        target = instr + (2 + offset);
-                       start = (u_int32_t *) symval->value;
+                       start = (uint32_t *)symval->value;
                        if (target >= limit || target < start)
                                break;
-                       instr++; //skip delay slot
+                       instr++; /* skip delay slot */
                }
        }
 
@@ -263,7 +178,7 @@ again:      
        fbt->fbtp_symindx = symindx;
        if ((*instr & 0xff000000) == FBT_JUMP)
                fbt->fbtp_rval = DTRACE_INVOP_B;
-       else    
+       else
                fbt->fbtp_rval = DTRACE_INVOP_POPM;
        fbt->fbtp_savedval = *instr;
        fbt->fbtp_patchval = FBT_PATCHVAL;
@@ -275,1029 +190,3 @@ again:   
        instr++;
        goto again;
 }
-
-static void
-fbt_provide_module(void *arg, modctl_t *lf)
-{
-       char modname[MAXPATHLEN];
-       int i;
-       size_t len;
-
-       strlcpy(modname, lf->filename, sizeof(modname));
-       len = strlen(modname);
-       if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
-               modname[len - 3] = '\0';
-
-       /*
-        * Employees of dtrace and their families are ineligible.  Void
-        * where prohibited.
-        */
-       if (strcmp(modname, "dtrace") == 0)
-               return;
-
-       /*
-        * The cyclic timer subsystem can be built as a module and DTrace
-        * depends on that, so it is ineligible too.
-        */
-       if (strcmp(modname, "cyclic") == 0)
-               return;
-
-       /*
-        * To register with DTrace, a module must list 'dtrace' as a
-        * dependency in order for the kernel linker to resolve
-        * symbols like dtrace_register(). All modules with such a
-        * dependency are ineligible for FBT tracing.
-        */
-       for (i = 0; i < lf->ndeps; i++)
-               if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
-                       return;
-
-       if (lf->fbt_nentries) {
-               /*
-                * This module has some FBT entries allocated; we're afraid
-                * to screw with it.
-                */
-               return;
-       }
-
-       /*
-        * List the functions in the module and the symbol values.
-        */
-       (void) linker_file_function_listall(lf, fbt_provide_module_function, 
modname);
-}
-
-static void
-fbt_destroy(void *arg, dtrace_id_t id, void *parg)
-{
-       fbt_probe_t *fbt = parg, *next, *hash, *last;
-       modctl_t *ctl;
-       int ndx;
-
-       do {
-               ctl = fbt->fbtp_ctl;
-
-               ctl->fbt_nentries--;
-
-               /*
-                * Now we need to remove this probe from the fbt_probetab.
-                */
-               ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
-               last = NULL;
-               hash = fbt_probetab[ndx];
-
-               while (hash != fbt) {
-                       ASSERT(hash != NULL);
-                       last = hash;
-                       hash = hash->fbtp_hashnext;
-               }
-
-               if (last != NULL) {
-                       last->fbtp_hashnext = fbt->fbtp_hashnext;
-               } else {
-                       fbt_probetab[ndx] = fbt->fbtp_hashnext;
-               }
-
-               next = fbt->fbtp_next;
-               free(fbt, M_FBT);
-
-               fbt = next;
-       } while (fbt != NULL);
-}
-
-static void
-fbt_enable(void *arg, dtrace_id_t id, void *parg)
-{
-       fbt_probe_t *fbt = parg;
-       modctl_t *ctl = fbt->fbtp_ctl;
-
-       ctl->nenabled++;
-
-       /*
-        * Now check that our modctl has the expected load count.  If it
-        * doesn't, this module must have been unloaded and reloaded -- and
-        * we're not going to touch it.
-        */
-       if (ctl->loadcnt != fbt->fbtp_loadcnt) {
-               if (fbt_verbose) {
-                       printf("fbt is failing for probe %s "
-                           "(module %s reloaded)",
-                           fbt->fbtp_name, ctl->filename);
-               }
-
-               return;
-       }
-
-       for (; fbt != NULL; fbt = fbt->fbtp_next) {
-               *fbt->fbtp_patchpoint = fbt->fbtp_patchval;
-               cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
-       }
-}
-
-static void
-fbt_disable(void *arg, dtrace_id_t id, void *parg)
-{
-       fbt_probe_t *fbt = parg;
-       modctl_t *ctl = fbt->fbtp_ctl;
-
-       ASSERT(ctl->nenabled > 0);
-       ctl->nenabled--;
-
-       if ((ctl->loadcnt != fbt->fbtp_loadcnt))
-               return;
-
-       for (; fbt != NULL; fbt = fbt->fbtp_next) {
-               *fbt->fbtp_patchpoint = fbt->fbtp_savedval;
-               cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
-       }
-}
-
-static void
-fbt_suspend(void *arg, dtrace_id_t id, void *parg)
-{
-       fbt_probe_t *fbt = parg;
-       modctl_t *ctl = fbt->fbtp_ctl;
-
-       ASSERT(ctl->nenabled > 0);
-
-       if ((ctl->loadcnt != fbt->fbtp_loadcnt))
-               return;
-
-       for (; fbt != NULL; fbt = fbt->fbtp_next) {
-               *fbt->fbtp_patchpoint = fbt->fbtp_savedval;
-               cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
-       }
-}
-
-static void
-fbt_resume(void *arg, dtrace_id_t id, void *parg)
-{
-       fbt_probe_t *fbt = parg;
-       modctl_t *ctl = fbt->fbtp_ctl;
-
-       ASSERT(ctl->nenabled > 0);
-
-       if ((ctl->loadcnt != fbt->fbtp_loadcnt))
-               return;
-
-       for (; fbt != NULL; fbt = fbt->fbtp_next) {
-               *fbt->fbtp_patchpoint = fbt->fbtp_patchval;
-               cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
-       }
-}
-
-static int
-fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
-{
-       const Elf_Sym *symp = lc->symtab;;
-       const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
-       const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
-       int i;
-       uint32_t *ctfoff;
-       uint32_t objtoff = hp->cth_objtoff;
-       uint32_t funcoff = hp->cth_funcoff;
-       ushort_t info;
-       ushort_t vlen;
-
-       /* Sanity check. */
-       if (hp->cth_magic != CTF_MAGIC) {
-               printf("Bad magic value in CTF data of '%s'\n",lf->pathname);
-               return (EINVAL);
-       }
-
-       if (lc->symtab == NULL) {
-               printf("No symbol table in '%s'\n",lf->pathname);
-               return (EINVAL);
-       }
-
-       if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) 
== NULL)
-               return (ENOMEM);
-
-       *lc->ctfoffp = ctfoff;
-
-       for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
-               if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
-                       *ctfoff = 0xffffffff;
-                       continue;
-               }
-
-               switch (ELF_ST_TYPE(symp->st_info)) {
-               case STT_OBJECT:
-                       if (objtoff >= hp->cth_funcoff ||
-                           (symp->st_shndx == SHN_ABS && symp->st_value == 0)) 
{
-                               *ctfoff = 0xffffffff;
-                               break;
-                       }
-
-                       *ctfoff = objtoff;
-                       objtoff += sizeof (ushort_t);
-                       break;
-
-               case STT_FUNC:
-                       if (funcoff >= hp->cth_typeoff) {
-                               *ctfoff = 0xffffffff;
-                               break;
-                       }
-
-                       *ctfoff = funcoff;
-
-                       info = *((const ushort_t *)(ctfdata + funcoff));
-                       vlen = CTF_INFO_VLEN(info);
-
-                       /*
-                        * If we encounter a zero pad at the end, just skip it.
-                        * Otherwise skip over the function and its return type
-                        * (+2) and the argument list (vlen).
-                        */
-                       if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
-                               funcoff += sizeof (ushort_t); /* skip pad */
-                       else
-                               funcoff += sizeof (ushort_t) * (vlen + 2);
-                       break;
-
-               default:
-                       *ctfoff = 0xffffffff;
-                       break;
-               }
-       }
-
-       return (0);
-}
-
-static ssize_t
-fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
-    ssize_t *incrementp)
-{
-       ssize_t size, increment;
-
-       if (version > CTF_VERSION_1 &&
-           tp->ctt_size == CTF_LSIZE_SENT) {
-               size = CTF_TYPE_LSIZE(tp);
-               increment = sizeof (ctf_type_t);
-       } else {
-               size = tp->ctt_size;
-               increment = sizeof (ctf_stype_t);
-       }
-
-       if (sizep)
-               *sizep = size;
-       if (incrementp)
-               *incrementp = increment;
-
-       return (size);
-}
-
-static int
-fbt_typoff_init(linker_ctf_t *lc)
-{
-       const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
-       const ctf_type_t *tbuf;
-       const ctf_type_t *tend;
-       const ctf_type_t *tp;
-       const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
-       int ctf_typemax = 0;
-       uint32_t *xp;
-       ulong_t pop[CTF_K_MAX + 1] = { 0 };
-
-
-       /* Sanity check. */
-       if (hp->cth_magic != CTF_MAGIC)
-               return (EINVAL);
-
-       tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
-       tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
-
-       int child = hp->cth_parname != 0;
-
-       /*
-        * We make two passes through the entire type section.  In this first
-        * pass, we count the number of each type and the total number of types.
-        */
-       for (tp = tbuf; tp < tend; ctf_typemax++) {
-               ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
-               ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
-               ssize_t size, increment;
-
-               size_t vbytes;
-               uint_t n;
-
-               (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
-
-               switch (kind) {
-               case CTF_K_INTEGER:
-               case CTF_K_FLOAT:
-                       vbytes = sizeof (uint_t);
-                       break;
-               case CTF_K_ARRAY:
-                       vbytes = sizeof (ctf_array_t);
-                       break;
-               case CTF_K_FUNCTION:
-                       vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
-                       break;
-               case CTF_K_STRUCT:
-               case CTF_K_UNION:
-                       if (size < CTF_LSTRUCT_THRESH) {
-                               ctf_member_t *mp = (ctf_member_t *)
-                                   ((uintptr_t)tp + increment);
-
-                               vbytes = sizeof (ctf_member_t) * vlen;
-                               for (n = vlen; n != 0; n--, mp++)
-                                       child |= CTF_TYPE_ISCHILD(mp->ctm_type);
-                       } else {
-                               ctf_lmember_t *lmp = (ctf_lmember_t *)
-                                   ((uintptr_t)tp + increment);
-
-                               vbytes = sizeof (ctf_lmember_t) * vlen;
-                               for (n = vlen; n != 0; n--, lmp++)
-                                       child |=
-                                           CTF_TYPE_ISCHILD(lmp->ctlm_type);
-                       }
-                       break;
-               case CTF_K_ENUM:
-                       vbytes = sizeof (ctf_enum_t) * vlen;
-                       break;
-               case CTF_K_FORWARD:
-                       /*
-                        * For forward declarations, ctt_type is the CTF_K_*
-                        * kind for the tag, so bump that population count too.
-                        * If ctt_type is unknown, treat the tag as a struct.
-                        */
-                       if (tp->ctt_type == CTF_K_UNKNOWN ||
-                           tp->ctt_type >= CTF_K_MAX)
-                               pop[CTF_K_STRUCT]++;
-                       else
-                               pop[tp->ctt_type]++;
-                       /*FALLTHRU*/
-               case CTF_K_UNKNOWN:
-                       vbytes = 0;
-                       break;
-               case CTF_K_POINTER:
-               case CTF_K_TYPEDEF:
-               case CTF_K_VOLATILE:
-               case CTF_K_CONST:
-               case CTF_K_RESTRICT:
-                       child |= CTF_TYPE_ISCHILD(tp->ctt_type);
-                       vbytes = 0;
-                       break;
-               default:
-                       printf("%s(%d): detected invalid CTF kind -- %u\n", 
__func__, __LINE__, kind);
-                       return (EIO);
-               }
-               tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
-               pop[kind]++;
-       }
-
-       /* account for a sentinel value below */
-       ctf_typemax++;
-       *lc->typlenp = ctf_typemax;
-
-       if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_LINKER, M_ZERO | 
M_WAITOK)) == NULL)
-               return (ENOMEM);
-
-       *lc->typoffp = xp;
-
-       /* type id 0 is used as a sentinel value */
-       *xp++ = 0;
-
-       /*
-        * In the second pass, fill in the type offset.
-        */
-       for (tp = tbuf; tp < tend; xp++) {
-               ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
-               ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
-               ssize_t size, increment;
-
-               size_t vbytes;
-               uint_t n;
-
-               (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
-
-               switch (kind) {
-               case CTF_K_INTEGER:
-               case CTF_K_FLOAT:
-                       vbytes = sizeof (uint_t);
-                       break;
-               case CTF_K_ARRAY:
-                       vbytes = sizeof (ctf_array_t);
-                       break;
-               case CTF_K_FUNCTION:
-                       vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
-                       break;
-               case CTF_K_STRUCT:
-               case CTF_K_UNION:
-                       if (size < CTF_LSTRUCT_THRESH) {
-                               ctf_member_t *mp = (ctf_member_t *)
-                                   ((uintptr_t)tp + increment);
-
-                               vbytes = sizeof (ctf_member_t) * vlen;
-                               for (n = vlen; n != 0; n--, mp++)
-                                       child |= CTF_TYPE_ISCHILD(mp->ctm_type);
-                       } else {
-                               ctf_lmember_t *lmp = (ctf_lmember_t *)
-                                   ((uintptr_t)tp + increment);
-
-                               vbytes = sizeof (ctf_lmember_t) * vlen;
-                               for (n = vlen; n != 0; n--, lmp++)
-                                       child |=
-                                           CTF_TYPE_ISCHILD(lmp->ctlm_type);
-                       }
-                       break;
-               case CTF_K_ENUM:
-                       vbytes = sizeof (ctf_enum_t) * vlen;
-                       break;
-               case CTF_K_FORWARD:
-               case CTF_K_UNKNOWN:
-                       vbytes = 0;
-                       break;
-               case CTF_K_POINTER:
-               case CTF_K_TYPEDEF:
-               case CTF_K_VOLATILE:
-               case CTF_K_CONST:
-               case CTF_K_RESTRICT:
-                       vbytes = 0;
-                       break;
-               default:
-                       printf("%s(%d): detected invalid CTF kind -- %u\n", 
__func__, __LINE__, kind);
-                       return (EIO);
-               }
-               *xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
-               tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
-       }
-
-       return (0);
-}
-
-/*
- * CTF Declaration Stack
- *
- * In order to implement ctf_type_name(), we must convert a type graph back
- * into a C type declaration.  Unfortunately, a type graph represents a storage
- * class ordering of the type whereas a type declaration must obey the C rules
- * for operator precedence, and the two orderings are frequently in conflict.
- * For example, consider these CTF type graphs and their C declarations:
- *
- * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
- * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
- *
- * In each case, parentheses are used to raise operator * to higher lexical
- * precedence, so the string form of the C declaration cannot be constructed by
- * walking the type graph links and forming the string from left to right.
- *
- * The functions in this file build a set of stacks from the type graph nodes
- * corresponding to the C operator precedence levels in the appropriate order.
- * The code in ctf_type_name() can then iterate over the levels and nodes in
- * lexical precedence order and construct the final C declaration string.
- */
-typedef struct ctf_list {
-       struct ctf_list *l_prev; /* previous pointer or tail pointer */
-       struct ctf_list *l_next; /* next pointer or head pointer */
-} ctf_list_t;
-
-#define        ctf_list_prev(elem)     ((void *)(((ctf_list_t 
*)(elem))->l_prev))
-#define        ctf_list_next(elem)     ((void *)(((ctf_list_t 
*)(elem))->l_next))
-
-typedef enum {
-       CTF_PREC_BASE,
-       CTF_PREC_POINTER,
-       CTF_PREC_ARRAY,
-       CTF_PREC_FUNCTION,
-       CTF_PREC_MAX
-} ctf_decl_prec_t;
-
-typedef struct ctf_decl_node {
-       ctf_list_t cd_list;                     /* linked list pointers */
-       ctf_id_t cd_type;                       /* type identifier */
-       uint_t cd_kind;                         /* type kind */
-       uint_t cd_n;                            /* type dimension if array */
-} ctf_decl_node_t;
-
-typedef struct ctf_decl {
-       ctf_list_t cd_nodes[CTF_PREC_MAX];      /* declaration node stacks */
-       int cd_order[CTF_PREC_MAX];             /* storage order of decls */
-       ctf_decl_prec_t cd_qualp;               /* qualifier precision */
-       ctf_decl_prec_t cd_ordp;                /* ordered precision */
-       char *cd_buf;                           /* buffer for output */
-       char *cd_ptr;                           /* buffer location */
-       char *cd_end;                           /* buffer limit */
-       size_t cd_len;                          /* buffer space required */
-       int cd_err;                             /* saved error value */
-} ctf_decl_t;
-
-/*
- * Simple doubly-linked list append routine.  This implementation assumes that
- * each list element contains an embedded ctf_list_t as the first member.
- * An additional ctf_list_t is used to store the head (l_next) and tail
- * (l_prev) pointers.  The current head and tail list elements have their
- * previous and next pointers set to NULL, respectively.
- */
-static void
-ctf_list_append(ctf_list_t *lp, void *new)
-{
-       ctf_list_t *p = lp->l_prev;     /* p = tail list element */
-       ctf_list_t *q = new;            /* q = new list element */
-
-       lp->l_prev = q;
-       q->l_prev = p;
-       q->l_next = NULL;
-
-       if (p != NULL)
-               p->l_next = q;
-       else
-               lp->l_next = q;
-}
-
-/*
- * Prepend the specified existing element to the given ctf_list_t.  The
- * existing pointer should be pointing at a struct with embedded ctf_list_t.
- */
-static void
-ctf_list_prepend(ctf_list_t *lp, void *new)
-{
-       ctf_list_t *p = new;            /* p = new list element */
-       ctf_list_t *q = lp->l_next;     /* q = head list element */
-
-       lp->l_next = p;
-       p->l_prev = NULL;
-       p->l_next = q;
-
-       if (q != NULL)
-               q->l_prev = p;
-       else
-               lp->l_prev = p;
-}
-
-static void
-ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
-{
-       int i;
-
-       bzero(cd, sizeof (ctf_decl_t));
-
-       for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
-               cd->cd_order[i] = CTF_PREC_BASE - 1;
-
-       cd->cd_qualp = CTF_PREC_BASE;
-       cd->cd_ordp = CTF_PREC_BASE;
-
-       cd->cd_buf = buf;
-       cd->cd_ptr = buf;
-       cd->cd_end = buf + len;
-}
-
-static void
-ctf_decl_fini(ctf_decl_t *cd)
-{
-       ctf_decl_node_t *cdp, *ndp;
-       int i;
-
-       for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
-               for (cdp = ctf_list_next(&cd->cd_nodes[i]);
-                   cdp != NULL; cdp = ndp) {
-                       ndp = ctf_list_next(cdp);
-                       free(cdp, M_FBT);
-               }
-       }
-}
-
-static const ctf_type_t *
-ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
-{
-       const ctf_type_t *tp;
-       uint32_t offset;
-       uint32_t *typoff = *lc->typoffp;
-
-       if (type >= *lc->typlenp) {
-               printf("%s(%d): type %d exceeds max 
%ld\n",__func__,__LINE__,(int) type,*lc->typlenp);
-               return(NULL);
-       }
-
-       /* Check if the type isn't cross-referenced. */
-       if ((offset = typoff[type]) == 0) {
-               printf("%s(%d): type %d isn't cross 
referenced\n",__func__,__LINE__, (int) type);
-               return(NULL);
-       }
-
-       tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t));
-
-       return (tp);
-}
-
-static void
-fbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp)
-{
-       const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
-       const ctf_type_t *tp;
-       const ctf_array_t *ap;
-       ssize_t increment;
-
-       bzero(arp, sizeof(*arp));
-
-       if ((tp = ctf_lookup_by_id(lc, type)) == NULL)
-               return;
-
-       if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
-               return;
-
-       (void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
-
-       ap = (const ctf_array_t *)((uintptr_t)tp + increment);
-       arp->ctr_contents = ap->cta_contents;
-       arp->ctr_index = ap->cta_index;
-       arp->ctr_nelems = ap->cta_nelems;
-}
-
-static const char *
-ctf_strptr(linker_ctf_t *lc, int name)
-{
-       const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;;
-       const char *strp = "";
-
-       if (name < 0 || name >= hp->cth_strlen)
-               return (strp);
-
-       strp = (const char *)(lc->ctftab + hp->cth_stroff + name + 
sizeof(ctf_header_t));
-
-       return (strp);
-}
-
-static void
-ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
-{
-       ctf_decl_node_t *cdp;
-       ctf_decl_prec_t prec;
-       uint_t kind, n = 1;
-       int is_qual = 0;
-
-       const ctf_type_t *tp;
-       ctf_arinfo_t ar;
-
-       if ((tp = ctf_lookup_by_id(lc, type)) == NULL) {
-               cd->cd_err = ENOENT;
-               return;
-       }
-
-       switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
-       case CTF_K_ARRAY:
-               fbt_array_info(lc, type, &ar);
-               ctf_decl_push(cd, lc, ar.ctr_contents);
-               n = ar.ctr_nelems;
-               prec = CTF_PREC_ARRAY;
-               break;
-
-       case CTF_K_TYPEDEF:
-               if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') {
-                       ctf_decl_push(cd, lc, tp->ctt_type);
-                       return;
-               }
-               prec = CTF_PREC_BASE;
-               break;
-
-       case CTF_K_FUNCTION:
-               ctf_decl_push(cd, lc, tp->ctt_type);
-               prec = CTF_PREC_FUNCTION;
-               break;
-
-       case CTF_K_POINTER:
-               ctf_decl_push(cd, lc, tp->ctt_type);
-               prec = CTF_PREC_POINTER;
-               break;
-
-       case CTF_K_VOLATILE:
-       case CTF_K_CONST:
-       case CTF_K_RESTRICT:
-               ctf_decl_push(cd, lc, tp->ctt_type);
-               prec = cd->cd_qualp;
-               is_qual++;
-               break;
-
-       default:
-               prec = CTF_PREC_BASE;
-       }
-
-       if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
-               cd->cd_err = EAGAIN;
-               return;
-       }
-
-       cdp->cd_type = type;
-       cdp->cd_kind = kind;
-       cdp->cd_n = n;
-
-       if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
-               cd->cd_order[prec] = cd->cd_ordp++;
-
-       /*
-        * Reset cd_qualp to the highest precedence level that we've seen so
-        * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
-        */
-       if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
-               cd->cd_qualp = prec;
-
-       /*
-        * C array declarators are ordered inside out so prepend them.  Also by
-        * convention qualifiers of base types precede the type specifier (e.g.
-        * const int vs. int const) even though the two forms are equivalent.
-        */
-       if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
-               ctf_list_prepend(&cd->cd_nodes[prec], cdp);
-       else
-               ctf_list_append(&cd->cd_nodes[prec], cdp);
-}
-
-static void
-ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
-{
-       size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
-       va_list ap;
-       size_t n;
-
-       va_start(ap, format);
-       n = vsnprintf(cd->cd_ptr, len, format, ap);
-       va_end(ap);
-
-       cd->cd_ptr += MIN(n, len);
-       cd->cd_len += n;
-}
-
-static ssize_t
-fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
-{
-       ctf_decl_t cd;
-       ctf_decl_node_t *cdp;
-       ctf_decl_prec_t prec, lp, rp;
-       int ptr, arr;
-       uint_t k;
-
-       if (lc == NULL && type == CTF_ERR)
-               return (-1); /* simplify caller code by permitting CTF_ERR */
-
-       ctf_decl_init(&cd, buf, len);
-       ctf_decl_push(&cd, lc, type);
-
-       if (cd.cd_err != 0) {
-               ctf_decl_fini(&cd);
-               return (-1);
-       }
-
-       /*
-        * If the type graph's order conflicts with lexical precedence order
-        * for pointers or arrays, then we need to surround the declarations at
-        * the corresponding lexical precedence with parentheses.  This can
-        * result in either a parenthesized pointer (*) as in int (*)() or
-        * int (*)[], or in a parenthesized pointer and array as in int (*[])().
-        */
-       ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
-       arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
-
-       rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
-       lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
-

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to