/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* interface used by unwind support to query frame descriptor info
*/
#ifndef _LIBCRUN_
#include "lint.h"
#endif
#include "stack_unwind.h"
#include "unwind_context.h"
#include "reg_num.h"
enum CFA_ops {
/* skip 9 values */
};
struct operation_desc {
};
/* data factored offset */
/* data factored offset */
/* data factored offset */
/* data fctored offset */
/* code factored delta */
/* data factored offset */
};
struct register_state f_state[],
struct register_state f_start_state[],
/*
* The entry-point state of old_ctx defines the current
* suspended state of the caller (in new_ctx). If the old info
* will not be refered to again, old_ctx == new_ctx is OK
*/
void
struct _Unwind_Context *new_ctx)
{
}
void
{
default:
break;
case register_rule: /* CFA = offset + source_reg */
break;
case constant_rule: /* CFA = offset */
break;
case indirect_rule: /* CFA = *(offset + source_reg) */
break;
}
}
void
{
case undefined_rule:
default:
break;
case offset_rule: /* RA = *(offset + CFA) */
break;
case register_rule: /* RA = offset + source_reg */
break;
case indirect_rule: /* RA = *(offset + source_reg) */
break;
}
}
void
{
default:
break;
case offset_rule: /* target_reg = *(offset + CFA) */
break;
case is_offset_rule: /* target_reg = offset + CFA */
break;
case register_rule: /* target_reg = offset + source_reg */
break;
case constant_rule: /* target_reg = offset */
break;
case indirect_rule: /* target_reg = *(offset + source_reg) */
break;
}
}
/*
* Input: f->{cie_ops, cie_ops_end, fde_ops, fde_ops_end}
* + location of DWARF opcodes
* ctx->{current_regs, pc}
* + register values and pc at point of suspension
* Output: ctx->{entry_regs, cfa, ra}
* + register values when function was entered
* + Cannonical Frame Address
* + return address
*/
struct _Unwind_Context *ctx)
{
/* GPRs, RET_ADD, and CF_ADDR */
int i;
if (f == 0) {
/*
* When no FDE we assume all routines have a frame pointer
* and pass back existing callee saves registers
*/
return (0);
}
}
for (i = 0; i < 18; i++)
func_start_state[i] = nop;
for (i = 0; i < 18; i++)
func_state[i] = func_start_state[i];
return (0);
}
}
/*
* remap two-bit opcodes into a separate range or grab eight-bit opcode
* and advance pointer past it.
*/
static enum CFA_ops
{
if (c & 0xc0) {
switch (c & 0xc0) {
case DW_CFA_advance_loc:
return (DW_CFA_SUNW_advance_loc);
case DW_CFA_offset:
return (DW_CFA_SUNW_offset);
case DW_CFA_restore:
return (DW_CFA_SUNW_restore);
}
} else {
}
return (c);
}
static uint64_t
{
int shift = 0;
int val;
while (more) {
shift += 7;
}
return (res);
}
static uint64_t
{
int shift = 0;
unsigned int val;
while (more) {
shift += 7;
}
return (res);
}
/*
* do all field extractions needed for CFA operands and encoded FDE
* fields
*/
{
switch (opr) {
case NO_OPR:
res = 0;
break;
case ULEB128_FAC:
/* NOTREACHED */
break;
case ULEB128:
return (extractuleb(datap));
/* NOTREACHED */
break;
case ULEB128_SREG:
data += 1;
switch (res) {
/* verify that register is one which is being tracked */
case GPR_RBX:
case FP_RBP:
case SP_RSP:
case EIR_R12:
case EIR_R13:
case EIR_R14:
case EIR_R15:
break;
default:
break;
}
break;
case UNUM6:
data += 1;
break;
case UNUM8:
data += 1;
break;
case UNUM16:
data += 2;
break;
case UNUM32:
data += 4;
break;
case UNUM6_CFAC:
data += 1;
break;
case UNUM8_CFAC:
data += 1;
break;
case UNUM16_CFAC:
data += 2;
break;
case UNUM32_CFAC:
data += 4;
break;
case UNUM64:
data += 8;
break;
case SNUM8:
data += 1;
break;
case SNUM16:
data += 2;
break;
case SNUM32:
data += 4;
break;
case SNUM64:
data += 8;
break;
case SLEB128_FAC:
/* NOTREACHED */
break;
case SLEB128:
return (extractsleb(datap));
/* NOTREACHED */
break;
case ZTSTRING:
/* max length of augmentation string is 4 */
;
break;
case ADDR:
/* NOTREACHED */
break;
case SIZE:
case BLOCK:
res = 0; /* not implemented */
break;
}
return (res);
}
static uint64_t
{
switch (val) {
case 0x01:
break;
case 0x2:
break;
case 0x3:
break;
case 0x04:
break;
case 0x09:
break;
case 0x0a:
break;
case 0x0b:
break;
case 0x0c:
break;
}
switch (rel) {
case 0:
break;
case 1:
if (res != 0)
break;
default:
/* remainder not implemented */
break;
}
return (res);
}
struct register_state f_state[],
struct register_state f_start_state[],
struct register_state f_state[],
struct register_state f_start_state[],
{
void *d = data;
while (d < data_end) {
break;
}
return (reached_pc);
}
int
struct register_state f_state[],
struct register_state f_start_state[],
{
return (0);
switch (op) {
case DW_CFA_nop:
break;
case DW_CFA_set_loc:
return (1);
*reached_pc_p = val1;
break;
case DW_CFA_advance_loc1:
case DW_CFA_advance_loc2:
case DW_CFA_advance_loc4:
return (1);
*reached_pc_p += val1;
break;
case DW_CFA_offset_extended:
break;
case DW_CFA_restore_extended:
if (f_start_state != 0)
break;
case DW_CFA_undefined:
break;
case DW_CFA_same_value:
break;
case DW_CFA_register:
break;
case DW_CFA_remember_state:
break;
case DW_CFA_restore_state:
break;
case DW_CFA_def_cfa:
break;
case DW_CFA_def_cfa_register:
break;
case DW_CFA_def_cfa_offset:
break;
break;
case DW_CFA_expression:
break;
break;
case DW_CFA_def_cfa_sf:
break;
case DW_CFA_def_cfa_offset_sf:
break;
case DW_CFA_SUNW_advance_loc:
return (1);
*reached_pc_p += val1;
break;
case DW_CFA_SUNW_offset:
break;
case DW_CFA_SUNW_restore:
if (f_start_state != 0)
break;
}
return (0);
}