From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2124) id 1E9AC3857C79; Mon, 4 Dec 2023 17:33:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1E9AC3857C79 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Nick Clifton To: bfd-cvs@sourceware.org Subject: [binutils-gdb] s390: Support for jump visualization in disassembly X-Act-Checkin: binutils-gdb X-Git-Author: Jens Remus X-Git-Refname: refs/heads/master X-Git-Oldrev: 86b775c51597816dcab29dd37522b505d043dc51 X-Git-Newrev: c5306fed7d40717d9866524fb346ac2599f9769d Message-Id: <20231204173349.1E9AC3857C79@sourceware.org> Date: Mon, 4 Dec 2023 17:33:49 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Dec 2023 17:33:49 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dc5306fed7d40= 717d9866524fb346ac2599f9769d commit c5306fed7d40717d9866524fb346ac2599f9769d Author: Jens Remus Date: Wed Nov 29 21:44:34 2023 +0100 s390: Support for jump visualization in disassembly =20 Add support for jump visualization for the s390 architecture in disassembly: =20 objdump -d --visualize-jumps ... =20 Annotate the (conditional) jump and branch relative instructions with information required for jump visualization: - jump: Unconditional jump / branch relative. - condjump: Conditional jump / branch relative. - jumpsr: Jump / branch relative to subroutine. =20 Unconditional jump and branch relative instructions are annotated as jump. Conditional jump and branch relative instructions, jump / branch relative on count/index, and compare and jump / branch relative instructions are annotated as condjump. Jump and save (jas, jasl) and branch relative and save (bras, brasl) instructions are annotated as jumpsr (jump to subroutine). =20 Provide instruction information required for jump visualization during disassembly. The instruction type is provided after determining the opcode. For non-code it is set to dis_noninsn. Otherwise it defaults to dis_nonbranch. No annotation is done for data reference instructions (i.e. instruction types dis_dref and dis_dref2). Note that the instruction type needs to be provided before printing of the instruction, as it is used in print_address_func() to translate the argument value into an address if it is assumed to be a PC-relative offset. Note that this is never the case on s390, as print_address_func() is only called with addresses and never with offsets. The target of the (conditional) jump and branch relative instructions is provided during print, when the PC relative operand is decoded. =20 include/ * opcode/s390.h: Define opcode flags to annotate instruction class information for jump visualization: S390_INSTR_FLAG_CLASS_BRANCH, S390_INSTR_FLAG_CLASS_RELATIVE, S390_INSTR_FLAG_CLASS_CONDITIONAL, and S390_INSTR_FLAG_CLASS_SUBROUTINE. Define opcode flags mask S390_INSTR_FLAG_CLASS_MASK for above instruction class information. Define helpers for common instruction class flag combinations: S390_INSTR_FLAGS_CLASS_JUMP, S390_INSTR_FLAGS_CLASS_CONDJUMP, and S390_INSTR_FLAGS_CLASS_JUMPSR. =20 opcodes/ * s390-mkopc.c: Add opcode flags to annotate information for jump visualization: jump, condjump, and jumpsr. * s390-opc.txt: Annotate (conditional) jump and branch relative instructions with information for jump visualization. * s390-dis.c (print_insn_s390, s390_print_insn_with_opcode): Provide instruction information for jump visualization. =20 Signed-off-by: Jens Remus Reviewed-by: Andreas Krebbel Diff: --- binutils/NEWS | 2 ++ include/opcode/s390.h | 25 ++++++++++++++-- opcodes/s390-dis.c | 36 +++++++++++++++++++++- opcodes/s390-mkopc.c | 12 ++++++++ opcodes/s390-opc.txt | 82 +++++++++++++++++++++++++----------------------= ---- 5 files changed, 112 insertions(+), 45 deletions(-) diff --git a/binutils/NEWS b/binutils/NEWS index 3bf3b568179..73df7053be4 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -17,6 +17,8 @@ * objcopy --set-section-flags now supports "large" to set SHF_X86_64_LARGE for ELF x86-64 objects. =20 +* objdump --visualize-jumps is now supported on s390 architecture. + Changes in 2.41: =20 * The MIPS port now supports the Sony Interactive Entertainment Allegrex diff --git a/include/opcode/s390.h b/include/opcode/s390.h index f787b901632..d540e1dfd00 100644 --- a/include/opcode/s390.h +++ b/include/opcode/s390.h @@ -48,14 +48,35 @@ enum s390_opcode_cpu_val S390_OPCODE_MAXCPU }; =20 -/* Instruction specific flags. */ +/* Values defined for the flags field of a struct s390_opcode. */ + +/* Last one or two instruction operands are optional. */ #define S390_INSTR_FLAG_OPTPARM 0x1 #define S390_INSTR_FLAG_OPTPARM2 0x2 =20 +/* Instruction requires a specific facility. */ #define S390_INSTR_FLAG_HTM 0x4 #define S390_INSTR_FLAG_VX 0x8 #define S390_INSTR_FLAG_FACILITY_MASK 0xc =20 +/* Instruction annotations for jump visualization. */ +#define S390_INSTR_FLAG_CLASS_BRANCH 0x10 +#define S390_INSTR_FLAG_CLASS_RELATIVE 0x20 +#define S390_INSTR_FLAG_CLASS_CONDITIONAL 0x40 +#define S390_INSTR_FLAG_CLASS_SUBROUTINE 0x80 +#define S390_INSTR_FLAG_CLASS_MASK 0xf0 + +#define S390_INSTR_FLAGS_CLASS_JUMP \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE) + +#define S390_INSTR_FLAGS_CLASS_CONDJUMP \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE \ + | S390_INSTR_FLAG_CLASS_CONDITIONAL) + +#define S390_INSTR_FLAGS_CLASS_JUMPSR \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE \ + | S390_INSTR_FLAG_CLASS_SUBROUTINE) + /* The opcode table is an array of struct s390_opcode. */ =20 struct s390_opcode @@ -101,8 +122,6 @@ extern const int s390_num_opcodes; extern const struct s390_opcode s390_opformats[]; extern const int s390_num_opformats; =20 -/* Values defined for the flags field of a struct s390_opcode. */ - /* The operands table is an array of struct s390_operand. */ =20 struct s390_operand diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c index 2a3b4c21c3a..8c8a98c4e24 100644 --- a/opcodes/s390-dis.c +++ b/opcodes/s390-dis.c @@ -26,6 +26,7 @@ #include "opintl.h" #include "opcode/s390.h" #include "libiberty.h" +#include "dis-asm.h" =20 static int opc_index[256]; static int current_arch_mask =3D 0; @@ -259,9 +260,14 @@ s390_print_insn_with_opcode (bfd_vma memaddr, } else if (flags & S390_OPERAND_PCREL) { + bfd_vma target =3D memaddr + val.i + val.i; + + /* Provide info for jump visualization. May be evaluated by p_a_f(). = */ + info->target =3D target; + info->fprintf_styled_func (info->stream, dis_style_text, "%c", separator); - info->print_address_func (memaddr + val.i + val.i, info); + info->print_address_func (target, info); } else if (flags & S390_OPERAND_SIGNED) { @@ -332,6 +338,14 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_i= nfo *info) /* The output looks better if we put 6 bytes on a line. */ info->bytes_per_line =3D 6; =20 + /* Set some defaults for the insn info. */ + info->insn_info_valid =3D 0; + info->branch_delay_insns =3D 0; + info->data_size =3D 0; + info->insn_type =3D dis_nonbranch; + info->target =3D 0; + info->target2 =3D 0; + /* Every S390 instruction is max 6 bytes long. */ memset (buffer, 0, 6); status =3D info->read_memory_func (memaddr, buffer, 6, info); @@ -373,6 +387,23 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_i= nfo *info) =20 if (opcode !=3D NULL) { + /* Provide info for jump visualization. Must be done before print. */ + switch (opcode->flags & S390_INSTR_FLAG_CLASS_MASK) + { + case S390_INSTR_FLAGS_CLASS_JUMP: + info->insn_type =3D dis_branch; + break; + case S390_INSTR_FLAGS_CLASS_CONDJUMP: + info->insn_type =3D dis_condbranch; + break; + case S390_INSTR_FLAGS_CLASS_JUMPSR: + info->insn_type =3D dis_jsr; + break; + default: + info->insn_type =3D dis_nonbranch; + } + info->insn_info_valid =3D 1; + /* The instruction is valid. Print it and return its size. */ s390_print_insn_with_opcode (memaddr, info, buffer, opcode); return opsize; @@ -394,6 +425,9 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_in= fo *info) if (bytes_to_dump =3D=3D 0) return 0; =20 + info->insn_type =3D dis_noninsn; + info->insn_info_valid =3D 1; + /* Fall back to hex print. */ switch (bytes_to_dump) { diff --git a/opcodes/s390-mkopc.c b/opcodes/s390-mkopc.c index 48b1c1e0cdb..5f921ee0628 100644 --- a/opcodes/s390-mkopc.c +++ b/opcodes/s390-mkopc.c @@ -431,6 +431,18 @@ main (void) && (str[2] =3D=3D 0 || str[2] =3D=3D ',')) { flag_bits |=3D S390_INSTR_FLAG_VX; str +=3D 2; + } else if (strncmp (str, "jump", 7) =3D=3D 0 + && (str[4] =3D=3D 0 || str[4] =3D=3D ',')) { + flag_bits |=3D S390_INSTR_FLAGS_CLASS_JUMP; + str +=3D 4; + } else if (strncmp (str, "condjump", 7) =3D=3D 0 + && (str[8] =3D=3D 0 || str[8] =3D=3D ',')) { + flag_bits |=3D S390_INSTR_FLAGS_CLASS_CONDJUMP; + str +=3D 8; + } else if (strncmp (str, "jumpsr", 7) =3D=3D 0 + && (str[6] =3D=3D 0 || str[6] =3D=3D ',')) { + flag_bits |=3D S390_INSTR_FLAGS_CLASS_JUMPSR; + str +=3D 6; } else { fprintf (stderr, "Couldn't parse flags string %s\n", flags_string); diff --git a/opcodes/s390-opc.txt b/opcodes/s390-opc.txt index 853758b96aa..0fd04ee2770 100644 --- a/opcodes/s390-opc.txt +++ b/opcodes/s390-opc.txt @@ -245,15 +245,15 @@ d7 xc SS_L0RDRD "exclusive OR" g5 esa,zarch 17 xr RR_RR "exclusive OR" g5 esa,zarch f8 zap SS_LLRDRD "zero and add" g5 esa,zarch a70a ahi RI_RI "add halfword immediate" g5 esa,zarch -84 brxh RSI_RRP "branch relative on index high" g5 esa,zarch -84 jxh RSI_RRP "branch relative on index high" g5 esa,zarch -85 brxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch -85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch -a705 bras RI_RP "branch relative and save" g5 esa,zarch -a705 jas RI_RP "branch relative and save" g5 esa,zarch -a704 brc RI_UP "branch relative on condition" g5 esa,zarch -a706 brct RI_RP "branch relative on count" g5 esa,zarch -a706 jct RI_RP "branch relative on count" g5 esa,zarch +84 brxh RSI_RRP "branch relative on index high" g5 esa,zarch condjump +84 jxh RSI_RRP "branch relative on index high" g5 esa,zarch condjump +85 brxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch cond= jump +85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch condj= ump +a705 bras RI_RP "branch relative and save" g5 esa,zarch jumpsr +a705 jas RI_RP "branch relative and save" g5 esa,zarch jumpsr +a704 brc RI_UP "branch relative on condition" g5 esa,zarch condjump +a706 brct RI_RP "branch relative on count" g5 esa,zarch condjump +a706 jct RI_RP "branch relative on count" g5 esa,zarch condjump b241 cksm RRE_RR "checksum" g5 esa,zarch a70e chi RI_RI "compare halfword immediate" g5 esa,zarch a9 clcle RS_RRRD "compare logical long extended" g5 esa,zarch @@ -272,12 +272,12 @@ a701 tml RI_RU "test under mask low" g5 esa,zarch 4700 nop RX_0RRD "no operation" g5 esa,zarch optparm 4700 b*8 RX_0RRD "conditional branch" g5 esa,zarch 47f0 b RX_0RRD "unconditional branch" g5 esa,zarch -a704 jc RI_UP "conditional jump" g5 esa,zarch +a704 jc RI_UP "conditional jump" g5 esa,zarch condjump a704 jnop RI_0P "nop jump" g5 esa,zarch -a704 j*8 RI_0P "conditional jump" g5 esa,zarch -a704 br*8 RI_0P "conditional jump" g5 esa,zarch -a7f4 j RI_0P "unconditional jump" g5 esa,zarch -a7f4 bru RI_0P "unconditional jump" g5 esa,zarch +a704 j*8 RI_0P "conditional jump" g5 esa,zarch condjump +a704 br*8 RI_0P "conditional jump" g5 esa,zarch condjump +a7f4 j RI_0P "unconditional jump" g5 esa,zarch jump +a7f4 bru RI_0P "unconditional jump" g5 esa,zarch jump b34a axbr RRE_FEFE "add extended bfp" g5 esa,zarch b31a adbr RRE_FF "add long bfp" g5 esa,zarch ed000000001a adb RXE_FRRD "add long bfp" g5 esa,zarch @@ -446,10 +446,10 @@ e3000000000b slg RXE_RRRD "subtract logical 64" z900 = zarch e3000000001b slgf RXE_RRRD "subtract logical 64<32" z900 zarch e3000000000c msg RXE_RRRD "multiply single 64" z900 zarch e3000000001c msgf RXE_RRRD "multiply single 64<32" z900 zarch -ec0000000044 brxhg RIE_RRP "branch relative on index high 64" z900 zarch -ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch -ec0000000045 brxlg RIE_RRP "branch relative on index low or equal 64" z900= zarch -ec0000000045 jxleg RIE_RRP "branch relative on index low or equal 64" z900= zarch +ec0000000044 brxhg RIE_RRP "branch relative on index high 64" z900 zarch c= ondjump +ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch co= ndjump +ec0000000045 brxlg RIE_RRP "branch relative on index low or equal 64" z900= zarch condjump +ec0000000045 jxleg RIE_RRP "branch relative on index low or equal 64" z900= zarch condjump eb0000000044 bxhg RSE_RRRD "branch on index high 64" z900 zarch eb0000000045 bxleg RSE_RRRD "branch on index low or equal 64" z900 zarch eb000000000c srlg RSE_RRRD "shift right single logical 64" z900 zarch @@ -473,18 +473,18 @@ eb000000002c stcmh RSE_RURD "store characters under m= ask high" z900 zarch eb0000000080 icmh RSE_RURD "insert characters under mask high" z900 zarch a702 tmhh RI_RU "test under mask high high" z900 zarch a703 tmhl RI_RU "test under mask high low" z900 zarch -c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch +c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch condju= mp # jlc omitted due to missing jl* (see jl*8) and not added as non-standard = jgc c004 jgnop RIL_0P "nop jump long" z900 esa,zarch -c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch +c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch condjump # jl*8 omitted due to clash with non-standard j*8 flavors jle and jlh; exi= sts as non-standard jg*8 instead -c004 br*8l RIL_0P "conditional jump long" z900 esa,zarch -c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch -c0f4 brul RIL_0P "unconditional jump long" z900 esa,zarch -c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch -c005 jasl RIL_RP "branch relative and save long" z900 esa,zarch -a707 brctg RI_RP "branch relative on count 64" z900 zarch -a707 jctg RI_RP "branch relative on count 64" z900 zarch +c004 br*8l RIL_0P "conditional jump long" z900 esa,zarch condjump +c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch jump +c0f4 brul RIL_0P "unconditional jump long" z900 esa,zarch jump +c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch jumpsr +c005 jasl RIL_RP "branch relative and save long" z900 esa,zarch jumpsr +a707 brctg RI_RP "branch relative on count 64" z900 zarch condjump +a707 jctg RI_RP "branch relative on count 64" z900 zarch condjump a709 lghi RI_RI "load halfword immediate 64" z900 zarch a70b aghi RI_RI "add halfword immediate 64" z900 zarch a70d mghi RI_RI "multiply halfword immediate 64" z900 zarch @@ -896,18 +896,18 @@ ec00000000f6 crb$32 RRS_RRRD0 "compare and branch (32= )" z10 zarch ec00000000f6 crb RRS_RRRDU "compare and branch (32)" z10 zarch ec00000000e4 cgrb$32 RRS_RRRD0 "compare and branch (64)" z10 zarch ec00000000e4 cgrb RRS_RRRDU "compare and branch (64)" z10 zarch -ec0000000076 crj$32 RIE_RRP0 "compare and branch relative (32)" z10 zarch -ec0000000076 crj RIE_RRPU "compare and branch relative (32)" z10 zarch -ec0000000064 cgrj$32 RIE_RRP0 "compare and branch relative (64)" z10 zarch -ec0000000064 cgrj RIE_RRPU "compare and branch relative (64)" z10 zarch +ec0000000076 crj$32 RIE_RRP0 "compare and branch relative (32)" z10 zarch = condjump +ec0000000076 crj RIE_RRPU "compare and branch relative (32)" z10 zarch con= djump +ec0000000064 cgrj$32 RIE_RRP0 "compare and branch relative (64)" z10 zarch= condjump +ec0000000064 cgrj RIE_RRPU "compare and branch relative (64)" z10 zarch co= ndjump ec00000000fe cib$12 RIS_R0RDI "compare immediate and branch (32<8)" z10 za= rch ec00000000fe cib RIS_RURDI "compare immediate and branch (32<8)" z10 zarch ec00000000fc cgib$12 RIS_R0RDI "compare immediate and branch (64<8)" z10 z= arch ec00000000fc cgib RIS_RURDI "compare immediate and branch (64<8)" z10 zarch -ec000000007e cij$12 RIE_R0PI "compare immediate and branch relative (32<8)= " z10 zarch -ec000000007e cij RIE_RUPI "compare immediate and branch relative (32<8)" z= 10 zarch -ec000000007c cgij$12 RIE_R0PI "compare immediate and branch relative (64<8= )" z10 zarch -ec000000007c cgij RIE_RUPI "compare immediate and branch relative (64<8)" = z10 zarch +ec000000007e cij$12 RIE_R0PI "compare immediate and branch relative (32<8)= " z10 zarch condjump +ec000000007e cij RIE_RUPI "compare immediate and branch relative (32<8)" z= 10 zarch condjump +ec000000007c cgij$12 RIE_R0PI "compare immediate and branch relative (64<8= )" z10 zarch condjump +ec000000007c cgij RIE_RUPI "compare immediate and branch relative (64<8)" = z10 zarch condjump b9720000 crt$16 RRF_00RR "compare and trap" z10 zarch b972 crt RRF_U0RR "compare and trap" z10 zarch b9600000 cgrt$16 RRF_00RR "compare and trap 64" z10 zarch @@ -934,10 +934,10 @@ ec00000000f7 clrb$32 RRS_RRRD0 "compare logical and b= ranch (32)" z10 zarch ec00000000f7 clrb RRS_RRRDU "compare logical and branch (32)" z10 zarch ec00000000e5 clgrb$32 RRS_RRRD0 "compare logical and branch (64)" z10 zarch ec00000000e5 clgrb RRS_RRRDU "compare logical and branch (64)" z10 zarch -ec0000000077 clrj$32 RIE_RRP0 "compare logical and branch relative (32)" z= 10 zarch -ec0000000077 clrj RIE_RRPU "compare logical and branch relative (32)" z10 = zarch -ec0000000065 clgrj$32 RIE_RRP0 "compare logical and branch relative (64)" = z10 zarch -ec0000000065 clgrj RIE_RRPU "compare logical and branch relative (64)" z10= zarch +ec0000000077 clrj$32 RIE_RRP0 "compare logical and branch relative (32)" z= 10 zarch condjump +ec0000000077 clrj RIE_RRPU "compare logical and branch relative (32)" z10 = zarch condjump +ec0000000065 clgrj$32 RIE_RRP0 "compare logical and branch relative (64)" = z10 zarch condjump +ec0000000065 clgrj RIE_RRPU "compare logical and branch relative (64)" z10= zarch condjump ec00000000ff clib$12 RIS_R0RDU "compare logical immediate and branch (32<8= )" z10 zarch ec00000000ff clib RIS_RURDU "compare logical immediate and branch (32<8)" = z10 zarch ec00000000fd clgib$12 RIS_R0RDU "compare logical immediate and branch (64<= 8)" z10 zarch @@ -1011,8 +1011,8 @@ b9ca alhhhr RRF_R0RR2 "add logical high high" z196 za= rch b9da alhhlr RRF_R0RR2 "add logical high low" z196 zarch cc0a alsih RIL_RI "add logical with signed immediate high with cc" z196 za= rch cc0b alsihn RIL_RI "add logical with signed immediate high no cc" z196 zar= ch -cc06 brcth RIL_RP "branch relative on count high" z196 zarch -cc06 jcth RIL_RP "jump on count high" z196 zarch +cc06 brcth RIL_RP "branch relative on count high" z196 zarch condjump +cc06 jcth RIL_RP "jump on count high" z196 zarch condjump b9cd chhr RRE_RR "compare high high" z196 zarch b9dd chlr RRE_RR "compare high low" z196 zarch e300000000cd chf RXY_RRRD "compare high" z196 zarch