Linux Audio

Check our new training course

Open-source upstreaming

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