diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-06-30 11:44:13 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-06-30 11:44:13 +0000 |
commit | 4e1f938f9e4d41dcfe106b432ae2b08d3d5ab7c5 (patch) | |
tree | 2c61f53413cda0b76794d52f5b730115bf50b659 | |
parent | cb3493721e0f08d42f41165a7c089d9c11dcecab (diff) | |
parent | 1326c48877254e828afea8c9f7529f6faf1a1fde (diff) | |
download | illumos-joyent-release-20200702.tar.gz |
[illumos-gate merge]release-20200702
commit 1326c48877254e828afea8c9f7529f6faf1a1fde
12790 locale data install should not attempt to copy missing files
commit 5f9772673df89384a3fa8f1cbfcccd8d331f83ff
10854 empty struct array confuses CTF
commit 3f764e121447070c490c9637dd5791f8c8823ee4
12604 w needs to use line name instead of pid
commit 35060ceaa548c2d6fa63812e06a1a0f8dc4a06b0
12459 iwn: possible unaligned pointer issue
-rw-r--r-- | usr/src/cmd/w/w.c | 400 | ||||
-rw-r--r-- | usr/src/data/locale/Makefile | 6 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/ctf_dwarf.c | 117 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-array.c | 10 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/test-array.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/io/iwn/if_iwn.c | 31 |
6 files changed, 259 insertions, 309 deletions
diff --git a/usr/src/cmd/w/w.c b/usr/src/cmd/w/w.c index 85b5726631..65dda98621 100644 --- a/usr/src/cmd/w/w.c +++ b/usr/src/cmd/w/w.c @@ -53,26 +53,28 @@ * fixing bugs here, then you should probably fix 'em there too. */ -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> -#include <ctype.h> -#include <fcntl.h> -#include <time.h> -#include <err.h> -#include <errno.h> #include <sys/types.h> -#include <utmpx.h> +#include <sys/loadavg.h> +#include <sys/queue.h> #include <sys/stat.h> +#include <sys/sysmacros.h> + +#include <ctype.h> #include <dirent.h> -#include <procfs.h> /* /proc header file */ -#include <locale.h> -#include <unistd.h> -#include <sys/loadavg.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> #include <limits.h> +#include <locale.h> #include <priv_utils.h> -#include <sys/sysmacros.h> +#include <procfs.h> /* /proc header file */ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <utmpx.h> /* * Use the full lengths from utmpx for user and line. @@ -87,50 +89,25 @@ static struct utmpx dummy; #define DIV60(t) ((t+30)/60) /* x/60 rounded */ -#ifdef ERR -#undef ERR -#endif -#define ERR (-1) - -#define HSIZE 256 /* size of process hash table */ #define PROCDIR "/proc" -#define INITPROCESS (pid_t)1 /* init process pid */ -#define NONE 'n' /* no state */ -#define RUNNING 'r' /* runnable process */ -#define ZOMBIE 'z' /* zombie process */ -#define VISITED 'v' /* marked node as visited */ #define PRINTF(a) if (printf a < 0) { \ perror((gettext("%s: printf failed"), prog)); \ exit(1); } struct uproc { pid_t p_upid; /* process id */ - char p_state; /* numeric value of process state */ dev_t p_ttyd; /* controlling tty of process */ time_t p_time; /* seconds of user & system time */ time_t p_ctime; /* seconds of child user & sys time */ int p_igintr; /* 1 = ignores SIGQUIT and SIGINT */ char p_comm[PRARGSZ+1]; /* command */ char p_args[PRARGSZ+1]; /* command line arguments */ - struct uproc *p_child, /* first child pointer */ - *p_sibling, /* sibling pointer */ - *p_pgrpl, /* pgrp link */ - *p_link; /* hash table chain pointer */ + STAILQ_ENTRY(uproc) uprocs; }; +STAILQ_HEAD(uprochead, uproc) uphead; -/* - * define hash table for struct uproc - * Hash function uses process id - * and the size of the hash table(HSIZE) - * to determine process index into the table. - */ -static struct uproc pr_htbl[HSIZE]; - -static struct uproc *findhash(pid_t); static time_t findidle(char *); static void clnarglist(char *); -static void showtotals(struct uproc *); -static void calctotals(struct uproc *); static void prttime(time_t, int); static void prtat(time_t *time); @@ -147,12 +124,6 @@ static int login; /* true if invoked as login shell */ static time_t now; /* current time of day */ static time_t uptime; /* time of last reboot & elapsed time since */ static int nusers; /* number of users logged in now */ -static time_t idle; /* number of minutes user is idle */ -static time_t jobtime; /* total cpu time visible */ -static char doing[520]; /* process attached to terminal */ -static time_t proctime; /* cpu time of process in doing */ -static pid_t curpid, empty; -static int add_times; /* boolean: add the cpu times or not */ /* * Basic privs we never need and can drop. This is likely not exhaustive, @@ -179,13 +150,13 @@ main(int argc, char *argv[]) struct utmpx *utmpbegin; struct utmpx *utmpend; struct utmpx *utp; - struct uproc *up, *parent, *pgrp; + struct uproc *up; struct psinfo info; struct sigaction actinfo[ACTSIZE]; struct pstatus statinfo; struct stat sbuf; DIR *dirp; - struct dirent *dp; + struct dirent *dp; char pname[PATH_MAX]; int procfd; int dirfd; @@ -375,13 +346,11 @@ main(int argc, char *argv[]) } } - /* - * loop through /proc, reading info about each process - * and build the parent/child tree - */ + /* Loop through /proc, reading info about each process */ if ((dirp = opendir(PROCDIR)) == NULL) err(EXIT_FAILURE, gettext("could not open %s"), PROCDIR); + STAILQ_INIT(&uphead); while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; @@ -391,7 +360,6 @@ main(int argc, char *argv[]) continue; dirfd = priv_proc_open(pname, O_RDONLY | O_DIRECTORY); - if (dirfd < 0) continue; @@ -400,106 +368,73 @@ main(int argc, char *argv[]) (void) close(dirfd); continue; } - if (!do_proc_read(procfd, &info, sizeof (info))) { - warn(gettext("read() failed on %s"), pname); + warn(gettext("failed to read %s"), pname); (void) close(dirfd); continue; } (void) close(procfd); - up = findhash(info.pr_pid); - up->p_ttyd = info.pr_ttydev; - up->p_state = (info.pr_nlwp == 0 ? ZOMBIE : RUNNING); - up->p_time = 0; - up->p_ctime = 0; - up->p_igintr = 0; - (void) strlcpy(up->p_comm, info.pr_fname, - sizeof (up->p_comm)); - up->p_args[0] = 0; - - if (up->p_state != NONE && up->p_state != ZOMBIE) { - procfd = priv_proc_openat(dirfd, "status", O_RDONLY); - if (procfd < 0) { - (void) close(dirfd); - continue; - } - - if (!do_proc_read(procfd, &statinfo, - sizeof (statinfo))) { - warn(gettext("read() failed on %s/status"), - pname); - - (void) close(procfd); - (void) close(dirfd); - continue; - } - (void) close(procfd); - - up->p_time = statinfo.pr_utime.tv_sec + - statinfo.pr_stime.tv_sec; /* seconds */ - up->p_ctime = statinfo.pr_cutime.tv_sec + - statinfo.pr_cstime.tv_sec; - - procfd = priv_proc_openat(dirfd, "sigact", O_RDONLY); - if (procfd < 0) { - (void) close(dirfd); - continue; - } - - if (!do_proc_read(procfd, actinfo, sizeof (actinfo))) { - warn(gettext("read() failed on %s/sigact"), - pname); + /* Not interested in zombies */ + if (info.pr_nlwp == 0) + continue; + /* Not interested in processes without a terminal */ + if (info.pr_ttydev == NODEV) + continue; - (void) close(procfd); - (void) close(dirfd); - continue; - } + procfd = priv_proc_openat(dirfd, "status", O_RDONLY); + if (procfd < 0) { + (void) close(dirfd); + continue; + } + if (!do_proc_read(procfd, &statinfo, sizeof (statinfo))) { + warn(gettext("failed to read %s/status"), pname); (void) close(procfd); (void) close(dirfd); - up->p_igintr = - actinfo[SIGINT-1].sa_handler == SIG_IGN && - actinfo[SIGQUIT-1].sa_handler == SIG_IGN; - - /* - * Process args. - */ - up->p_args[0] = '\0'; - clnarglist(info.pr_psargs); - (void) strlcpy(up->p_args, info.pr_psargs, - sizeof (up->p_args)); - if (up->p_args[0] == 0 || - up->p_args[0] == '-' && up->p_args[1] <= ' ' || - up->p_args[0] == '?') { - (void) strlcat(up->p_args, " (", - sizeof (up->p_args)); - (void) strlcat(up->p_args, up->p_comm, - sizeof (up->p_args)); - (void) strlcat(up->p_args, ")", - sizeof (up->p_args)); - } + continue; } + (void) close(procfd); - /* - * link pgrp together in case parents go away - * Pgrp chain is a single linked list originating - * from the pgrp leader to its group member. - */ - if (info.pr_pgid != info.pr_pid) { /* not pgrp leader */ - pgrp = findhash(info.pr_pgid); - up->p_pgrpl = pgrp->p_pgrpl; - pgrp->p_pgrpl = up; + procfd = priv_proc_openat(dirfd, "sigact", O_RDONLY); + if (procfd < 0) { + (void) close(dirfd); + continue; + } + if (!do_proc_read(procfd, actinfo, sizeof (actinfo))) { + warn(gettext("failed to read %s/sigact"), pname); + (void) close(procfd); + (void) close(dirfd); + continue; } - parent = findhash(info.pr_ppid); + (void) close(procfd); + (void) close(dirfd); - /* if this is the new member, link it in */ - if (parent->p_upid != INITPROCESS) { - if (parent->p_child) { - up->p_sibling = parent->p_child; - up->p_child = 0; - } - parent->p_child = up; + up = calloc(1, sizeof (*up)); + if (up == NULL) + err(EXIT_FAILURE, "calloc"); + up->p_upid = info.pr_pid; + up->p_ttyd = info.pr_ttydev; + up->p_time = + statinfo.pr_utime.tv_sec + + statinfo.pr_stime.tv_sec; + up->p_ctime = + statinfo.pr_cutime.tv_sec + + statinfo.pr_cstime.tv_sec; + up->p_igintr = + actinfo[SIGINT-1].sa_handler == SIG_IGN && + actinfo[SIGQUIT-1].sa_handler == SIG_IGN; + (void) strlcpy(up->p_comm, info.pr_fname, sizeof (up->p_comm)); + /* Process args */ + clnarglist(info.pr_psargs); + (void) strlcpy(up->p_args, info.pr_psargs, sizeof (up->p_args)); + if (up->p_args[0] == 0 || up->p_args[0] == '?' || + (up->p_args[0] == '-' && up->p_args[1] <= ' ')) { + (void) strlcat(up->p_args, " (", sizeof (up->p_args)); + (void) strlcat(up->p_args, up->p_comm, + sizeof (up->p_args)); + (void) strlcat(up->p_args, ")", sizeof (up->p_args)); } + STAILQ_INSERT_TAIL(&uphead, up, uprocs); } /* revert to non-privileged user after opening */ @@ -540,10 +475,17 @@ main(int argc, char *argv[]) * about each logged in user */ for (ut = utmpbegin; ut < utmpend; ut++) { + struct uproc *upt; + char linedev[PATH_MAX]; + char what[1024]; + time_t idle, jobtime, proctime; + pid_t curpid; + if (ut->ut_type != USER_PROCESS) continue; - if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0) - continue; /* we're looking for somebody else */ + if (sel_user != NULL && + strncmp(ut->ut_name, sel_user, NMAX) != 0) + continue; /* print login name of the user */ PRINTF(("%-*.*s ", LOGIN_WIDTH, NMAX, ut->ut_name)); @@ -552,8 +494,7 @@ main(int argc, char *argv[]) if (lflag) { PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, ut->ut_line)); } else { - if (ut->ut_line[0] == 'p' && ut->ut_line[1] == 't' && - ut->ut_line[2] == 's' && ut->ut_line[3] == '/') { + if (strncmp(ut->ut_line, "pts/", strlen("pts/")) == 0) { PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, &ut->ut_line[4])); } else { @@ -571,133 +512,62 @@ main(int argc, char *argv[]) /* print idle time */ idle = findidle(ut->ut_line); prttime(idle, 8); - showtotals(findhash(ut->ut_pid)); - } - if (fclose(stdout) == EOF) - err(EXIT_FAILURE, gettext("fclose failed")); - - return (0); -} - -/* - * Prints the CPU time for all processes & children, - * and the cpu time for interesting process, - * and what the user is doing. - */ -static void -showtotals(struct uproc *up) -{ - jobtime = 0; - proctime = 0; - empty = 1; - curpid = -1; - add_times = 1; - - calctotals(up); - - if (lflag) { - /* print CPU time for all processes & children */ - /* and need to convert clock ticks to seconds first */ - prttime((time_t)jobtime, 8); - - /* print cpu time for interesting process */ - /* and need to convert clock ticks to seconds first */ - prttime((time_t)proctime, 8); - } - /* what user is doing, current process */ - PRINTF(("%-.32s\n", doing)); -} -/* - * This recursive routine descends the process - * tree starting from the given process pointer(up). - * It used depth-first search strategy and also marked - * each node as visited as it traversed down the tree. - * It calculates the process time for all processes & - * children. It also finds the interesting process - * and determines its cpu time and command. - */ -static void -calctotals(struct uproc *up) -{ - struct uproc *zp; - - /* - * Once a node has been visited, stop adding cpu times - * for its children so they don't get totalled twice. - * Still look for the interesting job for this utmp - * entry, however. - */ - if (up->p_state == VISITED) - add_times = 0; - up->p_state = VISITED; - if (up->p_state == NONE || up->p_state == ZOMBIE) - return; - - if (empty && !up->p_igintr) { - empty = 0; + /* + * Go through the list of processes for this terminal, + * calculating job/process times, and look for the + * "most interesting" process. + */ + jobtime = 0; + proctime = 0; curpid = -1; - } + (void) strlcpy(what, "-", sizeof (what)); - if (up->p_upid > curpid && (!up->p_igintr || empty)) { - curpid = up->p_upid; - if (lflag) - (void) strlcpy(doing, up->p_args, sizeof (doing)); - else - (void) strlcpy(doing, up->p_comm, sizeof (doing)); - } + (void) snprintf(linedev, sizeof (linedev), "/dev/%s", + ut->ut_line); + if (stat(linedev, &sbuf) == -1 || + (sbuf.st_mode & S_IFMT) != S_IFCHR || + sbuf.st_rdev == NODEV) + goto skip; - if (add_times == 1) { - jobtime += up->p_time + up->p_ctime; - proctime += up->p_time; - } + STAILQ_FOREACH_SAFE(up, &uphead, uprocs, upt) { + if (up->p_ttyd != sbuf.st_rdev) + continue; + jobtime += up->p_time + up->p_ctime; + proctime += up->p_time; + /* + * Check for "most interesting" process, currently + * the one having the highest PID. + */ + if (up->p_upid > curpid && !up->p_igintr) { + curpid = up->p_upid; + if (lflag) { + (void) strlcpy(what, up->p_args, + sizeof (what)); + } else { + (void) strlcpy(what, up->p_comm, + sizeof (what)); + } + } + STAILQ_REMOVE(&uphead, up, uproc, uprocs); + free(up); + } - /* descend for its children */ - if (up->p_child) { - calctotals(up->p_child); - for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling) - calctotals(zp); +skip: + if (lflag) { + /* Print CPU time for all processes & children */ + prttime(jobtime, 8); + /* Print cpu time for interesting process */ + prttime(proctime, 8); + } + /* "Most interesting" process */ + PRINTF(("%-.32s\n", what)); } -} -/* - * Findhash finds the appropriate entry in the process - * hash table (pr_htbl) for the given pid in case that - * pid exists on the hash chain. It returns back a pointer - * to that uproc structure. If this is a new pid, it allocates - * a new node, initializes it, links it into the chain (after - * head) and returns a structure pointer. - */ -static struct uproc * -findhash(pid_t pid) -{ - struct uproc *up, *tp; - - tp = up = &pr_htbl[pid % HSIZE]; - if (up->p_upid == 0) { /* empty slot */ - up->p_upid = pid; - up->p_state = NONE; - up->p_child = up->p_sibling = up->p_pgrpl = up->p_link = 0; - return (up); - } - if (up->p_upid == pid) { /* found in hash table */ - return (up); - } - for (tp = up->p_link; tp; tp = tp->p_link) { /* follow chain */ - if (tp->p_upid == pid) - return (tp); - } - tp = malloc(sizeof (*tp)); /* add new node */ - if (tp == NULL) - err(EXIT_FAILURE, gettext("out of memory!")); - - (void) memset(tp, 0, sizeof (*tp)); - tp->p_upid = pid; - tp->p_state = NONE; - tp->p_child = tp->p_sibling = tp->p_pgrpl = 0; - tp->p_link = up->p_link; /* insert after head */ - up->p_link = tp; - return (tp); + if (fclose(stdout) == EOF) + err(EXIT_FAILURE, gettext("fclose failed")); + + return (0); } #define HR (60 * 60) diff --git a/usr/src/data/locale/Makefile b/usr/src/data/locale/Makefile index 99ee6a60ef..284f5b0cfa 100644 --- a/usr/src/data/locale/Makefile +++ b/usr/src/data/locale/Makefile @@ -146,8 +146,10 @@ locale/%/$(DTIME): locale/%/stamp $(ROOTDATA): $(ROOTLOCDIRS) $(ROOTCATDIRS) $(DATA) $(RM) $@ - -$(CP) $(@:$(ROOTLIB)/%=%) $@ - $(CHMOD) -f 0444 $@ + if [[ -f $(@:$(ROOTLIB)/%=%) ]]; then \ + $(CP) $(@:$(ROOTLIB)/%=%) $@; \ + $(CHMOD) -f 0444 $@ ; \ + fi %.mo: %.po $(MSGFMT) -o $@ $< diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c index 2f501a2334..3079831715 100644 --- a/usr/src/lib/libctf/common/ctf_dwarf.c +++ b/usr/src/lib/libctf/common/ctf_dwarf.c @@ -1456,13 +1456,102 @@ ctf_dwarf_create_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, } static int +ctf_dwarf_array_upper_bound(ctf_cu_t *cup, Dwarf_Die range, ctf_arinfo_t *ar) +{ + Dwarf_Attribute attr; + Dwarf_Unsigned uval; + Dwarf_Signed sval; + Dwarf_Half form; + Dwarf_Error derr; + const char *formstr = NULL; + int ret = 0; + + ctf_dprintf("setting array upper bound\n"); + + ar->ctr_nelems = 0; + + ret = ctf_dwarf_attribute(cup, range, DW_AT_upper_bound, &attr); + /* + * Treat the lack of an upper bound attribute as a zero element array + * and return success, otherwise return the error. + */ + if (ret != 0) { + if (ret == ENOENT) + return (0); + return (ret); + } + + if (dwarf_whatform(attr, &form, &derr) != DW_DLV_OK) { + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get DW_AT_upper_bound attribute form: %s\n", + dwarf_errmsg(derr)); + ret = ECTF_CONVBKERR; + goto done; + } + + /* + * Compilers can indicate array bounds using signed or unsigned values. + * Additionally, some compilers may also store the array bounds + * using as DW_FORM_data{1,2,4,8} (which DWARF treats as raw data and + * expects the caller to understand how to interpret the value). + * + * GCC 4.4.4 appears to always use unsigned values to encode the + * array size (using '(unsigned)-1' to represent a zero-length or + * unknown length array). Later versions of GCC use a signed value of + * -1 for zero/unknown length arrays, and unsigned values to encode + * known array sizes. + * + * Both dwarf_formsdata() and dwarf_formudata() will retrieve values + * as their respective signed/unsigned forms, but both will also + * retreive DW_FORM_data{1,2,4,8} values and treat them as signed or + * unsigned integers (i.e. dwarf_formsdata() treats DW_FORM_dataXX + * as signed integers and dwarf_formudata() treats DW_FORM_dataXX as + * unsigned integers). Both will return an error if the form is not + * their respective signed/unsigned form, or DW_FORM_dataXX. + * + * To obtain the upper bound, we use the appropriate + * dwarf_form[su]data() function based on the form of DW_AT_upper_bound. + * Additionally, we let dwarf_formudata() handle the DW_FORM_dataXX + * forms (via the default option in the switch). If the value is in an + * unexpected form (i.e. not DW_FORM_udata or DW_FORM_dataXX), + * dwarf_formudata() will return failure (i.e. not DW_DLV_OK) and set + * derr with the specific error value. + */ + switch (form) { + case DW_FORM_sdata: + if (dwarf_formsdata(attr, &sval, &derr) == DW_DLV_OK) { + ar->ctr_nelems = sval + 1; + goto done; + } + break; + case DW_FORM_udata: + default: + if (dwarf_formudata(attr, &uval, &derr) == DW_DLV_OK) { + ar->ctr_nelems = uval + 1; + goto done; + } + break; + } + + if (dwarf_get_FORM_name(form, &formstr) != DW_DLV_OK) + formstr = "unknown DWARF form"; + + (void) snprintf(cup->cu_errbuf, cup->cu_errlen, + "failed to get %s (%hu) value for DW_AT_upper_bound: %s\n", + formstr, form, dwarf_errmsg(derr)); + ret = ECTF_CONVBKERR; + +done: + dwarf_dealloc(cup->cu_dwarf, attr, DW_DLA_ATTR); + return (ret); +} + +static int ctf_dwarf_create_array_range(ctf_cu_t *cup, Dwarf_Die range, ctf_id_t *idp, ctf_id_t base, int isroot) { int ret; Dwarf_Die sib; - Dwarf_Unsigned val; - Dwarf_Signed sval; ctf_arinfo_t ar; ctf_dprintf("creating array range\n"); @@ -1482,30 +1571,8 @@ ctf_dwarf_create_array_range(ctf_cu_t *cup, Dwarf_Die range, ctf_id_t *idp, if ((ar.ctr_index = ctf_dwarf_long(cup)) == CTF_ERR) return (ctf_errno(cup->cu_ctfp)); - /* - * Array bounds can be signed or unsigned, but there are several kinds - * of signless forms (data1, data2, etc) that take their sign from the - * routine that is trying to interpret them. That is, data1 can be - * either signed or unsigned, depending on whether you use the signed or - * unsigned accessor function. GCC will use the signless forms to store - * unsigned values which have their high bit set, so we need to try to - * read them first as unsigned to get positive values. We could also - * try signed first, falling back to unsigned if we got a negative - * value. - */ - if ((ret = ctf_dwarf_unsigned(cup, range, DW_AT_upper_bound, - &val)) == 0) { - ar.ctr_nelems = val + 1; - } else if (ret != ENOENT) { - return (ret); - } else if ((ret = ctf_dwarf_signed(cup, range, DW_AT_upper_bound, - &sval)) == 0) { - ar.ctr_nelems = sval + 1; - } else if (ret != ENOENT) { + if ((ret = ctf_dwarf_array_upper_bound(cup, range, &ar)) != 0) return (ret); - } else { - ar.ctr_nelems = 0; - } if ((*idp = ctf_add_array(cup->cu_ctfp, isroot, &ar)) == CTF_ERR) return (ctf_errno(cup->cu_ctfp)); diff --git a/usr/src/test/util-tests/tests/ctf/check-array.c b/usr/src/test/util-tests/tests/ctf/check-array.c index be7a192480..46be6332cb 100644 --- a/usr/src/test/util-tests/tests/ctf/check-array.c +++ b/usr/src/test/util-tests/tests/ctf/check-array.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -36,6 +36,7 @@ static check_symbol_t check_syms[] = { { "g", "int [4][5][6][7][8]" }, { "h", "int [4][5][6][7][8][9]" }, { "i", "int [4][5][6][7][8][9][10]" }, + { "empty", "int [0]" }, { NULL } }; @@ -72,11 +73,18 @@ static check_descent_t check_array_i[] = { { NULL }, }; +static check_descent_t check_array_empty[] = { + { "int [0]", CTF_K_ARRAY, "int", 0 }, + { "int", CTF_K_INTEGER }, + { NULL } +}; + static check_descent_test_t descents[] = { { "a", check_array_a }, { "b", check_array_b }, { "c", check_array_c }, { "i", check_array_i }, + { "empty", check_array_empty }, { NULL } }; diff --git a/usr/src/test/util-tests/tests/ctf/test-array.c b/usr/src/test/util-tests/tests/ctf/test-array.c index 9c15771caf..14fc21d5dd 100644 --- a/usr/src/test/util-tests/tests/ctf/test-array.c +++ b/usr/src/test/util-tests/tests/ctf/test-array.c @@ -10,7 +10,7 @@ */ /* - * Copyright (c) 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -27,3 +27,5 @@ int f[4][5][6][7]; int g[4][5][6][7][8]; int h[4][5][6][7][8][9]; int i[4][5][6][7][8][9][10]; + +int empty[] = { }; diff --git a/usr/src/uts/common/io/iwn/if_iwn.c b/usr/src/uts/common/io/iwn/if_iwn.c index 9e07f2b8e2..d12a065be2 100644 --- a/usr/src/uts/common/io/iwn/if_iwn.c +++ b/usr/src/uts/common/io/iwn/if_iwn.c @@ -3222,7 +3222,9 @@ iwn_wakeup_intr(struct iwn_softc *sc) static void iwn_fatal_intr(struct iwn_softc *sc) { - struct iwn_fw_dump dump; + struct iwn_fw_dump *dump; + uint32_t buf[P2ROUNDUP(sizeof (*dump), sizeof (uint32_t)) / + sizeof (uint32_t)]; int i; /* Force a complete recalibration on next init. */ @@ -3230,7 +3232,7 @@ iwn_fatal_intr(struct iwn_softc *sc) /* Check that the error log address is valid. */ if (sc->errptr < IWN_FW_DATA_BASE || - sc->errptr + sizeof (dump) > + sc->errptr + sizeof (*dump) > IWN_FW_DATA_BASE + sc->fw_data_maxsz) { dev_err(sc->sc_dip, CE_WARN, "!bad firmware error log address 0x%08x", sc->errptr); @@ -3242,31 +3244,30 @@ iwn_fatal_intr(struct iwn_softc *sc) return; } /* Read firmware error log from SRAM. */ - /*LINTED: E_PTR_BAD_CAST_ALIGN*/ - iwn_mem_read_region_4(sc, sc->errptr, (uint32_t *)&dump, - sizeof (dump) / sizeof (uint32_t)); + dump = (struct iwn_fw_dump *)buf; + iwn_mem_read_region_4(sc, sc->errptr, buf, ARRAY_SIZE(buf)); iwn_nic_unlock(sc); - if (dump.valid == 0) { + if (dump->valid == 0) { dev_err(sc->sc_dip, CE_WARN, "!firmware error log is empty"); return; } dev_err(sc->sc_dip, CE_WARN, "!firmware error log:"); dev_err(sc->sc_dip, CE_CONT, "! error type = \"%s\" (0x%08X)", - (dump.id < __arraycount(iwn_fw_errmsg)) ? - iwn_fw_errmsg[dump.id] : "UNKNOWN", - dump.id); - dev_err(sc->sc_dip, CE_CONT, "! program counter = 0x%08X", dump.pc); + (dump->id < __arraycount(iwn_fw_errmsg)) ? + iwn_fw_errmsg[dump->id] : "UNKNOWN", + dump->id); + dev_err(sc->sc_dip, CE_CONT, "! program counter = 0x%08X", dump->pc); dev_err(sc->sc_dip, CE_CONT, "! source line = 0x%08X", - dump.src_line); + dump->src_line); dev_err(sc->sc_dip, CE_CONT, "! error data = 0x%08X%08X", - dump.error_data[0], dump.error_data[1]); + dump->error_data[0], dump->error_data[1]); dev_err(sc->sc_dip, CE_CONT, "! branch link = 0x%08X%08X", - dump.branch_link[0], dump.branch_link[1]); + dump->branch_link[0], dump->branch_link[1]); dev_err(sc->sc_dip, CE_CONT, "! interrupt link = 0x%08X%08X", - dump.interrupt_link[0], dump.interrupt_link[1]); - dev_err(sc->sc_dip, CE_CONT, "! time = %u", dump.time[0]); + dump->interrupt_link[0], dump->interrupt_link[1]); + dev_err(sc->sc_dip, CE_CONT, "! time = %u", dump->time[0]); /* Dump driver status (TX and RX rings) while we're here. */ dev_err(sc->sc_dip, CE_WARN, "!driver status:"); |