diff options
Diffstat (limited to 'libdw/dwarf_getlocation.c')
| -rw-r--r-- | libdw/dwarf_getlocation.c | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index f680aa96..c3233e29 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -1,5 +1,5 @@ /* Return location expression list. - Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <[email protected]>, 2000. @@ -111,15 +111,16 @@ loc_compare (const void *p1, const void *p2) return 0; } -static int -getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, - Dwarf_Op **llbuf, size_t *listlen) +int +internal_function +__libdw_intern_expression (Dwarf *dbg, + bool other_byte_order, unsigned int address_size, + void **cache, const Dwarf_Block *block, + Dwarf_Op **llbuf, size_t *listlen) { - Dwarf *dbg = cu->dbg; - /* Check whether we already looked at this list. */ struct loc_s fake = { .addr = block->data }; - struct loc_s **found = tfind (&fake, &cu->locs, loc_compare); + struct loc_s **found = tfind (&fake, cache, loc_compare); if (found != NULL) { /* We already saw it. */ @@ -132,6 +133,8 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, const unsigned char *data = block->data; const unsigned char *const end_data = data + block->length; + const struct { bool other_byte_order; } bo = { other_byte_order }; + struct loclist *loclist = NULL; unsigned int n = 0; /* Decode the opcodes. It is possible in some situations to have a @@ -151,7 +154,7 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, { case DW_OP_addr: /* Address, depends on address size of CU. */ - if (cu->address_size == 4) + if (address_size == 4) { if (unlikely (data + 4 > end_data)) { @@ -160,14 +163,14 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, return -1; } - newloc->number = read_4ubyte_unaligned_inc (dbg, data); + newloc->number = read_4ubyte_unaligned_inc (&bo, data); } else { if (unlikely (data + 8 > end_data)) goto invalid; - newloc->number = read_8ubyte_unaligned_inc (dbg, data); + newloc->number = read_8ubyte_unaligned_inc (&bo, data); } break; @@ -228,7 +231,7 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, if (unlikely (data + 2 > end_data)) goto invalid; - newloc->number = read_2ubyte_unaligned_inc (dbg, data); + newloc->number = read_2ubyte_unaligned_inc (&bo, data); break; case DW_OP_const2s: @@ -238,14 +241,14 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, if (unlikely (data + 2 > end_data)) goto invalid; - newloc->number = read_2sbyte_unaligned_inc (dbg, data); + newloc->number = read_2sbyte_unaligned_inc (&bo, data); break; case DW_OP_const4u: if (unlikely (data + 4 > end_data)) goto invalid; - newloc->number = read_4ubyte_unaligned_inc (dbg, data); + newloc->number = read_4ubyte_unaligned_inc (&bo, data); break; case DW_OP_const4s: @@ -253,21 +256,21 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, if (unlikely (data + 4 > end_data)) goto invalid; - newloc->number = read_4sbyte_unaligned_inc (dbg, data); + newloc->number = read_4sbyte_unaligned_inc (&bo, data); break; case DW_OP_const8u: if (unlikely (data + 8 > end_data)) goto invalid; - newloc->number = read_8ubyte_unaligned_inc (dbg, data); + newloc->number = read_8ubyte_unaligned_inc (&bo, data); break; case DW_OP_const8s: if (unlikely (data + 8 > end_data)) goto invalid; - newloc->number = read_8sbyte_unaligned_inc (dbg, data); + newloc->number = read_8sbyte_unaligned_inc (&bo, data); break; case DW_OP_constu: @@ -305,7 +308,19 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, } /* Allocate the array. */ - Dwarf_Op *result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n); + Dwarf_Op *result; + if (dbg != NULL) + result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n); + else + { + result = malloc (sizeof *result * n); + if (result == NULL) + { + nomem: + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + } /* Store the result. */ *llbuf = result; @@ -327,17 +342,37 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, /* Insert a record in the search tree so that we can find it again later. */ - struct loc_s *newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), - 1); + struct loc_s *newp; + if (dbg != NULL) + newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1); + else + { + newp = malloc (sizeof *newp); + if (newp == NULL) + { + free (result); + goto nomem; + } + } + newp->addr = block->data; newp->loc = result; newp->nloc = *listlen; - (void) tsearch (newp, &cu->locs, loc_compare); + (void) tsearch (newp, cache, loc_compare); /* We did it. */ return 0; } +static int +getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, + Dwarf_Op **llbuf, size_t *listlen) +{ + return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order, + cu->address_size, &cu->locs, + block, llbuf, listlen); +} + int dwarf_getlocation (attr, llbuf, listlen) Dwarf_Attribute *attr; |
