Linux Audio

Check our new training course

Linux BSP development engineering services

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