📄 bedbug.c.svn-base
字号:
} else if (strcmp (name, "tbl") == 0) val = 268; else if (strcmp (name, "tbu") == 0) val = 269; else return 0; /* tbr is a 10 bit field whose interpretation has the high and low five-bit fields reversed from their encoding in the operand */ val = htonl (val); tbr = ((val >> 5) & 0x1f) | ((val & 0x1f) << 5); return tbr;} /* tbr_name *//*====================================================================== * The next several functions (handle_xxx) are the routines that handle * disassembling the opcodes with simplified mnemonics. * * Arguments: * ctx A pointer to the disassembler context record. * * Returns TRUE if the simpler form was printed or FALSE if it was not. */int handle_bc (struct ppc_ctx *ctx){ unsigned long bo; unsigned long bi; static struct opcode blt = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0}, 0, "blt", H_RELATIVE }; static struct opcode bne = { B_OPCODE (16, 0, 0), B_MASK, {O_cr2, O_BD, 0}, 0, "bne", H_RELATIVE }; static struct opcode bdnz = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0}, 0, "bdnz", H_RELATIVE }; /*------------------------------------------------------------*/ if (get_operand_value (ctx->op, ctx->instr, O_BO, &bo) == FALSE) return FALSE; if (get_operand_value (ctx->op, ctx->instr, O_BI, &bi) == FALSE) return FALSE; if ((bo == 12) && (bi == 0)) { ctx->op = &blt; sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name); ctx->datalen += 8; print_operands (ctx); return TRUE; } else if ((bo == 4) && (bi == 10)) { ctx->op = =⃥ sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name); ctx->datalen += 8; print_operands (ctx); return TRUE; } else if ((bo == 16) && (bi == 0)) { ctx->op = &bdnz; sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name); ctx->datalen += 8; print_operands (ctx); return TRUE; } return FALSE;} /* handle_blt *//*====================================================================== * Outputs source line information for the disassembler. This should * be modified in the future to lookup the actual line of source code * from the file, but for now this will do. * * Arguments: * filename The address of a character array containing the * absolute path and file name of the source file. * * funcname The address of a character array containing the * name of the function (not C++ demangled (yet)) * to which this code belongs. * * line_no An integer specifying the source line number that * generated this code. * * pfunc The address of a function to call to print the output. * * * Returns TRUE if it was able to output the line info, or false if it was * not. */int print_source_line (char *filename, char *funcname, int line_no, int (*pfunc) (const char *)){ char out_buf[256]; /*------------------------------------------------------------*/ (*pfunc) (""); /* output a newline */ sprintf (out_buf, "%s %s(): line %d", filename, funcname, line_no); (*pfunc) (out_buf); return TRUE;} /* print_source_line *//*====================================================================== * Entry point for the PPC assembler. * * Arguments: * asm_buf An array of characters containing the assembly opcode * and operands to convert to a POWERPC machine * instruction. * * Returns the machine instruction or zero. */unsigned long asmppc (unsigned long memaddr, char *asm_buf, int *err){ struct opcode *opc; struct operand *oper[MAX_OPERANDS]; unsigned long instr; unsigned long param; char *ptr = asm_buf; char scratch[20]; int i; int w_operands = 0; /* wanted # of operands */ int n_operands = 0; /* # of operands read */ int asm_debug = 0; /*------------------------------------------------------------*/ if (err) *err = 0; if (get_word (&ptr, scratch) == 0) return 0; /* Lookup the opcode structure based on the opcode name */ if ((opc = find_opcode_by_name (scratch)) == (struct opcode *) 0) { if (err) *err = E_ASM_BAD_OPCODE; return 0; } if (asm_debug) { printf ("asmppc: Opcode = \"%s\"\n", opc->name); } for (i = 0; i < 8; ++i) { if (opc->fields[i] == 0) break; ++w_operands; } if (asm_debug) { printf ("asmppc: Expecting %d operands\n", w_operands); } instr = opc->opcode; /* read each operand */ while (n_operands < w_operands) { oper[n_operands] = &operands[opc->fields[n_operands] - 1]; if (oper[n_operands]->hint & OH_SILENT) { /* Skip silent operands, they are covered in opc->opcode */ if (asm_debug) { printf ("asmppc: Operand %d \"%s\" SILENT\n", n_operands, oper[n_operands]->name); } ++n_operands; continue; } if (get_word (&ptr, scratch) == 0) break; if (asm_debug) { printf ("asmppc: Operand %d \"%s\" : \"%s\"\n", n_operands, oper[n_operands]->name, scratch); } if ((param = parse_operand (memaddr, opc, oper[n_operands], scratch, err)) == -1) return 0; instr |= param; ++n_operands; } if (n_operands < w_operands) { if (err) *err = E_ASM_NUM_OPERANDS; return 0; } if (asm_debug) { printf ("asmppc: Instruction = 0x%08lx\n", instr); } return instr;} /* asmppc *//*====================================================================== * Called by the assembler to interpret a single operand * * Arguments: * ctx A pointer to the disassembler context record. * * Returns 0 if the operand is ok, or -1 if it is bad. */int parse_operand (unsigned long memaddr, struct opcode *opc, struct operand *oper, char *txt, int *err){ long data; long mask; int is_neg = 0; /*------------------------------------------------------------*/ mask = (1 << oper->bits) - 1; if (oper->hint & OH_ADDR) { data = read_number (txt); if (opc->hint & H_RELATIVE) data = data - memaddr; if (data < 0) is_neg = 1; data >>= 2; data &= (mask >> 1); if (is_neg) data |= 1 << (oper->bits - 1); } else if (oper->hint & OH_REG) { if (txt[0] == 'r' || txt[0] == 'R') txt++; else if (txt[0] == '%' && (txt[1] == 'r' || txt[1] == 'R')) txt += 2; data = read_number (txt); if (data > 31) { if (err) *err = E_ASM_BAD_REGISTER; return -1; } data = htonl (data); } else if (oper->hint & OH_SPR) { if ((data = spr_value (txt)) == 0) { if (err) *err = E_ASM_BAD_SPR; return -1; } } else if (oper->hint & OH_TBR) { if ((data = tbr_value (txt)) == 0) { if (err) *err = E_ASM_BAD_TBR; return -1; } } else { data = htonl (read_number (txt)); } return (data & mask) << oper->shift;} /* parse_operand */char *asm_error_str (int err){ switch (err) { case E_ASM_BAD_OPCODE: return "Bad opcode"; case E_ASM_NUM_OPERANDS: return "Bad number of operands"; case E_ASM_BAD_REGISTER: return "Bad register number"; case E_ASM_BAD_SPR: return "Bad SPR name or number"; case E_ASM_BAD_TBR: return "Bad TBR name or number"; } return "";} /* asm_error_str *//*====================================================================== * Copy a word from one buffer to another, ignores leading white spaces. * * Arguments: * src The address of a character pointer to the * source buffer. * dest A pointer to a character buffer to write the word * into. * * Returns the number of non-white space characters copied, or zero. */int get_word (char **src, char *dest){ char *ptr = *src; int nchars = 0; /*------------------------------------------------------------*/ /* Eat white spaces */ while (*ptr && isblank (*ptr)) ptr++; if (*ptr == 0) { *src = ptr; return 0; } /* Find the text of the word */ while (*ptr && !isblank (*ptr) && (*ptr != ',')) dest[nchars++] = *ptr++; ptr = (*ptr == ',') ? ptr + 1 : ptr; dest[nchars] = 0; *src = ptr; return nchars;} /* get_word *//*====================================================================== * Convert a numeric string to a number, be aware of base notations. * * Arguments: * txt The numeric string. * * Returns the converted numeric value. */long read_number (char *txt){ long val; int is_neg = 0; /*------------------------------------------------------------*/ if (txt == 0 || *txt == 0) return 0; if (*txt == '-') { is_neg = 1; ++txt; } if (txt[0] == '0' && (txt[1] == 'x' || txt[1] == 'X')) /* hex */ val = simple_strtoul (&txt[2], NULL, 16); else /* decimal */ val = simple_strtoul (txt, NULL, 10); if (is_neg) val = -val; return val;} /* read_number */int downstring (char *s){ if (!s || !*s) return 0; while (*s) { if (isupper (*s)) *s = tolower (*s); s++; } return 0;} /* downstring *//*====================================================================== * Examines the instruction at the current address and determines the * next address to be executed. This will take into account branches * of different types so that a "step" and "next" operations can be * supported. * * Arguments: * nextaddr The address (to be filled in) of the next * instruction to execute. This will only be a valid * address if TRUE is returned. * * step_over A flag indicating how to compute addresses for * branch statements: * TRUE = Step over the branch (next) * FALSE = step into the branch (step) * * Returns TRUE if it was able to compute the address. Returns FALSE if * it has a problem reading the current instruction or one of the registers. */int find_next_address (unsigned char *nextaddr, int step_over, struct pt_regs *regs){ unsigned long pc; /* SRR0 register from PPC */ unsigned long ctr; /* CTR register from PPC */ unsigned long cr; /* CR register from PPC */ unsigned long lr; /* LR register from PPC */ unsigned long instr; /* instruction at SRR0 */ unsigned long next; /* computed instruction for 'next' */ unsigned long step; /* computed instruction for 'step' */ unsigned long addr = 0; /* target address operand */ unsigned long aa = 0; /* AA operand */ unsigned long lk = 0; /* LK operand */ unsigned long bo = 0; /* BO operand */ unsigned long bi = 0; /* BI operand */ struct opcode *op = 0; /* opcode structure for 'instr' */ int ctr_ok = 0; int cond_ok = 0; int conditional = 0; int branch = 0; /*------------------------------------------------------------*/ if (nextaddr == 0 || regs == 0) { printf ("find_next_address: bad args"); return FALSE; } pc = regs->nip & 0xfffffffc; instr = INSTRUCTION (pc); if ((op = find_opcode (instr)) == (struct opcode *) 0) { printf ("find_next_address: can't parse opcode 0x%lx", instr); return FALSE; } ctr = regs->ctr; cr = regs->ccr; lr = regs->link; switch (op->opcode) { case B_OPCODE (16, 0, 0): /* bc */ case B_OPCODE (16, 0, 1): /* bcl */ case B_OPCODE (16, 1, 0): /* bca */ case B_OPCODE (16, 1, 1): /* bcla */ if (!get_operand_value (op, instr, O_BD, &addr) || !get_operand_value (op, instr, O_BO, &bo) || !get_operand_value (op, instr, O_BI, &bi) || !get_operand_value (op, instr, O_AA, &aa) || !get_operand_value (op, instr, O_LK, &lk)) return FALSE; if ((addr & (1 << 13)) != 0) addr = addr - (1 << 14); addr <<= 2; conditional = 1; branch = 1; break; case I_OPCODE (18, 0, 0): /* b */ case I_OPCODE (18, 0, 1): /* bl */ case I_OPCODE (18, 1, 0): /* ba */ case I_OPCODE (18, 1, 1): /* bla */ if (!get_operand_value (op, instr, O_LI, &addr) || !get_operand_value (op, instr, O_AA, &aa) || !get_operand_value (op, instr, O_LK, &lk)) return FALSE; if ((addr & (1 << 23)) != 0) addr = addr - (1 << 24); addr <<= 2; conditional = 0; branch = 1; break; case XL_OPCODE (19, 528, 0): /* bcctr */ case XL_OPCODE (19, 528, 1): /* bcctrl */ if (!get_operand_value (op, instr, O_BO, &bo) || !get_operand_value (op, instr, O_BI, &bi) || !get_operand_value (op, instr, O_LK, &lk)) return FALSE; addr = ctr; aa = 1; conditional = 1; branch = 1; break; case XL_OPCODE (19, 16, 0): /* bclr */ case XL_OPCODE (19, 16, 1): /* bclrl */ if (!get_operand_value (op, instr, O_BO, &bo) || !get_operand_value (op, instr, O_BI, &bi) || !get_operand_value (op, instr, O_LK, &lk)) return FALSE; addr = lr; aa = 1; conditional = 1; branch = 1; break; default: conditional = 0; branch = 0; break; } if (conditional) { switch ((bo & 0x1e) >> 1) { case 0: /* 0000y */ if (--ctr != 0) ctr_ok = 1; cond_ok = !(cr & (1 << (31 - bi))); break; case 1: /* 0001y */ if (--ctr == 0) ctr_ok = 1; cond_ok = !(cr & (1 << (31 - bi))); break; case 2: /* 001zy */ ctr_ok = 1; cond_ok = !(cr & (1 << (31 - bi))); break; case 4: /* 0100y */ if (--ctr != 0) ctr_ok = 1; cond_ok = cr & (1 << (31 - bi)); break; case 5: /* 0101y */ if (--ctr == 0) ctr_ok = 1; cond_ok = cr & (1 << (31 - bi)); break; case 6: /* 011zy */ ctr_ok = 1; cond_ok = cr & (1 << (31 - bi)); break; case 8: /* 1z00y */ if (--ctr != 0) ctr_ok = cond_ok = 1; break; case 9: /* 1z01y */ if (--ctr == 0) ctr_ok = cond_ok = 1; break; case 10: /* 1z1zz */ ctr_ok = cond_ok = 1; break; } } if (branch && (!conditional || (ctr_ok && cond_ok))) { if (aa) step = addr; else step = addr + pc; if (lk) next = pc + 4; else next = step; } else { step = next = pc + 4; } if (step_over == TRUE) *(unsigned long *) nextaddr = next; else *(unsigned long *) nextaddr = step; return TRUE;} /* find_next_address *//* * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */#endif /* CONFIG_COMMANDS & CFG_CMD_BEDBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -