4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2018 Joyent, Inc.
31 * The raw file target is invoked whenever a file of unrecognizable type is
32 * specified on the command line, or when raw file examination is forced using
33 * the -f option. If one file is specified, that file will be opened as the
34 * "object" file. If two files are specified, the second one will be opened
35 * as the "core" file. Each file is opened using the fdio backend, which
36 * internally supports both byte-oriented i/o and block-oriented i/o as needed.
39 #include <mdb/mdb_modapi.h>
40 #include <mdb/mdb_target_impl.h>
41 #include <mdb/mdb_io_impl.h>
42 #include <mdb/mdb_conf.h>
43 #include <mdb/mdb_err.h>
46 #include <sys/dtrace.h>
49 typedef struct rf_data
{
50 mdb_io_t
*r_object_fio
;
54 #define RF_OBJECT(p) (((rf_data_t *)(p))->r_object_fio)
55 #define RF_CORE(p) (((rf_data_t *)(p))->r_core_fio)
58 rf_data_destroy(rf_data_t
*rf
)
60 if (rf
->r_object_fio
!= NULL
)
61 mdb_io_destroy(rf
->r_object_fio
);
63 if (rf
->r_core_fio
!= NULL
)
64 mdb_io_destroy(rf
->r_core_fio
);
66 mdb_free(rf
, sizeof (rf_data_t
));
70 rf_setflags(mdb_tgt_t
*t
, int flags
)
72 if ((flags
^ t
->t_flags
) & MDB_TGT_F_RDWR
) {
73 uint_t otflags
= t
->t_flags
;
74 rf_data_t
*orf
= t
->t_data
;
78 if (orf
->r_object_fio
!= NULL
)
79 argv
[argc
++] = IOP_NAME(orf
->r_object_fio
);
80 if (orf
->r_core_fio
!= NULL
)
81 argv
[argc
++] = IOP_NAME(orf
->r_core_fio
);
83 t
->t_flags
= (t
->t_flags
& ~MDB_TGT_F_RDWR
) |
84 (flags
& MDB_TGT_F_RDWR
);
86 if (mdb_rawfile_tgt_create(t
, argc
, argv
) == -1) {
99 rf_destroy(mdb_tgt_t
*t
)
101 rf_data_destroy(t
->t_data
);
106 rf_name(mdb_tgt_t
*t
)
112 rf_read(mdb_io_t
*io
, void *buf
, size_t nbytes
, uint64_t addr
)
117 return (set_errno(EMDB_NOMAP
));
119 if (IOP_SEEK(io
, addr
, SEEK_SET
) == -1)
120 return (-1); /* errno is set for us */
122 if ((rbytes
= IOP_READ(io
, buf
, nbytes
)) == 0)
123 (void) set_errno(EMDB_EOF
);
129 rf_write(mdb_io_t
*io
, const void *buf
, size_t nbytes
, uint64_t addr
)
132 return (set_errno(EMDB_NOMAP
));
134 if (IOP_SEEK(io
, addr
, SEEK_SET
) == -1)
135 return (-1); /* errno is set for us */
137 return (IOP_WRITE(io
, buf
, nbytes
));
141 rf_aread(mdb_tgt_t
*t
, mdb_tgt_as_t as
, void *buf
,
142 size_t len
, mdb_tgt_addr_t addr
)
144 switch ((uintptr_t)as
) {
145 case (uintptr_t)MDB_TGT_AS_VIRT
:
146 case (uintptr_t)MDB_TGT_AS_PHYS
:
147 if (RF_CORE(t
->t_data
) != NULL
)
148 return (rf_read(RF_CORE(t
->t_data
), buf
, len
, addr
));
150 case (uintptr_t)MDB_TGT_AS_FILE
:
151 return (rf_read(RF_OBJECT(t
->t_data
), buf
, len
, addr
));
153 return (set_errno(EMDB_NOMAP
));
158 rf_awrite(mdb_tgt_t
*t
, mdb_tgt_as_t as
, const void *buf
,
159 size_t len
, mdb_tgt_addr_t addr
)
161 switch ((uintptr_t)as
) {
162 case (uintptr_t)MDB_TGT_AS_VIRT
:
163 case (uintptr_t)MDB_TGT_AS_PHYS
:
164 if (RF_CORE(t
->t_data
) != NULL
)
165 return (rf_write(RF_CORE(t
->t_data
), buf
, len
, addr
));
167 case (uintptr_t)MDB_TGT_AS_FILE
:
168 return (rf_write(RF_OBJECT(t
->t_data
), buf
, len
, addr
));
170 return (set_errno(EMDB_NOMAP
));
175 rf_vread(mdb_tgt_t
*t
, void *buf
, size_t nbytes
, uintptr_t addr
)
177 if (RF_CORE(t
->t_data
) != NULL
)
178 return (rf_read(RF_CORE(t
->t_data
), buf
, nbytes
, addr
));
180 return (rf_read(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
184 rf_vwrite(mdb_tgt_t
*t
, const void *buf
, size_t nbytes
, uintptr_t addr
)
186 if (RF_CORE(t
->t_data
) != NULL
)
187 return (rf_write(RF_CORE(t
->t_data
), buf
, nbytes
, addr
));
189 return (rf_write(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
193 rf_pread(mdb_tgt_t
*t
, void *buf
, size_t nbytes
, physaddr_t addr
)
195 if (RF_CORE(t
->t_data
) != NULL
)
196 return (rf_read(RF_CORE(t
->t_data
), buf
, nbytes
, addr
));
198 return (rf_read(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
202 rf_pwrite(mdb_tgt_t
*t
, const void *buf
, size_t nbytes
, physaddr_t addr
)
204 if (RF_CORE(t
->t_data
) != NULL
)
205 return (rf_write(RF_CORE(t
->t_data
), buf
, nbytes
, addr
));
207 return (rf_write(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
211 rf_fread(mdb_tgt_t
*t
, void *buf
, size_t nbytes
, uintptr_t addr
)
213 return (rf_read(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
217 rf_fwrite(mdb_tgt_t
*t
, const void *buf
, size_t nbytes
, uintptr_t addr
)
219 return (rf_write(RF_OBJECT(t
->t_data
), buf
, nbytes
, addr
));
224 rf_print_map(mdb_io_t
*io
, const char *type
, int tflags
,
225 mdb_tgt_map_f
*func
, void *private)
229 (void) mdb_iob_snprintf(map
.map_name
, MDB_TGT_MAPSZ
,
230 "%s (%s)", IOP_NAME(io
), type
);
233 map
.map_size
= IOP_SEEK(io
, 0, SEEK_END
);
234 map
.map_flags
= MDB_TGT_MAP_R
;
236 if (tflags
& MDB_TGT_F_RDWR
)
237 map
.map_flags
|= MDB_TGT_MAP_W
;
239 return (func(private, &map
, map
.map_name
));
243 rf_mapping_iter(mdb_tgt_t
*t
, mdb_tgt_map_f
*func
, void *private)
245 rf_data_t
*rf
= t
->t_data
;
247 if (rf
->r_object_fio
!= NULL
&& rf_print_map(rf
->r_object_fio
,
248 "object file", t
->t_flags
, func
, private) != 0)
251 if (rf
->r_core_fio
!= NULL
&& rf_print_map(rf
->r_core_fio
,
252 "core file", t
->t_flags
, func
, private) != 0)
260 rf_status(mdb_tgt_t
*t
, mdb_tgt_status_t
*tsp
)
262 bzero(tsp
, sizeof (mdb_tgt_status_t
));
264 if (RF_CORE(t
->t_data
) != NULL
)
265 tsp
->st_state
= MDB_TGT_DEAD
;
267 tsp
->st_state
= MDB_TGT_IDLE
;
274 rf_status_dcmd(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
276 rf_data_t
*rf
= mdb
.m_target
->t_data
;
278 if (rf
->r_object_fio
!= NULL
) {
279 mdb_printf("debugging file '%s' (object file)",
280 IOP_NAME(rf
->r_object_fio
));
282 if (rf
->r_core_fio
!= NULL
) {
283 mdb_printf(" and file '%s' (core file)",
284 IOP_NAME(rf
->r_core_fio
));
289 mdb_printf("debugging empty target\n");
295 static const mdb_dcmd_t rf_dcmds
[] = {
296 { "status", NULL
, "print summary of current target", rf_status_dcmd
},
300 static const struct rf_magic
{
305 { DOF_MAG_STRING
, DOF_MAG_STRLEN
, "dof" },
310 rf_activate(mdb_tgt_t
*t
)
312 rf_data_t
*rf
= t
->t_data
;
313 const struct rf_magic
*m
;
317 (void) mdb_tgt_register_dcmds(t
, &rf_dcmds
[0], MDB_MOD_FORCE
);
320 * We set the legacy adb variable 'd' to be the size of the file (data
321 * segment). To get this value, we call seek() on the underlying fdio.
323 if (rf
->r_object_fio
!= NULL
) {
324 size
= IOP_SEEK(rf
->r_object_fio
, 0, SEEK_END
);
325 if ((v
= mdb_nv_lookup(&mdb
.m_nv
, "d")) != NULL
)
326 mdb_nv_set_value(v
, size
);
330 * Load any debugging support modules that match the file type, as
331 * determined by our poor man's /etc/magic. If many clients need
332 * to use this feature, rf_magic[] should be computed dynamically.
334 for (m
= rf_magic
; m
->rfm_str
!= NULL
; m
++) {
335 char *buf
= mdb_alloc(m
->rfm_len
, UM_SLEEP
);
337 if (mdb_tgt_vread(t
, buf
, m
->rfm_len
, 0) == m
->rfm_len
&&
338 bcmp(buf
, m
->rfm_str
, m
->rfm_len
) == 0) {
339 (void) mdb_module_load(m
->rfm_mod
,
340 MDB_MOD_LOCAL
| MDB_MOD_SILENT
);
343 mdb_free(buf
, m
->rfm_len
);
348 rf_deactivate(mdb_tgt_t
*t
)
350 const mdb_dcmd_t
*dcp
;
352 for (dcp
= &rf_dcmds
[0]; dcp
->dc_name
!= NULL
; dcp
++) {
353 if (mdb_module_remove_dcmd(t
->t_module
, dcp
->dc_name
) == -1)
354 warn("failed to remove dcmd %s", dcp
->dc_name
);
358 static const mdb_tgt_ops_t rawfile_ops
= {
359 rf_setflags
, /* t_setflags */
360 (int (*)()) mdb_tgt_notsup
, /* t_setcontext */
361 rf_activate
, /* t_activate */
362 rf_deactivate
, /* t_deactivate */
363 (void (*)()) mdb_tgt_nop
, /* t_periodic */
364 rf_destroy
, /* t_destroy */
365 rf_name
, /* t_name */
366 (const char *(*)()) mdb_conf_isa
, /* t_isa */
367 (const char *(*)()) mdb_conf_platform
, /* t_platform */
368 (int (*)()) mdb_tgt_notsup
, /* t_uname */
369 (int (*)()) mdb_tgt_notsup
, /* t_dmodel */
370 rf_aread
, /* t_aread */
371 rf_awrite
, /* t_awrite */
372 rf_vread
, /* t_vread */
373 rf_vwrite
, /* t_vwrite */
374 rf_pread
, /* t_pread */
375 rf_pwrite
, /* t_pwrite */
376 rf_fread
, /* t_fread */
377 rf_fwrite
, /* t_fwrite */
378 (ssize_t (*)()) mdb_tgt_notsup
, /* t_ioread */
379 (ssize_t (*)()) mdb_tgt_notsup
, /* t_iowrite */
380 (int (*)()) mdb_tgt_notsup
, /* t_vtop */
381 (int (*)()) mdb_tgt_notsup
, /* t_lookup_by_name */
382 (int (*)()) mdb_tgt_notsup
, /* t_lookup_by_addr */
383 (int (*)()) mdb_tgt_notsup
, /* t_symbol_iter */
384 rf_mapping_iter
, /* t_mapping_iter */
385 rf_mapping_iter
, /* t_object_iter */
386 (const mdb_map_t
*(*)()) mdb_tgt_null
, /* t_addr_to_map */
387 (const mdb_map_t
*(*)()) mdb_tgt_null
, /* t_name_to_map */
388 (struct ctf_file
*(*)()) mdb_tgt_null
, /* t_addr_to_ctf */
389 (struct ctf_file
*(*)()) mdb_tgt_null
, /* t_name_to_ctf */
390 rf_status
, /* t_status */
391 (int (*)()) mdb_tgt_notsup
, /* t_run */
392 (int (*)()) mdb_tgt_notsup
, /* t_step */
393 (int (*)()) mdb_tgt_notsup
, /* t_step_out */
394 (int (*)()) mdb_tgt_notsup
, /* t_next */
395 (int (*)()) mdb_tgt_notsup
, /* t_cont */
396 (int (*)()) mdb_tgt_notsup
, /* t_signal */
397 (int (*)()) mdb_tgt_null
, /* t_add_vbrkpt */
398 (int (*)()) mdb_tgt_null
, /* t_add_sbrkpt */
399 (int (*)()) mdb_tgt_null
, /* t_add_pwapt */
400 (int (*)()) mdb_tgt_null
, /* t_add_vwapt */
401 (int (*)()) mdb_tgt_null
, /* t_add_iowapt */
402 (int (*)()) mdb_tgt_null
, /* t_add_sysenter */
403 (int (*)()) mdb_tgt_null
, /* t_add_sysexit */
404 (int (*)()) mdb_tgt_null
, /* t_add_signal */
405 (int (*)()) mdb_tgt_null
, /* t_add_fault */
406 (int (*)()) mdb_tgt_notsup
, /* t_getareg */
407 (int (*)()) mdb_tgt_notsup
, /* t_putareg */
408 (int (*)()) mdb_tgt_notsup
, /* t_stack_iter */
409 (int (*)()) mdb_tgt_notsup
/* t_auxv */
413 mdb_rawfile_tgt_create(mdb_tgt_t
*t
, int argc
, const char *argv
[])
415 mdb_io_t
*io
[2] = { NULL
, NULL
};
420 return (set_errno(EINVAL
));
422 rf
= mdb_zalloc(sizeof (rf_data_t
), UM_SLEEP
);
423 t
->t_ops
= &rawfile_ops
;
426 if (t
->t_flags
& MDB_TGT_F_RDWR
)
431 for (i
= 0; i
< argc
; i
++) {
432 io
[i
] = mdb_fdio_create_path(NULL
, argv
[i
], oflags
, 0);
434 warn("failed to open %s", argv
[i
]);
439 rf
->r_object_fio
= io
[0]; /* first file is the "object" */
440 rf
->r_core_fio
= io
[1]; /* second file is the "core" */
441 t
->t_flags
|= MDB_TGT_F_ASIO
; /* do i/o using aread and awrite */
446 for (i
= 0; i
< argc
; i
++) {
448 mdb_io_destroy(io
[i
]);
452 mdb_free(rf
, sizeof (rf_data_t
));
453 return (set_errno(EMDB_TGT
));