Beispiel #1
0
Datei: 01.c Projekt: 2ion/scripts
int main(int argc, char**argv) {
  long int x;
  int fd;
  size_t cnt;
  unsigned char _buf[BUILTIN_BUF_LEN] = {0};
  unsigned char *buf = _buf;

  if(argc != 2)
    return 1;

  switch(x = strtol((const char*)argv[1], NULL, 0xA)) {
    case LONG_MIN:
    case LONG_MAX:
      perror("Invalid argument");
      return 1;
    default:
      break;
  }

  cnt = (size_t) (x < 0 ? 0 : x);

  if(cnt > BUILTIN_BUF_LEN) {
    if((buf = malloc(sizeof(char)*cnt)) == NULL) {
      perror("Memory allocation error");
      return 1;
    }
    memset(buf, 0, cnt);
  }

  if((fd = open("/dev/urandom", O_RDONLY)) == -1) {
    perror("Failed to open /dev/urandom");
    FREEBUF(buf, _buf);  
    return 1;
  }

  if(read(fd, buf, cnt) == -1) {
    perror("Couldn't read from /dev/urandom");
    close(fd);
    FREEBUF(buf, _buf);
    return 1;
  }

  for(x = 0; x < cnt; x++)
    printbits(buf[x]);

  putchar('\n');

  close(fd);
  FREEBUF(buf, _buf);

  return 0;
}
Beispiel #2
0
void optFreeOptions()
{
    int i;
    for(i = 0; i < g_opts.nCount; i++){
        OptCmdOptions *opts = &(g_opts.opts[i]);

        FREEBUF(opts->long_name);
        FREEBUF(opts->description);
    }
    g_opts.opts = NULL;
    g_opts.nSize = 0;
    FREEBUF(g_opts.opts);
    g_opts.nCount = 0;
}
void
map_cpus_to_prstatus_kdump_cmprs(void)
{
	void **nt_ptr;
	int online, i, j, nrcpus;
	size_t size;

	if (!(online = get_cpus_online()) || (online == kt->cpus))
		return;

	if (CRASHDEBUG(1))
		error(INFO,
		    "cpus: %d online: %d NT_PRSTATUS notes: %d (remapping)\n",
			kt->cpus, online, dd->num_prstatus_notes);

	size = NR_CPUS * sizeof(void *);

	nt_ptr = (void **)GETBUF(size);
	BCOPY(dd->nt_prstatus_percpu, nt_ptr, size);
	BZERO(dd->nt_prstatus_percpu, size);

	/*
	 *  Re-populate the array with the notes mapping to online cpus
	 */
	nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);

	for (i = 0, j = 0; i < nrcpus; i++) {
		if (in_cpu_map(ONLINE, i))
			dd->nt_prstatus_percpu[i] = nt_ptr[j++];
	}

	FREEBUF(nt_ptr);
}
Beispiel #4
0
/*
 *  Quickest way to gdb -- just pass a command string to pass through.
 */
int
gdb_pass_through(char *cmd, FILE *fptr, ulong flags)
{
        struct gnu_request *req;
	int retval;

	if (CRASHDEBUG(1))
  		console("gdb_pass_through: [%s]\n", cmd); 

        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
        req->buf = cmd;
	if (fptr)
		req->fp = fptr;
        req->command = GNU_PASS_THROUGH;
	req->flags = flags;

        gdb_interface(req);

	if ((req->flags & (GNU_RETURN_ON_ERROR|GNU_COMMAND_FAILED)) ==
	    (GNU_RETURN_ON_ERROR|GNU_COMMAND_FAILED))
		retval = FALSE;
	else
		retval = TRUE;

        FREEBUF(req);

	return retval;
}
Beispiel #5
0
/*
 *  Check whether string in args[0] is a valid gdb command.
 */
