Deleted Added
full compact
core.c (249677) core.c (249679)
1/*-
2 * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
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 unchanged lines hidden (view full) ---

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 *
1/*-
2 * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
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 unchanged lines hidden (view full) ---

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: head/lib/libprocstat/core.c 249677 2013-04-20 08:03:56Z trociny $
26 * $FreeBSD: head/lib/libprocstat/core.c 249679 2013-04-20 08:07:04Z trociny $
27 */
28
29#include <sys/param.h>
30#include <sys/elf.h>
27 */
28
29#include <sys/param.h>
30#include <sys/elf.h>
31#include <sys/exec.h>
31#include <sys/user.h>
32
33#include <assert.h>
34#include <err.h>
35#include <fcntl.h>
36#include <gelf.h>
37#include <libelf.h>
38#include <stdbool.h>

--- 12 unchanged lines hidden (view full) ---

51 int pc_fd;
52 Elf *pc_elf;
53 GElf_Ehdr pc_ehdr;
54 GElf_Phdr pc_phdr;
55};
56
57static bool core_offset(struct procstat_core *core, off_t offset);
58static bool core_read(struct procstat_core *core, void *buf, size_t len);
32#include <sys/user.h>
33
34#include <assert.h>
35#include <err.h>
36#include <fcntl.h>
37#include <gelf.h>
38#include <libelf.h>
39#include <stdbool.h>

--- 12 unchanged lines hidden (view full) ---

52 int pc_fd;
53 Elf *pc_elf;
54 GElf_Ehdr pc_ehdr;
55 GElf_Phdr pc_phdr;
56};
57
58static bool core_offset(struct procstat_core *core, off_t offset);
59static bool core_read(struct procstat_core *core, void *buf, size_t len);
60static ssize_t core_read_mem(struct procstat_core *core, void *buf,
61 size_t len, vm_offset_t addr, bool readall);
62static void *get_args(struct procstat_core *core, vm_offset_t psstrings,
63 enum psc_type type, void *buf, size_t *lenp);
59
60struct procstat_core *
61procstat_core_open(const char *filename)
62{
63 struct procstat_core *core;
64 Elf *e;
65 GElf_Ehdr ehdr;
66 GElf_Phdr phdr;

--- 74 unchanged lines hidden (view full) ---

141}
142
143void *
144procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
145 size_t *lenp)
146{
147 Elf_Note nhdr;
148 off_t offset, eoffset;
64
65struct procstat_core *
66procstat_core_open(const char *filename)
67{
68 struct procstat_core *core;
69 Elf *e;
70 GElf_Ehdr ehdr;
71 GElf_Phdr phdr;

--- 74 unchanged lines hidden (view full) ---

146}
147
148void *
149procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
150 size_t *lenp)
151{
152 Elf_Note nhdr;
153 off_t offset, eoffset;
154 vm_offset_t psstrings;
149 void *freebuf;
150 size_t len;
151 u_int32_t n_type;
152 int cstructsize, structsize;
153 char nbuf[8];
154
155 assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
156

--- 21 unchanged lines hidden (view full) ---

178 case PSC_TYPE_RLIMIT:
179 n_type = NT_PROCSTAT_RLIMIT;
180 structsize = sizeof(struct rlimit) * RLIM_NLIMITS;
181 break;
182 case PSC_TYPE_OSREL:
183 n_type = NT_PROCSTAT_OSREL;
184 structsize = sizeof(int);
185 break;
155 void *freebuf;
156 size_t len;
157 u_int32_t n_type;
158 int cstructsize, structsize;
159 char nbuf[8];
160
161 assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
162

--- 21 unchanged lines hidden (view full) ---

184 case PSC_TYPE_RLIMIT:
185 n_type = NT_PROCSTAT_RLIMIT;
186 structsize = sizeof(struct rlimit) * RLIM_NLIMITS;
187 break;
188 case PSC_TYPE_OSREL:
189 n_type = NT_PROCSTAT_OSREL;
190 structsize = sizeof(int);
191 break;
192 case PSC_TYPE_PSSTRINGS:
193 case PSC_TYPE_ARGV:
194 case PSC_TYPE_ENVV:
195 n_type = NT_PROCSTAT_PSSTRINGS;
196 structsize = sizeof(vm_offset_t);
197 break;
186 default:
187 warnx("unknown core stat type: %d", type);
188 return (NULL);
189 }
190
191 offset = core->pc_phdr.p_offset;
192 eoffset = offset + core->pc_phdr.p_filesz;
193

--- 39 unchanged lines hidden (view full) ---

233 warn("malloc(%zu)", len);
234 return (NULL);
235 }
236 }
237 if (!core_read(core, buf, len)) {
238 free(freebuf);
239 return (NULL);
240 }
198 default:
199 warnx("unknown core stat type: %d", type);
200 return (NULL);
201 }
202
203 offset = core->pc_phdr.p_offset;
204 eoffset = offset + core->pc_phdr.p_filesz;
205

--- 39 unchanged lines hidden (view full) ---

