+/* See symtab.h. */
+
+bool
+find_function_entry_range_from_pc (CORE_ADDR pc, const char **name,
+ CORE_ADDR *address, CORE_ADDR *endaddr)
+{
+ const struct block *block;
+ bool status = find_pc_partial_function (pc, name, address, endaddr, &block);
+
+ if (status && block != nullptr && !BLOCK_CONTIGUOUS_P (block))
+ {
+ CORE_ADDR entry_pc = BLOCK_ENTRY_PC (block);
+
+ for (int i = 0; i < BLOCK_NRANGES (block); i++)
+ {
+ if (BLOCK_RANGE_START (block, i) <= entry_pc
+ && entry_pc < BLOCK_RANGE_END (block, i))
+ {
+ if (address != nullptr)
+ *address = BLOCK_RANGE_START (block, i);
+
+ if (endaddr != nullptr)
+ *endaddr = BLOCK_RANGE_END (block, i);
+
+ return status;
+ }
+ }
+
+ /* It's an internal error if we exit the above loop without finding
+ the range. */
+ internal_error (__FILE__, __LINE__,
+ _("Entry block not found in find_function_entry_range_from_pc"));
+ }
+
+ return status;
+}
+
+/* See symtab.h. */
+
+struct type *
+find_function_type (CORE_ADDR pc)
+{
+ struct symbol *sym = find_pc_function (pc);
+
+ if (sym != NULL && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == pc)
+ return SYMBOL_TYPE (sym);
+
+ return NULL;
+}
+
+/* See symtab.h. */
+
+struct type *
+find_gnu_ifunc_target_type (CORE_ADDR resolver_funaddr)
+{
+ struct type *resolver_type = find_function_type (resolver_funaddr);
+ if (resolver_type != NULL)
+ {
+ /* Get the return type of the resolver. */
+ struct type *resolver_ret_type
+ = check_typedef (TYPE_TARGET_TYPE (resolver_type));
+
+ /* If we found a pointer to function, then the resolved type
+ is the type of the pointed-to function. */
+ if (TYPE_CODE (resolver_ret_type) == TYPE_CODE_PTR)
+ {
+ struct type *resolved_type
+ = TYPE_TARGET_TYPE (resolver_ret_type);
+ if (TYPE_CODE (check_typedef (resolved_type)) == TYPE_CODE_FUNC)
+ return resolved_type;
+ }
+ }
+
+ return NULL;
+}
+
+/* Return the innermost stack frame that is executing inside of BLOCK and is
+ at least as old as the selected frame. Return NULL if there is no
+ such frame. If BLOCK is NULL, just return NULL. */