summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2020-06-30 11:44:13 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2020-06-30 11:44:13 +0000
commit4e1f938f9e4d41dcfe106b432ae2b08d3d5ab7c5 (patch)
tree2c61f53413cda0b76794d52f5b730115bf50b659
parentcb3493721e0f08d42f41165a7c089d9c11dcecab (diff)
parent1326c48877254e828afea8c9f7529f6faf1a1fde (diff)
downloadillumos-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.c400
-rw-r--r--usr/src/data/locale/Makefile6
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c117
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-array.c10
-rw-r--r--usr/src/test/util-tests/tests/ctf/test-array.c4
-rw-r--r--usr/src/uts/common/io/iwn/if_iwn.c31
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:");