Linux Audio

Check our new training course

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