xref: /openbmc/linux/arch/sh/include/asm/dwarf.h (revision 597473720f4dc69749542bfcfed4a927a43d935e)
1  /* SPDX-License-Identifier: GPL-2.0
2   *
3   * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
4   */
5  #ifndef __ASM_SH_DWARF_H
6  #define __ASM_SH_DWARF_H
7  
8  #ifdef CONFIG_DWARF_UNWINDER
9  
10  /*
11   * DWARF expression operations
12   */
13  #define DW_OP_addr	0x03
14  #define DW_OP_deref	0x06
15  #define DW_OP_const1u	0x08
16  #define DW_OP_const1s	0x09
17  #define DW_OP_const2u	0x0a
18  #define DW_OP_const2s	0x0b
19  #define DW_OP_const4u	0x0c
20  #define DW_OP_const4s	0x0d
21  #define DW_OP_const8u	0x0e
22  #define DW_OP_const8s	0x0f
23  #define DW_OP_constu	0x10
24  #define DW_OP_consts	0x11
25  #define DW_OP_dup	0x12
26  #define DW_OP_drop	0x13
27  #define DW_OP_over	0x14
28  #define DW_OP_pick	0x15
29  #define DW_OP_swap	0x16
30  #define DW_OP_rot	0x17
31  #define DW_OP_xderef	0x18
32  #define DW_OP_abs	0x19
33  #define DW_OP_and	0x1a
34  #define DW_OP_div	0x1b
35  #define DW_OP_minus	0x1c
36  #define DW_OP_mod	0x1d
37  #define DW_OP_mul	0x1e
38  #define DW_OP_neg	0x1f
39  #define DW_OP_not	0x20
40  #define DW_OP_or	0x21
41  #define DW_OP_plus	0x22
42  #define DW_OP_plus_uconst	0x23
43  #define DW_OP_shl	0x24
44  #define DW_OP_shr	0x25
45  #define DW_OP_shra	0x26
46  #define DW_OP_xor	0x27
47  #define DW_OP_skip	0x2f
48  #define DW_OP_bra	0x28
49  #define DW_OP_eq	0x29
50  #define DW_OP_ge	0x2a
51  #define DW_OP_gt	0x2b
52  #define DW_OP_le	0x2c
53  #define DW_OP_lt	0x2d
54  #define DW_OP_ne	0x2e
55  #define DW_OP_lit0	0x30
56  #define DW_OP_lit1	0x31
57  #define DW_OP_lit2	0x32
58  #define DW_OP_lit3	0x33
59  #define DW_OP_lit4	0x34
60  #define DW_OP_lit5	0x35
61  #define DW_OP_lit6	0x36
62  #define DW_OP_lit7	0x37
63  #define DW_OP_lit8	0x38
64  #define DW_OP_lit9	0x39
65  #define DW_OP_lit10	0x3a
66  #define DW_OP_lit11	0x3b
67  #define DW_OP_lit12	0x3c
68  #define DW_OP_lit13	0x3d
69  #define DW_OP_lit14	0x3e
70  #define DW_OP_lit15	0x3f
71  #define DW_OP_lit16	0x40
72  #define DW_OP_lit17	0x41
73  #define DW_OP_lit18	0x42
74  #define DW_OP_lit19	0x43
75  #define DW_OP_lit20	0x44
76  #define DW_OP_lit21	0x45
77  #define DW_OP_lit22	0x46
78  #define DW_OP_lit23	0x47
79  #define DW_OP_lit24	0x48
80  #define DW_OP_lit25	0x49
81  #define DW_OP_lit26	0x4a
82  #define DW_OP_lit27	0x4b
83  #define DW_OP_lit28	0x4c
84  #define DW_OP_lit29	0x4d
85  #define DW_OP_lit30	0x4e
86  #define DW_OP_lit31	0x4f
87  #define DW_OP_reg0	0x50
88  #define DW_OP_reg1	0x51
89  #define DW_OP_reg2	0x52
90  #define DW_OP_reg3	0x53
91  #define DW_OP_reg4	0x54
92  #define DW_OP_reg5	0x55
93  #define DW_OP_reg6	0x56
94  #define DW_OP_reg7	0x57
95  #define DW_OP_reg8	0x58
96  #define DW_OP_reg9	0x59
97  #define DW_OP_reg10	0x5a
98  #define DW_OP_reg11	0x5b
99  #define DW_OP_reg12	0x5c
100  #define DW_OP_reg13	0x5d
101  #define DW_OP_reg14	0x5e
102  #define DW_OP_reg15	0x5f
103  #define DW_OP_reg16	0x60
104  #define DW_OP_reg17	0x61
105  #define DW_OP_reg18	0x62
106  #define DW_OP_reg19	0x63
107  #define DW_OP_reg20	0x64
108  #define DW_OP_reg21	0x65
109  #define DW_OP_reg22	0x66
110  #define DW_OP_reg23	0x67
111  #define DW_OP_reg24	0x68
112  #define DW_OP_reg25	0x69
113  #define DW_OP_reg26	0x6a
114  #define DW_OP_reg27	0x6b
115  #define DW_OP_reg28	0x6c
116  #define DW_OP_reg29	0x6d
117  #define DW_OP_reg30	0x6e
118  #define DW_OP_reg31	0x6f
119  #define DW_OP_breg0	0x70
120  #define DW_OP_breg1	0x71
121  #define DW_OP_breg2	0x72
122  #define DW_OP_breg3	0x73
123  #define DW_OP_breg4	0x74
124  #define DW_OP_breg5	0x75
125  #define DW_OP_breg6	0x76
126  #define DW_OP_breg7	0x77
127  #define DW_OP_breg8	0x78
128  #define DW_OP_breg9	0x79
129  #define DW_OP_breg10	0x7a
130  #define DW_OP_breg11	0x7b
131  #define DW_OP_breg12	0x7c
132  #define DW_OP_breg13	0x7d
133  #define DW_OP_breg14	0x7e
134  #define DW_OP_breg15	0x7f
135  #define DW_OP_breg16	0x80
136  #define DW_OP_breg17	0x81
137  #define DW_OP_breg18	0x82
138  #define DW_OP_breg19	0x83
139  #define DW_OP_breg20	0x84
140  #define DW_OP_breg21	0x85
141  #define DW_OP_breg22	0x86
142  #define DW_OP_breg23	0x87
143  #define DW_OP_breg24	0x88
144  #define DW_OP_breg25	0x89
145  #define DW_OP_breg26	0x8a
146  #define DW_OP_breg27	0x8b
147  #define DW_OP_breg28	0x8c
148  #define DW_OP_breg29	0x8d
149  #define DW_OP_breg30	0x8e
150  #define DW_OP_breg31	0x8f
151  #define DW_OP_regx	0x90
152  #define DW_OP_fbreg	0x91
153  #define DW_OP_bregx	0x92
154  #define DW_OP_piece	0x93
155  #define DW_OP_deref_size	0x94
156  #define DW_OP_xderef_size	0x95
157  #define DW_OP_nop	0x96
158  #define DW_OP_push_object_address	0x97
159  #define DW_OP_call2	0x98
160  #define DW_OP_call4	0x99
161  #define DW_OP_call_ref	0x9a
162  #define DW_OP_form_tls_address	0x9b
163  #define DW_OP_call_frame_cfa	0x9c
164  #define DW_OP_bit_piece	0x9d
165  #define DW_OP_lo_user	0xe0
166  #define DW_OP_hi_user	0xff
167  
168  /*
169   * Addresses used in FDE entries in the .eh_frame section may be encoded
170   * using one of the following encodings.
171   */
172  #define DW_EH_PE_absptr	0x00
173  #define DW_EH_PE_omit	0xff
174  #define DW_EH_PE_uleb128	0x01
175  #define DW_EH_PE_udata2	0x02
176  #define DW_EH_PE_udata4	0x03
177  #define DW_EH_PE_udata8	0x04
178  #define DW_EH_PE_sleb128	0x09
179  #define DW_EH_PE_sdata2	0x0a
180  #define DW_EH_PE_sdata4	0x0b
181  #define DW_EH_PE_sdata8	0x0c
182  #define DW_EH_PE_signed	0x09
183  
184  #define DW_EH_PE_pcrel	0x10
185  
186  /*
187   * The architecture-specific register number that contains the return
188   * address in the .debug_frame table.
189   */
190  #define DWARF_ARCH_RA_REG	17
191  
192  #ifndef __ASSEMBLY__
193  
194  #include <linux/compiler.h>
195  #include <linux/bug.h>
196  #include <linux/list.h>
197  #include <linux/module.h>
198  
199  /*
200   * Read either the frame pointer (r14) or the stack pointer (r15).
201   * NOTE: this MUST be inlined.
202   */
dwarf_read_arch_reg(unsigned int reg)203  static __always_inline unsigned long dwarf_read_arch_reg(unsigned int reg)
204  {
205  	unsigned long value = 0;
206  
207  	switch (reg) {
208  	case 14:
209  		__asm__ __volatile__("mov r14, %0\n" : "=r" (value));
210  		break;
211  	case 15:
212  		__asm__ __volatile__("mov r15, %0\n" : "=r" (value));
213  		break;
214  	default:
215  		BUG();
216  	}
217  
218  	return value;
219  }
220  
221  /**
222   *	dwarf_cie - Common Information Entry
223   */
224  struct dwarf_cie {
225  	unsigned long length;
226  	unsigned long cie_id;
227  	unsigned char version;
228  	const char *augmentation;
229  	unsigned int code_alignment_factor;
230  	int data_alignment_factor;
231  
232  	/* Which column in the rule table represents return addr of func. */
233  	unsigned int return_address_reg;
234  
235  	unsigned char *initial_instructions;
236  	unsigned char *instructions_end;
237  
238  	unsigned char encoding;
239  
240  	unsigned long cie_pointer;
241  
242  	unsigned long flags;
243  #define DWARF_CIE_Z_AUGMENTATION	(1 << 0)
244  
245  	/* linked-list entry if this CIE is from a module */
246  	struct list_head link;
247  
248  	struct rb_node node;
249  };
250  
251  /**
252   *	dwarf_fde - Frame Description Entry
253   */
254  struct dwarf_fde {
255  	unsigned long length;
256  	unsigned long cie_pointer;
257  	struct dwarf_cie *cie;
258  	unsigned long initial_location;
259  	unsigned long address_range;
260  	unsigned char *instructions;
261  	unsigned char *end;
262  
263  	/* linked-list entry if this FDE is from a module */
264  	struct list_head link;
265  
266  	struct rb_node node;
267  };
268  
269  /**
270   *	dwarf_frame - DWARF information for a frame in the call stack
271   */
272  struct dwarf_frame {
273  	struct dwarf_frame *prev, *next;
274  
275  	unsigned long pc;
276  
277  	struct list_head reg_list;
278  
279  	unsigned long cfa;
280  
281  	/* Valid when DW_FRAME_CFA_REG_OFFSET is set in flags */
282  	unsigned int cfa_register;
283  	unsigned int cfa_offset;
284  
285  	/* Valid when DW_FRAME_CFA_REG_EXP is set in flags */
286  	unsigned char *cfa_expr;
287  	unsigned int cfa_expr_len;
288  
289  	unsigned long flags;
290  #define DWARF_FRAME_CFA_REG_OFFSET	(1 << 0)
291  #define DWARF_FRAME_CFA_REG_EXP		(1 << 1)
292  
293  	unsigned long return_addr;
294  };
295  
296  /**
297   *	dwarf_reg - DWARF register
298   *	@flags: Describes how to calculate the value of this register
299   */
300  struct dwarf_reg {
301  	struct list_head link;
302  
303  	unsigned int number;
304  
305  	unsigned long addr;
306  	unsigned long flags;
307  #define DWARF_REG_OFFSET	(1 << 0)
308  #define DWARF_VAL_OFFSET	(1 << 1)
309  #define DWARF_UNDEFINED		(1 << 2)
310  };
311  
312  /*
313   * Call Frame instruction opcodes.
314   */
315  #define DW_CFA_advance_loc	0x40
316  #define DW_CFA_offset		0x80
317  #define DW_CFA_restore		0xc0
318  #define DW_CFA_nop		0x00
319  #define DW_CFA_set_loc		0x01
320  #define DW_CFA_advance_loc1	0x02
321  #define DW_CFA_advance_loc2	0x03
322  #define DW_CFA_advance_loc4	0x04
323  #define DW_CFA_offset_extended	0x05
324  #define DW_CFA_restore_extended	0x06
325  #define DW_CFA_undefined	0x07
326  #define DW_CFA_same_value	0x08
327  #define DW_CFA_register		0x09
328  #define DW_CFA_remember_state	0x0a
329  #define DW_CFA_restore_state	0x0b
330  #define DW_CFA_def_cfa		0x0c
331  #define DW_CFA_def_cfa_register	0x0d
332  #define DW_CFA_def_cfa_offset	0x0e
333  #define DW_CFA_def_cfa_expression	0x0f
334  #define DW_CFA_expression	0x10
335  #define DW_CFA_offset_extended_sf	0x11
336  #define DW_CFA_def_cfa_sf	0x12
337  #define DW_CFA_def_cfa_offset_sf	0x13
338  #define DW_CFA_val_offset	0x14
339  #define DW_CFA_val_offset_sf	0x15
340  #define DW_CFA_val_expression	0x16
341  #define DW_CFA_lo_user		0x1c
342  #define DW_CFA_hi_user		0x3f
343  
344  /* GNU extension opcodes  */
345  #define DW_CFA_GNU_args_size	0x2e
346  #define DW_CFA_GNU_negative_offset_extended 0x2f
347  
348  /*
349   * Some call frame instructions encode their operands in the opcode. We
350   * need some helper functions to extract both the opcode and operands
351   * from an instruction.
352   */
DW_CFA_opcode(unsigned long insn)353  static inline unsigned int DW_CFA_opcode(unsigned long insn)
354  {
355  	return (insn & 0xc0);
356  }
357  
DW_CFA_operand(unsigned long insn)358  static inline unsigned int DW_CFA_operand(unsigned long insn)
359  {
360  	return (insn & 0x3f);
361  }
362  
363  #define DW_EH_FRAME_CIE	0		/* .eh_frame CIE IDs are 0 */
364  #define DW_CIE_ID	0xffffffff
365  #define DW64_CIE_ID	0xffffffffffffffffULL
366  
367  /*
368   * DWARF FDE/CIE length field values.
369   */
370  #define DW_EXT_LO	0xfffffff0
371  #define DW_EXT_HI	0xffffffff
372  #define DW_EXT_DWARF64	DW_EXT_HI
373  
374  extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
375  					      struct dwarf_frame *);
376  extern void dwarf_free_frame(struct dwarf_frame *);
377  
378  extern int module_dwarf_finalize(const Elf_Ehdr *, const Elf_Shdr *,
379  				 struct module *);
380  extern void module_dwarf_cleanup(struct module *);
381  
382  #endif /* !__ASSEMBLY__ */
383  
384  #define CFI_STARTPROC	.cfi_startproc
385  #define CFI_ENDPROC	.cfi_endproc
386  #define CFI_DEF_CFA	.cfi_def_cfa
387  #define CFI_REGISTER	.cfi_register
388  #define CFI_REL_OFFSET	.cfi_rel_offset
389  #define CFI_UNDEFINED	.cfi_undefined
390  
391  #else
392  
393  /*
394   * Use the asm comment character to ignore the rest of the line.
395   */
396  #define CFI_IGNORE	!
397  
398  #define CFI_STARTPROC	CFI_IGNORE
399  #define CFI_ENDPROC	CFI_IGNORE
400  #define CFI_DEF_CFA	CFI_IGNORE
401  #define CFI_REGISTER	CFI_IGNORE
402  #define CFI_REL_OFFSET	CFI_IGNORE
403  #define CFI_UNDEFINED	CFI_IGNORE
404  
405  #ifndef __ASSEMBLY__
dwarf_unwinder_init(void)406  static inline void dwarf_unwinder_init(void)
407  {
408  }
409  
410  #define module_dwarf_finalize(hdr, sechdrs, me)	(0)
411  #define module_dwarf_cleanup(mod)		do { } while (0)
412  
413  #endif
414  
415  #endif /* CONFIG_DWARF_UNWINDER */
416  
417  #endif /* __ASM_SH_DWARF_H */
418