int
is_gdb_command(int merge_orig_args, ulong flags)
{
        int retval;
        struct gnu_request *req;

        if (!args[0])
                return FALSE;

	if (STREQ(args[0], "Q")) {
		args[0] = "q";
		return TRUE;
	}

	if (is_restricted_command(args[0], flags))
		return FALSE;

        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
	req->buf = GETBUF(strlen(args[0])+1);
        req->command = GNU_COMMAND_EXISTS;
        req->name = args[0];
        req->flags = GNU_RETURN_ON_ERROR; 
	req->fp = pc->nullfp;

        gdb_interface(req);

	if (req->flags & GNU_COMMAND_FAILED) 
		retval = FALSE;
	else
        	retval = req->value;

	FREEBUF(req->buf);
        FREEBUF(req);

	if (retval && merge_orig_args) {
		int i;
		for (i = argcnt; i; i--)
			args[i] = args[i-1];
		args[0] = "gdb";
		argcnt++;
	}

        return retval;
}
int 
dwarf_print_stack_entry(struct bt_info *bt, int level)
{
	unsigned long offset;
	struct syment *sp;
	char *name;
	struct unwind_frame_info *frame;

	frame = (struct unwind_frame_info *)GETBUF(sizeof(struct unwind_frame_info));
	UNW_SP(frame) = bt->stkptr;
	UNW_PC(frame) = bt->instptr;

	sp = value_search(UNW_PC(frame), &offset);
	if (!sp) {
		if (CRASHDEBUG(1))
		    fprintf(fp, "unwind: cannot find symbol for PC: %lx\n",
			UNW_PC(frame));
		goto bailout;
	}

	/*
	 * If offset is zero, it means we have crossed over to the next
	 *  function. Recalculate by adjusting the text address
	 */
	if (!offset) {
		sp = value_search(UNW_PC(frame) - 1, &offset);
		if (!sp) {
			if (CRASHDEBUG(1))
				fprintf(fp,
				    "unwind: cannot find symbol for PC: %lx\n",
					UNW_PC(frame)-1);
			goto bailout;
		}
	}
        name = sp->name;
	fprintf(fp, " #%d [%016lx] %s at %016lx \n", level, UNW_SP(frame), name, UNW_PC(frame));

bailout:
	FREEBUF(frame);
	return level;
}
void
dwarf_debug(struct bt_info *bt)
{
	struct unwind_frame_info *frame;
	ulong bp;
	int is_ehframe = (!st->dwarf_debug_frame_size && st->dwarf_eh_frame_size);

	if (!bt->hp->eip) {
		dump_local_unwind_tables();
		return;
	}

	if (!(kt->flags & DWARF_UNWIND_CAPABLE)) {
		error(INFO, "not DWARF capable\n");
		return;
	}

        frame = (struct unwind_frame_info *)GETBUF(sizeof(struct unwind_frame_info));

	/*
	 *  XXX: This only works for the first PC/SP pair seen in a normal
	 *  backtrace, so it's not particularly helpful.  Ideally it should
         *  be capable to take any PC/SP pair in a stack, but it appears to
	 *  related to the rbp value. 
	 */

	UNW_PC(frame) = bt->hp->eip;
	UNW_SP(frame) = bt->hp->esp;

        readmem(UNW_SP(frame), KVADDR, &bp,
 		sizeof(unsigned long), "reading bp", FAULT_ON_ERROR);
        frame->regs.rbp = bp;  /* fixme for x86 */

	unwind(frame, is_ehframe);

	fprintf(fp, "frame size: %lx (%lx)\n", 
		(ulong)UNW_SP(frame), (ulong)UNW_SP(frame) - bt->hp->esp);

	FREEBUF(frame);
}
Beispiel #8
0
static FILE *open_output_file(const char *dname, const char *fname)
{
	FILE *filp = NULL;
	char *output_file;

	output_file = GETBUF(sizeof(char) * (strlen(dname) + strlen(fname) + 2));
	if (output_file == NULL) {
		error(FATAL,
		      "cannot allocate memory for logfile name '%s%s'\n",
		      dname, fname);
	}

	create_output_dir(dname);
	sprintf(output_file,"%s/%s", dname, fname);

	filp = fopen(output_file, "w");
	if (!filp) {
		error(FATAL, "cannot create log file '%s'\n", output_file);
	}
	FREEBUF(output_file);

	return filp;
}
Beispiel #9
0
static void output_cpu_logs(char *dirname)
{
	int i;
	struct per_cpu_data *pcd;
	size_t n, idx, start, end, len;
	size_t padding;
	char *source, fname[MAX_FNAME + 1];

	/* allocate subbuf memory */
	subbuf = GETBUF(chan.subbuf_size);
	if (!subbuf) {
		error(FATAL, "cannot allocate memory\n");
	}

	for (i = 0; i < kt->cpus; i++) {
		pcd = &per_cpu[i];

		if (pcd->buf.subbufs_produced == 0 && pcd->buf.offset == 0) {
			if (is_global == 1) {
				error(WARNING, "There is no data in the relay buffer.\n");
				break;
			} else {
				error(WARNING, "[cpu:%d]There is no data in the relay buffer.\n", i);
				continue;
			}
		}

		end = pcd->buf.subbufs_produced + 1;
		if (pcd->buf.subbufs_produced >= chan.n_subbufs) {
			start = end - chan.n_subbufs;
		} else {
			start = 0;
		}

		create_output_filename(fname, MAX_FNAME, i);
		fprintf(fp, "--- generating '%s/%s' ---\n", dirname, fname);
		fprintf(fp, "  subbufs ready on relayfs:%ld\n", (long)end);
		fprintf(fp, "  n_subbufs:%ld, read subbuf from:%ld(%ld) "
			"to:%ld(%ld) (offset:0-%ld)\n\n",
			(long)chan.n_subbufs,
			(long)start,
			(long)(start % chan.n_subbufs),
			(long)end-1,
			(long)((end-1) % chan.n_subbufs),
			(long) pcd->buf.offset);
		outfp = open_output_file(dirname, fname);

		for (n = start; n < end; n++) {
			/* read relayfs subbufs and write to log file */
			idx = n % chan.n_subbufs;
			source = pcd->buf.start + idx * chan.subbuf_size;
			if (old_format == 1) {
				readmem((ulong)pcd->buf.padding + sizeof(unsigned) * idx,
					KVADDR, &padding, sizeof(unsigned),
					"padding", FAULT_ON_ERROR);
			} else {
				readmem((ulong)pcd->buf.padding + sizeof(padding) * idx,
					KVADDR, &padding, sizeof(padding),
					"padding", FAULT_ON_ERROR);
			}
			if (n == end - 1) {
				len = pcd->buf.offset;
			} else {
				len = chan.subbuf_size;
			}

			if (old_format == 1) {
				source += sizeof(unsigned int);
				len -= sizeof(unsigned int) + padding;
			} else {
				len -= padding;
			}
			if (len > 0) {
				readmem((ulong)source, KVADDR, subbuf, len,
					"subbuf", FAULT_ON_ERROR);
				if (fwrite(subbuf, len, 1, outfp) != 1) {
					error(FATAL, "cannot write log data\n");
				}
			}
		}
		fclose(outfp);
		outfp = NULL;

		/*
		 * -a option retrieve the old data of subbuffer where the
		 * probe record is written at that time.
		 */
		if (retrieve_all == 1 && start != 0) {
			strncat(fname, ".may_broken", MAX_FNAME);
			fprintf(fp, "--- generating '%s/%s' ---\n", dirname, fname);
			fprintf(fp, "  read subbuf %ld(%ld) (offset:%ld-%ld)\n",
				(long)start-1,
				(long)((start-1) % chan.n_subbufs),
				(long)pcd->buf.offset,
				(long)chan.subbuf_size);
			outfp = open_output_file(dirname, fname);

			idx = (start - 1) % chan.n_subbufs;
			source = pcd->buf.start + idx * chan.subbuf_size +
				 pcd->buf.offset;
			len = chan.subbuf_size - pcd->buf.offset;
			if (len) {
				readmem((ulong)source, KVADDR, subbuf, len,
					"may_broken_subbuf", FAULT_ON_ERROR);
				if (fwrite(subbuf, len, 1, outfp) != 1) {
					error(FATAL,
					      "cannot write log data(may_broken)\n");
				}
			}
			fclose(outfp);
			outfp = NULL;
		}
		if (is_global == 1)
			break;
	}
	if (subbuf) {
		FREEBUF(subbuf);
		subbuf = NULL;
	}
	return;
}
Beispiel #10
0
void
gdb_session_init(void)
{
	struct gnu_request *req;
	int debug_data_pulled_in;

        if (!have_partial_symbols() && !have_full_symbols())
		no_debugging_data(FATAL);

	/*
	 *  Restore the SIGINT and SIGPIPE handlers, which got temporarily
	 *  re-assigned by gdb.  The SIGINT call also initializes GDB's
         *  SIGINT sigaction.
	 */
	SIGACTION(SIGINT, restart, &pc->sigaction, &pc->gdb_sigaction);
	SIGACTION(SIGPIPE, SIG_IGN, &pc->sigaction, NULL);

	if (!(pc->flags & DROP_CORE)) 
		SIGACTION(SIGSEGV, restart, &pc->sigaction, NULL);

	/*
	 *  Set up pointers to gdb variables.
	 */
#if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
	gdb_output_format = &output_format;
	gdb_print_max = &print_max;
	gdb_prettyprint_structs = &prettyprint_structs;
	gdb_prettyprint_arrays = &prettyprint_arrays;
	gdb_repeat_count_threshold = &repeat_count_threshold;
	gdb_stop_print_at_null = &stop_print_at_null;
	gdb_output_radix = &output_radix;
#else
	gdb_output_format = (int *) 
		gdb_user_print_option_address("output_format");
	gdb_print_max = (unsigned int *)
		gdb_user_print_option_address("print_max");
	gdb_prettyprint_structs = (int *)
		gdb_user_print_option_address("prettyprint_structs");
	gdb_prettyprint_arrays = (int *)
		gdb_user_print_option_address("prettyprint_arrays");
	gdb_repeat_count_threshold = (int *)
		gdb_user_print_option_address("repeat_count_threshold");
	gdb_stop_print_at_null = (int *)
		gdb_user_print_option_address("stop_print_at_null");
	gdb_output_radix = (unsigned int *)
		gdb_user_print_option_address("output_radix");
#endif
	/*
         *  If the output radix is set via the --hex or --dec command line
	 *  option, then pc->output_radix will be non-zero; otherwise use 
	 *  the gdb default.  
	 */
	if (pc->output_radix) {  
		*gdb_output_radix = pc->output_radix;
		*gdb_output_format = (*gdb_output_radix == 10) ? 0 : 'x';
	}

	switch (*gdb_output_radix)
	{
	case 10:
	case 16:
		pc->output_radix = *gdb_output_radix;
		break;
	default:
		pc->output_radix = *gdb_output_radix = 10;
		*gdb_output_format = 0;
	}
		
	*gdb_prettyprint_structs = 1;
	*gdb_repeat_count_threshold = 0x7fffffff;
	*gdb_print_max = 256;
#ifdef GDB_5_3
	gdb_disassemble_from_exec = 0;
#endif

	pc->flags |= GDB_INIT;   /* set here so gdb_interface will work */

        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
        req->buf = GETBUF(BUFSIZE);

	/*
	 *  Make sure the namelist has symbolic data.  Later versions of
	 *  gcc may require that debug data be pulled in by printing a 
	 *  static kernel data structure.
  	 */
	debug_data_pulled_in = FALSE;
retry:
	BZERO(req->buf, BUFSIZE);
        req->command = GNU_GET_DATATYPE;
	req->name = XEN_HYPER_MODE() ? "page_info" : "task_struct";
        req->flags = GNU_RETURN_ON_ERROR;
        gdb_interface(req);

        if (req->flags & GNU_COMMAND_FAILED) {
		if (XEN_HYPER_MODE())
			no_debugging_data(WARNING);  /* just bail out */

		if (!debug_data_pulled_in) {
			if (CRASHDEBUG(1))
				error(INFO, 
           "gdb_session_init: pulling in debug data by accessing init_mm.mmap %s\n",
					symbol_exists("sysfs_mount") ?
					"and syfs_mount" : "");
			debug_data_pulled_in = TRUE;
			req->command = GNU_PASS_THROUGH;
			req->flags = GNU_RETURN_ON_ERROR|GNU_NO_READMEM;
			req->name = NULL;
			if (symbol_exists("sysfs_mount"))
				sprintf(req->buf, "print sysfs_mount, init_mm.mmap");
			else
				sprintf(req->buf, "print init_mm.mmap");
			gdb_interface(req);
        		if (!(req->flags & GNU_COMMAND_FAILED)) 
				goto retry;
		}
		no_debugging_data(WARNING);
	}

	if (pc->flags & KERNEL_DEBUG_QUERY) {
		fprintf(fp, "\n%s: %s: contains debugging data\n\n",
			pc->program_name, pc->namelist);
		if (REMOTE())
			remote_exit();
		clean_exit(0);
	}

	/*
	 *  Set up any pre-ordained gdb settings here that can't be
	 *  accessed directly.
	 */

	req->command = GNU_PASS_THROUGH;
	req->name = NULL, req->flags = 0;
	sprintf(req->buf, "set height 0");
	gdb_interface(req);

	req->command = GNU_PASS_THROUGH;
	req->name = NULL, req->flags = 0;
	sprintf(req->buf, "set width 0");
	gdb_interface(req);

       /*
        *  Patch gdb's symbol values with the correct values from either
        *  the System.map or non-debug vmlinux, whichever is in effect.
        */
	if ((pc->flags & SYSMAP) || (kt->flags & (RELOC_SET|RELOC_FORCE)) || 
	    (pc->namelist_debug && !pc->debuginfo_file)) {
		req->command = GNU_PATCH_SYMBOL_VALUES;
        	req->flags = GNU_RETURN_ON_ERROR;
		gdb_interface(req);
        	if (req->flags & GNU_COMMAND_FAILED)
			error(FATAL, "patching of gdb symbol values failed\n");
	} else if (!(pc->flags & SILENT))
		fprintf(fp, "\n");


	FREEBUF(req->buf);
	FREEBUF(req);
}
/*
 *  Transfer the relevant data from the kernel and module unwind_table
 *  structures to the local_unwind_table structures.
 */
