X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Famd64-tdep.c;h=5c56a970d8c457db940a811dd7eddddd59cce242;hb=aec72fda3b320c36eb99fc1c4cf95b10fc026729;hp=614b6fdd07f65267aaac9bfac43ba2089117bcdb;hpb=cf84fa6bcf514157df8343d32885050bafc396f7;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 614b6fdd07..5c56a970d8 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001-2018 Free Software Foundation, Inc. + Copyright (C) 2001-2020 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -39,14 +39,14 @@ #include "disasm.h" #include "amd64-tdep.h" #include "i387-tdep.h" -#include "x86-xstate.h" +#include "gdbsupport/x86-xstate.h" #include #include "target-descriptions.h" #include "arch/amd64.h" #include "producer.h" #include "ax.h" #include "ax-gdb.h" -#include "common/byte-vector.h" +#include "gdbsupport/byte-vector.h" #include "osabi.h" #include "x86-tdep.h" @@ -541,17 +541,108 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2) static void amd64_classify (struct type *type, enum amd64_reg_class theclass[2]); -/* Return non-zero if TYPE is a non-POD structure or union type. */ +/* Return true if TYPE is a structure or union with unaligned fields. */ -static int -amd64_non_pod_p (struct type *type) +static bool +amd64_has_unaligned_fields (struct type *type) { - /* ??? A class with a base class certainly isn't POD, but does this - catch all non-POD structure types? */ - if (TYPE_CODE (type) == TYPE_CODE_STRUCT && TYPE_N_BASECLASSES (type) > 0) - return 1; + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + for (int i = 0; i < TYPE_NFIELDS (type); i++) + { + struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); + int bitpos = TYPE_FIELD_BITPOS (type, i); + int align = type_align(subtype); + + /* Ignore static fields, empty fields (for example nested + empty structures), and bitfields (these are handled by + the caller). */ + if (field_is_static (&TYPE_FIELD (type, i)) + || (TYPE_FIELD_BITSIZE (type, i) == 0 + && TYPE_LENGTH (subtype) == 0) + || TYPE_FIELD_PACKED (type, i)) + continue; - return 0; + if (bitpos % 8 != 0) + return true; + + int bytepos = bitpos / 8; + if (bytepos % align != 0) + return true; + + if (amd64_has_unaligned_fields (subtype)) + return true; + } + } + + return false; +} + +/* Classify field I of TYPE starting at BITOFFSET according to the rules for + structures and union types, and store the result in THECLASS. */ + +static void +amd64_classify_aggregate_field (struct type *type, int i, + enum amd64_reg_class theclass[2], + unsigned int bitoffset) +{ + struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); + int bitpos = bitoffset + TYPE_FIELD_BITPOS (type, i); + int pos = bitpos / 64; + enum amd64_reg_class subclass[2]; + int bitsize = TYPE_FIELD_BITSIZE (type, i); + int endpos; + + if (bitsize == 0) + bitsize = TYPE_LENGTH (subtype) * 8; + endpos = (bitpos + bitsize - 1) / 64; + + /* Ignore static fields, or empty fields, for example nested + empty structures.*/ + if (field_is_static (&TYPE_FIELD (type, i)) || bitsize == 0) + return; + + if (TYPE_CODE (subtype) == TYPE_CODE_STRUCT + || TYPE_CODE (subtype) == TYPE_CODE_UNION) + { + /* Each field of an object is classified recursively. */ + int j; + for (j = 0; j < TYPE_NFIELDS (subtype); j++) + amd64_classify_aggregate_field (subtype, j, theclass, bitpos); + return; + } + + gdb_assert (pos == 0 || pos == 1); + + amd64_classify (subtype, subclass); + theclass[pos] = amd64_merge_classes (theclass[pos], subclass[0]); + if (bitsize <= 64 && pos == 0 && endpos == 1) + /* This is a bit of an odd case: We have a field that would + normally fit in one of the two eightbytes, except that + it is placed in a way that this field straddles them. + This has been seen with a structure containing an array. + + The ABI is a bit unclear in this case, but we assume that + this field's class (stored in subclass[0]) must also be merged + into class[1]. In other words, our field has a piece stored + in the second eight-byte, and thus its class applies to + the second eight-byte as well. + + In the case where the field length exceeds 8 bytes, + it should not be necessary to merge the field class + into class[1]. As LEN > 8, subclass[1] is necessarily + different from AMD64_NO_CLASS. If subclass[1] is equal + to subclass[0], then the normal class[1]/subclass[1] + merging will take care of everything. For subclass[1] + to be different from subclass[0], I can only see the case + where we have a SSE/SSEUP or X87/X87UP pair, which both + use up all 16 bytes of the aggregate, and are already + handled just fine (because each portion sits on its own + 8-byte). */ + theclass[1] = amd64_merge_classes (theclass[1], subclass[0]); + if (pos == 0) + theclass[1] = amd64_merge_classes (theclass[1], subclass[1]); } /* Classify TYPE according to the rules for aggregate (structures and @@ -560,10 +651,9 @@ amd64_non_pod_p (struct type *type) static void amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2]) { - /* 1. If the size of an object is larger than two eightbytes, or in - C++, is a non-POD structure or union type, or contains + /* 1. If the size of an object is larger than two eightbytes, or it has unaligned fields, it has class memory. */ - if (TYPE_LENGTH (type) > 16 || amd64_non_pod_p (type)) + if (TYPE_LENGTH (type) > 16 || amd64_has_unaligned_fields (type)) { theclass[0] = theclass[1] = AMD64_MEMORY; return; @@ -595,53 +685,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2]) || TYPE_CODE (type) == TYPE_CODE_UNION); for (i = 0; i < TYPE_NFIELDS (type); i++) - { - struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); - int pos = TYPE_FIELD_BITPOS (type, i) / 64; - enum amd64_reg_class subclass[2]; - int bitsize = TYPE_FIELD_BITSIZE (type, i); - int endpos; - - if (bitsize == 0) - bitsize = TYPE_LENGTH (subtype) * 8; - endpos = (TYPE_FIELD_BITPOS (type, i) + bitsize - 1) / 64; - - /* Ignore static fields, or empty fields, for example nested - empty structures.*/ - if (field_is_static (&TYPE_FIELD (type, i)) || bitsize == 0) - continue; - - gdb_assert (pos == 0 || pos == 1); - - amd64_classify (subtype, subclass); - theclass[pos] = amd64_merge_classes (theclass[pos], subclass[0]); - if (bitsize <= 64 && pos == 0 && endpos == 1) - /* This is a bit of an odd case: We have a field that would - normally fit in one of the two eightbytes, except that - it is placed in a way that this field straddles them. - This has been seen with a structure containing an array. - - The ABI is a bit unclear in this case, but we assume that - this field's class (stored in subclass[0]) must also be merged - into class[1]. In other words, our field has a piece stored - in the second eight-byte, and thus its class applies to - the second eight-byte as well. - - In the case where the field length exceeds 8 bytes, - it should not be necessary to merge the field class - into class[1]. As LEN > 8, subclass[1] is necessarily - different from AMD64_NO_CLASS. If subclass[1] is equal - to subclass[0], then the normal class[1]/subclass[1] - merging will take care of everything. For subclass[1] - to be different from subclass[0], I can only see the case - where we have a SSE/SSEUP or X87/X87UP pair, which both - use up all 16 bytes of the aggregate, and are already - handled just fine (because each portion sits on its own - 8-byte). */ - theclass[1] = amd64_merge_classes (theclass[1], subclass[0]); - if (pos == 0) - theclass[1] = amd64_merge_classes (theclass[1], subclass[1]); - } + amd64_classify_aggregate_field (type, i, theclass, 0); } /* 4. Then a post merger cleanup is done: */ @@ -954,6 +998,9 @@ if (return_method == return_method_struct) offset = 8; break; + case AMD64_NO_CLASS: + continue; + default: gdb_assert (!"Unexpected register class."); } @@ -1418,7 +1465,7 @@ fixup_displaced_copy (struct gdbarch *gdbarch, } } -struct displaced_step_closure * +displaced_step_closure_up amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs) @@ -1427,8 +1474,8 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to continually watch for running off the end of the buffer. */ int fixup_sentinel_space = len; - amd64_displaced_step_closure *dsc - = new amd64_displaced_step_closure (len + fixup_sentinel_space); + std::unique_ptr dsc + (new amd64_displaced_step_closure (len + fixup_sentinel_space)); gdb_byte *buf = &dsc->insn_buf[0]; struct amd64_insn *details = &dsc->insn_details; @@ -1453,7 +1500,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, /* Modify the insn to cope with the address where it will be executed from. In particular, handle any rip-relative addressing. */ - fixup_displaced_copy (gdbarch, dsc, from, to, regs); + fixup_displaced_copy (gdbarch, dsc.get (), from, to, regs); write_memory (to, buf, len); @@ -1464,7 +1511,8 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, displaced_step_dump_bytes (gdb_stdlog, buf, len); } - return dsc; + /* This is a work around for a problem with g++ 4.8. */ + return displaced_step_closure_up (dsc.release ()); } static int @@ -2581,16 +2629,15 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); *this_cache = cache; - TRY + try { amd64_frame_cache_1 (this_frame, cache); } - CATCH (ex, RETURN_MASK_ERROR) + catch (const gdb_exception_error &ex) { if (ex.error != NOT_AVAILABLE_ERROR) - throw_exception (ex); + throw; } - END_CATCH return cache; } @@ -2699,7 +2746,7 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); - TRY + try { get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8; @@ -2713,12 +2760,11 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache->base_p = 1; } - CATCH (ex, RETURN_MASK_ERROR) + catch (const gdb_exception_error &ex) { if (ex.error != NOT_AVAILABLE_ERROR) - throw_exception (ex); + throw; } - END_CATCH *this_cache = cache; return cache; @@ -2876,7 +2922,7 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); *this_cache = cache; - TRY + try { /* Cache base will be %esp plus cache->sp_offset (-8). */ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); @@ -2894,12 +2940,11 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache->base_p = 1; } - CATCH (ex, RETURN_MASK_ERROR) + catch (const gdb_exception_error &ex) { if (ex.error != NOT_AVAILABLE_ERROR) - throw_exception (ex); + throw; } - END_CATCH return cache; } @@ -3107,15 +3152,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL) { - const struct tdesc_feature *feature = - tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments"); - struct tdesc_arch_data *tdesc_data_segments = - (struct tdesc_arch_data *) info.tdep_info; - - tdesc_numbered_register (feature, tdesc_data_segments, - AMD64_FSBASE_REGNUM, "fs_base"); - tdesc_numbered_register (feature, tdesc_data_segments, - AMD64_GSBASE_REGNUM, "gs_base"); + tdep->fsbase_regnum = AMD64_FSBASE_REGNUM; } if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys") != NULL) @@ -3298,36 +3335,14 @@ amd64_target_description (uint64_t xcr0, bool segments) return *tdesc; } +void _initialize_amd64_tdep (); void -_initialize_amd64_tdep (void) +_initialize_amd64_tdep () { gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_NONE, amd64_none_init_abi); gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32, GDB_OSABI_NONE, amd64_x32_none_init_abi); - -#if GDB_SELF_TEST - struct - { - const char *xml; - uint64_t mask; - } xml_masks[] = { - { "i386/amd64.xml", X86_XSTATE_SSE_MASK }, - { "i386/amd64-avx.xml", X86_XSTATE_AVX_MASK }, - { "i386/amd64-mpx.xml", X86_XSTATE_MPX_MASK }, - { "i386/amd64-avx-mpx.xml", X86_XSTATE_AVX_MPX_MASK }, - { "i386/amd64-avx-avx512.xml", X86_XSTATE_AVX_AVX512_MASK }, - { "i386/amd64-avx-mpx-avx512-pku.xml", - X86_XSTATE_AVX_MPX_AVX512_PKU_MASK }, - }; - - for (auto &a : xml_masks) - { - auto tdesc = amd64_target_description (a.mask, true); - - selftests::record_xml_tdesc (a.xml, tdesc); - } -#endif /* GDB_SELF_TEST */ }