Linux Audio

Check our new training course

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