static int
populate_local_tables(ulong root, char *buf)
{
	struct list_data list_data, *ld;
	int i, cnt;
	ulong *table_list;
	ulong vaddr;
	struct local_unwind_table *tp;

        ld = &list_data;
        BZERO(ld, sizeof(struct list_data));
        ld->start = root;
        ld->member_offset = OFFSET(unwind_table_link);
	ld->flags = RETURN_ON_LIST_ERROR;
	if (CRASHDEBUG(1))
        	ld->flags |= VERBOSE;

	hq_open();
        cnt = do_list(ld);
	if (cnt == -1) {
		error(WARNING, "UNWIND: failed to gather unwind_table list");
		return 0;
	}
        table_list = (ulong *)GETBUF(cnt * sizeof(ulong));
	cnt = retrieve_list(table_list, cnt);
	hq_close();

	if (!(local_unwind_tables = 
	    malloc(sizeof(struct local_unwind_table) * cnt))) {
		error(WARNING, "cannot malloc unwind_table space (%d tables)\n",
			cnt);
		FREEBUF(table_list);
		return 0;
	}

	for (i = 0; i < cnt; i++, tp++) {

                if (!readmem(table_list[i], KVADDR, buf,
                    SIZE(unwind_table), "unwind_table",
                    RETURN_ON_ERROR|QUIET)) {
			error(WARNING, "cannot read unwind_table\n");
			goto failed;
		}

		tp = &local_unwind_tables[i];

		/*
		 *  Copy the required table info for find_table().
		 */
        	BCOPY(buf + OFFSET(unwind_table_core),
                	(char *)&tp->core.pc, sizeof(ulong)*2);
        	BCOPY(buf + OFFSET(unwind_table_init),
                	(char *)&tp->init.pc, sizeof(ulong)*2);
        	BCOPY(buf + OFFSET(unwind_table_size),
                	(char *)&tp->size, sizeof(ulong));

		/*
		 *  Then read the DWARF CFI data.
		 */
		vaddr = ULONG(buf + OFFSET(unwind_table_address));

		if (!(tp->address = malloc(tp->size))) {
			error(WARNING, "cannot malloc unwind_table space\n");
			goto failed;
			break;
		}
                if (!readmem(vaddr, KVADDR, tp->address,
                    tp->size, "DWARF CFI data", RETURN_ON_ERROR|QUIET)) {
			error(WARNING, "cannot read unwind_table data\n");
			goto failed;
		}
	}

	unwind_tables_cnt = cnt;

	if (CRASHDEBUG(7))
		dump_local_unwind_tables();

failed:

	FREEBUF(table_list);
	return unwind_tables_cnt;
}
/*
 *  Find the appropriate kernel-only "root_table" unwind_table,
 *  and pass it to populate_local_tables() to do the heavy lifting.
 */
