aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormostang.com!davidm <mostang.com!davidm>2002-12-19 07:16:50 +0000
committermostang.com!davidm <mostang.com!davidm>2002-12-19 07:16:50 +0000
commit692d6c69566f0b3eb68f039512788da752e1a3cd (patch)
tree6549930f4788a5a74f978efa296488a0d12e7844 /src
parent8bcc9b73a929af90619b3c4947f2f6bfbc5d119b (diff)
downloadlibunwind-692d6c69566f0b3eb68f039512788da752e1a3cd.tar.gz
Rename: src/dyn-remote-ia64.c -> src/dyn-remote.c
(Logical change 1.32)
Diffstat (limited to 'src')
-rw-r--r--src/dyn-remote.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/dyn-remote.c b/src/dyn-remote.c
index e69de29b..d4d50027 100644
--- a/src/dyn-remote.c
+++ b/src/dyn-remote.c
@@ -0,0 +1,259 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2001-2002 Hewlett-Packard Co
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <endian.h>
+#include <stdlib.h>
+
+#include "internal.h"
+
+static void
+free_regions (unw_dyn_region_info_t *region)
+{
+ if (region->next)
+ free_regions (region->next);
+ free (region);
+}
+
+static int
+intern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
+ unw_dyn_op_t *op, void *arg)
+{
+ int ret;
+
+ if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0
+ || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0
+ || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0
+ || (ret = fetchw (as, a, addr, &op->val, arg)) < 0)
+ return ret;
+ return 0;
+}
+
+static int
+intern_regions (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg)
+{
+ uint32_t insn_count, op_count;
+ unw_dyn_region_info_t *region;
+ unw_word_t next_addr;
+ int i, ret;
+
+ *regionp = NULL;
+
+ if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &insn_count, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &op_count, arg)) < 0)
+ return ret;
+
+ region = calloc (1, _U_dyn_region_info_size (op_count));
+ if (!region)
+ {
+ ret = -UNW_ENOMEM;
+ goto out;
+ }
+
+ region->insn_count = insn_count;
+ region->op_count = op_count;
+ for (i = 0; i < op_count; ++i)
+ if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0)
+ goto out;
+
+ if (next_addr)
+ if ((ret = intern_regions (as, a, &next_addr, &region->next, arg)) < 0)
+ goto out;
+
+ *regionp = region;
+ return 0;
+
+ out:
+ if (region)
+ free_regions (region);
+ return ret;
+}
+
+static int
+intern_array (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data,
+ void *arg)
+{
+ unw_word_t *data = calloc (table_len, WSIZE);
+ int ret = 0, i;
+
+ if (!data)
+ {
+ ret = -UNW_ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < table_len; ++i)
+ if (fetchw (as, a, addr, data + i, arg) < 0)
+ goto out;
+
+ *table_data = data;
+ return 0;
+
+ out:
+ if (data)
+ free (data);
+ return ret;
+}
+
+static void
+free_dyn_info (unw_dyn_info_t *di)
+{
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ if (di->u.pi.regions)
+ {
+ free_regions (di->u.pi.regions);
+ di->u.pi.regions = NULL;
+ }
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ if (di->u.ti.table_data)
+ {
+ free (di->u.ti.table_data);
+ di->u.ti.table_data = NULL;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static int
+intern_dyn_info (unw_addr_space_t as, unw_accessors_t *a,
+ unw_word_t *addr, unw_dyn_info_t *di, void *arg)
+{
+ int ret;
+
+ switch (di->format)
+ {
+ case UNW_INFO_FORMAT_DYNAMIC:
+ if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &di->u.pi.flags, arg)) < 0
+ || (ret = fetch32 (as, a, addr, &di->u.pi.pad0, arg)) < 0
+ || (ret = intern_regions (as, a, addr, &di->u.pi.regions, arg)) < 0)
+ goto out;
+ break;
+
+ case UNW_INFO_FORMAT_TABLE:
+ if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0
+ || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0
+ || (ret = intern_array (as, a, addr, di->u.ti.table_len,
+ &di->u.ti.table_data, arg)) < 0)
+ goto out;
+ break;
+
+ default:
+ ret = -UNW_ENOINFO;
+ goto out;
+ }
+ return 0;
+
+ out:
+ free_dyn_info (di);
+ return ret;
+}
+
+HIDDEN int
+unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, unw_word_t *genp,
+ int need_unwind_info, void *arg)
+{
+ unw_accessors_t *a = unw_get_accessors (as);
+ unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2;
+ unw_word_t start_ip, end_ip;
+ unw_dyn_info_t di;
+ int32_t pad;
+ int ret;
+
+ ret = (*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg);
+ if (ret < 0)
+ return ret;
+
+ do
+ {
+ addr = dyn_list_addr;
+
+ if ((ret = fetchw (as, a, &addr, &gen1, arg)) < 0
+ || (ret = fetchw (as, a, &addr, &next_addr, arg)) < 0)
+ return ret;
+
+ for (addr = next_addr; addr != 0; addr = next_addr)
+ {
+ if ((ret = fetchw (as, a, &addr, &next_addr, arg)) < 0
+ || (ret = fetchw (as, a, &addr, &start_ip, arg)) < 0
+ || (ret = fetchw (as, a, &addr, &end_ip, arg)) < 0)
+ return ret;
+
+ if (ip >= di.start_ip && ip < di.end_ip)
+ {
+ if ((ret = fetchw (as, a, &addr, &di.gp, arg)) < 0
+ || (ret = fetch32 (as, a, &addr, &di.format, arg)) < 0
+ || (ret = fetch32 (as, a, &addr, &pad, arg)) < 0)
+ return ret;
+
+ if (need_unwind_info)
+ if ((ret = intern_dyn_info (as, a, &addr, &di, arg)) < 0)
+ return ret;
+
+ ret = unwi_extract_dynamic_proc_info (as, ip, pi, &di,
+ need_unwind_info, arg);
+ if (ret < 0)
+ {
+ free_dyn_info (&di);
+ return ret;
+ }
+ return 0;
+ }
+ }
+
+ /* Recheck generation number to ensure things didn't change
+ underneath us: */
+ addr = dyn_list_addr;
+ if ((ret = fetchw (as, a, &addr, &gen2, arg)) < 0)
+ return ret;
+ }
+ while (gen1 != gen2);
+ *genp = gen1;
+ return 0;
+}
+
+HIDDEN void
+unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi,
+ void *arg)
+{
+ if (!pi->unwind_info)
+ return;
+
+ free_dyn_info(pi->unwind_info);
+ pi->unwind_info = NULL;
+}