From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15856 invoked by alias); 8 Jul 2002 23:44:49 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 15847 invoked from network); 8 Jul 2002 23:44:47 -0000 Received: from unknown (HELO www.dberlin.org) (138.88.46.115) by sources.redhat.com with SMTP; 8 Jul 2002 23:44:47 -0000 Received: by www.dberlin.org (Postfix, from userid 503) id AD22D1943B60; Mon, 8 Jul 2002 19:44:46 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) by www.dberlin.org (Postfix) with ESMTP id B7CF7181BE81; Mon, 8 Jul 2002 19:44:40 -0400 (EDT) Date: Mon, 08 Jul 2002 16:48:00 -0000 From: Daniel Berlin To: gdb-patches@sources.redhat.com Cc: jimb@redhat.com Subject: [RFA]: dwarf2expr.[ch] Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Spam-Status: No, hits=0.6 required=5.0 tests=DOUBLE_CAPSWORD,NO_MX_FOR_FROM,AWL version=2.31 X-Spam-Level: X-SW-Source: 2002-07/txt/msg00129.txt.bz2 Here were the dwarf2expr.[ch] that were not included. Sorry again about that. I haven't touched this code in ages, since it just works (tested on powerpc-linux/i686-pc-linux-gnu/powerpc-eabisim on i686), so it may be there are better ways to do things since i wrote it. I also can't remember why get_subr was needed, and never implemented it. Refresh my memory if you could, since you wrote the spec? :) I've only reposted it for completeness sake, i'll include it again when i revise the loc_computed patch. --Dan Index: dwarf2expr.c =================================================================== RCS file: dwarf2expr.c diff -N dwarf2expr.c *** /dev/null 1 Jan 1970 00:00:00 -0000 --- dwarf2expr.c 8 Jul 2002 23:41:18 -0000 *************** *** 0 **** --- 1,479 ---- + + #include "defs.h" + #include "symtab.h" + #include "gdbtypes.h" + #include "elf/dwarf2.h" + #include "dwarf2expr.h" + struct dwarf_expr_context * new_dwarf_expr_context() + { + struct dwarf_expr_context *retval; + retval = xcalloc (1, sizeof (struct dwarf_expr_context)); + return retval; + } + void free_dwarf_expr_context (struct dwarf_expr_context *ctx) + { + free (ctx->stack); + free (ctx); + } + static void dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need) + { + if (ctx->stack_len + need > ctx->stack_allocated) + { + ctx->stack = xrealloc (ctx->stack, + (ctx->stack_len + need) * sizeof (CORE_ADDR)); + ctx->stack_allocated = ctx->stack_len + need; + } + } + void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value) + { + dwarf_expr_grow_stack (ctx, 1); + ctx->stack[ctx->stack_len++] = value; + } + void dwarf_expr_pop (struct dwarf_expr_context *ctx) + { + ctx->stack_len--; + } + static void execute_stack_op (struct dwarf_expr_context *, + unsigned char *, + unsigned char *); + void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, size_t len) + { + execute_stack_op (ctx, addr, addr + len); + } + + CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) + { + if (ctx->stack_len < n) + (ctx->error) ("Asked for position %d of stack, stack only has %d elements on it\n", + n, ctx->stack_len); + return ctx->stack[ctx->stack_len - (1+n)]; + + } + /* Decode the unsigned LEB128 constant at BUF into the variable pointed to + by R, and return the new value of BUF. */ + + static unsigned char * + read_uleb128 (unsigned char *buf, ULONGEST *r) + { + unsigned shift = 0; + ULONGEST result = 0; + + while (1) + { + unsigned char byte = *buf++; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + *r = result; + return buf; + } + + /* Decode the signed LEB128 constant at BUF into the variable pointed to + by R, and return the new value of BUF. */ + + static unsigned char * + read_sleb128 (unsigned char *buf, LONGEST *r) + { + unsigned shift = 0; + LONGEST result = 0; + unsigned char byte; + + while (1) + { + byte = *buf++; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0) + result |= - (1 << shift); + + *r = result; + return buf; + } + static void + execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr, + unsigned char *op_end) + { + while (op_ptr < op_end) + { + enum dwarf_location_atom op = *op_ptr++; + ULONGEST result, reg; + LONGEST offset; + ctx->in_reg = 0; + switch (op) + { + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + result = op - DW_OP_lit0; + break; + + case DW_OP_addr: + result = (CORE_ADDR) + extract_unsigned_integer (op_ptr, + TARGET_PTR_BIT / TARGET_CHAR_BIT); + op_ptr += TARGET_PTR_BIT / TARGET_CHAR_BIT; + break; + + case DW_OP_const1u: + result = extract_unsigned_integer (op_ptr, 1); + op_ptr += 1; + break; + case DW_OP_const1s: + result = extract_signed_integer (op_ptr, 1); + op_ptr += 1; + break; + case DW_OP_const2u: + result = extract_unsigned_integer (op_ptr, 2); + op_ptr += 2; + break; + case DW_OP_const2s: + result = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + break; + case DW_OP_const4u: + result = extract_unsigned_integer (op_ptr, 4); + op_ptr += 4; + break; + case DW_OP_const4s: + result = extract_signed_integer (op_ptr, 4); + op_ptr += 4; + break; + case DW_OP_const8u: + result = extract_unsigned_integer (op_ptr, 8); + op_ptr += 8; + break; + case DW_OP_const8s: + result = extract_signed_integer (op_ptr, 8); + op_ptr += 8; + break; + case DW_OP_constu: + op_ptr = read_uleb128 (op_ptr, &result); + break; + case DW_OP_consts: + op_ptr = read_sleb128 (op_ptr, &offset); + result = offset; + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + { + result = (ctx->read_reg) (ctx->read_reg_baton, op - DW_OP_reg0); + ctx->in_reg = 1; + } + break; + case DW_OP_regx: + { + op_ptr = read_uleb128 (op_ptr, ®); + result = (ctx->read_reg) (ctx->read_reg_baton, reg); + ctx->in_reg = 1; + } + break; + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + { + op_ptr = read_sleb128 (op_ptr, &offset); + result = (ctx->read_reg) (ctx->read_reg_baton, op - DW_OP_breg0); + result += offset; + } + break; + case DW_OP_bregx: + { + op_ptr = read_uleb128 (op_ptr, ®); + op_ptr = read_sleb128 (op_ptr, &offset); + result = (ctx->read_reg) (ctx->read_reg_baton, reg); + result += offset; + } + break; + case DW_OP_fbreg: + { + unsigned char *datastart; + unsigned char *dataend; + unsigned int before_stack_len; + + op_ptr = read_sleb128 (op_ptr, &offset); + /* Rather than create a whole new context, we simply + record the stack length before execution, then reset it + afterwards, effectively erasing whatever the recursive + call put there. */ + before_stack_len = ctx->stack_len; + (ctx->get_frame_base)(ctx->get_frame_base_baton, &datastart, &dataend); + dwarf_expr_eval (ctx, datastart, dataend - datastart); + result = dwarf_expr_fetch (ctx, 0) + offset; + ctx->stack_len = before_stack_len; + ctx->in_reg = 0; + } + break; + case DW_OP_dup: + result = dwarf_expr_fetch (ctx, 0); + break; + + case DW_OP_drop: + dwarf_expr_pop(ctx); + goto no_push; + + case DW_OP_pick: + offset = *op_ptr++; + result = dwarf_expr_fetch (ctx, offset); + break; + + case DW_OP_over: + result = dwarf_expr_fetch (ctx, 1); + break; + + case DW_OP_rot: + { + CORE_ADDR t1, t2, t3; + + if (ctx->stack_len < 3) + (ctx->error) ("Not enough elements for DW_OP_rot. Need 3, have %d\n", + ctx->stack_len); + t1 = ctx->stack[ctx->stack_len - 1]; + t2 = ctx->stack[ctx->stack_len - 2]; + t3 = ctx->stack[ctx->stack_len - 3]; + ctx->stack[ctx->stack_len - 1] = t2; + ctx->stack[ctx->stack_len - 2] = t3; + ctx->stack[ctx->stack_len - 3] = t1; + goto no_push; + } + + case DW_OP_deref: + case DW_OP_deref_size: + case DW_OP_abs: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_plus_uconst: + /* Unary operations. */ + result = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); + + switch (op) + { + case DW_OP_deref: + { + result = (CORE_ADDR) + (ctx->read_mem) (ctx->read_mem_baton, + result, + TARGET_PTR_BIT / TARGET_CHAR_BIT); + } + break; + + case DW_OP_deref_size: + { + result = (ctx->read_mem) (ctx->read_mem_baton, result, *op_ptr++); + } + break; + + case DW_OP_abs: + if ((signed int) result < 0) + result = -result; + break; + case DW_OP_neg: + result = -result; + break; + case DW_OP_not: + result = ~result; + break; + case DW_OP_plus_uconst: + op_ptr = read_uleb128 (op_ptr, ®); + result += reg; + break; + } + break; + + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_le: + case DW_OP_ge: + case DW_OP_eq: + case DW_OP_lt: + case DW_OP_gt: + case DW_OP_ne: + { + /* Binary operations. */ + CORE_ADDR first, second; + second = dwarf_expr_fetch (ctx, 0); + first = dwarf_expr_fetch (ctx, 1); + dwarf_expr_pop (ctx); + dwarf_expr_pop (ctx); + switch (op) + { + case DW_OP_and: + result = second & first; + break; + case DW_OP_div: + result = (LONGEST)second / (LONGEST)first; + break; + case DW_OP_minus: + result = second - first; + break; + case DW_OP_mod: + result = (LONGEST)second % (LONGEST)first; + break; + case DW_OP_mul: + result = second * first; + break; + case DW_OP_or: + result = second | first; + break; + case DW_OP_plus: + result = second + first; + break; + case DW_OP_shl: + result = second << first; + break; + case DW_OP_shr: + result = second >> first; + break; + case DW_OP_shra: + result = (LONGEST)second >> first; + break; + case DW_OP_xor: + result = second ^ first; + break; + case DW_OP_le: + result = (LONGEST)first <= (LONGEST)second; + break; + case DW_OP_ge: + result = (LONGEST)first >= (LONGEST)second; + break; + case DW_OP_eq: + result = (LONGEST)first == (LONGEST)second; + break; + case DW_OP_lt: + result = (LONGEST)first < (LONGEST)second; + break; + case DW_OP_gt: + result = (LONGEST)first > (LONGEST)second; + break; + case DW_OP_ne: + result = (LONGEST)first != (LONGEST)second; + break; + } + } + break; + + case DW_OP_skip: + offset = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + op_ptr += offset; + goto no_push; + + case DW_OP_bra: + offset = extract_signed_integer (op_ptr, 2); + op_ptr += 2; + if (dwarf_expr_fetch (ctx, 0) != 0) + op_ptr += offset; + dwarf_expr_pop (ctx); + goto no_push; + + case DW_OP_nop: + goto no_push; + + default: + abort (); + } + + /* Most things push a result value. */ + dwarf_expr_push (ctx, result); + no_push:; + } + } Index: dwarf2expr.h =================================================================== RCS file: dwarf2expr.h diff -N dwarf2expr.h *** /dev/null 1 Jan 1970 00:00:00 -0000 --- dwarf2expr.h 8 Jul 2002 23:41:18 -0000 *************** *** 0 **** --- 1,57 ---- + #if !defined (DWARF2EXPR_H) + #define DWARF2EXPR_H + struct dwarf_expr_context + { + /* The stack of values, allocated with xmalloc. */ + CORE_ADDR *stack; + + /* The number of values currently pushed on the stack, and the + number of elements allocated to the stack. */ + int stack_len, stack_allocated; + + /* The size of an address, in bits. */ + int addr_size; + + /* Return the value of register number REGNUM. */ + CORE_ADDR (*read_reg) (void *baton, int regnum); + void *read_reg_baton; + + /* Return the LEN-byte value at ADDR. */ + CORE_ADDR (*read_mem) (void *baton, CORE_ADDR addr, size_t len); + void *read_mem_baton; + + /* Return the location expression for the frame base attribute. The + result must be live until the current expression evaluation is + complete. */ + void (*get_frame_base) (void *baton, unsigned char **begin, + unsigned char **end); + void *get_frame_base_baton; + + /* Return the location expression for the dwarf expression + subroutine in the die at OFFSET in the current compilation unit. + The result must be live until the current expression evaluation + is complete. */ + unsigned char *(*get_subr) (void *baton, off_t offset); + void *get_subr_baton; + + /* Return the `object address' for DW_OP_push_object_address. */ + CORE_ADDR (*get_object_address) (void *baton); + void *get_object_address_baton; + + /* The current depth of dwarf expression recursion, via DW_OP_call*, + DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum + depth we'll tolerate before raising an error. */ + int recursion_depth, max_recursion_depth; + + int in_reg; + + void (*error) (const char *fmt, ...); + }; + struct dwarf_expr_context * new_dwarf_expr_context(); + void free_dwarf_expr_context (struct dwarf_expr_context *ctx); + void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value); + void dwarf_expr_pop (struct dwarf_expr_context *ctx); + void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, + size_t len); + CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); + #endif