This patch will need to be submitted and accepted for master before I can take it for scarthgap.
Thanks, Steve On Fri, May 24, 2024 at 1:12 PM Mark Hatle via lists.openembedded.org <mark.hatle=amd....@lists.openembedded.org> wrote: > > Code backported from binutils development tree. > > aarch64: Remove asserts from operand qualifier decoders [PR31595] > > Given that the disassembler should never abort when decoding > (potentially random) data, assertion statements in the > `get_*reg_qualifier_from_value' function family prove problematic. > > ... > > Signed-off-by: Mark Hatle <mark.ha...@amd.com> > --- > .../binutils/binutils-2.42.inc | 1 + > ...sserts-from-operand-qualifier-decode.patch | 382 ++++++++++++++++++ > 2 files changed, 383 insertions(+) > create mode 100644 > meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch > > diff --git a/meta/recipes-devtools/binutils/binutils-2.42.inc > b/meta/recipes-devtools/binutils/binutils-2.42.inc > index 3b6f47d4ce..d2f49560f3 100644 > --- a/meta/recipes-devtools/binutils/binutils-2.42.inc > +++ b/meta/recipes-devtools/binutils/binutils-2.42.inc > @@ -36,5 +36,6 @@ SRC_URI = "\ > file://0013-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch \ > file://0014-Remove-duplicate-pe-dll.o-entry-deom-targ_extra_ofil.patch \ > file://0015-gprofng-change-use-of-bignum-to-bigint.patch \ > + file://0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch \ > " > S = "${WORKDIR}/git" > diff --git > a/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch > > b/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch > new file mode 100644 > index 0000000000..7b52425a38 > --- /dev/null > +++ > b/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch > @@ -0,0 +1,382 @@ > +From 5b1c70bfe0d8f84dc28237d6150b7b9d57c791a8 Mon Sep 17 00:00:00 2001 > +From: Victor Do Nascimento <victor.donascime...@arm.com> > +Date: Tue, 16 Apr 2024 11:49:15 +0100 > +Subject: [PATCH] aarch64: Remove asserts from operand qualifier decoders > + [PR31595] > + > +Given that the disassembler should never abort when decoding > +(potentially random) data, assertion statements in the > +`get_*reg_qualifier_from_value' function family prove problematic. > + > +Consider the random 32-bit word W, encoded in a data segment and > +encountered on execution of `objdump -D <obj_name>'. > + > +If: > + > + (W & ~opcode_mask) == valid instruction > + > +Then before `print_insn_aarch64_word' has a chance to report the > +instruction as potentially undefined, an attempt will be made to have > +the qualifiers for the instruction's register operands (if any) > +decoded. If the relevant bits do not map onto a valid qualifier for > +the matched instruction-like word, an abort will be triggered and the > +execution of objdump aborted. > + > +As this scenario is perfectly feasible and, in light of the fact that > +objdump must successfully decode all sections of a given object file, > +it is not appropriate to assert in this family of functions. > + > +Therefore, we add a new pseudo-qualifier `AARCH64_OPND_QLF_ERR' for > +handling invalid qualifier-associated values and re-purpose the > +assertion conditions in qualifier-retrieving functions to be the > +predicate guarding the returning of the calculated qualifier type. > +If the predicate fails, we return this new qualifier and allow the > +caller to handle the error as appropriate. > + > +As these functions are called either from within > +`aarch64_extract_operand' or `do_special_decoding', both of which are > +expected to return non-zero values, it suffices that callers return > +zero upon encountering `AARCH64_OPND_QLF_ERR'. > + > +Ar present the error presented in the hypothetical scenario has been > +encountered in `get_sreg_qualifier_from_value', but the change is made > +to the whole family to keep the interface consistent. > + > +Bug: https://sourceware.org/PR31595 > + > +Upstream-Status: Backport [commit 2601b201e95ea0edab89342ee7137c74e88a8a79] > + > +Signed-off-by: Mark Hatle <mark.ha...@amd.com> > +--- > + .../testsuite/binutils-all/aarch64/illegal.d | 1 + > + .../testsuite/binutils-all/aarch64/illegal.s | 3 + > + include/opcode/aarch64.h | 3 + > + opcodes/aarch64-dis.c | 98 +++++++++++++++---- > + 4 files changed, 87 insertions(+), 18 deletions(-) > + > +diff --git a/binutils/testsuite/binutils-all/aarch64/illegal.d > b/binutils/testsuite/binutils-all/aarch64/illegal.d > +index 4b90a1d9f39..b69318aec85 100644 > +--- a/binutils/testsuite/binutils-all/aarch64/illegal.d > ++++ b/binutils/testsuite/binutils-all/aarch64/illegal.d > +@@ -8,5 +8,6 @@ Disassembly of section \.text: > + > + 0+000 <.*>: > + [ ]+0:[ ]+68ea18cc[ ]+.inst[ ]+0x68ea18cc ; undefined > ++[ ]+4:[ ]+9dc39839[ ]+.inst[ ]+0x9dc39839 ; undefined > + #pass > + > +diff --git a/binutils/testsuite/binutils-all/aarch64/illegal.s > b/binutils/testsuite/binutils-all/aarch64/illegal.s > +index 216cbe6f265..43668c6db55 100644 > +--- a/binutils/testsuite/binutils-all/aarch64/illegal.s > ++++ b/binutils/testsuite/binutils-all/aarch64/illegal.s > +@@ -4,4 +4,7 @@ > + # ldpsw x12, x6, [x6],#-8 ; illegal because one of the dest regs is > also the address reg > + .inst 0x68ea18cc > + > ++ # illegal, resembles the opcode `ldapur' with invalid qualifier bits > ++ .inst 0x9dc39839 > ++ > + # FIXME: Add more illegal instructions here. > +diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h > +index 2fca9528c20..e8fe93ef127 100644 > +--- a/include/opcode/aarch64.h > ++++ b/include/opcode/aarch64.h > +@@ -894,6 +894,9 @@ enum aarch64_opnd_qualifier > + /* Special qualifier helping retrieve qualifier information during the > + decoding time (currently not in use). */ > + AARCH64_OPND_QLF_RETRIEVE, > ++ > ++ /* Special qualifier used for indicating error in qualifier retrieval. */ > ++ AARCH64_OPND_QLF_ERR, > + }; > + > + /* Instruction class. */ > +diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c > +index 96f42ae862a..b70e6da9eb7 100644 > +--- a/opcodes/aarch64-dis.c > ++++ b/opcodes/aarch64-dis.c > +@@ -219,9 +219,10 @@ static inline enum aarch64_opnd_qualifier > + get_greg_qualifier_from_value (aarch64_insn value) > + { > + enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value; > +- assert (value <= 0x1 > +- && aarch64_get_qualifier_standard_value (qualifier) == value); > +- return qualifier; > ++ if (value <= 0x1 > ++ && aarch64_get_qualifier_standard_value (qualifier) == value) > ++ return qualifier; > ++ return AARCH64_OPND_QLF_ERR; > + } > + > + /* Given VALUE, return qualifier for a vector register. This does not > support > +@@ -237,9 +238,10 @@ get_vreg_qualifier_from_value (aarch64_insn value) > + if (qualifier >= AARCH64_OPND_QLF_V_2H) > + qualifier += 1; > + > +- assert (value <= 0x8 > +- && aarch64_get_qualifier_standard_value (qualifier) == value); > +- return qualifier; > ++ if (value <= 0x8 > ++ && aarch64_get_qualifier_standard_value (qualifier) == value) > ++ return qualifier; > ++ return AARCH64_OPND_QLF_ERR; > + } > + > + /* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */ > +@@ -248,9 +250,10 @@ get_sreg_qualifier_from_value (aarch64_insn value) > + { > + enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value; > + > +- assert (value <= 0x4 > +- && aarch64_get_qualifier_standard_value (qualifier) == value); > +- return qualifier; > ++ if (value <= 0x4 > ++ && aarch64_get_qualifier_standard_value (qualifier) == value) > ++ return qualifier; > ++ return AARCH64_OPND_QLF_ERR; > + } > + > + /* Given the instruction in *INST which is probably half way through the > +@@ -263,13 +266,17 @@ get_expected_qualifier (const aarch64_inst *inst, int > i) > + { > + aarch64_opnd_qualifier_seq_t qualifiers; > + /* Should not be called if the qualifier is known. */ > +- assert (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL); > +- int invalid_count; > +- if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list, > +- i, qualifiers, &invalid_count)) > +- return qualifiers[i]; > ++ if (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL) > ++ { > ++ int invalid_count; > ++ if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list, > ++ i, qualifiers, &invalid_count)) > ++ return qualifiers[i]; > ++ else > ++ return AARCH64_OPND_QLF_NIL; > ++ } > + else > +- return AARCH64_OPND_QLF_NIL; > ++ return AARCH64_OPND_QLF_ERR; > + } > + > + /* Operand extractors. */ > +@@ -355,6 +362,8 @@ aarch64_ext_reglane (const aarch64_operand *self, > aarch64_opnd_info *info, > + aarch64_insn value = extract_field (FLD_imm4_11, code, 0); > + /* Depend on AARCH64_OPND_Ed to determine the qualifier. */ > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); > + info->reglane.index = value >> shift; > + } > +@@ -374,6 +383,8 @@ aarch64_ext_reglane (const aarch64_operand *self, > aarch64_opnd_info *info, > + if (pos > 3) > + return false; > + info->qualifier = get_sreg_qualifier_from_value (pos); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + info->reglane.index = (unsigned) (value >> 1); > + } > + } > +@@ -381,6 +392,8 @@ aarch64_ext_reglane (const aarch64_operand *self, > aarch64_opnd_info *info, > + { > + /* Need information in other operand(s) to help decoding. */ > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + switch (info->qualifier) > + { > + case AARCH64_OPND_QLF_S_4B: > +@@ -405,6 +418,8 @@ aarch64_ext_reglane (const aarch64_operand *self, > aarch64_opnd_info *info, > + > + /* Need information in other operand(s) to help decoding. */ > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + switch (info->qualifier) > + { > + case AARCH64_OPND_QLF_S_H: > +@@ -644,9 +659,15 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand > *self ATTRIBUTE_UNUSED, > + 1xxx 1 2D */ > + info->qualifier = > + get_vreg_qualifier_from_value ((pos << 1) | (int) Q); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return false; > + } > + else > +- info->qualifier = get_sreg_qualifier_from_value (pos); > ++ { > ++ info->qualifier = get_sreg_qualifier_from_value (pos); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > ++ } > + > + if (info->type == AARCH64_OPND_IMM_VLSR) > + /* immh <shift> > +@@ -773,6 +794,8 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand > *self ATTRIBUTE_UNUSED, > + > + /* cmode */ > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + switch (info->qualifier) > + { > + case AARCH64_OPND_QLF_NIL: > +@@ -1014,6 +1037,8 @@ aarch64_ext_ft (const aarch64_operand *self > ATTRIBUTE_UNUSED, > + if (value > 0x4) > + return false; > + info->qualifier = get_sreg_qualifier_from_value (value); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + } > + > + return true; > +@@ -1086,6 +1111,8 @@ aarch64_ext_rcpc3_addr_offset (const aarch64_operand > *self ATTRIBUTE_UNUSED, > + aarch64_operand_error *errors ATTRIBUTE_UNUSED) > + { > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + > + /* Rn */ > + info->addr.base_regno = extract_field (self->fields[0], code, 0); > +@@ -1105,6 +1132,8 @@ aarch64_ext_addr_offset (const aarch64_operand *self > ATTRIBUTE_UNUSED, > + aarch64_operand_error *errors ATTRIBUTE_UNUSED) > + { > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + > + /* Rn */ > + info->addr.base_regno = extract_field (self->fields[0], code, 0); > +@@ -1154,6 +1183,8 @@ aarch64_ext_addr_regoff (const aarch64_operand *self > ATTRIBUTE_UNUSED, > + /* Need information in other operand(s) to help achieve the decoding > + from 'S' field. */ > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + /* Get the size of the data element that is accessed, which may be > + different from that of the source register size, e.g. in strb/ldrb. > */ > + size = aarch64_get_qualifier_esize (info->qualifier); > +@@ -1172,6 +1203,8 @@ aarch64_ext_addr_simm (const aarch64_operand *self, > aarch64_opnd_info *info, > + { > + aarch64_insn imm; > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + > + /* Rn */ > + info->addr.base_regno = extract_field (FLD_Rn, code, 0); > +@@ -1210,6 +1243,8 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, > aarch64_opnd_info *info, > + { > + int shift; > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); > + /* Rn */ > + info->addr.base_regno = extract_field (self->fields[0], code, 0); > +@@ -1228,6 +1263,8 @@ aarch64_ext_addr_simm10 (const aarch64_operand *self, > aarch64_opnd_info *info, > + aarch64_insn imm; > + > + info->qualifier = get_expected_qualifier (inst, info->idx); > ++ if (info->qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + /* Rn */ > + info->addr.base_regno = extract_field (self->fields[0], code, 0); > + /* simm10 */ > +@@ -2467,6 +2504,8 @@ decode_sizeq (aarch64_inst *inst) > + if (mask == 0x7) > + { > + inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value); > ++ if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + return 1; > + } > + > +@@ -2649,6 +2688,8 @@ do_special_decoding (aarch64_inst *inst) > + idx = select_operand_for_sf_field_coding (inst->opcode); > + value = extract_field (FLD_sf, inst->value, 0); > + inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); > ++ if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + if ((inst->opcode->flags & F_N) > + && extract_field (FLD_N, inst->value, 0) != value) > + return 0; > +@@ -2659,6 +2700,8 @@ do_special_decoding (aarch64_inst *inst) > + idx = select_operand_for_sf_field_coding (inst->opcode); > + value = extract_field (FLD_lse_sz, inst->value, 0); > + inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); > ++ if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + } > + /* rcpc3 'size' field. */ > + if (inst->opcode->flags & F_RCPC3_SIZE) > +@@ -2670,12 +2713,18 @@ do_special_decoding (aarch64_inst *inst) > + { > + if (aarch64_operands[inst->operands[i].type].op_class > + == AARCH64_OPND_CLASS_INT_REG) > +- inst->operands[i].qualifier = get_greg_qualifier_from_value > (value & 1); > ++ { > ++ inst->operands[i].qualifier = get_greg_qualifier_from_value > (value & 1); > ++ if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > ++ } > + else if (aarch64_operands[inst->operands[i].type].op_class > + == AARCH64_OPND_CLASS_FP_REG) > + { > + value += (extract_field (FLD_opc1, inst->value, 0) << 2); > + inst->operands[i].qualifier = get_sreg_qualifier_from_value > (value); > ++ if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + } > + } > + } > +@@ -2709,7 +2758,11 @@ do_special_decoding (aarch64_inst *inst) > + /* For most related instruciton, the 'size' field is fully available > for > + operand encoding. */ > + if (mask == 0x3) > +- inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value); > ++ { > ++ inst->operands[idx].qualifier = get_sreg_qualifier_from_value > (value); > ++ if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > ++ } > + else > + { > + get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list, > +@@ -2744,6 +2797,9 @@ do_special_decoding (aarch64_inst *inst) > + Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask); > + inst->operands[0].qualifier = > + get_vreg_qualifier_from_value ((num << 1) | Q); > ++ if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > ++ > + } > + > + if ((inst->opcode->flags & F_OPD_SIZE) && inst->opcode->iclass == > sve2_urqvs) > +@@ -2753,7 +2809,11 @@ do_special_decoding (aarch64_inst *inst) > + inst->opcode->mask); > + inst->operands[0].qualifier > + = get_vreg_qualifier_from_value (1 + (size << 1)); > ++ if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + inst->operands[2].qualifier = get_sreg_qualifier_from_value (size); > ++ if (inst->operands[2].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + } > + > + if (inst->opcode->flags & F_GPRSIZE_IN_Q) > +@@ -2772,6 +2832,8 @@ do_special_decoding (aarch64_inst *inst) > + assert (idx == 0 || idx == 1); > + value = extract_field (FLD_Q, inst->value, 0); > + inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); > ++ if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) > ++ return 0; > + } > + > + if (inst->opcode->flags & F_LDS_SIZE) > +-- > +2.34.1 > + > -- > 2.34.1 > > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#199901): https://lists.openembedded.org/g/openembedded-core/message/199901 Mute This Topic: https://lists.openembedded.org/mt/106288403/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-