Linux Audio

Check our new training course

Loading...
v6.13.7
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   4 * Copyright (C) 2002-2006 Novell, Inc.
   5 *	Jan Beulich <jbeulich@novell.com>
   6 *
   7 * A simple API for unwinding kernel stacks.  This is used for
   8 * debugging and error reporting purposes.  The kernel doesn't need
   9 * full-blown stack unwinding with all the bells and whistles, so there
  10 * is not much point in implementing the full Dwarf2 unwind API.
  11 */
  12
  13#include <linux/sched.h>
  14#include <linux/module.h>
  15#include <linux/memblock.h>
  16#include <linux/sort.h>
  17#include <linux/slab.h>
  18#include <linux/stop_machine.h>
  19#include <linux/uaccess.h>
  20#include <linux/ptrace.h>
  21#include <asm/sections.h>
  22#include <linux/unaligned.h>
  23#include <asm/unwind.h>
  24
  25extern char __start_unwind[], __end_unwind[];
  26/* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
  27
  28/* #define UNWIND_DEBUG */
  29
  30#ifdef UNWIND_DEBUG
  31int dbg_unw;
  32#define unw_debug(fmt, ...)			\
  33do {						\
  34	if (dbg_unw)				\
  35		pr_info(fmt, ##__VA_ARGS__);	\
  36} while (0);
  37#else
  38#define unw_debug(fmt, ...)
  39#endif
  40
  41#define MAX_STACK_DEPTH 8
  42
  43#define EXTRA_INFO(f) { \
  44		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
  45				% sizeof_field(struct unwind_frame_info, f)) \
  46				+ offsetof(struct unwind_frame_info, f) \
  47				/ sizeof_field(struct unwind_frame_info, f), \
  48				sizeof_field(struct unwind_frame_info, f) \
  49	}
  50#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
  51
  52static const struct {
  53	unsigned offs:BITS_PER_LONG / 2;
  54	unsigned width:BITS_PER_LONG / 2;
  55} reg_info[] = {
  56UNW_REGISTER_INFO};
  57
  58#undef PTREGS_INFO
  59#undef EXTRA_INFO
  60
  61#ifndef REG_INVALID
  62#define REG_INVALID(r) (reg_info[r].width == 0)
  63#endif
  64
  65#define DW_CFA_nop                          0x00
  66#define DW_CFA_set_loc                      0x01
  67#define DW_CFA_advance_loc1                 0x02
  68#define DW_CFA_advance_loc2                 0x03
  69#define DW_CFA_advance_loc4                 0x04
  70#define DW_CFA_offset_extended              0x05
  71#define DW_CFA_restore_extended             0x06
  72#define DW_CFA_undefined                    0x07
  73#define DW_CFA_same_value                   0x08
  74#define DW_CFA_register                     0x09
  75#define DW_CFA_remember_state               0x0a
  76#define DW_CFA_restore_state                0x0b
  77#define DW_CFA_def_cfa                      0x0c
  78#define DW_CFA_def_cfa_register             0x0d
  79#define DW_CFA_def_cfa_offset               0x0e
  80#define DW_CFA_def_cfa_expression           0x0f
  81#define DW_CFA_expression                   0x10
  82#define DW_CFA_offset_extended_sf           0x11
  83#define DW_CFA_def_cfa_sf                   0x12
  84#define DW_CFA_def_cfa_offset_sf            0x13
  85#define DW_CFA_val_offset                   0x14
  86#define DW_CFA_val_offset_sf                0x15
  87#define DW_CFA_val_expression               0x16
  88#define DW_CFA_lo_user                      0x1c
  89#define DW_CFA_GNU_window_save              0x2d
  90#define DW_CFA_GNU_args_size                0x2e
  91#define DW_CFA_GNU_negative_offset_extended 0x2f
  92#define DW_CFA_hi_user                      0x3f
  93
  94#define DW_EH_PE_FORM     0x07
  95#define DW_EH_PE_native   0x00
  96#define DW_EH_PE_leb128   0x01
  97#define DW_EH_PE_data2    0x02
  98#define DW_EH_PE_data4    0x03
  99#define DW_EH_PE_data8    0x04
 100#define DW_EH_PE_signed   0x08
 101#define DW_EH_PE_ADJUST   0x70
 102#define DW_EH_PE_abs      0x00
 103#define DW_EH_PE_pcrel    0x10
 104#define DW_EH_PE_textrel  0x20
 105#define DW_EH_PE_datarel  0x30
 106#define DW_EH_PE_funcrel  0x40
 107#define DW_EH_PE_aligned  0x50
 108#define DW_EH_PE_indirect 0x80
 109#define DW_EH_PE_omit     0xff
 110
 111#define CIE_ID	0
 112
 113typedef unsigned long uleb128_t;
 114typedef signed long sleb128_t;
 115
 116static struct unwind_table {
 117	struct {
 118		unsigned long pc;
 119		unsigned long range;
 120	} core, init;
 121	const void *address;
 122	unsigned long size;
 123	const unsigned char *header;
 124	unsigned long hdrsz;
 125	struct unwind_table *link;
 126	const char *name;
 127} root_table;
 128
 129struct unwind_item {
 130	enum item_location {
 131		Nowhere,
 132		Memory,
 133		Register,
 134		Value
 135	} where;
 136	uleb128_t value;
 137};
 138
 139struct unwind_state {
 140	uleb128_t loc, org;
 141	const u8 *cieStart, *cieEnd;
 142	uleb128_t codeAlign;
 143	sleb128_t dataAlign;
 144	struct cfa {
 145		uleb128_t reg, offs;
 146	} cfa;
 147	struct unwind_item regs[ARRAY_SIZE(reg_info)];
 148	unsigned stackDepth:8;
 149	unsigned version:8;
 150	const u8 *label;
 151	const u8 *stack[MAX_STACK_DEPTH];
 152};
 153
 154static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
 155
 156static struct unwind_table *find_table(unsigned long pc)
 157{
 158	struct unwind_table *table;
 159
 160	for (table = &root_table; table; table = table->link)
 161		if ((pc >= table->core.pc
 162		     && pc < table->core.pc + table->core.range)
 163		    || (pc >= table->init.pc
 164			&& pc < table->init.pc + table->init.range))
 165			break;
 166
 167	return table;
 168}
 169
 170static unsigned long read_pointer(const u8 **pLoc,
 171				  const void *end, signed ptrType);
 172static void init_unwind_hdr(struct unwind_table *table,
 173			    void *(*alloc) (unsigned long));
 174
 175/*
 176 * wrappers for header alloc (vs. calling one vs. other at call site)
 177 * to elide section mismatches warnings
 178 */
 179static void *__init unw_hdr_alloc_early(unsigned long sz)
 180{
 181	return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
 182}
 183
 184static void init_unwind_table(struct unwind_table *table, const char *name,
 185			      const void *core_start, unsigned long core_size,
 186			      const void *init_start, unsigned long init_size,
 187			      const void *table_start, unsigned long table_size,
 188			      const u8 *header_start, unsigned long header_size)
 189{
 190	table->core.pc = (unsigned long)core_start;
 191	table->core.range = core_size;
 192	table->init.pc = (unsigned long)init_start;
 193	table->init.range = init_size;
 194	table->address = table_start;
 195	table->size = table_size;
 196	/* To avoid the pointer addition with NULL pointer.*/
 197	if (header_start != NULL) {
 198		const u8 *ptr = header_start + 4;
 199		const u8 *end = header_start + header_size;
 200		/* See if the linker provided table looks valid. */
 201		if (header_size <= 4
 202		|| header_start[0] != 1
 203		|| (void *)read_pointer(&ptr, end, header_start[1])
 204				!= table_start
 205		|| header_start[2] == DW_EH_PE_omit
 206		|| read_pointer(&ptr, end, header_start[2]) <= 0
 207		|| header_start[3] == DW_EH_PE_omit)
 208			header_start = NULL;
 209	}
 210	table->hdrsz = header_size;
 211	smp_wmb();
 212	table->header = header_start;
 213	table->link = NULL;
 214	table->name = name;
 215}
 216
 217void __init arc_unwind_init(void)
 218{
 219	init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
 220			  __start_unwind, __end_unwind - __start_unwind,
 221			  NULL, 0);
 222	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
 223
 224	init_unwind_hdr(&root_table, unw_hdr_alloc_early);
 225}
 226
 227static const u32 bad_cie, not_fde;
 228static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
 229static const u32 *__cie_for_fde(const u32 *fde);
 230static signed fde_pointer_type(const u32 *cie);
 231
 232struct eh_frame_hdr_table_entry {
 233	unsigned long start, fde;
 234};
 235
 236static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
 237{
 238	const struct eh_frame_hdr_table_entry *e1 = p1;
 239	const struct eh_frame_hdr_table_entry *e2 = p2;
 240
 241	return (e1->start > e2->start) - (e1->start < e2->start);
 242}
 243
 244static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
 245{
 246	struct eh_frame_hdr_table_entry *e1 = p1;
 247	struct eh_frame_hdr_table_entry *e2 = p2;
 
 248
 249	swap(e1->start, e2->start);
 250	swap(e1->fde, e2->fde);
 
 
 
 
 251}
 252
 253static void init_unwind_hdr(struct unwind_table *table,
 254			    void *(*alloc) (unsigned long))
 255{
 256	const u8 *ptr;
 257	unsigned long tableSize = table->size, hdrSize;
 258	unsigned int n;
 259	const u32 *fde;
 260	struct {
 261		u8 version;
 262		u8 eh_frame_ptr_enc;
 263		u8 fde_count_enc;
 264		u8 table_enc;
 265		unsigned long eh_frame_ptr;
 266		unsigned int fde_count;
 267		struct eh_frame_hdr_table_entry table[];
 268	} __attribute__ ((__packed__)) *header;
 269
 270	if (table->header)
 271		return;
 272
 273	if (table->hdrsz)
 274		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
 275			table->name);
 276
 277	if (tableSize & (sizeof(*fde) - 1))
 278		return;
 279
 280	for (fde = table->address, n = 0;
 281	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
 282	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 283		const u32 *cie = cie_for_fde(fde, table);
 284		signed ptrType;
 285
 286		if (cie == &not_fde)
 287			continue;
 288		if (cie == NULL || cie == &bad_cie)
 289			goto ret_err;
 290		ptrType = fde_pointer_type(cie);
 291		if (ptrType < 0)
 292			goto ret_err;
 293
 294		ptr = (const u8 *)(fde + 2);
 295		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
 296								ptrType)) {
 297			/* FIXME_Rajesh We have 4 instances of null addresses
 298			 * instead of the initial loc addr
 299			 * return;
 300			 */
 301			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
 302				(const u8 *)(fde + 1) + *fde);
 303		}
 304		++n;
 305	}
 306
 307	if (tableSize || !n)
 308		goto ret_err;
 309
 310	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
 311	    + 2 * n * sizeof(unsigned long);
 312
 313	header = alloc(hdrSize);
 314	if (!header)
 315		goto ret_err;
 316
 317	header->version = 1;
 318	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
 319	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
 320	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
 321	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
 322	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
 323		     % __alignof(typeof(header->fde_count)));
 324	header->fde_count = n;
 325
 326	BUILD_BUG_ON(offsetof(typeof(*header), table)
 327		     % __alignof(typeof(*header->table)));
 328	for (fde = table->address, tableSize = table->size, n = 0;
 329	     tableSize;
 330	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 331		const u32 *cie = __cie_for_fde(fde);
 332
 333		if (fde[1] == CIE_ID)
 334			continue;	/* this is a CIE */
 335		ptr = (const u8 *)(fde + 2);
 336		header->table[n].start = read_pointer(&ptr,
 337						      (const u8 *)(fde + 1) +
 338						      *fde,
 339						      fde_pointer_type(cie));
 340		header->table[n].fde = (unsigned long)fde;
 341		++n;
 342	}
 343	WARN_ON(n != header->fde_count);
 344
 345	sort(header->table,
 346	     n,
 347	     sizeof(*header->table),
 348	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
 349
 350	table->hdrsz = hdrSize;
 351	smp_wmb();
 352	table->header = (const void *)header;
 353	return;
 354
 355ret_err:
 356	panic("Attention !!! Dwarf FDE parsing errors\n");
 357}
 358
 359#ifdef CONFIG_MODULES
 360static void *unw_hdr_alloc(unsigned long sz)
 361{
 362	return kmalloc(sz, GFP_KERNEL);
 363}
 364
 365static struct unwind_table *last_table;
 366
 367/* Must be called with module_mutex held. */
 368void *unwind_add_table(struct module *module, const void *table_start,
 369		       unsigned long table_size)
 370{
 371	struct unwind_table *table;
 372	struct module_memory *core_text;
 373	struct module_memory *init_text;
 374
 375	if (table_size <= 0)
 376		return NULL;
 377
 378	table = kmalloc(sizeof(*table), GFP_KERNEL);
 379	if (!table)
 380		return NULL;
 381
 382	core_text = &module->mem[MOD_TEXT];
 383	init_text = &module->mem[MOD_INIT_TEXT];
 384
 385	init_unwind_table(table, module->name, core_text->base, core_text->size,
 386			  init_text->base, init_text->size, table_start, table_size, NULL, 0);
 387
 388	init_unwind_hdr(table, unw_hdr_alloc);
 389
 390#ifdef UNWIND_DEBUG
 391	unw_debug("Table added for [%s] %lx %lx\n",
 392		module->name, table->core.pc, table->core.range);
 393#endif
 394	if (last_table)
 395		last_table->link = table;
 396	else
 397		root_table.link = table;
 398	last_table = table;
 399
 400	return table;
 401}
 402
 403struct unlink_table_info {
 404	struct unwind_table *table;
 405	int init_only;
 406};
 407
 408static int unlink_table(void *arg)
 409{
 410	struct unlink_table_info *info = arg;
 411	struct unwind_table *table = info->table, *prev;
 412
 413	for (prev = &root_table; prev->link && prev->link != table;
 414	     prev = prev->link)
 415		;
 416
 417	if (prev->link) {
 418		if (info->init_only) {
 419			table->init.pc = 0;
 420			table->init.range = 0;
 421			info->table = NULL;
 422		} else {
 423			prev->link = table->link;
 424			if (!prev->link)
 425				last_table = prev;
 426		}
 427	} else
 428		info->table = NULL;
 429
 430	return 0;
 431}
 432
 433/* Must be called with module_mutex held. */
 434void unwind_remove_table(void *handle, int init_only)
 435{
 436	struct unwind_table *table = handle;
 437	struct unlink_table_info info;
 438
 439	if (!table || table == &root_table)
 440		return;
 441
 442	if (init_only && table == last_table) {
 443		table->init.pc = 0;
 444		table->init.range = 0;
 445		return;
 446	}
 447
 448	info.table = table;
 449	info.init_only = init_only;
 450
 451	unlink_table(&info); /* XXX: SMP */
 452	kfree(table->header);
 453	kfree(table);
 454}
 455
 456#endif /* CONFIG_MODULES */
 457
 458static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
 459{
 460	const u8 *cur = *pcur;
 461	uleb128_t value;
 462	unsigned int shift;
 463
 464	for (shift = 0, value = 0; cur < end; shift += 7) {
 465		if (shift + 7 > 8 * sizeof(value)
 466		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 467			cur = end + 1;
 468			break;
 469		}
 470		value |= (uleb128_t) (*cur & 0x7f) << shift;
 471		if (!(*cur++ & 0x80))
 472			break;
 473	}
 474	*pcur = cur;
 475
 476	return value;
 477}
 478
 479static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
 480{
 481	const u8 *cur = *pcur;
 482	sleb128_t value;
 483	unsigned int shift;
 484
 485	for (shift = 0, value = 0; cur < end; shift += 7) {
 486		if (shift + 7 > 8 * sizeof(value)
 487		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 488			cur = end + 1;
 489			break;
 490		}
 491		value |= (sleb128_t) (*cur & 0x7f) << shift;
 492		if (!(*cur & 0x80)) {
 493			value |= -(*cur++ & 0x40) << shift;
 494			break;
 495		}
 496	}
 497	*pcur = cur;
 498
 499	return value;
 500}
 501
 502static const u32 *__cie_for_fde(const u32 *fde)
 503{
 504	const u32 *cie;
 505
 506	cie = fde + 1 - fde[1] / sizeof(*fde);
 507
 508	return cie;
 509}
 510
 511static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
 512{
 513	const u32 *cie;
 514
 515	if (!*fde || (*fde & (sizeof(*fde) - 1)))
 516		return &bad_cie;
 517
 518	if (fde[1] == CIE_ID)
 519		return &not_fde;	/* this is a CIE */
 520
 521	if ((fde[1] & (sizeof(*fde) - 1)))
 522/* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
 523		return NULL;	/* this is not a valid FDE */
 524
 525	cie = __cie_for_fde(fde);
 526
 527	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
 528	    || (*cie & (sizeof(*cie) - 1))
 529	    || (cie[1] != CIE_ID))
 530		return NULL;	/* this is not a (valid) CIE */
 531	return cie;
 532}
 533
 534static unsigned long read_pointer(const u8 **pLoc, const void *end,
 535				  signed ptrType)
 536{
 537	unsigned long value = 0;
 538	union {
 539		const u8 *p8;
 540		const u16 *p16u;
 541		const s16 *p16s;
 542		const u32 *p32u;
 543		const s32 *p32s;
 544		const unsigned long *pul;
 545	} ptr;
 546
 547	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
 548		return 0;
 549	ptr.p8 = *pLoc;
 550	switch (ptrType & DW_EH_PE_FORM) {
 551	case DW_EH_PE_data2:
 552		if (end < (const void *)(ptr.p16u + 1))
 553			return 0;
 554		if (ptrType & DW_EH_PE_signed)
 555			value = get_unaligned((u16 *) ptr.p16s++);
 556		else
 557			value = get_unaligned((u16 *) ptr.p16u++);
 558		break;
 559	case DW_EH_PE_data4:
 560#ifdef CONFIG_64BIT
 561		if (end < (const void *)(ptr.p32u + 1))
 562			return 0;
 563		if (ptrType & DW_EH_PE_signed)
 564			value = get_unaligned(ptr.p32s++);
 565		else
 566			value = get_unaligned(ptr.p32u++);
 567		break;
 568	case DW_EH_PE_data8:
 569		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
 570#else
 571		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
 572#endif
 573		fallthrough;
 574	case DW_EH_PE_native:
 575		if (end < (const void *)(ptr.pul + 1))
 576			return 0;
 577		value = get_unaligned((unsigned long *)ptr.pul++);
 578		break;
 579	case DW_EH_PE_leb128:
 580		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
 581		value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
 582		    : get_uleb128(&ptr.p8, end);
 583		if ((const void *)ptr.p8 > end)
 584			return 0;
 585		break;
 586	default:
 587		return 0;
 588	}
 589	switch (ptrType & DW_EH_PE_ADJUST) {
 590	case DW_EH_PE_abs:
 591		break;
 592	case DW_EH_PE_pcrel:
 593		value += (unsigned long)*pLoc;
 594		break;
 595	default:
 596		return 0;
 597	}
 598	if ((ptrType & DW_EH_PE_indirect)
 599	    && __get_user(value, (unsigned long __user *)value))
 600		return 0;
 601	*pLoc = ptr.p8;
 602
 603	return value;
 604}
 605
 606static signed fde_pointer_type(const u32 *cie)
 607{
 608	const u8 *ptr = (const u8 *)(cie + 2);
 609	unsigned int version = *ptr;
 610
 611	if (*++ptr) {
 612		const char *aug;
 613		const u8 *end = (const u8 *)(cie + 1) + *cie;
 614		uleb128_t len;
 615
 616		/* check if augmentation size is first (and thus present) */
 617		if (*ptr != 'z')
 618			return -1;
 619
 620		/* check if augmentation string is nul-terminated */
 621		aug = (const void *)ptr;
 622		ptr = memchr(aug, 0, end - ptr);
 623		if (ptr == NULL)
 624			return -1;
 625
 626		++ptr;		/* skip terminator */
 627		get_uleb128(&ptr, end);	/* skip code alignment */
 628		get_sleb128(&ptr, end);	/* skip data alignment */
 629		/* skip return address column */
 630		version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
 631		len = get_uleb128(&ptr, end);	/* augmentation length */
 632
 633		if (ptr + len < ptr || ptr + len > end)
 634			return -1;
 635
 636		end = ptr + len;
 637		while (*++aug) {
 638			if (ptr >= end)
 639				return -1;
 640			switch (*aug) {
 641			case 'L':
 642				++ptr;
 643				break;
 644			case 'P':{
 645					signed ptrType = *ptr++;
 646
 647					if (!read_pointer(&ptr, end, ptrType)
 648					    || ptr > end)
 649						return -1;
 650				}
 651				break;
 652			case 'R':
 653				return *ptr;
 654			default:
 655				return -1;
 656			}
 657		}
 658	}
 659	return DW_EH_PE_native | DW_EH_PE_abs;
 660}
 661
 662static int advance_loc(unsigned long delta, struct unwind_state *state)
 663{
 664	state->loc += delta * state->codeAlign;
 665
 666	/* FIXME_Rajesh: Probably we are defining for the initial range as well;
 667	   return delta > 0;
 668	 */
 669	unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
 670	return 1;
 671}
 672
 673static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
 674		     struct unwind_state *state)
 675{
 676	if (reg < ARRAY_SIZE(state->regs)) {
 677		state->regs[reg].where = where;
 678		state->regs[reg].value = value;
 679
 680#ifdef UNWIND_DEBUG
 681		unw_debug("r%lu: ", reg);
 682		switch (where) {
 683		case Nowhere:
 684			unw_debug("s ");
 685			break;
 686		case Memory:
 687			unw_debug("c(%lu) ", value);
 688			break;
 689		case Register:
 690			unw_debug("r(%lu) ", value);
 691			break;
 692		case Value:
 693			unw_debug("v(%lu) ", value);
 694			break;
 695		default:
 696			break;
 697		}
 698#endif
 699	}
 700}
 701
 702static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
 703		      signed ptrType, struct unwind_state *state)
 704{
 705	union {
 706		const u8 *p8;
 707		const u16 *p16;
 708		const u32 *p32;
 709	} ptr;
 710	int result = 1;
 711	u8 opcode;
 712
 713	if (start != state->cieStart) {
 714		state->loc = state->org;
 715		result =
 716		    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
 717			       state);
 718		if (targetLoc == 0 && state->label == NULL)
 719			return result;
 720	}
 721	for (ptr.p8 = start; result && ptr.p8 < end;) {
 722		switch (*ptr.p8 >> 6) {
 723			uleb128_t value;
 724
 725		case 0:
 726			opcode = *ptr.p8++;
 727
 728			switch (opcode) {
 729			case DW_CFA_nop:
 730				unw_debug("cfa nop ");
 731				break;
 732			case DW_CFA_set_loc:
 733				state->loc = read_pointer(&ptr.p8, end,
 734							  ptrType);
 735				if (state->loc == 0)
 736					result = 0;
 737				unw_debug("cfa_set_loc: 0x%lx ", state->loc);
 738				break;
 739			case DW_CFA_advance_loc1:
 740				unw_debug("\ncfa advance loc1:");
 741				result = ptr.p8 < end
 742				    && advance_loc(*ptr.p8++, state);
 743				break;
 744			case DW_CFA_advance_loc2:
 745				value = *ptr.p8++;
 746				value += *ptr.p8++ << 8;
 747				unw_debug("\ncfa advance loc2:");
 748				result = ptr.p8 <= end + 2
 749				    /* && advance_loc(*ptr.p16++, state); */
 750				    && advance_loc(value, state);
 751				break;
 752			case DW_CFA_advance_loc4:
 753				unw_debug("\ncfa advance loc4:");
 754				result = ptr.p8 <= end + 4
 755				    && advance_loc(*ptr.p32++, state);
 756				break;
 757			case DW_CFA_offset_extended:
 758				value = get_uleb128(&ptr.p8, end);
 759				unw_debug("cfa_offset_extended: ");
 760				set_rule(value, Memory,
 761					 get_uleb128(&ptr.p8, end), state);
 762				break;
 763			case DW_CFA_val_offset:
 764				value = get_uleb128(&ptr.p8, end);
 765				set_rule(value, Value,
 766					 get_uleb128(&ptr.p8, end), state);
 767				break;
 768			case DW_CFA_offset_extended_sf:
 769				value = get_uleb128(&ptr.p8, end);
 770				set_rule(value, Memory,
 771					 get_sleb128(&ptr.p8, end), state);
 772				break;
 773			case DW_CFA_val_offset_sf:
 774				value = get_uleb128(&ptr.p8, end);
 775				set_rule(value, Value,
 776					 get_sleb128(&ptr.p8, end), state);
 777				break;
 778			case DW_CFA_restore_extended:
 779				unw_debug("cfa_restore_extended: ");
 780			case DW_CFA_undefined:
 781				unw_debug("cfa_undefined: ");
 782			case DW_CFA_same_value:
 783				unw_debug("cfa_same_value: ");
 784				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
 785					 state);
 786				break;
 787			case DW_CFA_register:
 788				unw_debug("cfa_register: ");
 789				value = get_uleb128(&ptr.p8, end);
 790				set_rule(value,
 791					 Register,
 792					 get_uleb128(&ptr.p8, end), state);
 793				break;
 794			case DW_CFA_remember_state:
 795				unw_debug("cfa_remember_state: ");
 796				if (ptr.p8 == state->label) {
 797					state->label = NULL;
 798					return 1;
 799				}
 800				if (state->stackDepth >= MAX_STACK_DEPTH)
 801					return 0;
 802				state->stack[state->stackDepth++] = ptr.p8;
 803				break;
 804			case DW_CFA_restore_state:
 805				unw_debug("cfa_restore_state: ");
 806				if (state->stackDepth) {
 807					const uleb128_t loc = state->loc;
 808					const u8 *label = state->label;
 809
 810					state->label =
 811					    state->stack[state->stackDepth - 1];
 812					memcpy(&state->cfa, &badCFA,
 813					       sizeof(state->cfa));
 814					memset(state->regs, 0,
 815					       sizeof(state->regs));
 816					state->stackDepth = 0;
 817					result =
 818					    processCFI(start, end, 0, ptrType,
 819						       state);
 820					state->loc = loc;
 821					state->label = label;
 822				} else
 823					return 0;
 824				break;
 825			case DW_CFA_def_cfa:
 826				state->cfa.reg = get_uleb128(&ptr.p8, end);
 827				unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
 828				fallthrough;
 829			case DW_CFA_def_cfa_offset:
 830				state->cfa.offs = get_uleb128(&ptr.p8, end);
 831				unw_debug("cfa_def_cfa_offset: 0x%lx ",
 832					  state->cfa.offs);
 833				break;
 834			case DW_CFA_def_cfa_sf:
 835				state->cfa.reg = get_uleb128(&ptr.p8, end);
 836				fallthrough;
 837			case DW_CFA_def_cfa_offset_sf:
 838				state->cfa.offs = get_sleb128(&ptr.p8, end)
 839				    * state->dataAlign;
 840				break;
 841			case DW_CFA_def_cfa_register:
 842				unw_debug("cfa_def_cfa_register: ");
 843				state->cfa.reg = get_uleb128(&ptr.p8, end);
 844				break;
 845				/*todo case DW_CFA_def_cfa_expression: */
 846				/*todo case DW_CFA_expression: */
 847				/*todo case DW_CFA_val_expression: */
 848			case DW_CFA_GNU_args_size:
 849				get_uleb128(&ptr.p8, end);
 850				break;
 851			case DW_CFA_GNU_negative_offset_extended:
 852				value = get_uleb128(&ptr.p8, end);
 853				set_rule(value,
 854					 Memory,
 855					 (uleb128_t) 0 - get_uleb128(&ptr.p8,
 856								     end),
 857					 state);
 858				break;
 859			case DW_CFA_GNU_window_save:
 860			default:
 861				unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
 862				result = 0;
 863				break;
 864			}
 865			break;
 866		case 1:
 867			unw_debug("\ncfa_adv_loc: ");
 868			result = advance_loc(*ptr.p8++ & 0x3f, state);
 869			break;
 870		case 2:
 871			unw_debug("cfa_offset: ");
 872			value = *ptr.p8++ & 0x3f;
 873			set_rule(value, Memory, get_uleb128(&ptr.p8, end),
 874				 state);
 875			break;
 876		case 3:
 877			unw_debug("cfa_restore: ");
 878			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
 879			break;
 880		}
 881
 882		if (ptr.p8 > end)
 883			result = 0;
 884		if (result && targetLoc != 0 && targetLoc < state->loc)
 885			return 1;
 886	}
 887
 888	return result && ptr.p8 == end && (targetLoc == 0 || (
 889		/*todo While in theory this should apply, gcc in practice omits
 890		  everything past the function prolog, and hence the location
 891		  never reaches the end of the function.
 892		targetLoc < state->loc && */  state->label == NULL));
 893}
 894
 895/* Unwind to previous to frame.  Returns 0 if successful, negative
 896 * number in case of an error. */
 897int arc_unwind(struct unwind_frame_info *frame)
 898{
 899#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
 900	const u32 *fde = NULL, *cie = NULL;
 901	const u8 *ptr = NULL, *end = NULL;
 902	unsigned long pc = UNW_PC(frame) - frame->call_frame;
 903	unsigned long startLoc = 0, endLoc = 0, cfa;
 904	unsigned int i;
 905	signed ptrType = -1;
 906	uleb128_t retAddrReg = 0;
 907	const struct unwind_table *table;
 908	struct unwind_state state;
 909	unsigned long *fptr;
 910	unsigned long addr;
 911
 912	unw_debug("\n\nUNWIND FRAME:\n");
 913	unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
 914		  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
 915		  UNW_FP(frame));
 916
 917	if (UNW_PC(frame) == 0)
 918		return -EINVAL;
 919
 920#ifdef UNWIND_DEBUG
 921	{
 922		unsigned long *sptr = (unsigned long *)UNW_SP(frame);
 923		unw_debug("\nStack Dump:\n");
 924		for (i = 0; i < 20; i++, sptr++)
 925			unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
 926		unw_debug("\n");
 927	}
 928#endif
 929
 930	table = find_table(pc);
 931	if (table != NULL
 932	    && !(table->size & (sizeof(*fde) - 1))) {
 933		const u8 *hdr = table->header;
 934		unsigned long tableSize;
 935
 936		smp_rmb();
 937		if (hdr && hdr[0] == 1) {
 938			switch (hdr[3] & DW_EH_PE_FORM) {
 939			case DW_EH_PE_native:
 940				tableSize = sizeof(unsigned long);
 941				break;
 942			case DW_EH_PE_data2:
 943				tableSize = 2;
 944				break;
 945			case DW_EH_PE_data4:
 946				tableSize = 4;
 947				break;
 948			case DW_EH_PE_data8:
 949				tableSize = 8;
 950				break;
 951			default:
 952				tableSize = 0;
 953				break;
 954			}
 955			ptr = hdr + 4;
 956			end = hdr + table->hdrsz;
 957			if (tableSize && read_pointer(&ptr, end, hdr[1])
 958			    == (unsigned long)table->address
 959			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
 960			    && i == (end - ptr) / (2 * tableSize)
 961			    && !((end - ptr) % (2 * tableSize))) {
 962				do {
 963					const u8 *cur =
 964					    ptr + (i / 2) * (2 * tableSize);
 965
 966					startLoc = read_pointer(&cur,
 967								cur + tableSize,
 968								hdr[3]);
 969					if (pc < startLoc)
 970						i /= 2;
 971					else {
 972						ptr = cur - tableSize;
 973						i = (i + 1) / 2;
 974					}
 975				} while (startLoc && i > 1);
 976				if (i == 1
 977				    && (startLoc = read_pointer(&ptr,
 978								ptr + tableSize,
 979								hdr[3])) != 0
 980				    && pc >= startLoc)
 981					fde = (void *)read_pointer(&ptr,
 982								   ptr +
 983								   tableSize,
 984								   hdr[3]);
 985			}
 986		}
 987
 988		if (fde != NULL) {
 989			cie = cie_for_fde(fde, table);
 990			ptr = (const u8 *)(fde + 2);
 991			if (cie != NULL
 992			    && cie != &bad_cie
 993			    && cie != &not_fde
 994			    && (ptrType = fde_pointer_type(cie)) >= 0
 995			    && read_pointer(&ptr,
 996					    (const u8 *)(fde + 1) + *fde,
 997					    ptrType) == startLoc) {
 998				if (!(ptrType & DW_EH_PE_indirect))
 999					ptrType &=
1000					    DW_EH_PE_FORM | DW_EH_PE_signed;
1001				endLoc =
1002				    startLoc + read_pointer(&ptr,
1003							    (const u8 *)(fde +
1004									 1) +
1005							    *fde, ptrType);
1006				if (pc >= endLoc) {
1007					fde = NULL;
1008					cie = NULL;
1009				}
1010			} else {
1011				fde = NULL;
1012				cie = NULL;
1013			}
1014		}
1015	}
1016	if (cie != NULL) {
1017		memset(&state, 0, sizeof(state));
1018		state.cieEnd = ptr;	/* keep here temporarily */
1019		ptr = (const u8 *)(cie + 2);
1020		end = (const u8 *)(cie + 1) + *cie;
1021		frame->call_frame = 1;
1022		if (*++ptr) {
1023			/* check if augmentation size is first (thus present) */
1024			if (*ptr == 'z') {
1025				while (++ptr < end && *ptr) {
1026					switch (*ptr) {
1027					/* chk for ignorable or already handled
1028					 * nul-terminated augmentation string */
1029					case 'L':
1030					case 'P':
1031					case 'R':
1032						continue;
1033					case 'S':
1034						frame->call_frame = 0;
1035						continue;
1036					default:
1037						break;
1038					}
1039					break;
1040				}
1041			}
1042			if (ptr >= end || *ptr)
1043				cie = NULL;
1044		}
1045		++ptr;
1046	}
1047	if (cie != NULL) {
1048		/* get code alignment factor */
1049		state.codeAlign = get_uleb128(&ptr, end);
1050		/* get data alignment factor */
1051		state.dataAlign = get_sleb128(&ptr, end);
1052		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1053			cie = NULL;
1054		else {
1055			retAddrReg =
1056			    state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1057								      end);
1058			unw_debug("CIE Frame Info:\n");
1059			unw_debug("return Address register 0x%lx\n",
1060				  retAddrReg);
1061			unw_debug("data Align: %ld\n", state.dataAlign);
1062			unw_debug("code Align: %lu\n", state.codeAlign);
1063			/* skip augmentation */
1064			if (((const char *)(cie + 2))[1] == 'z') {
1065				uleb128_t augSize = get_uleb128(&ptr, end);
1066
1067				ptr += augSize;
1068			}
1069			if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1070			    || REG_INVALID(retAddrReg)
1071			    || reg_info[retAddrReg].width !=
1072			    sizeof(unsigned long))
1073				cie = NULL;
1074		}
1075	}
1076	if (cie != NULL) {
1077		state.cieStart = ptr;
1078		ptr = state.cieEnd;
1079		state.cieEnd = end;
1080		end = (const u8 *)(fde + 1) + *fde;
1081		/* skip augmentation */
1082		if (((const char *)(cie + 2))[1] == 'z') {
1083			uleb128_t augSize = get_uleb128(&ptr, end);
1084
1085			if ((ptr += augSize) > end)
1086				fde = NULL;
1087		}
1088	}
1089	if (cie == NULL || fde == NULL) {
1090#ifdef CONFIG_FRAME_POINTER
1091		unsigned long top, bottom;
1092
1093		top = STACK_TOP_UNW(frame->task);
1094		bottom = STACK_BOTTOM_UNW(frame->task);
1095#if FRAME_RETADDR_OFFSET < 0
1096		if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1097		    && bottom < UNW_FP(frame)
1098#else
1099		if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1100		    && bottom > UNW_FP(frame)
1101#endif
1102		    && !((UNW_SP(frame) | UNW_FP(frame))
1103			 & (sizeof(unsigned long) - 1))) {
1104			unsigned long link;
1105
1106			if (!__get_user(link, (unsigned long *)
1107					(UNW_FP(frame) + FRAME_LINK_OFFSET))
1108#if FRAME_RETADDR_OFFSET < 0
1109			    && link > bottom && link < UNW_FP(frame)
1110#else
1111			    && link > UNW_FP(frame) && link < bottom
1112#endif
1113			    && !(link & (sizeof(link) - 1))
1114			    && !__get_user(UNW_PC(frame),
1115					   (unsigned long *)(UNW_FP(frame)
1116						+ FRAME_RETADDR_OFFSET)))
1117			{
1118				UNW_SP(frame) =
1119				    UNW_FP(frame) + FRAME_RETADDR_OFFSET
1120#if FRAME_RETADDR_OFFSET < 0
1121				    -
1122#else
1123				    +
1124#endif
1125				    sizeof(UNW_PC(frame));
1126				UNW_FP(frame) = link;
1127				return 0;
1128			}
1129		}
1130#endif
1131		return -ENXIO;
1132	}
1133	state.org = startLoc;
1134	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1135
1136	unw_debug("\nProcess instructions\n");
1137
1138	/* process instructions
1139	 * For ARC, we optimize by having blink(retAddrReg) with
1140	 * the sameValue in the leaf function, so we should not check
1141	 * state.regs[retAddrReg].where == Nowhere
1142	 */
1143	if (!processCFI(ptr, end, pc, ptrType, &state)
1144	    || state.loc > endLoc
1145/*	   || state.regs[retAddrReg].where == Nowhere */
1146	    || state.cfa.reg >= ARRAY_SIZE(reg_info)
1147	    || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1148	    || state.cfa.offs % sizeof(unsigned long))
1149		return -EIO;
1150
1151#ifdef UNWIND_DEBUG
1152	unw_debug("\n");
1153
1154	unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1155	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1156
1157		if (REG_INVALID(i))
1158			continue;
1159
1160		switch (state.regs[i].where) {
1161		case Nowhere:
1162			break;
1163		case Memory:
1164			unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1165			break;
1166		case Register:
1167			unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1168			break;
1169		case Value:
1170			unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1171			break;
1172		}
1173	}
1174
1175	unw_debug("\n");
1176#endif
1177
1178	/* update frame */
1179	if (frame->call_frame
1180	    && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1181		frame->call_frame = 0;
1182	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1183	startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1184	endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1185	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1186		startLoc = min(STACK_LIMIT(cfa), cfa);
1187		endLoc = max(STACK_LIMIT(cfa), cfa);
1188	}
1189
1190	unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
1191		  state.cfa.reg, state.cfa.offs, cfa);
1192
1193	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1194		if (REG_INVALID(i)) {
1195			if (state.regs[i].where == Nowhere)
1196				continue;
1197			return -EIO;
1198		}
1199		switch (state.regs[i].where) {
1200		default:
1201			break;
1202		case Register:
1203			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1204			    || REG_INVALID(state.regs[i].value)
1205			    || reg_info[i].width >
1206			    reg_info[state.regs[i].value].width)
1207				return -EIO;
1208			switch (reg_info[state.regs[i].value].width) {
1209			case sizeof(u8):
1210				state.regs[i].value =
1211				FRAME_REG(state.regs[i].value, const u8);
1212				break;
1213			case sizeof(u16):
1214				state.regs[i].value =
1215				FRAME_REG(state.regs[i].value, const u16);
1216				break;
1217			case sizeof(u32):
1218				state.regs[i].value =
1219				FRAME_REG(state.regs[i].value, const u32);
1220				break;
1221#ifdef CONFIG_64BIT
1222			case sizeof(u64):
1223				state.regs[i].value =
1224				FRAME_REG(state.regs[i].value, const u64);
1225				break;
1226#endif
1227			default:
1228				return -EIO;
1229			}
1230			break;
1231		}
1232	}
1233
1234	unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1235	fptr = (unsigned long *)(&frame->regs);
1236	for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1237
1238		if (REG_INVALID(i))
1239			continue;
1240		switch (state.regs[i].where) {
1241		case Nowhere:
1242			if (reg_info[i].width != sizeof(UNW_SP(frame))
1243			    || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1244			    != &UNW_SP(frame))
1245				continue;
1246			UNW_SP(frame) = cfa;
1247			break;
1248		case Register:
1249			switch (reg_info[i].width) {
1250			case sizeof(u8):
1251				FRAME_REG(i, u8) = state.regs[i].value;
1252				break;
1253			case sizeof(u16):
1254				FRAME_REG(i, u16) = state.regs[i].value;
1255				break;
1256			case sizeof(u32):
1257				FRAME_REG(i, u32) = state.regs[i].value;
1258				break;
1259#ifdef CONFIG_64BIT
1260			case sizeof(u64):
1261				FRAME_REG(i, u64) = state.regs[i].value;
1262				break;
1263#endif
1264			default:
1265				return -EIO;
1266			}
1267			break;
1268		case Value:
1269			if (reg_info[i].width != sizeof(unsigned long))
1270				return -EIO;
1271			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1272			    * state.dataAlign;
1273			break;
1274		case Memory:
1275			addr = cfa + state.regs[i].value * state.dataAlign;
1276
1277			if ((state.regs[i].value * state.dataAlign)
1278			    % sizeof(unsigned long)
1279			    || addr < startLoc
1280			    || addr + sizeof(unsigned long) < addr
1281			    || addr + sizeof(unsigned long) > endLoc)
1282					return -EIO;
1283
1284			switch (reg_info[i].width) {
1285			case sizeof(u8):
1286				__get_user(FRAME_REG(i, u8),
1287					   (u8 __user *)addr);
1288				break;
1289			case sizeof(u16):
1290				__get_user(FRAME_REG(i, u16),
1291					   (u16 __user *)addr);
1292				break;
1293			case sizeof(u32):
1294				__get_user(FRAME_REG(i, u32),
1295					   (u32 __user *)addr);
1296				break;
1297#ifdef CONFIG_64BIT
1298			case sizeof(u64):
1299				__get_user(FRAME_REG(i, u64),
1300					   (u64 __user *)addr);
1301				break;
1302#endif
1303			default:
1304				return -EIO;
1305			}
1306
1307			break;
1308		}
1309		unw_debug("r%d: 0x%lx ", i, *fptr);
1310	}
1311
1312	return 0;
1313#undef FRAME_REG
1314}
1315EXPORT_SYMBOL(arc_unwind);
v5.14.15
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   4 * Copyright (C) 2002-2006 Novell, Inc.
   5 *	Jan Beulich <jbeulich@novell.com>
   6 *
   7 * A simple API for unwinding kernel stacks.  This is used for
   8 * debugging and error reporting purposes.  The kernel doesn't need
   9 * full-blown stack unwinding with all the bells and whistles, so there
  10 * is not much point in implementing the full Dwarf2 unwind API.
  11 */
  12
  13#include <linux/sched.h>
  14#include <linux/module.h>
  15#include <linux/memblock.h>
  16#include <linux/sort.h>
  17#include <linux/slab.h>
  18#include <linux/stop_machine.h>
  19#include <linux/uaccess.h>
  20#include <linux/ptrace.h>
  21#include <asm/sections.h>
  22#include <asm/unaligned.h>
  23#include <asm/unwind.h>
  24
  25extern char __start_unwind[], __end_unwind[];
  26/* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
  27
  28/* #define UNWIND_DEBUG */
  29
  30#ifdef UNWIND_DEBUG
  31int dbg_unw;
  32#define unw_debug(fmt, ...)			\
  33do {						\
  34	if (dbg_unw)				\
  35		pr_info(fmt, ##__VA_ARGS__);	\
  36} while (0);
  37#else
  38#define unw_debug(fmt, ...)
  39#endif
  40
  41#define MAX_STACK_DEPTH 8
  42
  43#define EXTRA_INFO(f) { \
  44		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
  45				% sizeof_field(struct unwind_frame_info, f)) \
  46				+ offsetof(struct unwind_frame_info, f) \
  47				/ sizeof_field(struct unwind_frame_info, f), \
  48				sizeof_field(struct unwind_frame_info, f) \
  49	}
  50#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
  51
  52static const struct {
  53	unsigned offs:BITS_PER_LONG / 2;
  54	unsigned width:BITS_PER_LONG / 2;
  55} reg_info[] = {
  56UNW_REGISTER_INFO};
  57
  58#undef PTREGS_INFO
  59#undef EXTRA_INFO
  60
  61#ifndef REG_INVALID
  62#define REG_INVALID(r) (reg_info[r].width == 0)
  63#endif
  64
  65#define DW_CFA_nop                          0x00
  66#define DW_CFA_set_loc                      0x01
  67#define DW_CFA_advance_loc1                 0x02
  68#define DW_CFA_advance_loc2                 0x03
  69#define DW_CFA_advance_loc4                 0x04
  70#define DW_CFA_offset_extended              0x05
  71#define DW_CFA_restore_extended             0x06
  72#define DW_CFA_undefined                    0x07
  73#define DW_CFA_same_value                   0x08
  74#define DW_CFA_register                     0x09
  75#define DW_CFA_remember_state               0x0a
  76#define DW_CFA_restore_state                0x0b
  77#define DW_CFA_def_cfa                      0x0c
  78#define DW_CFA_def_cfa_register             0x0d
  79#define DW_CFA_def_cfa_offset               0x0e
  80#define DW_CFA_def_cfa_expression           0x0f
  81#define DW_CFA_expression                   0x10
  82#define DW_CFA_offset_extended_sf           0x11
  83#define DW_CFA_def_cfa_sf                   0x12
  84#define DW_CFA_def_cfa_offset_sf            0x13
  85#define DW_CFA_val_offset                   0x14
  86#define DW_CFA_val_offset_sf                0x15
  87#define DW_CFA_val_expression               0x16
  88#define DW_CFA_lo_user                      0x1c
  89#define DW_CFA_GNU_window_save              0x2d
  90#define DW_CFA_GNU_args_size                0x2e
  91#define DW_CFA_GNU_negative_offset_extended 0x2f
  92#define DW_CFA_hi_user                      0x3f
  93
  94#define DW_EH_PE_FORM     0x07
  95#define DW_EH_PE_native   0x00
  96#define DW_EH_PE_leb128   0x01
  97#define DW_EH_PE_data2    0x02
  98#define DW_EH_PE_data4    0x03
  99#define DW_EH_PE_data8    0x04
 100#define DW_EH_PE_signed   0x08
 101#define DW_EH_PE_ADJUST   0x70
 102#define DW_EH_PE_abs      0x00
 103#define DW_EH_PE_pcrel    0x10
 104#define DW_EH_PE_textrel  0x20
 105#define DW_EH_PE_datarel  0x30
 106#define DW_EH_PE_funcrel  0x40
 107#define DW_EH_PE_aligned  0x50
 108#define DW_EH_PE_indirect 0x80
 109#define DW_EH_PE_omit     0xff
 110
 111#define CIE_ID	0
 112
 113typedef unsigned long uleb128_t;
 114typedef signed long sleb128_t;
 115
 116static struct unwind_table {
 117	struct {
 118		unsigned long pc;
 119		unsigned long range;
 120	} core, init;
 121	const void *address;
 122	unsigned long size;
 123	const unsigned char *header;
 124	unsigned long hdrsz;
 125	struct unwind_table *link;
 126	const char *name;
 127} root_table;
 128
 129struct unwind_item {
 130	enum item_location {
 131		Nowhere,
 132		Memory,
 133		Register,
 134		Value
 135	} where;
 136	uleb128_t value;
 137};
 138
 139struct unwind_state {
 140	uleb128_t loc, org;
 141	const u8 *cieStart, *cieEnd;
 142	uleb128_t codeAlign;
 143	sleb128_t dataAlign;
 144	struct cfa {
 145		uleb128_t reg, offs;
 146	} cfa;
 147	struct unwind_item regs[ARRAY_SIZE(reg_info)];
 148	unsigned stackDepth:8;
 149	unsigned version:8;
 150	const u8 *label;
 151	const u8 *stack[MAX_STACK_DEPTH];
 152};
 153
 154static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
 155
 156static struct unwind_table *find_table(unsigned long pc)
 157{
 158	struct unwind_table *table;
 159
 160	for (table = &root_table; table; table = table->link)
 161		if ((pc >= table->core.pc
 162		     && pc < table->core.pc + table->core.range)
 163		    || (pc >= table->init.pc
 164			&& pc < table->init.pc + table->init.range))
 165			break;
 166
 167	return table;
 168}
 169
 170static unsigned long read_pointer(const u8 **pLoc,
 171				  const void *end, signed ptrType);
 172static void init_unwind_hdr(struct unwind_table *table,
 173			    void *(*alloc) (unsigned long));
 174
 175/*
 176 * wrappers for header alloc (vs. calling one vs. other at call site)
 177 * to elide section mismatches warnings
 178 */
 179static void *__init unw_hdr_alloc_early(unsigned long sz)
 180{
 181	return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
 182}
 183
 184static void init_unwind_table(struct unwind_table *table, const char *name,
 185			      const void *core_start, unsigned long core_size,
 186			      const void *init_start, unsigned long init_size,
 187			      const void *table_start, unsigned long table_size,
 188			      const u8 *header_start, unsigned long header_size)
 189{
 190	table->core.pc = (unsigned long)core_start;
 191	table->core.range = core_size;
 192	table->init.pc = (unsigned long)init_start;
 193	table->init.range = init_size;
 194	table->address = table_start;
 195	table->size = table_size;
 196	/* To avoid the pointer addition with NULL pointer.*/
 197	if (header_start != NULL) {
 198		const u8 *ptr = header_start + 4;
 199		const u8 *end = header_start + header_size;
 200		/* See if the linker provided table looks valid. */
 201		if (header_size <= 4
 202		|| header_start[0] != 1
 203		|| (void *)read_pointer(&ptr, end, header_start[1])
 204				!= table_start
 205		|| header_start[2] == DW_EH_PE_omit
 206		|| read_pointer(&ptr, end, header_start[2]) <= 0
 207		|| header_start[3] == DW_EH_PE_omit)
 208			header_start = NULL;
 209	}
 210	table->hdrsz = header_size;
 211	smp_wmb();
 212	table->header = header_start;
 213	table->link = NULL;
 214	table->name = name;
 215}
 216
 217void __init arc_unwind_init(void)
 218{
 219	init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
 220			  __start_unwind, __end_unwind - __start_unwind,
 221			  NULL, 0);
 222	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
 223
 224	init_unwind_hdr(&root_table, unw_hdr_alloc_early);
 225}
 226
 227static const u32 bad_cie, not_fde;
 228static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
 229static const u32 *__cie_for_fde(const u32 *fde);
 230static signed fde_pointer_type(const u32 *cie);
 231
 232struct eh_frame_hdr_table_entry {
 233	unsigned long start, fde;
 234};
 235
 236static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
 237{
 238	const struct eh_frame_hdr_table_entry *e1 = p1;
 239	const struct eh_frame_hdr_table_entry *e2 = p2;
 240
 241	return (e1->start > e2->start) - (e1->start < e2->start);
 242}
 243
 244static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
 245{
 246	struct eh_frame_hdr_table_entry *e1 = p1;
 247	struct eh_frame_hdr_table_entry *e2 = p2;
 248	unsigned long v;
 249
 250	v = e1->start;
 251	e1->start = e2->start;
 252	e2->start = v;
 253	v = e1->fde;
 254	e1->fde = e2->fde;
 255	e2->fde = v;
 256}
 257
 258static void init_unwind_hdr(struct unwind_table *table,
 259			    void *(*alloc) (unsigned long))
 260{
 261	const u8 *ptr;
 262	unsigned long tableSize = table->size, hdrSize;
 263	unsigned int n;
 264	const u32 *fde;
 265	struct {
 266		u8 version;
 267		u8 eh_frame_ptr_enc;
 268		u8 fde_count_enc;
 269		u8 table_enc;
 270		unsigned long eh_frame_ptr;
 271		unsigned int fde_count;
 272		struct eh_frame_hdr_table_entry table[];
 273	} __attribute__ ((__packed__)) *header;
 274
 275	if (table->header)
 276		return;
 277
 278	if (table->hdrsz)
 279		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
 280			table->name);
 281
 282	if (tableSize & (sizeof(*fde) - 1))
 283		return;
 284
 285	for (fde = table->address, n = 0;
 286	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
 287	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 288		const u32 *cie = cie_for_fde(fde, table);
 289		signed ptrType;
 290
 291		if (cie == &not_fde)
 292			continue;
 293		if (cie == NULL || cie == &bad_cie)
 294			goto ret_err;
 295		ptrType = fde_pointer_type(cie);
 296		if (ptrType < 0)
 297			goto ret_err;
 298
 299		ptr = (const u8 *)(fde + 2);
 300		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
 301								ptrType)) {
 302			/* FIXME_Rajesh We have 4 instances of null addresses
 303			 * instead of the initial loc addr
 304			 * return;
 305			 */
 306			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
 307				(const u8 *)(fde + 1) + *fde);
 308		}
 309		++n;
 310	}
 311
 312	if (tableSize || !n)
 313		goto ret_err;
 314
 315	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
 316	    + 2 * n * sizeof(unsigned long);
 317
 318	header = alloc(hdrSize);
 319	if (!header)
 320		goto ret_err;
 321
 322	header->version = 1;
 323	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
 324	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
 325	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
 326	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
 327	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
 328		     % __alignof(typeof(header->fde_count)));
 329	header->fde_count = n;
 330
 331	BUILD_BUG_ON(offsetof(typeof(*header), table)
 332		     % __alignof(typeof(*header->table)));
 333	for (fde = table->address, tableSize = table->size, n = 0;
 334	     tableSize;
 335	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 336		const u32 *cie = __cie_for_fde(fde);
 337
 338		if (fde[1] == CIE_ID)
 339			continue;	/* this is a CIE */
 340		ptr = (const u8 *)(fde + 2);
 341		header->table[n].start = read_pointer(&ptr,
 342						      (const u8 *)(fde + 1) +
 343						      *fde,
 344						      fde_pointer_type(cie));
 345		header->table[n].fde = (unsigned long)fde;
 346		++n;
 347	}
 348	WARN_ON(n != header->fde_count);
 349
 350	sort(header->table,
 351	     n,
 352	     sizeof(*header->table),
 353	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
 354
 355	table->hdrsz = hdrSize;
 356	smp_wmb();
 357	table->header = (const void *)header;
 358	return;
 359
 360ret_err:
 361	panic("Attention !!! Dwarf FDE parsing errors\n");
 362}
 363
 364#ifdef CONFIG_MODULES
 365static void *unw_hdr_alloc(unsigned long sz)
 366{
 367	return kmalloc(sz, GFP_KERNEL);
 368}
 369
 370static struct unwind_table *last_table;
 371
 372/* Must be called with module_mutex held. */
 373void *unwind_add_table(struct module *module, const void *table_start,
 374		       unsigned long table_size)
 375{
 376	struct unwind_table *table;
 
 
 377
 378	if (table_size <= 0)
 379		return NULL;
 380
 381	table = kmalloc(sizeof(*table), GFP_KERNEL);
 382	if (!table)
 383		return NULL;
 384
 385	init_unwind_table(table, module->name,
 386			  module->core_layout.base, module->core_layout.size,
 387			  module->init_layout.base, module->init_layout.size,
 388			  table_start, table_size,
 389			  NULL, 0);
 390
 391	init_unwind_hdr(table, unw_hdr_alloc);
 392
 393#ifdef UNWIND_DEBUG
 394	unw_debug("Table added for [%s] %lx %lx\n",
 395		module->name, table->core.pc, table->core.range);
 396#endif
 397	if (last_table)
 398		last_table->link = table;
 399	else
 400		root_table.link = table;
 401	last_table = table;
 402
 403	return table;
 404}
 405
 406struct unlink_table_info {
 407	struct unwind_table *table;
 408	int init_only;
 409};
 410
 411static int unlink_table(void *arg)
 412{
 413	struct unlink_table_info *info = arg;
 414	struct unwind_table *table = info->table, *prev;
 415
 416	for (prev = &root_table; prev->link && prev->link != table;
 417	     prev = prev->link)
 418		;
 419
 420	if (prev->link) {
 421		if (info->init_only) {
 422			table->init.pc = 0;
 423			table->init.range = 0;
 424			info->table = NULL;
 425		} else {
 426			prev->link = table->link;
 427			if (!prev->link)
 428				last_table = prev;
 429		}
 430	} else
 431		info->table = NULL;
 432
 433	return 0;
 434}
 435
 436/* Must be called with module_mutex held. */
 437void unwind_remove_table(void *handle, int init_only)
 438{
 439	struct unwind_table *table = handle;
 440	struct unlink_table_info info;
 441
 442	if (!table || table == &root_table)
 443		return;
 444
 445	if (init_only && table == last_table) {
 446		table->init.pc = 0;
 447		table->init.range = 0;
 448		return;
 449	}
 450
 451	info.table = table;
 452	info.init_only = init_only;
 453
 454	unlink_table(&info); /* XXX: SMP */
 455	kfree(table->header);
 456	kfree(table);
 457}
 458
 459#endif /* CONFIG_MODULES */
 460
 461static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
 462{
 463	const u8 *cur = *pcur;
 464	uleb128_t value;
 465	unsigned int shift;
 466
 467	for (shift = 0, value = 0; cur < end; shift += 7) {
 468		if (shift + 7 > 8 * sizeof(value)
 469		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 470			cur = end + 1;
 471			break;
 472		}
 473		value |= (uleb128_t) (*cur & 0x7f) << shift;
 474		if (!(*cur++ & 0x80))
 475			break;
 476	}
 477	*pcur = cur;
 478
 479	return value;
 480}
 481
 482static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
 483{
 484	const u8 *cur = *pcur;
 485	sleb128_t value;
 486	unsigned int shift;
 487
 488	for (shift = 0, value = 0; cur < end; shift += 7) {
 489		if (shift + 7 > 8 * sizeof(value)
 490		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 491			cur = end + 1;
 492			break;
 493		}
 494		value |= (sleb128_t) (*cur & 0x7f) << shift;
 495		if (!(*cur & 0x80)) {
 496			value |= -(*cur++ & 0x40) << shift;
 497			break;
 498		}
 499	}
 500	*pcur = cur;
 501
 502	return value;
 503}
 504
 505static const u32 *__cie_for_fde(const u32 *fde)
 506{
 507	const u32 *cie;
 508
 509	cie = fde + 1 - fde[1] / sizeof(*fde);
 510
 511	return cie;
 512}
 513
 514static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
 515{
 516	const u32 *cie;
 517
 518	if (!*fde || (*fde & (sizeof(*fde) - 1)))
 519		return &bad_cie;
 520
 521	if (fde[1] == CIE_ID)
 522		return &not_fde;	/* this is a CIE */
 523
 524	if ((fde[1] & (sizeof(*fde) - 1)))
 525/* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
 526		return NULL;	/* this is not a valid FDE */
 527
 528	cie = __cie_for_fde(fde);
 529
 530	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
 531	    || (*cie & (sizeof(*cie) - 1))
 532	    || (cie[1] != CIE_ID))
 533		return NULL;	/* this is not a (valid) CIE */
 534	return cie;
 535}
 536
 537static unsigned long read_pointer(const u8 **pLoc, const void *end,
 538				  signed ptrType)
 539{
 540	unsigned long value = 0;
 541	union {
 542		const u8 *p8;
 543		const u16 *p16u;
 544		const s16 *p16s;
 545		const u32 *p32u;
 546		const s32 *p32s;
 547		const unsigned long *pul;
 548	} ptr;
 549
 550	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
 551		return 0;
 552	ptr.p8 = *pLoc;
 553	switch (ptrType & DW_EH_PE_FORM) {
 554	case DW_EH_PE_data2:
 555		if (end < (const void *)(ptr.p16u + 1))
 556			return 0;
 557		if (ptrType & DW_EH_PE_signed)
 558			value = get_unaligned((u16 *) ptr.p16s++);
 559		else
 560			value = get_unaligned((u16 *) ptr.p16u++);
 561		break;
 562	case DW_EH_PE_data4:
 563#ifdef CONFIG_64BIT
 564		if (end < (const void *)(ptr.p32u + 1))
 565			return 0;
 566		if (ptrType & DW_EH_PE_signed)
 567			value = get_unaligned(ptr.p32s++);
 568		else
 569			value = get_unaligned(ptr.p32u++);
 570		break;
 571	case DW_EH_PE_data8:
 572		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
 573#else
 574		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
 575#endif
 576		fallthrough;
 577	case DW_EH_PE_native:
 578		if (end < (const void *)(ptr.pul + 1))
 579			return 0;
 580		value = get_unaligned((unsigned long *)ptr.pul++);
 581		break;
 582	case DW_EH_PE_leb128:
 583		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
 584		value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
 585		    : get_uleb128(&ptr.p8, end);
 586		if ((const void *)ptr.p8 > end)
 587			return 0;
 588		break;
 589	default:
 590		return 0;
 591	}
 592	switch (ptrType & DW_EH_PE_ADJUST) {
 593	case DW_EH_PE_abs:
 594		break;
 595	case DW_EH_PE_pcrel:
 596		value += (unsigned long)*pLoc;
 597		break;
 598	default:
 599		return 0;
 600	}
 601	if ((ptrType & DW_EH_PE_indirect)
 602	    && __get_user(value, (unsigned long __user *)value))
 603		return 0;
 604	*pLoc = ptr.p8;
 605
 606	return value;
 607}
 608
 609static signed fde_pointer_type(const u32 *cie)
 610{
 611	const u8 *ptr = (const u8 *)(cie + 2);
 612	unsigned int version = *ptr;
 613
 614	if (*++ptr) {
 615		const char *aug;
 616		const u8 *end = (const u8 *)(cie + 1) + *cie;
 617		uleb128_t len;
 618
 619		/* check if augmentation size is first (and thus present) */
 620		if (*ptr != 'z')
 621			return -1;
 622
 623		/* check if augmentation string is nul-terminated */
 624		aug = (const void *)ptr;
 625		ptr = memchr(aug, 0, end - ptr);
 626		if (ptr == NULL)
 627			return -1;
 628
 629		++ptr;		/* skip terminator */
 630		get_uleb128(&ptr, end);	/* skip code alignment */
 631		get_sleb128(&ptr, end);	/* skip data alignment */
 632		/* skip return address column */
 633		version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
 634		len = get_uleb128(&ptr, end);	/* augmentation length */
 635
 636		if (ptr + len < ptr || ptr + len > end)
 637			return -1;
 638
 639		end = ptr + len;
 640		while (*++aug) {
 641			if (ptr >= end)
 642				return -1;
 643			switch (*aug) {
 644			case 'L':
 645				++ptr;
 646				break;
 647			case 'P':{
 648					signed ptrType = *ptr++;
 649
 650					if (!read_pointer(&ptr, end, ptrType)
 651					    || ptr > end)
 652						return -1;
 653				}
 654				break;
 655			case 'R':
 656				return *ptr;
 657			default:
 658				return -1;
 659			}
 660		}
 661	}
 662	return DW_EH_PE_native | DW_EH_PE_abs;
 663}
 664
 665static int advance_loc(unsigned long delta, struct unwind_state *state)
 666{
 667	state->loc += delta * state->codeAlign;
 668
 669	/* FIXME_Rajesh: Probably we are defining for the initial range as well;
 670	   return delta > 0;
 671	 */
 672	unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
 673	return 1;
 674}
 675
 676static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
 677		     struct unwind_state *state)
 678{
 679	if (reg < ARRAY_SIZE(state->regs)) {
 680		state->regs[reg].where = where;
 681		state->regs[reg].value = value;
 682
 683#ifdef UNWIND_DEBUG
 684		unw_debug("r%lu: ", reg);
 685		switch (where) {
 686		case Nowhere:
 687			unw_debug("s ");
 688			break;
 689		case Memory:
 690			unw_debug("c(%lu) ", value);
 691			break;
 692		case Register:
 693			unw_debug("r(%lu) ", value);
 694			break;
 695		case Value:
 696			unw_debug("v(%lu) ", value);
 697			break;
 698		default:
 699			break;
 700		}
 701#endif
 702	}
 703}
 704
 705static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
 706		      signed ptrType, struct unwind_state *state)
 707{
 708	union {
 709		const u8 *p8;
 710		const u16 *p16;
 711		const u32 *p32;
 712	} ptr;
 713	int result = 1;
 714	u8 opcode;
 715
 716	if (start != state->cieStart) {
 717		state->loc = state->org;
 718		result =
 719		    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
 720			       state);
 721		if (targetLoc == 0 && state->label == NULL)
 722			return result;
 723	}
 724	for (ptr.p8 = start; result && ptr.p8 < end;) {
 725		switch (*ptr.p8 >> 6) {
 726			uleb128_t value;
 727
 728		case 0:
 729			opcode = *ptr.p8++;
 730
 731			switch (opcode) {
 732			case DW_CFA_nop:
 733				unw_debug("cfa nop ");
 734				break;
 735			case DW_CFA_set_loc:
 736				state->loc = read_pointer(&ptr.p8, end,
 737							  ptrType);
 738				if (state->loc == 0)
 739					result = 0;
 740				unw_debug("cfa_set_loc: 0x%lx ", state->loc);
 741				break;
 742			case DW_CFA_advance_loc1:
 743				unw_debug("\ncfa advance loc1:");
 744				result = ptr.p8 < end
 745				    && advance_loc(*ptr.p8++, state);
 746				break;
 747			case DW_CFA_advance_loc2:
 748				value = *ptr.p8++;
 749				value += *ptr.p8++ << 8;
 750				unw_debug("\ncfa advance loc2:");
 751				result = ptr.p8 <= end + 2
 752				    /* && advance_loc(*ptr.p16++, state); */
 753				    && advance_loc(value, state);
 754				break;
 755			case DW_CFA_advance_loc4:
 756				unw_debug("\ncfa advance loc4:");
 757				result = ptr.p8 <= end + 4
 758				    && advance_loc(*ptr.p32++, state);
 759				break;
 760			case DW_CFA_offset_extended:
 761				value = get_uleb128(&ptr.p8, end);
 762				unw_debug("cfa_offset_extended: ");
 763				set_rule(value, Memory,
 764					 get_uleb128(&ptr.p8, end), state);
 765				break;
 766			case DW_CFA_val_offset:
 767				value = get_uleb128(&ptr.p8, end);
 768				set_rule(value, Value,
 769					 get_uleb128(&ptr.p8, end), state);
 770				break;
 771			case DW_CFA_offset_extended_sf:
 772				value = get_uleb128(&ptr.p8, end);
 773				set_rule(value, Memory,
 774					 get_sleb128(&ptr.p8, end), state);
 775				break;
 776			case DW_CFA_val_offset_sf:
 777				value = get_uleb128(&ptr.p8, end);
 778				set_rule(value, Value,
 779					 get_sleb128(&ptr.p8, end), state);
 780				break;
 781			case DW_CFA_restore_extended:
 782				unw_debug("cfa_restore_extended: ");
 783			case DW_CFA_undefined:
 784				unw_debug("cfa_undefined: ");
 785			case DW_CFA_same_value:
 786				unw_debug("cfa_same_value: ");
 787				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
 788					 state);
 789				break;
 790			case DW_CFA_register:
 791				unw_debug("cfa_register: ");
 792				value = get_uleb128(&ptr.p8, end);
 793				set_rule(value,
 794					 Register,
 795					 get_uleb128(&ptr.p8, end), state);
 796				break;
 797			case DW_CFA_remember_state:
 798				unw_debug("cfa_remember_state: ");
 799				if (ptr.p8 == state->label) {
 800					state->label = NULL;
 801					return 1;
 802				}
 803				if (state->stackDepth >= MAX_STACK_DEPTH)
 804					return 0;
 805				state->stack[state->stackDepth++] = ptr.p8;
 806				break;
 807			case DW_CFA_restore_state:
 808				unw_debug("cfa_restore_state: ");
 809				if (state->stackDepth) {
 810					const uleb128_t loc = state->loc;
 811					const u8 *label = state->label;
 812
 813					state->label =
 814					    state->stack[state->stackDepth - 1];
 815					memcpy(&state->cfa, &badCFA,
 816					       sizeof(state->cfa));
 817					memset(state->regs, 0,
 818					       sizeof(state->regs));
 819					state->stackDepth = 0;
 820					result =
 821					    processCFI(start, end, 0, ptrType,
 822						       state);
 823					state->loc = loc;
 824					state->label = label;
 825				} else
 826					return 0;
 827				break;
 828			case DW_CFA_def_cfa:
 829				state->cfa.reg = get_uleb128(&ptr.p8, end);
 830				unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
 831				fallthrough;
 832			case DW_CFA_def_cfa_offset:
 833				state->cfa.offs = get_uleb128(&ptr.p8, end);
 834				unw_debug("cfa_def_cfa_offset: 0x%lx ",
 835					  state->cfa.offs);
 836				break;
 837			case DW_CFA_def_cfa_sf:
 838				state->cfa.reg = get_uleb128(&ptr.p8, end);
 839				fallthrough;
 840			case DW_CFA_def_cfa_offset_sf:
 841				state->cfa.offs = get_sleb128(&ptr.p8, end)
 842				    * state->dataAlign;
 843				break;
 844			case DW_CFA_def_cfa_register:
 845				unw_debug("cfa_def_cfa_register: ");
 846				state->cfa.reg = get_uleb128(&ptr.p8, end);
 847				break;
 848				/*todo case DW_CFA_def_cfa_expression: */
 849				/*todo case DW_CFA_expression: */
 850				/*todo case DW_CFA_val_expression: */
 851			case DW_CFA_GNU_args_size:
 852				get_uleb128(&ptr.p8, end);
 853				break;
 854			case DW_CFA_GNU_negative_offset_extended:
 855				value = get_uleb128(&ptr.p8, end);
 856				set_rule(value,
 857					 Memory,
 858					 (uleb128_t) 0 - get_uleb128(&ptr.p8,
 859								     end),
 860					 state);
 861				break;
 862			case DW_CFA_GNU_window_save:
 863			default:
 864				unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
 865				result = 0;
 866				break;
 867			}
 868			break;
 869		case 1:
 870			unw_debug("\ncfa_adv_loc: ");
 871			result = advance_loc(*ptr.p8++ & 0x3f, state);
 872			break;
 873		case 2:
 874			unw_debug("cfa_offset: ");
 875			value = *ptr.p8++ & 0x3f;
 876			set_rule(value, Memory, get_uleb128(&ptr.p8, end),
 877				 state);
 878			break;
 879		case 3:
 880			unw_debug("cfa_restore: ");
 881			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
 882			break;
 883		}
 884
 885		if (ptr.p8 > end)
 886			result = 0;
 887		if (result && targetLoc != 0 && targetLoc < state->loc)
 888			return 1;
 889	}
 890
 891	return result && ptr.p8 == end && (targetLoc == 0 || (
 892		/*todo While in theory this should apply, gcc in practice omits
 893		  everything past the function prolog, and hence the location
 894		  never reaches the end of the function.
 895		targetLoc < state->loc && */  state->label == NULL));
 896}
 897
 898/* Unwind to previous to frame.  Returns 0 if successful, negative
 899 * number in case of an error. */
 900int arc_unwind(struct unwind_frame_info *frame)
 901{
 902#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
 903	const u32 *fde = NULL, *cie = NULL;
 904	const u8 *ptr = NULL, *end = NULL;
 905	unsigned long pc = UNW_PC(frame) - frame->call_frame;
 906	unsigned long startLoc = 0, endLoc = 0, cfa;
 907	unsigned int i;
 908	signed ptrType = -1;
 909	uleb128_t retAddrReg = 0;
 910	const struct unwind_table *table;
 911	struct unwind_state state;
 912	unsigned long *fptr;
 913	unsigned long addr;
 914
 915	unw_debug("\n\nUNWIND FRAME:\n");
 916	unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
 917		  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
 918		  UNW_FP(frame));
 919
 920	if (UNW_PC(frame) == 0)
 921		return -EINVAL;
 922
 923#ifdef UNWIND_DEBUG
 924	{
 925		unsigned long *sptr = (unsigned long *)UNW_SP(frame);
 926		unw_debug("\nStack Dump:\n");
 927		for (i = 0; i < 20; i++, sptr++)
 928			unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
 929		unw_debug("\n");
 930	}
 931#endif
 932
 933	table = find_table(pc);
 934	if (table != NULL
 935	    && !(table->size & (sizeof(*fde) - 1))) {
 936		const u8 *hdr = table->header;
 937		unsigned long tableSize;
 938
 939		smp_rmb();
 940		if (hdr && hdr[0] == 1) {
 941			switch (hdr[3] & DW_EH_PE_FORM) {
 942			case DW_EH_PE_native:
 943				tableSize = sizeof(unsigned long);
 944				break;
 945			case DW_EH_PE_data2:
 946				tableSize = 2;
 947				break;
 948			case DW_EH_PE_data4:
 949				tableSize = 4;
 950				break;
 951			case DW_EH_PE_data8:
 952				tableSize = 8;
 953				break;
 954			default:
 955				tableSize = 0;
 956				break;
 957			}
 958			ptr = hdr + 4;
 959			end = hdr + table->hdrsz;
 960			if (tableSize && read_pointer(&ptr, end, hdr[1])
 961			    == (unsigned long)table->address
 962			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
 963			    && i == (end - ptr) / (2 * tableSize)
 964			    && !((end - ptr) % (2 * tableSize))) {
 965				do {
 966					const u8 *cur =
 967					    ptr + (i / 2) * (2 * tableSize);
 968
 969					startLoc = read_pointer(&cur,
 970								cur + tableSize,
 971								hdr[3]);
 972					if (pc < startLoc)
 973						i /= 2;
 974					else {
 975						ptr = cur - tableSize;
 976						i = (i + 1) / 2;
 977					}
 978				} while (startLoc && i > 1);
 979				if (i == 1
 980				    && (startLoc = read_pointer(&ptr,
 981								ptr + tableSize,
 982								hdr[3])) != 0
 983				    && pc >= startLoc)
 984					fde = (void *)read_pointer(&ptr,
 985								   ptr +
 986								   tableSize,
 987								   hdr[3]);
 988			}
 989		}
 990
 991		if (fde != NULL) {
 992			cie = cie_for_fde(fde, table);
 993			ptr = (const u8 *)(fde + 2);
 994			if (cie != NULL
 995			    && cie != &bad_cie
 996			    && cie != &not_fde
 997			    && (ptrType = fde_pointer_type(cie)) >= 0
 998			    && read_pointer(&ptr,
 999					    (const u8 *)(fde + 1) + *fde,
1000					    ptrType) == startLoc) {
1001				if (!(ptrType & DW_EH_PE_indirect))
1002					ptrType &=
1003					    DW_EH_PE_FORM | DW_EH_PE_signed;
1004				endLoc =
1005				    startLoc + read_pointer(&ptr,
1006							    (const u8 *)(fde +
1007									 1) +
1008							    *fde, ptrType);
1009				if (pc >= endLoc) {
1010					fde = NULL;
1011					cie = NULL;
1012				}
1013			} else {
1014				fde = NULL;
1015				cie = NULL;
1016			}
1017		}
1018	}
1019	if (cie != NULL) {
1020		memset(&state, 0, sizeof(state));
1021		state.cieEnd = ptr;	/* keep here temporarily */
1022		ptr = (const u8 *)(cie + 2);
1023		end = (const u8 *)(cie + 1) + *cie;
1024		frame->call_frame = 1;
1025		if (*++ptr) {
1026			/* check if augmentation size is first (thus present) */
1027			if (*ptr == 'z') {
1028				while (++ptr < end && *ptr) {
1029					switch (*ptr) {
1030					/* chk for ignorable or already handled
1031					 * nul-terminated augmentation string */
1032					case 'L':
1033					case 'P':
1034					case 'R':
1035						continue;
1036					case 'S':
1037						frame->call_frame = 0;
1038						continue;
1039					default:
1040						break;
1041					}
1042					break;
1043				}
1044			}
1045			if (ptr >= end || *ptr)
1046				cie = NULL;
1047		}
1048		++ptr;
1049	}
1050	if (cie != NULL) {
1051		/* get code alignment factor */
1052		state.codeAlign = get_uleb128(&ptr, end);
1053		/* get data alignment factor */
1054		state.dataAlign = get_sleb128(&ptr, end);
1055		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1056			cie = NULL;
1057		else {
1058			retAddrReg =
1059			    state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1060								      end);
1061			unw_debug("CIE Frame Info:\n");
1062			unw_debug("return Address register 0x%lx\n",
1063				  retAddrReg);
1064			unw_debug("data Align: %ld\n", state.dataAlign);
1065			unw_debug("code Align: %lu\n", state.codeAlign);
1066			/* skip augmentation */
1067			if (((const char *)(cie + 2))[1] == 'z') {
1068				uleb128_t augSize = get_uleb128(&ptr, end);
1069
1070				ptr += augSize;
1071			}
1072			if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1073			    || REG_INVALID(retAddrReg)
1074			    || reg_info[retAddrReg].width !=
1075			    sizeof(unsigned long))
1076				cie = NULL;
1077		}
1078	}
1079	if (cie != NULL) {
1080		state.cieStart = ptr;
1081		ptr = state.cieEnd;
1082		state.cieEnd = end;
1083		end = (const u8 *)(fde + 1) + *fde;
1084		/* skip augmentation */
1085		if (((const char *)(cie + 2))[1] == 'z') {
1086			uleb128_t augSize = get_uleb128(&ptr, end);
1087
1088			if ((ptr += augSize) > end)
1089				fde = NULL;
1090		}
1091	}
1092	if (cie == NULL || fde == NULL) {
1093#ifdef CONFIG_FRAME_POINTER
1094		unsigned long top, bottom;
1095
1096		top = STACK_TOP_UNW(frame->task);
1097		bottom = STACK_BOTTOM_UNW(frame->task);
1098#if FRAME_RETADDR_OFFSET < 0
1099		if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1100		    && bottom < UNW_FP(frame)
1101#else
1102		if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1103		    && bottom > UNW_FP(frame)
1104#endif
1105		    && !((UNW_SP(frame) | UNW_FP(frame))
1106			 & (sizeof(unsigned long) - 1))) {
1107			unsigned long link;
1108
1109			if (!__get_user(link, (unsigned long *)
1110					(UNW_FP(frame) + FRAME_LINK_OFFSET))
1111#if FRAME_RETADDR_OFFSET < 0
1112			    && link > bottom && link < UNW_FP(frame)
1113#else
1114			    && link > UNW_FP(frame) && link < bottom
1115#endif
1116			    && !(link & (sizeof(link) - 1))
1117			    && !__get_user(UNW_PC(frame),
1118					   (unsigned long *)(UNW_FP(frame)
1119						+ FRAME_RETADDR_OFFSET)))
1120			{
1121				UNW_SP(frame) =
1122				    UNW_FP(frame) + FRAME_RETADDR_OFFSET
1123#if FRAME_RETADDR_OFFSET < 0
1124				    -
1125#else
1126				    +
1127#endif
1128				    sizeof(UNW_PC(frame));
1129				UNW_FP(frame) = link;
1130				return 0;
1131			}
1132		}
1133#endif
1134		return -ENXIO;
1135	}
1136	state.org = startLoc;
1137	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1138
1139	unw_debug("\nProcess instructions\n");
1140
1141	/* process instructions
1142	 * For ARC, we optimize by having blink(retAddrReg) with
1143	 * the sameValue in the leaf function, so we should not check
1144	 * state.regs[retAddrReg].where == Nowhere
1145	 */
1146	if (!processCFI(ptr, end, pc, ptrType, &state)
1147	    || state.loc > endLoc
1148/*	   || state.regs[retAddrReg].where == Nowhere */
1149	    || state.cfa.reg >= ARRAY_SIZE(reg_info)
1150	    || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1151	    || state.cfa.offs % sizeof(unsigned long))
1152		return -EIO;
1153
1154#ifdef UNWIND_DEBUG
1155	unw_debug("\n");
1156
1157	unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1158	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1159
1160		if (REG_INVALID(i))
1161			continue;
1162
1163		switch (state.regs[i].where) {
1164		case Nowhere:
1165			break;
1166		case Memory:
1167			unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1168			break;
1169		case Register:
1170			unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1171			break;
1172		case Value:
1173			unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1174			break;
1175		}
1176	}
1177
1178	unw_debug("\n");
1179#endif
1180
1181	/* update frame */
1182	if (frame->call_frame
1183	    && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1184		frame->call_frame = 0;
1185	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1186	startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1187	endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1188	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1189		startLoc = min(STACK_LIMIT(cfa), cfa);
1190		endLoc = max(STACK_LIMIT(cfa), cfa);
1191	}
1192
1193	unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
1194		  state.cfa.reg, state.cfa.offs, cfa);
1195
1196	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1197		if (REG_INVALID(i)) {
1198			if (state.regs[i].where == Nowhere)
1199				continue;
1200			return -EIO;
1201		}
1202		switch (state.regs[i].where) {
1203		default:
1204			break;
1205		case Register:
1206			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1207			    || REG_INVALID(state.regs[i].value)
1208			    || reg_info[i].width >
1209			    reg_info[state.regs[i].value].width)
1210				return -EIO;
1211			switch (reg_info[state.regs[i].value].width) {
1212			case sizeof(u8):
1213				state.regs[i].value =
1214				FRAME_REG(state.regs[i].value, const u8);
1215				break;
1216			case sizeof(u16):
1217				state.regs[i].value =
1218				FRAME_REG(state.regs[i].value, const u16);
1219				break;
1220			case sizeof(u32):
1221				state.regs[i].value =
1222				FRAME_REG(state.regs[i].value, const u32);
1223				break;
1224#ifdef CONFIG_64BIT
1225			case sizeof(u64):
1226				state.regs[i].value =
1227				FRAME_REG(state.regs[i].value, const u64);
1228				break;
1229#endif
1230			default:
1231				return -EIO;
1232			}
1233			break;
1234		}
1235	}
1236
1237	unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1238	fptr = (unsigned long *)(&frame->regs);
1239	for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1240
1241		if (REG_INVALID(i))
1242			continue;
1243		switch (state.regs[i].where) {
1244		case Nowhere:
1245			if (reg_info[i].width != sizeof(UNW_SP(frame))
1246			    || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1247			    != &UNW_SP(frame))
1248				continue;
1249			UNW_SP(frame) = cfa;
1250			break;
1251		case Register:
1252			switch (reg_info[i].width) {
1253			case sizeof(u8):
1254				FRAME_REG(i, u8) = state.regs[i].value;
1255				break;
1256			case sizeof(u16):
1257				FRAME_REG(i, u16) = state.regs[i].value;
1258				break;
1259			case sizeof(u32):
1260				FRAME_REG(i, u32) = state.regs[i].value;
1261				break;
1262#ifdef CONFIG_64BIT
1263			case sizeof(u64):
1264				FRAME_REG(i, u64) = state.regs[i].value;
1265				break;
1266#endif
1267			default:
1268				return -EIO;
1269			}
1270			break;
1271		case Value:
1272			if (reg_info[i].width != sizeof(unsigned long))
1273				return -EIO;
1274			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1275			    * state.dataAlign;
1276			break;
1277		case Memory:
1278			addr = cfa + state.regs[i].value * state.dataAlign;
1279
1280			if ((state.regs[i].value * state.dataAlign)
1281			    % sizeof(unsigned long)
1282			    || addr < startLoc
1283			    || addr + sizeof(unsigned long) < addr
1284			    || addr + sizeof(unsigned long) > endLoc)
1285					return -EIO;
1286
1287			switch (reg_info[i].width) {
1288			case sizeof(u8):
1289				__get_user(FRAME_REG(i, u8),
1290					   (u8 __user *)addr);
1291				break;
1292			case sizeof(u16):
1293				__get_user(FRAME_REG(i, u16),
1294					   (u16 __user *)addr);
1295				break;
1296			case sizeof(u32):
1297				__get_user(FRAME_REG(i, u32),
1298					   (u32 __user *)addr);
1299				break;
1300#ifdef CONFIG_64BIT
1301			case sizeof(u64):
1302				__get_user(FRAME_REG(i, u64),
1303					   (u64 __user *)addr);
1304				break;
1305#endif
1306			default:
1307				return -EIO;
1308			}
1309
1310			break;
1311		}
1312		unw_debug("r%d: 0x%lx ", i, *fptr);
1313	}
1314
1315	return 0;
1316#undef FRAME_REG
1317}
1318EXPORT_SYMBOL(arc_unwind);