From: Roland McGrath Date: Wed, 22 Jul 2009 20:55:50 +0000 (-0700) Subject: Rejigger calling conventions for dwarf_frame_{cfa,register}. X-Git-Tag: elfutils-0.142~5^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=af80014e49796185298dfb261ddf1e51d98f25c0;p=thirdparty%2Felfutils.git Rejigger calling conventions for dwarf_frame_{cfa,register}. --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 1b19e9fc5..76663eebf 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,19 @@ +2009-07-22 Roland McGrath + + * dwarf_frame_cfa.c: Change calling convention. + * libdw.h: Update decl. + + * dwarf_frame_register.c: Change calling/return-value convention for + value-only results and undefined/same_value. + * libdw.h: Update decl. + + * dwarf_getlocation.c (__libdw_intern_expression): Take new bool + argument, append DW_OP_stack_value if set. Don't take NOPS argument, + return that value instead. + (getlocation): Update caller. + * dwarf_frame_cfa.c: Likewise. + * libdwP.h: Update decl. + 2009-07-21 Roland McGrath * dwarf_getsrc_file.c: Ignore a CU that just has no DW_AT_stmt_list. diff --git a/libdw/dwarf_frame_cfa.c b/libdw/dwarf_frame_cfa.c index ccd7702fc..d1c57108f 100644 --- a/libdw/dwarf_frame_cfa.c +++ b/libdw/dwarf_frame_cfa.c @@ -56,46 +56,41 @@ #include int -dwarf_frame_cfa (fs, ops) +dwarf_frame_cfa (fs, ops, nops) Dwarf_Frame *fs; Dwarf_Op **ops; + size_t *nops; { /* Maybe there was a previous error. */ if (fs == NULL) return -1; + int result = 0; switch (fs->cfa_rule) { case cfa_undefined: *ops = NULL; - return 0; + *nops = 0; + break; case cfa_offset: /* The Dwarf_Op was already fully initialized by execute_cfi. */ *ops = &fs->cfa_data.offset; - return 1; + *nops = 1; + break; case cfa_expr: - { - unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32 - ? 4 : 8); - size_t nops; - - /* Parse the expression into internal form. */ - int result = __libdw_intern_expression (NULL, - fs->cache->other_byte_order, - address_size, - &fs->cache->expr_tree, - &fs->cfa_data.expr, - ops, &nops, - IDX_debug_frame); - return result ?: (int) nops; - } + /* Parse the expression into internal form. */ + result = __libdw_intern_expression + (NULL, fs->cache->other_byte_order, + fs->cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8, + &fs->cache->expr_tree, &fs->cfa_data.expr, false, + ops, nops, IDX_debug_frame); + break; default: abort (); } - /*NOTREACHED*/ - return -1; + return result; } diff --git a/libdw/dwarf_frame_register.c b/libdw/dwarf_frame_register.c index 231459a6e..3d232e95b 100644 --- a/libdw/dwarf_frame_register.c +++ b/libdw/dwarf_frame_register.c @@ -58,7 +58,7 @@ int dwarf_frame_register (fs, regno, ops_mem, ops, nops) Dwarf_Frame *fs; int regno; - Dwarf_Op ops_mem[2]; + Dwarf_Op ops_mem[3]; Dwarf_Op **ops; size_t *nops; { @@ -72,7 +72,8 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops) return -1; } - int result = 0; /* A location, not a value. */ + *ops = ops_mem; + *nops = 0; if (unlikely ((size_t) regno >= fs->nregs)) goto default_rule; @@ -89,35 +90,32 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops) /*FALLTHROUGH*/ case reg_undefined: /* The value is known to be unavailable. */ - result = 1; - /*FALLTHROUGH*/ + break; + case reg_same_value: same_value: /* The location is not known here, but the caller might know it. */ *ops = NULL; - *nops = 0; break; - case reg_val_offset: - result = 1; /* A value, not a location. */ - /*FALLTHROUGH*/ case reg_offset: - ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa }; - ops_mem[1] = (Dwarf_Op) { .atom = DW_OP_plus_uconst, - .number = reg->value }; + case reg_val_offset: + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa }; + if (reg->value != 0) + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_plus_uconst, + .number = reg->value }; + if (reg->rule == reg_val_offset) + /* A value, not a location. */ + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_stack_value }; *ops = ops_mem; - *nops = reg->value == 0 ? 1 : 2; break; case reg_register: - ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_regx, .number = reg->value }; - *ops = ops_mem; - *nops = 1; + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_regx, + .number = reg->value }; break; case reg_val_expression: - result = 1; /* A value, not a location. */ - /*FALLTHROUGH*/ case reg_expression: { unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32 @@ -132,13 +130,13 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops) if (__libdw_intern_expression (NULL, fs->cache->other_byte_order, address_size, - &fs->cache->expr_tree, - &block, ops, nops, - IDX_debug_frame) < 0) - result = -1; + &fs->cache->expr_tree, &block, + reg->rule == reg_val_expression, + ops, nops, IDX_debug_frame) < 0) + return -1; break; } } - return result; + return 0; } diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 0ce10837f..1488203b9 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -167,7 +167,7 @@ int internal_function __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, unsigned int address_size, - void **cache, const Dwarf_Block *block, + void **cache, const Dwarf_Block *block, bool valuep, Dwarf_Op **llbuf, size_t *listlen, int sec_index) { /* Check whether we already looked at this list. */ @@ -179,6 +179,12 @@ __libdw_intern_expression (Dwarf *dbg, *llbuf = (*found)->loc; *listlen = (*found)->nloc; + if (valuep) + { + assert (*listlen > 1); + assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value); + } + return 0; } @@ -358,6 +364,19 @@ __libdw_intern_expression (Dwarf *dbg, goto invalid; } + if (valuep) + { + struct loclist *newloc; + newloc = (struct loclist *) alloca (sizeof (struct loclist)); + newloc->atom = DW_OP_stack_value; + newloc->number = 0; + newloc->number2 = 0; + newloc->offset = data - block->data; + newloc->next = loclist; + loclist = newloc; + ++n; + } + /* Allocate the array. */ Dwarf_Op *result; if (dbg != NULL) @@ -420,8 +439,8 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, Dwarf_Op **llbuf, size_t *listlen, int sec_index) { return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order, - cu->address_size, &cu->locs, - block, llbuf, listlen, sec_index); + cu->address_size, &cu->locs, block, false, + llbuf, listlen, sec_index); } int diff --git a/libdw/libdw.h b/libdw/libdw.h index 81c2b73e6..ec352b4d3 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -750,34 +750,36 @@ extern int dwarf_cfi_addrframe (Dwarf_CFI *cache, extern int dwarf_frame_info (Dwarf_Frame *frame, Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp); -/* Deliver a DWARF expression that yields the Canonical Frame Address at - this frame state. Returns -1 for errors, or the number of operations - stored at *OPS. That pointer can be used only as long as FRAME is alive - and unchanged. Returns zero if the CFA cannot be determined here. */ -extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops) +/* Return a DWARF expression that yields the Canonical Frame Address at + this frame state. Returns -1 for errors, or zero for success, with + *NOPS set to the number of operations stored at *OPS. That pointer + can be used only as long as FRAME is alive and unchanged. *NOPS is + zero if the CFA cannot be determined here. Note that if nonempty, + *OPS is a DWARF expression, not a location description--append + DW_OP_stack_value to a get a location description for the CFA. */ +extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops, size_t *nops) __nonnull_attribute__ (2); -/* Deliver a DWARF expression that yields the location or value of - DWARF register number REGNO in the state described by FRAME. +/* Deliver a DWARF location description that yields the location or + value of DWARF register number REGNO in the state described by FRAME. - Returns -1 for errors, 0 if REGNO has an accessible location, - or 1 if REGNO has only a computable value. Stores at *NOPS - the number of operations in the array stored at *OPS. - With return value 0, this is a DWARF location expression. - With return value 1, this is a DWARF expression that computes the value. + Returns -1 for errors or zero for success, setting *NOPS to the + number of operations in the array stored at *OPS. Note the last + operation is DW_OP_stack_value if there is no mutable location but + only a computable value. - Return value 1 with *NOPS zero means CFI says the caller's REGNO is - "undefined" here, i.e. it's call-clobbered and cannot be recovered. + *NOPS zero with *OPS set to OPS_MEM means CFI says the caller's + REGNO is "undefined", i.e. it's call-clobbered and cannot be recovered. - Return value 0 with *NOPS zero means CFI says the caller's REGNO is - "same_value" here, i.e. this frame did not change it; ask the caller - frame where to find it. + *NOPS zero with *OPS set to a null pointer means CFI says the + caller's REGNO is "same_value", i.e. this frame did not change it; + ask the caller frame where to find it. For common simple expressions *OPS is OPS_MEM. For arbitrary DWARF expressions in the CFI, *OPS is an internal pointer that can be used as long as the Dwarf_CFI used to create FRAME remains alive. */ extern int dwarf_frame_register (Dwarf_Frame *frame, int regno, - Dwarf_Op ops_mem[2], + Dwarf_Op ops_mem[3], Dwarf_Op **ops, size_t *nops) __nonnull_attribute__ (3, 4, 5); diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 5c39b585e..a8f392475 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -423,9 +423,10 @@ extern int __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, unsigned int address_size, void **cache, const Dwarf_Block *block, + bool valuep, Dwarf_Op **llbuf, size_t *listlen, int sec_index) - __nonnull_attribute__ (4, 5, 6, 7) internal_function; + __nonnull_attribute__ (4, 5, 7, 8) internal_function; /* Return error code of last failing function call. This value is kept diff --git a/tests/ChangeLog b/tests/ChangeLog index 58eed0057..87654d605 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2009-07-22 Roland McGrath + + * addrcfi.c: Update dwarf_frame_{cfa,register} calling convention. + 2009-07-08 Roland McGrath * addrcfi.c: New file. diff --git a/tests/addrcfi.c b/tests/addrcfi.c index 6230621f0..2a3db05c1 100644 --- a/tests/addrcfi.c +++ b/tests/addrcfi.c @@ -125,10 +125,11 @@ handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi, ra_regno, signalp ? " (signal frame)" : ""); Dwarf_Op *cfa_ops; - int cfa_nops = dwarf_frame_cfa (stuff->frame, &cfa_ops); + size_t cfa_nops; + result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops); printf ("\tCFA "); - print_detail (cfa_nops < 0 ? -1 : 1, cfa_ops, cfa_nops, stuff->bias); + print_detail (result, cfa_ops, cfa_nops, stuff->bias); (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc), &print_register, stuff);