103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Function return value location for Linux/TILE-Gx ABI. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2012 Tilera Corporation 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2014 Red Hat, Inc. 403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes WITHOUT ANY WARRANTY; without even the implied warranty of 2303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes General Public License for more details. 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef HAVE_CONFIG_H 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# include <config.h> 3303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 3403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <assert.h> 3603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <dwarf.h> 3703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define BACKEND tilegx_ 3903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "libebl_CPU.h" 4003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* r0. */ 4303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwarf_Op loc_intreg[] = 4403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_reg0 } 4603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 4703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define nloc_intreg 1 4803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* The return value is a structure and is actually stored in stack space 5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes passed in a hidden argument by the caller. But, the compiler 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes helpfully returns the address of that space in r0. */ 5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwarf_Op loc_aggregate[] = 5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_breg0, .number = 0 } 5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define nloc_aggregate 1 5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint 5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughestilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Start with the function's type, and get the DW_AT_type attribute, 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes which is the type of the return value. */ 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die die_mem, *typedie = &die_mem; 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int tag = dwarf_peeled_die_type (functypedie, typedie); 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag <= 0) 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return tag; 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word size; 6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (tag) 7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case -1: 7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_subrange_type: 7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) 7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem, *attr; 7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); 7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes typedie = dwarf_formref_die (attr, &die_mem); 8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes tag = DWARF_TAG_OR_RETURN (typedie); 8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Fall through. */ 8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_base_type: 8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_enumeration_type: 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_pointer_type: 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_ptr_to_member_type: 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem; 9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, 9103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr_mem), &size) != 0) 9203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 9303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) 9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size = 8; 9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 9703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_base_type) 9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word encoding; 10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, 10203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr_mem), 10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &encoding) != 0) 10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Small enough structs are passed directly in registers R0 ... R7. */ 10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (size <= 8) 11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes intreg: 11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_intreg; 11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return nloc_intreg; 11403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 11503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Else fall through. */ 11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_structure_type: 11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_class_type: 11903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_union_type: 12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes aggregate: 12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_aggregate; 12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return nloc_aggregate; 12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_array_type: 12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_string_type: 12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_aggregate_size (typedie, &size) == 0 && size <= 8) 12703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_array_type) 12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem, *attr; 13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Check if it's a character array. */ 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); 13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes typedie = dwarf_formref_die (attr, &die_mem); 13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes tag = DWARF_TAG_OR_RETURN (typedie); 13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag != DW_TAG_base_type) 13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto aggregate; 13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr_integrate (typedie, 13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DW_AT_byte_size, 13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr_mem), 14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &size) != 0) 14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (size != 1) 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto aggregate; 14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto intreg; 14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto aggregate; 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 14903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* XXX We don't have a good way to return specific errors from ebl calls. 15103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This value means we do not understand the type, but it is well-formed 15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DWARF and might be valid. */ 15303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -2; 15403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 155