#ifdefined __amd64__ || defined __i386__ /* * Copyright (c) 2022 Alexey Dobriyan <adobriyan@gmail.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ /* * Create a process without mappings by unmapping everything at once and * holding it with ptrace(2). See what happens to * * /proc/${pid}/maps * /proc/${pid}/numa_maps * /proc/${pid}/smaps * /proc/${pid}/smaps_rollup
*/ #undef _GNU_SOURCE #define _GNU_SOURCE
/* * There seems to be 2 types of valid output: * "0 A A B 0 0 0\n" for dynamic exeuctables, * "0 0 0 B 0 0 0\n" for static executables.
*/ staticint test_proc_pid_statm(pid_t pid)
{ char buf[4096];
snprintf(buf, sizeof(buf), "/proc/%u/statm", pid); int fd = open(buf, O_RDONLY); if (fd == -1) {
perror("open /proc/${pid}/statm"); return EXIT_FAILURE;
}
constchar *p = buf; constchar *const end = p + rv;
/* size */
assert(p != end && *p++ == '0');
assert(p != end && *p++ == ' ');
uint64_t resident;
p = parse_u64(p, end, &resident);
assert(p != end && *p++ == ' ');
uint64_t shared;
p = parse_u64(p, end, &shared);
assert(p != end && *p++ == ' ');
uint64_t text;
p = parse_u64(p, end, &text);
assert(p != end && *p++ == ' ');
assert(p != end && *p++ == '0');
assert(p != end && *p++ == ' ');
/* data */
assert(p != end && *p++ == '0');
assert(p != end && *p++ == ' ');
assert(p != end && *p++ == '0');
assert(p != end && *p++ == '\n');
assert(p == end);
/* * "text" is "mm->end_code - mm->start_code" at execve(2) time. * munmap() doesn't change it. It can be anything (just link * statically). It can't be 0 because executing to this point * implies at least 1 page of code.
*/
assert(text > 0);
/* * These two are always equal. Always 0 for statically linked * executables and sometimes 0 for dynamically linked executables. * There is no way to tell one from another without parsing ELF * which is too much for this test.
*/
assert(resident == shared);
for (len = -4096;; len -= 4096) {
munmap(NULL, len);
}
} #else #error"implement 'unmap everything'" #endif return EXIT_FAILURE;
} else { /* * TODO find reliable way to signal parent that munmap(2) completed. * Child can't do it directly because it effectively doesn't exist * anymore. Looking at child's VM files isn't 100% reliable either: * due to a bug they may not become empty or empty-like.
*/
sleep(1);
if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_maps(pid);
} if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_numa_maps(pid);
} if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_smaps(pid);
} if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_smaps_rollup(pid);
} if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_statm(pid);
}
/* Cut the rope. */ int wstatus;
waitpid(pid, &wstatus, 0);
assert(WIFSTOPPED(wstatus));
assert(WSTOPSIG(wstatus) == SIGSEGV);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.