1 /* $NetBSD: db_disasm.c,v 1.13 2009/03/14 21:04:03 dsl Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie the 26 * rights to redistribute these changes. 27 * 28 * Id: db_disasm.c,v 2.3 91/02/05 17:11:03 mrt (CMU) 29 */ 30 31 /* 32 * Instruction disassembler. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.13 2009/03/14 21:04:03 dsl Exp $"); 37 38 #ifndef _KERNEL 39 #include "stubs.h" 40 #include <sys/types.h> 41 #include <sys/time.h> 42 #include <sys/ksyms.h> 43 #include <machine/stdarg.h> 44 #endif /* _KERNEL */ 45 46 #include <sys/param.h> 47 #include <sys/proc.h> 48 #include <machine/db_machdep.h> 49 50 #include <ddb/db_access.h> 51 #include <ddb/db_sym.h> 52 #include <ddb/db_output.h> 53 #include <ddb/db_interface.h> 54 55 #ifndef _KERNEL 56 #define db_printsym(a, x, fn) fn("%lx ", (a)) 57 #endif 58 59 /* 60 * Size attributes 61 */ 62 #define BYTE 0 63 #define WORD 1 64 #define LONG 2 65 #define QUAD 3 66 #define SNGL 4 67 #define DBLR 5 68 #define EXTR 6 69 #define SDEP 7 70 #define NONE 8 71 72 /* 73 * Addressing modes 74 */ 75 #define E 1 /* general effective address */ 76 #define Eind 2 /* indirect address (jump, call) */ 77 #define Ew 3 /* address, word size */ 78 #define Eb 4 /* address, byte size */ 79 #define R 5 /* register, in 'reg' field */ 80 #define Rw 6 /* word register, in 'reg' field */ 81 #define Ri 7 /* register in instruction */ 82 #define S 8 /* segment reg, in 'reg' field */ 83 #define Si 9 /* segment reg, in instruction */ 84 #define A 10 /* accumulator */ 85 #define BX 11 /* (bx) */ 86 #define CL 12 /* cl, for shifts */ 87 #define DX 13 /* dx, for IO */ 88 #define SI 14 /* si */ 89 #define DI 15 /* di */ 90 #define CR 16 /* control register */ 91 #define DR 17 /* debug register */ 92 #define TR 18 /* test register */ 93 #define I 19 /* immediate, unsigned */ 94 #define Is 20 /* immediate, signed */ 95 #define Ib 21 /* byte immediate, unsigned */ 96 #define Ibs 22 /* byte immediate, signed */ 97 #define Iw 23 /* word immediate, unsigned */ 98 #define Il 24 /* long immediate */ 99 #define O 25 /* direct address */ 100 #define Db 26 /* byte displacement from EIP */ 101 #define Dl 27 /* long displacement from EIP */ 102 #define o1 28 /* constant 1 */ 103 #define o3 29 /* constant 3 */ 104 #define OS 30 /* immediate offset/segment */ 105 #define ST 31 /* FP stack top */ 106 #define STI 32 /* FP stack */ 107 #define X 33 /* extended FP op */ 108 #define XA 34 /* for 'fstcw %ax' */ 109 #define Ed 35 /* address, double size */ 110 #define Iq 36 /* word immediate, maybe 64bits */ 111 112 struct inst { 113 const char *i_name; /* name */ 114 short i_has_modrm; /* has regmodrm byte */ 115 short i_size; /* operand size */ 116 int i_mode; /* addressing modes */ 117 const char *i_extra; /* pointer to extra opcode table */ 118 }; 119 120 #define op1(x) (x) 121 #define op2(x,y) ((x)|((y)<<8)) 122 #define op3(x,y,z) ((x)|((y)<<8)|((z)<<16)) 123 124 struct finst { 125 const char *f_name; /* name for memory instruction */ 126 int f_size; /* size for memory instruction */ 127 int f_rrmode; /* mode for rr instruction */ 128 const char *f_rrname; /* name for rr instruction 129 (or pointer to table) */ 130 }; 131 132 const char * const db_Grp6[] = { 133 "sldt", 134 "str", 135 "lldt", 136 "ltr", 137 "verr", 138 "verw", 139 "", 140 "" 141 }; 142 143 const char * const db_Grp7[] = { 144 "sgdt", 145 "sidt", 146 "lgdt", 147 "lidt", 148 "smsw", 149 "", 150 "lmsw", 151 "invlpg" 152 }; 153 154 const char * const db_Grp8[] = { 155 "", 156 "", 157 "", 158 "", 159 "bt", 160 "bts", 161 "btr", 162 "btc" 163 }; 164 165 const char * const db_Grp9[] = { 166 "", 167 "cmpxchg8b", 168 "", 169 "", 170 "", 171 "", 172 "", 173 "", 174 }; 175 176 const struct inst db_inst_0f0x[] = { 177 /*00*/ { "", true, NONE, op1(Ew), (const char *)db_Grp6 }, 178 /*01*/ { "", true, NONE, op1(Ew), (const char *)db_Grp7 }, 179 /*02*/ { "lar", true, LONG, op2(E,R), 0 }, 180 /*03*/ { "lsl", true, LONG, op2(E,R), 0 }, 181 /*04*/ { "", false, NONE, 0, 0 }, 182 /*05*/ { "syscall",false,NONE, 0, 0 }, 183 /*06*/ { "clts", false, NONE, 0, 0 }, 184 /*07*/ { "sysret",false, NONE, 0, 0 }, 185 186 /*08*/ { "invd", false, NONE, 0, 0 }, 187 /*09*/ { "wbinvd",false, NONE, 0, 0 }, 188 /*0a*/ { "", false, NONE, 0, 0 }, 189 /*0b*/ { "ud2", false, NONE, 0, 0 }, 190 /*0c*/ { "", false, NONE, 0, 0 }, 191 /*0d*/ { "prefetch",true,NONE, op2(E,R), 0 }, /* Not 'R' really */ 192 /*0e*/ { "", false, NONE, 0, 0 }, /* FEMMS (3DNow) */ 193 /*0f*/ { "", false, NONE, 0, 0 }, /* 3DNow */ 194 }; 195 196 const struct inst db_inst_0f2x[] = { 197 /*20*/ { "mov", true, LONG, op2(CR,E), 0 }, /* use E for reg */ 198 /*21*/ { "mov", true, LONG, op2(DR,E), 0 }, /* since mod == 11 */ 199 /*22*/ { "mov", true, LONG, op2(E,CR), 0 }, 200 /*23*/ { "mov", true, LONG, op2(E,DR), 0 }, 201 /*24*/ { "mov", true, LONG, op2(TR,E), 0 }, 202 /*25*/ { "", false, NONE, 0, 0 }, 203 /*26*/ { "mov", true, LONG, op2(E,TR), 0 }, 204 /*27*/ { "", false, NONE, 0, 0 }, 205 206 /*28*/ { "", false, NONE, 0, 0 }, 207 /*29*/ { "", false, NONE, 0, 0 }, 208 /*2a*/ { "", false, NONE, 0, 0 }, 209 /*2b*/ { "", false, NONE, 0, 0 }, 210 /*2c*/ { "", false, NONE, 0, 0 }, 211 /*2d*/ { "", false, NONE, 0, 0 }, 212 /*2e*/ { "", false, NONE, 0, 0 }, 213 /*2f*/ { "", false, NONE, 0, 0 }, 214 }; 215 216 const struct inst db_inst_0f3x[] = { 217 /*30*/ { "wrmsr", false, NONE, 0, 0 }, 218 /*31*/ { "rdtsc", false, NONE, 0, 0 }, 219 /*32*/ { "rdmsr", false, NONE, 0, 0 }, 220 /*33*/ { "rdpmc", false, NONE, 0, 0 }, 221 /*34*/ { "sysenter",false,NONE, 0, 0 }, 222 /*35*/ { "sysexit",false, NONE, 0, 0 }, 223 /*36*/ { "", false, NONE, 0, 0 }, 224 /*37*/ { "", false, NONE, 0, 0 }, 225 226 /*38*/ { "", false, NONE, 0, 0 }, 227 /*39*/ { "", false, NONE, 0, 0 }, 228 /*3a*/ { "", false, NONE, 0, 0 }, 229 /*3v*/ { "", false, NONE, 0, 0 }, 230 /*3c*/ { "", false, NONE, 0, 0 }, 231 /*3d*/ { "", false, NONE, 0, 0 }, 232 /*3e*/ { "", false, NONE, 0, 0 }, 233 /*3f*/ { "", false, NONE, 0, 0 }, 234 }; 235 236 const struct inst db_inst_0f4x[] = { 237 /*40*/ { "cmovo", true, LONG, op2(E,R), 0 }, 238 /*41*/ { "cmovno", true, LONG, op2(E,R), 0 }, 239 /*42*/ { "cmovc", true, LONG, op2(E,R), 0 }, 240 /*43*/ { "cmovnc", true, LONG, op2(E,R), 0 }, 241 /*44*/ { "cmovz", true, LONG, op2(E,R), 0 }, 242 /*45*/ { "cmovnz", true, LONG, op2(E,R), 0 }, 243 /*46*/ { "cmovbe", true, LONG, op2(E,R), 0 }, 244 /*47*/ { "cmovmbe",true, LONG, op2(E,R), 0 }, 245 /*48*/ { "cmovs", true, LONG, op2(E,R), 0 }, 246 /*49*/ { "cmovns", true, LONG, op2(E,R), 0 }, 247 /*4a*/ { "cmovp", true, LONG, op2(E,R), 0 }, 248 /*4b*/ { "cmovnp", true, LONG, op2(E,R), 0 }, 249 /*4c*/ { "cmovl", true, LONG, op2(E,R), 0 }, 250 /*4d*/ { "cmovnl", true, LONG, op2(E,R), 0 }, 251 /*4e*/ { "cmovle", true, LONG, op2(E,R), 0 }, 252 /*4f*/ { "cmovnle",true, LONG, op2(E,R), 0 }, 253 }; 254 255 const struct inst db_inst_0f8x[] = { 256 /*80*/ { "jo", false, NONE, op1(Dl), 0 }, 257 /*81*/ { "jno", false, NONE, op1(Dl), 0 }, 258 /*82*/ { "jb", false, NONE, op1(Dl), 0 }, 259 /*83*/ { "jnb", false, NONE, op1(Dl), 0 }, 260 /*84*/ { "jz", false, NONE, op1(Dl), 0 }, 261 /*85*/ { "jnz", false, NONE, op1(Dl), 0 }, 262 /*86*/ { "jbe", false, NONE, op1(Dl), 0 }, 263 /*87*/ { "jnbe", false, NONE, op1(Dl), 0 }, 264 265 /*88*/ { "js", false, NONE, op1(Dl), 0 }, 266 /*89*/ { "jns", false, NONE, op1(Dl), 0 }, 267 /*8a*/ { "jp", false, NONE, op1(Dl), 0 }, 268 /*8b*/ { "jnp", false, NONE, op1(Dl), 0 }, 269 /*8c*/ { "jl", false, NONE, op1(Dl), 0 }, 270 /*8d*/ { "jnl", false, NONE, op1(Dl), 0 }, 271 /*8e*/ { "jle", false, NONE, op1(Dl), 0 }, 272 /*8f*/ { "jnle", false, NONE, op1(Dl), 0 }, 273 }; 274 275 const struct inst db_inst_0f9x[] = { 276 /*90*/ { "seto", true, NONE, op1(Eb), 0 }, 277 /*91*/ { "setno", true, NONE, op1(Eb), 0 }, 278 /*92*/ { "setb", true, NONE, op1(Eb), 0 }, 279 /*93*/ { "setnb", true, NONE, op1(Eb), 0 }, 280 /*94*/ { "setz", true, NONE, op1(Eb), 0 }, 281 /*95*/ { "setnz", true, NONE, op1(Eb), 0 }, 282 /*96*/ { "setbe", true, NONE, op1(Eb), 0 }, 283 /*97*/ { "setnbe",true, NONE, op1(Eb), 0 }, 284 285 /*98*/ { "sets", true, NONE, op1(Eb), 0 }, 286 /*99*/ { "setns", true, NONE, op1(Eb), 0 }, 287 /*9a*/ { "setp", true, NONE, op1(Eb), 0 }, 288 /*9b*/ { "setnp", true, NONE, op1(Eb), 0 }, 289 /*9c*/ { "setl", true, NONE, op1(Eb), 0 }, 290 /*9d*/ { "setnl", true, NONE, op1(Eb), 0 }, 291 /*9e*/ { "setle", true, NONE, op1(Eb), 0 }, 292 /*9f*/ { "setnle",true, NONE, op1(Eb), 0 }, 293 }; 294 295 const struct inst db_inst_0fax[] = { 296 /*a0*/ { "push", false, NONE, op1(Si), 0 }, 297 /*a1*/ { "pop", false, NONE, op1(Si), 0 }, 298 /*a2*/ { "cpuid", false, NONE, 0, 0 }, 299 /*a3*/ { "bt", true, LONG, op2(R,E), 0 }, 300 /*a4*/ { "shld", true, LONG, op3(Ib,E,R), 0 }, 301 /*a5*/ { "shld", true, LONG, op3(CL,E,R), 0 }, 302 /*a6*/ { "", false, NONE, 0, 0 }, 303 /*a7*/ { "", false, NONE, 0, 0 }, 304 305 /*a8*/ { "push", false, NONE, op1(Si), 0 }, 306 /*a9*/ { "pop", false, NONE, op1(Si), 0 }, 307 /*aa*/ { "rsm", false, NONE, 0, 0 }, 308 /*ab*/ { "bts", true, LONG, op2(R,E), 0 }, 309 /*ac*/ { "shrd", true, LONG, op3(Ib,E,R), 0 }, 310 /*ad*/ { "shrd", true, LONG, op3(CL,E,R), 0 }, 311 /*ae*/ { "fxsave",true, LONG, 0, 0 }, 312 /*af*/ { "imul", true, LONG, op2(E,R), 0 }, 313 }; 314 315 const struct inst db_inst_0fbx[] = { 316 /*b0*/ { "cmpxchg",true, BYTE, op2(R, E), 0 }, 317 /*b1*/ { "cmpxchg",true, LONG, op2(R, E), 0 }, 318 /*b2*/ { "lss", true, LONG, op2(E, R), 0 }, 319 /*b3*/ { "btr", true, LONG, op2(R, E), 0 }, 320 /*b4*/ { "lfs", true, LONG, op2(E, R), 0 }, 321 /*b5*/ { "lgs", true, LONG, op2(E, R), 0 }, 322 /*b6*/ { "movzb", true, LONG, op2(E, R), 0 }, 323 /*b7*/ { "movzw", true, LONG, op2(E, R), 0 }, 324 325 /*b8*/ { "", false, NONE, 0, 0 }, 326 /*b9*/ { "", false, NONE, 0, 0 }, 327 /*ba*/ { "", true, LONG, op2(Ib, E), (const char *)db_Grp8 }, 328 /*bb*/ { "btc", true, LONG, op2(R, E), 0 }, 329 /*bc*/ { "bsf", true, LONG, op2(E, R), 0 }, 330 /*bd*/ { "bsr", true, LONG, op2(E, R), 0 }, 331 /*be*/ { "movsb", true, LONG, op2(E, R), 0 }, 332 /*bf*/ { "movsw", true, LONG, op2(E, R), 0 }, 333 }; 334 335 const struct inst db_inst_0fcx[] = { 336 /*c0*/ { "xadd", true, BYTE, op2(R, E), 0 }, 337 /*c1*/ { "xadd", true, LONG, op2(R, E), 0 }, 338 /*c2*/ { "", false, NONE, 0, 0 }, 339 /*c3*/ { "", false, NONE, 0, 0 }, 340 /*c4*/ { "", false, NONE, 0, 0 }, 341 /*c5*/ { "", false, NONE, 0, 0 }, 342 /*c6*/ { "", false, NONE, 0, 0 }, 343 /*c7*/ { "", true, NONE, op1(E), (const char *)db_Grp9 }, 344 /*c8*/ { "bswap", false, LONG, op1(Ri), 0 }, 345 /*c9*/ { "bswap", false, LONG, op1(Ri), 0 }, 346 /*ca*/ { "bswap", false, LONG, op1(Ri), 0 }, 347 /*cb*/ { "bswap", false, LONG, op1(Ri), 0 }, 348 /*cc*/ { "bswap", false, LONG, op1(Ri), 0 }, 349 /*cd*/ { "bswap", false, LONG, op1(Ri), 0 }, 350 /*ce*/ { "bswap", false, LONG, op1(Ri), 0 }, 351 /*cf*/ { "bswap", false, LONG, op1(Ri), 0 }, 352 }; 353 354 const struct inst * const db_inst_0f[] = { 355 db_inst_0f0x, 356 0, 357 db_inst_0f2x, 358 db_inst_0f3x, 359 db_inst_0f4x, 360 0, 361 0, 362 0, 363 db_inst_0f8x, 364 db_inst_0f9x, 365 db_inst_0fax, 366 db_inst_0fbx, 367 db_inst_0fcx, 368 0, 369 0, 370 0 371 }; 372 373 const char * const db_Esc92[] = { 374 "fnop", "", "", "", "", "", "", "" 375 }; 376 const char * const db_Esc93[] = { 377 "", "", "", "", "", "", "", "" 378 }; 379 const char * const db_Esc94[] = { 380 "fchs", "fabs", "", "", "ftst", "fxam", "", "" 381 }; 382 const char * const db_Esc95[] = { 383 "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","" 384 }; 385 const char * const db_Esc96[] = { 386 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp", 387 "fincstp" 388 }; 389 const char * const db_Esc97[] = { 390 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos" 391 }; 392 393 const char * const db_Esca4[] = { 394 "", "fucompp","", "", "", "", "", "" 395 }; 396 397 const char * const db_Escb4[] = { 398 "", "", "fnclex","fninit","", "", "", "" 399 }; 400 401 const char * const db_Esce3[] = { 402 "", "fcompp","", "", "", "", "", "" 403 }; 404 405 const char * const db_Escf4[] = { 406 "fnstsw","", "", "", "", "", "", "" 407 }; 408 409 const struct finst db_Esc8[] = { 410 /*0*/ { "fadd", SNGL, op2(STI,ST), 0 }, 411 /*1*/ { "fmul", SNGL, op2(STI,ST), 0 }, 412 /*2*/ { "fcom", SNGL, op2(STI,ST), 0 }, 413 /*3*/ { "fcomp", SNGL, op2(STI,ST), 0 }, 414 /*4*/ { "fsub", SNGL, op2(STI,ST), 0 }, 415 /*5*/ { "fsubr", SNGL, op2(STI,ST), 0 }, 416 /*6*/ { "fdiv", SNGL, op2(STI,ST), 0 }, 417 /*7*/ { "fdivr", SNGL, op2(STI,ST), 0 }, 418 }; 419 420 const struct finst db_Esc9[] = { 421 /*0*/ { "fld", SNGL, op1(STI), 0 }, 422 /*1*/ { "", NONE, op1(STI), "fxch" }, 423 /*2*/ { "fst", SNGL, op1(X), (const char *)db_Esc92 }, 424 /*3*/ { "fstp", SNGL, op1(X), (const char *)db_Esc93 }, 425 /*4*/ { "fldenv", NONE, op1(X), (const char *)db_Esc94 }, 426 /*5*/ { "fldcw", NONE, op1(X), (const char *)db_Esc95 }, 427 /*6*/ { "fnstenv",NONE, op1(X), (const char *)db_Esc96 }, 428 /*7*/ { "fnstcw", NONE, op1(X), (const char *)db_Esc97 }, 429 }; 430 431 const struct finst db_Esca[] = { 432 /*0*/ { "fiadd", WORD, 0, 0 }, 433 /*1*/ { "fimul", WORD, 0, 0 }, 434 /*2*/ { "ficom", WORD, 0, 0 }, 435 /*3*/ { "ficomp", WORD, 0, 0 }, 436 /*4*/ { "fisub", WORD, op1(X), (const char *)db_Esca4 }, 437 /*5*/ { "fisubr", WORD, 0, 0 }, 438 /*6*/ { "fidiv", WORD, 0, 0 }, 439 /*7*/ { "fidivr", WORD, 0, 0 } 440 }; 441 442 const struct finst db_Escb[] = { 443 /*0*/ { "fild", WORD, 0, 0 }, 444 /*1*/ { "", NONE, 0, 0 }, 445 /*2*/ { "fist", WORD, 0, 0 }, 446 /*3*/ { "fistp", WORD, 0, 0 }, 447 /*4*/ { "", WORD, op1(X), (const char *)db_Escb4 }, 448 /*5*/ { "fld", EXTR, 0, 0 }, 449 /*6*/ { "", WORD, 0, 0 }, 450 /*7*/ { "fstp", EXTR, 0, 0 }, 451 }; 452 453 const struct finst db_Escc[] = { 454 /*0*/ { "fadd", DBLR, op2(ST,STI), 0 }, 455 /*1*/ { "fmul", DBLR, op2(ST,STI), 0 }, 456 /*2*/ { "fcom", DBLR, op2(ST,STI), 0 }, 457 /*3*/ { "fcomp", DBLR, op2(ST,STI), 0 }, 458 /*4*/ { "fsub", DBLR, op2(ST,STI), "fsubr" }, 459 /*5*/ { "fsubr", DBLR, op2(ST,STI), "fsub" }, 460 /*6*/ { "fdiv", DBLR, op2(ST,STI), "fdivr" }, 461 /*7*/ { "fdivr", DBLR, op2(ST,STI), "fdiv" }, 462 }; 463 464 const struct finst db_Escd[] = { 465 /*0*/ { "fld", DBLR, op1(STI), "ffree" }, 466 /*1*/ { "", NONE, 0, 0 }, 467 /*2*/ { "fst", DBLR, op1(STI), 0 }, 468 /*3*/ { "fstp", DBLR, op1(STI), 0 }, 469 /*4*/ { "frstor", NONE, op1(STI), "fucom" }, 470 /*5*/ { "", NONE, op1(STI), "fucomp" }, 471 /*6*/ { "fnsave", NONE, 0, 0 }, 472 /*7*/ { "fnstsw", NONE, 0, 0 }, 473 }; 474 475 const struct finst db_Esce[] = { 476 /*0*/ { "fiadd", LONG, op2(ST,STI), "faddp" }, 477 /*1*/ { "fimul", LONG, op2(ST,STI), "fmulp" }, 478 /*2*/ { "ficom", LONG, 0, 0 }, 479 /*3*/ { "ficomp", LONG, op1(X), (const char *)db_Esce3 }, 480 /*4*/ { "fisub", LONG, op2(ST,STI), "fsubrp" }, 481 /*5*/ { "fisubr", LONG, op2(ST,STI), "fsubp" }, 482 /*6*/ { "fidiv", LONG, op2(ST,STI), "fdivrp" }, 483 /*7*/ { "fidivr", LONG, op2(ST,STI), "fdivp" }, 484 }; 485 486 const struct finst db_Escf[] = { 487 /*0*/ { "fild", LONG, 0, 0 }, 488 /*1*/ { "", LONG, 0, 0 }, 489 /*2*/ { "fist", LONG, 0, 0 }, 490 /*3*/ { "fistp", LONG, 0, 0 }, 491 /*4*/ { "fbld", NONE, op1(XA), (const char *)db_Escf4 }, 492 /*5*/ { "fld", QUAD, 0, 0 }, 493 /*6*/ { "fbstp", NONE, 0, 0 }, 494 /*7*/ { "fstp", QUAD, 0, 0 }, 495 }; 496 497 const struct finst * const db_Esc_inst[] = { 498 db_Esc8, db_Esc9, db_Esca, db_Escb, 499 db_Escc, db_Escd, db_Esce, db_Escf 500 }; 501 502 const char * const db_Grp1[] = { 503 "add", 504 "or", 505 "adc", 506 "sbb", 507 "and", 508 "sub", 509 "xor", 510 "cmp" 511 }; 512 513 const char * const db_Grp2[] = { 514 "rol", 515 "ror", 516 "rcl", 517 "rcr", 518 "shl", 519 "shr", 520 "shl", 521 "sar" 522 }; 523 524 const struct inst db_Grp3[] = { 525 { "test", true, NONE, op2(I,E), 0 }, 526 { "test", true, NONE, op2(I,E), 0 }, 527 { "not", true, NONE, op1(E), 0 }, 528 { "neg", true, NONE, op1(E), 0 }, 529 { "mul", true, NONE, op2(E,A), 0 }, 530 { "imul", true, NONE, op2(E,A), 0 }, 531 { "div", true, NONE, op2(E,A), 0 }, 532 { "idiv", true, NONE, op2(E,A), 0 }, 533 }; 534 535 const struct inst db_Grp4[] = { 536 { "inc", true, BYTE, op1(E), 0 }, 537 { "dec", true, BYTE, op1(E), 0 }, 538 { "", true, NONE, 0, 0 }, 539 { "", true, NONE, 0, 0 }, 540 { "", true, NONE, 0, 0 }, 541 { "", true, NONE, 0, 0 }, 542 { "", true, NONE, 0, 0 }, 543 { "", true, NONE, 0, 0 } 544 }; 545 546 const struct inst db_Grp5[] = { 547 { "inc", true, LONG, op1(E), 0 }, 548 { "dec", true, LONG, op1(E), 0 }, 549 { "call", true, NONE, op1(Eind),0 }, 550 { "lcall", true, NONE, op1(Eind),0 }, 551 { "jmp", true, NONE, op1(Eind),0 }, 552 { "ljmp", true, NONE, op1(Eind),0 }, 553 { "push", true, LONG, op1(E), 0 }, 554 { "", true, NONE, 0, 0 } 555 }; 556 557 const struct inst db_inst_table[256] = { 558 /*00*/ { "add", true, BYTE, op2(R, E), 0 }, 559 /*01*/ { "add", true, LONG, op2(R, E), 0 }, 560 /*02*/ { "add", true, BYTE, op2(E, R), 0 }, 561 /*03*/ { "add", true, LONG, op2(E, R), 0 }, 562 /*04*/ { "add", false, BYTE, op2(Is, A), 0 }, 563 /*05*/ { "add", false, LONG, op2(Is, A), 0 }, 564 /*06*/ { "push", false, NONE, op1(Si), 0 }, 565 /*07*/ { "pop", false, NONE, op1(Si), 0 }, 566 567 /*08*/ { "or", true, BYTE, op2(R, E), 0 }, 568 /*09*/ { "or", true, LONG, op2(R, E), 0 }, 569 /*0a*/ { "or", true, BYTE, op2(E, R), 0 }, 570 /*0b*/ { "or", true, LONG, op2(E, R), 0 }, 571 /*0c*/ { "or", false, BYTE, op2(I, A), 0 }, 572 /*0d*/ { "or", false, LONG, op2(I, A), 0 }, 573 /*0e*/ { "push", false, NONE, op1(Si), 0 }, 574 /*0f*/ { "", false, NONE, 0, 0 }, 575 576 /*10*/ { "adc", true, BYTE, op2(R, E), 0 }, 577 /*11*/ { "adc", true, LONG, op2(R, E), 0 }, 578 /*12*/ { "adc", true, BYTE, op2(E, R), 0 }, 579 /*13*/ { "adc", true, LONG, op2(E, R), 0 }, 580 /*14*/ { "adc", false, BYTE, op2(Is, A), 0 }, 581 /*15*/ { "adc", false, LONG, op2(Is, A), 0 }, 582 /*16*/ { "push", false, NONE, op1(Si), 0 }, 583 /*17*/ { "pop", false, NONE, op1(Si), 0 }, 584 585 /*18*/ { "sbb", true, BYTE, op2(R, E), 0 }, 586 /*19*/ { "sbb", true, LONG, op2(R, E), 0 }, 587 /*1a*/ { "sbb", true, BYTE, op2(E, R), 0 }, 588 /*1b*/ { "sbb", true, LONG, op2(E, R), 0 }, 589 /*1c*/ { "sbb", false, BYTE, op2(Is, A), 0 }, 590 /*1d*/ { "sbb", false, LONG, op2(Is, A), 0 }, 591 /*1e*/ { "push", false, NONE, op1(Si), 0 }, 592 /*1f*/ { "pop", false, NONE, op1(Si), 0 }, 593 594 /*20*/ { "and", true, BYTE, op2(R, E), 0 }, 595 /*21*/ { "and", true, LONG, op2(R, E), 0 }, 596 /*22*/ { "and", true, BYTE, op2(E, R), 0 }, 597 /*23*/ { "and", true, LONG, op2(E, R), 0 }, 598 /*24*/ { "and", false, BYTE, op2(I, A), 0 }, 599 /*25*/ { "and", false, LONG, op2(I, A), 0 }, 600 /*26*/ { "", false, NONE, 0, 0 }, 601 /*27*/ { "aaa", false, NONE, 0, 0 }, 602 603 /*28*/ { "sub", true, BYTE, op2(R, E), 0 }, 604 /*29*/ { "sub", true, LONG, op2(R, E), 0 }, 605 /*2a*/ { "sub", true, BYTE, op2(E, R), 0 }, 606 /*2b*/ { "sub", true, LONG, op2(E, R), 0 }, 607 /*2c*/ { "sub", false, BYTE, op2(Is, A), 0 }, 608 /*2d*/ { "sub", false, LONG, op2(Is, A), 0 }, 609 /*2e*/ { "", false, NONE, 0, 0 }, 610 /*2f*/ { "das", false, NONE, 0, 0 }, 611 612 /*30*/ { "xor", true, BYTE, op2(R, E), 0 }, 613 /*31*/ { "xor", true, LONG, op2(R, E), 0 }, 614 /*32*/ { "xor", true, BYTE, op2(E, R), 0 }, 615 /*33*/ { "xor", true, LONG, op2(E, R), 0 }, 616 /*34*/ { "xor", false, BYTE, op2(I, A), 0 }, 617 /*35*/ { "xor", false, LONG, op2(I, A), 0 }, 618 /*36*/ { "", false, NONE, 0, 0 }, 619 /*37*/ { "daa", false, NONE, 0, 0 }, 620 621 /*38*/ { "cmp", true, BYTE, op2(R, E), 0 }, 622 /*39*/ { "cmp", true, LONG, op2(R, E), 0 }, 623 /*3a*/ { "cmp", true, BYTE, op2(E, R), 0 }, 624 /*3b*/ { "cmp", true, LONG, op2(E, R), 0 }, 625 /*3c*/ { "cmp", false, BYTE, op2(Is, A), 0 }, 626 /*3d*/ { "cmp", false, LONG, op2(Is, A), 0 }, 627 /*3e*/ { "", false, NONE, 0, 0 }, 628 /*3f*/ { "aas", false, NONE, 0, 0 }, 629 630 /*40*/ { "inc", false, LONG, op1(Ri), 0 }, 631 /*41*/ { "inc", false, LONG, op1(Ri), 0 }, 632 /*42*/ { "inc", false, LONG, op1(Ri), 0 }, 633 /*43*/ { "inc", false, LONG, op1(Ri), 0 }, 634 /*44*/ { "inc", false, LONG, op1(Ri), 0 }, 635 /*45*/ { "inc", false, LONG, op1(Ri), 0 }, 636 /*46*/ { "inc", false, LONG, op1(Ri), 0 }, 637 /*47*/ { "inc", false, LONG, op1(Ri), 0 }, 638 639 /*48*/ { "dec", false, LONG, op1(Ri), 0 }, 640 /*49*/ { "dec", false, LONG, op1(Ri), 0 }, 641 /*4a*/ { "dec", false, LONG, op1(Ri), 0 }, 642 /*4b*/ { "dec", false, LONG, op1(Ri), 0 }, 643 /*4c*/ { "dec", false, LONG, op1(Ri), 0 }, 644 /*4d*/ { "dec", false, LONG, op1(Ri), 0 }, 645 /*4e*/ { "dec", false, LONG, op1(Ri), 0 }, 646 /*4f*/ { "dec", false, LONG, op1(Ri), 0 }, 647 648 /*50*/ { "push", false, QUAD, op1(Ri), 0 }, 649 /*51*/ { "push", false, QUAD, op1(Ri), 0 }, 650 /*52*/ { "push", false, QUAD, op1(Ri), 0 }, 651 /*53*/ { "push", false, QUAD, op1(Ri), 0 }, 652 /*54*/ { "push", false, QUAD, op1(Ri), 0 }, 653 /*55*/ { "push", false, QUAD, op1(Ri), 0 }, 654 /*56*/ { "push", false, QUAD, op1(Ri), 0 }, 655 /*57*/ { "push", false, QUAD, op1(Ri), 0 }, 656 657 /*58*/ { "pop", false, QUAD, op1(Ri), 0 }, 658 /*59*/ { "pop", false, QUAD, op1(Ri), 0 }, 659 /*5a*/ { "pop", false, QUAD, op1(Ri), 0 }, 660 /*5b*/ { "pop", false, QUAD, op1(Ri), 0 }, 661 /*5c*/ { "pop", false, QUAD, op1(Ri), 0 }, 662 /*5d*/ { "pop", false, QUAD, op1(Ri), 0 }, 663 /*5e*/ { "pop", false, QUAD, op1(Ri), 0 }, 664 /*5f*/ { "pop", false, QUAD, op1(Ri), 0 }, 665 666 /*60*/ { "pusha", false, LONG, 0, 0 }, 667 /*61*/ { "popa", false, LONG, 0, 0 }, 668 /*62*/ { "bound", true, LONG, op2(E, R), 0 }, 669 #if 0 670 /*63*/ { "arpl", true, NONE, op2(Ew,Rw), 0 },/* XXX in 32 bit mode */ 671 #else 672 /*63*/ { "movslq",true, NONE, op2(Ed, R), 0 },/* aka MOVSXD, in 64bit mode */ 673 #endif 674 675 /*64*/ { "", false, NONE, 0, 0 }, 676 /*65*/ { "", false, NONE, 0, 0 }, 677 /*66*/ { "", false, NONE, 0, 0 }, 678 /*67*/ { "", false, NONE, 0, 0 }, 679 680 /*68*/ { "push", false, LONG, op1(I), 0 }, 681 /*69*/ { "imul", true, LONG, op3(I,E,R), 0 }, 682 /*6a*/ { "push", false, LONG, op1(Ib), 0 }, 683 /*6b*/ { "imul", true, LONG, op3(Ibs,E,R),0 }, 684 /*6c*/ { "ins", false, BYTE, op2(DX, DI), 0 }, 685 /*6d*/ { "ins", false, LONG, op2(DX, DI), 0 }, 686 /*6e*/ { "outs", false, BYTE, op2(SI, DX), 0 }, 687 /*6f*/ { "outs", false, LONG, op2(SI, DX), 0 }, 688 689 /*70*/ { "jo", false, NONE, op1(Db), 0 }, 690 /*71*/ { "jno", false, NONE, op1(Db), 0 }, 691 /*72*/ { "jb", false, NONE, op1(Db), 0 }, 692 /*73*/ { "jnb", false, NONE, op1(Db), 0 }, 693 /*74*/ { "jz", false, NONE, op1(Db), 0 }, 694 /*75*/ { "jnz", false, NONE, op1(Db), 0 }, 695 /*76*/ { "jbe", false, NONE, op1(Db), 0 }, 696 /*77*/ { "jnbe", false, NONE, op1(Db), 0 }, 697 698 /*78*/ { "js", false, NONE, op1(Db), 0 }, 699 /*79*/ { "jns", false, NONE, op1(Db), 0 }, 700 /*7a*/ { "jp", false, NONE, op1(Db), 0 }, 701 /*7b*/ { "jnp", false, NONE, op1(Db), 0 }, 702 /*7c*/ { "jl", false, NONE, op1(Db), 0 }, 703 /*7d*/ { "jnl", false, NONE, op1(Db), 0 }, 704 /*7e*/ { "jle", false, NONE, op1(Db), 0 }, 705 /*7f*/ { "jnle", false, NONE, op1(Db), 0 }, 706 707 /*80*/ { "", true, BYTE, op2(I, E), (const char *)db_Grp1 }, 708 /*81*/ { "", true, LONG, op2(I, E), (const char *)db_Grp1 }, 709 /*82*/ { "", true, BYTE, op2(Is,E), (const char *)db_Grp1 }, 710 /*83*/ { "", true, LONG, op2(Ibs,E), (const char *)db_Grp1 }, 711 /*84*/ { "test", true, BYTE, op2(R, E), 0 }, 712 /*85*/ { "test", true, LONG, op2(R, E), 0 }, 713 /*86*/ { "xchg", true, BYTE, op2(R, E), 0 }, 714 /*87*/ { "xchg", true, LONG, op2(R, E), 0 }, 715 716 /*88*/ { "mov", true, BYTE, op2(R, E), 0 }, 717 /*89*/ { "mov", true, LONG, op2(R, E), 0 }, 718 /*8a*/ { "mov", true, BYTE, op2(E, R), 0 }, 719 /*8b*/ { "mov", true, LONG, op2(E, R), 0 }, 720 /*8c*/ { "mov", true, NONE, op2(S, Ew), 0 }, 721 /*8d*/ { "lea", true, LONG, op2(E, R), 0 }, 722 /*8e*/ { "mov", true, NONE, op2(Ew, S), 0 }, 723 /*8f*/ { "pop", true, LONG, op1(E), 0 }, 724 725 /*90*/ { "nop", false, NONE, 0, 0 }, 726 /*91*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 727 /*92*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 728 /*93*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 729 /*94*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 730 /*95*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 731 /*96*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 732 /*97*/ { "xchg", false, LONG, op2(A, Ri), 0 }, 733 734 /*98*/ { "cbw", false, SDEP, 0, "cwde" }, /* cbw/cwde */ 735 /*99*/ { "cwd", false, SDEP, 0, "cdq" }, /* cwd/cdq */ 736 /*9a*/ { "lcall", false, NONE, op1(OS), 0 }, 737 /*9b*/ { "wait", false, NONE, 0, 0 }, 738 /*9c*/ { "pushf", false, LONG, 0, 0 }, 739 /*9d*/ { "popf", false, LONG, 0, 0 }, 740 /*9e*/ { "sahf", false, NONE, 0, 0 }, 741 /*9f*/ { "lahf", false, NONE, 0, 0 }, 742 743 /*a0*/ { "mov", false, BYTE, op2(O, A), 0 }, 744 /*a1*/ { "mov", false, LONG, op2(O, A), 0 }, 745 /*a2*/ { "mov", false, BYTE, op2(A, O), 0 }, 746 /*a3*/ { "mov", false, LONG, op2(A, O), 0 }, 747 /*a4*/ { "movs", false, BYTE, op2(SI,DI), 0 }, 748 /*a5*/ { "movs", false, LONG, op2(SI,DI), 0 }, 749 /*a6*/ { "cmps", false, BYTE, op2(SI,DI), 0 }, 750 /*a7*/ { "cmps", false, LONG, op2(SI,DI), 0 }, 751 752 /*a8*/ { "test", false, BYTE, op2(I, A), 0 }, 753 /*a9*/ { "test", false, LONG, op2(I, A), 0 }, 754 /*aa*/ { "stos", false, BYTE, op1(DI), 0 }, 755 /*ab*/ { "stos", false, LONG, op1(DI), 0 }, 756 /*ac*/ { "lods", false, BYTE, op1(SI), 0 }, 757 /*ad*/ { "lods", false, LONG, op1(SI), 0 }, 758 /*ae*/ { "scas", false, BYTE, op1(SI), 0 }, 759 /*af*/ { "scas", false, LONG, op1(SI), 0 }, 760 761 /*b0*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 762 /*b1*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 763 /*b2*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 764 /*b3*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 765 /*b4*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 766 /*b5*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 767 /*b6*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 768 /*b7*/ { "mov", false, BYTE, op2(I, Ri), 0 }, 769 770 /*b8*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 771 /*b9*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 772 /*ba*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 773 /*bb*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 774 /*bc*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 775 /*bd*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 776 /*be*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 777 /*bf*/ { "mov", false, LONG, op2(Iq, Ri), 0 }, 778 779 /*c0*/ { "", true, BYTE, op2(Ib, E), (const char *)db_Grp2 }, 780 /*c1*/ { "", true, LONG, op2(Ib, E), (const char *)db_Grp2 }, 781 /*c2*/ { "ret", false, NONE, op1(Iw), 0 }, 782 /*c3*/ { "ret", false, NONE, 0, 0 }, 783 /*c4*/ { "les", true, LONG, op2(E, R), 0 }, 784 /*c5*/ { "lds", true, LONG, op2(E, R), 0 }, 785 /*c6*/ { "mov", true, BYTE, op2(I, E), 0 }, 786 /*c7*/ { "mov", true, LONG, op2(I, E), 0 }, 787 788 /*c8*/ { "enter", false, NONE, op2(Ib, Iw), 0 }, 789 /*c9*/ { "leave", false, NONE, 0, 0 }, 790 /*ca*/ { "lret", false, NONE, op1(Iw), 0 }, 791 /*cb*/ { "lret", false, NONE, 0, 0 }, 792 /*cc*/ { "int", false, NONE, op1(o3), 0 }, 793 /*cd*/ { "int", false, NONE, op1(Ib), 0 }, 794 /*ce*/ { "into", false, NONE, 0, 0 }, 795 /*cf*/ { "iret", false, NONE, 0, 0 }, 796 797 /*d0*/ { "", true, BYTE, op2(o1, E), (const char *)db_Grp2 }, 798 /*d1*/ { "", true, LONG, op2(o1, E), (const char *)db_Grp2 }, 799 /*d2*/ { "", true, BYTE, op2(CL, E), (const char *)db_Grp2 }, 800 /*d3*/ { "", true, LONG, op2(CL, E), (const char *)db_Grp2 }, 801 /*d4*/ { "aam", true, NONE, 0, 0 }, 802 /*d5*/ { "aad", true, NONE, 0, 0 }, 803 /*d6*/ { "", false, NONE, 0, 0 }, 804 /*d7*/ { "xlat", false, BYTE, op1(BX), 0 }, 805 806 /*d8*/ { "", true, NONE, 0, (const char *)db_Esc8 }, 807 /*d9*/ { "", true, NONE, 0, (const char *)db_Esc9 }, 808 /*da*/ { "", true, NONE, 0, (const char *)db_Esca }, 809 /*db*/ { "", true, NONE, 0, (const char *)db_Escb }, 810 /*dc*/ { "", true, NONE, 0, (const char *)db_Escc }, 811 /*dd*/ { "", true, NONE, 0, (const char *)db_Escd }, 812 /*de*/ { "", true, NONE, 0, (const char *)db_Esce }, 813 /*df*/ { "", true, NONE, 0, (const char *)db_Escf }, 814 815 /*e0*/ { "loopne",false, NONE, op1(Db), 0 }, 816 /*e1*/ { "loope", false, NONE, op1(Db), 0 }, 817 /*e2*/ { "loop", false, NONE, op1(Db), 0 }, 818 /*e3*/ { "jcxz", false, SDEP, op1(Db), "jecxz" }, 819 /*e4*/ { "in", false, BYTE, op2(Ib, A), 0 }, 820 /*e5*/ { "in", false, LONG, op2(Ib, A) , 0 }, 821 /*e6*/ { "out", false, BYTE, op2(A, Ib), 0 }, 822 /*e7*/ { "out", false, LONG, op2(A, Ib) , 0 }, 823 824 /*e8*/ { "call", false, NONE, op1(Dl), 0 }, 825 /*e9*/ { "jmp", false, NONE, op1(Dl), 0 }, 826 /*ea*/ { "ljmp", false, NONE, op1(OS), 0 }, 827 /*eb*/ { "jmp", false, NONE, op1(Db), 0 }, 828 /*ec*/ { "in", false, BYTE, op2(DX, A), 0 }, 829 /*ed*/ { "in", false, LONG, op2(DX, A) , 0 }, 830 /*ee*/ { "out", false, BYTE, op2(A, DX), 0 }, 831 /*ef*/ { "out", false, LONG, op2(A, DX) , 0 }, 832 833 /*f0*/ { "", false, NONE, 0, 0 }, 834 /*f1*/ { "", false, NONE, 0, 0 }, 835 /*f2*/ { "", false, NONE, 0, 0 }, 836 /*f3*/ { "", false, NONE, 0, 0 }, 837 /*f4*/ { "hlt", false, NONE, 0, 0 }, 838 /*f5*/ { "cmc", false, NONE, 0, 0 }, 839 /*f6*/ { "", true, BYTE, 0, (const char *)db_Grp3 }, 840 /*f7*/ { "", true, LONG, 0, (const char *)db_Grp3 }, 841 842 /*f8*/ { "clc", false, NONE, 0, 0 }, 843 /*f9*/ { "stc", false, NONE, 0, 0 }, 844 /*fa*/ { "cli", false, NONE, 0, 0 }, 845 /*fb*/ { "sti", false, NONE, 0, 0 }, 846 /*fc*/ { "cld", false, NONE, 0, 0 }, 847 /*fd*/ { "std", false, NONE, 0, 0 }, 848 /*fe*/ { "", true, NONE, 0, (const char *)db_Grp4 }, 849 /*ff*/ { "", true, NONE, 0, (const char *)db_Grp5 }, 850 }; 851 852 const struct inst db_bad_inst = 853 { "???", false, NONE, 0, 0 } 854 ; 855 856 #define f_mod(byte) ((byte)>>6) 857 #define f_reg(byte) (((byte)>>3)&0x7) 858 #define f_rm(byte) ((byte)&0x7) 859 860 #define sib_ss(byte) ((byte)>>6) 861 #define sib_index(byte) (((byte)>>3)&0x7) 862 #define sib_base(byte) ((byte)&0x7) 863 864 struct i_addr { 865 int is_reg; /* if reg, reg number is in 'disp' */ 866 int disp; 867 const char * base; 868 const char * index; 869 int ss; 870 }; 871 872 const char * const db_index_reg_32[8] = { 873 "%ebx,%esi", 874 "%ebx,%edi", 875 "%ebp,%esi", 876 "%ebp,%edi", 877 "%esi", 878 "%edi", 879 "%ebp", 880 "%ebx" 881 }; 882 883 #define DB_REG_DFLT 0 884 #define DB_REG_REX 1 885 886 const char * const db_reg[2][4][8] = { 887 { 888 { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" }, 889 { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" }, 890 { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" }, 891 { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi" } 892 }, { 893 { "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" }, 894 { "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" }, 895 { "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" }, 896 { "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" } 897 }}; 898 899 const char * const db_seg_reg[8] = { 900 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" 901 }; 902 903 /* 904 * lengths for size attributes 905 */ 906 const int db_lengths[] = { 907 1, /* BYTE */ 908 2, /* WORD */ 909 4, /* LONG */ 910 4, /* QUAD - 64bit immediates are done by Iq */ 911 4, /* SNGL */ 912 8, /* DBLR */ 913 10, /* EXTR */ 914 }; 915 916 #define REX 0x00 917 #define REX_b 0x01 918 #define REX_x 0x02 919 #define REX_xb 0x03 920 #define REX_r 0x04 921 #define REX_rb 0x05 922 #define REX_rx 0x06 923 #define REX_rxb 0x07 924 #define REX_w 0x08 925 #define REX_wb 0x09 926 #define REX_wx 0x0a 927 #define REX_wxb 0x0b 928 #define REX_wr 0x0c 929 #define REX_wrb 0x0d 930 #define REX_wrx 0x0e 931 #define REX_wrxb 0x0f 932 933 const char * const rex_str[0x10] = { 934 "rex ", /* 0x40 */ 935 "rex.b ", /* 0x41 */ 936 "rex.x ", /* 0x42 */ 937 "rex.xb ", /* 0x43 */ 938 "rex.r ", /* 0x44 */ 939 "rex.rb ", /* 0x45 */ 940 "rex.rx ", /* 0x46 */ 941 "rex.rxb ", /* 0x47 */ 942 "rex.w ", /* 0x48 */ 943 "rex.wb ", /* 0x49 */ 944 "rex.wx ", /* 0x4a */ 945 "rex.wxb ", /* 0x4b */ 946 "rex.wr ", /* 0x4c */ 947 "rex.wrb ", /* 0x4d */ 948 "rex.wrx ", /* 0x4e */ 949 "rex.wrxb ", /* 0x4f */ 950 }; 951 952 #define get_value_inc(result, loc, size, is_signed) \ 953 do { \ 954 result = db_get_value((loc), (size), (is_signed)); \ 955 (loc) += (size); \ 956 } while (0) 957 958 959 db_addr_t db_read_address(db_addr_t, u_int, int, int, struct i_addr *); 960 void db_print_address(const char *, u_int, int, struct i_addr *); 961 db_addr_t db_disasm_esc(db_addr_t, int, u_int, int, int, const char *); 962 963 /* 964 * Read address at location and return updated location. 965 */ 966 db_addr_t 967 db_read_address(db_addr_t loc, u_int rex, int short_addr, int regmodrm, struct i_addr *addrp) 968 /* addrp: out */ 969 { 970 int mod, rm, sib, index, disp, ext; 971 972 mod = f_mod(regmodrm); 973 rm = f_rm(regmodrm); 974 975 if (mod == 3) { 976 addrp->is_reg = true; 977 addrp->disp = rm; 978 return (loc); 979 } 980 addrp->is_reg = false; 981 addrp->index = 0; 982 983 if (short_addr) { 984 /* x86_64 32 bit address mode */ 985 if (mod != 3 && rm == 4) { 986 ext = ((rex & REX_x) != 0); 987 get_value_inc(sib, loc, 1, false); 988 rm = sib_base(sib); 989 index = sib_index(sib); 990 if (index != 4) 991 addrp->index = db_reg[ext][LONG][index]; 992 addrp->ss = sib_ss(sib); 993 } 994 995 ext = ((rex & REX_b) != 0); 996 switch (mod) { 997 case 0: 998 if (rm == 5) { 999 get_value_inc(addrp->disp, loc, 4, false); 1000 addrp->base = 0; 1001 } else { 1002 addrp->disp = 0; 1003 addrp->base = db_reg[ext][LONG][rm]; 1004 } 1005 break; 1006 case 1: 1007 get_value_inc(disp, loc, 1, true); 1008 addrp->disp = disp; 1009 addrp->base = db_reg[ext][LONG][rm]; 1010 break; 1011 case 2: 1012 get_value_inc(disp, loc, 4, false); 1013 addrp->disp = disp; 1014 addrp->base = db_reg[ext][LONG][rm]; 1015 break; 1016 } 1017 } else { 1018 /* x86_64 64 bit address mode */ 1019 1020 if (mod != 3 && rm == 4) { 1021 ext = ((rex & REX_x) != 0); 1022 get_value_inc(sib, loc, 1, false); 1023 rm = sib_base(sib); 1024 index = sib_index(sib); 1025 if (index != 4) 1026 addrp->index = db_reg[ext][QUAD][index]; 1027 addrp->ss = sib_ss(sib); 1028 } 1029 1030 ext = ((rex & REX_b) != 0); 1031 switch (mod) { 1032 case 0: 1033 if (rm == 5) { 1034 /* x86_64 RIP-relative addressing */ 1035 get_value_inc(addrp->disp, loc, 4, false); 1036 addrp->base = "%rip"; 1037 } else { 1038 addrp->disp = 0; 1039 addrp->base = db_reg[ext][QUAD][rm]; 1040 } 1041 break; 1042 case 1: 1043 get_value_inc(disp, loc, 1, true); 1044 addrp->disp = disp; 1045 addrp->base = db_reg[ext][QUAD][rm]; 1046 break; 1047 case 2: 1048 get_value_inc(disp, loc, 4, false); 1049 addrp->disp = disp; 1050 addrp->base = db_reg[ext][QUAD][rm]; 1051 break; 1052 } 1053 } 1054 return (loc); 1055 } 1056 1057 void 1058 db_print_address(const char * seg, u_int rex, int size, struct i_addr *addrp) 1059 { 1060 if (addrp->is_reg) { 1061 int ext = ((rex & REX_b) != 0); 1062 db_printf("%s", db_reg[ext][size][addrp->disp]); 1063 return; 1064 } 1065 1066 if (seg) 1067 db_printf("%s:", seg); 1068 1069 db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, db_printf); 1070 1071 if (addrp->base != 0 || addrp->index != 0) { 1072 db_printf("("); 1073 if (addrp->base) 1074 db_printf("%s", addrp->base); 1075 if (addrp->index) 1076 db_printf(",%s,%d", addrp->index, 1<<addrp->ss); 1077 db_printf(")"); 1078 } 1079 } 1080 1081 /* 1082 * Disassemble floating-point ("escape") instruction 1083 * and return updated location. 1084 */ 1085 db_addr_t 1086 db_disasm_esc(db_addr_t loc, int inst, u_int rex, int short_addr, int size, const char * seg) 1087 { 1088 int regmodrm; 1089 const struct finst *fp; 1090 int mod; 1091 struct i_addr address; 1092 const char * name; 1093 1094 get_value_inc(regmodrm, loc, 1, false); 1095 fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; 1096 mod = f_mod(regmodrm); 1097 if (mod != 3) { 1098 /* 1099 * Normal address modes. 1100 */ 1101 loc = db_read_address(loc, rex, short_addr, regmodrm, &address); 1102 db_printf("%s", fp->f_name); 1103 switch(fp->f_size) { 1104 case SNGL: 1105 db_printf("s"); 1106 break; 1107 case DBLR: 1108 db_printf("l"); 1109 break; 1110 case EXTR: 1111 db_printf("t"); 1112 break; 1113 case WORD: 1114 db_printf("s"); 1115 break; 1116 case LONG: 1117 db_printf("l"); 1118 break; 1119 case QUAD: 1120 db_printf("q"); 1121 break; 1122 default: 1123 break; 1124 } 1125 db_printf("\t"); 1126 db_print_address(seg, rex, BYTE, &address); 1127 } else { 1128 /* 1129 * 'reg-reg' - special formats 1130 */ 1131 switch (fp->f_rrmode) { 1132 case op2(ST,STI): 1133 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1134 db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm)); 1135 break; 1136 case op2(STI,ST): 1137 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1138 db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm)); 1139 break; 1140 case op1(STI): 1141 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1142 db_printf("%s\t%%st(%d)",name, f_rm(regmodrm)); 1143 break; 1144 case op1(X): 1145 db_printf("%s", ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]); 1146 break; 1147 case op1(XA): 1148 db_printf("%s\t%%ax", 1149 ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]); 1150 break; 1151 default: 1152 db_printf("<bad instruction>"); 1153 break; 1154 } 1155 } 1156 1157 return (loc); 1158 } 1159 1160 /* 1161 * Disassemble instruction at 'loc'. 'altfmt' specifies an 1162 * (optional) alternate format. Return address of start of 1163 * next instruction. 1164 */ 1165 db_addr_t 1166 db_disasm(db_addr_t loc, bool altfmt) 1167 { 1168 int inst; 1169 int size; 1170 int short_addr; 1171 const char * seg; 1172 const struct inst * ip; 1173 const char * i_name; 1174 int i_size; 1175 int i_mode; 1176 int regmodrm = 0; 1177 bool first; 1178 int displ; 1179 int prefix; 1180 int imm; 1181 int imm2; 1182 uint64_t imm64; 1183 int len; 1184 struct i_addr address; 1185 #ifdef _KERNEL 1186 pt_entry_t *pte, *pde; 1187 #endif 1188 u_int rex = 0; 1189 1190 #ifdef _KERNEL 1191 /* 1192 * Don't try to disassemble the location if the mapping is invalid. 1193 * If we do, we'll fault, and end up debugging the debugger! 1194 * in the case of largepages, "pte" is really the pde and "pde" is 1195 * really the entry for the pdp itself. 1196 */ 1197 if ((vaddr_t)loc >= VM_MIN_KERNEL_ADDRESS) 1198 pte = kvtopte((vaddr_t)loc); 1199 else 1200 pte = vtopte((vaddr_t)loc); 1201 pde = vtopte((vaddr_t)pte); 1202 if ((*pde & PG_V) == 0 || (*pte & PG_V) == 0) { 1203 db_printf("invalid address\n"); 1204 return (loc); 1205 } 1206 #endif 1207 1208 get_value_inc(inst, loc, 1, false); 1209 short_addr = false; 1210 size = LONG; 1211 seg = 0; 1212 1213 /* 1214 * Get prefixes 1215 */ 1216 prefix = true; 1217 do { 1218 if ((inst & 0xf0) == 0x40) { 1219 rex |= inst; 1220 } else 1221 switch (inst) { 1222 case 0x66: /* data16 */ 1223 size = WORD; 1224 break; 1225 case 0x67: 1226 short_addr = true; 1227 break; 1228 case 0x26: 1229 seg = "%es"; 1230 break; 1231 case 0x36: 1232 seg = "%ss"; 1233 break; 1234 case 0x2e: 1235 seg = "%cs"; 1236 break; 1237 case 0x3e: 1238 seg = "%ds"; 1239 break; 1240 case 0x64: 1241 seg = "%fs"; 1242 break; 1243 case 0x65: 1244 seg = "%gs"; 1245 break; 1246 case 0xf0: 1247 db_printf("lock "); 1248 break; 1249 case 0xf2: 1250 db_printf("repne "); 1251 break; 1252 case 0xf3: 1253 db_printf("repe "); /* XXX repe VS rep */ 1254 break; 1255 default: 1256 prefix = false; 1257 break; 1258 } 1259 if (prefix) 1260 get_value_inc(inst, loc, 1, false); 1261 } while (prefix); 1262 1263 if (rex != 0) { 1264 if (rex & REX_w) 1265 size = QUAD; 1266 if (altfmt == true) /* XXX */ 1267 db_printf("%s", rex_str[rex & 0x0f]); 1268 } 1269 1270 if (inst >= 0xd8 && inst <= 0xdf) { 1271 loc = db_disasm_esc(loc, inst, rex, short_addr, size, seg); 1272 db_printf("\n"); 1273 return (loc); 1274 } 1275 1276 if (inst == 0x0f) { 1277 get_value_inc(inst, loc, 1, false); 1278 ip = db_inst_0f[inst>>4]; 1279 if (ip == 0) 1280 ip = &db_bad_inst; 1281 else 1282 ip = &ip[inst&0xf]; 1283 } else { 1284 ip = &db_inst_table[inst]; 1285 } 1286 1287 if (ip->i_has_modrm) { 1288 get_value_inc(regmodrm, loc, 1, false); 1289 loc = db_read_address(loc, rex, short_addr, regmodrm, &address); 1290 } 1291 1292 i_name = ip->i_name; 1293 i_size = ip->i_size; 1294 i_mode = ip->i_mode; 1295 1296 if (ip->i_extra == (const char *)db_Grp1 || 1297 ip->i_extra == (const char *)db_Grp2 || 1298 ip->i_extra == (const char *)db_Grp6 || 1299 ip->i_extra == (const char *)db_Grp7 || 1300 ip->i_extra == (const char *)db_Grp8 || 1301 ip->i_extra == (const char *)db_Grp9) { 1302 if (ip->i_extra == (const char *)db_Grp7 && regmodrm == 0xf8) { 1303 i_name = "swapgs"; 1304 i_mode = 0; 1305 } else { 1306 i_name = ((const char * const *)ip->i_extra) 1307 [f_reg(regmodrm)]; 1308 } 1309 } else if (ip->i_extra == (const char *)db_Grp3) { 1310 ip = (const struct inst *)ip->i_extra; 1311 ip = &ip[f_reg(regmodrm)]; 1312 i_name = ip->i_name; 1313 i_mode = ip->i_mode; 1314 } else if (ip->i_extra == (const char *)db_Grp4 || 1315 ip->i_extra == (const char *)db_Grp5) { 1316 ip = (const struct inst *)ip->i_extra; 1317 ip = &ip[f_reg(regmodrm)]; 1318 i_name = ip->i_name; 1319 i_mode = ip->i_mode; 1320 i_size = ip->i_size; 1321 } 1322 1323 if (i_size == SDEP) { 1324 if (size == WORD) 1325 db_printf("%s", i_name); 1326 else 1327 db_printf("%s", ip->i_extra); 1328 } else { 1329 db_printf("%s", i_name); 1330 if (i_size != NONE) { 1331 if (i_size == BYTE) { 1332 db_printf("b"); 1333 size = BYTE; 1334 } else if (i_size == WORD) { 1335 db_printf("w"); 1336 size = WORD; 1337 } else if (size == WORD) { 1338 db_printf("w"); 1339 } else if (i_size == QUAD) { 1340 db_printf("q"); 1341 size = QUAD; 1342 } else if (size == QUAD) { 1343 db_printf("q"); 1344 } else { 1345 db_printf("l"); 1346 } 1347 } 1348 } 1349 db_printf("\t"); 1350 for (first = true; 1351 i_mode != 0; 1352 i_mode >>= 8, first = false) { 1353 char tbuf[24]; 1354 1355 if (!first) 1356 db_printf(","); 1357 1358 switch (i_mode & 0xFF) { 1359 case E: 1360 db_print_address(seg, rex, size, &address); 1361 break; 1362 case Eind: 1363 db_printf("*"); 1364 db_print_address(seg, rex, size, &address); 1365 break; 1366 case Ed: 1367 db_print_address(seg, rex, LONG, &address); 1368 break; 1369 case Ew: 1370 db_print_address(seg, rex, WORD, &address); 1371 break; 1372 case Eb: 1373 db_print_address(seg, rex, BYTE, &address); 1374 break; 1375 case R: { 1376 int ext = ((rex & REX_r) != 0); 1377 db_printf("%s", db_reg[ext][size][f_reg(regmodrm)]); 1378 break; 1379 } 1380 case Rw: { 1381 int ext = ((rex & REX_r) != 0); 1382 db_printf("%s", db_reg[ext][WORD][f_reg(regmodrm)]); 1383 break; 1384 } 1385 case Ri: { 1386 int ext = ((rex & REX_b) != 0); 1387 db_printf("%s", db_reg[ext][size][f_rm(inst)]); 1388 break; 1389 } 1390 case S: 1391 db_printf("%s", db_seg_reg[f_reg(regmodrm)]); 1392 break; 1393 case Si: 1394 db_printf("%s", db_seg_reg[f_reg(inst)]); 1395 break; 1396 case A: { 1397 int ext = ((rex & REX_w) != 0); 1398 db_printf("%s", db_reg[ext][size][0]); /* acc */ 1399 break; 1400 } 1401 case BX: 1402 if (seg) 1403 db_printf("%s:", seg); 1404 db_printf("(%s)", short_addr ? "%ebx" : "%rbx"); 1405 break; 1406 case CL: 1407 db_printf("%%cl"); 1408 break; 1409 case DX: 1410 db_printf("%%dx"); 1411 break; 1412 case SI: 1413 if (seg) 1414 db_printf("%s:", seg); 1415 db_printf("(%s)", short_addr ? "%esi" : "%rsi"); 1416 break; 1417 case DI: 1418 db_printf("%%es:(%s)", short_addr ? "%edi" : "%rdi"); 1419 break; 1420 case CR: 1421 db_printf("%%cr%d", f_reg(regmodrm)); 1422 break; 1423 case DR: 1424 db_printf("%%dr%d", f_reg(regmodrm)); 1425 break; 1426 case TR: 1427 db_printf("%%tr%d", f_reg(regmodrm)); 1428 break; 1429 case Iq: 1430 if (size == QUAD) { 1431 get_value_inc(imm64, loc, 8, false); 1432 db_format_radix(tbuf, 24, imm64, true); 1433 db_printf("$%s", tbuf); 1434 break; 1435 } 1436 case I: 1437 len = db_lengths[size]; 1438 get_value_inc(imm, loc, len, false);/* unsigned */ 1439 db_format_radix(tbuf, 24, (unsigned int)imm, true); 1440 db_printf("$%s", tbuf); 1441 break; 1442 case Is: 1443 len = db_lengths[size]; 1444 get_value_inc(imm, loc, len, true); /* signed */ 1445 db_format_radix(tbuf, 24, imm, true); 1446 db_printf("$%s", tbuf); 1447 break; 1448 case Ib: 1449 get_value_inc(imm, loc, 1, false); /* unsigned */ 1450 db_format_radix(tbuf, 24, (unsigned int)imm, true); 1451 db_printf("$%s", tbuf); 1452 break; 1453 case Ibs: 1454 get_value_inc(imm, loc, 1, true); /* signed */ 1455 db_format_radix(tbuf, 24, imm, true); 1456 db_printf("$%s", tbuf); 1457 break; 1458 case Iw: 1459 get_value_inc(imm, loc, 2, false); /* unsigned */ 1460 db_format_radix(tbuf, 24, (unsigned int)imm, true); 1461 db_printf("$%s", tbuf); 1462 break; 1463 case Il: 1464 get_value_inc(imm, loc, 4, false); 1465 db_format_radix(tbuf, 24, (unsigned int)imm, true); 1466 db_printf("$%s", tbuf); 1467 break; 1468 case O: /* Only move %eax to/from absolute address */ 1469 if (short_addr) 1470 get_value_inc(imm64, loc, 2, true); 1471 else 1472 get_value_inc(imm64, loc, 8, true); 1473 if (seg) { 1474 db_format_radix(tbuf, 24, imm64, true); 1475 db_printf("%s:%s", seg, tbuf); 1476 } else 1477 db_printsym((db_addr_t)imm64, DB_STGY_ANY, 1478 db_printf); 1479 break; 1480 case Db: 1481 get_value_inc(displ, loc, 1, true); 1482 db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN, 1483 db_printf); 1484 break; 1485 case Dl: 1486 get_value_inc(displ, loc, 4, true); 1487 db_printsym((db_addr_t)(displ + loc), DB_STGY_XTRN, 1488 db_printf); 1489 break; 1490 case o1: 1491 db_printf("$1"); 1492 break; 1493 case o3: 1494 db_printf("$3"); 1495 break; 1496 case OS: 1497 get_value_inc(imm, loc, 4, false); /* offset */ 1498 db_format_radix(tbuf, 24, (unsigned int)imm, true); 1499 db_printf("$%s", tbuf); 1500 get_value_inc(imm2, loc, 2, false); /* segment */ 1501 db_format_radix(tbuf, 24, (unsigned int)imm2, true); 1502 db_printf(",%s", tbuf); 1503 break; 1504 } 1505 } 1506 1507 db_printf("\n"); 1508 return (loc); 1509 } 1510