diff options
author | Adeel <3840695+am11@users.noreply.github.com> | 2022-06-29 19:13:56 +0300 |
---|---|---|
committer | Stephen M. Webb <stephen.webb@bregmasoft.ca> | 2022-07-08 15:59:28 -0400 |
commit | 4640cd26d5e045b738bacc20ed92a7cf8e801c0f (patch) | |
tree | 9340c3756e6e732a9bbb7f3824b8eb40e65fe044 /src/mi | |
parent | cfcf3d193a4425f58ed9556ec54b6d7ab0557330 (diff) | |
download | libunwind-4640cd26d5e045b738bacc20ed92a7cf8e801c0f.tar.gz |
Expose get_proc_info_in_range API
Diffstat (limited to 'src/mi')
-rw-r--r-- | src/mi/Gget_proc_info_in_range.c | 111 | ||||
-rw-r--r-- | src/mi/Lget_proc_info_in_range.c | 5 |
2 files changed, 116 insertions, 0 deletions
diff --git a/src/mi/Gget_proc_info_in_range.c b/src/mi/Gget_proc_info_in_range.c new file mode 100644 index 00000000..b9a369ba --- /dev/null +++ b/src/mi/Gget_proc_info_in_range.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2022 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 <stddef.h> +#include "libunwind_i.h" +#include "dwarf-eh.h" +#include "dwarf_i.h" + +int +unw_get_proc_info_in_range (unw_word_t start_ip, unw_word_t end_ip, + unw_word_t eh_frame_table, unw_word_t eh_frame_table_len, + unw_word_t exidx_frame_table, unw_word_t exidx_frame_table_len, + unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, + void *arg) +{ + int ret = 0; + + unw_dyn_info_t di; + memset(&di, 0, sizeof(di)); + + di.start_ip = start_ip; + di.end_ip = end_ip; + di.gp = pi->gp; + di.u.rti.name_ptr = 0; + +#if UNW_TARGET_ARM + if (exidx_frame_table != 0) { + di.format = UNW_INFO_FORMAT_ARM_EXIDX; + di.u.rti.table_data = exidx_frame_table; + di.u.rti.table_len = exidx_frame_table_len; + di.u.rti.segbase = 0; + } + else +#endif + if (eh_frame_table != 0) { + unw_accessors_t *a = unw_get_accessors_int (as); + + unw_word_t hdr; + if ((*a->access_mem)(as, eh_frame_table, &hdr, 0, arg) < 0) { + return -UNW_EINVAL; + } + struct dwarf_eh_frame_hdr* exhdr = (struct dwarf_eh_frame_hdr*)&hdr; + + if (exhdr->version != DW_EH_VERSION) { + Debug (1, "Unexpected version %d\n", exhdr->version); + return -UNW_EBADVERSION; + } + unw_word_t addr = eh_frame_table + offsetof(struct dwarf_eh_frame_hdr, eh_frame); + unw_word_t eh_frame_start; + unw_word_t fde_count; + + /* read eh_frame_ptr */ + if ((ret = dwarf_read_encoded_pointer(as, a, &addr, exhdr->eh_frame_ptr_enc, pi, &eh_frame_start, arg)) < 0) { + return ret; + } + + /* read fde_count */ + if ((ret = dwarf_read_encoded_pointer(as, a, &addr, exhdr->fde_count_enc, pi, &fde_count, arg)) < 0) { + return ret; + } + + // If there are no frame table entries + if (fde_count == 0) { + Debug(1, "No frame table entries\n"); + return -UNW_ENOINFO; + } + + if (exhdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { + Debug (1, "Table encoding not supported %x\n", exhdr->table_enc); + return -UNW_EINVAL; + } + + di.format = UNW_INFO_FORMAT_REMOTE_TABLE; + di.u.rti.table_data = addr; + di.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); + di.u.rti.segbase = eh_frame_table; + } + else { + Debug (1, "No frame table data\n"); + return -UNW_ENOINFO; + } + + ret = tdep_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + if (ret < 0) { + return ret; + } + + if (ip < pi->start_ip || ip >= pi->end_ip) { + Debug (1, "ip %p not in range start_ip %p end_ip %p\n", ip, pi->start_ip, pi->end_ip); + return -UNW_ENOINFO; + } + return UNW_ESUCCESS; +} diff --git a/src/mi/Lget_proc_info_in_range.c b/src/mi/Lget_proc_info_in_range.c new file mode 100644 index 00000000..da670090 --- /dev/null +++ b/src/mi/Lget_proc_info_in_range.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include <libunwind.h> +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info_in_range.c" +#endif |