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