brintos

brintos / linux-shallow public Read only

0
0
Text · 19.2 KiB · 16c2b03 Raw
832 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.4 *5 * Lots of this code have been borrowed or heavily inspired from parts of6 * the libunwind 0.99 code which are (amongst other contributors I may have7 * forgotten):8 *9 * Copyright (C) 2002-2007 Hewlett-Packard Co10 *	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>11 *12 * And the bugs have been added by:13 *14 * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>15 * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>16 *17 */18 19#include <elf.h>20#include <errno.h>21#include <gelf.h>22#include <fcntl.h>23#include <inttypes.h>24#include <string.h>25#include <unistd.h>26#include <sys/mman.h>27#include <linux/list.h>28#include <linux/zalloc.h>29#ifndef REMOTE_UNWIND_LIBUNWIND30#include <libunwind.h>31#include <libunwind-ptrace.h>32#endif33#include "callchain.h"34#include "thread.h"35#include "session.h"36#include "perf_regs.h"37#include "unwind.h"38#include "map.h"39#include "symbol.h"40#include "debug.h"41#include "asm/bug.h"42#include "dso.h"43 44extern int45UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,46				    unw_word_t ip,47				    unw_dyn_info_t *di,48				    unw_proc_info_t *pi,49				    int need_unwind_info, void *arg);50 51#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)52 53extern int54UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,55				 unw_word_t ip,56				 unw_word_t segbase,57				 const char *obj_name, unw_word_t start,58				 unw_word_t end);59 60#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)61 62#define DW_EH_PE_FORMAT_MASK	0x0f	/* format of the encoded value */63#define DW_EH_PE_APPL_MASK	0x70	/* how the value is to be applied */64 65/* Pointer-encoding formats: */66#define DW_EH_PE_omit		0xff67#define DW_EH_PE_ptr		0x00	/* pointer-sized unsigned value */68#define DW_EH_PE_udata4		0x03	/* unsigned 32-bit value */69#define DW_EH_PE_udata8		0x04	/* unsigned 64-bit value */70#define DW_EH_PE_sdata4		0x0b	/* signed 32-bit value */71#define DW_EH_PE_sdata8		0x0c	/* signed 64-bit value */72 73/* Pointer-encoding application: */74#define DW_EH_PE_absptr		0x00	/* absolute value */75#define DW_EH_PE_pcrel		0x10	/* rel. to addr. of encoded value */76 77/*78 * The following are not documented by LSB v1.3, yet they are used by79 * GCC, presumably they aren't documented by LSB since they aren't80 * used on Linux:81 */82#define DW_EH_PE_funcrel	0x40	/* start-of-procedure-relative */83#define DW_EH_PE_aligned	0x50	/* aligned pointer */84 85/* Flags intentionally not handled, since they're not needed:86 * #define DW_EH_PE_indirect      0x8087 * #define DW_EH_PE_uleb128       0x0188 * #define DW_EH_PE_udata2        0x0289 * #define DW_EH_PE_sleb128       0x0990 * #define DW_EH_PE_sdata2        0x0a91 * #define DW_EH_PE_textrel       0x2092 * #define DW_EH_PE_datarel       0x3093 */94 95struct unwind_info {96	struct perf_sample	*sample;97	struct machine		*machine;98	struct thread		*thread;99	bool			 best_effort;100};101 102#define dw_read(ptr, type, end) ({	\103	type *__p = (type *) ptr;	\104	type  __v;			\105	if ((__p + 1) > (type *) end)	\106		return -EINVAL;		\107	__v = *__p++;			\108	ptr = (typeof(ptr)) __p;	\109	__v;				\110	})111 112static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,113				   u8 encoding)114{115	u8 *cur = *p;116	*val = 0;117 118	switch (encoding) {119	case DW_EH_PE_omit:120		*val = 0;121		goto out;122	case DW_EH_PE_ptr:123		*val = dw_read(cur, unsigned long, end);124		goto out;125	default:126		break;127	}128 129	switch (encoding & DW_EH_PE_APPL_MASK) {130	case DW_EH_PE_absptr:131		break;132	case DW_EH_PE_pcrel:133		*val = (unsigned long) cur;134		break;135	default:136		return -EINVAL;137	}138 139	if ((encoding & 0x07) == 0x00)140		encoding |= DW_EH_PE_udata4;141 142	switch (encoding & DW_EH_PE_FORMAT_MASK) {143	case DW_EH_PE_sdata4:144		*val += dw_read(cur, s32, end);145		break;146	case DW_EH_PE_udata4:147		*val += dw_read(cur, u32, end);148		break;149	case DW_EH_PE_sdata8:150		*val += dw_read(cur, s64, end);151		break;152	case DW_EH_PE_udata8:153		*val += dw_read(cur, u64, end);154		break;155	default:156		return -EINVAL;157	}158 159 out:160	*p = cur;161	return 0;162}163 164#define dw_read_encoded_value(ptr, end, enc) ({			\165	u64 __v;						\166	if (__dw_read_encoded_value(&ptr, end, &__v, enc)) {	\167		return -EINVAL;                                 \168	}                                                       \169	__v;                                                    \170	})171 172static int elf_section_address_and_offset(int fd, const char *name, u64 *address, u64 *offset)173{174	Elf *elf;175	GElf_Ehdr ehdr;176	GElf_Shdr shdr;177	int ret = -1;178 179	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);180	if (elf == NULL)181		return -1;182 183	if (gelf_getehdr(elf, &ehdr) == NULL)184		goto out_err;185 186	if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))187		goto out_err;188 189	*address = shdr.sh_addr;190	*offset = shdr.sh_offset;191	ret = 0;192out_err:193	elf_end(elf);194	return ret;195}196 197#ifndef NO_LIBUNWIND_DEBUG_FRAME198static u64 elf_section_offset(int fd, const char *name)199{200	u64 address, offset = 0;201 202	if (elf_section_address_and_offset(fd, name, &address, &offset))203		return 0;204 205	return offset;206}207#endif208 209static u64 elf_base_address(int fd)210{211	Elf *elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);212	GElf_Phdr phdr;213	u64 retval = 0;214	size_t i, phdrnum = 0;215 216	if (elf == NULL)217		return 0;218	(void)elf_getphdrnum(elf, &phdrnum);219	/* PT_LOAD segments are sorted by p_vaddr, so the first has the minimum p_vaddr. */220	for (i = 0; i < phdrnum; i++) {221		if (gelf_getphdr(elf, i, &phdr) && phdr.p_type == PT_LOAD) {222			retval = phdr.p_vaddr & -getpagesize();223			break;224		}225	}226 227	elf_end(elf);228	return retval;229}230 231#ifndef NO_LIBUNWIND_DEBUG_FRAME232static int elf_is_exec(int fd, const char *name)233{234	Elf *elf;235	GElf_Ehdr ehdr;236	int retval = 0;237 238	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);239	if (elf == NULL)240		return 0;241	if (gelf_getehdr(elf, &ehdr) == NULL)242		goto out;243 244	retval = (ehdr.e_type == ET_EXEC);245 246out:247	elf_end(elf);248	pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);249	return retval;250}251#endif252 253struct table_entry {254	u32 start_ip_offset;255	u32 fde_offset;256};257 258struct eh_frame_hdr {259	unsigned char version;260	unsigned char eh_frame_ptr_enc;261	unsigned char fde_count_enc;262	unsigned char table_enc;263 264	/*265	 * The rest of the header is variable-length and consists of the266	 * following members:267	 *268	 *	encoded_t eh_frame_ptr;269	 *	encoded_t fde_count;270	 */271 272	/* A single encoded pointer should not be more than 8 bytes. */273	u64 enc[2];274 275	/*276	 * struct {277	 *    encoded_t start_ip;278	 *    encoded_t fde_addr;279	 * } binary_search_table[fde_count];280	 */281	char data[];282} __packed;283 284static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,285			       u64 offset, u64 *table_data_offset, u64 *fde_count)286{287	struct eh_frame_hdr hdr;288	u8 *enc = (u8 *) &hdr.enc;289	u8 *end = (u8 *) &hdr.data;290	ssize_t r;291 292	r = dso__data_read_offset(dso, machine, offset,293				  (u8 *) &hdr, sizeof(hdr));294	if (r != sizeof(hdr))295		return -EINVAL;296 297	/* We dont need eh_frame_ptr, just skip it. */298	dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);299 300	*fde_count  = dw_read_encoded_value(enc, end, hdr.fde_count_enc);301	*table_data_offset = enc - (u8 *) &hdr;302	return 0;303}304 305struct read_unwind_spec_eh_frame_maps_cb_args {306	struct dso *dso;307	u64 base_addr;308};309 310static int read_unwind_spec_eh_frame_maps_cb(struct map *map, void *data)311{312 313	struct read_unwind_spec_eh_frame_maps_cb_args *args = data;314 315	if (map__dso(map) == args->dso && map__start(map) - map__pgoff(map) < args->base_addr)316		args->base_addr = map__start(map) - map__pgoff(map);317 318	return 0;319}320 321 322static int read_unwind_spec_eh_frame(struct dso *dso, struct unwind_info *ui,323				     u64 *table_data, u64 *segbase,324				     u64 *fde_count)325{326	struct read_unwind_spec_eh_frame_maps_cb_args args = {327		.dso = dso,328		.base_addr = UINT64_MAX,329	};330	int ret, fd;331 332	if (dso__data(dso)->eh_frame_hdr_offset == 0) {333		fd = dso__data_get_fd(dso, ui->machine);334		if (fd < 0)335			return -EINVAL;336 337		/* Check the .eh_frame section for unwinding info */338		ret = elf_section_address_and_offset(fd, ".eh_frame_hdr",339						     &dso__data(dso)->eh_frame_hdr_addr,340						     &dso__data(dso)->eh_frame_hdr_offset);341		dso__data(dso)->elf_base_addr = elf_base_address(fd);342		dso__data_put_fd(dso);343		if (ret || dso__data(dso)->eh_frame_hdr_offset == 0)344			return -EINVAL;345	}346 347	maps__for_each_map(thread__maps(ui->thread), read_unwind_spec_eh_frame_maps_cb, &args);348 349	args.base_addr -= dso__data(dso)->elf_base_addr;350	/* Address of .eh_frame_hdr */351	*segbase = args.base_addr + dso__data(dso)->eh_frame_hdr_addr;352	ret = unwind_spec_ehframe(dso, ui->machine, dso__data(dso)->eh_frame_hdr_offset,353				   table_data, fde_count);354	if (ret)355		return ret;356	/* binary_search_table offset plus .eh_frame_hdr address */357	*table_data += *segbase;358	return 0;359}360 361#ifndef NO_LIBUNWIND_DEBUG_FRAME362static int read_unwind_spec_debug_frame(struct dso *dso,363					struct machine *machine, u64 *offset)364{365	int fd;366	u64 ofs = dso__data(dso)->debug_frame_offset;367 368	/* debug_frame can reside in:369	 *  - dso370	 *  - debug pointed by symsrc_filename371	 *  - gnu_debuglink, which doesn't necessary372	 *    has to be pointed by symsrc_filename373	 */374	if (ofs == 0) {375		fd = dso__data_get_fd(dso, machine);376		if (fd >= 0) {377			ofs = elf_section_offset(fd, ".debug_frame");378			dso__data_put_fd(dso);379		}380 381		if (ofs <= 0) {382			fd = open(dso__symsrc_filename(dso), O_RDONLY);383			if (fd >= 0) {384				ofs = elf_section_offset(fd, ".debug_frame");385				close(fd);386			}387		}388 389		if (ofs <= 0) {390			char *debuglink = malloc(PATH_MAX);391			int ret = 0;392 393			if (debuglink == NULL) {394				pr_err("unwind: Can't read unwind spec debug frame.\n");395				return -ENOMEM;396			}397 398			ret = dso__read_binary_type_filename(399				dso, DSO_BINARY_TYPE__DEBUGLINK,400				machine->root_dir, debuglink, PATH_MAX);401			if (!ret) {402				fd = open(debuglink, O_RDONLY);403				if (fd >= 0) {404					ofs = elf_section_offset(fd,405							".debug_frame");406					close(fd);407				}408			}409			if (ofs > 0) {410				if (dso__symsrc_filename(dso) != NULL) {411					pr_warning(412						"%s: overwrite symsrc(%s,%s)\n",413							__func__,414							dso__symsrc_filename(dso),415							debuglink);416					dso__free_symsrc_filename(dso);417				}418				dso__set_symsrc_filename(dso, debuglink);419			} else {420				free(debuglink);421			}422		}423 424		dso__data(dso)->debug_frame_offset = ofs;425	}426 427	*offset = ofs;428	if (*offset)429		return 0;430 431	return -EINVAL;432}433#endif434 435static struct map *find_map(unw_word_t ip, struct unwind_info *ui)436{437	struct addr_location al;438	struct map *ret;439 440	addr_location__init(&al);441	thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al);442	ret = map__get(al.map);443	addr_location__exit(&al);444	return ret;445}446 447static int448find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,449	       int need_unwind_info, void *arg)450{451	struct unwind_info *ui = arg;452	struct map *map;453	struct dso *dso;454	unw_dyn_info_t di;455	u64 table_data, segbase, fde_count;456	int ret = -EINVAL;457 458	map = find_map(ip, ui);459	if (!map)460		return -EINVAL;461 462	dso = map__dso(map);463	if (!dso) {464		map__put(map);465		return -EINVAL;466	}467 468	pr_debug("unwind: find_proc_info dso %s\n", dso__name(dso));469 470	/* Check the .eh_frame section for unwinding info */471	if (!read_unwind_spec_eh_frame(dso, ui, &table_data, &segbase, &fde_count)) {472		memset(&di, 0, sizeof(di));473		di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;474		di.start_ip = map__start(map);475		di.end_ip   = map__end(map);476		di.u.rti.segbase    = segbase;477		di.u.rti.table_data = table_data;478		di.u.rti.table_len  = fde_count * sizeof(struct table_entry)479				      / sizeof(unw_word_t);480		ret = dwarf_search_unwind_table(as, ip, &di, pi,481						need_unwind_info, arg);482	}483 484#ifndef NO_LIBUNWIND_DEBUG_FRAME485	/* Check the .debug_frame section for unwinding info */486	if (ret < 0 &&487	    !read_unwind_spec_debug_frame(dso, ui->machine, &segbase)) {488		int fd = dso__data_get_fd(dso, ui->machine);489		int is_exec = elf_is_exec(fd, dso__name(dso));490		u64 start = map__start(map);491		unw_word_t base = is_exec ? 0 : start;492		const char *symfile;493 494		if (fd >= 0)495			dso__data_put_fd(dso);496 497		symfile = dso__symsrc_filename(dso) ?: dso__name(dso);498 499		memset(&di, 0, sizeof(di));500		if (dwarf_find_debug_frame(0, &di, ip, base, symfile, start, map__end(map)))501			ret = dwarf_search_unwind_table(as, ip, &di, pi,502							need_unwind_info, arg);503	}504#endif505	map__put(map);506	return ret;507}508 509static int access_fpreg(unw_addr_space_t __maybe_unused as,510			unw_regnum_t __maybe_unused num,511			unw_fpreg_t __maybe_unused *val,512			int __maybe_unused __write,513			void __maybe_unused *arg)514{515	pr_err("unwind: access_fpreg unsupported\n");516	return -UNW_EINVAL;517}518 519static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,520				  unw_word_t __maybe_unused *dil_addr,521				  void __maybe_unused *arg)522{523	return -UNW_ENOINFO;524}525 526static int resume(unw_addr_space_t __maybe_unused as,527		  unw_cursor_t __maybe_unused *cu,528		  void __maybe_unused *arg)529{530	pr_err("unwind: resume unsupported\n");531	return -UNW_EINVAL;532}533 534static int535get_proc_name(unw_addr_space_t __maybe_unused as,536	      unw_word_t __maybe_unused addr,537		char __maybe_unused *bufp, size_t __maybe_unused buf_len,538		unw_word_t __maybe_unused *offp, void __maybe_unused *arg)539{540	pr_err("unwind: get_proc_name unsupported\n");541	return -UNW_EINVAL;542}543 544static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,545			  unw_word_t *data)546{547	struct map *map;548	struct dso *dso;549	ssize_t size;550 551	map = find_map(addr, ui);552	if (!map) {553		pr_debug("unwind: no map for %lx\n", (unsigned long)addr);554		return -1;555	}556 557	dso = map__dso(map);558 559	if (!dso) {560		map__put(map);561		return -1;562	}563 564	size = dso__data_read_addr(dso, map, ui->machine,565				   addr, (u8 *) data, sizeof(*data));566	map__put(map);567	return !(size == sizeof(*data));568}569 570static int access_mem(unw_addr_space_t __maybe_unused as,571		      unw_word_t addr, unw_word_t *valp,572		      int __write, void *arg)573{574	struct unwind_info *ui = arg;575	const char *arch = perf_env__arch(ui->machine->env);576	struct stack_dump *stack = &ui->sample->user_stack;577	u64 start, end;578	int offset;579	int ret;580 581	/* Don't support write, probably not needed. */582	if (__write || !stack || !ui->sample->user_regs.regs) {583		*valp = 0;584		return 0;585	}586 587	ret = perf_reg_value(&start, &ui->sample->user_regs,588			     perf_arch_reg_sp(arch));589	if (ret)590		return ret;591 592	end = start + stack->size;593 594	/* Check overflow. */595	if (addr + sizeof(unw_word_t) < addr)596		return -EINVAL;597 598	if (addr < start || addr + sizeof(unw_word_t) >= end) {599		ret = access_dso_mem(ui, addr, valp);600		if (ret) {601			pr_debug("unwind: access_mem %p not inside range"602				 " 0x%" PRIx64 "-0x%" PRIx64 "\n",603				 (void *) (uintptr_t) addr, start, end);604			*valp = 0;605			return ret;606		}607		return 0;608	}609 610	offset = addr - start;611	*valp  = *(unw_word_t *)&stack->data[offset];612	pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",613		 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);614	return 0;615}616 617static int access_reg(unw_addr_space_t __maybe_unused as,618		      unw_regnum_t regnum, unw_word_t *valp,619		      int __write, void *arg)620{621	struct unwind_info *ui = arg;622	int id, ret;623	u64 val;624 625	/* Don't support write, I suspect we don't need it. */626	if (__write) {627		pr_err("unwind: access_reg w %d\n", regnum);628		return 0;629	}630 631	if (!ui->sample->user_regs.regs) {632		*valp = 0;633		return 0;634	}635 636	id = LIBUNWIND__ARCH_REG_ID(regnum);637	if (id < 0)638		return -EINVAL;639 640	ret = perf_reg_value(&val, &ui->sample->user_regs, id);641	if (ret) {642		if (!ui->best_effort)643			pr_err("unwind: can't read reg %d\n", regnum);644		return ret;645	}646 647	*valp = (unw_word_t) val;648	pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);649	return 0;650}651 652static void put_unwind_info(unw_addr_space_t __maybe_unused as,653			    unw_proc_info_t *pi __maybe_unused,654			    void *arg __maybe_unused)655{656	pr_debug("unwind: put_unwind_info called\n");657}658 659static int entry(u64 ip, struct thread *thread,660		 unwind_entry_cb_t cb, void *arg)661{662	struct unwind_entry e;663	struct addr_location al;664	int ret;665 666	addr_location__init(&al);667	e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);668	e.ip     = ip;669	e.ms.map = al.map;670	e.ms.maps = al.maps;671 672	pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",673		 al.sym ? al.sym->name : "''",674		 ip,675		 al.map ? map__map_ip(al.map, ip) : (u64) 0);676 677	ret = cb(&e, arg);678	addr_location__exit(&al);679	return ret;680}681 682static void display_error(int err)683{684	switch (err) {685	case UNW_EINVAL:686		pr_err("unwind: Only supports local.\n");687		break;688	case UNW_EUNSPEC:689		pr_err("unwind: Unspecified error.\n");690		break;691	case UNW_EBADREG:692		pr_err("unwind: Register unavailable.\n");693		break;694	default:695		break;696	}697}698 699static unw_accessors_t accessors = {700	.find_proc_info		= find_proc_info,701	.put_unwind_info	= put_unwind_info,702	.get_dyn_info_list_addr	= get_dyn_info_list_addr,703	.access_mem		= access_mem,704	.access_reg		= access_reg,705	.access_fpreg		= access_fpreg,706	.resume			= resume,707	.get_proc_name		= get_proc_name,708};709 710static int _unwind__prepare_access(struct maps *maps)711{712	void *addr_space = unw_create_addr_space(&accessors, 0);713 714	maps__set_addr_space(maps, addr_space);715	if (!addr_space) {716		pr_err("unwind: Can't create unwind address space.\n");717		return -ENOMEM;718	}719 720	unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);721	return 0;722}723 724static void _unwind__flush_access(struct maps *maps)725{726	unw_flush_cache(maps__addr_space(maps), 0, 0);727}728 729static void _unwind__finish_access(struct maps *maps)730{731	unw_destroy_addr_space(maps__addr_space(maps));732}733 734static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,735		       void *arg, int max_stack)736{737	const char *arch = perf_env__arch(ui->machine->env);738	u64 val;739	unw_word_t ips[max_stack];740	unw_addr_space_t addr_space;741	unw_cursor_t c;742	int ret, i = 0;743 744	ret = perf_reg_value(&val, &ui->sample->user_regs,745			     perf_arch_reg_ip(arch));746	if (ret)747		return ret;748 749	ips[i++] = (unw_word_t) val;750 751	/*752	 * If we need more than one entry, do the DWARF753	 * unwind itself.754	 */755	if (max_stack - 1 > 0) {756		WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");757		addr_space = maps__addr_space(thread__maps(ui->thread));758 759		if (addr_space == NULL)760			return -1;761 762		ret = unw_init_remote(&c, addr_space, ui);763		if (ret && !ui->best_effort)764			display_error(ret);765 766		while (!ret && (unw_step(&c) > 0) && i < max_stack) {767			unw_get_reg(&c, UNW_REG_IP, &ips[i]);768 769			/*770			 * Decrement the IP for any non-activation frames.771			 * this is required to properly find the srcline772			 * for caller frames.773			 * See also the documentation for dwfl_frame_pc(),774			 * which this code tries to replicate.775			 */776			if (unw_is_signal_frame(&c) <= 0)777				--ips[i];778 779			++i;780		}781 782		max_stack = i;783	}784 785	/*786	 * Display what we got based on the order setup.787	 */788	for (i = 0; i < max_stack && !ret; i++) {789		int j = i;790 791		if (callchain_param.order == ORDER_CALLER)792			j = max_stack - i - 1;793		ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;794	}795 796	return ret;797}798 799static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,800			struct thread *thread,801			struct perf_sample *data, int max_stack,802			bool best_effort)803{804	struct unwind_info ui = {805		.sample       = data,806		.thread       = thread,807		.machine      = maps__machine(thread__maps(thread)),808		.best_effort  = best_effort809	};810 811	if (!data->user_regs.regs)812		return -EINVAL;813 814	if (max_stack <= 0)815		return -EINVAL;816 817	return get_entries(&ui, cb, arg, max_stack);818}819 820static struct unwind_libunwind_ops821_unwind_libunwind_ops = {822	.prepare_access = _unwind__prepare_access,823	.flush_access   = _unwind__flush_access,824	.finish_access  = _unwind__finish_access,825	.get_entries    = _unwind__get_entries,826};827 828#ifndef REMOTE_UNWIND_LIBUNWIND829struct unwind_libunwind_ops *830local_unwind_libunwind_ops = &_unwind_libunwind_ops;831#endif832