]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - usr.bin/procstat/procstat_auxv.c
MFC r240514:
[FreeBSD/releng/9.1.git] / usr.bin / procstat / procstat_auxv.c
1 /*-
2  * Copyright (c) 2011 Mikolaj Golub
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/elf.h>
31 #include <sys/sysctl.h>
32 #include <sys/user.h>
33
34 #include <vm/vm.h>
35
36 #include <err.h>
37 #include <errno.h>
38 #include <libprocstat.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "procstat.h"
45
46 #define PROC_AUXV_MAX   256
47
48 static Elf_Auxinfo auxv[PROC_AUXV_MAX];
49 static char prefix[256];
50
51 #if __ELF_WORD_SIZE == 64
52 static Elf32_Auxinfo auxv32[PROC_AUXV_MAX];
53
54 static const char *elf32_sv_names[] = {
55         "Linux ELF32",
56         "FreeBSD ELF32",
57 };
58
59 static int
60 is_elf32(pid_t pid)
61 {
62         int error, name[4];
63         size_t len, i;
64         static char sv_name[256];
65
66         name[0] = CTL_KERN;
67         name[1] = KERN_PROC;
68         name[2] = KERN_PROC_SV_NAME;
69         name[3] = pid;
70         len = sizeof(sv_name);
71         error = sysctl(name, 4, sv_name, &len, NULL, 0);
72         if (error != 0 || len == 0)
73                 return (0);
74         for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) {
75                 if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0)
76                         return (1);
77         }
78         return (0);
79 }
80
81 static size_t
82 retrieve_auxv32(pid_t pid)
83 {
84         int name[4];
85         size_t len, i;
86         void *ptr;
87
88         name[0] = CTL_KERN;
89         name[1] = KERN_PROC;
90         name[2] = KERN_PROC_AUXV;
91         name[3] = pid;
92         len = sizeof(auxv32);
93         if (sysctl(name, 4, auxv32, &len, NULL, 0) == -1) {
94                 if (errno != ESRCH && errno != EPERM)
95                         warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
96                 return (0);
97         }
98         for (i = 0; i < len; i++) {
99                 /*
100                  * XXX: We expect that values for a_type on a 32-bit platform
101                  * are directly mapped to those on 64-bit one, which is not
102                  * necessarily true.
103                  */
104                 auxv[i].a_type = auxv32[i].a_type;
105                 ptr = &auxv32[i].a_un;
106                 auxv[i].a_un.a_val = *((uint32_t *)ptr);
107         }
108         return (len);
109 }
110 #endif /* __ELF_WORD_SIZE == 64 */
111
112 #define PRINT(name, spec, val)          \
113         printf("%s %-16s " #spec "\n", prefix, #name, (val))
114 #define PRINT_UNKNOWN(type, val)        \
115         printf("%s %16ld %#lx\n", prefix, (long)type, (u_long)(val))
116
117 static size_t
118 retrieve_auxv(pid_t pid)
119 {
120         int name[4];
121         size_t len;
122
123 #if __ELF_WORD_SIZE == 64
124         if (is_elf32(pid))
125                 return (retrieve_auxv32(pid));
126 #endif
127         name[0] = CTL_KERN;
128         name[1] = KERN_PROC;
129         name[2] = KERN_PROC_AUXV;
130         name[3] = pid;
131         len = sizeof(auxv);
132         if (sysctl(name, 4, auxv, &len, NULL, 0) == -1) {
133                 if (errno != ESRCH && errno != EPERM)
134                         warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
135                 return (0);
136         }
137         return (len);
138 }
139
140 void
141 procstat_auxv(struct kinfo_proc *kipp)
142 {
143         size_t len, i;
144
145         if (!hflag)
146                 printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE");
147         len = retrieve_auxv(kipp->ki_pid);
148         if (len == 0)
149                 return;
150         snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid,
151             kipp->ki_comm);
152         for (i = 0; i < len; i++) {
153                 switch(auxv[i].a_type) {
154                 case AT_NULL:
155                         return;
156                 case AT_IGNORE:
157                         break;
158                 case AT_EXECFD:
159                         PRINT(AT_EXECFD, %ld, (long)auxv[i].a_un.a_val);
160                         break;
161                 case AT_PHDR:
162                         PRINT(AT_PHDR, %p, auxv[i].a_un.a_ptr);
163                         break;
164                 case AT_PHENT:
165                         PRINT(AT_PHENT, %ld, (long)auxv[i].a_un.a_val);
166                         break;
167                 case AT_PHNUM:
168                         PRINT(AT_PHNUM, %ld, (long)auxv[i].a_un.a_val);
169                         break;
170                 case AT_PAGESZ:
171                         PRINT(AT_PAGESZ, %ld, (long)auxv[i].a_un.a_val);
172                         break;
173                 case AT_BASE:
174                         PRINT(AT_BASE, %p, auxv[i].a_un.a_ptr);
175                         break;
176                 case AT_FLAGS:
177                         PRINT(AT_FLAGS, %#lx, (u_long)auxv[i].a_un.a_val);
178                         break;
179                 case AT_ENTRY:
180                         PRINT(AT_ENTRY, %p, auxv[i].a_un.a_ptr);
181                         break;
182 #ifdef AT_NOTELF
183                 case AT_NOTELF:
184                         PRINT(AT_NOTELF, %ld, (long)auxv[i].a_un.a_val);
185                         break;
186 #endif
187 #ifdef AT_UID
188                 case AT_UID:
189                         PRINT(AT_UID, %ld, (long)auxv[i].a_un.a_val);
190                         break;
191 #endif
192 #ifdef AT_EUID
193                 case AT_EUID:
194                         PRINT(AT_EUID, %ld, (long)auxv[i].a_un.a_val);
195                         break;
196 #endif
197 #ifdef AT_GID
198                 case AT_GID:
199                         PRINT(AT_GID, %ld, (long)auxv[i].a_un.a_val);
200                         break;
201 #endif
202 #ifdef AT_EGID
203                 case AT_EGID:
204                         PRINT(AT_EGID, %ld, (long)auxv[i].a_un.a_val);
205                         break;
206 #endif
207                 case AT_EXECPATH:
208                         PRINT(AT_EXECPATH, %p, auxv[i].a_un.a_ptr);
209                         break;
210                 case AT_CANARY:
211                         PRINT(AT_CANARY, %p, auxv[i].a_un.a_ptr);
212                         break;
213                 case AT_CANARYLEN:
214                         PRINT(AT_CANARYLEN, %ld, (long)auxv[i].a_un.a_val);
215                         break;
216                 case AT_OSRELDATE:
217                         PRINT(AT_OSRELDATE, %ld, (long)auxv[i].a_un.a_val);
218                         break;
219                 case AT_NCPUS:
220                         PRINT(AT_NCPUS, %ld, (long)auxv[i].a_un.a_val);
221                         break;
222                 case AT_PAGESIZES:
223                         PRINT(AT_PAGESIZES, %p, auxv[i].a_un.a_ptr);
224                         break;
225                 case AT_PAGESIZESLEN:
226                         PRINT(AT_PAGESIZESLEN, %ld, (long)auxv[i].a_un.a_val);
227                         break;
228                 case AT_STACKPROT:
229                         if ((auxv[i].a_un.a_val & VM_PROT_EXECUTE) != 0)
230                                 PRINT(AT_STACKPROT, %s, "NONEXECUTABLE");
231                         else
232                                 PRINT(AT_STACKPROT, %s, "EXECUTABLE");
233                         break;
234                 case AT_COUNT:
235                         PRINT(AT_COUNT, %ld, (long)auxv[i].a_un.a_val);
236                         break;
237                 default:
238                         PRINT_UNKNOWN(auxv[i].a_type, auxv[i].a_un.a_val);
239                         break;
240                 }
241         }
242         printf("\n");
243 }
244