Files
mckernel/test/proc_maps/arm64/proc_maps.c
Shiratori, Takehiro cf113d392a Test "/proc/PID/maps support add" on arm64.
Change-Id: I0585ae6257b5c0269760dd7f23ba75b83dd7ac2c
2018-11-22 04:53:04 +00:00

255 lines
5.6 KiB
C

/* proc_maps.c COPYRIGHT FUJITSU LIMITED 2018 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#define BUF_SIZE 4096
#define EXP_STR_SIZE 64
int main(int argc, char *argv[])
{
FILE *fp = NULL;
const char pfname[] = "/proc/self/maps";
int result = 0;
int i = 0;
int offset_ng = 0;
int dev_ng = 0;
int inode_ng = 0;
int vdso_ok = 0;
int vsyscall_ok = 0;
int stack_ok = 0;
int heap_ok = 0;
int pathempty_ok = 0;
const unsigned int page_size = sysconf(_SC_PAGESIZE);
char buf[BUF_SIZE];
struct {
int okng;
int prot;
int flags;
void *addr;
char exp[EXP_STR_SIZE];
} mapconf[] = {
{ -1, PROT_NONE, MAP_PRIVATE },
{ -1, PROT_NONE, MAP_SHARED },
{ -1, PROT_READ, MAP_PRIVATE },
{ -1, PROT_READ, MAP_SHARED },
{ -1, PROT_WRITE, MAP_PRIVATE },
{ -1, PROT_WRITE, MAP_SHARED },
{ -1, PROT_EXEC, MAP_PRIVATE },
{ -1, PROT_EXEC, MAP_SHARED },
{ -1, PROT_READ | PROT_WRITE, MAP_PRIVATE },
{ -1, PROT_READ | PROT_WRITE, MAP_SHARED },
{ -1, PROT_READ | PROT_EXEC, MAP_PRIVATE },
{ -1, PROT_READ | PROT_EXEC, MAP_SHARED },
{ -1, PROT_WRITE | PROT_EXEC, MAP_PRIVATE },
{ -1, PROT_WRITE | PROT_EXEC, MAP_SHARED },
{ -1, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE },
{ -1, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED },
};
/* fopen */
if ((fp = fopen(pfname, "r")) == NULL) {
printf("fopen() failed. %d\n", errno);
result = -1;
goto fast_err;
}
/* mapping */
for (i = 0; i < sizeof(mapconf) / sizeof(mapconf[0]); i++) {
mapconf[i].addr = mmap(NULL, page_size, mapconf[i].prot,
mapconf[i].flags | MAP_ANONYMOUS, -1, 0);
if (mapconf[i].addr == NULL) {
printf("mmap(prot=%d, flags=%d) failed. %d\n",
mapconf[i].prot, mapconf[i].flags, errno);
result = -1;
goto err;
}
snprintf(mapconf[i].exp, sizeof(mapconf[i].exp),
"%lx-%lx %s%s%s%s", mapconf[i].addr, mapconf[i].addr + page_size,
mapconf[i].prot & PROT_READ ? "r" : "-",
mapconf[i].prot & PROT_WRITE ? "w" : "-",
mapconf[i].prot & PROT_EXEC ? "x" : "-",
mapconf[i].flags & MAP_PRIVATE ? "p" : "s");
}
/* print-procfs */
while (fgets(buf, sizeof(buf), fp) != NULL) {
unsigned long start;
unsigned long end;
char prot[8];
unsigned long offset = 1;
unsigned long dev1 = 1;
unsigned long dev2 = 1;
unsigned long inode = 1;
char pathname[BUF_SIZE] = "\0";
sscanf(buf, "%lx-%lx %s %lx %lx:%lx %lx\t\t\t%s",
&start, &end, prot, &offset, &dev1, &dev2, &inode, pathname);
if (offset != 0) {
offset_ng = 1;
}
if (dev1 != 0 || dev2 != 0) {
dev_ng = 1;
}
if (inode != 0) {
inode_ng = 1;
}
if (strlen(pathname) != 0) {
if (vdso_ok != 1) {
if (!strcmp("[vdso]", pathname)) {
vdso_ok = 1;
}
}
if (vsyscall_ok != 1) {
if (!strcmp("[vsyscall]", pathname)) {
vsyscall_ok = 1;
}
}
if (stack_ok != 1) {
if (!strcmp("[stack]", pathname)) {
unsigned long stack_addr = (unsigned long)pathname;
stack_addr--;
if ((start <= stack_addr) &&
(stack_addr < end)) {
stack_ok = 1;
} else {
stack_ok = -1;
}
}
}
if (heap_ok != 1) {
if (!strcmp("[heap]", pathname)) {
unsigned long heap_addr = (unsigned long)sbrk(0);
heap_addr--;
if ((start <= heap_addr) &&
(heap_addr < end)) {
heap_ok = 1;
} else {
heap_ok = -1;
}
}
}
} else if (pathempty_ok != 1) {
pathempty_ok = 1;
}
for (i = 0; i < sizeof(mapconf) / sizeof(mapconf[0]); i++) {
if (mapconf[i].okng == -1) {
if (strstr(buf, mapconf[i].exp)) {
mapconf[i].okng = 0;
break;
}
}
}
}
/* unmapping */
for (i = 0; i < sizeof(mapconf) / sizeof(mapconf[0]); i++) {
munmap(mapconf[i].addr, page_size);
}
/* ok/ng check */
/* addr, prot and flags */
for (i = 0; i < sizeof(mapconf) / sizeof(mapconf[0]); i++) {
if (mapconf[i].okng == -1) {
printf("TEST%03d: NG, %s not found.\n", i + 1, mapconf[i].exp);
result = -1;
} else {
printf("TEST%03d: OK\n", i + 1);
}
}
/* offset */
if (offset_ng == 1) {
printf("TEST%03d: NG, offset field is not 0.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
/* dev */
if (dev_ng == 1) {
printf("TEST%03d: NG, dev field is not 0.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
/* inode */
if (inode_ng == 1) {
printf("TEST%03d: NG, inode field is not 0.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
/* pathname */
/* [vsdo] */
if (vdso_ok == 1) {
printf("TEST%03d: OK\n", ++i);
} else {
printf("TEST%03d: NG, [vdso] pathname not found.\n", ++i);
result = -1;
}
/* [vsyscall] */
if (vsyscall_ok == 1) {
printf("TEST%03d: OK\n", ++i);
} else {
printf("TEST%03d: NG, [vsyscall] pathname not found.\n", ++i);
result = -1;
}
/* [stack] */
if (stack_ok == 0) {
printf("TEST%03d: NG, [stack] pathname not found.\n", ++i);
result = -1;
} else if (stack_ok == -1) {
printf("TEST%03d: NG, [stack] pathname found, but addr is not expected.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
/* [heap] */
if (heap_ok == 0) {
printf("TEST%03d: NG, [heap] pathname not found.\n", ++i);
result = -1;
} else if (heap_ok == -1) {
printf("TEST%03d: NG, [heap] pathname found, but addr is not expected.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
/* empty */
if (pathempty_ok == 0) {
printf("TEST%03d: NG, empty pathname not found.\n", ++i);
result = -1;
} else {
printf("TEST%03d: OK\n", ++i);
}
err:
if (fclose(fp)) {
printf("fclose() failed. %d\n", errno);
result = -1;
}
fast_err:
return result;
}