diff options
| author | Roland McGrath <[email protected]> | 2009-06-24 17:41:40 -0700 |
|---|---|---|
| committer | Roland McGrath <[email protected]> | 2009-07-08 15:15:52 -0700 |
| commit | 3c84db3b4b610bf636c4363abb6d3dac5ae020f9 (patch) | |
| tree | e0af0c5a7f27a3f06a66353a3da9bec0bd7bd32f /libdw/dwarf_getlocation.c | |
| parent | fe8b42e6131b74829fe31d15f31349cade566a59 (diff) | |
CFI support: lookup by PC and translate into DWARF location per register
Diffstat (limited to 'libdw/dwarf_getlocation.c')
| -rw-r--r-- | libdw/dwarf_getlocation.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 62106ce3..b036883c 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -163,15 +163,16 @@ check_constant_offset (Dwarf_Attribute *attr, return 0; } -static int -getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, - Dwarf_Op **llbuf, size_t *listlen, int sec_index) +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, int sec_index) { - 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. */ @@ -184,6 +185,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 @@ -204,7 +207,7 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, case DW_OP_addr: /* Address, depends on address size of CU. */ if (__libdw_read_address_inc (dbg, sec_index, &data, - cu->address_size, &newloc->number)) + address_size, &newloc->number)) return -1; break; @@ -269,7 +272,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: @@ -279,14 +282,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: @@ -294,21 +297,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: @@ -346,7 +349,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; @@ -368,17 +383,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, int sec_index) +{ + return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order, + cu->address_size, &cu->locs, + block, llbuf, listlen, sec_index); +} + int dwarf_getlocation (attr, llbuf, listlen) Dwarf_Attribute *attr; |