static int 
gather_in_memory_unwind_tables(void)
{
	int i, cnt, found;
	struct syment *sp, *root_tables[10];
	char *root_table_buf;
	char buf[BUFSIZE];
	ulong name;

	STRUCT_SIZE_INIT(unwind_table, "unwind_table");
	MEMBER_OFFSET_INIT(unwind_table_core, "unwind_table", "core");
	MEMBER_OFFSET_INIT(unwind_table_init, "unwind_table", "init");
	MEMBER_OFFSET_INIT(unwind_table_address, "unwind_table", "address");
	MEMBER_OFFSET_INIT(unwind_table_size, "unwind_table", "size");
	MEMBER_OFFSET_INIT(unwind_table_link, "unwind_table", "link");
	MEMBER_OFFSET_INIT(unwind_table_name, "unwind_table", "name");

	if (INVALID_SIZE(unwind_table) ||
	    INVALID_MEMBER(unwind_table_core) ||
	    INVALID_MEMBER(unwind_table_init) ||
	    INVALID_MEMBER(unwind_table_address) ||
	    INVALID_MEMBER(unwind_table_size) ||
	    INVALID_MEMBER(unwind_table_link) ||
	    INVALID_MEMBER(unwind_table_name)) {
		if (CRASHDEBUG(1)) 
			error(NOTE, 
	    "unwind_table structure has changed, or does not exist in this kernel\n");
		return 0;
	}

	/*
	 *  Unfortunately there are two kernel root_table symbols.
	 */
	if (!(cnt = get_syment_array("root_table", root_tables, 10)))
		return 0;

	root_table_buf = GETBUF(SIZE(unwind_table));
	for (i = found = 0; i < cnt; i++) {
		sp = root_tables[i];
		if (!readmem(sp->value, KVADDR, root_table_buf,
                    SIZE(unwind_table), "root unwind_table", 
		    RETURN_ON_ERROR|QUIET))
			goto gather_failed;

		name = ULONG(root_table_buf + OFFSET(unwind_table_name));
		if (read_string(name, buf, strlen("kernel")+1) && 
		    STREQ("kernel", buf)) {
			found++;
			if (CRASHDEBUG(1))
				fprintf(fp, "root_table name: %lx [%s]\n", 
					name, buf);
			break;
		}
	}

	if (!found)
		goto gather_failed;

	cnt = populate_local_tables(sp->value, root_table_buf);

	FREEBUF(root_table_buf);
	return cnt;

gather_failed:

	FREEBUF(root_table_buf);
	return 0;
}
int 
dwarf_backtrace(struct bt_info *bt, int level, ulong stacktop)
{
	unsigned long bp, offset;
	struct syment *sp;
	char *name;
	struct unwind_frame_info *frame;
	int is_ehframe = (!st->dwarf_debug_frame_size && st->dwarf_eh_frame_size);

	frame = (struct unwind_frame_info *)GETBUF(sizeof(struct unwind_frame_info));
//	frame->regs.rsp = bt->stkptr;
//	frame->regs.rip = bt->instptr;
	UNW_SP(frame) = bt->stkptr;
	UNW_PC(frame) = bt->instptr;

	/* read rbp from stack for non active tasks */
	if (!(bt->flags & BT_DUMPFILE_SEARCH) && !bt->bptr) {
//		readmem(frame->regs.rsp, KVADDR, &bp,
		readmem(UNW_SP(frame), KVADDR, &bp,
	                sizeof(unsigned long), "reading bp", FAULT_ON_ERROR);
		frame->regs.rbp = bp;  /* fixme for x86 */
	}

	sp = value_search(UNW_PC(frame), &offset);
	if (!sp) {
		if (CRASHDEBUG(1))
		    fprintf(fp, "unwind: cannot find symbol for PC: %lx\n", 
			UNW_PC(frame));
		goto bailout;
	}

	/*
	 * If offset is zero, it means we have crossed over to the next
	 *  function. Recalculate by adjusting the text address
	 */
	if (!offset) {
		sp = value_search(UNW_PC(frame) - 1, &offset);
		if (!sp) {
			if (CRASHDEBUG(1))
				fprintf(fp, 
				    "unwind: cannot find symbol for PC: %lx\n",
					UNW_PC(frame)-1);
			goto bailout;
		}
	}
		


        name = sp->name;
	fprintf(fp, " #%d [%016lx] %s at %016lx \n", level, UNW_SP(frame), name, UNW_PC(frame));

	if (CRASHDEBUG(2))
		fprintf(fp, "    < SP: %lx PC: %lx FP: %lx >\n", UNW_SP(frame), 
			UNW_PC(frame), frame->regs.rbp);

       	while ((UNW_SP(frame) < stacktop)
				&& !unwind(frame, is_ehframe) && UNW_PC(frame)) {
		/* To prevent rip pushed on IRQ stack being reported both
		 * both on the IRQ and process stacks
		 */
		if ((bt->flags & BT_IRQSTACK) && (UNW_SP(frame) >= stacktop - 16))
			break;
               	level++;
		sp = value_search(UNW_PC(frame), &offset);
		if (!sp) {
			if (CRASHDEBUG(1))
				fprintf(fp, 
				    "unwind: cannot find symbol for PC: %lx\n",
					UNW_PC(frame));
			break;
		}

		/*
		 * If offset is zero, it means we have crossed over to the next
		 *  function. Recalculate by adjusting the text address
		 */
		if (!offset) {
			sp = value_search(UNW_PC(frame) - 1, &offset);
			if (!sp) {
				if (CRASHDEBUG(1))
					fprintf(fp,
					    "unwind: cannot find symbol for PC: %lx\n",
						UNW_PC(frame)-1);
				goto bailout;
			}
		}
	        name = sp->name;
		fprintf(fp, "%s#%d [%016lx] %s at %016lx \n", level < 10 ? " " : "",
			level, UNW_SP(frame), name, UNW_PC(frame));

		if (CRASHDEBUG(2))
			fprintf(fp, "    < SP: %lx PC: %lx FP: %lx >\n", UNW_SP(frame), 
				UNW_PC(frame), frame->regs.rbp);
       	}

bailout:
	FREEBUF(frame);
	return ++level;
}
Beispiel #14
0
static void
init_ram_segments(void)
{
	int i, errflag;
        FILE *iomem; 
	char buf[BUFSIZE], *p1, *p2;
	physaddr_t start, end;

	if ((iomem = fopen("/proc/iomem", "r")) == NULL)
		goto fail_iomem;

	while (fgets(buf, BUFSIZE, iomem)) {
		if (strstr(buf, "System RAM")) {
			console(buf);
			nr_segments++;
		}
	}
	if (!nr_segments)
		goto fail_iomem;

	ram_segments = (struct ram_segments *)
		GETBUF(sizeof(struct ram_segments) * nr_segments);

	rewind(iomem);
	i = 0;
	while (fgets(buf, BUFSIZE, iomem)) {
		if (strstr(buf, "System RAM")) {
			if (!(p1 = strstr(buf, ":")))
				goto fail_iomem;
			*p1 = NULLCHAR;
			clean_line(buf);
			if (strstr(buf, " "))
				goto fail_iomem;
			p1 = buf;
			if (!(p2 = strstr(buf, "-")))
				goto fail_iomem;
			*p2 = NULLCHAR;
			p2++;
			errflag = 0;
			start = htoll(p1, RETURN_ON_ERROR|QUIET, &errflag);
			end = htoll(p2, RETURN_ON_ERROR|QUIET, &errflag);
			if (errflag)
				goto fail_iomem;
			ram_segments[i].start = PHYSPAGEBASE(start);
			if (PAGEOFFSET(start))
				ram_segments[i].start += PAGESIZE();
			ram_segments[i].end = PHYSPAGEBASE(end);
			if (PAGEOFFSET(end) == (PAGESIZE()-1))
				ram_segments[i].end += PAGESIZE();
			console("ram_segments[%d]: %016llx %016llx [%s-%s]\n", i,
				(ulonglong)ram_segments[i].start, 
				(ulonglong)ram_segments[i].end, p1, p2);
			i++;
		}
	}

	fclose(iomem);
	return;

fail_iomem:
	fclose(iomem);
	nr_segments = 0;
	if (ram_segments)
		FREEBUF(ram_segments);

	return; 
}
Beispiel #15
0
/* 
 *  Just pass in an unused filename.
 */
