#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#define NELEMS(arr) (sizeof(arr)/sizeof(arr[0]))
#define BUF_SIZE (BUFSIZ)
+#define HEXA 16
+#define PERM_LEN 5
+#define ADDR_LEN 16
+#define STR_ANONY "[anony]"
+#define STR_ANONY_LEN 8
enum {
OPT_HELP,
OPT_SAVE_CORE,
};
+struct addr_node {
+ long *startaddr;
+ long *endaddr;
+ char perm[5];
+ char *fpath;
+ struct addr_node *next;
+};
+
const struct option opts[] = {
{ "help", no_argument, 0, OPT_HELP },
{ "report", no_argument, 0, OPT_REPORT },
return (num == 0 && cs == str) ? NULL : str;
}
-static void meminfo_report(const char *pidstr){
+static void meminfo_report(const char *pidstr)
+{
char infoname[BUF_SIZE];
char memsize[BUF_SIZE];
char linebuf[BUF_SIZE];
}
}
+static struct addr_node *get_addr_list_from_maps(int fd)
+{
+ int fpath_len, result;
+ long *saddr;
+ long *eaddr;
+ char perm[PERM_LEN];
+ char path[PATH_MAX];
+ char addr[ADDR_LEN * 2];
+ char linebuf[BUF_SIZE];
+ struct addr_node *head = NULL;
+ struct addr_node *tail = NULL;
+ struct addr_node *t_node = NULL;
+
+ /* parsing the maps to get executable code address */
+ while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
+ memset(path, 0, PATH_MAX);
+ result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
+ if (result < 0)
+ continue;
+ perm[PERM_LEN - 1] = 0;
+ /* rwxp */
+ if ((perm[2] == 'x' && path[0] == '/') ||
+ (perm[1] == 'w' && path[0] != '/'))
+ {
+ /* add addr node to list */
+ addr[ADDR_LEN] = 0;
+ saddr = (long *)strtoul(addr, NULL, HEXA);
+ /* ffff0000-ffff1000 */
+ eaddr = (long *)strtoul(&addr[ADDR_LEN + 1], NULL, HEXA);
+ /* make node and attach to the list */
+ t_node = (struct addr_node *)mmap(0, sizeof(struct addr_node),
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (t_node == NULL) {
+ fprintf(stderr, "error : mmap\n");
+ return NULL;
+ }
+ memcpy(t_node->perm, perm, PERM_LEN);
+ t_node->startaddr = saddr;
+ t_node->endaddr = eaddr;
+ t_node->fpath = NULL;
+ fpath_len = strlen(path);
+ if (fpath_len > 0) {
+ t_node->fpath = (char *)mmap(0, fpath_len + 1,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, fpath_len + 1);
+ memcpy(t_node->fpath, path, fpath_len);
+ } else {
+ t_node->fpath = (char *)mmap(0, STR_ANONY_LEN,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, STR_ANONY_LEN);
+ memcpy(t_node->fpath, STR_ANONY, STR_ANONY_LEN);
+ }
+ t_node->next = NULL;
+ if (head == NULL) {
+ head = t_node;
+ tail = t_node;
+ } else {
+ tail->next = t_node;
+ tail = t_node;
+ }
+ }
+ }
+ return head;
+}
+
+static void free_all_nodes(struct addr_node *start)
+{
+ struct addr_node *t_node, *n_node;
+ int fpath_len;
+
+ if (start == NULL)
+ return;
+ t_node = start;
+ n_node = t_node->next;
+ while (t_node) {
+ if (t_node->fpath != NULL) {
+ fpath_len = strlen(t_node->fpath);
+ munmap(t_node->fpath, fpath_len + 1);
+ }
+ munmap(t_node, sizeof(struct addr_node));
+ if (n_node == NULL)
+ break;
+ t_node = n_node;
+ n_node = n_node->next;
+ }
+}
+
+static void print_node_to_file(struct addr_node *start)
+{
+ struct addr_node *t_node;
+
+ t_node = start;
+ printf("\n%s\n", "Maps Information");
+ while (t_node) {
+ if (!strncmp(STR_ANONY, t_node->fpath, STR_ANONY_LEN)) {
+ t_node = t_node->next;
+ } else {
+ printf( "%16lx %16lx %s %s\n",
+ (unsigned long)t_node->startaddr,
+ (unsigned long)t_node->endaddr,
+ t_node->perm, t_node->fpath);
+ t_node = t_node->next;
+ }
+ }
+ printf("%s\n", "End of Maps Information");
+}
+
+static void maps_report(const char *pidstr)
+{
+ char file_path[PATH_MAX];
+ struct addr_node *head = NULL;
+ int fd;
+
+ /* open maps file */
+ snprintf(file_path, PATH_MAX, "/proc/%s/maps", pidstr);
+
+ if ((fd = open(file_path, O_RDONLY)) < 0) {
+ fprintf(stderr, "[crash-pipe]can't open %s\n", file_path);
+ } else {
+ /* parsing the maps to get code segment address*/
+ head = get_addr_list_from_maps(fd);
+ close(fd);
+ }
+ if (head != NULL) {
+ /* print maps information */
+ print_node_to_file(head);
+ free_all_nodes(head);
+ }
+}
+
static void report(int argc, char *argv[])
{
const char *pidstr = argv[0];
meminfo_report(pidstr);
+ maps_report(pidstr);
+
printf(" - passed from kernel -\n"
"%16s: %s\n"
"%16s: %s\n"