├── README.md ├── h8 ├── LICENSE ├── ana.cpp ├── emu.cpp ├── h8.cfg ├── h8.hpp ├── ins.cpp ├── ins.hpp ├── makefile ├── out.cpp └── reg.cpp ├── insn_trace.py ├── lgebd ├── lgebd.cpp ├── lgebd.hpp └── makefile ├── openssl ├── .gitignore ├── README.md ├── build_til.sh ├── empty │ ├── errno.h │ ├── limits.h │ ├── stdarg.h │ ├── stddef.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── sys │ │ ├── time.h │ │ └── types.h │ └── time.h ├── gcc32.cfg ├── gcc64.cfg └── openssl_all.h ├── rsrc.py └── zlibdll ├── .gitignore ├── README.md ├── zlib114dll.exc ├── zlibdll-vc32.cfg ├── zlibdll.h └── zlibdll.sh /README.md: -------------------------------------------------------------------------------- 1 | ida 2 | === 3 | 4 | Miscellaneous IDA scripts and projects 5 | -------------------------------------------------------------------------------- /h8/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT is license used for this processor module with written permission from Hex-Rays. 2 | 3 | --- 4 | 5 | Copyright (C) 2013 Hex-Rays, Michael Mohr 6 | 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | -------------------------------------------------------------------------------- /h8/emu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-99 by Ilfak Guilfanov. 4 | * ALL RIGHTS RESERVED. 5 | * E-mail: ig@datarescue.com 6 | * 7 | * 8 | */ 9 | 10 | #include "h8.hpp" 11 | #include 12 | #include 13 | 14 | static bool flow; 15 | static bool check_for_table_jump(void); 16 | static bool check_for_generic_indirect_jump(void); 17 | static bool check_for_generic_indirect_call(void); 18 | //------------------------------------------------------------------------ 19 | static void process_immediate_number(int n) 20 | { 21 | doImmd(cmd.ea); 22 | if ( isDefArg(uFlag,n) ) 23 | return; 24 | switch ( cmd.itype ) 25 | { 26 | case H8_shal: 27 | case H8_shar: 28 | case H8_shll: 29 | case H8_shlr: 30 | case H8_rotl: 31 | case H8_rotr: 32 | case H8_rotxl: 33 | case H8_rotxr: 34 | if ( n == 0 ) 35 | op_dec(cmd.ea, n); 36 | break; 37 | case H8_and: 38 | case H8_or: 39 | case H8_xor: 40 | op_num(cmd.ea, n); 41 | break; 42 | } 43 | } 44 | 45 | //---------------------------------------------------------------------- 46 | inline bool issp(int x) 47 | { 48 | return x == R7 || x == ER7; 49 | } 50 | 51 | inline bool isbp(int x) 52 | { 53 | return x == R6 || x == ER6; 54 | } 55 | 56 | //---------------------------------------------------------------------- 57 | int idaapi is_sp_based(const op_t &x) 58 | { 59 | return OP_SP_ADD 60 | | ((x.type == o_displ || x.type == o_phrase) && issp(x.phrase) 61 | ? OP_SP_BASED 62 | : OP_FP_BASED); 63 | } 64 | 65 | //---------------------------------------------------------------------- 66 | static void add_stkpnt(ssize_t value) 67 | { 68 | func_t *pfn = get_func(cmd.ea); 69 | if ( pfn == NULL ) 70 | return; 71 | 72 | if ( value & 1 ) 73 | value++; 74 | 75 | add_auto_stkpnt2(pfn, cmd.ea+cmd.size, value); 76 | } 77 | 78 | //---------------------------------------------------------------------- 79 | // Does the instruction in 'cmd' spoil any register from 'regs'? 80 | // Only o_phrase operand with not ph_normal types are consulted 81 | static bool is_reg_spoiled_by_phrase(const uint32 *regs, size_t n) 82 | { 83 | for ( size_t i=0; i < UA_MAXOP; i++ ) 84 | { 85 | if ( cmd.Operands[i].type == o_phrase 86 | && cmd.Operands[i].phtype != ph_normal 87 | && (cmd.get_canon_feature() & (CF_USE1<= 0 177 | || is_reg_spoiled_by_phrase(spoil_list, spoil_sz) 178 | || is_complex_insn(reg); 179 | } 180 | 181 | //---------------------------------------------------------------------- 182 | static bool get_op_value(const op_t &x, uval_t *value, ea_t *base_addr = NULL) 183 | { 184 | if ( base_addr != NULL ) 185 | *base_addr = 0; 186 | 187 | if ( x.type == o_imm ) 188 | { 189 | *value = x.value; 190 | return true; 191 | } 192 | 193 | if ( x.type != o_reg 194 | && (x.type != o_displ 195 | || x.displtype != dt_normal && x.displtype != dt_regidx) 196 | && x.type != o_phrase 197 | && x.type != o_pcidx ) 198 | { 199 | return false; 200 | } 201 | uint16 reg = x.reg; 202 | 203 | bool ok = false; 204 | insn_t saved = cmd; 205 | ea_t next_ea = cmd.ea; 206 | while ( (!hasRef(get_flags_novalue(next_ea)) || get_first_cref_to(next_ea) == BADADDR) 207 | && decode_prev_insn(cmd.ea) != BADADDR ) 208 | { 209 | if ( cmd.itype == H8_mov 210 | && cmd.Op1.type == o_imm 211 | && cmd.Op2.type == o_reg 212 | && cmd.Op2.reg == reg ) 213 | { 214 | *value = cmd.Op1.value; 215 | ok = true; 216 | break; 217 | } 218 | 219 | if ( is_reg_spoiled(reg) ) 220 | break; 221 | 222 | next_ea = cmd.ea; 223 | } 224 | cmd = saved; 225 | 226 | if ( ok ) 227 | { 228 | if ( x.type == o_phrase ) 229 | { 230 | if ( x.phtype == ph_pre_inc ) 231 | *value += 1; 232 | else if ( x.phtype == ph_pre_dec ) 233 | *value -= 1; 234 | } 235 | else if ( x.type == o_displ ) 236 | { 237 | if ( x.displtype == dt_regidx ) 238 | { 239 | if ( (cmd.auxpref == aux_long) != 0 ) 240 | *value <<= 2; 241 | else if ( (cmd.auxpref == aux_word) != 0 ) 242 | *value <<= 1; 243 | } 244 | // if the offset from the base is greater than the base address 245 | // then they are most likely swapped around, so swap them back here 246 | if ( base_addr != NULL ) 247 | *base_addr = x.addr > *value ? x.addr : *value; 248 | *value += x.addr; 249 | } 250 | } 251 | else 252 | { 253 | if ( x.type == o_displ ) 254 | { 255 | *value = x.addr; 256 | ok = true; 257 | } 258 | } 259 | 260 | return ok; 261 | } 262 | 263 | //---------------------------------------------------------------------- 264 | static void trace_sp(void) 265 | { 266 | // @sp++ 267 | if ( cmd.Op1.type == o_phrase 268 | && issp(cmd.Op1.reg) 269 | && cmd.Op1.phtype == ph_post_inc ) 270 | { 271 | ssize_t size = get_dtyp_size(cmd.Op2.dtyp); 272 | if ( cmd.Op2.type == o_reglist ) 273 | size *= cmd.Op2.nregs; 274 | add_stkpnt(size); 275 | return; 276 | } 277 | 278 | // @--sp 279 | if ( cmd.Op2.type == o_phrase 280 | && issp(cmd.Op2.reg) 281 | && cmd.Op2.phtype == ph_pre_dec ) 282 | { 283 | ssize_t size = get_dtyp_size(cmd.Op1.dtyp); 284 | if ( cmd.Op1.type == o_reglist ) 285 | size *= cmd.Op1.nregs; 286 | add_stkpnt(-size); 287 | return; 288 | } 289 | 290 | uval_t v; 291 | switch ( cmd.itype ) 292 | { 293 | case H8_add: 294 | case H8_adds: 295 | if ( !issp(cmd.Op2.reg) ) 296 | break; 297 | if ( get_op_value(cmd.Op1, &v) ) 298 | add_stkpnt(v); 299 | break; 300 | case H8_sub: 301 | case H8_subs: 302 | if ( !issp(cmd.Op2.reg) ) 303 | break; 304 | if ( get_op_value(cmd.Op1, &v) ) 305 | add_stkpnt(0-v); 306 | break; 307 | case H8_push: 308 | add_stkpnt(0-get_dtyp_size(cmd.Op1.dtyp)); 309 | break; 310 | case H8_pop: 311 | add_stkpnt( get_dtyp_size(cmd.Op1.dtyp)); 312 | break; 313 | } 314 | } 315 | 316 | //---------------------------------------------------------------------- 317 | static void add_code_xref(const op_t &x, ea_t ea) 318 | { 319 | cref_t ftype = fl_JN; 320 | if ( InstrIsSet(cmd.itype, CF_CALL) ) 321 | { 322 | if ( !func_does_return(ea) ) 323 | flow = false; 324 | ftype = fl_CN; 325 | } 326 | ua_add_cref(x.offb, ea, ftype); 327 | } 328 | 329 | //---------------------------------------------------------------------- 330 | static void handle_operand(const op_t &x, bool is_forced, bool isload) 331 | { 332 | uval_t op_value; 333 | 334 | switch ( x.type ) 335 | { 336 | case o_reg: 337 | case o_reglist: 338 | return; 339 | 340 | case o_imm: 341 | QASSERT(10094, isload); 342 | process_immediate_number(x.n); 343 | if ( op_adds_xrefs(uFlag, x.n) ) 344 | ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN|OOFW_IMM); 345 | break; 346 | 347 | case o_phrase: 348 | if ( is_forced ) 349 | break; 350 | if ( !isDefArg(uFlag,x.n) && get_op_value(x, &op_value) ) 351 | { 352 | op_offset(cmd.ea, x.n, REF_OFF32, op_value); 353 | } 354 | if ( op_adds_xrefs(uFlag, x.n) ) 355 | { 356 | ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, get_displ_outf(x)); 357 | if ( ea != BADADDR ) 358 | { 359 | ua_dodata2(x.offb, ea, x.dtyp); 360 | if ( !isload ) 361 | doVar(ea); 362 | } 363 | } 364 | break; 365 | 366 | case o_displ: 367 | if ( is_forced ) 368 | break; 369 | if ( op_adds_xrefs(uFlag, x.n) ) 370 | { 371 | ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, get_displ_outf(x)); 372 | if ( ea != BADADDR ) 373 | { 374 | ua_dodata2(x.offb, ea, x.dtyp); 375 | if ( !isload ) 376 | doVar(ea); 377 | } 378 | if ( (x.flags & OF_OUTER_DISP) != 0 ) 379 | { 380 | ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, OOF_OUTER | OOF_SIGNED | OOFW_32); 381 | if ( ea != BADADDR ) 382 | { 383 | ua_dodata2(x.offo, ea, x.szfl & idx_byte ? dt_byte : dt_word); 384 | if ( !isload ) 385 | doVar(ea); 386 | } 387 | } 388 | } 389 | // create stack variables if required 390 | if ( may_create_stkvars() && !isDefArg(uFlag, x.n) ) 391 | { 392 | func_t *pfn = get_func(cmd.ea); 393 | if ( pfn != NULL 394 | && (issp(x.phrase) 395 | || isbp(x.phrase) && (pfn->flags & FUNC_FRAME) != 0) ) 396 | { 397 | if ( ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) 398 | op_stkvar(cmd.ea, x.n); 399 | } 400 | } 401 | break; 402 | case o_near: 403 | add_code_xref(x, calc_mem(x.addr)); 404 | break; 405 | case o_mem: 406 | { 407 | ea_t ea = x.memtype == mem_sbr ? 408 | calc_mem_sbr_based(x.addr) : 409 | calc_mem(x.addr); 410 | if ( !isEnabled(ea) && find_sym(ea) ) 411 | break; // address not here 412 | ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); 413 | ua_dodata2(x.offb, ea, x.dtyp); 414 | if ( x.memtype == mem_ind || x.memtype == mem_vec7 ) 415 | { 416 | ssize_t size = get_dtyp_size(x.dtyp); 417 | flags_t F = getFlags(ea); 418 | if ( (isWord(F) || isDwrd(F)) 419 | && (!isDefArg0(F) || isOff0(F)) ) 420 | { 421 | ea_t target = calc_mem(size == 2 422 | ? get_word(ea) 423 | : trim_ea_branch(get_long(ea))); 424 | if ( isEnabled(target) ) 425 | add_code_xref(x, target); 426 | if ( !isOff0(F) ) 427 | set_offset(ea, 0, calc_mem(0)); 428 | } 429 | break; 430 | } 431 | if ( !isload ) 432 | doVar(ea); 433 | } 434 | break; 435 | case o_pcidx: 436 | { 437 | uval_t value; 438 | bool ok = get_op_value(x, &value); 439 | if ( ok ) 440 | { 441 | ea_t ea = cmd.ea + cmd.size + (value << 1); 442 | add_code_xref(x, ea); 443 | } 444 | } 445 | break; 446 | default: 447 | INTERR(10095); 448 | } 449 | } 450 | 451 | 452 | //---------------------------------------------------------------------- 453 | static void check_base_reg_change_value() 454 | { 455 | if ( cmd.itype == H8_ldc 456 | && cmd.Op2.type == o_reg 457 | && (cmd.Op2.reg == SBR || cmd.Op2.reg == VBR) ) 458 | { 459 | sel_t value = BADSEL; 460 | bool ok = get_op_value(cmd.Op1, &value); 461 | split_srarea(cmd.ea + cmd.size, cmd.Op2.reg, value, ok ? SR_autostart : SR_user); 462 | } 463 | } 464 | 465 | //---------------------------------------------------------------------- 466 | int idaapi emu(void) 467 | { 468 | uint32 Feature = cmd.get_canon_feature(); 469 | bool flag1 = is_forced_operand(cmd.ea, 0); 470 | bool flag2 = is_forced_operand(cmd.ea, 1); 471 | bool flag3 = is_forced_operand(cmd.ea, 2); 472 | 473 | flow = ((Feature & CF_STOP) == 0); 474 | 475 | if ( Feature & CF_USE1 ) handle_operand(cmd.Op1, flag1, true); 476 | if ( Feature & CF_USE2 ) handle_operand(cmd.Op2, flag2, true); 477 | if ( Feature & CF_USE3 ) handle_operand(cmd.Op3, flag3, true); 478 | 479 | if ( Feature & CF_CHG1 ) handle_operand(cmd.Op1, flag1, false); 480 | if ( Feature & CF_CHG2 ) handle_operand(cmd.Op2, flag2, false); 481 | if ( Feature & CF_CHG3 ) handle_operand(cmd.Op3, flag3, false); 482 | 483 | // 484 | // Check for table and generic indirect jumps 485 | // 486 | if ( cmd.itype == H8_jmp && cmd.Op1.type == o_phrase ) 487 | { 488 | if ( !check_for_table_jump() ) 489 | check_for_generic_indirect_jump(); 490 | } 491 | 492 | if ( cmd.itype == H8_jsr && cmd.Op1.type == o_phrase ) 493 | { 494 | check_for_generic_indirect_call(); 495 | } 496 | 497 | // 498 | // Check for SBR, VBR change value 499 | // 500 | if ( is_h8sx() ) 501 | check_base_reg_change_value(); 502 | 503 | // 504 | // Determine if the next instruction should be executed 505 | // 506 | if ( segtype(cmd.ea) == SEG_XTRN ) 507 | flow = false; 508 | if ( flow ) 509 | ua_add_cref(0,cmd.ea+cmd.size,fl_F); 510 | 511 | 512 | // 513 | // Handle SP modifications 514 | // 515 | if ( may_trace_sp() ) 516 | { 517 | if ( !flow ) 518 | recalc_spd(cmd.ea); // recalculate SP register for the next insn 519 | else 520 | trace_sp(); 521 | } 522 | 523 | return 1; 524 | } 525 | 526 | //---------------------------------------------------------------------- 527 | int is_jump_func(const func_t * /*pfn*/, ea_t *jump_target) 528 | { 529 | *jump_target = BADADDR; 530 | return 1; // means "no" 531 | } 532 | 533 | //---------------------------------------------------------------------- 534 | int may_be_func(void) // can a function start here? 535 | // arg: none, the instruction is in 'cmd' 536 | // returns: probability 0..100 537 | // 'cmd' structure is filled upon the entrace 538 | // the idp module is allowed to modify 'cmd' 539 | { 540 | if ( cmd.itype == H8_push && isbp(cmd.Op1.reg) ) 541 | return 100; // push.l er6 542 | if ( cmd.itype == H8_push && cmd.Op1.reg==ER3 ) 543 | return 100; // push.l er3 544 | if ( cmd.itype == H8_push && cmd.Op1.reg==R3 ) 545 | return 100; // push.w r3 546 | return 0; 547 | } 548 | 549 | //---------------------------------------------------------------------- 550 | int is_sane_insn(int /*nocrefs*/) 551 | { 552 | if ( cmd.itype == H8_nop ) 553 | { 554 | for ( int i=0; i < 8; i++ ) 555 | if ( get_word(cmd.ea-i*2) != 0 ) 556 | return 1; 557 | return 0; // too many nops in a row 558 | } 559 | return 1; 560 | } 561 | 562 | //---------------------------------------------------------------------- 563 | int idaapi h8_is_align_insn(ea_t ea) 564 | { 565 | if ( !decode_insn(ea) ) 566 | return 0; 567 | switch ( cmd.itype ) 568 | { 569 | case H8_nop: 570 | break; 571 | case H8_mov: 572 | case H8_or: 573 | if ( cmd.Op1.type == cmd.Op2.type && cmd.Op1.reg == cmd.Op2.reg ) 574 | break; 575 | default: 576 | return 0; 577 | } 578 | return cmd.size; 579 | } 580 | 581 | //---------------------------------------------------------------------- 582 | bool idaapi is_return_insn() 583 | { 584 | return cmd.itype == H8_rte 585 | || cmd.itype == H8_rts 586 | || cmd.itype == H8_rtel 587 | || cmd.itype == H8_rtsl; 588 | } 589 | 590 | //---------------------------------------------------------------------- 591 | bool idaapi create_func_frame(func_t *pfn) 592 | { 593 | int code = 0; 594 | if ( pfn->frame == BADNODE ) 595 | { 596 | size_t regs = 0; 597 | ea_t ea = pfn->startEA; 598 | bool bpused = false; 599 | while ( ea < pfn->endEA ) // skip all pushregs 600 | { // (must test that ea is lower 601 | // than pfn->endEA) 602 | decode_insn(ea); 603 | ea += cmd.size; 604 | switch ( cmd.itype ) 605 | { 606 | case H8_nop: 607 | continue; 608 | case H8_push: 609 | regs += get_dtyp_size(cmd.Op1.dtyp); 610 | continue; 611 | case H8_stm: 612 | if ( !issp(cmd.Op2.reg) ) 613 | break; 614 | regs += cmd.Op1.nregs * get_dtyp_size(cmd.Op1.dtyp); 615 | continue; 616 | case H8_mov: // mov.l er6, sp 617 | if ( cmd.Op1.type == o_reg && issp(cmd.Op1.reg) 618 | && cmd.Op2.type == o_reg && isbp(cmd.Op2.reg) ) 619 | bpused = true; 620 | break; 621 | default: 622 | break; 623 | } 624 | break; 625 | } 626 | if ( regs != 0 || bpused ) 627 | { 628 | setflag((uint32 &)pfn->flags, FUNC_FRAME, bpused); 629 | return add_frame(pfn, 0, (ushort)regs, 0); 630 | } 631 | } 632 | return code != 0; 633 | } 634 | 635 | //---------------------------------------------------------------------- 636 | int idaapi h8_get_frame_retsize(func_t *) 637 | { 638 | return advanced() ? 4 : 2; 639 | } 640 | 641 | //---------------------------------------------------------------------- 642 | // These are the recognized jump table sizing patterns 643 | //0100 cmp.b #7, r0l 644 | //0102 bls loc_108:8 645 | //0104 bra def_200:8 646 | //0106 loc_108: ; jump table lookup 647 | //0200 def_200: ; default jump target 648 | // Or 649 | //0100 cmp.b #7, r0l 650 | //0102 bls loc_108:8 651 | //0104 jmp def_2000:16 652 | //0108 loc_108: ; jump table lookup 653 | //2000 def_2000: ; default jump target 654 | // Or 655 | //0100 mov.w #7, r3 656 | //0104 cmp.w r3, r0 657 | //0106 bls loc_10C:8 658 | //0108 bra def_200:8 659 | //010A loc_10C: ; jump table lookup 660 | //0200 def_200: ; default jump target 661 | // Or 662 | //0100 mov.w #7, r3 663 | //0104 cmp.w r3, r0 664 | //0106 bls loc_10C:8 665 | //0108 jmp def_2000:16 666 | //010C loc_10C: ; jump table lookup 667 | //2000 def_2000: ; default jump target 668 | // Or 669 | //0100 cmp.b #7, r0l 670 | //0102 bhi def_200:8 671 | //0104 ; jump table lookup 672 | //0200 def_200: ; default jump target 673 | // Or 674 | //0100 mov.w #7, r3 675 | //0104 cmp.w r3, r0 676 | //0106 bhi def_200:8 677 | //0108 ; jump table lookup 678 | //0200 def_200: ; default jump target 679 | //---------------------------------------------------------------------- 680 | static bool find_table_size(ea_t *defea, int *size, int rlx, ea_t code_ip) 681 | { 682 | *defea = BADADDR; 683 | *size = INT_MAX; 684 | if ( decode_prev_insn(cmd.ea) == BADADDR ) 685 | return true; 686 | 687 | if ( cmd.itype == H8_bhi ) // bhi default 688 | { 689 | *defea = cmd.Op1.addr; 690 | } 691 | else 692 | { 693 | if ( cmd.itype != H8_jmp // jmp default 694 | && cmd.itype != H8_bra ) // bra default 695 | { 696 | return true; 697 | } 698 | *defea = cmd.Op1.addr; 699 | 700 | if ( decode_prev_insn(cmd.ea) == BADADDR 701 | || cmd.itype != H8_bls // bls code_ip 702 | || cmd.Op1.addr != code_ip ) 703 | { 704 | return true; 705 | } 706 | } 707 | 708 | if ( decode_prev_insn(cmd.ea) == BADADDR 709 | || cmd.itype != H8_cmp // cmp.b #size, rlx 710 | || cmd.Op2.type != o_reg ) 711 | { 712 | return true; 713 | } 714 | if ( cmd.Op1.type == o_imm ) 715 | { 716 | if ( cmd.auxpref != aux_byte 717 | || cmd.Op2.reg != rlx ) 718 | { 719 | return true; 720 | } 721 | } 722 | else 723 | { 724 | if ( cmd.Op1.type != o_reg // cmp.w RX, rx 725 | || cmd.Op2.reg != (rlx - 24) ) 726 | { 727 | return true; 728 | } 729 | int rx = cmd.Op1.reg; 730 | if ( decode_prev_insn(cmd.ea) == BADADDR 731 | || cmd.itype != H8_mov // mov.w #size, RX 732 | || cmd.Op2.type != o_reg 733 | || cmd.Op2.reg != rx 734 | || cmd.Op1.type != o_imm ) 735 | { 736 | return true; 737 | } 738 | } 739 | 740 | *size = int(cmd.Op1.value + 1); 741 | return true; 742 | } 743 | 744 | //---------------------------------------------------------------------- 745 | // This is jump table pattern #1 746 | //0100 sub.b r0h, r0h 747 | //0102 mov.b @(jpt_10a:16,r0), r0l 748 | //0106 add.b #loc_10C & 0xFF, r0l 749 | //0108 addx #loc_10C >> 8, r0h 750 | //010A jmp @r0 751 | //010C loc_10C: ; base address of jump table 752 | // Or 753 | //0100 mov.b @(jpt_10a:16,r0), r0l 754 | //0104 sub.b r0h, r0h 755 | //0106 add.b #loc_10C & 0xFF, r0l 756 | //0108 addx #loc_10C >> 8, r0h 757 | //010A jmp @r0 758 | //010C loc_10C: ; base address of jump table 759 | //---------------------------------------------------------------------- 760 | static bool is_jump_pattern1(ea_t *base, ea_t *table, ea_t *defea, int *size, int *elsize) 761 | { 762 | int reg = cmd.Op1.phrase; 763 | int rh = reg + 16; 764 | int rl = rh + 8; 765 | if ( decode_prev_insn(cmd.ea) == BADADDR 766 | || cmd.itype != H8_addx // addx #baseh, rh 767 | || cmd.Op1.type != o_imm 768 | || cmd.Op2.reg != rh ) 769 | { 770 | return false; 771 | } 772 | int baseh = (int)cmd.Op1.value; // msb of base 773 | ea_t eah = cmd.ea; 774 | 775 | if ( decode_prev_insn(cmd.ea) == BADADDR 776 | || cmd.itype != H8_add // add.b #basel, rl 777 | || cmd.auxpref != aux_byte 778 | || cmd.Op1.type != o_imm 779 | || cmd.Op2.reg != rl ) 780 | { 781 | return false; 782 | } 783 | int basel = (int)cmd.Op1.value; // lsb of base 784 | ea_t eal = cmd.ea; 785 | 786 | int rx, rhx, rlx; 787 | ea_t obase; 788 | if ( decode_prev_insn(cmd.ea) == BADADDR ) 789 | return false; 790 | else 791 | { 792 | if ( cmd.itype == H8_mov ) // mov.b @(table:16,rx), rl 793 | { 794 | if ( cmd.auxpref != aux_byte 795 | || cmd.Op1.type != o_displ 796 | || cmd.Op2.reg != rl ) 797 | { 798 | return false; 799 | } 800 | 801 | *table = cmd.Op1.addr; 802 | rx = cmd.Op1.reg; 803 | rhx = rx + 16; 804 | rlx = rhx + 8; 805 | obase = toEA(cmd.cs, 0); 806 | set_offset(cmd.ea, 0, obase); 807 | 808 | if ( decode_prev_insn(cmd.ea) == BADADDR 809 | || (cmd.itype != H8_sub && cmd.itype != H8_xor) // sub.b rhx, rhx 810 | || cmd.auxpref != aux_byte 811 | || cmd.Op1.type != o_reg 812 | || cmd.Op2.type != o_reg 813 | || cmd.Op1.reg != rhx 814 | || cmd.Op2.reg != rhx ) 815 | { 816 | return false; 817 | } 818 | } 819 | else if ( cmd.itype == H8_sub || cmd.itype == H8_xor ) // sub.b rhx, rhx 820 | { 821 | if ( cmd.auxpref != aux_byte 822 | || cmd.Op1.type != o_reg 823 | || cmd.Op2.type != o_reg 824 | || cmd.Op1.reg != cmd.Op2.reg ) 825 | { 826 | return false; 827 | } 828 | 829 | rhx = cmd.Op1.reg; 830 | rlx = rhx + 8; 831 | rx = rhx - 16; 832 | 833 | if ( decode_prev_insn(cmd.ea) == BADADDR 834 | || (cmd.itype != H8_mov) // mov.b @(table:16,rx), rl 835 | || cmd.auxpref != aux_byte 836 | || cmd.Op1.type != o_displ 837 | || cmd.Op2.reg != rl 838 | || cmd.Op1.reg != rx ) 839 | { 840 | return false; 841 | } 842 | 843 | *table = cmd.Op1.addr; 844 | obase = toEA(cmd.cs, 0); 845 | set_offset(cmd.ea, 0, obase); 846 | } 847 | else 848 | return false; 849 | } 850 | 851 | *base = int(baseh<<8) | basel; 852 | ea_t bea = toEA(cmd.cs, *base); 853 | op_offset(eah, 0, REF_HIGH8, bea, obase); 854 | op_offset(eal, 0, REF_LOW8, bea, obase); 855 | 856 | // the jump table is found, try to determine its size 857 | *elsize = 1; 858 | return find_table_size(defea, size, rlx, cmd.ip); 859 | } 860 | 861 | //---------------------------------------------------------------------- 862 | // This is jump table pattern #2 863 | // (*1* may be omitted...IE, this logic is located above jump table sizing instructions) 864 | //0100 *1* sub.b r0h, r0h 865 | //0102 add.w r0, r0 866 | //0104 mov.w @(jpt_108:16,r0), r0 867 | //0108 jmp @r0 868 | //---------------------------------------------------------------------- 869 | static bool is_jump_pattern2(ea_t *base, ea_t *table, ea_t *defea, int *size, int *elsize) 870 | { 871 | int reg = cmd.Op1.phrase; 872 | if ( decode_prev_insn(cmd.ea) == BADADDR 873 | || cmd.itype != H8_mov // mov.w @(table:16,r0), r0 874 | || cmd.auxpref != aux_word 875 | || cmd.Op1.type != o_displ 876 | || cmd.Op2.reg != reg ) 877 | { 878 | return false; 879 | } 880 | *table = cmd.Op1.addr; 881 | int rx = cmd.Op1.reg; 882 | *base = 0; 883 | ea_t bea = toEA(cmd.cs, 0); 884 | set_offset(cmd.ea, 0, bea); 885 | 886 | if ( decode_prev_insn(cmd.ea) == BADADDR 887 | || cmd.itype != H8_add // add.w r0, r0 888 | || cmd.auxpref != aux_word 889 | || cmd.Op1.type != o_reg 890 | || cmd.Op1.reg != rx 891 | || cmd.Op2.reg != rx ) 892 | { 893 | return false; 894 | } 895 | int rhx = rx + 16; 896 | int rlx = rhx + 8; 897 | 898 | ea_t oldea = cmd.ea; 899 | ea_t oldip = cmd.ip; 900 | if ( decode_prev_insn(cmd.ea) == BADADDR 901 | || (cmd.itype != H8_sub && cmd.itype != H8_xor) // sub.b rhx, rhx 902 | || cmd.auxpref != aux_byte 903 | || cmd.Op1.type != o_reg 904 | || cmd.Op2.type != o_reg 905 | || cmd.Op1.reg != rhx 906 | || cmd.Op2.reg != rhx ) 907 | { 908 | cmd.ea = oldea; // forgive this... 909 | cmd.ip = oldip; 910 | } 911 | 912 | // the jump table is found, try to determine its size 913 | *elsize = 2; 914 | return find_table_size(defea, size, rlx, cmd.ip); 915 | } 916 | 917 | //---------------------------------------------------------------------- 918 | typedef bool h8_is_pattern_t(ea_t *base, ea_t *table, ea_t *defea, int *size, int *elsize); 919 | 920 | static h8_is_pattern_t *const jump_patterns[] = { is_jump_pattern1, is_jump_pattern2 }; 921 | 922 | static bool check_for_table_jump(void) 923 | { 924 | ea_t base = BADADDR, table = BADADDR, defea = BADADDR; 925 | int size = 0, elsize = 0; 926 | 927 | int i; 928 | bool ok = false; 929 | insn_t saved = cmd; 930 | for ( i=0; !ok && i < qnumber(jump_patterns); i++ ) 931 | { 932 | ok = jump_patterns[i](&base, &table, &defea, &size, &elsize); 933 | cmd = saved; 934 | } 935 | if ( !ok ) 936 | return false; 937 | 938 | if ( table != BADADDR ) 939 | table = toEA(cmd.cs, table); 940 | if ( base != BADADDR ) 941 | base = toEA(cmd.cs, base); 942 | if ( defea != BADADDR ) 943 | defea = toEA(cmd.cs, defea); 944 | 945 | // check the table contents 946 | int oldsize = size; 947 | segment_t *s = getseg(table); 948 | if ( s == NULL ) 949 | return false; 950 | int maxsize = int(s->endEA - table); 951 | if ( size > maxsize ) 952 | size = maxsize; 953 | 954 | for ( i=0; i < size; i++ ) 955 | { 956 | ea_t ea = table+i*elsize; 957 | flags_t F = getFlags(ea); 958 | if ( !hasValue(F) || (i && (has_any_name(F) || hasRef(F))) ) 959 | break; 960 | int el = elsize == 1 ? get_byte(ea) : get_word(ea); 961 | flags_t F2 = get_flags_novalue(base+el); 962 | if ( isTail(F2) 963 | || isData(F2) 964 | || (!isCode(F2) && !decode_insn(base+el)) ) 965 | { 966 | break; 967 | } 968 | } 969 | cmd = saved; 970 | size = i; 971 | if ( size != oldsize ) 972 | msg("Warning: jpt_%04a calculated size of %d forced to %d!\n", 973 | cmd.ip, oldsize, size); 974 | 975 | // create the table 976 | if ( size == 0 ) 977 | return false; 978 | for ( i=0; i < size; i++ ) 979 | { 980 | ea_t ea = table + i*elsize; 981 | (elsize == 1 ? doByte : doWord)(ea, elsize); 982 | op_offset(ea, 0, elsize == 1 ? REF_OFF8 : REF_OFF16, BADADDR, base); 983 | ua_add_cref(0, base + (elsize==1?get_byte(ea):get_word(ea)), fl_JN); 984 | } 985 | char buf[MAXSTR]; 986 | qsnprintf(buf, sizeof(buf), "def_%a", cmd.ip); 987 | // set_name(defea, buf, SN_NOWARN|SN_LOCAL); // temporary kernel bug workaround 988 | set_name(defea, buf, SN_NOWARN); 989 | qsnprintf(buf, sizeof(buf), "jpt_%a", cmd.ip); 990 | set_name(table, buf, SN_NOWARN); 991 | return true; 992 | } 993 | 994 | //---------------------------------------------------------------------- 995 | static bool check_for_generic_indirect_jump(void) 996 | { 997 | // Add code to handle the indirect jumps here 998 | // Ilfak, I don't have any of these... :) 999 | return false; 1000 | } 1001 | 1002 | //---------------------------------------------------------------------- 1003 | static bool check_for_generic_indirect_call(void) 1004 | { 1005 | // Add code to handle the indirect calls here 1006 | // However, I do have plenty of these... :( 1007 | return false; 1008 | } 1009 | 1010 | //---------------------------------------------------------------------- 1011 | #define SKIP_NOPPC_FUNCTIONS 1012 | #include "../jptcmn.cpp" 1013 | 1014 | // ---------- 1015 | // Normalize switch var type 1016 | // byte -> word; word, long - no need 1017 | // 1018 | // 11 extu.w r1 | exts.w r1 1019 | // 1020 | // ---------- 1021 | // Normalize switch var value 1022 | // in: er1 1023 | // 1024 | // is_var_word == true (r1) 1025 | // 10 dec.w #1|#2, r1 | sub.w #baseval, r1 1026 | // is_var_word == false (er1) 1027 | // 10 dec.l #1|#2, er1 | sub.l #baseval, er1 1028 | // 1029 | // ---------- 1030 | // Default or end of switch jump 1031 | // in: er1 1032 | // 1033 | // is_var_word == true (r1) 1034 | // 9 cmp.w #maxval, r1 1035 | // is_var_word == false (er1) 1036 | // 9 cmp.l #maxval, er1 1037 | // 1038 | // 8 bhi default 1039 | // 1040 | // is_var_word == true (r1) 1041 | // 7 mov.w r1, r2 (optional) else r[r1] = r[r2] 1042 | // is_var_word == false (er1) 1043 | // 7 mov.l er1, er2 (optional) else r[r1] = r[r2] 1044 | // 1045 | // ---------- 1046 | // Case offset load: 1047 | // in : er2 - switch var value 1048 | // out: er0 - case label offset 1049 | // is_var_word set 1050 | // 1051 | // is_var_word == true (r1) 1052 | // if is_jtsz_byte 1053 | // 4 mov.b @(bytesz_offsets:32,r2.w),r0l 1054 | // else 1055 | // 4 mov.w @(wordsz_offsets:32,r2.w),r0 1056 | // 1057 | // 6 extu.l er2 1058 | // if is_jtsz_byte 1059 | // 4 mov.b @(bytesz_offsets:32,er2),r0l 1060 | // else 1061 | // 5 add.l er2, er2 | shll.l er2 1062 | // 4 mov.w @(wordsz_offsets:32,er2),r0 1063 | // 1064 | // is_var_word == false (er1) 1065 | // if is_jtsz_byte 1066 | // 4 mov.b @(bytesz_offsets:32,er2.l),r0l 1067 | // else 1068 | // 4 mov.w @(wordsz_offsets:32,er2.l),r0 1069 | // 1070 | // if is_jtsz_byte 1071 | // 4 mov.b @(bytesz_offsets:32,er2),r0l 1072 | // else 1073 | // 5 add.l er2, er2 | shll.l er2 1074 | // 4 mov.w @(wordsz_offsets:32,er2),r0 1075 | // 1076 | // ---------- 1077 | // Jump block: 1078 | // in : er0 - case label offset 1079 | // out: is_jtsz_byte set 1080 | // 1081 | // is_jtsz_byte == true (r0l) 1082 | // 3 extu.w r0 1083 | // 2 extu.l er0 1084 | // 1 add.l #base_offsets,er0 1085 | // 0 jmp @er0 1086 | // 1087 | // 3 1088 | // 2 extu.l #2, er0 1089 | // 1 add.l #base_offsets,er0 1090 | // 0 jmp @er0 1091 | // 1092 | // 3 1093 | // 2 1094 | // 1 shlr.b r0l 1095 | // 0 bra r0l.b 1096 | // 1097 | // is_jtsz_byte == false (r0) 1098 | // 3 1099 | // 2 extu.l er0 1100 | // 1 add.l #base_offsets,er0 1101 | // 0 jmp @er0 1102 | // 1103 | // 3 1104 | // 2 1105 | // 1 shlr.w r0 1106 | // 0 bra r0.w 1107 | // 1108 | // 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 1109 | 1110 | static const char roots_hew_jmp[] = { 1, 0 }; 1111 | static const char depends_hew_jmp[][2] = 1112 | { 1113 | { 1 }, // 0 1114 | { 2 }, // 1 1115 | { 3 }, // 2 1116 | { 4 }, // 3 1117 | { 5 }, // 4 1118 | { 6 }, // 5 1119 | { 7 }, // 6 1120 | { 8 }, // 7 1121 | { 9 }, // 8 1122 | { -10 }, // 9 1123 | { -11 }, // 10 1124 | { 0 }, // 11 1125 | }; 1126 | 1127 | class hew_jmp_pattern_t : public jump_pattern_t 1128 | { 1129 | protected: 1130 | enum { er0 = 1, er1, er2 }; 1131 | bool is_jtsz_byte; // is jump table byte or word size 1132 | bool is_var_word; // is switch var word or long 1133 | bool is_bra; // bra or jump switch 1134 | 1135 | hew_jmp_pattern_t(const char *_roots, const char (*_depends)[2], switch_info_ex_t &_si) 1136 | : jump_pattern_t(_roots, _depends, _si) 1137 | { 1138 | allow_noflows = false; 1139 | is_jtsz_byte = false; 1140 | is_var_word = false; 1141 | is_bra = false; 1142 | } 1143 | 1144 | public: 1145 | virtual void check_spoiled(void); 1146 | hew_jmp_pattern_t(switch_info_ex_t &_si) : jump_pattern_t(roots_hew_jmp, depends_hew_jmp, _si) 1147 | { 1148 | allow_noflows = false; 1149 | is_jtsz_byte = false; 1150 | is_var_word = false; 1151 | is_bra = false; 1152 | } 1153 | 1154 | virtual bool jpib(void); 1155 | virtual bool jpia(void); 1156 | virtual bool jpi9(void); 1157 | virtual bool jpi8(void); 1158 | virtual bool jpi7(void); 1159 | virtual bool jpi6(void); 1160 | virtual bool jpi5(void); 1161 | virtual bool jpi4(void); 1162 | virtual bool jpi3(void); 1163 | virtual bool jpi2(void); 1164 | virtual bool jpi1(void); 1165 | virtual bool jpi0(void); 1166 | }; 1167 | 1168 | //-------------------------------------------------------------------------- 1169 | void hew_jmp_pattern_t::check_spoiled(void) 1170 | { 1171 | if ( r[er0] != -1 && is_reg_spoiled(r[er0]) ) 1172 | spoiled[er0] = true; 1173 | if ( r[er1] != -1 && is_reg_spoiled(r[er1]) ) 1174 | spoiled[er1] = true; 1175 | if ( r[er2] != -1 && is_reg_spoiled(r[er2]) ) 1176 | spoiled[er2] = true; 1177 | } 1178 | 1179 | //-------------------------------------------------------------------------- 1180 | bool hew_jmp_pattern_t::jpib() 1181 | { 1182 | if ( (cmd.itype == H8_extu || cmd.itype == H8_exts) 1183 | && cmd.Op2.is_reg(r[er1]) ) 1184 | { 1185 | si.startea = cmd.ea; 1186 | return true; 1187 | } 1188 | return false; 1189 | } 1190 | 1191 | //-------------------------------------------------------------------------- 1192 | bool hew_jmp_pattern_t::jpia() 1193 | { 1194 | if ( (cmd.itype == H8_dec || cmd.itype == H8_sub) 1195 | && (is_var_word && cmd.auxpref == aux_word || cmd.auxpref == aux_long) 1196 | && cmd.Op1.type == o_imm 1197 | && cmd.Op2.is_reg(r[er1]) ) 1198 | { 1199 | si.lowcase = cmd.Op1.value; 1200 | si.startea = cmd.ea; 1201 | return true; 1202 | } 1203 | 1204 | return false; 1205 | } 1206 | 1207 | //-------------------------------------------------------------------------- 1208 | bool hew_jmp_pattern_t::jpi9(void) 1209 | { 1210 | if ( cmd.itype != H8_cmp 1211 | || (!is_var_word || cmd.auxpref != aux_word) && cmd.auxpref != aux_long 1212 | || cmd.Op1.type != o_imm 1213 | || !cmd.Op2.is_reg(r[er1]) ) 1214 | { 1215 | return false; 1216 | } 1217 | 1218 | si.ncases = cmd.Op1.value + 1; 1219 | si.set_expr(cmd.Op2.reg, cmd.Op2.dtyp); 1220 | si.lowcase = 0; 1221 | si.startea = cmd.ea; 1222 | 1223 | // return true; 1224 | // otherwise we can eat all up to the other switch 1225 | skip[10] = true; 1226 | skip[11] = true; 1227 | 1228 | insn_t saved = cmd; 1229 | if ( decode_prev_insn(cmd.ea) != BADADDR 1230 | && jpia() ) 1231 | { 1232 | eas[10] = cmd.ea; 1233 | if ( decode_prev_insn(cmd.ea) != BADADDR 1234 | && jpib() ) 1235 | { 1236 | eas[11] = cmd.ea; 1237 | } 1238 | } 1239 | cmd = saved; 1240 | return true; 1241 | } 1242 | 1243 | //-------------------------------------------------------------------------- 1244 | bool hew_jmp_pattern_t::jpi8(void) 1245 | { 1246 | if ( cmd.itype != H8_bhi || cmd.Op1.type != o_near ) 1247 | return false; 1248 | 1249 | si.defjump = toEA(cmd.cs, cmd.Op1.addr); 1250 | si.flags |= SWI_DEFAULT; 1251 | return true; 1252 | } 1253 | 1254 | //-------------------------------------------------------------------------- 1255 | bool hew_jmp_pattern_t::jpi7(void) 1256 | { 1257 | if ( cmd.itype == H8_mov 1258 | && (is_var_word && cmd.auxpref == aux_word || cmd.auxpref == aux_long) 1259 | && cmd.Op1.type == o_reg 1260 | && (cmd.auxpref == aux_long && cmd.Op2.is_reg(r[er2]) 1261 | || cmd.auxpref == aux_word && cmd.Op2.is_reg(reg_toR0(r[er2]))) ) 1262 | { 1263 | r[er1] = cmd.Op1.reg; 1264 | return true; 1265 | } 1266 | 1267 | if ( jpi8() ) 1268 | { 1269 | r[er1] = r[er2]; 1270 | skip[8] = true; 1271 | return true; 1272 | } 1273 | return false; 1274 | } 1275 | 1276 | //-------------------------------------------------------------------------- 1277 | bool hew_jmp_pattern_t::jpi6(void) 1278 | { 1279 | if ( cmd.itype == H8_extu 1280 | && cmd.auxpref == aux_long 1281 | && !cmd.Op1.shown() 1282 | && cmd.Op2.is_reg(r[er2]) ) 1283 | { 1284 | is_var_word = true; 1285 | return true; 1286 | } 1287 | 1288 | if ( jpi7() ) 1289 | { 1290 | skip[7] = true; 1291 | return true; 1292 | } 1293 | return false; 1294 | } 1295 | 1296 | //-------------------------------------------------------------------------- 1297 | bool hew_jmp_pattern_t::jpi5(void) 1298 | { 1299 | return cmd.auxpref == aux_long 1300 | && cmd.Op2.is_reg(r[er2]) 1301 | && (cmd.itype == H8_add && cmd.Op1.is_reg(r[er2]) 1302 | || cmd.itype == H8_shll); 1303 | } 1304 | 1305 | //-------------------------------------------------------------------------- 1306 | bool hew_jmp_pattern_t::jpi4(void) 1307 | { 1308 | if ( !(cmd.itype == H8_mov 1309 | && (is_jtsz_byte && cmd.auxpref == aux_byte || cmd.auxpref == aux_word) 1310 | && cmd.Op1.type == o_displ 1311 | && (cmd.Op1.displtype == dt_normal 1312 | || cmd.Op1.displtype == dt_regidx && (cmd.Op1.szfl & (idx_word | idx_long)) != 0) 1313 | && (cmd.Op1.szfl & disp_32) != 0 1314 | && cmd.Op2.type == o_reg 1315 | && (is_jtsz_byte && cmd.Op2.reg == reg_toR0L(r[er0]) 1316 | || cmd.Op2.reg == reg_toR0(r[er0]))) ) 1317 | { 1318 | return false; 1319 | } 1320 | 1321 | if ( !isDefArg(uFlag,cmd.Op1.n) ) 1322 | op_offset(cmd.ea, cmd.Op1.n, REF_OFF32, calc_mem(cmd.Op1.addr)); 1323 | 1324 | si.jumps = cmd.Op1.addr; 1325 | r[er2] = cmd.Op1.reg; 1326 | 1327 | if ( is_jtsz_byte ) 1328 | { 1329 | skip[5] = true; 1330 | si.set_jtable_element_size(1); 1331 | } 1332 | else 1333 | { 1334 | si.set_jtable_element_size(2); 1335 | } 1336 | 1337 | if ( cmd.Op1.displtype == dt_regidx ) 1338 | { 1339 | is_var_word = (cmd.Op1.szfl & idx_word) != 0; 1340 | skip[5] = true; 1341 | skip[6] = true; 1342 | return true; 1343 | } 1344 | 1345 | return true; 1346 | } 1347 | 1348 | //-------------------------------------------------------------------------- 1349 | bool hew_jmp_pattern_t::jpi3(void) 1350 | { 1351 | if ( cmd.itype == H8_extu 1352 | && cmd.auxpref == aux_word 1353 | && cmd.Op2.type == o_reg 1354 | && cmd.Op2.reg == reg_toR0(r[er0]) ) 1355 | { 1356 | is_jtsz_byte = true; 1357 | return true; 1358 | } 1359 | 1360 | if ( jpi4() ) 1361 | { 1362 | skip[4] = true; 1363 | return true; 1364 | } 1365 | return false; 1366 | } 1367 | 1368 | //-------------------------------------------------------------------------- 1369 | bool hew_jmp_pattern_t::jpi2(void) 1370 | { 1371 | if ( !(cmd.itype == H8_extu 1372 | && cmd.auxpref == aux_long 1373 | && cmd.Op2.type == o_reg 1374 | && cmd.Op2.reg == r[er0]) ) 1375 | { 1376 | return false; 1377 | } 1378 | 1379 | if ( cmd.Op1.shown() 1380 | && cmd.Op1.value == 2 ) 1381 | { 1382 | is_jtsz_byte = true; 1383 | skip[3] = true; 1384 | } 1385 | return true; 1386 | } 1387 | 1388 | //-------------------------------------------------------------------------- 1389 | bool hew_jmp_pattern_t::jpi1(void) 1390 | { 1391 | if ( is_bra ) 1392 | { 1393 | skip[2] = true; 1394 | skip[3] = true; 1395 | return cmd.itype == H8_shlr 1396 | && (is_jtsz_byte && cmd.auxpref == aux_byte || cmd.auxpref == aux_word) 1397 | && cmd.Op2.is_reg(r[er0]); 1398 | } 1399 | 1400 | if ( cmd.itype == H8_add 1401 | && cmd.auxpref == aux_long 1402 | && cmd.Op1.type == o_imm 1403 | && cmd.Op2.is_reg(r[er0]) ) 1404 | { 1405 | si.elbase = toEA(cmd.cs, cmd.Op1.value); 1406 | si.flags |= SWI_ELBASE; 1407 | return true; 1408 | } 1409 | return false; 1410 | } 1411 | 1412 | //-------------------------------------------------------------------------- 1413 | bool hew_jmp_pattern_t::jpi0(void) 1414 | { 1415 | if ( cmd.itype == H8_jmp 1416 | && cmd.Op1.type == o_phrase 1417 | && cmd.Op1.phtype == ph_normal ) 1418 | { 1419 | is_bra = false; 1420 | r[er0] = cmd.Op1.reg; 1421 | return true; 1422 | } 1423 | else if ( cmd.itype == H8_bra 1424 | && cmd.Op1.type == o_pcidx 1425 | && (cmd.Op1.szfl & idx_long) == 0 ) 1426 | { 1427 | is_bra = true; 1428 | si.elbase = cmd.ea + cmd.size; 1429 | si.flags |= SWI_ELBASE; 1430 | r[er0] = cmd.Op1.reg; 1431 | is_jtsz_byte = (cmd.Op1.szfl & idx_byte) != 0; 1432 | si.set_jtable_element_size(is_jtsz_byte ? 1 : 2); 1433 | return true; 1434 | } 1435 | return false; 1436 | } 1437 | 1438 | //---------------------------------------------------------------------- 1439 | static jump_table_type_t is_hew_pattern(switch_info_ex_t &si) 1440 | { 1441 | hew_jmp_pattern_t jp(si); 1442 | return jp.match(cmd.ea) ? JT_FLAT32 : JT_NONE; 1443 | } 1444 | 1445 | //---------------------------------------------------------------------- 1446 | static bool check_for_jump1(switch_info_ex_t &si) 1447 | { 1448 | static is_pattern_t *const h8_patterns[] = { is_hew_pattern }; 1449 | return check_for_table_jump2(h8_patterns, qnumber(h8_patterns), NULL, si); 1450 | } 1451 | 1452 | //---------------------------------------------------------------------- 1453 | bool idaapi h8_is_switch(switch_info_ex_t *si) 1454 | { 1455 | if ( cmd.itype != H8_jmp && cmd.itype != H8_bra ) 1456 | return false; 1457 | 1458 | insn_t saved = cmd; 1459 | bool found = check_for_jump1(*si); 1460 | cmd = saved; 1461 | return found; 1462 | } 1463 | 1464 | // Purpose: calculate function argument locations 1465 | // Arguments: 1466 | // type : points to the return type of the function type string 1467 | // cc : calling convention 1468 | // arglocs : the result array 1469 | // returns: 1-not implemented, 2-ok, -1-error 1470 | // ================================================================== 1471 | // calc_arglocs should fill the 'arglocs' array with the argument 1472 | // location information. The hppa module does it by calling the 1473 | // set_reg1 and set_stkoff functions. 1474 | // See hppa_calc_arglocs for an example 1475 | // ================================================================== 1476 | // See rej10b0161_h8s.pdf, section 9.3.2 - Function Calling Interface 1477 | int h8_calc_arglocs(const type_t *type, cm_t /*cc*/, varloc_t *arglocs) 1478 | { 1479 | return -1; 1480 | } 1481 | 1482 | // Purpose: use information about a stack argument 1483 | // Arguments: 1484 | // ea : address of the push instruction which 1485 | // pushes the function argument into the stack 1486 | // type : the function argument type 1487 | // name : the function argument name. may be NULL 1488 | // returns: true - ok, false - failed 1489 | // ================================================================== 1490 | // use_stkarg_type gives the processor module the opportunity to 1491 | // attach a comment to the push instruction or otherwise improve 1492 | // the listing. Since hppa does not use push to prepare arguments, 1493 | // this callback is not implemented for it. If you wish, you could 1494 | // call a function similar to hppa_set_op_type() in your 1495 | // implementation of the use_stkarg_type callback. BTW, I checked 1496 | // all processor modules, it is implemented only for x86. 1497 | bool h8_use_stkvar_type(ea_t ea, const type_t *type, const char *name) 1498 | { 1499 | return false; 1500 | } 1501 | -------------------------------------------------------------------------------- /h8/h8.cfg: -------------------------------------------------------------------------------- 1 | ; 2 | ; This file describes the standard address names for Hitachi H8 3 | ; 4 | 5 | .default H8/3644 6 | 7 | .H8/3644 8 | TIER 0xF770 9 | TCSRX 0xF771 10 | FRCH 0xF772 11 | FRCL 0xF773 12 | OCRAH 0xF774 13 | OCRAL 0xF775 14 | TCRX 0xF776 15 | TOCR 0xF777 16 | ICRAH 0xF778 17 | ICRAL 0xF779 18 | ICRBH 0xF77A 19 | ICRBL 0xF77B 20 | ICRCH 0xF77C 21 | ICRCL 0xF77D 22 | ICRDH 0xF77E 23 | ICRDL 0xF77F 24 | FLMCR 0xFF80 25 | EBR1 0xFF82 26 | EBR2 0xFF83 27 | SCR1 0xFFA0 28 | SCSR1 0xFFA1 29 | SDRU 0xFFA2 30 | SDRL 0xFFA3 31 | SMR 0xFFA8 32 | BRR 0xFFA9 33 | SCR3 0xFFAA 34 | TDR 0xFFAB 35 | SSR 0xFFAC 36 | RDR 0xFFAD 37 | TMA 0xFFB0 38 | TCA 0xFFB1 39 | TMB1 0xFFB2 40 | TCB1 0xFFB3 41 | TCRV0 0xFFB8 42 | TCSRV 0xFFB9 43 | TCORA 0xFFBA 44 | TCORB 0xFFBB 45 | TCNTV 0xFFBC 46 | TCRV1 0xFFBD 47 | TCSRW 0xFFBE 48 | TCW 0xFFBF 49 | AMR 0xFFC4 50 | ADRR 0xFFC5 51 | ADSR 0xFFC6 52 | PWCR 0xFFD0 53 | PWDRU 0xFFD1 54 | PWDRL 0xFFD2 55 | PDR1 0xFFD4 56 | PDR2 0xFFD5 57 | PDR3 0xFFD6 58 | PDR5 0xFFD8 59 | PDR6 0xFFD9 60 | PDR7 0xFFDA 61 | PDR8 0xFFDB 62 | PDR9 0xFFDC 63 | PDRB 0xFFDD 64 | PCR1 0xFFE4 65 | PCR2 0xFFE5 66 | PCR3 0xFFE6 67 | PCR5 0xFFE8 68 | PCR6 0xFFE9 69 | PCR7 0xFFEA 70 | PCR8 0xFFEB 71 | PCR9 0xFFEC 72 | PUCR1 0xFFED 73 | PUCR3 0xFFEE 74 | PUCR5 0xFFEF 75 | SYSCR1 0xFFF0 76 | SYSCR2 0xFFF1 77 | IEGR1 0xFFF2 78 | IEGR2 0xFFF3 79 | IENR1 0xFFF4 80 | IENR2 0xFFF5 81 | IENR3 0xFFF6 82 | IRR1 0xFFF7 83 | IRR2 0xFFF8 84 | IRR3 0xFFF9 85 | PMR1 0xFFFC 86 | PMR3 0xFFFD 87 | PMR7 0xFFFF 88 | 89 | .H8S/2215R 90 | UCTLR 0xC00080 91 | UTSTRA 0xC00081 92 | UDMAR 0xC00082 93 | UDRR 0xC00083 94 | UTRG0 0xC00084 95 | UFCLR0 0xC00086 96 | UESTL0 0xC00088 97 | UESTL1 0xC00089 98 | UEDR0s 0xC00090 99 | UEDR0i 0xC00094 100 | UEDR0o 0xC00098 101 | UEDR3 0xC0009c 102 | UEDR1 0xC000a0 103 | UEDR2 0xC000a4 104 | UESZ0o 0xC000bc 105 | UESZ2 0xC000bd 106 | UIFR0 0xC000c0 107 | UIFR1 0xC000c1 108 | UIFR3 0xC000c3 109 | UIER0 0xC000c4 110 | UIER1 0xC000c5 111 | UIER3 0xC000c7 112 | UISR0 0xC000c8 113 | UISR1 0xC000c9 114 | UISR3 0xC000cb 115 | UDSR 0xC000cc 116 | UCVR 0xC000cf 117 | UTSRH 0xC000d0 118 | UTSRL 0xC000d1 119 | UTSTR0 0xC000f0 120 | UTSTR1 0xC000f1 121 | UTSTR2 0xC000f2 122 | UTSTRB 0xC000fb 123 | UTSTRC 0xC000fc 124 | UTSTRD 0xC000fd 125 | UTSTRE 0xC000fe 126 | UTSTRF 0xC000ff 127 | 128 | DADR_0 0xFFFDAC D/A data register 0 129 | DADR_1 0xFFFDAD D/A data register 1 130 | DACR 0xFFFDAE D/A control register 131 | 132 | SCRX 0xFFFDB4 Serial control register X 133 | 134 | SBYCR 0xFFFDE4 Standby control register 135 | SYSCR 0xFFFDE5 System control register 136 | SCKCR 0xFFFDE6 System clock control register 137 | MDCR 0xFFFDE7 Mode control register 138 | MSTPCRA 0xFFFDE8 Module stop control register A 139 | MSTPCRB 0xFFFDE9 Module stop control register B 140 | MSTPCRC 0xFFFDEA Module stop control register C 141 | 142 | PFCR 0xFFFDEB Pin function control register 143 | LPWRCR 0xFFFDEC Low power control register 144 | 145 | SEMRA_0 0xFFFDF8 Serial extended mode register A_0 146 | SEMRB_0 0xFFFDF9 Serial extended mode register B_0 147 | 148 | ISCRH 0xFFFE12 IRQ sense control register H 149 | ISCRL 0xFFFE13 IRQ sense control register L 150 | IER 0xFFFE14 IRQ enable register 151 | ISR 0xFFFE15 IRQ status register 152 | 153 | DTCERA 0xFFFE16 DTC enable register A 154 | DTCERB 0xFFFE17 DTC enable register B 155 | DTCERC 0xFFFE18 DTC enable register C 156 | DTCERD 0xFFFE19 DTC enable register D 157 | DTCERE 0xFFFE1A DTC enable register E 158 | DTCERF 0xFFFE1B DTC enable register F 159 | DTVECR 0xFFFE1F DTC vector register 160 | 161 | P1DDR 0xFFFE30 Port 1 data direction register 162 | P3DDR 0xFFFE32 Port 3 data direction register 163 | P7DDR 0xFFFE36 Port 7 data direction register 164 | PADDR 0xFFFE39 Port A data direction register 165 | PBDDR 0xFFFE3A Port B data direction register 166 | PCDDR 0xFFFE3B Port C data direction register 167 | PDDDR 0xFFFE3C Port D data direction register 168 | PEDDR 0xFFFE3D Port E data direction register 169 | PFDDR 0xFFFE3E Port F data direction register 170 | PGDDR 0xFFFE3F Port G data direction register 171 | PAPCR 0xFFFE40 Port A pull-up MOS control register 172 | PBPCR 0xFFFE41 Port B pull-up MOS control register 173 | PCPCR 0xFFFE42 Port C pull-up MOS control register 174 | PDPCR 0xFFFE43 Port D pull-up MOS control register 175 | PEPCR 0xFFFE44 Port E pull-up MOS control register 176 | P3ODR 0xFFFE46 Port 3 open drain control register 177 | PAODR 0xFFFE47 Port A open drain control register 178 | 179 | TSTR 0xFFFEB0 Timer start register 180 | TSYR 0xFFFEB1 Timer synchro register 181 | 182 | IPRA 0xFFFEC0 Interrupt priority register A 183 | IPRB 0xFFFEC1 Interrupt priority register B 184 | IPRC 0xFFFEC2 Interrupt priority register C 185 | IPRD 0xFFFEC3 Interrupt priority register D 186 | IPRE 0xFFFEC4 Interrupt priority register E 187 | IPRF 0xFFFEC5 Interrupt priority register F 188 | IPRG 0xFFFEC6 Interrupt priority register G 189 | IPRI 0xFFFEC8 Interrupt priority register I 190 | IPRJ 0xFFFEC9 Interrupt priority register J 191 | IPRK 0xFFFECA Interrupt priority register K 192 | IPRM 0xFFFECC Interrupt priority register M 193 | 194 | ABWCR 0xFFFED0 Bus width control register 195 | ASTCR 0xFFFED1 Access state control register 196 | WCRH 0xFFFED2 Wait control register H 197 | WCRL 0xFFFED3 Wait control register L 198 | BCRH 0xFFFED4 Bus control register H 199 | BCRL 0xFFFED5 Bus control register L 200 | 201 | RAMER 0xFFFEDB RAM emulation register 202 | 203 | MAR0AH 0xFFFEE0 Memory address register 0A H 204 | MAR0AL 0xFFFEE2 Memory address register 0A L 205 | IOAR0A 0xFFFEE4 I/O address register 0A 206 | ETCR0A 0xFFFEE6 Transfer count register 0A 207 | MAR0BH 0xFFFEE8 Memory address register 0B H 208 | MAR0BL 0xFFFEEA Memory address register 0B L 209 | IOAR0B 0xFFFEEC I/O address register 0B 210 | ETCR0B 0xFFFEEE Transfer count register 0B 211 | MAR1AH 0xFFFEF0 Memory address register 1A H 212 | MAR1AL 0xFFFEF2 Memory address register 1A L 213 | IOAR1A 0xFFFEF4 I/O address register 1A 214 | ETCR1A 0xFFFEF6 Transfer count register 1A 215 | MAR1BH 0xFFFEF8 Memory address register 1BH 216 | MAR1BL 0xFFFEFA Memory address register 1BL 217 | IOAR1B 0xFFFEFC I/O address register 1B 218 | ETCR1B 0xFFFEFE Transfer count register 1B 219 | 220 | P1DR 0xFFFF00 Port 1 data register 221 | P3DR 0xFFFF02 Port 3 data register 222 | P7DR 0xFFFF06 Port 7 data register 223 | PADR 0xFFFF09 Port A data register 224 | PBDR 0xFFFF0A Port B data register 225 | PCDR 0xFFFF0B Port C data register 226 | PDDR 0xFFFF0C Port D data register 227 | PEDR 0xFFFF0D Port E data register 228 | PFDR 0xFFFF0E Port F data register 229 | PGDR 0xFFFF0F Port G data register 230 | 231 | TCR_0 0xFFFF10 Timer control register 0 232 | TMDR_0 0xFFFF11 Timer mode register 0 233 | TIORH_0 0xFFFF12 Timer I/O control register H_0 234 | TIORL_0 0xFFFF13 Timer I/O control register L_0 235 | TIER_0 0xFFFF14 Timer interrupt enable register 0 236 | TSR_0 0xFFFF15 Timer status register 0 237 | TCNT_0 0xFFFF16 Timer counter 0 238 | TGRA_0 0xFFFF18 Timer general register A 0 239 | 240 | TGRB_0 0xFFFF1A Timer general register B_0 241 | TGRC_0 0xFFFF1C Timer general register C_0 242 | TGRD_0 0xFFFF1E Timer general register D_0 243 | 244 | TCR_1 0xFFFF20 Timer control register 1 245 | TMDR_1 0xFFFF21 Timer mode register 1 246 | TIOR_1 0xFFFF22 Timer I/O control register 1 247 | TIER_1 0xFFFF24 Timer interrupt enable register 1 248 | TSR_1 0xFFFF25 Timer status register 1 249 | TCNT_1 0xFFFF26 Timer counter 1 250 | TGRA_1 0xFFFF28 Timer general register A_1 251 | TGRB_1 0xFFFF2A Timer general register B_1 252 | 253 | TCR_2 0xFFFF30 Timer control register 2 254 | TMDR_2 0xFFFF31 Timer mode register 2 255 | TIOR_2 0xFFFF32 Timer I/O control register 2 256 | TIER_2 0xFFFF34 Timer interrupt enable register 2 257 | TSR_2 0xFFFF35 Timer status register 2 258 | TCNT_2 0xFFFF36 Timer counter 2 259 | TGRA_2 0xFFFF38 Timer general register A_2 260 | TGRB_2 0xFFFF3A Timer general register B_2 261 | 262 | DMAWER 0xFFFF60 DMA write enable register 263 | DMACR0A 0xFFFF62 DMA control register 0A 264 | DMACR0B 0xFFFF63 DMA control register 0B 265 | DMACR1A 0xFFFF64 DMA control register 1A 266 | DMACR1B 0xFFFF65 DMA control register 1B 267 | DMABCR 0xFFFF66 DMA band control register 268 | 269 | TCR_0 0xFFFF68 Timer control register 0 270 | TCR_1 0xFFFF69 Timer control register 1 271 | TCSR_0 0xFFFF6A Timer control/status register 0 272 | TCSR_1 0xFFFF6B Timer control/status register 1 273 | TCORA_0 0xFFFF6C Time constant register A0 274 | TCORA_1 0xFFFF6D Time constant register A1 275 | TCORB_0 0xFFFF6E Time constant register B0 276 | TCORB_1 0xFFFF6F Time constant register B1 277 | TCNT_0 0xFFFF70 Timer counter 0 278 | TCNT_1 0xFFFF71 Timer counter 1 279 | TCSR 0xFFFF74 Timer control/status register 280 | 281 | SMR_0 0xFFFF78 Serial mode register 0 282 | BRR_0 0xFFFF79 Bit rate register 0 283 | SCR_0 0xFFFF7A Serial control register 0 284 | TDR_0 0xFFFF7B Transmit data register 0 285 | SSR_0 0xFFFF7C Serial status register 0 286 | RDR_0 0xFFFF7D Receive data register 0 287 | SCMR_0 0xFFFF7E Smart card mode register 0 288 | 289 | SMR_1 0xFFFF80 Serial mode register 1 290 | BRR_1 0xFFFF81 Bit rate register 1 291 | SCR_1 0xFFFF82 Serial control register 1 292 | TDR_1 0xFFFF83 Transmit data register 1 293 | SSR_1 0xFFFF84 Serial status register 1 294 | RDR_1 0xFFFF85 Receive data register 1 295 | SCMR_1 0xFFFF86 Smart card mode register 1 296 | SMR_2 0xFFFF88 Serial mode register 2 297 | BRR_2 0xFFFF89 Bit rate register 2 298 | SCR_2 0xFFFF8A Serial control register 2 299 | TDR_2 0xFFFF8B Transmit data register 2 300 | SSR_2 0xFFFF8C Serial status register 2 301 | RDR_2 0xFFFF8D Receive data register 2 302 | SCMR_2 0xFFFF8E Smart card mode register 2 303 | 304 | ADDRAH 0xFFFF90 A/D data register AH 305 | ADDRAL 0xFFFF91 A/D data register AL 306 | ADDRBH 0xFFFF92 A/D data register BH 307 | ADDRBL 0xFFFF93 A/D data register BL 308 | ADDRCH 0xFFFF94 A/D data register CH 309 | ADDRCL 0xFFFF95 A/D data register CL 310 | ADDRDH 0xFFFF96 A/D data register DH 311 | ADDRDL 0xFFFF97 A/D data register DL 312 | ADCSR 0xFFFF98 A/D control/status register 313 | ADCR 0xFFFF99 A/D control register 314 | 315 | FLMCR1 0xFFFFA8 Flash memory control register 1 316 | FLMCR2 0xFFFFA9 Flash memory control register 2 317 | 318 | EBR1 0xFFFFAA Erase block register 1 319 | EBR2 0xFFFFAB Erase block register 2 320 | 321 | PORT1 0xFFFFB0 Port 1 register 322 | PORT3 0xFFFFB2 Port 3 register 323 | PORT4 0xFFFFB3 Port 4 register 324 | PORT7 0xFFFFB6 Port 7 register 325 | PORT9 0xFFFFB8 Port 9 register 326 | PORTA 0xFFFFB9 Port A register 327 | PORTB 0xFFFFBA Port B register 328 | PORTC 0xFFFFBB Port C register 329 | PORTD 0xFFFFBC Port D register 330 | PORTE 0xFFFFBD Port E register 331 | PORTF 0xFFFFBE Port F register 332 | PORTG 0xFFFFBF Port G register 333 | -------------------------------------------------------------------------------- /h8/h8.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-99 by Ilfak Guilfanov. 4 | * ALL RIGHTS RESERVED. 5 | * E-mail: ig@datarescue.com 6 | * 7 | * 8 | */ 9 | 10 | #ifndef _H8_HPP 11 | #define _H8_HPP 12 | 13 | #include "../idaidp.hpp" 14 | #include "ins.hpp" 15 | #include 16 | 17 | //--------------------------------- 18 | // Operand types: 19 | 20 | /* 21 | o_reg 1 Register direct 22 | Rn 23 | x.reg 24 | o_phrase 2 Register indirect 25 | @ERn 26 | x.phrase contains register number 27 | x.phtype contains phrase type (normal, post, pre) 28 | o_displ 3 Register indirect with displacement 29 | @(d:2,ERn)/@(d:16,ERn)/@(d:32,ERn) 30 | x.reg, x.addr, disp_16, disp_32, disp_2 31 | o_displ 4 Index register indirect with displacement 32 | @(d:16, RnL.B)/@(d:16,Rn.W)/@(d:16,ERn.L) 33 | @(d:32, RnL.B)/@(d:32,Rn.W)/@(d:32,ERn.L) 34 | x.displtype = dt_regidx, 35 | x.reg, 36 | x.addr - disp_16, disp_32, idx_byte/word/long 37 | o_phrase 5 Register indirect with post-inc/pre-dec/pre-inc/post-dec 38 | @ERn+/@-ERn/@+ERn/@ERn- 39 | o_mem 6 Absolute address 40 | @aa:8/@aa:16/@aa:24/@aa:32 41 | x.memtype = @aa:8 ? mem_sbr : mem_direct 42 | x.addr 43 | o_imm 7 Immediate 44 | #x:2/#xx:3/#xx:4/#xx:5/#xx:8/#xx:16/#xx:32 45 | #1/#2/#4/#8/#16 46 | x.value 47 | o_near 8 Program-counter relative 48 | @(d:8,PC)/@(d:16,PC) 49 | o_pcidx 9 Program-counter relative with index register 50 | @(RnL.B,PC)/@(Rn.W,PC)/@(ERn.L,PC) 51 | x.reg 52 | o_mem 10 Memory indirect 53 | @@aa:8 54 | x.memtype = mem_ind 55 | x.addr 56 | o_mem 11 Extended memory indirect 57 | @@vec:7 58 | x.memtype = mem_vec7 59 | x.addr 60 | o_reglist Register list 61 | x.reg, x.nregs 62 | o_displ first operand of MOVA insn 63 | @(d16,.[BW])/@(d32:.[BW]) 64 | x.displtype = dt_movaop1, 65 | x.addr, 66 | x.szfl - disp_16/disp_32/idx_byte/idx_word 67 | x.idxt - type 68 | type: 69 | o_reg - x.reg EQ to o_regidx 70 | o_phrase - x.phrase,x.idxdt 71 | o_displ - x.reg,x.value,x.idxsz,x.idxdt 72 | o_regidx - x.reg,x.value,x.idxsz,x.idxdt 73 | o_mem - x.value,x.idsz,x.idxdt 74 | */ 75 | 76 | #define o_reglist o_idpspec0 77 | #define o_pcidx o_idpspec1 78 | 79 | #define phtype specflag1 // phrase type: 80 | const int ph_normal = 0; // just simple indirection 81 | const int ph_pre_dec = 0x10; // -@Rn ^ 3 -> @Rn+ 82 | const int ph_post_inc = 0x13; // @Rn+ 83 | const int ph_pre_inc = 0x11; // +@ERn 84 | const int ph_post_dec = 0x12; // @ERn- 85 | 86 | #define displtype specflag1 // displ type: 87 | const int dt_normal = 0; // Register indirect with displacement 88 | const int dt_regidx = 1; // Index register indirect with displacement 89 | const int dt_movaop1 = 2; // first operand of MOVA insn 90 | 91 | #define szfl specflag2 // various operand size flags 92 | // index target 93 | const int idx_byte = 0x01; // .b 94 | const int idx_word = 0x02; // .w 95 | const int idx_long = 0x04; // .l 96 | // size of operand displ 97 | const int disp_16 = 0x10; // 16bit displacement 98 | const int disp_24 = 0x20; // 24bit displacement 99 | const int disp_32 = 0x40; // 32bit displacement 100 | const int disp_2 = 0x80; // 2bit displacement 101 | 102 | #define memtype specflag1 // mem type: 103 | const int mem_direct = 0; // x.addr - direct memory ref 104 | const int mem_sbr = 1; // SBR based @aa:8 105 | const int mem_vec7 = 2; // @@vec:7 106 | const int mem_ind = 3; // @@aa:8 107 | 108 | #define nregs specflag1 // o_reglist: number of registers 109 | 110 | // MOVA Op1 store 111 | #define idxt specflag3 // MOVA: optype_t of index 112 | #define idxsz specflag4 // MOVA: size of index 113 | #define idxdt specval // MOVA: index phtype,displtype,memtype 114 | 115 | //------------------------------------------------------------------ 116 | const uint16 aux_none = 0; // no postfix 117 | const uint16 aux_byte = 1; // .b postfix 118 | const uint16 aux_word = 2; // .w postfix 119 | const uint16 aux_long = 3; // .l postfix 120 | 121 | //------------------------------------------------------------------ 122 | #ifdef _MSC_VER 123 | #define ENUM8BIT : uint8 124 | #else 125 | #define ENUM8BIT 126 | #endif 127 | enum regnum_t ENUM8BIT 128 | { 129 | R0, R1, R2, R3, R4, R5, R6, R7, SP=R7, 130 | E0, E1, E2, E3, E4, E5, E6, E7, 131 | R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H, 132 | R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L, 133 | ER0, ER1, ER2, ER3, ER4, ER5, ER6, ER7, 134 | // don't change registers order above this line 135 | MACL, MACH, 136 | PC, 137 | CCR, EXR, 138 | rVcs, rVds, // virtual registers for code and data segments 139 | VBR, SBR, // base or segment registers 140 | }; 141 | 142 | //------------------------------------------------------------------ 143 | // processor types 144 | 145 | typedef uint16 proctype_t; 146 | 147 | static const proctype_t none = 0; 148 | static const proctype_t P300 = 0x0001; // H8/300, H8/300H 149 | static const proctype_t P2000 = 0x0002; // H8S/2000 150 | static const proctype_t P2600 = 0x0004; // H8S/2600 151 | static const proctype_t PSX = 0x0008; // H8SX 152 | 153 | // assume 'Normal mode' as the default 154 | static const proctype_t MODE_MASK= 0xF000; 155 | static const proctype_t MODE_MID = 0x1000; // H8SX 156 | static const proctype_t MODE_ADV = 0x2000; // H8/300H (!), H8S, H8SX 157 | static const proctype_t MODE_MAX = 0x3000; // H8SX 158 | 159 | static const proctype_t P30A = P300 | MODE_ADV; 160 | static const proctype_t P26A = P2600 | MODE_ADV; 161 | 162 | extern proctype_t ptype; // contains all bits which correspond 163 | // to the supported processors set 164 | 165 | inline bool advanced(void) { return (ptype & MODE_MASK) != 0; } 166 | inline bool is_h8s(void) { return (ptype & (P2000|P2600)) != 0; } 167 | inline bool is_h8sx(void) { return (ptype & PSX) != 0; } 168 | 169 | //------------------------------------------------------------------ 170 | #define UAS_HEW 0x0001 // HEW assembler 171 | 172 | inline bool is_hew_asm(void) 173 | { 174 | return (ash.uflag & UAS_HEW) != 0; 175 | } 176 | 177 | //------------------------------------------------------------------ 178 | extern netnode helper; 179 | 180 | ea_t trim_ea_branch(ea_t ea); // trim address according to proc mode 181 | ea_t calc_mem(ea_t ea); // map virtual to physical ea 182 | ea_t calc_mem_sbr_based(ea_t ea); // map virtual @aa:8 physical ea 183 | const char *find_sym(ea_t address); 184 | 185 | void idaapi header(void); 186 | void idaapi footer(void); 187 | 188 | void idaapi segstart(ea_t ea); 189 | void idaapi segend(ea_t ea); 190 | void idaapi assumes(ea_t ea); 191 | 192 | void idaapi out(void); 193 | int idaapi outspec(ea_t ea,uchar segtype); 194 | 195 | int idaapi ana(void); 196 | int idaapi emu(void); 197 | bool idaapi outop(op_t &op); 198 | void idaapi data(ea_t ea); 199 | 200 | int idaapi h8_is_align_insn(ea_t ea); 201 | bool idaapi create_func_frame(func_t *pfn); 202 | int idaapi is_sp_based(const op_t &x); 203 | bool idaapi is_return_insn(void); 204 | 205 | int idaapi h8_get_frame_retsize(func_t *); 206 | int is_jump_func(const func_t *pfn, ea_t *jump_target); 207 | int may_be_func(void); // can a function start here? 208 | int get_displ_outf(const op_t &x); 209 | int is_sane_insn(int nocrefs); 210 | bool idaapi h8_is_switch(switch_info_ex_t *si); 211 | void idaapi h8_gen_stkvar_def(char *buf, size_t bufsize, const member_t *mptr, sval_t v); 212 | 213 | 214 | // type system functions 215 | int h8_calc_arglocs(const type_t *type, cm_t cc, varloc_t *arglocs); 216 | bool h8_use_stkvar_type(ea_t ea, const type_t *type, const char *name); 217 | int h8_use_arg_types(ea_t caller, 218 | const type_t * const *types, 219 | const char * const *names, 220 | const varloc_t *arglocs, 221 | int n, 222 | const type_t **rtypes, 223 | const char **rnames, 224 | uint32 *rlocs, 225 | int rn); 226 | int h8_use_regvar_type(ea_t ea, 227 | const type_t * const *types, 228 | const char * const *names, 229 | const uint32 *regs, 230 | int n); 231 | 232 | #endif // _H8_HPP 233 | -------------------------------------------------------------------------------- /h8/ins.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-99 by Ilfak Guilfanov. 4 | * ALL RIGHTS RESERVED. 5 | * E-mail: ig@datarescue.com 6 | * 7 | * 8 | */ 9 | 10 | #include "h8.hpp" 11 | 12 | instruc_t Instructions[] = 13 | { 14 | { "", 0 }, // Unknown Operation 15 | 16 | { "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add binary 17 | { "adds", CF_USE1|CF_USE2|CF_CHG2 }, // Add with sign extension 18 | { "addx", CF_USE1|CF_USE2|CF_CHG2 }, // Add with extend carry 19 | { "and", CF_USE1|CF_USE2|CF_CHG2 }, // Logical AND 20 | { "andc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical AND with control register 21 | { "band", CF_USE1|CF_USE2|CF_CHG2 }, // Bit AND 22 | { "bra", CF_USE1|CF_STOP|CF_JUMP }, // Branch always 23 | { "brn", CF_USE1 }, // Branch never 24 | { "bhi", CF_USE1 }, // Branch if higher 25 | { "bls", CF_USE1 }, // Branch if lower or same 26 | { "bcc", CF_USE1 }, // Branch if carry clear (higher or same) 27 | { "bcs", CF_USE1 }, // Branch if carry set (lower) 28 | { "bne", CF_USE1 }, // Branch if not equal 29 | { "beq", CF_USE1 }, // Branch if equal 30 | { "bvc", CF_USE1 }, // Branch if overflow clear 31 | { "bvs", CF_USE1 }, // Branch if overflow set 32 | { "bpl", CF_USE1 }, // Branch if plus 33 | { "bmi", CF_USE1 }, // Branch if minus 34 | { "bge", CF_USE1 }, // Branch if greates or equal 35 | { "blt", CF_USE1 }, // Branch if less 36 | { "bgt", CF_USE1 }, // Branch if greater 37 | { "ble", CF_USE1 }, // Branch if less or equal 38 | { "bclr", CF_USE1|CF_USE2|CF_CHG2 }, // Bit clear 39 | { "biand", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert AND 40 | { "bild", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert load 41 | { "bior", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert OR 42 | { "bist", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert store 43 | { "bixor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert XOR 44 | { "bld", CF_USE1|CF_USE2 }, // Bit load 45 | { "bnot", CF_USE1|CF_USE2|CF_CHG2 }, // Bit NOT 46 | { "bor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit OR 47 | { "bset", CF_USE1|CF_USE2|CF_CHG2 }, // Bit set 48 | { "bsr", CF_USE1|CF_CALL }, // Branch to subroutine 49 | { "bst", CF_USE1|CF_USE2|CF_CHG2 }, // Bit store 50 | { "btst", CF_USE1|CF_USE2 }, // Bit test 51 | { "bxor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit XOR 52 | { "clrmac", 0 }, // Clear MAC register 53 | { "cmp", CF_USE1|CF_USE2 }, // Compare 54 | { "daa", CF_USE1|CF_CHG1 }, // Decimal adjust add 55 | { "das", CF_USE1|CF_CHG1 }, // Decimal adjust subtract 56 | { "dec", CF_USE1|CF_USE2|CF_CHG2 }, // Decrement 57 | { "divxs", CF_USE1|CF_USE2|CF_CHG2 }, // Divide extended as signed 58 | { "divxu", CF_USE1|CF_USE2|CF_CHG2 }, // Divide extended as unsigned 59 | { "eepmov", 0 }, // Move data to EEPROM 60 | { "exts", CF_USE1|CF_USE2|CF_CHG2 }, // Extend as signed 61 | { "extu", CF_USE1|CF_USE2|CF_CHG2 }, // Extend as unsigned 62 | { "inc", CF_USE1|CF_USE2|CF_CHG2 }, // Increment 63 | { "jmp", CF_USE1|CF_STOP|CF_JUMP }, // Jump 64 | { "jsr", CF_USE1|CF_CALL }, // Jump to subroutine 65 | { "ldc", CF_USE1|CF_CHG2 }, // Load to control register 66 | { "ldm", CF_USE1|CF_CHG2 }, // Load to multiple registers 67 | { "ldmac", CF_USE1|CF_CHG2 }, // Load to MAC register 68 | { "mac", CF_USE1|CF_USE2 }, // Multiply and accumulate 69 | { "mov", CF_USE1|CF_CHG2 }, // Move data 70 | { "movfpe", CF_USE1|CF_CHG2 }, // Move from peripheral with E clock 71 | { "movtpe", CF_USE1|CF_CHG2 }, // Move to peripheral with E clock 72 | { "mulxs", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply extend as signed 73 | { "mulxu", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply extend as unsigned 74 | { "neg", CF_USE1|CF_CHG1 }, // Negate 75 | { "nop", 0 }, // No operation 76 | { "not", CF_USE1|CF_CHG1 }, // Logical complement 77 | { "or", CF_USE1|CF_USE2|CF_CHG2 }, // Logical OR 78 | { "orc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical OR with control register 79 | { "pop", CF_CHG1 }, // Pop data from stack 80 | { "push", CF_USE1 }, // Push data on stack 81 | { "rotl", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate left 82 | { "rotr", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate right 83 | { "rotxl", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate with extend carry left 84 | { "rotxr", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate with extend carry right 85 | { "rte", CF_STOP }, // Return from exception 86 | { "rts", CF_STOP }, // Return from subroutine 87 | { "shal", CF_USE1|CF_USE2|CF_CHG2 }, // Shift arithmetic left 88 | { "shar", CF_USE1|CF_USE2|CF_CHG2 }, // Shift arithmetic right 89 | { "shll", CF_USE1|CF_USE2|CF_CHG2 }, // Shift logical left 90 | { "shlr", CF_USE1|CF_USE2|CF_CHG2 }, // Shift logical right 91 | { "sleep", 0 }, // Power down mode 92 | { "stc", CF_USE1|CF_CHG2 }, // Store from control register 93 | { "stm", CF_USE1|CF_CHG2 }, // Store from multiple registers 94 | { "stmac", CF_USE1|CF_CHG2 }, // Store from MAC register 95 | { "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract binary 96 | { "subs", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract with sign extension 97 | { "subx", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract with extend carry 98 | { "tas", CF_USE1|CF_CHG1 }, // Test and set 99 | { "trapa", CF_USE1|CF_CALL }, // Trap always 100 | { "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Logical XOR 101 | { "xorc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical XOR with control register 102 | 103 | // H8SX 104 | { "rte/l", CF_STOP|CF_USE1|CF_CHG1 }, // Returns from an exception, 105 | // restoring data to multiple general registers 106 | { "rts/l", CF_STOP|CF_USE1|CF_CHG1 }, // Returns from a subroutine, 107 | // restoring data to multiple general registers 108 | { "movmd", 0 }, // Transfers a data block 109 | { "movsd", CF_USE1 }, // Transfers a data block with zero detection 110 | { "bra/s", CF_USE1|CF_STOP }, // Branch always after the next instruction (delay slot) 111 | { "mova/b", CF_USE1|CF_CHG2 }, // MOVe effective Address/B 112 | { "mova/w", CF_USE1|CF_CHG2 }, // MOVe effective Address/W 113 | { "mova/l", CF_USE1|CF_CHG2 }, // MOVe effective Address/L 114 | { "bset/ne", CF_USE1|CF_USE2|CF_CHG2 }, // Bit SET if Not Equal 115 | { "bset/eq", CF_USE1|CF_USE2|CF_CHG2 }, // Bit SET if EQual 116 | { "bclr/ne", CF_USE1|CF_USE2|CF_CHG2 }, // Bit CLeaR if Not Equal 117 | { "bclr/eq", CF_USE1|CF_USE2|CF_CHG2 }, // Bit CLear if EQual 118 | { "bstz", CF_USE1|CF_USE2|CF_CHG2 }, // Bit STore Zero flag 119 | { "bistz", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Invert STore Zero flag 120 | { "bfld", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Bit Field LoaD 121 | { "bfst", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Bit Field STore 122 | { "muls", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Signed 123 | { "divs", CF_USE1|CF_USE2|CF_CHG2 }, // DIVide as Signed 124 | { "mulu", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Unsigned 125 | { "divu", CF_USE1|CF_USE2|CF_CHG2 }, // DIVide as Unsigned 126 | { "muls/u", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Signed 127 | { "mulu/u", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Unsigned 128 | { "bra/bc", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // BRAnch if Bit Cleared 129 | { "bra/bs", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // BRAnch if Bit Set 130 | { "bsr/bc", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to SubRoutine if Bit Cleared 131 | { "bsr/bs", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to SubRoutine if Bit Set 132 | }; 133 | 134 | CASSERT(qnumber(Instructions) == H8_last); 135 | -------------------------------------------------------------------------------- /h8/ins.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-2008 Hex-Rays 4 | * ALL RIGHTS RESERVED. 5 | * 6 | */ 7 | 8 | #ifndef __INSTRS_HPP 9 | #define __INSTRS_HPP 10 | 11 | extern instruc_t Instructions[]; 12 | 13 | enum nameNum ENUM_SIZE(uint16) 14 | { 15 | 16 | H8_null = 0, // Unknown Operation 17 | 18 | H8_add, // Add binary 19 | H8_adds, // Add with sign extension 20 | H8_addx, // Add with extend carry 21 | H8_and, // Logical AND 22 | H8_andc, // Logical AND with control register 23 | H8_band, // Bit AND 24 | H8_bra, // Branch always 25 | H8_brn, // Branch never 26 | H8_bhi, // Branch if higher 27 | H8_bls, // Branch if lower or same 28 | H8_bcc, // Branch if carry clear (higher or same) 29 | H8_bcs, // Branch if carry set (lower) 30 | H8_bne, // Branch if not equal 31 | H8_beq, // Branch if equal 32 | H8_bvc, // Branch if overflow clear 33 | H8_bvs, // Branch if overflow set 34 | H8_bpl, // Branch if plus 35 | H8_bmi, // Branch if minus 36 | H8_bge, // Branch if greates or equal 37 | H8_blt, // Branch if less 38 | H8_bgt, // Branch if greater 39 | H8_ble, // Branch if less or equal 40 | H8_bclr, // Bit clear 41 | H8_biand, // Bit invert AND 42 | H8_bild, // Bit invert load 43 | H8_bior, // Bit invert OR 44 | H8_bist, // Bit invert store 45 | H8_bixor, // Bit invert XOR 46 | H8_bld, // Bit load 47 | H8_bnot, // Bit NOT 48 | H8_bor, // Bit OR 49 | H8_bset, // Bit set 50 | H8_bsr, // Branch to subroutine 51 | H8_bst, // Bit store 52 | H8_btst, // Bit test 53 | H8_bxor, // Bit XOR 54 | H8_clrmac, // Clear MAC register 55 | H8_cmp, // Compare 56 | H8_daa, // Decimal adjust add 57 | H8_das, // Decimal adjust subtract 58 | H8_dec, // Decrement 59 | H8_divxs, // Divide extended as signed 60 | H8_divxu, // Divide extended as unsigned 61 | H8_eepmov, // Move data to EEPROM 62 | H8_exts, // Extend as signed 63 | H8_extu, // Extend as unsigned 64 | H8_inc, // Increment 65 | H8_jmp, // Jump 66 | H8_jsr, // Jump to subroutine 67 | H8_ldc, // Load to control register 68 | H8_ldm, // Load to multiple registers 69 | H8_ldmac, // Load to MAC register 70 | H8_mac, // Multiply and accumulate 71 | H8_mov, // Move data 72 | H8_movfpe, // Move from peripheral with E clock 73 | H8_movtpe, // Move to peripheral with E clock 74 | H8_mulxs, // Multiply extend as signed 75 | H8_mulxu, // Multiply extend as unsigned 76 | H8_neg, // Negate 77 | H8_nop, // No operation 78 | H8_not, // Logical complement 79 | H8_or, // Logical OR 80 | H8_orc, // Logical OR with control register 81 | H8_pop, // Pop data from stack 82 | H8_push, // Push data on stack 83 | H8_rotl, // Rotate left 84 | H8_rotr, // Rotate right 85 | H8_rotxl, // Rotate with extend carry left 86 | H8_rotxr, // Rotate with extend carry right 87 | H8_rte, // Return from exception 88 | H8_rts, // Return from subroutine 89 | H8_shal, // Shift arithmetic left 90 | H8_shar, // Shift arithmetic right 91 | H8_shll, // Shift logical left 92 | H8_shlr, // Shift logical right 93 | H8_sleep, // Power down mode 94 | H8_stc, // Store from control register 95 | H8_stm, // Store from multiple registers 96 | H8_stmac, // Store from MAC register 97 | H8_sub, // Subtract binary 98 | H8_subs, // Subtract with sign extension 99 | H8_subx, // Subtract with extend carry 100 | H8_tas, // Test and set 101 | H8_trapa, // Trap always 102 | H8_xor, // Logical XOR 103 | H8_xorc, // Logical XOR with control register 104 | 105 | // H8SX 106 | H8_rtel, // Returns from an exception, restoring data to multiple general registers 107 | H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers 108 | H8_movmd, // Transfers a data block 109 | H8_movsd, // Transfers a data block with zero detection 110 | H8_bras, // Branch always after the next instruction (delay slot) 111 | H8_movab, // MOVe effective Address/B 112 | H8_movaw, // MOVe effective Address/W 113 | H8_moval, // MOVe effective Address/L 114 | H8_bsetne, // Bit SET if Not Equal 115 | H8_bseteq, // Bit SET if EQual 116 | H8_bclrne, // Bit CLeaR if Not Equal 117 | H8_bclreq, // Bit CLeaR if Equal 118 | H8_bstz, // Bit STore Zero flag 119 | H8_bistz, // Bit Invert STore Zero flag 120 | H8_bfld, // Bit Field LoaD 121 | H8_bfst, // Bit Field STore 122 | H8_muls, // MULtiply as Signed 123 | H8_divs, // DIVide as Signed 124 | H8_mulu, // MULtiply as Unsigned 125 | H8_divu, // DIVide as Unsigned 126 | H8_mulsu, // MULtiply as Signed 127 | H8_muluu, // MULtiply as Unsigned 128 | H8_brabc, // BRAnch if Bit Cleared 129 | H8_brabs, // BRAnch if Bit Set 130 | H8_bsrbc, // Branch to SubRoutine if Bit Cleared 131 | H8_bsrbs, // Branch to SubRoutine if Bit Set 132 | 133 | H8_last, 134 | 135 | }; 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /h8/makefile: -------------------------------------------------------------------------------- 1 | PROC=h8 2 | ADDITIONAL_GOALS=config 3 | 4 | include ../module.mak 5 | 6 | config: $(C)h8.cfg 7 | $(C)h8.cfg: h8.cfg 8 | $(CP) $? $@ 9 | 10 | # MAKEDEP dependency list ------------------ 11 | $(F)ana$(O) : $(I)area.hpp $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ 12 | $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ 13 | $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ 14 | $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ 15 | $(I)offset.hpp $(I)pro.h $(I)queue.hpp $(I)segment.hpp \ 16 | $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp h8.hpp \ 17 | ins.hpp 18 | $(F)emu$(O) : $(I)area.hpp $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ 19 | $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp \ 20 | $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ 21 | $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ 22 | $(I)offset.hpp $(I)pro.h $(I)queue.hpp $(I)segment.hpp \ 23 | $(I)srarea.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ 24 | ../jptcmn.cpp emu.cpp h8.hpp ins.hpp 25 | $(F)ins$(O) : $(I)area.hpp $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ 26 | $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ 27 | $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ 28 | $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ 29 | $(I)offset.hpp $(I)pro.h $(I)queue.hpp $(I)segment.hpp \ 30 | $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp h8.hpp ins.cpp \ 31 | ins.hpp 32 | $(F)out$(O) : $(I)area.hpp $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ 33 | $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ 34 | $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ 35 | $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ 36 | $(I)offset.hpp $(I)pro.h $(I)queue.hpp $(I)segment.hpp \ 37 | $(I)srarea.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ 38 | ../idaidp.hpp h8.hpp ins.hpp out.cpp 39 | $(F)reg$(O) : $(I)area.hpp $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ 40 | $(I)diskio.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ 41 | $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ 42 | $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ 43 | $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ 44 | $(I)queue.hpp $(I)segment.hpp $(I)srarea.hpp $(I)ua.hpp \ 45 | $(I)xref.hpp ../idaidp.hpp h8.hpp ins.hpp reg.cpp 46 | -------------------------------------------------------------------------------- /h8/out.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-99 by Ilfak Guilfanov. 4 | * ALL RIGHTS RESERVED. 5 | * E-mail: ig@datarescue.com 6 | * 7 | * 8 | */ 9 | 10 | #include "h8.hpp" 11 | #include 12 | #include 13 | 14 | //---------------------------------------------------------------------- 15 | int get_displ_outf(const op_t &x) 16 | { 17 | return OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED 18 | | ((isStkvar(uFlag,x.n) || (x.szfl & disp_32) || advanced()) ? OOFW_32 : OOFW_16); 19 | } 20 | 21 | //---------------------------------------------------------------------- 22 | static void out_bad_address(ea_t addr) 23 | { 24 | const char *name = find_sym(addr); 25 | if ( name != NULL ) 26 | { 27 | out_line(name, COLOR_IMPNAME); 28 | } 29 | else 30 | { 31 | out_tagon(COLOR_ERROR); 32 | OutLong(addr, 16); 33 | out_tagoff(COLOR_ERROR); 34 | QueueSet(Q_noName, cmd.ea); 35 | } 36 | } 37 | 38 | //---------------------------------------------------------------------- 39 | inline void outreg(int r) 40 | { 41 | out_register(ph.regNames[r]); 42 | } 43 | 44 | //---------------------------------------------------------------------- 45 | ea_t trim_ea_branch(ea_t ea) 46 | { 47 | switch ( ptype & MODE_MASK ) 48 | { 49 | case MODE_MID: 50 | case MODE_ADV: 51 | return ea & 0x00FFFFFF; 52 | case MODE_MAX: 53 | return ea; 54 | } 55 | return ea & 0x0000FFFF; 56 | } 57 | 58 | //---------------------------------------------------------------------- 59 | ea_t calc_mem(ea_t ea) 60 | { 61 | return toEA(cmd.cs, ea); 62 | } 63 | 64 | //---------------------------------------------------------------------- 65 | ea_t calc_mem_sbr_based(ea_t ea) 66 | { 67 | sel_t base = get_segreg(cmd.ea, SBR); 68 | return (base & 0xFFFFFF00) | (ea & 0x000000FF); 69 | } 70 | 71 | //---------------------------------------------------------------------- 72 | static void out_sizer(char szfl) 73 | { 74 | static char show_sizer = -1; 75 | if ( show_sizer == -1 ) 76 | show_sizer = !qgetenv("H8_NOSIZER"); 77 | if ( !show_sizer ) 78 | return; 79 | 80 | if ( szfl & disp_2 ) 81 | return; 82 | int size = (szfl & disp_32) ? 32 : 83 | (szfl & disp_24) ? 24 : 84 | (szfl & disp_16) ? 16 : 8; 85 | out_symbol(':'); 86 | out_long(size, 10); 87 | } 88 | 89 | //---------------------------------------------------------------------- 90 | static void attach_name_comment(const op_t &x, ea_t v) 91 | { 92 | char buf[MAXSTR]; 93 | if ( get_name_expr(cmd.ea, x.n, v, BADADDR, buf, sizeof(buf)) > 0 94 | && !has_cmt(get_flags_novalue(cmd.ea)) ) 95 | { 96 | set_cmt(cmd.ea, buf, false); 97 | } 98 | } 99 | 100 | //---------------------------------------------------------------------- 101 | static ea_t get_data_ref(ea_t ea) 102 | { 103 | ea_t to = BADADDR; 104 | xrefblk_t xb; 105 | for ( bool ok=xb.first_from(ea, XREF_DATA); ok; ok=xb.next_from() ) 106 | { 107 | if ( xb.type == dr_O ) 108 | return xb.to; 109 | } 110 | return to; 111 | } 112 | 113 | //---------------------------------------------------------------------- 114 | //lint -esym(1764,x) 115 | bool idaapi outop(op_t &x) 116 | { 117 | switch ( x.type ) 118 | { 119 | 120 | case o_void: 121 | return 0; 122 | 123 | case o_reg: 124 | outreg(x.reg); 125 | break; 126 | 127 | case o_reglist: 128 | if ( is_hew_asm() ) 129 | out_symbol('('); 130 | outreg(x.reg); 131 | out_symbol('-'); 132 | outreg(x.reg+x.nregs-1); 133 | if ( is_hew_asm() ) 134 | out_symbol(')'); 135 | break; 136 | 137 | case o_imm: 138 | out_symbol('#'); 139 | OutValue(x, OOFS_IFSIGN|OOFW_IMM); 140 | break; 141 | 142 | case o_mem: 143 | out_symbol('@'); 144 | if ( x.memtype == mem_vec7 || x.memtype == mem_ind ) 145 | out_symbol('@'); 146 | // no break 147 | case o_near: 148 | { 149 | ea_t ea = x.memtype == mem_sbr ? 150 | calc_mem_sbr_based(x.addr) : 151 | calc_mem(x.addr); 152 | if ( is_hew_asm() && (x.szfl & disp_24) ) 153 | out_symbol('@'); 154 | out_addr_tag(ea); 155 | if ( x.memtype == mem_sbr 156 | || !out_name_expr(x, ea, x.addr) ) 157 | { 158 | out_bad_address(x.addr); 159 | if ( x.memtype == mem_sbr ) 160 | attach_name_comment(x, ea); 161 | } 162 | if ( x.memtype != mem_vec7 ) 163 | out_sizer(x.szfl); 164 | } 165 | break; 166 | 167 | case o_phrase: 168 | out_symbol('@'); 169 | 170 | if ( x.phtype == ph_pre_dec ) 171 | out_symbol('-'); 172 | else if ( x.phtype == ph_pre_inc ) 173 | out_symbol('+'); 174 | 175 | outreg(x.phrase); 176 | 177 | if ( x.phtype == ph_post_inc ) 178 | out_symbol('+'); 179 | else if ( x.phtype == ph_post_dec ) 180 | out_symbol('-'); 181 | 182 | { 183 | ea_t ea = get_data_ref(cmd.ea); 184 | if ( ea != BADADDR ) 185 | attach_name_comment(x, ea); 186 | } 187 | break; 188 | 189 | case o_displ: 190 | out_symbol('@'); 191 | out_symbol('('); 192 | OutValue(x, get_displ_outf(x)); 193 | out_sizer(x.szfl); 194 | out_symbol(','); 195 | if ( x.displtype == dt_movaop1 ) 196 | { 197 | op_t ea; 198 | memset(&ea, 0, sizeof(ea)); 199 | ea.offb = cmd.Op1.offo; 200 | ea.type = cmd.Op1.idxt; 201 | ea.phrase = cmd.Op1.phrase; 202 | ea.phtype = cmd.Op1.idxdt; 203 | ea.addr = cmd.Op1.value; 204 | ea.szfl = cmd.Op1.idxsz; 205 | outop(ea); 206 | out_symbol('.'); 207 | out_symbol(x.szfl & idx_byte ? 'b' : 208 | x.szfl & idx_word ? 'w' : 'l'); 209 | } 210 | else if ( x.displtype == dt_regidx ) 211 | { 212 | outreg(x.reg); 213 | out_symbol('.'); 214 | out_symbol(x.szfl & idx_byte ? 'b' : 215 | x.szfl & idx_word ? 'w' : 'l'); 216 | } 217 | else 218 | { 219 | outreg(x.reg); 220 | } 221 | out_symbol(')'); 222 | break; 223 | 224 | case o_pcidx: 225 | outreg(x.reg); 226 | break; 227 | 228 | default: 229 | INTERR(10096); 230 | } 231 | return 1; 232 | } 233 | 234 | //---------------------------------------------------------------------- 235 | void idaapi out(void) 236 | { 237 | static const char *const postfixes[] = { NULL, ".b", ".w", ".l" }; 238 | char buf[MAXSTR]; 239 | init_output_buffer(buf, sizeof(buf)); 240 | 241 | const char *postfix = postfixes[cmd.auxpref]; 242 | OutMnem(8, postfix); 243 | 244 | bool showOp1 = cmd.Op1.shown(); 245 | if ( showOp1 ) 246 | out_one_operand(0); 247 | if ( cmd.Op2.type != o_void ) 248 | { 249 | if ( showOp1 ) 250 | { 251 | out_symbol(','); 252 | OutChar(' '); 253 | } 254 | out_one_operand(1); 255 | } 256 | if ( cmd.Op3.type != o_void ) 257 | { 258 | out_symbol(','); 259 | OutChar(' '); 260 | out_one_operand(2); 261 | } 262 | 263 | for ( int i=0; i < 3; i++ ) 264 | if ( isVoid(cmd.ea, uFlag, i) ) 265 | OutImmChar(cmd.Operands[i]); 266 | 267 | term_output_buffer(); 268 | gl_comm = 1; 269 | MakeLine(buf); 270 | } 271 | 272 | //-------------------------------------------------------------------------- 273 | void idaapi segstart(ea_t ea) 274 | { 275 | const char *predefined[] = 276 | { 277 | ".text", // Text section 278 | ".rdata", // Read-only data section 279 | ".data", // Data sections 280 | ".lit8", // Data sections 281 | ".lit4", // Data sections 282 | ".sdata", // Small data section, addressed through register $gp 283 | ".sbss", // Small bss section, addressed through register $gp 284 | }; 285 | 286 | segment_t *Sarea = getseg(ea); 287 | if ( Sarea == NULL || is_spec_segm(Sarea->type) ) 288 | return; 289 | 290 | char sname[MAXNAMELEN]; 291 | char sclas[MAXNAMELEN]; 292 | get_true_segm_name(Sarea, sname, sizeof(sname)); 293 | get_segm_class(Sarea, sclas, sizeof(sclas)); 294 | 295 | int i; 296 | for ( i=0; i < qnumber(predefined); i++ ) 297 | if ( strcmp(sname, predefined[i]) == 0 ) 298 | break; 299 | if ( i != qnumber(predefined) ) 300 | printf_line(inf.indent, COLSTR("%s", SCOLOR_ASMDIR), sname); 301 | else 302 | printf_line(inf.indent, COLSTR("%s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT), 303 | strcmp(sclas,"CODE") == 0 ? ".text" : ".data", 304 | ash.cmnt, 305 | sname); 306 | } 307 | 308 | //-------------------------------------------------------------------------- 309 | void idaapi segend(ea_t) 310 | { 311 | #if 0 312 | segment_t *s = getseg(ea-1); 313 | if ( !is_spec_segm(s->type) ) 314 | printf_line(0,COLSTR(";%-*s ends",SCOLOR_AUTOCMT),inf.indent-2,get_segm_name(s)); 315 | #endif 316 | } 317 | 318 | //-------------------------------------------------------------------------- 319 | void idaapi assumes(ea_t ea) 320 | { 321 | segment_t *seg = getseg(ea); 322 | if ( !inf.s_assume || seg == NULL ) 323 | return; 324 | bool seg_started = (ea == seg->startEA); 325 | 326 | for ( int i = ph.regFirstSreg; i <= ph.regLastSreg; i++ ) 327 | { 328 | if ( i == ph.regCodeSreg || i == ph.regDataSreg ) 329 | continue; 330 | segreg_area_t sra; 331 | if ( !get_srarea2(&sra, ea, i) ) 332 | continue; 333 | bool show = sra.startEA == ea; 334 | if ( show ) 335 | { 336 | segreg_area_t prev_sra; 337 | if ( get_prev_srarea(&prev_sra, ea, i) ) 338 | show = sra.val != prev_sra.val; 339 | } 340 | if ( seg_started || show ) 341 | gen_cmt_line("%-*s assume %s: %a", int(inf.indent-strlen(ash.cmnt)-2), "", ph.regNames[i], sra.val); 342 | } 343 | } 344 | 345 | //-------------------------------------------------------------------------- 346 | // Generate stack variable definition line 347 | // If this function is NULL, then the kernel will create the line itself. 348 | void idaapi h8_gen_stkvar_def(char *buf, size_t bufsize, const member_t *mptr, sval_t v) 349 | { 350 | char sign = ' '; 351 | if ( v < 0 ) 352 | { 353 | v = -v; 354 | sign = '-'; 355 | } 356 | 357 | char num[MAX_NUMBUF]; 358 | btoa(num, sizeof(num), v); 359 | 360 | qstring name = get_member_name2(mptr->id); 361 | if ( is_hew_asm() ) 362 | { 363 | qsnprintf(buf, bufsize, 364 | COLSTR("%s", SCOLOR_LOCNAME) 365 | COLSTR(": ", SCOLOR_SYMBOL) 366 | COLSTR(".assign", SCOLOR_ASMDIR) 367 | COLSTR(" %c", SCOLOR_SYMBOL) 368 | COLSTR("%s", SCOLOR_DNUM), 369 | name.c_str(), sign, num); 370 | } 371 | else 372 | { 373 | qsnprintf(buf, bufsize, 374 | COLSTR("%-*s", SCOLOR_LOCNAME) 375 | COLSTR("= %c", SCOLOR_SYMBOL) 376 | COLSTR("%s", SCOLOR_DNUM), inf.indent, name.c_str(), sign, num); 377 | } 378 | } 379 | 380 | //-------------------------------------------------------------------------- 381 | void idaapi header(void) 382 | { 383 | gen_header(GH_PRINT_ALL); 384 | 385 | if ( ptype == P300 ) 386 | return; 387 | char procdir[MAXSTR]; 388 | qsnprintf(procdir, MAXSTR, ".h8300%s%s", 389 | is_h8sx() ? "sx" : is_h8s() ? "s" : "h", 390 | advanced() ? "" : "n"); 391 | MakeNull(); 392 | printf_line(inf.indent, "%s", procdir); 393 | } 394 | 395 | //-------------------------------------------------------------------------- 396 | void idaapi footer(void) 397 | { 398 | qstring nbuf = get_colored_name(inf.beginEA); 399 | const char *name = nbuf.c_str(); 400 | const char *end = ash.end; 401 | if ( end == NULL ) 402 | printf_line(inf.indent, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name); 403 | else 404 | printf_line(inf.indent, 405 | COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), 406 | ash.end, 407 | ash.cmnt, 408 | name); 409 | } 410 | -------------------------------------------------------------------------------- /h8/reg.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Interactive disassembler (IDA). 3 | * Copyright (c) 1990-2001 by Ilfak Guilfanov. 4 | * ALL RIGHTS RESERVED. 5 | * FIDO: 2:5020/209 6 | * E-mail: ig@datarescue.com 7 | * 8 | */ 9 | 10 | #include "h8.hpp" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | //-------------------------------------------------------------------------- 19 | static const char *register_names[] = 20 | { 21 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 22 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", 23 | "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", 24 | "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", 25 | "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", 26 | "macl", "mach", 27 | "pc", 28 | "ccr", "exr", 29 | "cs","ds", // virtual registers for code and data segments 30 | "vbr", "sbr", 31 | }; 32 | 33 | //-------------------------------------------------------------------------- 34 | static const uchar startcode_0[] = { 0x01, 0x00, 0x6D, 0xF3 }; // push.l er3 35 | static const uchar startcode_1[] = { 0x6D, 0xF3 }; // push.w r3 36 | 37 | static const bytes_t startcodes[] = 38 | { 39 | { sizeof(startcode_0), startcode_0 }, 40 | { sizeof(startcode_1), startcode_1 }, 41 | { 0, NULL } 42 | }; 43 | 44 | //----------------------------------------------------------------------- 45 | // GNU ASM 46 | //----------------------------------------------------------------------- 47 | static const asm_t gas = 48 | { 49 | AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, 50 | 0, 51 | "GNU assembler", 52 | 0, 53 | NULL, // header lines 54 | NULL, // no bad instructions 55 | ".org", // org 56 | NULL, // end 57 | 58 | ";", // comment string 59 | '"', // string delimiter 60 | '"', // char delimiter 61 | "\"", // special symbols in char and string constants 62 | 63 | ".ascii", // ascii string directive 64 | ".byte", // byte directive 65 | ".word", // word directive 66 | ".long", // double words 67 | NULL, // qwords 68 | NULL, // oword (16 bytes) 69 | ".float", // float (4 bytes) 70 | ".double", // double (8 bytes) 71 | NULL, // tbyte (10/12 bytes) 72 | NULL, // packed decimal real 73 | NULL, // arrays (#h,#d,#v,#s(...) 74 | ".space %s", // uninited arrays 75 | "=", // equ 76 | NULL, // 'seg' prefix (example: push seg seg001) 77 | NULL, // Pointer to checkarg_preline() function. 78 | NULL, // char *(*checkarg_atomprefix)(char *operand,void *res); // if !NULL, is called before each atom 79 | NULL, // const char **checkarg_operations; 80 | NULL, // translation to use in character and string constants. 81 | NULL, // current IP (instruction pointer) 82 | NULL, // func_header 83 | NULL, // func_footer 84 | ".globl", // "public" name keyword 85 | NULL, // "weak" name keyword 86 | ".extern", // "extrn" name keyword 87 | // .extern directive requires an explicit object size 88 | ".comm", // "comm" (communal variable) 89 | NULL, // get_type_name 90 | ".align", // "align" keyword 91 | '(', ')', // lbrace, rbrace 92 | "%", // mod 93 | "&", // and 94 | "|", // or 95 | "^", // xor 96 | "~", // not 97 | "<<", // shl 98 | ">>", // shr 99 | NULL, // sizeof_fmt 100 | 0, // flag2 101 | NULL, // cmnt2 102 | NULL, // low8 103 | NULL, // high8 104 | NULL, // low16 105 | NULL, // high16 106 | "#include \"%s\"", // a_include_fmt 107 | NULL, // a_vstruc_fmt 108 | NULL, // a_3byte 109 | NULL, // a_rva 110 | NULL, // a_yword 111 | }; 112 | 113 | //----------------------------------------------------------------------- 114 | // HEW ASM 115 | //----------------------------------------------------------------------- 116 | const asm_t hew = 117 | { 118 | AS_ASCIIC|AS_ALIGN2|ASH_HEXF1|ASD_DECF0|ASO_OCTF7|ASB_BINF4|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, 119 | UAS_HEW, 120 | "HEW assembler", 121 | 0, 122 | NULL, // header lines 123 | NULL, // no bad instructions 124 | ".org", // org 125 | ".end", // end 126 | 127 | ";", // comment string 128 | '"', // string delimiter 129 | '"', // char delimiter 130 | "\"", // special symbols in char and string constants 131 | 132 | ".sdata", // ascii string directive 133 | ".data.b", // byte directive 134 | ".data.w", // word directive 135 | ".data.l", // double words 136 | NULL, // qwords 137 | NULL, // oword (16 bytes) 138 | ".float", // float (4 bytes) 139 | ".double", // double (8 bytes) 140 | NULL, // tbyte (10/12 bytes) 141 | NULL, // packed decimal real 142 | NULL, // arrays (#h,#d,#v,#s(...) 143 | ".res %s", // uninited arrays 144 | ": .assign", // equ that allows set/reset values 145 | //": .equ", // equ (does not allow for reuse) 146 | //": .reg (%s)",// equ for regs (does not allow for reuse) 147 | //": .bequ", // equ for bits (does not allow for reuse) 148 | NULL, // 'seg' prefix (example: push seg seg001) 149 | NULL, // Pointer to checkarg_preline() function. 150 | NULL, // char *(*checkarg_atomprefix)(char *operand,void *res); // if !NULL, is called before each atom 151 | NULL, // const char **checkarg_operations; 152 | NULL, // translation to use in character and string constants. 153 | "$", // current IP (instruction pointer) 154 | NULL, // func_header 155 | NULL, // func_footer 156 | ".global", // "public" name keyword 157 | NULL, // "weak" name keyword 158 | ".global", // "extrn" name keyword 159 | ".comm", // "comm" (communal variable) 160 | NULL, // get_type_name 161 | ".align", // "align" keyword 162 | '(', ')', // lbrace, rbrace 163 | "%", // mod 164 | "&", // and 165 | "|", // or 166 | "~", // xor 167 | "~", // not 168 | "<<", // shl 169 | ">>", // shr 170 | "sizeof", // sizeof_fmt 171 | 0, // flag2 172 | NULL, // cmnt2 173 | "low", // low8 174 | "high", // high8 175 | "lword", // low16 176 | "hword", // high16 177 | ".include \"%s\"", // a_include_fmt 178 | NULL, // a_vstruc_fmt 179 | NULL, // a_3byte 180 | NULL, // a_rva 181 | NULL, // a_yword 182 | }; 183 | 184 | static const asm_t *const asms[] = { &gas, &hew, NULL }; 185 | 186 | //-------------------------------------------------------------------------- 187 | static char device[MAXSTR] = ""; 188 | static ioport_t *ports = NULL; 189 | static size_t numports = 0; 190 | static const char cfgname[] = "h8.cfg"; 191 | 192 | static void load_symbols(void) 193 | { 194 | free_ioports(ports, numports); 195 | ports = read_ioports(&numports, cfgname, device, sizeof(device), NULL); 196 | } 197 | 198 | //-------------------------------------------------------------------------- 199 | const char *find_sym(ea_t address) 200 | { 201 | const ioport_t *port = find_ioport(ports, numports, address); 202 | return port ? port->name : NULL; 203 | } 204 | 205 | //-------------------------------------------------------------------------- 206 | static const char *idaapi set_idp_options(const char *keyword,int /*value_type*/,const void * /*value*/) 207 | { 208 | if ( keyword != NULL ) 209 | return IDPOPT_BADKEY; 210 | if ( choose_ioport_device(cfgname, device, sizeof(device), NULL) ) 211 | load_symbols(); 212 | return IDPOPT_OK; 213 | } 214 | 215 | //-------------------------------------------------------------------------- 216 | netnode helper; 217 | proctype_t ptype; 218 | 219 | static const proctype_t ptypes[] = 220 | { 221 | P300, 222 | MODE_ADV | P300, 223 | P300 | P2000 | P2600, 224 | MODE_ADV | P300 | P2000 | P2600, 225 | P300 | P2000 | P2600 | PSX, 226 | MODE_MID | P300 | P2000 | P2600 | PSX, 227 | MODE_ADV | P300 | P2000 | P2600 | PSX, 228 | MODE_MAX | P300 | P2000 | P2600 | PSX, 229 | }; 230 | 231 | 232 | static int idaapi notify(processor_t::idp_notify msgid, ...) 233 | { 234 | int ret = 1; 235 | va_list va; 236 | va_start(va, msgid); 237 | 238 | // A well behaving processor module should call invoke_callbacks() 239 | // in his notify() function. If this function returns 0, then 240 | // the processor module should process the notification itself 241 | // Otherwise the code should be returned to the caller: 242 | 243 | int code = invoke_callbacks(HT_IDP, msgid, va); 244 | if ( code ) 245 | { 246 | ret = code; 247 | goto finish_up; 248 | } 249 | 250 | switch ( msgid ) 251 | { 252 | case processor_t::init: 253 | // __emit__(0xCC); // debugger trap 254 | helper.create("$ h8"); 255 | helper.supval(0, device, sizeof(device)); 256 | inf.mf = 1; 257 | break; 258 | 259 | /* +++ START TYPEINFO CALLBACKS +++ */ 260 | // see module/{i960,hppa}/reg.cpp starting on line 253 261 | // Decorate/undecorate a C symbol name 262 | // Arguments: 263 | // const til_t *ti - pointer to til 264 | // const char *name - name of symbol 265 | // const type_t *type - type of symbol. If NULL then it will try to guess. 266 | // char *outbuf - output buffer 267 | // size_t bufsize - size of the output buffer 268 | // bool mangle - true-mangle, false-unmangle 269 | // cm_t cc - real calling convention for VOIDARG functions 270 | // returns: true if success 271 | case processor_t::decorate_name: 272 | { 273 | const til_t *ti = va_arg(va, const til_t *); 274 | const char *name = va_arg(va, const char *); 275 | const type_t *type = va_arg(va, const type_t *); 276 | char *outbuf = va_arg(va, char *); 277 | size_t bufsize = va_arg(va, size_t); 278 | bool mangle = va_argi(va, bool); 279 | cm_t real_cc = va_argi(va, cm_t); 280 | return gen_decorate_name(ti, name, type, outbuf, bufsize, mangle, real_cc); 281 | } 282 | 283 | // Setup default type libraries (called after loading a new file into the database) 284 | // The processor module may load tils, setup memory model and perform other actions 285 | // required to set up the type system. 286 | // args: none 287 | // returns: nothing 288 | case processor_t::setup_til: 289 | { 290 | } 291 | 292 | // Purpose: get prefix and size of 'segment based' ptr type (something like 293 | // char _ss *ptr). See description in typeinf.hpp. 294 | // Other modules simply set the pointer to NULL and return 0 295 | // Ilfak confirmed that this approach is correct for the H8. 296 | // Used only for BTMT_CLOSURE types, doubtful you will encounter them for H8. 297 | // Arguments: 298 | // unsigned int ptrt - ... 299 | // const char **ptrname - output arg 300 | // returns: size of type 301 | case processor_t::based_ptr: 302 | { 303 | /*unsigned int ptrt =*/ va_arg(va, unsigned int); 304 | char **ptrname = va_arg(va, char **); 305 | *ptrname = NULL; 306 | return 0; 307 | } 308 | 309 | // The H8 supports normal (64KB addressing, 16 bits) and advanced mode 310 | // (16MB addressing, 24 bits). However, according to the Renesas technical 311 | // documentation, certain instructions accept 32-bit pointer values where 312 | // the upper 8 bits are "reserved". Ilfak confirms that "4+1" is fine. 313 | // Used only for BTMT_CLOSURE types, doubtful you will encounter them for H8. 314 | case processor_t::max_ptr_size: 315 | { 316 | return 4+1; 317 | } 318 | 319 | // get default enum size 320 | // args: cm_t cm 321 | // returns: sizeof(enum) 322 | case processor_t::get_default_enum_size: 323 | { 324 | // cm_t cm = va_argi(va, cm_t); 325 | return inf.cc.size_e; 326 | } 327 | 328 | case processor_t::use_stkarg_type: 329 | { 330 | ea_t ea = va_arg(va, ea_t); 331 | const type_t *type = va_arg(va, const type_t *); 332 | const char *name = va_arg(va, const char *); 333 | return h8_use_stkvar_type(ea, type, name); 334 | } 335 | 336 | // calculate number of purged bytes by the given function type 337 | // For cdecl functions, 'purged bytes' is always zero 338 | // See the IDA Pro Book, 2e, at the end of pp. 107 for details 339 | // args: type_t *type - must be function type 340 | // returns: number of bytes purged from the stack + 2 341 | case processor_t::calc_purged_bytes: 342 | { 343 | //e.g. const type_t t_int[] = { BT_INT, 0 }; 344 | //const type_t *type = va_arg(va, const type_t *); // must be BT_FUNC 345 | return 0+2; 346 | } 347 | 348 | case processor_t::calc_arglocs2: 349 | { 350 | const type_t *type = va_arg(va, const type_t *); 351 | cm_t cc = va_argi(va, cm_t); 352 | varloc_t *arglocs = va_arg(va, varloc_t *); 353 | return h8_calc_arglocs(type, cc, arglocs); 354 | } 355 | 356 | /* +++ END TYPEINFO CALLBACKS +++ */ 357 | 358 | case processor_t::term: 359 | free_ioports(ports, numports); 360 | break; 361 | 362 | case processor_t::newasm: // new assembler type selected 363 | { 364 | int asmnum = va_arg(va, int); 365 | bool hew_asm = asmnum == 1; 366 | if ( advanced() ) 367 | { 368 | register_names[R7] = "r7"; 369 | register_names[ER7] = hew_asm ? "er7" : "sp"; 370 | } 371 | else 372 | { 373 | register_names[R7] = hew_asm ? "r7" : "sp"; 374 | register_names[ER7] = "er7"; 375 | } 376 | } 377 | break; 378 | 379 | case processor_t::newfile: // new file loaded 380 | load_symbols(); 381 | if ( is_h8sx() ) 382 | { 383 | set_default_segreg_value(NULL, VBR, 0); 384 | set_default_segreg_value(NULL, SBR, 0xFFFFFF00); 385 | } 386 | break; 387 | 388 | case processor_t::oldfile: // old file loaded 389 | load_symbols(); 390 | break; 391 | 392 | case processor_t::closebase: 393 | case processor_t::savebase: 394 | helper.supset(0, device); 395 | break; 396 | 397 | case processor_t::newprc: // new processor type 398 | ptype = ptypes[va_arg(va, int)]; 399 | if ( advanced() ) 400 | { 401 | ph.flag |= PR_DEFSEG32; 402 | } 403 | if ( is_h8sx() ) 404 | { 405 | ph.flag |= PR_SEGS; 406 | ph.regLastSreg = SBR; 407 | ph.segreg_size = 4; 408 | } 409 | break; 410 | 411 | case processor_t::newseg: // new segment 412 | break; 413 | 414 | case processor_t::is_jump_func: 415 | { 416 | const func_t *pfn = va_arg(va, const func_t *); 417 | ea_t *jump_target = va_arg(va, ea_t *); 418 | ret = is_jump_func(pfn, jump_target); 419 | } 420 | break; 421 | 422 | case processor_t::is_sane_insn: 423 | ret = is_sane_insn(va_arg(va, int)); 424 | break; 425 | 426 | case processor_t::may_be_func: 427 | // can a function start here? 428 | // arg: none, the instruction is in 'cmd' 429 | // returns: probability 0..100 430 | // 'cmd' structure is filled upon the entrace 431 | // the idp module is allowed to modify 'cmd' 432 | ret = may_be_func(); 433 | break; 434 | 435 | case processor_t::gen_regvar_def: 436 | { 437 | regvar_t *v = va_arg(va, regvar_t*); 438 | if ( is_hew_asm() ) 439 | { 440 | printf_line(0, COLSTR("%s", SCOLOR_REG) 441 | COLSTR(": .reg (", SCOLOR_SYMBOL) 442 | COLSTR("%s", SCOLOR_REG) 443 | COLSTR(")", SCOLOR_SYMBOL), v->user, v->canon); 444 | ret = 0; 445 | } 446 | } 447 | break; 448 | 449 | case processor_t::is_ret_insn: 450 | { 451 | ea_t ea = va_arg(va, ea_t); 452 | insn_t saved = cmd; 453 | int code2 = decode_insn(ea) != 0 && is_return_insn() ? 2 : 0; 454 | cmd = saved; 455 | ret = code2; 456 | } 457 | break; 458 | 459 | default: 460 | break; 461 | } 462 | 463 | finish_up: 464 | va_end(va); 465 | return ret; 466 | } 467 | 468 | //----------------------------------------------------------------------- 469 | #define FAMILY "Hitachi H8:" 470 | static const char *const shnames[] = 471 | { 472 | "h8300", "h8300a", "h8s300", "h8s300a", "h8sxn", "h8sxm", "h8sxa", "h8sx", NULL 473 | }; 474 | static const char *const lnames[] = 475 | { 476 | FAMILY"Hitachi H8/300H normal", 477 | "Hitachi H8/300H advanced", 478 | "Hitachi H8S normal", 479 | "Hitachi H8S advanced", 480 | "Hitachi H8SX normal", 481 | "Hitachi H8SX middle", 482 | "Hitachi H8SX advanced", 483 | "Hitachi H8SX maximum", 484 | NULL 485 | }; 486 | 487 | //----------------------------------------------------------------------- 488 | // Processor Definition 489 | //----------------------------------------------------------------------- 490 | processor_t LPH = 491 | { 492 | IDP_INTERFACE_VERSION, // version 493 | PLFM_H8, // id 494 | PRN_HEX | PR_USE32 | PR_WORD_INS | PR_TYPEINFO, 495 | 8, // 8 bits in a byte for code segments 496 | 8, // 8 bits in a byte for other segments 497 | 498 | shnames, 499 | lnames, 500 | 501 | asms, 502 | 503 | notify, 504 | 505 | header, 506 | footer, 507 | 508 | segstart, 509 | segend, 510 | 511 | assumes, // generate "assume" directives 512 | 513 | ana, // analyze instruction 514 | emu, // emulate instruction 515 | 516 | out, // generate text representation of instruction 517 | outop, // generate ... operand 518 | intel_data, // generate ... data directive 519 | NULL, // compare operands 520 | NULL, // can have type 521 | 522 | qnumber(register_names), // Number of registers 523 | register_names, // Register names 524 | NULL, // get abstract register 525 | 526 | 0, // Number of register files 527 | NULL, // Register file names 528 | NULL, // Register descriptions 529 | NULL, // Pointer to CPU registers 530 | 531 | rVcs, // first 532 | rVds, // last 533 | 0, // size of a segment register 534 | rVcs, rVds, 535 | 536 | startcodes, // start sequences 537 | NULL, // see is_ret_insn callback in the notify() function 538 | 539 | H8_null, 540 | H8_last, 541 | Instructions, 542 | 543 | NULL, // int (*is_far_jump)(int icode); 544 | NULL, // Translation function for offsets 545 | 0, // int tbyte_size; -- doesn't exist 546 | ieee_realcvt, // int (*realcvt)(void *m, ushort *e, ushort swt); 547 | { 0, 7, 15, 0 }, // char real_width[4]; 548 | // number of symbols after decimal point 549 | // 2byte float (0-does not exist) 550 | // normal float 551 | // normal double 552 | // long double 553 | h8_is_switch, // int (*is_switch)(switch_info_t *si); 554 | NULL, // int32 (*gen_map_file)(FILE *fp); 555 | NULL, // ea_t (*extract_address)(ea_t ea,const char *string,int x); 556 | is_sp_based, // int (*is_sp_based)(op_t &x); 557 | create_func_frame, // int (*create_func_frame)(func_t *pfn); 558 | h8_get_frame_retsize, // int (*get_frame_retsize(func_t *pfn) 559 | h8_gen_stkvar_def, // void (*gen_stkvar_def)(char *buf,const member_t *mptr,long v); 560 | gen_spcdef, // Generate text representation of an item in a special segment 561 | H8_rts, // Icode of return instruction. It is ok to give any of possible return instructions 562 | set_idp_options, // const char *(*set_idp_options)(const char *keyword,int value_type,const void *value); 563 | h8_is_align_insn, // int (*is_align_insn)(ea_t ea); 564 | NULL, // mvm_t *mvm; 565 | 0, // high_fixup_bits 566 | }; 567 | -------------------------------------------------------------------------------- /insn_trace.py: -------------------------------------------------------------------------------- 1 | """ 2 | IDA: create instructions in unexplored code 3 | 4 | Sometimes obfuscated code includes: 5 | 6 | * illegal instructions 7 | * jumps into the middle of subsequent instructions 8 | * etc 9 | 10 | Of course these instructions are never executed, but IDA's recursive descent 11 | algorithm fails to decode these subroutines successfully. This debug hook 12 | attempts to address this situation via instruction tracing at runtime. 13 | 14 | To use this hook, 15 | * set a breakpoint at the obfuscated code 16 | * enable instruction-level tracing 17 | * activate this hook code 18 | 19 | # https://hex-rays.com/products/ida/support/sdkdoc/dbg_8hpp.html 20 | # https://github.com/idapython/src/blob/master/examples/debughook.py 21 | """ 22 | 23 | import ida_bytes 24 | import ida_dbg 25 | import ida_ua 26 | import idc 27 | 28 | 29 | class InstructionTracer(ida_dbg.DBG_Hooks): 30 | 31 | def __init__(self, *args): 32 | super(InstructionTracer, self).__init__(*args) 33 | self._visited_addrs = set() 34 | 35 | def clear_state(self): 36 | self._visited_addrs.clear() 37 | 38 | def dbg_trace(self, tid, ip): 39 | if ip in self._visited_addrs: 40 | return 1 41 | self._visited_addrs.add(ip) 42 | if idc.is_unknown(ida_bytes.get_flags(ip)): 43 | ida_ua.create_insn(ip) 44 | else: 45 | idc.msg( 46 | 'Skipping explored EA at address 0x{0:X}\n'.format(ip) 47 | ) 48 | # print idc.generate_disasm_line(ip, 0) 49 | if ida_ua.decode_insn(ip) > 0: 50 | if 'ret' in ida_ua.cmd.get_canon_mnem().lower(): 51 | idc.msg('Found ret instruction, suspending execution\n') 52 | ida_dbg.suspend_process() 53 | else: 54 | idc.msg( 55 | 'Unable to decode instruction at address 0x{0:X}\n'.format(ip) 56 | ) 57 | ida_dbg.suspend_process() 58 | return 0 59 | 60 | 61 | # my_tracer = InstructionTracer() 62 | # my_tracer.hook() 63 | # insn_dbg.unhook() 64 | -------------------------------------------------------------------------------- /lgebd/lgebd.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | An IDA loader for LG Blu-Ray drive firmware based on the Renesas H8. 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | // for ntohl and ntohs 19 | #if defined(__NT__) 20 | #include 21 | #else 22 | #include 23 | #endif 24 | #include 25 | #include 26 | #include "../idaldr.h" 27 | #include "lgebd.hpp" 28 | 29 | class lgebd_error: public std::exception { 30 | private: 31 | const char *reason; 32 | public: 33 | lgebd_error(const char *why) { this->reason = why; } 34 | const char * what() const throw() { return this->reason; } 35 | }; 36 | 37 | static bool verify_firmware_checksum(linput_t *li) { 38 | size_t i; 39 | ssize_t bytes_read; 40 | uint32 file_size; 41 | uint16 buf[8192]; 42 | uint16 chksum_file; 43 | uint16 chksum_calc = 0x00; 44 | uint32 bytes_processed; 45 | 46 | qlseek(li, 0, SEEK_SET); 47 | bytes_read = qlread(li, buf, sizeof(buf)); 48 | if(bytes_read != sizeof(buf)) { 49 | throw lgebd_error("Unable to read input file"); 50 | } 51 | // the firmware checksum is stored in first two bytes 52 | chksum_file = ntohs(buf[0]); 53 | // calculate the checksum from the remainder of the input file 54 | for(i = 1; i < (bytes_read/2); i++) 55 | chksum_calc += ntohs(buf[i]); 56 | bytes_processed = bytes_read; 57 | 58 | file_size = (uint32)qlsize(li); 59 | while(bytes_processed < file_size) { 60 | bytes_read = qlread(li, buf, sizeof(buf)); 61 | if(bytes_read < 0) { 62 | throw lgebd_error("Unable to read input file"); 63 | } 64 | for(i = 0; i < (bytes_read/2); i++) 65 | chksum_calc += ntohs(buf[i]); 66 | bytes_processed += bytes_read; 67 | } 68 | qlseek(li, 0, SEEK_SET); 69 | chksum_calc = ~chksum_calc; 70 | return (chksum_calc == chksum_file); 71 | } 72 | 73 | 74 | /* 75 | * check the input file format. 76 | * - if recognized, return 1 and fill 'fileformatname'. 77 | * otherwise return 0 78 | */ 79 | static int idaapi accept_file( 80 | qstring *fileformatname, 81 | qstring *processor, 82 | linput_t *li, 83 | const char */*filename*/) 84 | { 85 | size_t i; 86 | const char *format_name; 87 | uint32 file_size, fw_type; 88 | uint32 load_addr, load_size; 89 | unsigned char buf[HEADER_SIZE]; 90 | 91 | file_size = (uint32)qlsize(li); 92 | if(file_size > MAX_FIRMWARE_SIZE) { 93 | return 0; 94 | } 95 | if(qlread(li, buf, sizeof(buf)) != sizeof(buf)) { 96 | return 0; 97 | } 98 | qlseek(li, 0, SEEK_SET); 99 | load_addr = ntohl(*(uint32 *)(buf+HEADER_OFFSET_LOAD_ADDR)); 100 | load_size = ntohl(*(uint32 *)(buf+HEADER_OFFSET_LOAD_SIZE)); 101 | // the firmware consists of a 0x400-byte header which defines (at least) 102 | // some strings, the file checksum, the load address, and the load size. 103 | if((load_size + HEADER_SIZE) != file_size) { 104 | return 0; 105 | } 106 | // compare the calculated checksum with the value from the firmware image 107 | try { 108 | if(!verify_firmware_checksum(li)) { 109 | return 0; 110 | } 111 | } catch(const lgebd_error &e) { 112 | msg("LGEBD: failed to calculate firmware checksum: %s\n", e.what()); 113 | return 0; 114 | } 115 | // try to identify the firmware type 116 | fw_type = FW_TYPE_UNKNOWN; 117 | for(i = 0; i < (HEADER_SIZE-4); i++) { 118 | if(memcmp(buf, "MAIN", 4) == 0) { 119 | fw_type = FW_TYPE_MAIN; 120 | break; 121 | } else if(memcmp(buf, "CORE", 4) == 0) { 122 | fw_type = FW_TYPE_CORE; 123 | break; 124 | } 125 | } 126 | // fill in file format name 127 | if((load_addr == 0x410000) || fw_type == FW_TYPE_MAIN) { 128 | format_name = "LG Renesas Blu-Ray drive firmware (MAIN)"; 129 | } else if(load_addr == 0x400000 || fw_type == FW_TYPE_CORE) { 130 | format_name = "LG Renesas Blu-Ray drive firmware (CORE)"; 131 | } else { 132 | format_name = "LG Renesas Blu-Ray drive firmware (UNKNOWN)"; 133 | } 134 | fileformatname->insert(0, format_name); 135 | *processor = "h8300a"; 136 | return 1; 137 | } 138 | 139 | 140 | /* 141 | * load the file into the database 142 | */ 143 | static void idaapi load_file(linput_t *li, ushort neflags, const char *fileformatname) { 144 | unsigned char *fw_base, *fw_curr; 145 | uint32 load_addr, load_size, i, file_size; 146 | ea_t startEA, endEA, sjtEA, putative_addr; 147 | uint32 current_offset, increment_by, putative_count; 148 | 149 | if(ph.id != PLFM_H8) 150 | set_processor_type("h8300a", SETPROC_LOADER); 151 | // TODO: look into set_abi_name() here as well? 152 | // http://gcc-renesas.com/manuals/SH-ABI-Specification.html 153 | // http://gcc.gnu.org/projects/h8300-abi.html 154 | // 0 -> GNU assembler (possibly from KPIT) 155 | // http://www.kpitgnutools.com/ 156 | // 1 -> HEW (High-performance Embedded Workshop) 157 | // http://am.renesas.com/products/tools/ide/ide_hew/index.jsp 158 | set_target_assembler(1); 159 | 160 | // read in the firmware into memory 161 | file_size = qlsize(li); 162 | fw_base = (unsigned char *)qalloc(file_size); 163 | if(!fw_base) { 164 | loader_failure(); 165 | } 166 | qlseek(li, 0, SEEK_SET); 167 | if(qlread(li, fw_base, file_size) != file_size) { 168 | qfree(fw_base); 169 | loader_failure(); 170 | } 171 | qlseek(li, 0, SEEK_SET); 172 | // The following three segments represent what appear to be private 173 | // code/data segments, available only to the drive's OS at runtime. 174 | if(!add_segm(0, 0x100000, 0x107000, "PRIVATE", CLASS_CODE)) { 175 | qfree(fw_base); 176 | loader_failure(); 177 | } 178 | // This address space may be hardware registers and/or 179 | // subroutines implemented in hardware 180 | if(!add_segm(0, 0, 0x7000, "HARDWARE", CLASS_CODE)) { 181 | qfree(fw_base); 182 | loader_failure(); 183 | } 184 | // RAM (possibly) 185 | if(!add_segm(0, 0xFFE000, 0xFFFFFF, "RAM", CLASS_DATA)) { 186 | qfree(fw_base); 187 | loader_failure(); 188 | } 189 | // identify the start and end EA based 190 | // on values in the firmware header 191 | load_addr = ntohl(*(uint32 *)(fw_base+0x40)); 192 | load_size = ntohl(*(uint32 *)(fw_base+0x44)); 193 | startEA = load_addr; 194 | endEA = load_addr + load_size - 1; 195 | // init refinfo for the ROM 196 | msg("LGE: load addr = 0x%06X\n", load_addr); 197 | msg("LGE: load size = 0x%06X\n", load_size); 198 | // load the ROM firmware into the database 199 | mem2base((fw_base+HEADER_SIZE), startEA, endEA, HEADER_SIZE); 200 | // create a segment around the ROM section 201 | if(!add_segm(0, startEA, endEA, "ROM", CLASS_CODE)) { 202 | qfree(fw_base); 203 | loader_failure(); 204 | } 205 | // The firmware appears to reference some kind of permanent 206 | // storage, likely a small flash chip. Not sure what size 207 | // this is; use 128K for now. 208 | if(!add_segm(0, 0x800000, 0x820000, "FLASH", CLASS_DATA)) { 209 | qfree(fw_base); 210 | loader_failure(); 211 | } 212 | // use 32-bit addressing 213 | segment_t *s = getseg(startEA); 214 | set_segm_addressing(s, SEGMENT_32BIT); 215 | // Special handling for the MAIN firmware image 216 | if(strstr(fileformatname, "MAIN") != NULL) { 217 | // Search for the SCSI jump table 218 | sjtEA = BADADDR; 219 | putative_count = 0; 220 | current_offset = HEADER_SIZE; 221 | fw_curr = fw_base + current_offset; 222 | while(current_offset < file_size) { 223 | putative_addr = ntohl(*(uint32 *)(fw_curr)); 224 | if(putative_addr >= startEA && putative_addr <= endEA) { 225 | increment_by = 4; 226 | putative_count++; 227 | } else { 228 | if(putative_count > 0) { 229 | if(putative_count == 256) { 230 | sjtEA = (startEA-HEADER_SIZE)+(current_offset-(4*putative_count)); 231 | break; 232 | } 233 | putative_count = 0; 234 | } 235 | increment_by = 1; 236 | } 237 | fw_curr += increment_by; 238 | current_offset += increment_by; 239 | } 240 | if(sjtEA != BADADDR) { 241 | #if defined(__EA64__) 242 | msg("LGE: SCSI jump table found @ 0x%06llX\n", sjtEA); 243 | #else 244 | msg("LGE: SCSI jump table found @ 0x%06X\n", sjtEA); 245 | #endif 246 | for(i=0; i<256; i++) { 247 | create_dword(sjtEA, 4); 248 | sjtEA += 4; 249 | } 250 | } 251 | } 252 | // free the allocated memory 253 | qfree(fw_base); 254 | // create the file header comment 255 | if((neflags & NEF_RELOAD) == 0) 256 | create_filename_cmt(); 257 | } 258 | 259 | 260 | loader_t LDSC = { 261 | IDP_INTERFACE_VERSION, // api version 262 | 0, // loader flags 263 | accept_file, // accept_file callback 264 | load_file, // load_file callback 265 | NULL, // save_file callback 266 | NULL, // move_segm callback 267 | NULL // unused 268 | }; 269 | -------------------------------------------------------------------------------- /lgebd/lgebd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LGEBD_HPP 2 | #define LGEBD_HPP 3 | 4 | // Firmware header size is 1024 (0x400) bytes 5 | #define HEADER_SIZE 0x400 6 | 7 | // arbitrary firmware file size limit ... we don't 8 | // expect drive firmware to be very large. 9 | #define MAX_FIRMWARE_SIZE 10000000 10 | 11 | // segment bitness flags 12 | #define SEGMENT_16BIT 0 13 | #define SEGMENT_32BIT 1 14 | #define SEGMENT_64BIT 2 15 | 16 | // firmware types (UNKNOWN/CORE/MAIN) 17 | #define FW_TYPE_UNKNOWN 0 18 | #define FW_TYPE_MAIN 1 19 | #define FW_TYPE_CORE 2 20 | 21 | // offsets for data in the firmware header 22 | #define HEADER_OFFSET_LOAD_ADDR 0x40 23 | #define HEADER_OFFSET_LOAD_SIZE 0x44 24 | 25 | #endif // LGEBD_HPP 26 | -------------------------------------------------------------------------------- /lgebd/makefile: -------------------------------------------------------------------------------- 1 | PROC=lgebd 2 | include ../loader.mak 3 | 4 | # MAKEDEP dependency list ------------------ 5 | $(F)lgebd$(O) : $(I)bytes.hpp ../idaldr.h lgebd.hpp 6 | -------------------------------------------------------------------------------- /openssl/.gitignore: -------------------------------------------------------------------------------- 1 | openssl-* 2 | *.til 3 | openssl_all.i 4 | -------------------------------------------------------------------------------- /openssl/README.md: -------------------------------------------------------------------------------- 1 | These are scripts to build an IDA type information library for all OpenSSL 1.0.2m headers. 2 | 3 | Dependencies: 4 | * ${IDA}/til/gnucmn.til 5 | * OpenSSL 1.0.2m, decompressed and configured 6 | -------------------------------------------------------------------------------- /openssl/build_til.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IDA="/opt/ida-7.0" 4 | if [ ! -d "${IDA}" ] 5 | then 6 | echo "Edit the IDA path in this script." 7 | exit 1 8 | fi 9 | 10 | rm -f openssl_*.til openssl_all.i 11 | 12 | OSSL_VER="1.0.2m" 13 | OSSL_INC_DIR="openssl-${OSSL_VER}/include" 14 | OSSL_TIL_BASE="openssl_${OSSL_VER//.}_gcc" 15 | 16 | if [ ! -d "${OSSL_INC_DIR}" ] 17 | then 18 | echo "Download and configure OpenSSL ${OSSL_VER}." 19 | exit 1 20 | fi 21 | 22 | ${IDA}/tilib -Gn -v -z -c @gcc32.cfg -I${OSSL_INC_DIR} -Iempty -b${IDA}/til/gnucmn.til -hopenssl_all.h \ 23 | -t"OpenSSL ${OSSL_VER} (gcc/x86, without leading underscore)" ${OSSL_TIL_BASE}_x86_nlu.til 24 | rm -f openssl_all.i 25 | ${IDA}/tilib64 -Gn -v -z -c @gcc64.cfg -I${OSSL_INC_DIR} -Iempty -b${IDA}/til/gnucmn.til -hopenssl_all.h \ 26 | -t"OpenSSL ${OSSL_VER} (gcc/x64, without leading underscore)" ${OSSL_TIL_BASE}_x64_nlu.til 27 | rm -f openssl_all.i 28 | 29 | 30 | ${IDA}/tilib -v -z -c @gcc32.cfg -I${OSSL_INC_DIR} -Iempty -b${IDA}/til/gnucmn.til -hopenssl_all.h \ 31 | -t"OpenSSL ${OSSL_VER} (gcc/x86, with leading underscore)" ${OSSL_TIL_BASE}_x86_wlu.til 32 | rm -f openssl_all.i 33 | ${IDA}/tilib64 -v -z -c @gcc64.cfg -I${OSSL_INC_DIR} -Iempty -b${IDA}/til/gnucmn.til -hopenssl_all.h \ 34 | -t"OpenSSL ${OSSL_VER} (gcc/x64, with leading underscore)" ${OSSL_TIL_BASE}_x64_wlu.til 35 | rm -f openssl_all.i 36 | -------------------------------------------------------------------------------- /openssl/empty/errno.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/errno.h -------------------------------------------------------------------------------- /openssl/empty/limits.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/limits.h -------------------------------------------------------------------------------- /openssl/empty/stdarg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/stdarg.h -------------------------------------------------------------------------------- /openssl/empty/stddef.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/stddef.h -------------------------------------------------------------------------------- /openssl/empty/stdio.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/stdio.h -------------------------------------------------------------------------------- /openssl/empty/stdlib.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/stdlib.h -------------------------------------------------------------------------------- /openssl/empty/string.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/string.h -------------------------------------------------------------------------------- /openssl/empty/sys/time.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/sys/time.h -------------------------------------------------------------------------------- /openssl/empty/sys/types.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/sys/types.h -------------------------------------------------------------------------------- /openssl/empty/time.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rupan/ida/0add64c5f345f8c152843fab3064f3be5e3c6349/openssl/empty/time.h -------------------------------------------------------------------------------- /openssl/gcc32.cfg: -------------------------------------------------------------------------------- 1 | -Cags44444248u 2 | 3 | -D__inline=inline 4 | -D__inline__=inline 5 | -D__signed__=signed 6 | 7 | -D__GNUC__ 8 | -Di386 9 | -D__i386 10 | -D__i386__ 11 | -D__i686__ 12 | -D__i686 13 | -D__unix 14 | -D__unix__ 15 | -D__STDC__ 16 | -D_HAVE_INT64 17 | -D__GLIBC_HAVE_LONG_LONG 18 | 19 | -Dlinux 20 | -------------------------------------------------------------------------------- /openssl/gcc64.cfg: -------------------------------------------------------------------------------- 1 | -Cags80144288u6 2 | 3 | -D__inline=inline 4 | -D__inline__=inline 5 | -D__signed__=signed 6 | 7 | -D__GNUC__ 8 | -D__x86_64 9 | -D__x86_64__ 10 | -D__amd64 11 | -D__amd64__ 12 | -D_LP64 13 | -D__LP64__ 14 | -D__unix__ 15 | -D__STDC__ 16 | -D_HAVE_INT64 17 | -D__GLIBC_HAVE_LONG_LONG 18 | 19 | -Dlinux 20 | -------------------------------------------------------------------------------- /openssl/openssl_all.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | -------------------------------------------------------------------------------- /rsrc.py: -------------------------------------------------------------------------------- 1 | """ 2 | Quick-and-dirty IDA loader for Mac OS classic (System 7) resource forks 3 | Copyright (c) 2021 - Michael Mohr 4 | Licence: GPLv3 5 | 6 | Useful links: 7 | * https://github.com/fuzziqersoftware/resource_dasm 8 | * https://github.com/MacPaw/XADMaster/wiki/Disassembling68KMacExecutables 9 | * https://code.google.com/archive/p/theunarchiver/wikis/Disassembling68KMacExecutables.wiki 10 | * https://github.com/dgelessus/python-rsrcfork 11 | * https://github.com/topics/classic-mac-os?o=asc&s=stars 12 | * https://github.com/csnover/ida-misc/tree/master/mac 13 | * https://github.com/ubuntor/m68k_mac_reversing_tools 14 | """ 15 | 16 | import struct 17 | 18 | import idaapi 19 | import ida_bytes 20 | import ida_entry 21 | import idc 22 | import idc_bc695 23 | 24 | 25 | def build_pascal_str(next_ea): 26 | str_len = idc_bc695.Byte(next_ea) 27 | ida_bytes.create_strlit(next_ea, 0, idc.STRTYPE_PASCAL) 28 | return next_ea + str_len + 1 29 | 30 | 31 | def accept_file(li, filename): 32 | file_size = li.size() 33 | header = li.read(16) 34 | if len(header) != 16: 35 | return 0 36 | data_offset, map_offset, data_size, map_size = struct.unpack(">IIII", header) 37 | if (data_offset + data_size + map_size) != file_size: 38 | return 0 39 | return {"format": "Mac OS Classic resource fork", "processor": "68K"} 40 | 41 | 42 | def load_file(li, neflags, format): 43 | li.file2base(0, 0, li.size(), False) 44 | 45 | data_start_ea = idc_bc695.Dword(0) 46 | data_end_ea = data_start_ea + idc_bc695.Dword(8) 47 | 48 | map_start_ea = idc_bc695.Dword(4) 49 | map_end_ea = map_start_ea + idc_bc695.Dword(12) 50 | add_seg(map_start_ea, map_end_ea, "ResourceMap", "DATA") 51 | 52 | header_start_ea = 0 53 | header_end_ea = data_start_ea 54 | add_seg(header_start_ea, header_end_ea, "ResourceHeader", "DATA") 55 | 56 | process_metadata() 57 | return 1 58 | 59 | 60 | def add_seg(start_ea, end_ea, name, sclass): 61 | seg = idaapi.segment_t() 62 | seg.start_ea = start_ea 63 | seg.end_ea = end_ea 64 | seg.bitness = 1 # 32-bit 65 | idaapi.add_segm_ex(seg, name, sclass, 0) 66 | 67 | 68 | def process_metadata(): 69 | """ 70 | Nearly a carbon copy of mac_os_resource.idc found here: 71 | https://github.com/MacPaw/XADMaster/wiki/Disassembling68KMacExecutables 72 | """ 73 | idc_bc695.MakeDword(0) 74 | idc_bc695.OpOff(0, 0, 0) 75 | idc_bc695.MakeComm(0, "Offset to resource data") 76 | 77 | idc_bc695.MakeDword(4) 78 | idc_bc695.OpOff(4, 0, 0) 79 | idc_bc695.MakeComm(4, "Offset to resource map") 80 | 81 | idc_bc695.MakeDword(8) 82 | idc_bc695.OpNumber(8, 0) 83 | idc_bc695.MakeComm(8, "Length of resource data") 84 | 85 | idc_bc695.MakeDword(12) 86 | idc_bc695.OpNumber(12, 0) 87 | idc_bc695.MakeComm(12, "Length of resource map") 88 | 89 | resdata = idc_bc695.Dword(0) 90 | resmap = idc_bc695.Dword(4) 91 | 92 | # left for documentation since this was in the original IDC script 93 | # it will be overwritten later anyway when the map data is parsed 94 | # idc_bc695.MakeNameEx(resdata, "ResourceData", 0) 95 | idc_bc695.MakeNameEx(resmap, "ResourceMap", 0) 96 | 97 | idc_bc695.MakeDword(resmap) 98 | idc_bc695.OpOff(resmap, 0, 0) 99 | idc_bc695.MakeComm(resmap, "Offset to resource data") 100 | 101 | idc_bc695.MakeDword(resmap + 4) 102 | idc_bc695.OpOff(resmap + 4, 0, 0) 103 | idc_bc695.MakeComm(resmap + 4, "Offset to resource map") 104 | 105 | idc_bc695.MakeDword(resmap + 8) 106 | idc_bc695.OpNumber(resmap + 8, 0) 107 | idc_bc695.MakeComm(resmap + 8, "Length of resource data") 108 | 109 | idc_bc695.MakeDword(resmap + 12) 110 | idc_bc695.OpNumber(resmap + 12, 0) 111 | idc_bc695.MakeComm(resmap + 12, "Length of resource map") 112 | 113 | idc_bc695.MakeDword(resmap + 16) 114 | idc_bc695.OpNumber(resmap + 16, 0) 115 | idc_bc695.MakeComm(resmap + 16, "Reserved for handle to next resource map") 116 | 117 | idc_bc695.MakeWord(resmap + 20) 118 | idc_bc695.OpNumber(resmap + 20, 0) 119 | idc_bc695.MakeComm(resmap + 20, "Reserved for file reference number") 120 | 121 | idc_bc695.MakeWord(resmap + 22) 122 | idc_bc695.OpNumber(resmap + 22, 0) 123 | idc_bc695.MakeComm(resmap + 22, "Resource fork attributes") 124 | 125 | idc_bc695.MakeWord(resmap + 24) 126 | idc_bc695.OpOffEx(resmap + 24, 0, idc.REF_OFF32, -1, resmap, -2) 127 | idc_bc695.MakeComm(resmap + 24, "Offset to type list") 128 | 129 | idc_bc695.MakeWord(resmap + 26) 130 | idc_bc695.OpOffEx(resmap + 26, 0, idc.REF_OFF32, -1, resmap, -2) 131 | idc_bc695.MakeComm(resmap + 26, "Offset to name list") 132 | 133 | idc_bc695.MakeWord(resmap + 28) 134 | idc_bc695.OpNumber(resmap + 28, 0) 135 | idc_bc695.MakeComm(resmap + 28, "Number of types minus one") 136 | 137 | restypelist = resmap + idc_bc695.Word(resmap + 24) + 2 138 | resnamelist = resmap + idc_bc695.Word(resmap + 26) + 2 139 | 140 | idc_bc695.MakeNameEx(restypelist, "ResourceTypeList", 0) 141 | idc_bc695.MakeNameEx(resnamelist, "ResourceNameList", 0) 142 | 143 | numtypes = idc_bc695.Word(resmap + 28) + 1 144 | 145 | for i in range(numtypes): 146 | entry = restypelist + i * 8 147 | 148 | # idc_bc695.MakeStr(entry + 0, entry + 4) 149 | idc.create_strlit(entry + 0, entry + 4) 150 | idc_bc695.MakeComm(entry + 0, "Resource type") 151 | 152 | idc_bc695.MakeWord(entry + 4) 153 | idc_bc695.OpNumber(entry + 4, 0) 154 | idc_bc695.MakeComm(entry + 4, "Number of resource of this type minus one") 155 | 156 | idc_bc695.MakeWord(entry + 6) 157 | idc_bc695.OpOffEx(entry + 6, 0, idc.REF_OFF32, -1, restypelist, 2) 158 | idc_bc695.MakeComm(entry + 6, "Offset of reference list for this type") 159 | 160 | reflist = restypelist + idc_bc695.Word(entry + 6) - 2 161 | 162 | # Some resources have # in their names 163 | # resname = idc_bc695.GetString(entry + 0, 4, idc.ASCSTR_C) 164 | resname = idc.get_strlit_contents(entry + 0, 4, idc.STRTYPE_C).decode("utf-8").replace("#", "") 165 | idc_bc695.MakeNameEx(reflist, "ReferenceList" + resname, 0) 166 | 167 | numrefs = idc_bc695.Word(entry + 4) + 1 168 | 169 | for j in range(numrefs): 170 | ref = reflist + j * 12 171 | 172 | idc_bc695.MakeWord(ref + 0) 173 | idc_bc695.OpNumber(ref + 0, 0) 174 | idc_bc695.MakeComm(ref + 0, "Resource ID") 175 | 176 | idc_bc695.MakeWord(ref + 2) 177 | idc_bc695.OpOffEx(ref + 2, 0, idc.REF_OFF32, -1, resnamelist, 0) 178 | idc_bc695.MakeComm(ref + 2, "Offset to resource name") 179 | 180 | idc_bc695.MakeDword(ref + 4) 181 | attrs = idc_bc695.Byte(ref + 4) 182 | idc_bc695.OpOffEx(ref + 4, 0, idc.REF_OFF32, -1, resdata, attrs << 24) 183 | idc_bc695.MakeComm(ref + 4, "Offset to resource data plus attributes") 184 | 185 | idc_bc695.MakeDword(ref + 8) 186 | idc_bc695.OpNumber(ref + 8, 0) 187 | idc_bc695.MakeComm(ref + 8, "Reserved for handle to resource") 188 | 189 | resid = str(idc_bc695.Word(ref + 0)) 190 | data = resdata + idc_bc695.Dword(ref + 4) - (attrs << 24) 191 | data_size = idc_bc695.Dword(data) + 4 # size *after* initial DWORD 192 | data_name = resname + "Resource" + resid 193 | if resname == "CODE" and resid != "0": 194 | add_seg(data, data + data_size, data_name, "CODE") 195 | else: 196 | add_seg(data, data + data_size, data_name, "DATA") 197 | idc_bc695.MakeNameEx(data, resname + "Resource" + resid, 0) 198 | 199 | idc_bc695.MakeDword(data) 200 | idc_bc695.OpNumber(data, 0) 201 | idc_bc695.MakeComm(data, "Length of resource data") 202 | 203 | if resname == "CODE" and resid != "0": 204 | idc_bc695.MakeWord(data + 4) 205 | idc_bc695.OpNumber(data + 4, 0) 206 | idc_bc695.MakeComm(data + 4, "Offset of first entry in jump table") 207 | 208 | idc_bc695.MakeWord(data + 6) 209 | idc_bc695.OpNumber(data + 6, 0) 210 | idc_bc695.MakeComm(data + 6, "Number of entries in jump table") 211 | 212 | code0 = idc_bc695.LocByName("CODEResource0") 213 | 214 | idc_bc695.MakeDword(code0 + 4) 215 | idc_bc695.OpNumber(code0 + 4, 0) 216 | idc_bc695.MakeComm(code0 + 4, "Size above A5") 217 | 218 | idc_bc695.MakeDword(code0 + 8) 219 | idc_bc695.OpNumber(code0 + 8, 0) 220 | idc_bc695.MakeComm(code0 + 8, "Size of globals") 221 | 222 | idc_bc695.MakeDword(code0 + 12) 223 | idc_bc695.OpNumber(code0 + 12, 0) 224 | idc_bc695.MakeComm(code0 + 12, "Length of jump table") 225 | 226 | idc_bc695.MakeDword(code0 + 16) 227 | idc_bc695.OpNumber(code0 + 16, 0) 228 | idc_bc695.MakeComm(code0 + 16, "A5 offset of jump table") 229 | 230 | idc_bc695.MakeNameEx(code0 + 20, "JumpTable", 0) 231 | 232 | length = idc_bc695.Dword(code0 + 12) 233 | 234 | for i in range(0, length, 8): 235 | jumpentry = code0 + 20 + i 236 | 237 | jumpresid = str(idc_bc695.Word(jumpentry + 4)) 238 | resoffs = idc_bc695.LocByName("CODEResource" + jumpresid) 239 | 240 | idc_bc695.MakeWord(jumpentry + 0) 241 | idc_bc695.OpOffEx(jumpentry + 0, 0, idc.REF_OFF32, -1, resoffs, -8) 242 | idc_bc695.MakeComm(jumpentry + 0, "Offset of function") 243 | 244 | jumptable_subroutine_ea = resoffs + idc_bc695.Word(jumpentry + 0) + 8 245 | idc.create_insn(jumptable_subroutine_ea) 246 | if i == 0: 247 | # the application main entry point 248 | ida_entry.add_entry(jumptable_subroutine_ea, jumptable_subroutine_ea, "_main", False, 0) 249 | 250 | idc_bc695.MakeWord(jumpentry + 2) 251 | idc_bc695.OpNumber(jumpentry + 2, 0) 252 | idc_bc695.MakeComm(jumpentry + 2, "Push instruction") 253 | 254 | idc_bc695.MakeWord(jumpentry + 4) 255 | idc_bc695.OpNumber(jumpentry + 4, 0) 256 | idc_bc695.MakeComm(jumpentry + 4, "Resource ID to push") 257 | 258 | idc_bc695.MakeWord(jumpentry + 6) 259 | idc_bc695.OpNumber(jumpentry + 6, 0) 260 | idc_bc695.MakeComm(jumpentry + 6, "LoadSeg instruction") 261 | 262 | funcoffs = resoffs + 8 + idc_bc695.Word(jumpentry + 0) 263 | idc_bc695.AutoMark(funcoffs, idc.AU_PROC) 264 | -------------------------------------------------------------------------------- /zlibdll/.gitignore: -------------------------------------------------------------------------------- 1 | dll16 2 | dll32 3 | ioapi.h 4 | readme.txt 5 | static32 6 | unzip.h 7 | zconf.h 8 | zip.h 9 | zlib114dll.zip 10 | zlib.h 11 | -------------------------------------------------------------------------------- /zlibdll/README.md: -------------------------------------------------------------------------------- 1 | These files will generate TIL and SIG files for IDA from the zLibDll binaries: 2 | 3 | http://www.winimage.com/zLibDll/index.html 4 | 5 | You will need to first download and decompress the following archive alongside the existing files: 6 | 7 | http://www.winimage.com/zLibDll/zlib114dll.zip 8 | -------------------------------------------------------------------------------- /zlibdll/zlib114dll.exc: -------------------------------------------------------------------------------- 1 | _tr_static_init 00 0000 C3909090909090909090909090909090................................ 2 | _match_init 00 0000 C3909090909090909090909090909090................................ 3 | -------------------------------------------------------------------------------- /zlibdll/zlibdll-vc32.cfg: -------------------------------------------------------------------------------- 1 | -Cavs40144 2 | -Ih 3 | 4 | -D_cdecl=__cdecl 5 | -D_pascal=__pascal 6 | -D_huge=__huge 7 | -D_near=__near 8 | -D_far=__far 9 | ;-D__inline=inline 10 | -D__inline= 11 | -D_inline= 12 | -Dinline= 13 | 14 | -DCM_WINNT 15 | -DMPR50 16 | 17 | -D_INTEGRAL_MAX_BITS=64 18 | -D_MSC_VER=1200 19 | -DZLIB_DLL 20 | -D_WINDOWS 21 | 22 | ;Version number 23 | ;-D__BCPLUSPLUS__=0x500 24 | ;-D__BORLANDC__=0x500 25 | ;-D__TURBOC__=0x500 26 | ;-D__TCPLUSPLUS__=0x500 27 | 28 | ;__CDECL__ 1 Defined if Calling Convention is set to C; otherwise undefined 29 | 30 | ; Defined by default indicating that the default char is unsigned char. 31 | ; Use the -K option to undefine this macro. 32 | -D_CHAR_UNSIGNED=1 33 | 34 | ; Available only for the 32-bit compiler. 35 | ; When defined, the macro indicates that the program is a console application. 36 | ; __CONSOLE__ 37 | 38 | ; Enable stack unwinding.This is true by default; use -xd- to disable. 39 | ;_CPPUNWIND 1 40 | 41 | ; Defined if in C++ mode; otherwise, undefined 42 | ;-D__cplusplus=1 43 | 44 | ;__DLL__ 1 Defined if Prolog/Epilog Code Generation is set to Windows DLL; otherwise undefined 45 | ;__DLL__ 1 True whenever -WD option is used. 46 | 47 | ; Always defined. The default value is 300. 48 | ; You can change the value to 400 or 500 by using the /4 or /5 options. 49 | -D_M_IX86=300 50 | 51 | ; Defined only for the 32-bit compiler if the -WM option is used. 52 | ; It specifies that the multithread library is to be linked. 53 | ; Multithread is on by default. 54 | -D__MT__=1 55 | 56 | ;__OVERLAY__ 1 Specific to the Borland C and C++ family of compilers. It is predefined as 1 if you compile a module with the -Y option (enable overlay support). If you do not enable overlay support, this macro is undefined. 57 | ;__PASCAL__ 1 Defined if Calling Convention is set to Pascal; otherwise undefined 58 | ;__STDC__ 1 Defined if you compile with the Keywords option set to ANSI; otherwise, undefined 59 | 60 | ; Specific to the Borland C++ compilers. 61 | ; It is defined as 1 for C++ files (meaning that Borland C++ supports templates); otherwise, it is undefined. 62 | ;__TEMPLATES__ 1 63 | 64 | ; Always true when the 32-bit compiler is used. 65 | -D__TLS__=1 66 | 67 | ;_WCHAR_T 1 Defined only for C++ programs to indicate that wchar_t is an intrinsically defined data type. 68 | ;_WCHAR_T_DEFINED 1 Defined only for C++ programs to indicate that wchar_t is an intrinsically defined data type. 69 | 70 | ; Defined for Windows 16- and 32-bit compilations 71 | -D_Windows=1 72 | 73 | ; Always defined for the 32-bit compiler. 74 | ; It is defined for console and GUI applications. 75 | -D__WIN32__=1 76 | -D_WIN32_WINNT=0x0500 77 | -DWINVER=0x0500 78 | -D_WIN32=1 79 | -DOLEDBVER=0x0250 80 | -DSECURITY_WIN32 81 | -DWIN32_SUPPORT 82 | -DDBNTWIN32 83 | -DW32SUT_32 84 | 85 | ;-D__MSDOS__=1 86 | -------------------------------------------------------------------------------- /zlibdll/zlibdll.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | -------------------------------------------------------------------------------- /zlibdll/zlibdll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IDA="${HOME}/ida-6.4" 4 | if [ ! -d "${IDA}" ] 5 | then 6 | echo "Edit the IDA path in this script." 7 | exit 1 8 | fi 9 | 10 | if [ ! -f "unzip.h" ] 11 | then 12 | echo "Download zlib114dll.zip and unzip it here." 13 | echo "http://www.winimage.com/zLibDll/zlib114dll.zip" 14 | exit 1 15 | fi 16 | 17 | ${IDA}/tilib -v -z -c @${IDA}/til-cfg/vc32.cfg -b${IDA}/til/pc/vc6win.til -hzlib114all.h -t'zlib 1.1.4 (WinImage, x86 VC6)' -Izlib114dll zlib114_x86_vc6.til 18 | 19 | pcf static32/zlibstat.lib zlib114_x86_vc6.pat 20 | sigmake -nzlib114dll zlib114_x86_vc6.pat zlib114_x86_vc6.sig 21 | ./bin/linux/sigmake -n'zlib dll 1.1.4 (WinImage, x86 static VC6)' -o2 zlibstat.pat zlib114_x86_vc6.sig 22 | --------------------------------------------------------------------------------