void
cmd_snap(void)
{
        int c, fd, n;
	physaddr_t paddr;
	size_t offset;
	char *buf;
	char *filename;
	struct node_table *nt;
	int type;
	char *elf_header;
	Elf64_Phdr *load;
	int load_index;

	if (!supported)
		error(FATAL, "command not supported on the %s architecture\n",
			pc->machine_type);

	filename = NULL;
	buf = GETBUF(PAGESIZE()); 
	type = KDUMP_ELF64;

        while ((c = getopt(argcnt, args, "n")) != EOF) {
                switch(c)
                {
		case 'n':
			if (machine_type("X86_64"))
				option_not_supported('n');
			else
				type = NETDUMP_ELF64;
			break;
                default:
                        argerrs++;
                        break;
                }
        }

        if (argerrs || !args[optind])
                cmd_usage(pc->curcmd, SYNOPSIS);

	while (args[optind]) {
		if (filename)
                	cmd_usage(pc->curcmd, SYNOPSIS);

		if (file_exists(args[optind], NULL))
			error(FATAL, "%s: file already exists\n", args[optind]);
		else if ((fd = open(args[optind], O_RDWR|O_CREAT, 0644)) < 0)
			error(FATAL, args[optind]);

		filename = args[optind];
		optind++;
	}

	if (!filename)
                cmd_usage(pc->curcmd, SYNOPSIS);

	init_ram_segments();

	if (!(elf_header = generate_elf_header(type, fd, filename)))
		error(FATAL, "cannot generate ELF header\n");

	load = (Elf64_Phdr *)(elf_header + sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr));
	load_index = machine_type("X86_64") || machine_type("IA64") ? 1 : 0;

	for (n = 0; n < vt->numnodes; n++) {
		nt = &vt->node_table[n];
		paddr = nt->start_paddr;
		offset = load[load_index + n].p_offset;

		for (c = 0; c < nt->size; c++, paddr += PAGESIZE()) {
			if (!verify_paddr(paddr))
				continue;
			if (!readmem(paddr, PHYSADDR, &buf[0], PAGESIZE(), 
			    "memory page", QUIET|RETURN_ON_ERROR))
				continue;

			lseek(fd, (off_t)(paddr + offset - nt->start_paddr), SEEK_SET);
			if (write(fd, &buf[0], PAGESIZE()) != PAGESIZE())
				error(FATAL, "write to dumpfile failed\n");

			if (!print_progress(filename, BTOP(paddr)))
				return;
		}
	}

        fprintf(stderr, "\r%s: [100%%] ", filename);
	fprintf(fp, "\n");
	sprintf(buf, "/bin/ls -l %s\n", filename);
	system(buf);

	FREEBUF(elf_header);
	FREEBUF(buf);
}
Beispiel #16
0
char *
generate_elf_header(int type, int fd, char *filename)
{
	int i, n;
	char *buffer, *ptr;
	Elf64_Ehdr *elf;
	Elf64_Phdr *notes;
	Elf64_Phdr *load;
	size_t offset, len, l_offset;
	size_t data_offset;
	struct elf_prpsinfo_64 prpsinfo;
	union prstatus prstatus;
	int prstatus_len;
	ushort e_machine;
	int num_segments;
	struct node_table *nt;
	struct SNAP_info {
		ulonglong task_struct;
		ulonglong arch_data1;
		ulonglong arch_data2;
	} SNAP_info;

	num_segments = vt->numnodes;

	if (machine_type("X86_64")) {
		e_machine = EM_X86_64;
		prstatus_len = sizeof(prstatus.x86_64);
		num_segments += 1;  /* mapped kernel section for phys_base */
	} else if (machine_type("X86")) {
		e_machine = EM_386;
		prstatus_len = sizeof(prstatus.x86);
	} else if (machine_type("IA64")) {
		e_machine = EM_IA_64;
		prstatus_len = sizeof(prstatus.ia64);
		num_segments += 1;  /* mapped kernel section for phys_start */
	} else if (machine_type("PPC64")) {
		e_machine = EM_PPC64;
		prstatus_len = sizeof(prstatus.ppc64);
	} else if (machine_type("ARM64")) {
		e_machine = EM_AARCH64;
		prstatus_len = sizeof(prstatus.arm64);
	} else
		return NULL;

	/* should be enought for the notes + roundup + two blocks */
	buffer = (char *)GETBUF(sizeof(Elf64_Ehdr) +
		num_segments * sizeof(Elf64_Phdr) + PAGESIZE() * 2);
	offset = 0;
	ptr = buffer;

	/* Elf header */
	elf = (Elf64_Ehdr *)ptr;
	memcpy(elf->e_ident, ELFMAG, SELFMAG);
	elf->e_ident[EI_CLASS] = ELFCLASS64;
#if __BYTE_ORDER == __BIG_ENDIAN
	elf->e_ident[EI_DATA] = ELFDATA2MSB;
#else
	elf->e_ident[EI_DATA] = ELFDATA2LSB;
#endif
	elf->e_ident[EI_VERSION] = EV_CURRENT;
	elf->e_ident[EI_OSABI] = ELFOSABI_SYSV;
	elf->e_ident[EI_ABIVERSION] = 0;
	memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);

	elf->e_type = ET_CORE;
	elf->e_machine = e_machine;
	elf->e_version = EV_CURRENT;
	elf->e_entry = 0;
	elf->e_phoff = sizeof(Elf64_Ehdr);
	elf->e_shoff = 0;
	elf->e_flags = 0;
	elf->e_ehsize = sizeof(Elf64_Ehdr);
	elf->e_phentsize = sizeof(Elf64_Phdr);
	elf->e_phnum = 1 + num_segments;
	elf->e_shentsize = 0;
	elf->e_shnum = 0;
	elf->e_shstrndx = 0;

	offset += sizeof(Elf64_Ehdr);
	ptr += sizeof(Elf64_Ehdr);

	/* PT_NOTE */
	notes = (Elf64_Phdr *)ptr;
	notes->p_type = PT_NOTE;
	notes->p_offset = 0; /* TO BE FILLED IN */
	notes->p_vaddr = 0;
	notes->p_paddr = 0;
	notes->p_filesz = 0; /* TO BE FILLED IN */
	notes->p_memsz = 0;
	notes->p_flags = 0;
	notes->p_align = 0;

	offset += sizeof(Elf64_Phdr);
	ptr += sizeof(Elf64_Phdr);

	/* PT_LOAD */
	load = (Elf64_Phdr *)ptr;
	for (i = n = 0; i < num_segments; i++) {
		load[i].p_type = PT_LOAD;
		load[i].p_offset = 0; /* TO BE FILLED IN */

		switch (e_machine)
		{
		case EM_X86_64:
			nt = &vt->node_table[n];
			if (i == 0) {
#ifdef X86_64
				load[i].p_vaddr = __START_KERNEL_map;
				load[i].p_paddr = machdep->machspec->phys_base;
#endif
				load[i].p_filesz = 0;
				load[i].p_memsz = load[i].p_filesz;
			} else {
				load[i].p_vaddr = PTOV(nt->start_paddr);
				load[i].p_paddr = nt->start_paddr;
				load[i].p_filesz = nt->size * PAGESIZE();
				load[i].p_memsz = load[i].p_filesz;
				n++;
			}
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = 0;
			break;

		case EM_386:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = 0;
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_IA_64:
			nt = &vt->node_table[n];
			if (i == 0) {
#ifdef IA64
				load[i].p_vaddr = machdep->machspec->kernel_start;
				load[i].p_paddr = machdep->machspec->phys_start;
#endif
				load[i].p_filesz = 0;
				load[i].p_memsz = load[i].p_filesz;
			} else {
				load[i].p_vaddr = PTOV(nt->start_paddr);
				load[i].p_paddr = nt->start_paddr;
				load[i].p_filesz = nt->size * PAGESIZE();
 				load[i].p_memsz = load[i].p_filesz;
				n++;
			}
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_PPC64:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = PTOV(nt->start_paddr);
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_AARCH64:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = PTOV(nt->start_paddr);
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;
		}

//		l_offset += load[i].p_filesz;
		offset += sizeof(Elf64_Phdr);
		ptr += sizeof(Elf64_Phdr);
	}
	notes->p_offset = offset;

	/* NT_PRSTATUS note */
	memset(&prstatus, 0, sizeof(prstatus));
	len = dump_elf_note(ptr, NT_PRSTATUS, "CORE",
		(char *)&prstatus, prstatus_len);
	offset += len;
	ptr += len;
	notes->p_filesz += len;

	/* NT_PRPSINFO note */
	memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo_64));
	prpsinfo.pr_state = 0;
	prpsinfo.pr_sname = 'R';
	prpsinfo.pr_zomb = 0;
	strcpy(prpsinfo.pr_fname, "vmlinux");

	len = dump_elf_note(ptr, NT_PRPSINFO, "CORE",
		(char *)&prpsinfo, sizeof(prpsinfo));

	offset += len;
	ptr += len;
	notes->p_filesz += len;

  	/* NT_TASKSTRUCT note */
	SNAP_info.task_struct = CURRENT_TASK();
#ifdef X86_64
	SNAP_info.arch_data1 = kt->relocate;
	SNAP_info.arch_data2 = 0;
#elif ARM64
	SNAP_info.arch_data1 = machdep->machspec->kimage_voffset;
	SNAP_info.arch_data2 = (machdep->machspec->VA_BITS_ACTUAL << 32) | 
				machdep->machspec->CONFIG_ARM64_VA_BITS;
#else
	SNAP_info.arch_data1 = 0;
	SNAP_info.arch_data2 = 0;
#endif
	len = dump_elf_note (ptr, NT_TASKSTRUCT, "SNAP",
		(char *)&SNAP_info, sizeof(struct SNAP_info));
	offset += len;
	ptr += len;
	notes->p_filesz += len;

	if (type == NETDUMP_ELF64)
		offset = roundup (offset, PAGESIZE());

	l_offset = offset;
	for (i = 0; i < num_segments; i++) {
		load[i].p_offset = l_offset;
		l_offset += load[i].p_filesz;
	}
	data_offset = offset;

	while (offset > 0) {
		len = write(fd, buffer + (data_offset - offset), offset);
		if (len < 0) {
			perror(filename);
			FREEBUF(buffer);
			return NULL;
		}

		offset -= len;
	}

	return buffer;
}