#ifndef DWARF2_LANG #define DWARF2_LANG #include /* * This is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2, or (at your option) any later * version. */ /* * This file defines macros that allow generation of DWARF debug records * for asm files. This file is platform independent. Register numbers * (which are about the only thing that is platform dependent) are to be * supplied by a platform defined file. */ #define DWARF_preamble() .section .debug_frame,"",@progbits /* * This macro starts a debug frame section. The debug_frame describes * where to find the registers that the enclosing function saved on * entry. * * ORD is use by the label generator and should be the same as what is * passed to CFI_postamble. * * pc, pc register gdb ordinal. * * code_align this is the factor used to define locations or regions * where the given definitions apply. If you use labels to define these * this should be 1. * * data_align this is the factor used to define register offsets. If * you use struct offset, this should be the size of the register in * bytes or the negative of that. This is how it is used: you will * define a register as the reference register, say the stack pointer, * then you will say where a register is located relative to this * reference registers value, say 40 for register 3 (the gdb register * number). The <40> will be multiplied by to define the * byte offset of the given register (3, in this example). So if your * <40> is the byte offset and the reference register points at the * begining, you would want 1 for the data_offset. If <40> was the 40th * 4-byte element in that structure you would want 4. And if your * reference register points at the end of the structure you would want * a negative data_align value(and you would have to do other math as * well). */ #define CFI_preamble(ORD, pc, code_align, data_align) \ .section .debug_frame,"",@progbits ; \ .align 4; \ frame/**/_/**/ORD: \ .long end/**/_/**/ORD-start/**/_/**/ORD; \ start/**/_/**/ORD: \ .long DW_CIE_ID; \ .byte DW_CIE_VERSION; \ .byte 0 ; \ .uleb128 code_align; \ .sleb128 data_align; \ .byte pc; /* * After the above macro and prior to the CFI_postamble, you need to * define the initial state. This starts with defining the reference * register and, usually the pc. Here are some helper macros: */ #define CFA_define_reference(reg, offset) \ .byte DW_CFA_def_cfa; \ .uleb128 reg; \ .uleb128 (offset); #define CFA_define_offset(reg, offset) \ .byte (DW_CFA_offset + reg); \ .uleb128 (offset); #define CFI_postamble(ORD) \ .align 4; \ end/**/_/**/ORD: /* * So now your code pushs stuff on the stack, you need a new location * and the rules for what to do. This starts a running description of * the call frame. You need to describe what changes with respect to * the call registers as the location of the pc moves through the code. * The following builds an FDE (fram descriptor entry?). Like the * above, it has a preamble and a postamble. It also is tied to the CFI * above. * The first entry after the preamble must be the location in the code * that the call frame is being described for. */ #define FDE_preamble(ORD, fde_no, initial_address, length) \ .align 4; \ .long FDE_end/**/_/**/fde_no-FDE_start/**/_/**/fde_no; \ FDE_start/**/_/**/fde_no: \ .long frame/**/_/**/ORD; \ .long initial_address; \ .long length; #define FDE_postamble(fde_no) \ .align 4; \ FDE_end/**/_/**/fde_no: /* * That done, you can now add registers, subtract registers, move the * reference and even change the reference. You can also define a new * area of code the info applies to. For discontinuous bits you should * start a new FDE. You may have as many as you like. */ /* * To advance the address by */ #define FDE_advance(bytes) \ .byte DW_CFA_advance_loc4 \ .long bytes /* * With the above you can define all the register locations. But * suppose the reference register moves... Takes the new offset NOT an * increment. This is how esp is tracked if it is not saved. */ #define CFA_define_cfa_offset(offset) \ .byte DW_CFA_def_cfa_offset; \ .uleb128 (offset); /* * Or suppose you want to use a different reference register... */ #define CFA_define_cfa_register(reg) \ .byte DW_CFA_def_cfa_register; \ .uleb128 reg; /* * Here we do the expression stuff */ #define CFA_expression_preamble(exno,reg) \ .leb128 reg; \ .uleb128 DW_FORM_end/**/_/**/exno-DW_FORM_start/**/_/**/exno; \ DW_FORM_start/**/_/**/exno: #define CFA_expression_postamble(exno) \ DW_FORM_end/**/_/**/exno: #define CFA_exp_push_addr(a) \ .byte DW_OP_addr; \ .long a; #define CFA_exp_push_const4s(a) \ .byte DW_OP_const4s; \ .long a; #define CFA_exp_swap .byte DW_OP_swap; #define CFA_exp_dup .byte DW_OP_dup; #define CFA_exp_drop .byte DW_OP_drop; /* * All these work on the top two elements on the stack, replacing them * with the result. Top comes first where it matters. True is 1, false 0. */ #define CFA_exp_deref .byte DW_OP_deref; #define CFA_exp_and .byte DW_OP_and; #define CFA_exp_div .byte DW_OP_div; #define CFA_exp_minus .byte DW_OP_minus; #define CFA_exp_mod .byte DW_OP_mod; #define CFA_exp_neg .byte DW_OP_neg; #define CFA_exp_plus .byte DW_OP_plus; #define CFA_exp_not .byte DW_OP_not; #define CFA_exp_or .byte DW_OP_or; #define CFA_exp_xor .byte DW_OP_xor; #define CFA_exp_OP_le .byte DW_OP_le; #define CFA_exp_OP_ge .byte DW_OP_ge; #define CFA_exp_OP_eq .byte DW_OP_eq; #define CFA_exp_OP_lt .byte DW_OP_lt; #define CFA_exp_OP_gt .byte DW_OP_gt; #define CFA_exp_OP_ne .byte DW_OP_ne; /* * To use the result... */ #define CFA_exp_OP_skip(count) \ .byte DW_OP_skip; \ .lbe??? count; #endif