/* * Use the DWARF expression for the Call-frame-address and determine * if return address is in LR and if a new frame was allocated. */ static int check_return_reg(int ra_regno, Dwarf_Frame *frame) { Dwarf_Op ops_mem[2]; Dwarf_Op dummy; Dwarf_Op *ops = &dummy; size_t nops; int result; result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops); if (result < 0) { pr_debug("dwarf_frame_register() %s\n", dwarf_errmsg(-1)); return -1; } /* * Check if return address is on the stack. If return address * is in a register (typically R0), it is yet to be saved on * the stack. */ if ((nops != 0 || ops != NULL) && !(nops == 1 && ops[0].atom == DW_OP_regx && ops[0].number2 == 0 && ops[0].offset == 0)) return 0; /* * Return address is in LR. Check if a frame was allocated * but not-yet used. */ result = dwarf_frame_cfa(frame, &ops, &nops); if (result < 0) { pr_debug("dwarf_frame_cfa() returns %d, %s\n", result, dwarf_errmsg(-1)); return -1; } /* * If call frame address is in r1, no new frame was allocated. */ if (nops == 1 && ops[0].atom == DW_OP_bregx && ops[0].number == 1 && ops[0].number2 == 0) return 1; /* * A new frame was allocated but has not yet been used. */ return 2; }
static int print_register (void *arg, int regno, const char *setname, const char *prefix, const char *regname, int bits __attribute__ ((unused)), int type __attribute__ ((unused))) { struct stuff *stuff = arg; printf ("\t%s reg%u (%s%s): ", setname, regno, prefix, regname); Dwarf_Op ops_mem[2]; Dwarf_Op *ops; size_t nops; int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops); print_detail (result, ops, nops, stuff->bias); return DWARF_CB_OK; }