Home | History | Annotate | Line # | Download | only in aarch64
db_disasm.c revision 1.7
      1 /* $NetBSD: db_disasm.c,v 1.7 2019/10/28 18:15:25 joerg Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2017 Ryo Shimizu <ryo (at) nerv.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.7 2019/10/28 18:15:25 joerg Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <machine/db_machdep.h>
     34 #include <ddb/db_interface.h>
     35 #include <ddb/db_sym.h>
     36 #include <ddb/db_output.h>
     37 #include <ddb/db_access.h>
     38 #include <ddb/db_user.h>
     39 
     40 #include <arch/aarch64/aarch64/disasm.h>
     41 
     42 static uint32_t
     43 db_disasm_readword(uintptr_t address)
     44 {
     45 	return db_get_value(address, sizeof(uint32_t), false);
     46 }
     47 
     48 static void
     49 db_disasm_printaddr(uintptr_t address)
     50 {
     51 	db_printf("%lx <", address);
     52 	db_printsym((db_addr_t)address, DB_STGY_ANY, db_printf);
     53 	db_printf(">");
     54 }
     55 
     56 static const disasm_interface_t db_disasm_interface = {
     57 	.di_readword = db_disasm_readword,
     58 	.di_printaddr = db_disasm_printaddr,
     59 	.di_printf = db_printf
     60 };
     61 
     62 db_addr_t
     63 db_disasm(db_addr_t loc, bool altfmt)
     64 {
     65 	return disasm(&db_disasm_interface, loc);
     66 }
     67 
     68 
     69 static char *strdisasm_ptr;
     70 static char strdisasm_buf[256];
     71 
     72 static uint32_t
     73 strdisasm_readword(uintptr_t address)
     74 {
     75 	return *(uint32_t *)address;
     76 }
     77 
     78 static void __printflike(1, 2)
     79 strdisasm_printf(const char *fmt, ...)
     80 {
     81 	va_list ap;
     82 	int len;
     83 
     84 	/* calculation spaces to append a string */
     85 	len = strdisasm_buf + sizeof(strdisasm_buf) - strdisasm_ptr;
     86 
     87 	va_start(ap, fmt);
     88 	len = vsnprintf(strdisasm_ptr, len, fmt, ap);
     89 	va_end(ap);
     90 
     91 	strdisasm_ptr += len;
     92 }
     93 
     94 static void
     95 strdisasm_printaddr(uintptr_t address)
     96 {
     97 	strdisasm_printf("0x%lx", address);
     98 }
     99 
    100 static const disasm_interface_t strdisasm_interface = {
    101 	.di_readword = strdisasm_readword,
    102 	.di_printaddr = strdisasm_printaddr,
    103 	.di_printf = strdisasm_printf
    104 };
    105 
    106 const char *
    107 strdisasm(vaddr_t pc)
    108 {
    109 	char *p;
    110 
    111 	strdisasm_ptr = strdisasm_buf;
    112 	disasm(&strdisasm_interface, (db_addr_t)pc);
    113 
    114 	/* replace tab to space, and chomp '\n' */
    115 	for (p = strdisasm_buf; *p != '\0'; p++) {
    116 		if (*p == '\t')
    117 			*p = ' ';
    118 	}
    119 	if ((p > strdisasm_buf) && (p[-1] == '\n'))
    120 		p[-1] = '\0';
    121 
    122 	return strdisasm_buf;
    123 }
    124 
    125 /*
    126  * disassemble aarch32 insns?
    127  */
    128 const char *
    129 strdisasm_aarch32(vaddr_t pc)
    130 {
    131 	uint32_t insn = *(uint32_t *)pc;
    132 
    133 	/* not supported any aarch32 insns yet... */
    134 	snprintf(strdisasm_buf, sizeof(strdisasm_buf), ".insn 0x%08x", insn);
    135 
    136 	return strdisasm_buf;
    137 }
    138 
    139