17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57b9b3bf3Sedp  * Common Development and Distribution License (the "License").
67b9b3bf3Sedp  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227b9b3bf3Sedp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24399ca3a7SJohn Levon  *
25399ca3a7SJohn Levon  * Copyright 2018 Joyent, Inc.
26a48fdbefSBryan Cantrill  * Copyright 2024 Oxide Computer Company
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Raw File Target
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * The raw file target is invoked whenever a file of unrecognizable type is
337c478bd9Sstevel@tonic-gate  * specified on the command line, or when raw file examination is forced using
347c478bd9Sstevel@tonic-gate  * the -f option.  If one file is specified, that file will be opened as the
357c478bd9Sstevel@tonic-gate  * "object" file.  If two files are specified, the second one will be opened
367c478bd9Sstevel@tonic-gate  * as the "core" file.  Each file is opened using the fdio backend, which
377c478bd9Sstevel@tonic-gate  * internally supports both byte-oriented i/o and block-oriented i/o as needed.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
417c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h>
427c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
437c478bd9Sstevel@tonic-gate #include <mdb/mdb_conf.h>
447c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
457c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
467c478bd9Sstevel@tonic-gate 
471a7c1b72Smws #include <sys/dtrace.h>
487c478bd9Sstevel@tonic-gate #include <fcntl.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate typedef struct rf_data {
517c478bd9Sstevel@tonic-gate 	mdb_io_t *r_object_fio;
527c478bd9Sstevel@tonic-gate 	mdb_io_t *r_core_fio;
537c478bd9Sstevel@tonic-gate } rf_data_t;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #define	RF_OBJECT(p)	(((rf_data_t *)(p))->r_object_fio)
567c478bd9Sstevel@tonic-gate #define	RF_CORE(p)	(((rf_data_t *)(p))->r_core_fio)
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static void
rf_data_destroy(rf_data_t * rf)597c478bd9Sstevel@tonic-gate rf_data_destroy(rf_data_t *rf)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	if (rf->r_object_fio != NULL)
627c478bd9Sstevel@tonic-gate 		mdb_io_destroy(rf->r_object_fio);
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	if (rf->r_core_fio != NULL)
657c478bd9Sstevel@tonic-gate 		mdb_io_destroy(rf->r_core_fio);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	mdb_free(rf, sizeof (rf_data_t));
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static int
rf_setflags(mdb_tgt_t * t,int flags)717c478bd9Sstevel@tonic-gate rf_setflags(mdb_tgt_t *t, int flags)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate 	if ((flags ^ t->t_flags) & MDB_TGT_F_RDWR) {
747c478bd9Sstevel@tonic-gate 		uint_t otflags = t->t_flags;
757c478bd9Sstevel@tonic-gate 		rf_data_t *orf = t->t_data;
767c478bd9Sstevel@tonic-gate 		const char *argv[2];
777c478bd9Sstevel@tonic-gate 		int argc = 0;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 		if (orf->r_object_fio != NULL)
807c478bd9Sstevel@tonic-gate 			argv[argc++] = IOP_NAME(orf->r_object_fio);
817c478bd9Sstevel@tonic-gate 		if (orf->r_core_fio != NULL)
827c478bd9Sstevel@tonic-gate 			argv[argc++] = IOP_NAME(orf->r_core_fio);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 		t->t_flags = (t->t_flags & ~MDB_TGT_F_RDWR) |
857c478bd9Sstevel@tonic-gate 		    (flags & MDB_TGT_F_RDWR);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 		if (mdb_rawfile_tgt_create(t, argc, argv) == -1) {
887c478bd9Sstevel@tonic-gate 			t->t_flags = otflags;
897c478bd9Sstevel@tonic-gate 			t->t_data = orf;
907c478bd9Sstevel@tonic-gate 			return (-1);
917c478bd9Sstevel@tonic-gate 		}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 		rf_data_destroy(orf);
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	return (0);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static void
rf_destroy(mdb_tgt_t * t)1007c478bd9Sstevel@tonic-gate rf_destroy(mdb_tgt_t *t)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	rf_data_destroy(t->t_data);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1067c478bd9Sstevel@tonic-gate static const char *
rf_name(mdb_tgt_t * t)1077c478bd9Sstevel@tonic-gate rf_name(mdb_tgt_t *t)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	return ("raw");
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate static ssize_t
rf_read(mdb_io_t * io,void * buf,size_t nbytes,uint64_t addr)1137c478bd9Sstevel@tonic-gate rf_read(mdb_io_t *io, void *buf, size_t nbytes, uint64_t addr)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	ssize_t rbytes;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	if (io == NULL)
1187c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	if (IOP_SEEK(io, addr, SEEK_SET) == -1)
1217c478bd9Sstevel@tonic-gate 		return (-1); /* errno is set for us */
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if ((rbytes = IOP_READ(io, buf, nbytes)) == 0)
1247c478bd9Sstevel@tonic-gate 		(void) set_errno(EMDB_EOF);
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	return (rbytes);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static ssize_t
rf_write(mdb_io_t * io,const void * buf,size_t nbytes,uint64_t addr)1307c478bd9Sstevel@tonic-gate rf_write(mdb_io_t *io, const void *buf, size_t nbytes, uint64_t addr)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	if (io == NULL)
1337c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (IOP_SEEK(io, addr, SEEK_SET) == -1)
1367c478bd9Sstevel@tonic-gate 		return (-1); /* errno is set for us */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	return (IOP_WRITE(io, buf, nbytes));
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static ssize_t
rf_aread(mdb_tgt_t * t,mdb_tgt_as_t as,void * buf,size_t len,mdb_tgt_addr_t addr)1427c478bd9Sstevel@tonic-gate rf_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf,
1437c478bd9Sstevel@tonic-gate     size_t len, mdb_tgt_addr_t addr)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)as) {
1467c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_VIRT:
1479c3024a3SHans Rosenfeld 	case (uintptr_t)MDB_TGT_AS_VIRT_I:
1489c3024a3SHans Rosenfeld 	case (uintptr_t)MDB_TGT_AS_VIRT_S:
1497c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_PHYS:
1507c478bd9Sstevel@tonic-gate 		if (RF_CORE(t->t_data) != NULL)
1517c478bd9Sstevel@tonic-gate 			return (rf_read(RF_CORE(t->t_data), buf, len, addr));
1527c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
1537c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_FILE:
1547c478bd9Sstevel@tonic-gate 		return (rf_read(RF_OBJECT(t->t_data), buf, len, addr));
1557c478bd9Sstevel@tonic-gate 	default:
1567c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate static ssize_t
rf_awrite(mdb_tgt_t * t,mdb_tgt_as_t as,const void * buf,size_t len,mdb_tgt_addr_t addr)1617c478bd9Sstevel@tonic-gate rf_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf,
1627c478bd9Sstevel@tonic-gate     size_t len, mdb_tgt_addr_t addr)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)as) {
1657c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_VIRT:
1669c3024a3SHans Rosenfeld 	case (uintptr_t)MDB_TGT_AS_VIRT_I:
1679c3024a3SHans Rosenfeld 	case (uintptr_t)MDB_TGT_AS_VIRT_S:
1687c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_PHYS:
1697c478bd9Sstevel@tonic-gate 		if (RF_CORE(t->t_data) != NULL)
1707c478bd9Sstevel@tonic-gate 			return (rf_write(RF_CORE(t->t_data), buf, len, addr));
1717c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
1727c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_FILE:
1737c478bd9Sstevel@tonic-gate 		return (rf_write(RF_OBJECT(t->t_data), buf, len, addr));
1747c478bd9Sstevel@tonic-gate 	default:
1757c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate static ssize_t
rf_vread(mdb_tgt_t * t,void * buf,size_t nbytes,uintptr_t addr)1807c478bd9Sstevel@tonic-gate rf_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate 	if (RF_CORE(t->t_data) != NULL)
1837c478bd9Sstevel@tonic-gate 		return (rf_read(RF_CORE(t->t_data), buf, nbytes, addr));
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	return (rf_read(RF_OBJECT(t->t_data), buf, nbytes, addr));
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate static ssize_t
rf_vwrite(mdb_tgt_t * t,const void * buf,size_t nbytes,uintptr_t addr)1897c478bd9Sstevel@tonic-gate rf_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 	if (RF_CORE(t->t_data) != NULL)
1927c478bd9Sstevel@tonic-gate 		return (rf_write(RF_CORE(t->t_data), buf, nbytes, addr));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	return (rf_write(RF_OBJECT(t->t_data), buf, nbytes, addr));
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate static ssize_t
rf_pread(mdb_tgt_t * t,void * buf,size_t nbytes,physaddr_t addr)1987c478bd9Sstevel@tonic-gate rf_pread(mdb_tgt_t *t, void *buf, size_t nbytes, physaddr_t addr)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	if (RF_CORE(t->t_data) != NULL)
2017c478bd9Sstevel@tonic-gate 		return (rf_read(RF_CORE(t->t_data), buf, nbytes, addr));
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	return (rf_read(RF_OBJECT(t->t_data), buf, nbytes, addr));
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate static ssize_t
rf_pwrite(mdb_tgt_t * t,const void * buf,size_t nbytes,physaddr_t addr)2077c478bd9Sstevel@tonic-gate rf_pwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, physaddr_t addr)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	if (RF_CORE(t->t_data) != NULL)
2107c478bd9Sstevel@tonic-gate 		return (rf_write(RF_CORE(t->t_data), buf, nbytes, addr));
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	return (rf_write(RF_OBJECT(t->t_data), buf, nbytes, addr));
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate static ssize_t
rf_fread(mdb_tgt_t * t,void * buf,size_t nbytes,uintptr_t addr)2167c478bd9Sstevel@tonic-gate rf_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate 	return (rf_read(RF_OBJECT(t->t_data), buf, nbytes, addr));
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate static ssize_t
rf_fwrite(mdb_tgt_t * t,const void * buf,size_t nbytes,uintptr_t addr)2227c478bd9Sstevel@tonic-gate rf_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	return (rf_write(RF_OBJECT(t->t_data), buf, nbytes, addr));
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate static int
rf_print_map(mdb_io_t * io,const char * type,int tflags,mdb_tgt_map_f * func,void * private)2297c478bd9Sstevel@tonic-gate rf_print_map(mdb_io_t *io, const char *type, int tflags,
2307c478bd9Sstevel@tonic-gate     mdb_tgt_map_f *func, void *private)
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 	mdb_map_t map;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	(void) mdb_iob_snprintf(map.map_name, MDB_TGT_MAPSZ,
2357c478bd9Sstevel@tonic-gate 	    "%s (%s)", IOP_NAME(io), type);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	map.map_base = 0;
2387c478bd9Sstevel@tonic-gate 	map.map_size = IOP_SEEK(io, 0, SEEK_END);
2397c478bd9Sstevel@tonic-gate 	map.map_flags = MDB_TGT_MAP_R;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if (tflags & MDB_TGT_F_RDWR)
2427c478bd9Sstevel@tonic-gate 		map.map_flags |= MDB_TGT_MAP_W;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	return (func(private, &map, map.map_name));
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate static int
rf_mapping_iter(mdb_tgt_t * t,mdb_tgt_map_f * func,void * private)2487c478bd9Sstevel@tonic-gate rf_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	rf_data_t *rf = t->t_data;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	if (rf->r_object_fio != NULL && rf_print_map(rf->r_object_fio,
2537c478bd9Sstevel@tonic-gate 	    "object file", t->t_flags, func, private) != 0)
2547c478bd9Sstevel@tonic-gate 		return (0);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if (rf->r_core_fio != NULL && rf_print_map(rf->r_core_fio,
2577c478bd9Sstevel@tonic-gate 	    "core file", t->t_flags, func, private) != 0)
2587c478bd9Sstevel@tonic-gate 		return (0);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	return (0);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2647c478bd9Sstevel@tonic-gate static int
rf_status(mdb_tgt_t * t,mdb_tgt_status_t * tsp)2657c478bd9Sstevel@tonic-gate rf_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate 	bzero(tsp, sizeof (mdb_tgt_status_t));
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	if (RF_CORE(t->t_data) != NULL)
2707c478bd9Sstevel@tonic-gate 		tsp->st_state = MDB_TGT_DEAD;
2717c478bd9Sstevel@tonic-gate 	else
2727c478bd9Sstevel@tonic-gate 		tsp->st_state = MDB_TGT_IDLE;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	return (0);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2787c478bd9Sstevel@tonic-gate static int
rf_status_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2797c478bd9Sstevel@tonic-gate rf_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 	rf_data_t *rf = mdb.m_target->t_data;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	if (rf->r_object_fio != NULL) {
2847c478bd9Sstevel@tonic-gate 		mdb_printf("debugging file '%s' (object file)",
2857c478bd9Sstevel@tonic-gate 		    IOP_NAME(rf->r_object_fio));
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		if (rf->r_core_fio != NULL) {
2887c478bd9Sstevel@tonic-gate 			mdb_printf(" and file '%s' (core file)",
2897c478bd9Sstevel@tonic-gate 			    IOP_NAME(rf->r_core_fio));
2907c478bd9Sstevel@tonic-gate 		}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
2937c478bd9Sstevel@tonic-gate 	} else {
2947c478bd9Sstevel@tonic-gate 		mdb_printf("debugging empty target\n");
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate static const mdb_dcmd_t rf_dcmds[] = {
3017c478bd9Sstevel@tonic-gate 	{ "status", NULL, "print summary of current target", rf_status_dcmd },
3027c478bd9Sstevel@tonic-gate 	{ NULL }
3037c478bd9Sstevel@tonic-gate };
3047c478bd9Sstevel@tonic-gate 
3051a7c1b72Smws static const struct rf_magic {
3061a7c1b72Smws 	const char *rfm_str;
3071a7c1b72Smws 	size_t rfm_len;
3081a7c1b72Smws 	const char *rfm_mod;
3091a7c1b72Smws } rf_magic[] = {
3101a7c1b72Smws 	{ DOF_MAG_STRING, DOF_MAG_STRLEN, "dof" },
3111a7c1b72Smws 	{ NULL, 0, NULL }
3121a7c1b72Smws };
3131a7c1b72Smws 
3147c478bd9Sstevel@tonic-gate static void
rf_activate(mdb_tgt_t * t)3157c478bd9Sstevel@tonic-gate rf_activate(mdb_tgt_t *t)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	rf_data_t *rf = t->t_data;
3181a7c1b72Smws 	const struct rf_magic *m;
3197c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
3207c478bd9Sstevel@tonic-gate 	off64_t size;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_register_dcmds(t, &rf_dcmds[0], MDB_MOD_FORCE);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	/*
3257c478bd9Sstevel@tonic-gate 	 * We set the legacy adb variable 'd' to be the size of the file (data
3261a7c1b72Smws 	 * segment).  To get this value, we call seek() on the underlying fdio.
3277c478bd9Sstevel@tonic-gate 	 */
3287c478bd9Sstevel@tonic-gate 	if (rf->r_object_fio != NULL) {
3297c478bd9Sstevel@tonic-gate 		size = IOP_SEEK(rf->r_object_fio, 0, SEEK_END);
3307c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&mdb.m_nv, "d")) != NULL)
3317c478bd9Sstevel@tonic-gate 			mdb_nv_set_value(v, size);
3327c478bd9Sstevel@tonic-gate 	}
3331a7c1b72Smws 
3341a7c1b72Smws 	/*
3351a7c1b72Smws 	 * Load any debugging support modules that match the file type, as
3361a7c1b72Smws 	 * determined by our poor man's /etc/magic.  If many clients need
3371a7c1b72Smws 	 * to use this feature, rf_magic[] should be computed dynamically.
3381a7c1b72Smws 	 */
3391a7c1b72Smws 	for (m = rf_magic; m->rfm_str != NULL; m++) {
3401a7c1b72Smws 		char *buf = mdb_alloc(m->rfm_len, UM_SLEEP);
3411a7c1b72Smws 
3421a7c1b72Smws 		if (mdb_tgt_vread(t, buf, m->rfm_len, 0) == m->rfm_len &&
3431a7c1b72Smws 		    bcmp(buf, m->rfm_str, m->rfm_len) == 0) {
3441a7c1b72Smws 			(void) mdb_module_load(m->rfm_mod,
3451a7c1b72Smws 			    MDB_MOD_LOCAL | MDB_MOD_SILENT);
3461a7c1b72Smws 		}
3471a7c1b72Smws 
3481a7c1b72Smws 		mdb_free(buf, m->rfm_len);
3491a7c1b72Smws 	}
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate static void
rf_deactivate(mdb_tgt_t * t)3537c478bd9Sstevel@tonic-gate rf_deactivate(mdb_tgt_t *t)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate 	const mdb_dcmd_t *dcp;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	for (dcp = &rf_dcmds[0]; dcp->dc_name != NULL; dcp++) {
3587c478bd9Sstevel@tonic-gate 		if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1)
3597c478bd9Sstevel@tonic-gate 			warn("failed to remove dcmd %s", dcp->dc_name);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate static const mdb_tgt_ops_t rawfile_ops = {
364*0c1b95beSRichard Lowe 	.t_setflags = rf_setflags,
365*0c1b95beSRichard Lowe 	.t_setcontext = (int (*)())(uintptr_t)mdb_tgt_notsup,
366*0c1b95beSRichard Lowe 	.t_activate = rf_activate,
367*0c1b95beSRichard Lowe 	.t_deactivate = rf_deactivate,
368*0c1b95beSRichard Lowe 	.t_periodic = (void (*)())(uintptr_t)mdb_tgt_nop,
369*0c1b95beSRichard Lowe 	.t_destroy = rf_destroy,
370*0c1b95beSRichard Lowe 	.t_name = rf_name,
371*0c1b95beSRichard Lowe 	.t_isa = (const char *(*)())mdb_conf_isa,
372*0c1b95beSRichard Lowe 	.t_platform = (const char *(*)())mdb_conf_platform,
373*0c1b95beSRichard Lowe 	.t_uname = (int (*)())(uintptr_t)mdb_tgt_notsup,
374*0c1b95beSRichard Lowe 	.t_dmodel = (int (*)())(uintptr_t)mdb_tgt_notsup,
375*0c1b95beSRichard Lowe 	.t_aread = rf_aread,
376*0c1b95beSRichard Lowe 	.t_awrite = rf_awrite,
377*0c1b95beSRichard Lowe 	.t_vread = rf_vread,
378*0c1b95beSRichard Lowe 	.t_vwrite = rf_vwrite,
379*0c1b95beSRichard Lowe 	.t_pread = rf_pread,
380*0c1b95beSRichard Lowe 	.t_pwrite = rf_pwrite,
381*0c1b95beSRichard Lowe 	.t_fread = rf_fread,
382*0c1b95beSRichard Lowe 	.t_fwrite = rf_fwrite,
383*0c1b95beSRichard Lowe 	.t_ioread = (ssize_t (*)())mdb_tgt_notsup,
384*0c1b95beSRichard Lowe 	.t_iowrite = (ssize_t (*)())mdb_tgt_notsup,
385*0c1b95beSRichard Lowe 	.t_vtop = (int (*)())(uintptr_t)mdb_tgt_notsup,
386*0c1b95beSRichard Lowe 	.t_lookup_by_name = (int (*)())(uintptr_t)mdb_tgt_notsup,
387*0c1b95beSRichard Lowe 	.t_lookup_by_addr = (int (*)())(uintptr_t)mdb_tgt_notsup,
388*0c1b95beSRichard Lowe 	.t_symbol_iter = (int (*)())(uintptr_t)mdb_tgt_notsup,
389*0c1b95beSRichard Lowe 	.t_mapping_iter = rf_mapping_iter,
390*0c1b95beSRichard Lowe 	.t_object_iter = rf_mapping_iter,
391*0c1b95beSRichard Lowe 	.t_addr_to_map = (const mdb_map_t *(*)())mdb_tgt_null,
392*0c1b95beSRichard Lowe 	.t_name_to_map = (const mdb_map_t *(*)())mdb_tgt_null,
393*0c1b95beSRichard Lowe 	.t_addr_to_ctf = (struct ctf_file *(*)())mdb_tgt_null,
394*0c1b95beSRichard Lowe 	.t_name_to_ctf = (struct ctf_file *(*)())mdb_tgt_null,
395*0c1b95beSRichard Lowe 	.t_status = rf_status,
396*0c1b95beSRichard Lowe 	.t_run = (int (*)())(uintptr_t)mdb_tgt_notsup,
397*0c1b95beSRichard Lowe 	.t_step = (int (*)())(uintptr_t)mdb_tgt_notsup,
398*0c1b95beSRichard Lowe 	.t_step_out = (int (*)())(uintptr_t)mdb_tgt_notsup,
399*0c1b95beSRichard Lowe 	.t_next = (int (*)())(uintptr_t)mdb_tgt_notsup,
400*0c1b95beSRichard Lowe 	.t_cont = (int (*)())(uintptr_t)mdb_tgt_notsup,
401*0c1b95beSRichard Lowe 	.t_signal = (int (*)())(uintptr_t)mdb_tgt_notsup,
402*0c1b95beSRichard Lowe 	.t_add_vbrkpt = (int (*)())(uintptr_t)mdb_tgt_null,
403*0c1b95beSRichard Lowe 	.t_add_sbrkpt = (int (*)())(uintptr_t)mdb_tgt_null,
404*0c1b95beSRichard Lowe 	.t_add_pwapt = (int (*)())(uintptr_t)mdb_tgt_null,
405*0c1b95beSRichard Lowe 	.t_add_vwapt = (int (*)())(uintptr_t)mdb_tgt_null,
406*0c1b95beSRichard Lowe 	.t_add_iowapt = (int (*)())(uintptr_t)mdb_tgt_null,
407*0c1b95beSRichard Lowe 	.t_add_sysenter = (int (*)())(uintptr_t)mdb_tgt_null,
408*0c1b95beSRichard Lowe 	.t_add_sysexit = (int (*)())(uintptr_t)mdb_tgt_null,
409*0c1b95beSRichard Lowe 	.t_add_signal = (int (*)())(uintptr_t)mdb_tgt_null,
410*0c1b95beSRichard Lowe 	.t_add_fault = (int (*)())(uintptr_t)mdb_tgt_null,
411*0c1b95beSRichard Lowe 	.t_getareg = (int (*)())(uintptr_t)mdb_tgt_notsup,
412*0c1b95beSRichard Lowe 	.t_putareg = (int (*)())(uintptr_t)mdb_tgt_notsup,
413*0c1b95beSRichard Lowe 	.t_stack_iter = (int (*)())(uintptr_t)mdb_tgt_notsup,
414*0c1b95beSRichard Lowe 	.t_auxv = (int (*)())(uintptr_t)mdb_tgt_notsup,
415*0c1b95beSRichard Lowe 	.t_thread_name = (int (*)())(uintptr_t)mdb_tgt_notsup,
4167c478bd9Sstevel@tonic-gate };
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate int
mdb_rawfile_tgt_create(mdb_tgt_t * t,int argc,const char * argv[])4197c478bd9Sstevel@tonic-gate mdb_rawfile_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	mdb_io_t *io[2] = { NULL, NULL };
4227c478bd9Sstevel@tonic-gate 	rf_data_t *rf;
4237c478bd9Sstevel@tonic-gate 	int oflags, i;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	if (argc > 2)
4267c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	rf = mdb_zalloc(sizeof (rf_data_t), UM_SLEEP);
4297c478bd9Sstevel@tonic-gate 	t->t_ops = &rawfile_ops;
4307c478bd9Sstevel@tonic-gate 	t->t_data = rf;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	if (t->t_flags & MDB_TGT_F_RDWR)
4337c478bd9Sstevel@tonic-gate 		oflags = O_RDWR;
4347c478bd9Sstevel@tonic-gate 	else
4357c478bd9Sstevel@tonic-gate 		oflags = O_RDONLY;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
4387c478bd9Sstevel@tonic-gate 		io[i] = mdb_fdio_create_path(NULL, argv[i], oflags, 0);
4397c478bd9Sstevel@tonic-gate 		if (io[i] == NULL) {
4407c478bd9Sstevel@tonic-gate 			warn("failed to open %s", argv[i]);
4417c478bd9Sstevel@tonic-gate 			goto err;
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	rf->r_object_fio = io[0];	/* first file is the "object" */
4467c478bd9Sstevel@tonic-gate 	rf->r_core_fio = io[1];		/* second file is the "core" */
4477c478bd9Sstevel@tonic-gate 	t->t_flags |= MDB_TGT_F_ASIO;	/* do i/o using aread and awrite */
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	return (0);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate err:
4527c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
4537c478bd9Sstevel@tonic-gate 		if (io[i] != NULL)
4547c478bd9Sstevel@tonic-gate 			mdb_io_destroy(io[i]);
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	mdb_free(rf, sizeof (rf_data_t));
4597c478bd9Sstevel@tonic-gate 	return (set_errno(EMDB_TGT));
4607c478bd9Sstevel@tonic-gate }
461