Branch data Line data Source code
1 : : /* Function return value location for Linux/m68k ABI. 2 : : This file is part of elfutils. 3 : : 4 : : This file is free software; you can redistribute it and/or modify 5 : : it under the terms of either 6 : : 7 : : * the GNU Lesser General Public License as published by the Free 8 : : Software Foundation; either version 3 of the License, or (at 9 : : your option) any later version 10 : : 11 : : or 12 : : 13 : : * the GNU General Public License as published by the Free 14 : : Software Foundation; either version 2 of the License, or (at 15 : : your option) any later version 16 : : 17 : : or both in parallel, as here. 18 : : 19 : : elfutils is distributed in the hope that it will be useful, but 20 : : WITHOUT ANY WARRANTY; without even the implied warranty of 21 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 : : General Public License for more details. 23 : : 24 : : You should have received copies of the GNU General Public License and 25 : : the GNU Lesser General Public License along with this program. If 26 : : not, see <http://www.gnu.org/licenses/>. */ 27 : : 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <assert.h> 34 : : #include <dwarf.h> 35 : : 36 : : #define BACKEND m68k_ 37 : : #include "libebl_CPU.h" 38 : : 39 : : 40 : : /* %d0, or pair %d0, %d1. */ 41 : : static const Dwarf_Op loc_intreg[] = 42 : : { 43 : : { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 }, 44 : : { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 }, 45 : : }; 46 : : #define nloc_intreg 1 47 : : #define nloc_intregpair 4 48 : : 49 : : /* %a0. */ 50 : : static const Dwarf_Op loc_ptrreg[] = 51 : : { 52 : : { .atom = DW_OP_reg8 } 53 : : }; 54 : : #define nloc_ptrreg 1 55 : : 56 : : /* %fp0. */ 57 : : static const Dwarf_Op loc_fpreg[] = 58 : : { 59 : : { .atom = DW_OP_reg16 } 60 : : }; 61 : : #define nloc_fpreg 1 62 : : 63 : : /* The return value is a structure and is actually stored in stack space 64 : : passed in a hidden argument by the caller. But, the compiler 65 : : helpfully returns the address of that space in %a0. */ 66 : : static const Dwarf_Op loc_aggregate[] = 67 : : { 68 : : { .atom = DW_OP_reg8 } 69 : : }; 70 : : #define nloc_aggregate 1 71 : : 72 : : int 73 : 0 : m68k_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) 74 : : { 75 : : /* Start with the function's type, and get the DW_AT_type attribute, 76 : : which is the type of the return value. */ 77 : 0 : Dwarf_Die die_mem, *typedie = &die_mem; 78 : 0 : int tag = dwarf_peeled_die_type (functypedie, typedie); 79 [ # # ]: 0 : if (tag <= 0) 80 : : return tag; 81 : : 82 [ # # # # ]: 0 : switch (tag) 83 : : { 84 : : case -1: 85 : : return -1; 86 : : 87 : 0 : case DW_TAG_subrange_type: 88 [ # # ]: 0 : if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) 89 : : { 90 : 0 : Dwarf_Attribute attr_mem, *attr; 91 : 0 : attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); 92 : 0 : typedie = dwarf_formref_die (attr, &die_mem); 93 [ # # ]: 0 : tag = DWARF_TAG_OR_RETURN (typedie); 94 : : } 95 : 0 : FALLTHROUGH; 96 : : 97 : : case DW_TAG_base_type: 98 : : case DW_TAG_enumeration_type: 99 : : CASE_POINTER: 100 : : { 101 : 0 : Dwarf_Word size; 102 : 0 : Dwarf_Attribute attr_mem; 103 [ # # ]: 0 : if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, 104 : : &attr_mem), &size) != 0) 105 : : { 106 [ # # ]: 0 : if (dwarf_is_pointer (tag)) 107 : 0 : size = 4; 108 : : else 109 : 0 : return -1; 110 : : } 111 [ # # ]: 0 : if (tag == DW_TAG_base_type) 112 : : { 113 : 0 : Dwarf_Word encoding; 114 [ # # ]: 0 : if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, 115 : : &attr_mem), 116 : : &encoding) != 0) 117 : 0 : return -1; 118 [ # # ]: 0 : if (encoding == DW_ATE_float) 119 : : { 120 [ # # ]: 0 : if (size > 12) 121 : : return -2; 122 : 0 : *locp = loc_fpreg; 123 : 0 : return nloc_fpreg; 124 : : } 125 : : } 126 [ # # ]: 0 : if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) 127 : : { 128 : 0 : *locp = loc_ptrreg; 129 : 0 : return nloc_ptrreg; 130 : : } 131 : 0 : *locp = loc_intreg; 132 [ # # ]: 0 : if (size <= 4) 133 : : return nloc_intreg; 134 [ # # ]: 0 : if (size <= 8) 135 : : return nloc_intregpair; 136 : : } 137 : 0 : FALLTHROUGH; 138 : : case DW_TAG_structure_type: 139 : : case DW_TAG_class_type: 140 : : case DW_TAG_union_type: 141 : : case DW_TAG_array_type: 142 : 0 : *locp = loc_aggregate; 143 : 0 : return nloc_aggregate; 144 : : } 145 : : 146 : : /* XXX We don't have a good way to return specific errors from ebl calls. 147 : : This value means we do not understand the type, but it is well-formed 148 : : DWARF and might be valid. */ 149 : : return -2; 150 : : }