unwind.c 32 KB

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