245 warn("malloc(%zu)", len);
246 return (NULL);
247 }
248 }
249 if (!core_read(core, buf, len)) {
250 free(freebuf);
251 return (NULL);
252 }
253 if (type == PSC_TYPE_ARGV || type == PSC_TYPE_ENVV) {
254 if (len < sizeof(psstrings)) {
255 free(freebuf);
256 return (NULL);
257 }
258 psstrings = *(vm_offset_t *)buf;
259 if (freebuf == NULL)
260 len = *lenp;
261 else
262 buf = NULL;
263 free(freebuf);
264 buf = get_args(core, psstrings, type, buf, &len);
265 }
241 *lenp = len;
242 return (buf);
243 }
244
245 return (NULL);
246}
247
248static bool

--- 22 unchanged lines hidden (view full) ---

271 return (false);
272 }
273 if (n < (ssize_t)len) {
274 warnx("core: short read");
275 return (false);
276 }
277 return (true);
278}
266 *lenp = len;
267 return (buf);
268 }
269
270 return (NULL);
271}
272
273static bool

--- 22 unchanged lines hidden (view full) ---

296 return (false);
297 }
298 if (n < (ssize_t)len) {
299 warnx("core: short read");
300 return (false);
301 }
302 return (true);
303}
304
305static ssize_t
306core_read_mem(struct procstat_core *core, void *buf, size_t len,
307 vm_offset_t addr, bool readall)
308{
309 GElf_Phdr phdr;
310 off_t offset;
311 int i;
312
313 assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
314
315 for (i = 0; i < core->pc_ehdr.e_phnum; i++) {
316 if (gelf_getphdr(core->pc_elf, i, &phdr) != &phdr) {
317 warnx("gelf_getphdr: %s", elf_errmsg(-1));
318 return (-1);
319 }
320 if (phdr.p_type != PT_LOAD)
321 continue;
322 if (addr < phdr.p_vaddr || addr > phdr.p_vaddr + phdr.p_memsz)
323 continue;
324 offset = phdr.p_offset + (addr - phdr.p_vaddr);
325 if ((phdr.p_vaddr + phdr.p_memsz) - addr < len) {
326 if (readall) {
327 warnx("format error: "
328 "attempt to read out of segment");
329 return (-1);
330 }
331 len = (phdr.p_vaddr + phdr.p_memsz) - addr;
332 }
333 if (!core_offset(core, offset))
334 return (-1);
335 if (!core_read(core, buf, len))
336 return (-1);
337 return (len);
338 }
339 warnx("format error: address %ju not found", (uintmax_t)addr);
340 return (-1);
341}
342
343#define ARGS_CHUNK_SZ 256 /* Chunk size (bytes) for get_args operations. */
344
345static void *
346get_args(struct procstat_core *core, vm_offset_t psstrings, enum psc_type type,
347 void *args, size_t *lenp)
348{
349 struct ps_strings pss;
350 void *freeargs;
351 vm_offset_t addr;
352 char **argv, *p;
353 size_t chunksz, done, len, nchr, size;
354 ssize_t n;
355 u_int i, nstr;
356
357 assert(type == PSC_TYPE_ARGV || type == PSC_TYPE_ENVV);
358
359 if (core_read_mem(core, &pss, sizeof(pss), psstrings, true) == -1)
360 return (NULL);
361 if (type == PSC_TYPE_ARGV) {
362 addr = (vm_offset_t)pss.ps_argvstr;
363 nstr = pss.ps_nargvstr;
364 } else /* type == PSC_TYPE_ENVV */ {
365 addr = (vm_offset_t)pss.ps_envstr;
366 nstr = pss.ps_nenvstr;
367 }
368 if (addr == 0 || nstr == 0)
369 return (NULL);
370 if (nstr > ARG_MAX) {
371 warnx("format error");
372 return (NULL);
373 }
374 size = nstr * sizeof(char *);
375 argv = malloc(size);
376 if (argv == NULL) {
377 warn("malloc(%zu)", size);
378 return (NULL);
379 }
380 done = 0;
381 freeargs = NULL;
382 if (core_read_mem(core, argv, size, addr, true) == -1)
383 goto fail;
384 if (args != NULL) {
385 nchr = MIN(ARG_MAX, *lenp);
386 } else {
387 nchr = ARG_MAX;
388 freeargs = args = malloc(nchr);
389 if (args == NULL) {
390 warn("malloc(%zu)", nchr);
391 goto fail;
392 }
393 }
394 p = args;
395 for (i = 0; ; i++) {
396 if (i == nstr)
397 goto done;
398 /*
399 * The program may have scribbled into its argv array, e.g. to
400 * remove some arguments. If that has happened, break out
401 * before trying to read from NULL.
402 */
403 if (argv[i] == NULL)
404 goto done;
405 for (addr = (vm_offset_t)argv[i]; ; addr += chunksz) {
406 chunksz = MIN(ARGS_CHUNK_SZ, nchr - 1 - done);
407 if (chunksz <= 0)
408 goto done;
409 n = core_read_mem(core, p, chunksz, addr, false);
410 if (n == -1)
411 goto fail;
412 len = strnlen(p, chunksz);
413 p += len;
414 done += len;
415 if (len != chunksz)
416 break;
417 }
418 *p++ = '\0';
419 done++;
420 }
421fail:
422 free(freeargs);
423 args = NULL;
424done:
425 *lenp = done;
426 free(argv);
427 return (args);
428}