Merge remote-tracking branch

'origin/GP-1774_James_JVM_switch_improvements--SQUASHED' (Closes #3980,
Closes #3981)
This commit is contained in:
Ryan Kurtz 2022-03-23 12:59:51 -04:00
commit 17a9c07972
4 changed files with 33 additions and 39 deletions

View file

@ -236,7 +236,7 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
if (column == 0) { if (column == 0) {
return ""; return "";
} }
return "Operand-" + column; return "Operand-" + (column - 1);
} }
/** /**

View file

@ -5,7 +5,7 @@
endian="big" endian="big"
size="32" size="32"
variant="default" variant="default"
version="1.0" version="1.1"
slafile="JVM.sla" slafile="JVM.sla"
processorspec="JVM.pspec" processorspec="JVM.pspec"
manualindexfile="../manuals/JVM.idx" manualindexfile="../manuals/JVM.idx"

View file

@ -1721,19 +1721,18 @@ Default:"default" addr is defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4
# lookupswitch # lookupswitch
################################################################################################## ##################################################################################################
LookupSwitch_match:match _offset is matchbyte1; matchbyte2; matchbyte3; matchbyte4; offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [match = (matchbyte1 << 24) | (matchbyte2 << 16) | (matchbyte3 << 8) | (matchbyte4); _offset = (offsetbyte1 << 24) | (offsetbyte2 << 16) | (offsetbyte3 << 8) | (offsetbyte4); ] #compute and display one match,offset pair
LookupSwitch_match:match _offset is matchbyte1; matchbyte2; matchbyte3; matchbyte4; offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [match = (matchbyte1 << 24) | (matchbyte2 << 16) | (matchbyte3 << 8) | (matchbyte4); _offset = inst_start + ((offsetbyte1 << 24) | (offsetbyte2 << 16) | (offsetbyte3 << 8) | (offsetbyte4)); ]
{ {
} }
LookupSwitch_case:"lscase" lscase is (in_lookup_switch=1 & in_table_switch=0) [ lscase = switch_num; switch_num = switch_num - 1;] #consume one match,offset pair and decrement the switch number
:^LookupSwitch_match, instruction is (in_lookup_switch=1 & in_table_switch=0); LookupSwitch_match; instruction [switch_num = switch_num - 1;]
{ {
} }
:^LookupSwitch_case LookupSwitch_match, instruction is (in_lookup_switch=1 & in_table_switch=0); LookupSwitch_case; LookupSwitch_match; instruction #leave the switch statement
{ :""LookupSwitch_match is (in_lookup_switch=1 & switch_num=1 & in_table_switch=0); LookupSwitch_match [in_lookup_switch=0;]
}
:"lscase" lscase LookupSwitch_match is (in_lookup_switch=1 & switch_num=1 & in_table_switch=0); LookupSwitch_match [in_lookup_switch=0; lscase=switch_num; ]
{ {
} }
@ -1744,14 +1743,14 @@ padSwitch: "" is alignmentPad = 2 & padVal & op ; pad1; pad2 { export *[const]:
padSwitch: "" is alignmentPad = 1 & padVal & op ; pad1 { export *[const]:1 padVal; } padSwitch: "" is alignmentPad = 1 & padVal & op ; pad1 { export *[const]:1 padVal; }
padSwitch: "" is alignmentPad = 0 & padVal & op { export *[const]:1 padVal; } padSwitch: "" is alignmentPad = 0 & padVal & op { export *[const]:1 padVal; }
dolookupswitch: _default, npairs is alignmentPad & defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4; npairsbyte1; npairsbyte2; npairsbyte3; npairsbyte4 [ npairs = (npairsbyte1 << 24) | (npairsbyte2 << 16) | (npairsbyte3 << 8) | npairsbyte4; _default = (defaultbyte1 << 24) | (defaultbyte2 << 16) | (defaultbyte3 << 8) | (defaultbyte4); switch_num = npairs; in_lookup_switch = 1;] #Note: "Default" constructor does not play nice with switchAssist injection...
dolookupswitch: _default, npairs is alignmentPad & defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4; npairsbyte1; npairsbyte2; npairsbyte3; npairsbyte4 [ npairs = (npairsbyte1 << 24) | (npairsbyte2 << 16) | (npairsbyte3 << 8) | npairsbyte4; _default = inst_start + ((defaultbyte1 << 24) | (defaultbyte2 << 16) | (defaultbyte3 << 8) | defaultbyte4); switch_num = npairs; in_lookup_switch = 1;]
{ {
_padding:1 = alignmentPad; local _padding:1 = alignmentPad;
_opcodeAddr:$(SIZE) = inst_start; local _opcodeAddr:$(SIZE) = inst_start;
_defaultAddr:$(SIZE) = inst_start + _default; local _key:$(SIZE) = 0;
_key:$(SIZE) = 0;
pop(_key); pop(_key);
_address:$(SIZE) = switchAssist(_key,_opcodeAddr,_padding,_defaultAddr,npairs:$(SIZE)); local _address:$(SIZE) = switchAssist(_key,_opcodeAddr,_padding,_default:$(SIZE),npairs:$(SIZE));
goto [ _address ]; goto [ _address ];
} }
@ -2013,20 +2012,29 @@ _value :$(DOUBLE_SIZE) = 0;
# tableswitch # tableswitch
######################################################################################################################## ########################################################################################################################
#compute and display one switch offset
Switch_offset:_offset is offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [ _offset = inst_start + ((offsetbyte1<<24) | (offsetbyte2<<16) | (offsetbyte3<<8) | offsetbyte4); ] Switch_offset:_offset is offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [ _offset = inst_start + ((offsetbyte1<<24) | (offsetbyte2<<16) | (offsetbyte3<<8) | offsetbyte4); ]
{ {
} }
Switch_case:"case" case is (in_table_switch=1) [ case = switch_high-switch_num; switch_num=switch_num-1; ] # Switch entry that's not the last one.
# no pcode def - this construction is just for consuming all of the bytes of a tableswitch instructions
# decrements the switch number
:^Switch_offset, instruction is (in_table_switch=1 & in_lookup_switch=0); Switch_offset; instruction [switch_num = switch_num - 1;]
{
}
#Last switch entry. Get out of switch context.
:""Switch_offset is (in_table_switch=1 & in_lookup_switch=0 &switch_num=0); Switch_offset [ in_table_switch=0; ]
{ {
} }
dotableswitch: Default, low, high is alignmentPad & Default;lowbyte1; lowbyte2; lowbyte3; lowbyte4; highbyte1; highbyte2; highbyte3; highbyte4 [ low = (lowbyte1 << 24) | (lowbyte2 << 16) | (lowbyte3 << 8) | lowbyte4; high = (highbyte1 << 24) | (highbyte2 << 16) | (highbyte3 << 8) | highbyte4; switch_low = low; switch_num = high - low; switch_high = high; in_table_switch = 1; ] dotableswitch: Default, low, high is alignmentPad & Default;lowbyte1; lowbyte2; lowbyte3; lowbyte4; highbyte1; highbyte2; highbyte3; highbyte4 [ low = (lowbyte1 << 24) | (lowbyte2 << 16) | (lowbyte3 << 8) | lowbyte4; high = (highbyte1 << 24) | (highbyte2 << 16) | (highbyte3 << 8) | highbyte4; switch_low = low; switch_num = high - low; switch_high = high; in_table_switch = 1; ]
{ {
_offset :$(SIZE) = 0; local _offset :$(SIZE) = 0;
idx :$(SIZE) = 0; local idx :$(SIZE) = 0;
padding:$(SIZE) = alignmentPad; local padding:$(SIZE) = alignmentPad;
pop(idx); pop(idx);
if (idx s< low) goto Default; if (idx s< low) goto Default;
@ -2037,7 +2045,6 @@ dotableswitch: Default, low, high is alignmentPad & Default;lowbyte1; lowbyte2;
goto [switch_target]; goto [switch_target];
} }
:tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=0; dotableswitch; instruction :tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=0; dotableswitch; instruction
{ {
build dotableswitch; build dotableswitch;
@ -2055,18 +2062,6 @@ dotableswitch: Default, low, high is alignmentPad & Default;lowbyte1; lowbyte2;
build dotableswitch; build dotableswitch;
} }
# Switch entry that's not the last one.
# no pcode def - this construction is just for consuming all of the bytes of a tableswitch instructions
# decrements the switch number
:^Switch_case Switch_offset, instruction is (in_table_switch=1 & in_lookup_switch=0); Switch_case; Switch_offset; instruction
{
}
#Last switch entry. Get out of switch context.
:"case" case Switch_offset is (in_table_switch=1 & in_lookup_switch=0 &switch_num=0); Switch_offset [ in_table_switch=0; case=switch_high-switch_num; ]
{
}
#wide loads #wide loads
:wide_iload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc415); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ] :wide_iload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc415); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{ {

View file

@ -113,9 +113,6 @@ public class JvmSwitchAnalyzer extends AbstractJavaAnalyzer {
if (!mnenomic.equals(TABLESWITCH_MNEMONIC) && !mnenomic.equals(LOOKUPSWITCH_MNEMONIC)) { if (!mnenomic.equals(TABLESWITCH_MNEMONIC) && !mnenomic.equals(LOOKUPSWITCH_MNEMONIC)) {
continue; //only care about switch instructions continue; //only care about switch instructions
} }
if (instruction.getMnemonicReferences().length > 0) {
continue; //analyzer has already handled this instructions
}
monitor.setMessage("JvmSwitchAnalyzer: " + instruction.getMinAddress()); monitor.setMessage("JvmSwitchAnalyzer: " + instruction.getMinAddress());
if (instruction.getMnemonicString().equals(TABLESWITCH_MNEMONIC)) { if (instruction.getMnemonicString().equals(TABLESWITCH_MNEMONIC)) {
processTableSwitch(program, reader, instruction, monitor); processTableSwitch(program, reader, instruction, monitor);
@ -182,13 +179,14 @@ public class JvmSwitchAnalyzer extends AbstractJavaAnalyzer {
// WARNING: this is very dependent on the sub-constructor for the switch stmt. // WARNING: this is very dependent on the sub-constructor for the switch stmt.
// if the op-object order changes for the operand, this will fail // if the op-object order changes for the operand, this will fail
Object[] opObjects = instruction.getOpObjects(0); Object[] opObjects = instruction.getOpObjects(0);
long defaultOffset = ((Scalar) opObjects[0]).getUnsignedValue();
long numberOfCases = ((Scalar) opObjects[1]).getUnsignedValue(); long numberOfCases = ((Scalar) opObjects[1]).getUnsignedValue();
List<Address> addressesToDisassemble = new ArrayList<>(); List<Address> addressesToDisassemble = new ArrayList<>();
//handle the default case //handle the default case
Address defaultAddress = instruction.getMinAddress().add(defaultOffset); Address defaultAddress = instruction.getAddress()
.getAddressSpace()
.getAddress(((Scalar) opObjects[0]).getUnsignedValue());
addressesToDisassemble.add(defaultAddress); addressesToDisassemble.add(defaultAddress);
addLabelAndReference(program, instruction, defaultAddress, DEFAULT_CASE_LABEL); addLabelAndReference(program, instruction, defaultAddress, DEFAULT_CASE_LABEL);
@ -225,8 +223,9 @@ public class JvmSwitchAnalyzer extends AbstractJavaAnalyzer {
private void addLabelAndReference(Program program, Instruction switchInstruction, private void addLabelAndReference(Program program, Instruction switchInstruction,
Address target, String label) { Address target, String label) {
program.getReferenceManager().addMemoryReference(switchInstruction.getMinAddress(), target, program.getReferenceManager()
RefType.COMPUTED_JUMP, SourceType.ANALYSIS, CodeUnit.MNEMONIC); .addMemoryReference(switchInstruction.getMinAddress(), target,
RefType.COMPUTED_JUMP, SourceType.ANALYSIS, CodeUnit.MNEMONIC);
//put switch table cases into namespace for the switch //put switch table cases into namespace for the switch
//create namespace if necessary //create namespace if necessary