X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Famd64-tdep.c;h=0ce9fbc2997313cdeff434d92851766a17dc510f;hb=1ee1a363454d88a87ad2ade7530b2a7fb670021e;hp=9006ec0167adab73515f8cbc5347938c97590a89;hpb=745ff14e6e1b88f04eb447d4883fab81650f745f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 9006ec0167..0ce9fbc299 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001-2019 Free Software Foundation, Inc. + Copyright (C) 2001-2020 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -546,19 +546,19 @@ static void amd64_classify (struct type *type, enum amd64_reg_class theclass[2]) static bool amd64_has_unaligned_fields (struct type *type) { - if (TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) + if (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION) { - for (int i = 0; i < TYPE_NFIELDS (type); i++) + for (int i = 0; i < type->num_fields (); i++) { - struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); + struct type *subtype = check_typedef (type->field (i).type ()); 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)) + if (field_is_static (&type->field (i)) || (TYPE_FIELD_BITSIZE (type, i) == 0 && TYPE_LENGTH (subtype) == 0) || TYPE_FIELD_PACKED (type, i)) @@ -579,6 +579,72 @@ amd64_has_unaligned_fields (struct type *type) 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 (i).type ()); + 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 (i)) || bitsize == 0) + return; + + if (subtype->code () == TYPE_CODE_STRUCT + || subtype->code () == TYPE_CODE_UNION) + { + /* Each field of an object is classified recursively. */ + int j; + for (j = 0; j < subtype->num_fields (); 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 arrays) and union types, and store the result in CLASS. */ @@ -601,7 +667,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2]) calculated according to the classes of the fields in the eightbyte: */ - if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + if (type->code () == TYPE_CODE_ARRAY) { struct type *subtype = check_typedef (TYPE_TARGET_TYPE (type)); @@ -615,57 +681,11 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2]) int i; /* Structure or union. */ - gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT - || 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 (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION); - 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]); - } + for (i = 0; i < type->num_fields (); i++) + amd64_classify_aggregate_field (type, i, theclass, 0); } /* 4. Then a post merger cleanup is done: */ @@ -688,7 +708,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2]) static void amd64_classify (struct type *type, enum amd64_reg_class theclass[2]) { - enum type_code code = TYPE_CODE (type); + enum type_code code = type->code (); int len = TYPE_LENGTH (type); theclass[0] = theclass[1] = AMD64_NO_CLASS; @@ -1445,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) @@ -1454,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; @@ -1480,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); @@ -1491,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 @@ -2341,6 +2362,9 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, pushq %rbp 0x55 movl %esp, %ebp 0x89 0xe5 (or 0x8b 0xec) + The `endbr64` instruction can be found before these sequences, and will be + skipped if found. + Any function that doesn't start with one of these sequences will be assumed to have no prologue and thus no valid frame pointer in %rbp. */ @@ -2351,6 +2375,8 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, struct amd64_frame_cache *cache) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + /* The `endbr64` instruction. */ + static const gdb_byte endbr64[4] = { 0xf3, 0x0f, 0x1e, 0xfa }; /* There are two variations of movq %rsp, %rbp. */ static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 }; static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec }; @@ -2371,6 +2397,20 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, op = read_code_unsigned_integer (pc, 1, byte_order); + /* Check for the `endbr64` instruction, skip it if found. */ + if (op == endbr64[0]) + { + read_code (pc + 1, buf, 3); + + if (memcmp (buf, &endbr64[1], 3) == 0) + pc += 4; + + op = read_code_unsigned_integer (pc, 1, byte_order); + } + + if (current_pc <= pc) + return current_pc; + if (op == 0x55) /* pushq %rbp */ { /* Take into account that we've executed the `pushq %rbp' that @@ -3314,8 +3354,9 @@ 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);