public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] s390: Support for jump visualization in disassembly
@ 2023-11-29 20:44 Jens Remus
  2023-12-04 17:34 ` Nick Clifton
  0 siblings, 1 reply; 2+ messages in thread
From: Jens Remus @ 2023-11-29 20:44 UTC (permalink / raw)
  To: binutils; +Cc: Jens Remus, Andreas Krebbel, Nick Clifton

Add support for jump visualization for the s390 architecture in
disassembly:

objdump -d --visualize-jumps ...

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.

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).

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.

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.

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.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Andreas Krebbel <krebbel@linux.ibm.com>
---
 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.
 
+* objdump --visualize-jumps is now supported on s390 architecture.
+
 Changes in 2.41:
 
 * 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
   };
 
-/* 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
 
+/* Instruction requires a specific facility.  */
 #define S390_INSTR_FLAG_HTM 0x4
 #define S390_INSTR_FLAG_VX 0x8
 #define S390_INSTR_FLAG_FACILITY_MASK 0xc
 
+/* 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.  */
 
 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;
 
-/* Values defined for the flags field of a struct s390_opcode.  */
-
 /* The operands table is an array of struct s390_operand.  */
 
 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"
 
 static int opc_index[256];
 static int current_arch_mask = 0;
@@ -259,9 +260,14 @@ s390_print_insn_with_opcode (bfd_vma memaddr,
 	}
       else if (flags & S390_OPERAND_PCREL)
 	{
+	  bfd_vma target = memaddr + val.i + val.i;
+
+	  /* Provide info for jump visualization.  May be evaluated by p_a_f().  */
+	  info->target = 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_info *info)
   /* The output looks better if we put 6 bytes on a line.  */
   info->bytes_per_line = 6;
 
+  /* Set some defaults for the insn info.  */
+  info->insn_info_valid    = 0;
+  info->branch_delay_insns = 0;
+  info->data_size          = 0;
+  info->insn_type          = dis_nonbranch;
+  info->target             = 0;
+  info->target2            = 0;
+
   /* Every S390 instruction is max 6 bytes long.  */
   memset (buffer, 0, 6);
   status = info->read_memory_func (memaddr, buffer, 6, info);
@@ -373,6 +387,23 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 
       if (opcode != 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 = dis_branch;
+	      break;
+	    case S390_INSTR_FLAGS_CLASS_CONDJUMP:
+	      info->insn_type = dis_condbranch;
+	      break;
+	    case S390_INSTR_FLAGS_CLASS_JUMPSR:
+	      info->insn_type = dis_jsr;
+	      break;
+	    default:
+	      info->insn_type = dis_nonbranch;
+	    }
+	  info->insn_info_valid = 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_info *info)
   if (bytes_to_dump == 0)
     return 0;
 
+  info->insn_type = dis_noninsn;
+  info->insn_info_valid = 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] == 0 || str[2] == ',')) {
 	      flag_bits |= S390_INSTR_FLAG_VX;
 	      str += 2;
+	    } else if (strncmp (str, "jump", 7) == 0
+		&& (str[4] == 0 || str[4] == ',')) {
+	      flag_bits |= S390_INSTR_FLAGS_CLASS_JUMP;
+	      str += 4;
+	    } else if (strncmp (str, "condjump", 7) == 0
+		&& (str[8] == 0 || str[8] == ',')) {
+	      flag_bits |= S390_INSTR_FLAGS_CLASS_CONDJUMP;
+	      str += 8;
+	    } else if (strncmp (str, "jumpsr", 7) == 0
+		&& (str[6] == 0 || str[6] == ',')) {
+	      flag_bits |= S390_INSTR_FLAGS_CLASS_JUMPSR;
+	      str += 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 condjump
+85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch condjump
+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 condjump
+ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch condjump
+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 mask 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 condjump
 # 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; exists 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 condjump
+ec0000000064 cgrj$32 RIE_RRP0 "compare and branch relative (64)" z10 zarch condjump
+ec0000000064 cgrj RIE_RRPU "compare and branch relative (64)" z10 zarch condjump
 ec00000000fe cib$12 RIS_R0RDI "compare immediate and branch (32<8)" z10 zarch
 ec00000000fe cib RIS_RURDI "compare immediate and branch (32<8)" z10 zarch
 ec00000000fc cgib$12 RIS_R0RDI "compare immediate and branch (64<8)" z10 zarch
 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)" z10 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)" z10 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 branch (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)" z10 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)" z10 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 zarch
 b9da alhhlr RRF_R0RR2 "add logical high low" z196 zarch
 cc0a alsih RIL_RI "add logical with signed immediate high with cc" z196 zarch
 cc0b alsihn RIL_RI "add logical with signed immediate high no cc" z196 zarch
-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
-- 
2.40.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] s390: Support for jump visualization in disassembly
  2023-11-29 20:44 [PATCH] s390: Support for jump visualization in disassembly Jens Remus
@ 2023-12-04 17:34 ` Nick Clifton
  0 siblings, 0 replies; 2+ messages in thread
From: Nick Clifton @ 2023-12-04 17:34 UTC (permalink / raw)
  To: Jens Remus, binutils; +Cc: Andreas Krebbel

Hi Jens,

> Add support for jump visualization for the s390 architecture in
> disassembly:
> 
> objdump -d --visualize-jumps ...

And it works like a charm. :-)

Patch approved and applied.

Cheers
   Nick



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-12-04 17:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-29 20:44 [PATCH] s390: Support for jump visualization in disassembly Jens Remus
2023-12-04 17:34 ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).