Merge remote-tracking branch 'origin/GP-5196_ghidragon_address_expression_and_symbol_names_in_address_input--SQUASHED'
@@ -399,6 +399,7 @@ src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png||GHIDRA||||END|
|
|||||||
src/main/help/help/topics/MemoryMapPlugin/images/MoveMemory.png||GHIDRA||||END|
|
src/main/help/help/topics/MemoryMapPlugin/images/MoveMemory.png||GHIDRA||||END|
|
||||||
src/main/help/help/topics/MemoryMapPlugin/images/SetImageBaseDialog.png||GHIDRA||||END|
|
src/main/help/help/topics/MemoryMapPlugin/images/SetImageBaseDialog.png||GHIDRA||||END|
|
||||||
src/main/help/help/topics/MemoryMapPlugin/images/SplitMemoryBlock.png||GHIDRA||||END|
|
src/main/help/help/topics/MemoryMapPlugin/images/SplitMemoryBlock.png||GHIDRA||||END|
|
||||||
|
src/main/help/help/topics/Misc/AddressExpressions.htm||GHIDRA||||END|
|
||||||
src/main/help/help/topics/Misc/Appendix.htm||GHIDRA||||END|
|
src/main/help/help/topics/Misc/Appendix.htm||GHIDRA||||END|
|
||||||
src/main/help/help/topics/Misc/Welcome_to_Ghidra_Help.htm||GHIDRA||||END|
|
src/main/help/help/topics/Misc/Welcome_to_Ghidra_Help.htm||GHIDRA||||END|
|
||||||
src/main/help/help/topics/Navigation/Navigation.htm||GHIDRA||||END|
|
src/main/help/help/topics/Navigation/Navigation.htm||GHIDRA||||END|
|
||||||
|
|||||||
@@ -196,6 +196,8 @@
|
|||||||
<!-- Formerly The Byte Viewer -->
|
<!-- Formerly The Byte Viewer -->
|
||||||
|
|
||||||
<tocdef id="Program Annotation" text="Program Annotation" target="help/topics/ProgramManagerPlugin/Program_Annotation.htm">
|
<tocdef id="Program Annotation" text="Program Annotation" target="help/topics/ProgramManagerPlugin/Program_Annotation.htm">
|
||||||
|
<tocdef id="Address Expressions" sortgroup="a" text="Address Expressions" target="help/topics/Misc/AddressExpressions.htm" />
|
||||||
|
|
||||||
<tocdef id="Auto Analysis" sortgroup="a" text="Auto Analysis" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm" >
|
<tocdef id="Auto Analysis" sortgroup="a" text="Auto Analysis" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm" >
|
||||||
<tocdef id="Forcing Analysis" sortgroup="a" text="Forcing Analysis" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analyze" />
|
<tocdef id="Forcing Analysis" sortgroup="a" text="Forcing Analysis" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analyze" />
|
||||||
<tocdef id="Auto Analysis Options Panel" sortgroup="b" text="Auto Analysis Options Panel" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analysis_Option" />
|
<tocdef id="Auto Analysis Options Panel" sortgroup="b" text="Auto Analysis Options Panel" target="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analysis_Option" />
|
||||||
|
|||||||
@@ -55,8 +55,9 @@
|
|||||||
|
|
||||||
<LI>Select the <B>User</B> radio button.</LI>
|
<LI>Select the <B>User</B> radio button.</LI>
|
||||||
|
|
||||||
<LI>Enter an address, or click in the Code Browser at the address of the new
|
<LI>Enter an address
|
||||||
fallthrough.</LI>
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>), or click in
|
||||||
|
the Code Browser at the address of the new fallthrough.</LI>
|
||||||
|
|
||||||
<LI>Select the <B>Apply</B> button to change the fallthrough and leave the dialog intact;
|
<LI>Select the <B>Apply</B> button to change the fallthrough and leave the dialog intact;
|
||||||
select the OK button to change the fallthrough and dismiss the dialog.</LI>
|
select the OK button to change the fallthrough and dismiss the dialog.</LI>
|
||||||
|
|||||||
@@ -243,8 +243,10 @@
|
|||||||
|
|
||||||
<P><B><I>Block Name</I></B> - Enter the name of the new memory block.</P>
|
<P><B><I>Block Name</I></B> - Enter the name of the new memory block.</P>
|
||||||
|
|
||||||
<P><B><I>Start Addr</I></B> - Enter the start address of the new memory block. If the
|
<P><B><I>Start Address</I></B> - Enter the start address
|
||||||
program language defines multiple address spaces, the address space must also be
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
of the new memory block. If
|
||||||
|
the program language defines multiple address spaces, the address space must also be
|
||||||
specified. The address space selection will not appear if only one is defined.
|
specified. The address space selection will not appear if only one is defined.
|
||||||
If creating an overlay memory block within an existing overlay address space that
|
If creating an overlay memory block within an existing overlay address space that
|
||||||
space should be selected. A block within the default address space may not span across
|
space should be selected. A block within the default address space may not span across
|
||||||
@@ -378,11 +380,14 @@
|
|||||||
|
|
||||||
<P><B><I>Length -</I></B> Length of the memory block to be moved (not editable).</P>
|
<P><B><I>Length -</I></B> Length of the memory block to be moved (not editable).</P>
|
||||||
|
|
||||||
<P><B><I>New Start Address -</I></B> Enter the NEW starting address for the block.
|
<P><B><I>New Start Address -</I></B> Enter the new starting address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
for the block.
|
||||||
The NEW ending address will be computed.</P>
|
The NEW ending address will be computed.</P>
|
||||||
|
|
||||||
<P><B><I>New End Address - </I></B> Enter the NEW ending address for the block. The
|
<P><B><I>New End Address - </I></B> Enter the new ending address
|
||||||
NEW starting address will be computed.</P>
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
for the block. The NEW starting address will be computed.</P>
|
||||||
|
|
||||||
<P><I><IMG src="help/shared/note.png" border="0"> You cannot move a block under the
|
<P><I><IMG src="help/shared/note.png" border="0"> You cannot move a block under the
|
||||||
following conditions:</I></P>
|
following conditions:</I></P>
|
||||||
@@ -404,11 +409,15 @@
|
|||||||
enter the split point:</P>
|
enter the split point:</P>
|
||||||
|
|
||||||
<UL>
|
<UL>
|
||||||
<LI>Enter an end address for the first block (block to split), or</LI>
|
<LI>Enter an end address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
for the first block (block to split), or</LI>
|
||||||
|
|
||||||
<LI>Enter a length for the first block (block to split), or</LI>
|
<LI>Enter a length for the first block (block to split), or</LI>
|
||||||
|
|
||||||
<LI>Enter a start address for the second block (new block), or</LI>
|
<LI>Enter a start address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
for the second block (new block), or</LI>
|
||||||
|
|
||||||
<LI>Enter a length for the second block (new block).</LI>
|
<LI>Enter a length for the second block (new block).</LI>
|
||||||
</UL>
|
</UL>
|
||||||
@@ -482,7 +491,9 @@
|
|||||||
|
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P><B><I>New Start Address -</I></B> A new start address can be entered here. It must
|
<P><B><I>New Start Address -</I></B> A new start address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
can be entered here. It must
|
||||||
be before the current start address.</P>
|
be before the current start address.</P>
|
||||||
|
|
||||||
<P><I><B>End Address -</B></I> Displays the end address of the block (not editable).</P>
|
<P><I><B>End Address -</B></I> Displays the end address of the block (not editable).</P>
|
||||||
@@ -521,7 +532,9 @@
|
|||||||
<P><I><B>Start Address -</B></I> Displays the start address of the block (not
|
<P><I><B>Start Address -</B></I> Displays the start address of the block (not
|
||||||
editable).</P>
|
editable).</P>
|
||||||
|
|
||||||
<P><B><I>New End Address -</I></B> A new end address can be entered here. It must be after
|
<P><B><I>New End Address -</I></B> A new end address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
can be entered here. It must be after
|
||||||
the current end address.</P>
|
the current end address.</P>
|
||||||
|
|
||||||
<P><I><B>Block Length -</B></I> Displays the length of the block. A new value can be
|
<P><I><B>Block Length -</B></I> Displays the length of the block. A new value can be
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,175 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||||
|
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<META name="generator" content=
|
||||||
|
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||||
|
|
||||||
|
<TITLE>Address Expressions</TITLE>
|
||||||
|
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
|
<BODY>
|
||||||
|
<H1><A name="Address_Expressions"></A>Address Expressions<BR>
|
||||||
|
</H1>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>An address expression is an arithmetic expression that is entered into an address input
|
||||||
|
field and can include symbol names or memory block names that when evaluated results in a
|
||||||
|
program address.</P>
|
||||||
|
|
||||||
|
<H2>Operands</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Operands can be either a number or a name that evaluates to an address.</P>
|
||||||
|
|
||||||
|
<H3>Names</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>If the operand is a name, then an attempt will be made to find a unique label or
|
||||||
|
function name in the current program for that name. If that fails, then memory blocks
|
||||||
|
will be searched looking for a memory block with that name. In either case, the associated
|
||||||
|
address for that label, function, or memory block will be used in evaluating the
|
||||||
|
expression.</P>
|
||||||
|
|
||||||
|
<P>Generally, symbols (addresses) must be the left operand for a binary operator and will
|
||||||
|
generate a address as the result (maintaining the address space). The one exception is
|
||||||
|
you can subtract two addresses and the result is a number.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Numbers</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Numeric operands will be evaluated as either a hex number or decimal number, depending
|
||||||
|
on the <B>Hex/Decimal Mode</B> of the input field.</P>
|
||||||
|
|
||||||
|
<P>When in hex mode, undecorated numbers will be interpreted as if they are hex values.
|
||||||
|
(so "100" would evaluate to the number 256). If in decimal mode, hex numbers can still be
|
||||||
|
entered by prefixing them with "0x".</P>
|
||||||
|
|
||||||
|
<P>For fields that support either mode, the current mode will be displayed as "hint text"
|
||||||
|
in the lower right corner of the field. The mode can be toggled between decimal and hex
|
||||||
|
by pressing <CTRL> M.</P>
|
||||||
|
|
||||||
|
<P>When in hex mode, there is no corresponding prefix to use to specify a number as being
|
||||||
|
decimal. So if you want to have a mixed mode expression, use decimal mode and use the
|
||||||
|
"0x" prefix for any hex numbers in the expression.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H2>Operators</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Most standard operators are supported, but not all operators are supported for all
|
||||||
|
operands. Also order of operands is important when mixing numbers and addresses. For
|
||||||
|
example,a number can be added to an address, but an address can't be added to a number.</P>
|
||||||
|
|
||||||
|
<P>Operator precedence is the standard precedence defined by the "C" programming
|
||||||
|
language.</P>
|
||||||
|
|
||||||
|
<H3>Math Operators</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Supported math operators are "+ - * /". These operators generate either a number or
|
||||||
|
address result depending on the operands.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Logical and Relational Operators</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Supported logical operators are "< > <= >= == != || && and !".
|
||||||
|
These operators generator a numeric value of 0 or 1.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Bit Operators</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Supported bit operators are <<, >>, &, |, ^, and ~. These operators
|
||||||
|
generate either a number or address result depending on the operands.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Groups Operators</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>Parenthesis can be used to group sub-expressions to control the order of
|
||||||
|
operations</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H2>Result</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>The result of the expression is always an address or a number. If the result is a
|
||||||
|
number, it is converted to an address using the selected address space (in the case where
|
||||||
|
there are multiple possible address spaces, a combo is shown for choosing the desired
|
||||||
|
address space, otherwise the default address space is used)</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H2>Examples</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<TABLE width=95% border="1">
|
||||||
|
<TR>
|
||||||
|
<TH valign="top" bgcolor="#c0c0c0">Expression<BR>
|
||||||
|
</TH>
|
||||||
|
|
||||||
|
<TH valign="top" bgcolor="#c0c0c0">Result<BR>
|
||||||
|
</TH>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>ENTRY+10</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address 0x10 higher than the symbol "ENTRY"</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>10+ENTRY</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Error (Can't add an address to a number)</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>100000+30</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address 0x100030 (hex mode)</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>0x100000+30</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address 0x100030 (hex mode)</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>0x100000+30</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address 0x10001e (decimal mode)</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>0x100000+(2*10)</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address 0x100020</TD>
|
||||||
|
</TR>
|
||||||
|
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>ENTRY + 1<<4</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address that is 16 higher than the symbol "ENTRY"</TD>
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>X - (X > 100) * 100</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">If symbol "X" address > 100, Result is 100 less than X; Otherwise X</TD>
|
||||||
|
</TR>
|
||||||
|
<TR>
|
||||||
|
<TD valign="top"><B>ENTRY | FF</B></TD>
|
||||||
|
|
||||||
|
<TD valign="top">Address that is the symbol "ENTRY" with its last 8 bits set to FF</TD>
|
||||||
|
</TR>
|
||||||
|
</TABLE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
@@ -49,7 +49,9 @@
|
|||||||
</LI>
|
</LI>
|
||||||
|
|
||||||
<LI>The "Enter Base Address" field in the dialog is filled in with the first address in the
|
<LI>The "Enter Base Address" field in the dialog is filled in with the first address in the
|
||||||
selection. You can enter a different address as the base address.</LI>
|
selection. You can enter a different address
|
||||||
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
|
||||||
|
as the base address.</LI>
|
||||||
|
|
||||||
<LI>
|
<LI>
|
||||||
The "Select Data Size" combo box has an entry for sizes 1, 2, 4, and 8. The size you select
|
The "Select Data Size" combo box has an entry for sizes 1, 2, 4, and 8. The size you select
|
||||||
|
|||||||
@@ -1167,9 +1167,10 @@ c<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|||||||
<P>[<I><B><IMG src="images/unchecked.png" alt="" valign="middle" align="middle">
|
<P>[<I><B><IMG src="images/unchecked.png" alt="" valign="middle" align="middle">
|
||||||
Offset</B></I>] The <I>To Address</I> entry is required for normal memory references
|
Offset</B></I>] The <I>To Address</I> entry is required for normal memory references
|
||||||
and specifies the reference destination as a memory offset within a selected address
|
and specifies the reference destination as a memory offset within a selected address
|
||||||
space. The address offset entry is always
|
space. Enter an address
|
||||||
interpretted as a unsigned hex value (i.e., the "0x" entry prefix is assumed).
|
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>) to specify
|
||||||
For those processors with multiple address-spaces, a pull-down is also provided
|
the referenced address.
|
||||||
|
For those processors with multiple address-spaces, a pull-down is also provided
|
||||||
allowing the address-space to be selected. Address spaces which overlay the
|
allowing the address-space to be selected. Address spaces which overlay the
|
||||||
</I>OTHER</I> non-loaded space are only included if the <B>Include OTHER overlay spaces</B>
|
</I>OTHER</I> non-loaded space are only included if the <B>Include OTHER overlay spaces</B>
|
||||||
checkbox is selected.<BR>
|
checkbox is selected.<BR>
|
||||||
|
|||||||
@@ -124,7 +124,10 @@
|
|||||||
range is smaller, then value associations for address range that was trucated is
|
range is smaller, then value associations for address range that was trucated is
|
||||||
effectively cleared. For example, in the dialog shown above, if you change the end
|
effectively cleared. For example, in the dialog shown above, if you change the end
|
||||||
address to 01001b47 and change the value to 111, then addresses 01001b33 to 01001b47
|
address to 01001b47 and change the value to 111, then addresses 01001b33 to 01001b47
|
||||||
will have the value 111 and address 01001b48 will have no value.<BR>
|
will have the value 111 and address 01001b48 will have no value. When entering a
|
||||||
|
new start or end address, you can also enter an
|
||||||
|
<A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>.
|
||||||
|
<BR>
|
||||||
</P>
|
</P>
|
||||||
</DIV>
|
</DIV>
|
||||||
</DIV>
|
</DIV>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -117,15 +117,14 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addressChanged() {
|
private void addressChanged(Address address) {
|
||||||
if (changing) {
|
if (changing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Runnable r = () -> {
|
Runnable r = () -> {
|
||||||
Address addr = addrField.getAddress();
|
if (address != null || addrField.getText().length() == 0) {
|
||||||
if (addr != null || addrField.getValue().length() == 0) {
|
model.setCurrentFallthrough(address);
|
||||||
model.setCurrentFallthrough(addr);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setStatusText("Invalid Address");
|
setStatusText("Invalid Address");
|
||||||
@@ -139,9 +138,7 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
private JPanel create() {
|
private JPanel create() {
|
||||||
JPanel panel = new JPanel(new BorderLayout(0, 10));
|
JPanel panel = new JPanel(new BorderLayout(0, 10));
|
||||||
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
|
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
|
||||||
addrField = new AddressInput();
|
addrField = new AddressInput(model.getProgram(), this::addressChanged);
|
||||||
addrField.setAddressFactory(model.getProgram().getAddressFactory());
|
|
||||||
addrField.addChangeListener(e -> addressChanged());
|
|
||||||
addrField.addActionListener(e -> model.setCurrentFallthrough(addrField.getAddress()));
|
addrField.addActionListener(e -> model.setCurrentFallthrough(addrField.getAddress()));
|
||||||
panel.add(createHomePanel(), BorderLayout.NORTH);
|
panel.add(createHomePanel(), BorderLayout.NORTH);
|
||||||
panel.add(createAddressPanel(), BorderLayout.CENTER);
|
panel.add(createAddressPanel(), BorderLayout.CENTER);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -148,8 +148,9 @@ class VarnodeLocationCellEditor extends AbstractCellEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component createAddressEditor(VarnodeInfo varnode) {
|
private Component createAddressEditor(VarnodeInfo varnode) {
|
||||||
addressInput = new AddressInput(BorderFactory.createEmptyBorder());
|
addressInput = new AddressInput(program);
|
||||||
addressInput.setAddressFactory(program.getAddressFactory());
|
addressInput.setComponentBorders(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
Address address = varnode.getAddress();
|
Address address = varnode.getAddress();
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
addressInput.setAddress(address);
|
addressInput.setAddress(address);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -35,7 +35,6 @@ import ghidra.app.util.HelpTopics;
|
|||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.database.mem.FileBytes;
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryBlockType;
|
import ghidra.program.model.mem.MemoryBlockType;
|
||||||
@@ -69,7 +68,6 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
private JCheckBox overlayCB;
|
private JCheckBox overlayCB;
|
||||||
private RegisterField initialValueField;
|
private RegisterField initialValueField;
|
||||||
private JLabel initialValueLabel;
|
private JLabel initialValueLabel;
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private AddressInput baseAddrField; // used for Bit and Byte mapped blocks
|
private AddressInput baseAddrField; // used for Bit and Byte mapped blocks
|
||||||
private IntegerTextField schemeDestByteCountField; // used for Byte mapped blocks
|
private IntegerTextField schemeDestByteCountField; // used for Byte mapped blocks
|
||||||
private IntegerTextField schemeSrcByteCountField; // used for Byte mapped blocks
|
private IntegerTextField schemeSrcByteCountField; // used for Byte mapped blocks
|
||||||
@@ -134,12 +132,12 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component buildBasicInfoPanel() {
|
private Component buildBasicInfoPanel() {
|
||||||
JPanel panel = new JPanel(new PairLayout(4, 10, 150));
|
JPanel panel = new JPanel(new PairLayout(5, 10, 150));
|
||||||
panel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5));
|
panel.setBorder(BorderFactory.createEmptyBorder(5, 7, 4, 5));
|
||||||
|
|
||||||
panel.add(new GLabel("Block Name:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Block Name:", SwingConstants.RIGHT));
|
||||||
panel.add(buildNameField());
|
panel.add(buildNameField());
|
||||||
panel.add(new GLabel("Start Addr:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Start Address:", SwingConstants.RIGHT));
|
||||||
panel.add(buildAddressField());
|
panel.add(buildAddressField());
|
||||||
panel.add(new GLabel("Length:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Length:", SwingConstants.RIGHT));
|
||||||
panel.add(buildLengthField());
|
panel.add(buildLengthField());
|
||||||
@@ -422,26 +420,16 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
model.setFileBytes((FileBytes) fileBytesComboBox.getSelectedItem());
|
model.setFileBytes((FileBytes) fileBytesComboBox.getSelectedItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addrChanged() {
|
private void addressChanged(Address address) {
|
||||||
Address addr = null;
|
model.setStartAddress(address);
|
||||||
try {
|
|
||||||
addr = addrField.getAddress();
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException e) {
|
|
||||||
// just let it be null
|
|
||||||
}
|
|
||||||
model.setStartAddress(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void baseAddressChanged() {
|
private void addressError(String errorMessage) {
|
||||||
Address addr = null;
|
model.setAddressError(errorMessage);
|
||||||
try {
|
}
|
||||||
addr = baseAddrField.getAddress();
|
|
||||||
}
|
private void baseAddressChanged(Address address) {
|
||||||
catch (IllegalArgumentException e) {
|
model.setBaseAddress(address);
|
||||||
// just let it be null
|
|
||||||
}
|
|
||||||
model.setBaseAddress(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void schemeSrcByteCountChanged() {
|
private void schemeSrcByteCountChanged() {
|
||||||
@@ -476,12 +464,11 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buildMappedPanel() {
|
private JPanel buildMappedPanel() {
|
||||||
|
Program program = model.getProgram();
|
||||||
JPanel panel = new JPanel(new PairLayout());
|
JPanel panel = new JPanel(new PairLayout());
|
||||||
|
|
||||||
baseAddrField = new AddressInput();
|
baseAddrField = new AddressInput(program, this::baseAddressChanged);
|
||||||
baseAddrField.setAddressFactory(addrFactory);
|
|
||||||
baseAddrField.setName("Source Addr");
|
baseAddrField.setName("Source Addr");
|
||||||
baseAddrField.addChangeListener(ev -> baseAddressChanged());
|
|
||||||
baseAddrField.setAccessibleName("Source Address");
|
baseAddrField.setAccessibleName("Source Address");
|
||||||
|
|
||||||
JPanel schemePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
JPanel schemePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||||
@@ -504,7 +491,6 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
schemePanel.add(new GLabel(" : "));
|
schemePanel.add(new GLabel(" : "));
|
||||||
schemePanel.add(schemeSrcByteCountField.getComponent());
|
schemePanel.add(schemeSrcByteCountField.getComponent());
|
||||||
|
|
||||||
Program program = model.getProgram();
|
|
||||||
Address minAddr = program.getMinAddress();
|
Address minAddr = program.getMinAddress();
|
||||||
if (minAddr == null) {
|
if (minAddr == null) {
|
||||||
minAddr = program.getAddressFactory().getDefaultAddressSpace().getAddress(0);
|
minAddr = program.getAddressFactory().getDefaultAddressSpace().getAddress(0);
|
||||||
@@ -561,12 +547,12 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component buildAddressField() {
|
private Component buildAddressField() {
|
||||||
addrField = new AddressInput();
|
Program program = model.getProgram();
|
||||||
|
addrField = new AddressInput(program, this::addressChanged);
|
||||||
|
addrField.setAddressErrorConsumer(this::addressError);
|
||||||
|
addrField.setAddressSpaceFilter(AddressInput.ALL_MEMORY_SPACES);
|
||||||
addrField.setName("Start Addr");
|
addrField.setName("Start Addr");
|
||||||
addrField.setAccessibleName("Memory Block Start Address");
|
addrField.setAccessibleName("Memory Block Start Address");
|
||||||
addrFactory = model.getProgram().getAddressFactory();
|
|
||||||
addrField.setAddressFactory(addrFactory, AddressInput.INCLUDE_ALL_MEMORY_SPACES);
|
|
||||||
addrField.addChangeListener(ev -> addrChanged());
|
|
||||||
return addrField;
|
return addrField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -59,6 +59,7 @@ class AddBlockModel {
|
|||||||
private String comment;
|
private String comment;
|
||||||
private FileBytes fileBytes;
|
private FileBytes fileBytes;
|
||||||
private long fileBytesOffset = -1;
|
private long fileBytesOffset = -1;
|
||||||
|
private String addressErrorMessage;
|
||||||
|
|
||||||
enum InitializedType {
|
enum InitializedType {
|
||||||
UNINITIALIZED, INITIALIZED_FROM_VALUE, INITIALIZED_FROM_FILE_BYTES;
|
UNINITIALIZED, INITIALIZED_FROM_VALUE, INITIALIZED_FROM_FILE_BYTES;
|
||||||
@@ -90,6 +91,14 @@ class AddBlockModel {
|
|||||||
|
|
||||||
void setStartAddress(Address addr) {
|
void setStartAddress(Address addr) {
|
||||||
startAddr = addr;
|
startAddr = addr;
|
||||||
|
addressErrorMessage = null;
|
||||||
|
validateInfo();
|
||||||
|
listener.stateChanged(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAddressError(String errorMessage) {
|
||||||
|
startAddr = null;
|
||||||
|
addressErrorMessage = errorMessage;
|
||||||
validateInfo();
|
validateInfo();
|
||||||
listener.stateChanged(null);
|
listener.stateChanged(null);
|
||||||
}
|
}
|
||||||
@@ -432,6 +441,9 @@ class AddBlockModel {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
message = "Please enter a valid Start Address";
|
message = "Please enter a valid Start Address";
|
||||||
|
if (addressErrorMessage != null) {
|
||||||
|
message = "Invalid Address: " + addressErrorMessage;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -18,6 +18,7 @@ package ghidra.app.plugin.core.memory;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
@@ -30,7 +31,7 @@ import ghidra.app.util.AddressInput;
|
|||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
@@ -49,7 +50,6 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
private final static String EXPAND_UP_TITLE = "Expand Block Up";
|
private final static String EXPAND_UP_TITLE = "Expand Block Up";
|
||||||
private final static String EXPAND_DOWN_TITLE = "Expand Block Down";
|
private final static String EXPAND_DOWN_TITLE = "Expand Block Down";
|
||||||
private int dialogType;
|
private int dialogType;
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private AddressInput startAddressInput;
|
private AddressInput startAddressInput;
|
||||||
private AddressInput endAddressInput;
|
private AddressInput endAddressInput;
|
||||||
private JTextField startField;
|
private JTextField startField;
|
||||||
@@ -66,7 +66,7 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
* @param af
|
* @param af
|
||||||
* @param dialogType
|
* @param dialogType
|
||||||
*/
|
*/
|
||||||
ExpandBlockDialog(PluginTool tool, ExpandBlockModel model, MemoryBlock block, AddressFactory af,
|
ExpandBlockDialog(PluginTool tool, ExpandBlockModel model, MemoryBlock block, Program program,
|
||||||
int dialogType) {
|
int dialogType) {
|
||||||
super(dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE, true);
|
super(dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE, true);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
@@ -74,9 +74,8 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
this.dialogType = dialogType;
|
this.dialogType = dialogType;
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP,
|
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP,
|
||||||
dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE));
|
dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE));
|
||||||
addrFactory = af;
|
|
||||||
model.setChangeListener(this);
|
model.setChangeListener(this);
|
||||||
addWorkPanel(create(block));
|
addWorkPanel(create(block, program));
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
setOkEnabled(false);
|
setOkEnabled(false);
|
||||||
@@ -109,16 +108,16 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
* Create the main work panel.
|
* Create the main work panel.
|
||||||
* @return JPanel
|
* @return JPanel
|
||||||
*/
|
*/
|
||||||
private JPanel create(MemoryBlock block) {
|
private JPanel create(MemoryBlock block, Program program) {
|
||||||
JPanel panel = new JPanel(new PairLayout(5, 5, 150));
|
JPanel panel = new JPanel(new PairLayout(5, 5, 150));
|
||||||
startAddressInput = new AddressInput();
|
AddressChangeListener listener = new AddressChangeListener();
|
||||||
|
|
||||||
|
startAddressInput = new AddressInput(program, listener);
|
||||||
startAddressInput.setName("NewStartAddress");
|
startAddressInput.setName("NewStartAddress");
|
||||||
startAddressInput.setAddressFactory(addrFactory);
|
|
||||||
startAddressInput.setAccessibleName("New Start Address");
|
startAddressInput.setAccessibleName("New Start Address");
|
||||||
|
|
||||||
endAddressInput = new AddressInput();
|
endAddressInput = new AddressInput(program, listener);
|
||||||
endAddressInput.setName("EndAddress");
|
endAddressInput.setName("EndAddress");
|
||||||
endAddressInput.setAddressFactory(addrFactory);
|
|
||||||
endAddressInput.setAccessibleName("New End Address");
|
endAddressInput.setAccessibleName("New End Address");
|
||||||
|
|
||||||
Address start = block.getStart();
|
Address start = block.getStart();
|
||||||
@@ -161,9 +160,6 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addListeners() {
|
private void addListeners() {
|
||||||
|
|
||||||
startAddressInput.addChangeListener(new AddressChangeListener());
|
|
||||||
endAddressInput.addChangeListener(new AddressChangeListener());
|
|
||||||
lengthField.setChangeListener(new LengthChangeListener());
|
lengthField.setChangeListener(new LengthChangeListener());
|
||||||
|
|
||||||
ActionListener al = e -> setStatusText("");
|
ActionListener al = e -> setStatusText("");
|
||||||
@@ -206,10 +202,10 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
|
|||||||
* Listener on the AddressInput field; update length field when the
|
* Listener on the AddressInput field; update length field when the
|
||||||
* address input field changes.
|
* address input field changes.
|
||||||
*/
|
*/
|
||||||
private class AddressChangeListener implements ChangeListener {
|
private class AddressChangeListener implements Consumer<Address> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(ChangeEvent event) {
|
public void accept(Address address) {
|
||||||
if (isChanging) {
|
if (isChanging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,7 +690,7 @@ class MemoryMapProvider extends ComponentProviderAdapter {
|
|||||||
"OTHER overlay blocks can not be split.");
|
"OTHER overlay blocks can not be split.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SplitBlockDialog d = new SplitBlockDialog(plugin, block, program.getAddressFactory());
|
SplitBlockDialog d = new SplitBlockDialog(plugin, block, program);
|
||||||
tool.showDialog(d, this);
|
tool.showDialog(d, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +711,7 @@ class MemoryMapProvider extends ComponentProviderAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExpandBlockDialog dialog =
|
ExpandBlockDialog dialog =
|
||||||
new ExpandBlockDialog(tool, model, block, program.getAddressFactory(), dialogType);
|
new ExpandBlockDialog(tool, model, block, program, dialogType);
|
||||||
model.initialize(block);
|
model.initialize(block);
|
||||||
dialog.dispose();
|
dialog.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -28,7 +28,7 @@ import ghidra.app.util.AddressInput;
|
|||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
@@ -82,9 +82,9 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||||||
setOkEnabled(false);
|
setOkEnabled(false);
|
||||||
changing = true;
|
changing = true;
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
AddressFactory factory = model.getAddressFactory();
|
Program program = model.getProgram();
|
||||||
newStartField.setAddressFactory(factory);
|
newStartField.setProgram(program);
|
||||||
newEndField.setAddressFactory(factory);
|
newEndField.setProgram(program);
|
||||||
}
|
}
|
||||||
Address newStart = model.getNewStartAddress();
|
Address newStart = model.getNewStartAddress();
|
||||||
if (newStart != null) {
|
if (newStart != null) {
|
||||||
@@ -136,8 +136,8 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buildMainPanel() {
|
private JPanel buildMainPanel() {
|
||||||
JPanel panel = new JPanel(new PairLayout(5, 20, 150));
|
JPanel panel = new JPanel(new PairLayout(2, 10, 150));
|
||||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
panel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
|
||||||
blockNameLabel = new GDLabel(".text");
|
blockNameLabel = new GDLabel(".text");
|
||||||
blockNameLabel.setName("blockName"); // name components for junits
|
blockNameLabel.setName("blockName"); // name components for junits
|
||||||
|
|
||||||
@@ -150,15 +150,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||||||
lengthLabel = new GDLabel("4096 (0x1000)");
|
lengthLabel = new GDLabel("4096 (0x1000)");
|
||||||
lengthLabel.setName("length");
|
lengthLabel.setName("length");
|
||||||
|
|
||||||
newStartField = new AddressInput();
|
newStartField = new AddressInput(model.getProgram(), this::startChanged);
|
||||||
newStartField.setName("newStart");
|
newStartField.setName("newStart");
|
||||||
|
|
||||||
newEndField = new AddressInput();
|
newEndField = new AddressInput(model.getProgram(), this::endChanged);
|
||||||
newEndField.setName("newEnd");
|
newEndField.setName("newEnd");
|
||||||
|
|
||||||
newStartField.addChangeListener(e -> startChanged());
|
|
||||||
newEndField.addChangeListener(e -> endChanged());
|
|
||||||
|
|
||||||
panel.add(new GLabel("Name:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Name:", SwingConstants.RIGHT));
|
||||||
panel.add(blockNameLabel);
|
panel.add(blockNameLabel);
|
||||||
panel.add(new GLabel("Start Address:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Start Address:", SwingConstants.RIGHT));
|
||||||
@@ -174,13 +171,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startChanged() {
|
private void startChanged(Address address) {
|
||||||
if (changing) {
|
if (changing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Address newStart = newStartField.getAddress();
|
if (address != null) {
|
||||||
if (newStart != null) {
|
model.setNewStartAddress(address);
|
||||||
model.setNewStartAddress(newStart);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setStatusText("Invalid Address");
|
setStatusText("Invalid Address");
|
||||||
@@ -188,13 +184,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void endChanged() {
|
private void endChanged(Address address) {
|
||||||
if (changing) {
|
if (changing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Address newEnd = newEndField.getAddress();
|
if (address != null) {
|
||||||
if (newEnd != null) {
|
model.setNewEndAddress(address);
|
||||||
model.setNewEndAddress(newEnd);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setStatusText("Invalid Address");
|
setStatusText("Invalid Address");
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -18,7 +18,8 @@ package ghidra.app.plugin.core.memory;
|
|||||||
import ghidra.app.cmd.memory.MoveBlockListener;
|
import ghidra.app.cmd.memory.MoveBlockListener;
|
||||||
import ghidra.app.cmd.memory.MoveBlockTask;
|
import ghidra.app.cmd.memory.MoveBlockTask;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
|
||||||
@@ -183,8 +184,8 @@ class MoveBlockModel implements DomainObjectListener {
|
|||||||
program = null;
|
program = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressFactory getAddressFactory() {
|
Program getProgram() {
|
||||||
return program.getAddressFactory();
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getEndAddress(Address start) {
|
private Address getEndAddress(Address start) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -27,7 +27,9 @@ import docking.widgets.label.GLabel;
|
|||||||
import ghidra.app.plugin.core.misc.RegisterField;
|
import ghidra.app.plugin.core.misc.RegisterField;
|
||||||
import ghidra.app.util.AddressInput;
|
import ghidra.app.util.AddressInput;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
@@ -50,16 +52,14 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
private JTextField blockTwoEndField;
|
private JTextField blockTwoEndField;
|
||||||
private RegisterField blockTwoLengthField;
|
private RegisterField blockTwoLengthField;
|
||||||
private MemoryBlock block;
|
private MemoryBlock block;
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private MemoryMapPlugin plugin;
|
private MemoryMapPlugin plugin;
|
||||||
|
|
||||||
SplitBlockDialog(MemoryMapPlugin plugin, MemoryBlock block, AddressFactory af) {
|
SplitBlockDialog(MemoryMapPlugin plugin, MemoryBlock block, Program program) {
|
||||||
super("Split Block");
|
super("Split Block");
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
addrFactory = af;
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP, "Split Block"));
|
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP, "Split Block"));
|
||||||
addWorkPanel(create());
|
addWorkPanel(create(program));
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
setOkEnabled(false);
|
setOkEnabled(false);
|
||||||
@@ -89,8 +89,8 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
* Create the work panel.
|
* Create the work panel.
|
||||||
* @return JPanel
|
* @return JPanel
|
||||||
*/
|
*/
|
||||||
private JPanel create() {
|
private JPanel create(Program program) {
|
||||||
JPanel panelOne = new JPanel(new PairLayout(5, 5, 150));
|
JPanel panelOne = new JPanel(new PairLayout(5, 10, 150));
|
||||||
panelOne.setBorder(BorderFactory.createTitledBorder("Block to Split"));
|
panelOne.setBorder(BorderFactory.createTitledBorder("Block to Split"));
|
||||||
blockOneNameField = new JTextField(10);
|
blockOneNameField = new JTextField(10);
|
||||||
blockOneNameField.setName("BlockOneName");
|
blockOneNameField.setName("BlockOneName");
|
||||||
@@ -99,7 +99,7 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
blockOneStartField.setName("BlockOneStart");
|
blockOneStartField.setName("BlockOneStart");
|
||||||
blockOneStartField.getAccessibleContext().setAccessibleName("Address of Block To Split");
|
blockOneStartField.getAccessibleContext().setAccessibleName("Address of Block To Split");
|
||||||
|
|
||||||
blockOneEnd = new AddressInput();
|
blockOneEnd = new AddressInput(program, this::blockOneEndChanged);
|
||||||
blockOneEnd.setName("BlockOneEnd");
|
blockOneEnd.setName("BlockOneEnd");
|
||||||
blockOneEnd.setAccessibleName("New Block End Adddress");
|
blockOneEnd.setAccessibleName("New Block End Adddress");
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
blockTwoNameField = new JTextField(10);
|
blockTwoNameField = new JTextField(10);
|
||||||
blockTwoNameField.setName("BlockTwoName");
|
blockTwoNameField.setName("BlockTwoName");
|
||||||
blockTwoNameField.getAccessibleContext().setAccessibleName("Name of New Block");
|
blockTwoNameField.getAccessibleContext().setAccessibleName("Name of New Block");
|
||||||
blockTwoStart = new AddressInput();
|
blockTwoStart = new AddressInput(program, this::blockTwoStartChanged);
|
||||||
blockTwoStart.setName("BlockTwoStart");
|
blockTwoStart.setName("BlockTwoStart");
|
||||||
blockTwoStart.setAccessibleName("New Block Start Address");
|
blockTwoStart.setAccessibleName("New Block Start Address");
|
||||||
blockTwoEndField = new JTextField(10);
|
blockTwoEndField = new JTextField(10);
|
||||||
@@ -141,11 +141,11 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
panelTwo.add(blockTwoLengthField);
|
panelTwo.add(blockTwoLengthField);
|
||||||
|
|
||||||
JPanel mainPanel = new JPanel();
|
JPanel mainPanel = new JPanel();
|
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
|
||||||
BoxLayout bl = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
|
BoxLayout bl = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
|
||||||
mainPanel.setLayout(bl);
|
mainPanel.setLayout(bl);
|
||||||
mainPanel.add(Box.createVerticalStrut(5));
|
|
||||||
mainPanel.add(panelOne);
|
mainPanel.add(panelOne);
|
||||||
mainPanel.add(Box.createVerticalStrut(10));
|
mainPanel.add(Box.createVerticalStrut(20));
|
||||||
mainPanel.add(panelTwo);
|
mainPanel.add(panelTwo);
|
||||||
|
|
||||||
return mainPanel;
|
return mainPanel;
|
||||||
@@ -166,7 +166,6 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
blockOneStartField.setText(startAddr.toString());
|
blockOneStartField.setText(startAddr.toString());
|
||||||
blockOneStartField.setEnabled(false);
|
blockOneStartField.setEnabled(false);
|
||||||
|
|
||||||
blockOneEnd.setAddressFactory(addrFactory);
|
|
||||||
blockOneEnd.setAddress(endAddr);
|
blockOneEnd.setAddress(endAddr);
|
||||||
blockOneEnd.setAddressSpaceEditable(false);
|
blockOneEnd.setAddressSpaceEditable(false);
|
||||||
|
|
||||||
@@ -174,7 +173,6 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
blockTwoNameField.setText(name + ".split");
|
blockTwoNameField.setText(name + ".split");
|
||||||
|
|
||||||
blockTwoStart.setAddressFactory(addrFactory);
|
|
||||||
blockTwoStart.setAddress(startAddr);
|
blockTwoStart.setAddress(startAddr);
|
||||||
blockTwoStart.setAddressSpaceEditable(false);
|
blockTwoStart.setAddressSpaceEditable(false);
|
||||||
|
|
||||||
@@ -189,8 +187,6 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
blockOneLengthField.setChangeListener(new LengthChangeListener(blockOneLengthField));
|
blockOneLengthField.setChangeListener(new LengthChangeListener(blockOneLengthField));
|
||||||
blockTwoLengthField.setChangeListener(new LengthChangeListener(blockTwoLengthField));
|
blockTwoLengthField.setChangeListener(new LengthChangeListener(blockTwoLengthField));
|
||||||
blockOneEnd.addChangeListener(new AddressChangeListener(blockOneEnd));
|
|
||||||
blockTwoStart.addChangeListener(new AddressChangeListener(blockTwoStart));
|
|
||||||
|
|
||||||
ActionListener al = e -> setStatusText("");
|
ActionListener al = e -> setStatusText("");
|
||||||
blockOneLengthField.addActionListener(al);
|
blockOneLengthField.addActionListener(al);
|
||||||
@@ -307,135 +303,101 @@ class SplitBlockDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void blockOneEndChanged(Address end) {
|
||||||
* Listener on the AddressInput fields; update other fields when either
|
setStatusText("");
|
||||||
* of these fields change.
|
boolean isValid = checkBlockOneEndAddress(end);
|
||||||
*/
|
setOkEnabled(isValid);
|
||||||
private class AddressChangeListener implements ChangeListener {
|
}
|
||||||
|
|
||||||
AddressInput source;
|
private void blockTwoStartChanged(Address start) {
|
||||||
|
setStatusText("");
|
||||||
|
boolean isValid = checkBlockTwoStartChanged(start);
|
||||||
|
setOkEnabled(isValid);
|
||||||
|
}
|
||||||
|
|
||||||
public AddressChangeListener(AddressInput source) {
|
private boolean checkBlockOneEndAddress(Address end) {
|
||||||
this.source = source;
|
|
||||||
|
if (end == null) {
|
||||||
|
setStatusText("Invalid Address");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
Address start = block.getStart();
|
||||||
public void stateChanged(ChangeEvent event) {
|
|
||||||
setStatusText("");
|
if (end.compareTo(start) < 0) {
|
||||||
boolean ok = false;
|
setStatusText("End address must be greater than start");
|
||||||
if (source == blockOneEnd) {
|
return false;
|
||||||
ok = blockOneEndChanged();
|
|
||||||
}
|
|
||||||
else if (source == blockTwoStart) {
|
|
||||||
ok = blockTwoStartChanged();
|
|
||||||
}
|
|
||||||
setOkEnabled(ok);
|
|
||||||
}
|
}
|
||||||
|
if (end.compareTo(block.getEnd()) == 0) {
|
||||||
private Address getAddress() throws InvalidInputException {
|
return false;
|
||||||
|
|
||||||
AddressInput field = source;
|
|
||||||
Address addr = field.getAddress();
|
|
||||||
if (addr == null && field.hasInput()) {
|
|
||||||
throw new InvalidInputException();
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
// change block One length and blockTwoStart, blockTwoLength
|
||||||
private boolean blockOneEndChanged() {
|
long length = 0;
|
||||||
Address start = block.getStart();
|
try {
|
||||||
Address end = null;
|
length = end.subtract(start) + 1;
|
||||||
try {
|
|
||||||
end = getAddress();
|
|
||||||
}
|
|
||||||
catch (InvalidInputException e) {
|
|
||||||
setStatusText("Invalid Address");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (end.compareTo(start) < 0) {
|
|
||||||
setStatusText("End address must be greater than start");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (end.compareTo(block.getEnd()) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// change block One length and blockTwoStart, blockTwoLength
|
|
||||||
long length = 0;
|
|
||||||
try {
|
|
||||||
length = end.subtract(start) + 1;
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException e) {
|
|
||||||
setStatusText(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
long blockSize = block.getSize();
|
|
||||||
if (length > blockSize) {
|
|
||||||
setStatusText(
|
|
||||||
"End address must be less than original block end (" + block.getEnd() + ")");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
blockOneLengthField.setValue(Long.valueOf(length));
|
|
||||||
|
|
||||||
try {
|
|
||||||
Address b2Start = end.addNoWrap(1);
|
|
||||||
blockTwoStart.setAddress(b2Start);
|
|
||||||
length = block.getEnd().subtract(b2Start) + 1;
|
|
||||||
blockTwoLengthField.setValue(Long.valueOf(length));
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
if (e instanceof AddressOverflowException) {
|
|
||||||
setStatusText("Could not create new start address");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
setStatusText(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long blockSize = block.getSize();
|
||||||
|
if (length > blockSize) {
|
||||||
|
setStatusText(
|
||||||
|
"End address must be less than original block end (" + block.getEnd() + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
blockOneLengthField.setValue(Long.valueOf(length));
|
||||||
|
|
||||||
private boolean blockTwoStartChanged() {
|
try {
|
||||||
Address start = null;
|
Address b2Start = end.addNoWrap(1);
|
||||||
try {
|
blockTwoStart.setAddress(b2Start);
|
||||||
start = getAddress();
|
length = block.getEnd().subtract(b2Start) + 1;
|
||||||
}
|
|
||||||
catch (InvalidInputException e) {
|
|
||||||
setStatusText("Invalid Address");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Address end = block.getEnd();
|
|
||||||
if (start == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (start.compareTo(end) > 0) {
|
|
||||||
setStatusText("Start address must not be greater than end");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (start.compareTo(block.getStart()) <= 0) {
|
|
||||||
setStatusText("Start address must be greater than original block start (" +
|
|
||||||
block.getStart() + ")");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// change block Two length, blockOneEnd, block One length
|
|
||||||
long length = end.subtract(start) + 1;
|
|
||||||
blockTwoLengthField.setValue(Long.valueOf(length));
|
blockTwoLengthField.setValue(Long.valueOf(length));
|
||||||
try {
|
|
||||||
Address b1End = start.subtractNoWrap(1);
|
|
||||||
blockOneEnd.setAddress(b1End);
|
|
||||||
length = b1End.subtract(block.getStart()) + 1;
|
|
||||||
blockOneLengthField.setValue(Long.valueOf(length));
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
if (e instanceof AddressOverflowException) {
|
|
||||||
setStatusText("Could not create end address for split block");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if (e instanceof AddressOverflowException) {
|
||||||
|
setStatusText("Could not create new start address");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkBlockTwoStartChanged(Address start) {
|
||||||
|
if (start == null) {
|
||||||
|
setStatusText("Invalid Address");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Address end = block.getEnd();
|
||||||
|
if (start == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (start.compareTo(end) > 0) {
|
||||||
|
setStatusText("Start address must not be greater than end");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (start.compareTo(block.getStart()) <= 0) {
|
||||||
|
setStatusText("Start address must be greater than original block start (" +
|
||||||
|
block.getStart() + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change block Two length, blockOneEnd, block One length
|
||||||
|
long length = end.subtract(start) + 1;
|
||||||
|
blockTwoLengthField.setValue(Long.valueOf(length));
|
||||||
|
try {
|
||||||
|
Address b1End = start.subtractNoWrap(1);
|
||||||
|
blockOneEnd.setAddress(b1End);
|
||||||
|
length = b1End.subtract(block.getStart()) + 1;
|
||||||
|
blockOneLengthField.setValue(Long.valueOf(length));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if (e instanceof AddressOverflowException) {
|
||||||
|
setStatusText("Could not create end address for split block");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -231,7 +231,7 @@ class EditExternalReferencePanel extends EditReferencePanel {
|
|||||||
updateExtLibPath();
|
updateExtLibPath();
|
||||||
|
|
||||||
extLabel.setText(extLoc.getLabel());
|
extLabel.setText(extLoc.getLabel());
|
||||||
extAddr.setAddressFactory(program.getAddressFactory());
|
extAddr.setProgram(program);
|
||||||
Address addr = extLoc.getAddress();
|
Address addr = extLoc.getAddress();
|
||||||
if (addr != null) {
|
if (addr != null) {
|
||||||
extAddr.setAddress(addr);
|
extAddr.setAddress(addr);
|
||||||
@@ -260,7 +260,7 @@ class EditExternalReferencePanel extends EditReferencePanel {
|
|||||||
extLibPath.setText(null);
|
extLibPath.setText(null);
|
||||||
|
|
||||||
extLabel.setText(null);
|
extLabel.setText(null);
|
||||||
extAddr.setAddressFactory(program.getAddressFactory());
|
extAddr.setProgram(program);
|
||||||
extAddr.clear();
|
extAddr.clear();
|
||||||
|
|
||||||
extLibName.requestFocus();
|
extLibName.requestFocus();
|
||||||
|
|||||||
@@ -191,7 +191,8 @@ class EditMemoryReferencePanel extends EditReferencePanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeToAddressField(Address toAddr) {
|
private void initializeToAddressField(Address toAddr) {
|
||||||
toAddressField.setAddressFactory(fromCodeUnit.getProgram().getAddressFactory(), (s) -> {
|
Program program = fromCodeUnit.getProgram();
|
||||||
|
toAddressField.setProgram(program, (s) -> {
|
||||||
if (s.isLoadedMemorySpace()) {
|
if (s.isLoadedMemorySpace()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -19,8 +19,6 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
import javax.swing.event.ChangeListener;
|
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
import docking.DialogComponentProvider;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
@@ -30,7 +28,7 @@ import ghidra.app.util.AddressInput;
|
|||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
@@ -44,7 +42,6 @@ import ghidra.util.layout.PairLayout;
|
|||||||
public class OffsetTableDialog extends DialogComponentProvider {
|
public class OffsetTableDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private AddressInput addrInput;
|
private AddressInput addrInput;
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private JComboBox<String> comboBox;
|
private JComboBox<String> comboBox;
|
||||||
private Address defaultAddress;
|
private Address defaultAddress;
|
||||||
private JCheckBox signedCheckBox;
|
private JCheckBox signedCheckBox;
|
||||||
@@ -52,15 +49,13 @@ public class OffsetTableDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new dialog
|
* Construct a new dialog
|
||||||
* @param parent parent of this dialog
|
|
||||||
* @param defaultAddress address to put in the address field as a default
|
* @param defaultAddress address to put in the address field as a default
|
||||||
* @param addrFactory address factory required by AddressInput object
|
* @param program the program
|
||||||
*/
|
*/
|
||||||
OffsetTableDialog(Address defaultAddress, AddressFactory addrFactory) {
|
OffsetTableDialog(Address defaultAddress, Program program) {
|
||||||
super("Create Offset References", true);
|
super("Create Offset References", true);
|
||||||
this.defaultAddress = defaultAddress;
|
this.defaultAddress = defaultAddress;
|
||||||
this.addrFactory = addrFactory;
|
addWorkPanel(buildMainPanel(program));
|
||||||
addWorkPanel(buildMainPanel());
|
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.REFERENCES, "Create_Offset_References"));
|
setHelpLocation(new HelpLocation(HelpTopics.REFERENCES, "Create_Offset_References"));
|
||||||
@@ -128,23 +123,16 @@ public class OffsetTableDialog extends DialogComponentProvider {
|
|||||||
signedCheckBox.setSelected(isSigned);
|
signedCheckBox.setSelected(isSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buildMainPanel() {
|
private JPanel buildMainPanel(Program program) {
|
||||||
JPanel panel = new JPanel(new PairLayout(10, 5));
|
JPanel panel = new JPanel(new PairLayout(10, 5));
|
||||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
|
||||||
addrInput = new AddressInput();
|
addrInput = new AddressInput(program, a -> clearStatusText());
|
||||||
addrInput.addActionListener(new ActionListener() {
|
addrInput.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
okCallback();
|
okCallback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
addrInput.addChangeListener(new ChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
clearStatusText();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addrInput.setAddressFactory(addrFactory);
|
|
||||||
addrInput.setAddress(defaultAddress);
|
addrInput.setAddress(defaultAddress);
|
||||||
|
|
||||||
panel.add(new GLabel("Enter Base Address:", SwingConstants.RIGHT));
|
panel.add(new GLabel("Enter Base Address:", SwingConstants.RIGHT));
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -101,10 +101,10 @@ public class OffsetTablePlugin extends Plugin {
|
|||||||
true);
|
true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddressFactory addressFactory = context.getProgram().getAddressFactory();
|
Program program = context.getProgram();
|
||||||
Address minAddress = context.getSelection().getMinAddress();
|
Address minAddress = context.getSelection().getMinAddress();
|
||||||
|
|
||||||
OffsetTableDialog dialog = new OffsetTableDialog(minAddress, addressFactory);
|
OffsetTableDialog dialog = new OffsetTableDialog(minAddress, program);
|
||||||
dialog.setSelectedSize(lastSelectedSize);
|
dialog.setSelectedSize(lastSelectedSize);
|
||||||
dialog.setSigned(lastSigned);
|
dialog.setSigned(lastSigned);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,17 +16,18 @@
|
|||||||
package ghidra.app.plugin.core.register;
|
package ghidra.app.plugin.core.register;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
import javax.swing.event.ChangeListener;
|
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
import docking.DialogComponentProvider;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import ghidra.app.util.AddressInput;
|
import ghidra.app.util.AddressInput;
|
||||||
import ghidra.app.util.bean.FixedBitSizeValueField;
|
import ghidra.app.util.bean.FixedBitSizeValueField;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.MessageType;
|
import ghidra.util.MessageType;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
@@ -39,9 +40,9 @@ class EditRegisterValueDialog extends DialogComponentProvider {
|
|||||||
private boolean wasCancelled = true;
|
private boolean wasCancelled = true;
|
||||||
|
|
||||||
EditRegisterValueDialog(Register register, Address start, Address end, BigInteger value,
|
EditRegisterValueDialog(Register register, Address start, Address end, BigInteger value,
|
||||||
AddressFactory factory) {
|
Program program) {
|
||||||
super("Edit Register Value Range");
|
super("Edit Register Value Range");
|
||||||
addWorkPanel(buildWorkPanel(register, start, end, value, factory));
|
addWorkPanel(buildWorkPanel(register, start, end, value, program));
|
||||||
|
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
@@ -49,24 +50,15 @@ class EditRegisterValueDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JComponent buildWorkPanel(Register register, Address start, Address end,
|
private JComponent buildWorkPanel(Register register, Address start, Address end,
|
||||||
BigInteger value, AddressFactory factory) {
|
BigInteger value, Program program) {
|
||||||
|
|
||||||
JTextField registerField =
|
JTextField registerField =
|
||||||
new JTextField(register.getName() + " (" + register.getBitLength() + ")");
|
new JTextField(register.getName() + " (" + register.getBitLength() + ")");
|
||||||
registerField.setEditable(false);
|
registerField.setEditable(false);
|
||||||
|
|
||||||
startAddrField = new AddressInput();
|
Consumer<Address> addressChangeListener = a -> updateOk();
|
||||||
endAddrField = new AddressInput();
|
startAddrField = new AddressInput(program, addressChangeListener);
|
||||||
ChangeListener changeListener = new ChangeListener() {
|
endAddrField = new AddressInput(program, addressChangeListener);
|
||||||
@Override
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
updateOk();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
startAddrField.setAddressFactory(factory);
|
|
||||||
endAddrField.setAddressFactory(factory);
|
|
||||||
startAddrField.addChangeListener(changeListener);
|
|
||||||
endAddrField.addChangeListener(changeListener);
|
|
||||||
|
|
||||||
registerValueField = new FixedBitSizeValueField(register.getBitLength(), true, false);
|
registerValueField = new FixedBitSizeValueField(register.getBitLength(), true, false);
|
||||||
startAddrField.setAddress(start);
|
startAddrField.setAddress(start);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -89,7 +89,7 @@ class RegisterValuesPanel extends JPanel {
|
|||||||
Address end = range.getEndAddress();
|
Address end = range.getEndAddress();
|
||||||
BigInteger value = range.getValue();
|
BigInteger value = range.getValue();
|
||||||
EditRegisterValueDialog dialog = new EditRegisterValueDialog(selectedRegister, start, end,
|
EditRegisterValueDialog dialog = new EditRegisterValueDialog(selectedRegister, start, end,
|
||||||
value, currentProgram.getAddressFactory());
|
value, currentProgram);
|
||||||
tool.showDialog(dialog, this);
|
tool.showDialog(dialog, this);
|
||||||
|
|
||||||
if (!dialog.wasCancelled()) {
|
if (!dialog.wasCancelled()) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -300,7 +300,7 @@ class EditExternalLocationPanel extends JPanel {
|
|||||||
if (extOriginalLabelTextField != null) {
|
if (extOriginalLabelTextField != null) {
|
||||||
extOriginalLabelTextField.setText(startingOriginalName);
|
extOriginalLabelTextField.setText(startingOriginalName);
|
||||||
}
|
}
|
||||||
extAddressInputWidget.setAddressFactory(program.getAddressFactory());
|
extAddressInputWidget.setProgram(program);
|
||||||
if (startingLocationAddress != null) {
|
if (startingLocationAddress != null) {
|
||||||
extAddressInputWidget.setAddress(startingLocationAddress);
|
extAddressInputWidget.setAddress(startingLocationAddress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2630,7 +2630,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Address choice = doAsk(Integer.class, title, message, existingValue, lastValue -> {
|
Address choice = doAsk(Integer.class, title, message, existingValue, lastValue -> {
|
||||||
|
|
||||||
AskAddrDialog dialog =
|
AskAddrDialog dialog =
|
||||||
new AskAddrDialog(title, message, currentProgram.getAddressFactory(), lastValue);
|
new AskAddrDialog(title, message, currentProgram, lastValue);
|
||||||
if (dialog.isCanceled()) {
|
if (dialog.isCanceled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -67,10 +67,7 @@ public class AddressSetEditorPanel extends JPanel {
|
|||||||
JLabel minLabel = new GDLabel("Min:");
|
JLabel minLabel = new GDLabel("Min:");
|
||||||
minLabel.setToolTipText("Enter minimum address to add or remove");
|
minLabel.setToolTipText("Enter minimum address to add or remove");
|
||||||
minAddressPanel.add(minLabel, BorderLayout.WEST);
|
minAddressPanel.add(minLabel, BorderLayout.WEST);
|
||||||
minAddressField = new AddressInput();
|
minAddressField = new AddressInput(addressFactory, a -> validateAddRemoveButton());
|
||||||
minAddressField.setAddressFactory(addressFactory);
|
|
||||||
ChangeListener listener = e -> validateAddRemoveButton();
|
|
||||||
minAddressField.addChangeListener(listener);
|
|
||||||
minAddressPanel.add(minAddressField, BorderLayout.CENTER);
|
minAddressPanel.add(minAddressField, BorderLayout.CENTER);
|
||||||
|
|
||||||
JPanel maxAddressPanel = new JPanel();
|
JPanel maxAddressPanel = new JPanel();
|
||||||
@@ -78,9 +75,7 @@ public class AddressSetEditorPanel extends JPanel {
|
|||||||
JLabel maxLabel = new GDLabel("Max:");
|
JLabel maxLabel = new GDLabel("Max:");
|
||||||
maxLabel.setToolTipText("Enter maximum address to add or remove");
|
maxLabel.setToolTipText("Enter maximum address to add or remove");
|
||||||
maxAddressPanel.add(maxLabel, BorderLayout.WEST);
|
maxAddressPanel.add(maxLabel, BorderLayout.WEST);
|
||||||
maxAddressField = new AddressInput();
|
maxAddressField = new AddressInput(addressFactory, a -> validateAddRemoveButton());
|
||||||
maxAddressField.setAddressFactory(addressFactory);
|
|
||||||
maxAddressField.addChangeListener(listener);
|
|
||||||
maxAddressPanel.add(maxAddressField, BorderLayout.CENTER);
|
maxAddressPanel.add(maxAddressField, BorderLayout.CENTER);
|
||||||
maxAddressPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
|
maxAddressPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
|
||||||
addRangeButton = new GButton(ADD_ICON);
|
addRangeButton = new GButton(ADD_ICON);
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ public class OptionsEditorPanel extends JPanel {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
AddressFactory addressFactory = addressFactoryService.getAddressFactory();
|
AddressFactory addressFactory = addressFactoryService.getAddressFactory();
|
||||||
AddressInput addressInput = new AddressInput();
|
AddressInput addressInput = new AddressInput(a -> option.setValue(a));
|
||||||
addressInput.setName(option.getName());
|
addressInput.setName(option.getName());
|
||||||
Address addr = (Address) option.getValue();
|
Address addr = (Address) option.getValue();
|
||||||
if (addr == null && addressFactory != null) {
|
if (addr == null && addressFactory != null) {
|
||||||
@@ -347,7 +347,6 @@ public class OptionsEditorPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
addressInput.setAddressFactory(addressFactory);
|
addressInput.setAddressFactory(addressFactory);
|
||||||
addressInput.setAddress(addr);
|
addressInput.setAddress(addr);
|
||||||
addressInput.addChangeListener(e -> option.setValue(addressInput.getAddress()));// addressInput.addActionListener(e -> option.setValue(addressInput.getAddress()));
|
|
||||||
return addressInput;
|
return addressInput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -18,9 +18,9 @@ package ghidra.app.util.cparser.CPP;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import generic.expressions.ExpressionEvaluator;
|
||||||
import ghidra.app.util.cparser.CPP.PreProcessor.PPToken;
|
import ghidra.app.util.cparser.CPP.PreProcessor.PPToken;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.util.AddressEvaluator;
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,14 +281,13 @@ public class DefineTable {
|
|||||||
|
|
||||||
StringBuffer buf = new StringBuffer(image);
|
StringBuffer buf = new StringBuffer(image);
|
||||||
int lastReplPos = pos;
|
int lastReplPos = pos;
|
||||||
|
|
||||||
boolean initialListSupplied = initialList != null; // initial list passed in
|
boolean initialListSupplied = initialList != null; // initial list passed in
|
||||||
ArrayList<String> sublist = new ArrayList<String>();
|
ArrayList<String> sublist = new ArrayList<String>();
|
||||||
if (initialList != null) {
|
if (initialList != null) {
|
||||||
sublist.addAll(initialList);
|
sublist.addAll(initialList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// don't replace an infinite number of times. Fail safe for possible ininite loop
|
// don't replace an infinite number of times. Fail safe for possible ininite loop
|
||||||
while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
|
while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
|
||||||
// clear list of used macros when move past replacement area
|
// clear list of used macros when move past replacement area
|
||||||
@@ -353,7 +352,8 @@ public class DefineTable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int replace(StringBuffer buf, String currKey, int fromIndex, ArrayList<String> sublist, boolean initialList) {
|
int replace(StringBuffer buf, String currKey, int fromIndex, ArrayList<String> sublist,
|
||||||
|
boolean initialList) {
|
||||||
String replacementString = null;
|
String replacementString = null;
|
||||||
|
|
||||||
if (sublist == null) {
|
if (sublist == null) {
|
||||||
@@ -451,11 +451,11 @@ public class DefineTable {
|
|||||||
argValue + " args processed : " + argsfound);
|
argValue + " args processed : " + argsfound);
|
||||||
return replString;
|
return replString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle "..." varargs
|
// Handle "..." varargs
|
||||||
// if last argument is ellipsis, then is varargs, replace the rest of the params
|
// if last argument is ellipsis, then is varargs, replace the rest of the params
|
||||||
String curArgName = argv.elementAt(index).image;
|
String curArgName = argv.elementAt(index).image;
|
||||||
if (index == argv.size()-1 && VARARG_ELLIPSIS.equals(curArgName)) {
|
if (index == argv.size() - 1 && VARARG_ELLIPSIS.equals(curArgName)) {
|
||||||
isVarArg = true;
|
isVarArg = true;
|
||||||
// Replace __VA_ARGS__ with the rest of params
|
// Replace __VA_ARGS__ with the rest of params
|
||||||
curArgName = "__VA_ARGS__";
|
curArgName = "__VA_ARGS__";
|
||||||
@@ -526,14 +526,14 @@ public class DefineTable {
|
|||||||
startpos = end;
|
startpos = end;
|
||||||
}
|
}
|
||||||
buf.append(substString.substring(startpos));
|
buf.append(substString.substring(startpos));
|
||||||
|
|
||||||
// Handle __VA_OPT__(<repl>)
|
// Handle __VA_OPT__(<repl>)
|
||||||
// if varargs and no more params, replace with ""
|
// if varargs and no more params, replace with ""
|
||||||
// if varargs and has vararg params, replace with <repl>
|
// if varargs and has vararg params, replace with <repl>
|
||||||
if (isVarArg) {
|
if (isVarArg) {
|
||||||
replace_VaOpt(buf, hadVarArgs);
|
replace_VaOpt(buf, hadVarArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
substString = buf.toString();
|
substString = buf.toString();
|
||||||
return substString;
|
return substString;
|
||||||
}
|
}
|
||||||
@@ -544,28 +544,29 @@ public class DefineTable {
|
|||||||
* @param buf string buffer to replace __VA_OPT__(value) within
|
* @param buf string buffer to replace __VA_OPT__(value) within
|
||||||
* @param hadVarArgs
|
* @param hadVarArgs
|
||||||
*/
|
*/
|
||||||
private void replace_VaOpt(StringBuffer buf, boolean hadVarArgs) {
|
private void replace_VaOpt(StringBuffer buf, boolean hadVarArgs) {
|
||||||
int optIdx = buf.indexOf("__VA_OPT__");
|
int optIdx = buf.indexOf("__VA_OPT__");
|
||||||
if (optIdx < 0) {
|
if (optIdx < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lparen = buf.indexOf("(", optIdx+1);
|
int lparen = buf.indexOf("(", optIdx + 1);
|
||||||
if (lparen < 0) {
|
if (lparen < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rparen = buf.indexOf(")",lparen+1);
|
int rparen = buf.indexOf(")", lparen + 1);
|
||||||
if (rparen < 0) {
|
if (rparen < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get in between string.
|
// get in between string.
|
||||||
String replarg = buf.substring(lparen+1, rparen);
|
String replarg = buf.substring(lparen + 1, rparen);
|
||||||
if (hadVarArgs) {
|
if (hadVarArgs) {
|
||||||
buf.replace(optIdx, rparen+1, replarg);
|
buf.replace(optIdx, rparen + 1, replarg);
|
||||||
} else {
|
}
|
||||||
buf.replace(optIdx, rparen+1, "");
|
else {
|
||||||
|
buf.replace(optIdx, rparen + 1, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +630,7 @@ public class DefineTable {
|
|||||||
public String expand(String image, boolean join) {
|
public String expand(String image, boolean join) {
|
||||||
return expand(image, join, null);
|
return expand(image, join, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do the final expansion of "##" concats in the define strings that protect normal macro substitution.
|
* do the final expansion of "##" concats in the define strings that protect normal macro substitution.
|
||||||
*
|
*
|
||||||
@@ -639,7 +640,7 @@ public class DefineTable {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String expand(String image, boolean join, ArrayList<String> list) {
|
public String expand(String image, boolean join, ArrayList<String> list) {
|
||||||
|
|
||||||
image = macroSub(image, 0, list);
|
image = macroSub(image, 0, list);
|
||||||
|
|
||||||
// get rid of ## constructs
|
// get rid of ## constructs
|
||||||
@@ -705,13 +706,13 @@ public class DefineTable {
|
|||||||
Iterator<String> iter = getDefineNames();
|
Iterator<String> iter = getDefineNames();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
String defName = iter.next();
|
String defName = iter.next();
|
||||||
|
|
||||||
String strValue = expandDefine(defName);
|
String strValue = expandDefine(defName);
|
||||||
if (strValue == null) {
|
if (strValue == null) {
|
||||||
// couldn't expand, must have been a macro
|
// couldn't expand, must have been a macro
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip off any casting/parentheses
|
// strip off any casting/parentheses
|
||||||
strValue = stripCast(strValue);
|
strValue = stripCast(strValue);
|
||||||
|
|
||||||
@@ -720,7 +721,7 @@ public class DefineTable {
|
|||||||
|
|
||||||
if (lvalue == null) {
|
if (lvalue == null) {
|
||||||
try {
|
try {
|
||||||
lvalue = AddressEvaluator.evaluateToLong(strValue);
|
lvalue = ExpressionEvaluator.evaluateToLong(strValue);
|
||||||
}
|
}
|
||||||
catch (Exception exc) {
|
catch (Exception exc) {
|
||||||
// ignore didn't parse well
|
// ignore didn't parse well
|
||||||
@@ -738,7 +739,8 @@ public class DefineTable {
|
|||||||
dtMgr.endTransaction(transactionID, true);
|
dtMgr.endTransaction(transactionID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void populateDefineEquate(DataTypeManager openDTMgrs[], DataTypeManager dtMgr, String category, String prefix, String defName, long value) {
|
public void populateDefineEquate(DataTypeManager openDTMgrs[], DataTypeManager dtMgr,
|
||||||
|
String category, String prefix, String defName, long value) {
|
||||||
String enumName = prefix + defName;
|
String enumName = prefix + defName;
|
||||||
|
|
||||||
// Start the Enum at 8, then resize to fit the value
|
// Start the Enum at 8, then resize to fit the value
|
||||||
@@ -751,33 +753,33 @@ public class DefineTable {
|
|||||||
CategoryPath path = getCategory(currentCategoryName);
|
CategoryPath path = getCategory(currentCategoryName);
|
||||||
path = new CategoryPath(path, category);
|
path = new CategoryPath(path, category);
|
||||||
enuum.setCategoryPath(path);
|
enuum.setCategoryPath(path);
|
||||||
|
|
||||||
DataType dt = resolveDataType(openDTMgrs, path, enuum);
|
DataType dt = resolveDataType(openDTMgrs, path, enuum);
|
||||||
|
|
||||||
dtMgr.addDataType(dt, DataTypeConflictHandler.DEFAULT_HANDLER);
|
dtMgr.addDataType(dt, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataType resolveDataType(DataTypeManager openDTMgrs[], CategoryPath path, DataType dt) {
|
|
||||||
if (openDTMgrs == null) {
|
|
||||||
return dt;
|
|
||||||
}
|
|
||||||
// If the exact data type exists in any open DTMgr, use the open DTmgr type
|
|
||||||
// instead
|
|
||||||
|
|
||||||
for (int i = 0; i < openDTMgrs.length; i++) {
|
private DataType resolveDataType(DataTypeManager openDTMgrs[], CategoryPath path, DataType dt) {
|
||||||
// look for the data type by name
|
if (openDTMgrs == null) {
|
||||||
// equivalent, return it
|
return dt;
|
||||||
// look for the data type by category
|
}
|
||||||
// equivalent, return it
|
// If the exact data type exists in any open DTMgr, use the open DTmgr type
|
||||||
DataType candidateDT = openDTMgrs[i].getDataType(dt.getCategoryPath(), dt.getName());
|
// instead
|
||||||
|
|
||||||
if (candidateDT != null && candidateDT.isEquivalent(candidateDT)) {
|
|
||||||
return candidateDT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dt;
|
for (int i = 0; i < openDTMgrs.length; i++) {
|
||||||
}
|
// look for the data type by name
|
||||||
|
// equivalent, return it
|
||||||
|
// look for the data type by category
|
||||||
|
// equivalent, return it
|
||||||
|
DataType candidateDT = openDTMgrs[i].getDataType(dt.getCategoryPath(), dt.getName());
|
||||||
|
|
||||||
|
if (candidateDT != null && candidateDT.isEquivalent(candidateDT)) {
|
||||||
|
return candidateDT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
public String expandDefine(String defName) {
|
public String expandDefine(String defName) {
|
||||||
// don't worry about macros
|
// don't worry about macros
|
||||||
@@ -789,13 +791,13 @@ public class DefineTable {
|
|||||||
// check if this is a numeric expression that could be simplified
|
// check if this is a numeric expression that could be simplified
|
||||||
//
|
//
|
||||||
String strValue = getValue(defName);
|
String strValue = getValue(defName);
|
||||||
|
|
||||||
ArrayList<String> list = new ArrayList();
|
ArrayList<String> list = new ArrayList();
|
||||||
list.add(defName);
|
list.add(defName);
|
||||||
|
|
||||||
String strExpanded = expand(strValue, true, list);
|
String strExpanded = expand(strValue, true, list);
|
||||||
strValue = strExpanded;
|
strValue = strExpanded;
|
||||||
|
|
||||||
return strValue;
|
return strValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -25,19 +25,17 @@ import docking.DockingWindowManager;
|
|||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import ghidra.app.util.AddressInput;
|
import ghidra.app.util.AddressInput;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
public class AskAddrDialog extends DialogComponentProvider {
|
public class AskAddrDialog extends DialogComponentProvider {
|
||||||
private boolean isCanceled;
|
private boolean isCanceled;
|
||||||
private AddressInput addrInput;
|
private AddressInput addrInput;
|
||||||
|
|
||||||
public AskAddrDialog(final String title, final String message, AddressFactory af,
|
public AskAddrDialog(final String title, final String message, Program program,
|
||||||
Address lastAddr) {
|
Address lastAddr) {
|
||||||
super(title, true, true, true, false);
|
super(title, true, true, true, false);
|
||||||
|
|
||||||
addrInput = new AddressInput();
|
addrInput = new AddressInput(program);
|
||||||
addrInput.setAddressFactory(af);
|
|
||||||
addrInput.selectDefaultAddressSpace();
|
|
||||||
if (lastAddr != null) {
|
if (lastAddr != null) {
|
||||||
addrInput.setAddress(lastAddr);
|
addrInput.setAddress(lastAddr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -251,7 +251,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
addrField.setValue("0x200");
|
addrField.setText("0x200");
|
||||||
nameField.setText(".test");
|
nameField.setText(".test");
|
||||||
lengthField.setText("0x100");
|
lengthField.setText("0x100");
|
||||||
commentField.setText("this is a block test");
|
commentField.setText("this is a block test");
|
||||||
@@ -319,7 +319,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
addrField.setValue("0x01001200");
|
addrField.setText("0x01001200");
|
||||||
nameField.setText(".test");
|
nameField.setText(".test");
|
||||||
lengthField.setText("0x100");
|
lengthField.setText("0x100");
|
||||||
commentField.setText("this is a block test");
|
commentField.setText("this is a block test");
|
||||||
@@ -354,7 +354,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
addrField.setValue("xxxxx");
|
addrField.setText("xxxxx");
|
||||||
nameField.setText(".test");
|
nameField.setText(".test");
|
||||||
lengthField.setText("0x100");
|
lengthField.setText("0x100");
|
||||||
commentField.setText("this is a block test");
|
commentField.setText("this is a block test");
|
||||||
@@ -364,7 +364,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
|
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Please enter a valid Start Address", msg);
|
assertEquals("Invalid Address: Could not evaluate token \"xxxxx\"", msg);
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
close(d);
|
close(d);
|
||||||
}
|
}
|
||||||
@@ -768,7 +768,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Please enter a source address for the bit block", msg);
|
assertEquals("Please enter a source address for the bit block", msg);
|
||||||
runSwing(() -> addrField.setValue("01001000"));
|
runSwing(() -> addrField.setText("01001000"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
@@ -844,7 +844,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Please enter a source address for the bit block", msg);
|
assertEquals("Please enter a source address for the bit block", msg);
|
||||||
runSwing(() -> addrField.setValue("01001000"));
|
runSwing(() -> addrField.setText("01001000"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
@@ -1040,7 +1040,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
// move the block to 0x300
|
// move the block to 0x300
|
||||||
Address newStart = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x300);
|
Address newStart = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x300);
|
||||||
Address newEnd = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x3ff);
|
Address newEnd = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x3ff);
|
||||||
runSwing(() -> startField.setValue(newStart));
|
runSwing(() -> startField.simulateAddressChanged(newStart));
|
||||||
assertEquals(newEnd, endField.getAddress());
|
assertEquals(newEnd, endField.getAddress());
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
|
|
||||||
@@ -1110,7 +1110,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
|
|
||||||
// enter an invalid address
|
// enter an invalid address
|
||||||
runSwing(() -> startField.setValue(getAddr(0x0300).toString() + "gggg"));
|
runSwing(() -> startField.setText(getAddr(0x0300).toString() + "gggg"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Invalid Address", msg);
|
assertEquals("Invalid Address", msg);
|
||||||
@@ -1168,7 +1168,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
|
|
||||||
// enter an invalid address
|
// enter an invalid address
|
||||||
runSwing(() -> endField.setValue(getAddr(0x0300).toString() + "gggg"));
|
runSwing(() -> endField.setText(getAddr(0x0300).toString() + "gggg"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Invalid Address", msg);
|
assertEquals("Invalid Address", msg);
|
||||||
@@ -1227,8 +1227,8 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
|
|
||||||
// enter an invalid address
|
// enter an invalid address
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
startField.setValue(getAddr(0x1000).toString());
|
startField.setText(getAddr(0x1000).toString());
|
||||||
endField.setValue(getAddr(0x10).toString());
|
endField.setText(getAddr(0x10).toString());
|
||||||
});
|
});
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
@@ -1287,7 +1287,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
|
|
||||||
// enter an invalid address
|
// enter an invalid address
|
||||||
runSwing(() -> startField.setValue("00000000"));
|
runSwing(() -> startField.setText("00000000"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
String msg = findLabelStr(d.getComponent(), "statusLabel");
|
||||||
assertEquals("Block is already at 00000000", msg);
|
assertEquals("Block is already at 00000000", msg);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -231,7 +231,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
|
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> blockOneEnd.setValue("01003000"));
|
runSwing(() -> blockOneEnd.setText("01003000"));
|
||||||
assertEquals(0x2001, blockOneLength.getValue().longValue());
|
assertEquals(0x2001, blockOneLength.getValue().longValue());
|
||||||
assertEquals(getAddr(0x01003001), blockTwoStart.getAddress());
|
assertEquals(getAddr(0x01003001), blockTwoStart.getAddress());
|
||||||
assertEquals("010075ff", blockTwoEnd.getText());
|
assertEquals("010075ff", blockTwoEnd.getText());
|
||||||
@@ -277,7 +277,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
|
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> blockTwoStart.setValue("01003000"));
|
runSwing(() -> blockTwoStart.setText("01003000"));
|
||||||
assertEquals(0x2000, blockOneLength.getValue().longValue());
|
assertEquals(0x2000, blockOneLength.getValue().longValue());
|
||||||
assertEquals(getAddr(0x01002fff), blockOneEnd.getAddress());
|
assertEquals(getAddr(0x01002fff), blockOneEnd.getAddress());
|
||||||
assertEquals("010075ff", blockTwoEnd.getText());
|
assertEquals("010075ff", blockTwoEnd.getText());
|
||||||
@@ -357,7 +357,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
|
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> blockOneEnd.setValue("01000"));
|
runSwing(() -> blockOneEnd.setText("01000"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
assertEquals("End address must be greater than start",
|
assertEquals("End address must be greater than start",
|
||||||
findLabelStr(d.getComponent(), "statusLabel"));
|
findLabelStr(d.getComponent(), "statusLabel"));
|
||||||
@@ -378,7 +378,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
|
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> blockTwoStart.setValue("01000"));
|
runSwing(() -> blockTwoStart.setText("01000"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
assertEquals("Start address must be greater than original block start (01001000)",
|
assertEquals("Start address must be greater than original block start (01001000)",
|
||||||
findLabelStr(d.getComponent(), "statusLabel"));
|
findLabelStr(d.getComponent(), "statusLabel"));
|
||||||
@@ -531,7 +531,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
|
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> start.setValue("00002000"));
|
runSwing(() -> start.setText("00002000"));
|
||||||
assertEquals("0x1005600", length.getText());
|
assertEquals("0x1005600", length.getText());
|
||||||
|
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
@@ -579,7 +579,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
assertNotNull(length);
|
assertNotNull(length);
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> start.setValue("01201000"));
|
runSwing(() -> start.setText("01201000"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
assertEquals("Start must be less than 01001000",
|
assertEquals("Start must be less than 01001000",
|
||||||
findLabelStr(d.getComponent(), "statusLabel"));
|
findLabelStr(d.getComponent(), "statusLabel"));
|
||||||
@@ -681,7 +681,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
|
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> start.setValue("01008000"));
|
runSwing(() -> start.setText("01008000"));
|
||||||
assertEquals("0100f3ff", end.getText());
|
assertEquals("0100f3ff", end.getText());
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
|
|
||||||
@@ -740,7 +740,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
|
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> end.setValue("01007700"));
|
runSwing(() -> end.setText("01007700"));
|
||||||
assertEquals("0x6701", length.getText());
|
assertEquals("0x6701", length.getText());
|
||||||
assertTrue(okButton.isEnabled());
|
assertTrue(okButton.isEnabled());
|
||||||
|
|
||||||
@@ -798,7 +798,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
|
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
|
||||||
JButton okButton = findButton(d.getComponent(), "OK");
|
JButton okButton = findButton(d.getComponent(), "OK");
|
||||||
|
|
||||||
runSwing(() -> end.setValue("01007000"));
|
runSwing(() -> end.setText("01007000"));
|
||||||
assertFalse(okButton.isEnabled());
|
assertFalse(okButton.isEnabled());
|
||||||
assertEquals("End must be greater than 010075ff",
|
assertEquals("End must be greater than 010075ff",
|
||||||
findLabelStr(d.getComponent(), "statusLabel"));
|
findLabelStr(d.getComponent(), "statusLabel"));
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import ghidra.program.database.*;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
|
|
||||||
|
public class AddressInputTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
|
private JFrame frame;
|
||||||
|
private AddressInput field;
|
||||||
|
private ProgramDB programOneSpace;
|
||||||
|
private ProgramDB programMultiSpaces;
|
||||||
|
private volatile Address changedAddress;
|
||||||
|
private volatile String errorMessage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
programOneSpace = createDefaultProgram("oneSpace", ProgramBuilder._TOY, this);
|
||||||
|
programMultiSpaces = createDefaultProgram("mulitSpaces", ProgramBuilder._8051, this);
|
||||||
|
field = new AddressInput(programOneSpace, this::addressChanged);
|
||||||
|
field.setAddressErrorConsumer(this::addressError);
|
||||||
|
frame = new JFrame("Test");
|
||||||
|
frame.getContentPane().add(field);
|
||||||
|
frame.pack();
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
frame.setVisible(false);
|
||||||
|
programOneSpace.release(this);
|
||||||
|
programMultiSpaces.release(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultState() {
|
||||||
|
assertTrue(getText().isBlank());
|
||||||
|
assertNull(getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHexOrDecimalMode() {
|
||||||
|
setText("100"); // should have defaulted to hex mode
|
||||||
|
assertEquals(addr(0x100), getAddress());
|
||||||
|
|
||||||
|
setHexMode(false);
|
||||||
|
assertEquals(addr(100), field.getAddress());
|
||||||
|
|
||||||
|
setHexMode(true);
|
||||||
|
assertEquals(addr(0x100), field.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwitchingBetweenOneAndMultiSpaces() {
|
||||||
|
assertEquals(1, field.getComponentCount());
|
||||||
|
setProgram(programMultiSpaces);
|
||||||
|
assertEquals(2, field.getComponentCount());
|
||||||
|
setProgram(programOneSpace);
|
||||||
|
assertEquals(1, field.getComponentCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetAddress() {
|
||||||
|
setAddress(addr(0x100));
|
||||||
|
assertEquals("100", getText());
|
||||||
|
setHexMode(false);
|
||||||
|
setAddress(addr(0x100));
|
||||||
|
assertEquals("0x100", getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSettingAddressChangesResultingSpace() {
|
||||||
|
setProgram(programMultiSpaces);
|
||||||
|
setText("100");
|
||||||
|
Address a = getAddress();
|
||||||
|
assertEquals("CODE:0100", a.toString(true));
|
||||||
|
Address newAddress = addr(programMultiSpaces, "EXTMEM", 0x20);
|
||||||
|
setAddress(newAddress);
|
||||||
|
setText("100");
|
||||||
|
a = getAddress();
|
||||||
|
assertEquals("EXTMEM:0100", a.toString(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAddressWithBadExpression() {
|
||||||
|
setText("100+ (");
|
||||||
|
assertNull(getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWorksWithJustAddressFactory() {
|
||||||
|
setAddressFactory(programMultiSpaces.getAddressFactory());
|
||||||
|
setText("100");
|
||||||
|
assertEquals(addr(programMultiSpaces, 0x100), getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSelectedAddressSpace() {
|
||||||
|
setProgram(programMultiSpaces);
|
||||||
|
ProgramAddressFactory factory = programMultiSpaces.getAddressFactory();
|
||||||
|
AddressSpace codeSpace = factory.getAddressSpace("CODE");
|
||||||
|
AddressSpace extmemSpace = factory.getAddressSpace("EXTMEM");
|
||||||
|
|
||||||
|
assertEquals(codeSpace, getAddressSpaceInField());
|
||||||
|
setAddress(addr(programMultiSpaces, "EXTMEM", 100));
|
||||||
|
assertEquals(extmemSpace, getAddressSpaceInField());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSpaceFilter() {
|
||||||
|
setProgram(programMultiSpaces);
|
||||||
|
setSpaceFilter(s -> s.getName().equals("EXTMEM"));
|
||||||
|
assertEquals(1, field.getComponentCount());
|
||||||
|
setText("100");
|
||||||
|
assertEquals(addr(programMultiSpaces, "EXTMEM", 0x100), getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddressChangeConsumer() {
|
||||||
|
setText("200");
|
||||||
|
assertEquals(addr(0x200), changedAddress);
|
||||||
|
setText("300");
|
||||||
|
assertEquals(addr(0x300), changedAddress);
|
||||||
|
setText("lkjlkj");
|
||||||
|
assertNull(changedAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddressErrorConsmer() {
|
||||||
|
errorMessage = null;
|
||||||
|
setText("200");
|
||||||
|
assertNull(errorMessage);
|
||||||
|
|
||||||
|
setText("xyz");
|
||||||
|
assertEquals("Could not evaluate token \"xyz\"", errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(long offset) {
|
||||||
|
return addr(programOneSpace, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(ProgramDB p, long offset) {
|
||||||
|
return p.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(ProgramDB p, String spaceName, long offset) {
|
||||||
|
AddressSpace space = p.getAddressFactory().getAddressSpace(spaceName);
|
||||||
|
return space.getAddress(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProgram(Program p) {
|
||||||
|
runSwing(() -> field.setProgram(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAddressFactory(AddressFactory factory) {
|
||||||
|
runSwing(() -> field.setAddressFactory(factory));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSpaceFilter(Predicate<AddressSpace> filter) {
|
||||||
|
runSwing(() -> field.setAddressSpaceFilter(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setText(String value) {
|
||||||
|
runSwing(() -> field.setText(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getText() {
|
||||||
|
return runSwing(() -> field.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAddress(Address a) {
|
||||||
|
runSwing(() -> field.setAddress(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address getAddress() {
|
||||||
|
return runSwing(() -> field.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AddressSpace getAddressSpaceInField() {
|
||||||
|
return runSwing(() -> field.getAddressSpace());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHexMode(boolean hexMode) {
|
||||||
|
runSwing(() -> field.setAssumeHex(hexMode));
|
||||||
|
waitForSwing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addressChanged(Address address) {
|
||||||
|
this.changedAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addressError(String errorMessage) {
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -21,7 +21,6 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import docking.widgets.values.AbstractValue;
|
import docking.widgets.values.AbstractValue;
|
||||||
import ghidra.app.util.AddressInput;
|
import ghidra.app.util.AddressInput;
|
||||||
import ghidra.features.base.values.AddressValue;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.address.AddressFactory;
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ public class AddressValueTest extends AbstractValueIntegrationTest {
|
|||||||
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
|
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
AddressInput addressInput = (AddressInput) nameValue.getComponent();
|
AddressInput addressInput = (AddressInput) nameValue.getComponent();
|
||||||
addressInput.setValue(text);
|
addressInput.setText(text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -43,7 +43,7 @@ public class ValuesMapDialogParseErrorTest extends AbstractValueIntegrationTest
|
|||||||
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
|
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
AddressInput addressInput = (AddressInput) nameValue.getComponent();
|
AddressInput addressInput = (AddressInput) nameValue.getComponent();
|
||||||
addressInput.setValue(text);
|
addressInput.setText(text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,103 +17,146 @@ package ghidra.program.util;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.*;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
|
||||||
|
|
||||||
/**
|
public class AddressEvaluatorTest extends AbstractGenericTest {
|
||||||
*
|
|
||||||
*
|
|
||||||
* TODO To change the template for this generated type comment go to
|
|
||||||
* Window - Preferences - Java - Code Style - Code Templates
|
|
||||||
*/
|
|
||||||
public class AddressEvaluatorTest extends AbstractGhidraHeadedIntegrationTest {
|
|
||||||
|
|
||||||
AddressFactory addrFactory;
|
private Program program;
|
||||||
|
private ProgramBuilder builder;
|
||||||
|
private Symbol entry;
|
||||||
|
private Symbol entryInFoo;
|
||||||
|
|
||||||
public AddressEvaluatorTest() {
|
public AddressEvaluatorTest() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address addr(String address) {
|
@Before
|
||||||
return addrFactory.getAddress(address);
|
public void setUp() throws Exception {
|
||||||
|
builder = new ProgramBuilder("Test", ProgramBuilder._TOY_LE, this);
|
||||||
|
builder.createMemory("TestBlock", "0x100", 100);
|
||||||
|
program = builder.getProgram();
|
||||||
|
entry = builder.createLabel("0x100", "entry");
|
||||||
|
builder.createNamespace("foo");
|
||||||
|
entryInFoo = builder.createLabel("0x103", "entry", "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
program.release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEval() throws Exception {
|
public void testLongValueExpression() {
|
||||||
Program p = createDefaultProgram("Test", ProgramBuilder._TOY_LE, this);
|
assertEval(addr("0x19"), "(2+3)*5");
|
||||||
addrFactory = p.getAddressFactory();
|
assertEval(addr("0x11"), "2+3*5");
|
||||||
int txId = p.startTransaction("Test");
|
assertEval(addr("0x11"), "2+(3*5)");
|
||||||
try {
|
assertEval(addr("0x3"), "0-5+8");
|
||||||
assertEquals(addr("0x19"), AddressEvaluator.evaluate(p, "(2+3)*5"));
|
assertEval(addr("0x3"), "-5+8");
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+3*5"));
|
assertEval(addr("0xfffffffB"), "-5");
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+(3*5)"));
|
assertEval(addr("0x11"), "3+(5+(3*2)+(3))");
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "(2+3*5)"));
|
}
|
||||||
assertEquals(addr("0x16"), AddressEvaluator.evaluate(p, "0x11+5"));
|
|
||||||
assertEquals(addr("0x02"), AddressEvaluator.evaluate(p, "2-1+1"));
|
|
||||||
assertEquals(addr("0x5"), AddressEvaluator.evaluate(p, "5"));
|
|
||||||
assertEquals(addr("0x3"), AddressEvaluator.evaluate(p, "0-5+8"));
|
|
||||||
assertEquals(addr("0x3"), AddressEvaluator.evaluate(p, "-5+8"));
|
|
||||||
assertEquals(addr("0xfffffffB"), AddressEvaluator.evaluate(p, "-5"));
|
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "3+(5+(3*2)+(3))"));
|
|
||||||
assertEquals(addr("0xff00"), AddressEvaluator.evaluate(p, "0xffff ^ 0xff"));
|
|
||||||
assertEquals(addr("0x123f"), AddressEvaluator.evaluate(p, "0xffff & 0x123f"));
|
|
||||||
assertEquals(addr("0x1234"), AddressEvaluator.evaluate(p, "0x1200 | 0x0034"));
|
|
||||||
assertEquals(addr("0xffffffff"), AddressEvaluator.evaluate(p, "~ 0x0"));
|
|
||||||
assertEquals(addr("0x1201"), AddressEvaluator.evaluate(p, "0x1200 | ~(0xfffffffe)"));
|
|
||||||
assertEquals(addr("0x480"), AddressEvaluator.evaluate(p, "0x1200 >> 2"));
|
|
||||||
assertEquals(addr("0x1200"), AddressEvaluator.evaluate(p, "0x480 << 2"));
|
|
||||||
|
|
||||||
assertEquals(addr("0x1"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x2)"));
|
@Test
|
||||||
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x1)"));
|
public void testAssumesHex() {
|
||||||
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x1)"));
|
assertEval(addr("0x30"), "20 + 10");
|
||||||
|
assertEval(addr("0xf1"), "e1+10");
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(addr("0x1"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) >= 0x1)"));
|
@Test
|
||||||
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) <= 0x1)"));
|
public void testAcceptsHexPrefix() {
|
||||||
|
assertEval(addr("0x16"), "0x11+5");
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "(4ul)"));
|
assertEval(addr("0x35"), "20+0x15");
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "(4UL)"));
|
}
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "( 4l )"));
|
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "(4L)"));
|
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "(4u )"));
|
|
||||||
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "( 4U)"));
|
|
||||||
|
|
||||||
assertEquals(null, AddressEvaluator.evaluate(p, "( 4P)"));
|
|
||||||
|
|
||||||
Symbol s = p.getSymbolTable().createLabel(addr("0x100"), "entry", SourceType.IMPORTED);
|
@Test
|
||||||
Address a = s.getAddress();
|
public void testBitWiseExpressions() {
|
||||||
a = a.add(10);
|
|
||||||
assertEquals(a, AddressEvaluator.evaluate(p, "entry+5*2"));
|
assertEval(addr("0xff00"), "0xffff ^ 0xff");
|
||||||
assertEquals(addr("0x101"), AddressEvaluator.evaluate(p, "entry + (entry == 0x100)"));
|
assertEval(addr("0x123f"), "0xffff & 0x123f");
|
||||||
assertEquals(addr("0x500"), AddressEvaluator.evaluate(p,
|
assertEval(addr("0x1234"), "0x1200 | 0x0034");
|
||||||
"entry + (entry == 0x100) * 0x400 + (entry < 0x100) * 0x500"));
|
assertEval(addr("0xffffffff"), "~ 0x0");
|
||||||
assertEquals(addr("0x600"), AddressEvaluator.evaluate(p,
|
assertEval(addr("0x1201"), "0x1200 | ~(0xfffffffe)");
|
||||||
"entry + (entry > 0x100) * 0x400 + (entry <= 0x100) * 0x500"));
|
assertEval(addr("0x480"), "0x1200 >> 2");
|
||||||
}
|
assertEval(addr("0x1200"), "0x480 << 2");
|
||||||
finally {
|
assertEval(addr("0x103"), "0x100 | 0x1 | ~(~0x2)");
|
||||||
p.endTransaction(txId, true);
|
}
|
||||||
p.release(this);
|
|
||||||
}
|
@Test
|
||||||
|
public void testLogicalExpressions() {
|
||||||
|
assertEval(addr("0x1"), "(((0x1 | 0x2) & 0x2) == 0x2)");
|
||||||
|
assertEval(addr("0x0"), "(((0x1 | 0x2) & 0x2) == 0x1)");
|
||||||
|
assertEval(addr("0x0"), "(((0x1 | 0x2) & 0x2) == 0x1)");
|
||||||
|
|
||||||
|
assertEval(addr("0x1"), "(((0x1 | 0x2) & 0x2) >= 0x1)");
|
||||||
|
assertEval(addr("0x0"), "(((0x1 | 0x2) & 0x2) <= 0x1)");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAlternateNumberDecorations() {
|
||||||
|
assertEval(addr("0x4"), "(4ul)");
|
||||||
|
assertEval(addr("0x4"), "(4UL)");
|
||||||
|
assertEval(addr("0x4"), "( 4l )");
|
||||||
|
assertEval(addr("0x4"), "(4L)");
|
||||||
|
assertEval(addr("0x4"), "(4u )");
|
||||||
|
assertEval(addr("0x4"), "( 4U)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidInput() {
|
||||||
|
assertEval(null, "( 4P)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShift() {
|
||||||
|
assertEval(addr("0x80"), "0x100 >> 1");
|
||||||
|
assertEval(addr("0x400"), "0x100 << 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSymbolLookup() {
|
||||||
|
assertEval(entry.getAddress(), "entry");
|
||||||
|
assertEval(entry.getAddress().add(10), "entry+5*2");
|
||||||
|
assertEval(addr("0x101"), "entry + (entry == 0x100)");
|
||||||
|
assertEval(addr("0x500"), "entry + (entry == 0x100) * 0x400 + (entry < 0x100) * 0x500");
|
||||||
|
assertEval(addr("0x600"), "entry + (entry > 0x100) * 0x400 + (entry <= 0x100) * 0x500");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSymbolInNamespaceLookup() {
|
||||||
|
assertEval(entryInFoo.getAddress(), "foo::entry");
|
||||||
|
assertEval(entryInFoo.getAddress().add(10), "foo::entry+5*2");
|
||||||
|
assertEval(null, "bar::entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSymbolShift() {
|
||||||
|
assertEval(addr("0x80"), "entry >> 1");
|
||||||
|
assertEval(addr("0x400"), "entry << 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMemoryBlockOffset() {
|
||||||
|
assertEval(addr("0x110"), "TestBlock+10");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultiAddrSpace() throws Exception {
|
public void testMultiAddrSpace() throws Exception {
|
||||||
Program p = createDefaultProgram("Test", ProgramBuilder._TOY_LE, this);
|
assertEval(addr("0x15"), "ram:2 + 0x13");
|
||||||
addrFactory = p.getAddressFactory();
|
assertEval(addr("register:0x15"), "register:2 + 0x13");
|
||||||
try {
|
}
|
||||||
assertEquals(addr("0x19"), AddressEvaluator.evaluate(p, "(2+3)*5"));
|
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+3*5"));
|
private void assertEval(Address addr, String input) {
|
||||||
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+(3*5)"));
|
assertEquals(addr, AddressEvaluator.evaluate(program, input));
|
||||||
assertEquals(addr("RAM:15"), AddressEvaluator.evaluate(p, "RAM:2 + 0x13"));
|
}
|
||||||
}
|
|
||||||
finally {
|
private Address addr(String address) {
|
||||||
p.release(this);
|
return program.getAddressFactory().getAddress(address);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -81,12 +81,11 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
|||||||
if (provider instanceof ProgramByteViewerComponentProvider) {
|
if (provider instanceof ProgramByteViewerComponentProvider) {
|
||||||
Program program = ((ProgramByteViewerComponentProvider) provider).getProgram();
|
Program program = ((ProgramByteViewerComponentProvider) provider).getProgram();
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
addressInputField = new AddressInput();
|
Address alignment = getAlignmentAddress();
|
||||||
addressInputField.setAddressFactory(program.getAddressFactory());
|
addressInputField = new AddressInput(program, a -> update());
|
||||||
addressInputField.showAddressSpaceCombo(false);
|
addressInputField.setAddressSpaceFilter(s -> s == alignment.getAddressSpace());
|
||||||
addressInputField.setAddress(getAlignmentAddress());
|
addressInputField.setAddress(alignment);
|
||||||
panel.add(addressInputField);
|
panel.add(addressInputField);
|
||||||
addressInputField.addChangeListener(this);
|
|
||||||
addressInputField.setAccessibleName("Alignment Address");
|
addressInputField.setAccessibleName("Alignment Address");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,13 +213,13 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasValidFieldValues() {
|
private boolean hasValidFieldValues() {
|
||||||
if (addressInputField.getValue().length() == 0) {
|
if (addressInputField.getText().length() == 0) {
|
||||||
setStatusText("Enter an alignment address");
|
setStatusText("Enter an alignment address");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Address alignmentAddress = addressInputField.getAddress();
|
Address alignmentAddress = addressInputField.getAddress();
|
||||||
if (alignmentAddress == null) {
|
if (alignmentAddress == null) {
|
||||||
setStatusText("Invalid alignment address:" + addressInputField.getValue());
|
setStatusText("Invalid alignment address:" + addressInputField.getText());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BigInteger bytesPerLine = bytesPerLineField.getValue();
|
BigInteger bytesPerLine = bytesPerLineField.getValue();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -553,7 +553,7 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
// current offset is 0
|
// current offset is 0
|
||||||
assertEquals(program.getMinAddress(), ai.getAddress());
|
assertEquals(program.getMinAddress(), ai.getAddress());
|
||||||
|
|
||||||
runSwing(() -> ai.setValue("0100100b"));
|
runSwing(() -> ai.setText("0100100b"));
|
||||||
pressButtonByText(d.getComponent(), "OK");
|
pressButtonByText(d.getComponent(), "OK");
|
||||||
// verify that offset label on the plugin shows '5'
|
// verify that offset label on the plugin shows '5'
|
||||||
assertEquals(5, plugin.getProvider().getOffset());
|
assertEquals(5, plugin.getProvider().getOffset());
|
||||||
@@ -587,7 +587,7 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
// current offset is 0
|
// current offset is 0
|
||||||
assertEquals(program.getMinAddress(), ai.getAddress());
|
assertEquals(program.getMinAddress(), ai.getAddress());
|
||||||
|
|
||||||
runSwing(() -> ai.setValue("0000:0c06"));
|
runSwing(() -> ai.setText("0000:0c06"));
|
||||||
pressButtonByText(d.getComponent(), "OK");
|
pressButtonByText(d.getComponent(), "OK");
|
||||||
|
|
||||||
assertEquals(10, plugin.getProvider().getOffset());
|
assertEquals(10, plugin.getProvider().getOffset());
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -55,8 +55,7 @@ public class EditableListingAddress extends DisplayableListingAddress implements
|
|||||||
private void buildPanel() {
|
private void buildPanel() {
|
||||||
setLayout(new PairLayout(5, 5, 50));
|
setLayout(new PairLayout(5, 5, 50));
|
||||||
|
|
||||||
addressField = new AddressInput();
|
addressField = new AddressInput(program);
|
||||||
addressField.setAddressFactory(program.getAddressFactory());
|
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
addressField.setAddress(address);
|
addressField.setAddress(address);
|
||||||
}
|
}
|
||||||
@@ -78,7 +77,7 @@ public class EditableListingAddress extends DisplayableListingAddress implements
|
|||||||
Address selectedAddress = addressField.getAddress();
|
Address selectedAddress = addressField.getAddress();
|
||||||
if (selectedAddress == null) {
|
if (selectedAddress == null) {
|
||||||
throw new InvalidInputException(
|
throw new InvalidInputException(
|
||||||
"\"" + addressField.getValue() + "\" is not a valid address.");
|
"\"" + addressField.getText() + "\" is not a valid address.");
|
||||||
}
|
}
|
||||||
if (!program.getMemory().contains(selectedAddress)) {
|
if (!program.getMemory().contains(selectedAddress)) {
|
||||||
throw new InvalidInputException(
|
throw new InvalidInputException(
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -24,7 +24,6 @@ import docking.widgets.label.GDLabel;
|
|||||||
import ghidra.app.util.AddressInput;
|
import ghidra.app.util.AddressInput;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
@@ -32,7 +31,6 @@ import ghidra.util.layout.PairLayout;
|
|||||||
public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private Program program;
|
private Program program;
|
||||||
private AddressFactory addressFactory;
|
|
||||||
private AddressRangeListener listener;
|
private AddressRangeListener listener;
|
||||||
|
|
||||||
private JPanel addressRangePanel;
|
private JPanel addressRangePanel;
|
||||||
@@ -45,7 +43,6 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
|||||||
AddressRangeListener listener) {
|
AddressRangeListener listener) {
|
||||||
super(programIndicator + " Address Range", true, true, true, false);
|
super(programIndicator + " Address Range", true, true, true, false);
|
||||||
this.program = program;
|
this.program = program;
|
||||||
addressFactory = program.getAddressFactory();
|
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.LABEL, "AddEditDialog"));
|
setHelpLocation(new HelpLocation(HelpTopics.LABEL, "AddEditDialog"));
|
||||||
addWorkPanel(createAddressRangePanel());
|
addWorkPanel(createAddressRangePanel());
|
||||||
@@ -68,8 +65,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
|||||||
minLabel.setToolTipText("Enter minimum address to add or remove");
|
minLabel.setToolTipText("Enter minimum address to add or remove");
|
||||||
addressRangePanel.add(minLabel);
|
addressRangePanel.add(minLabel);
|
||||||
|
|
||||||
minAddressField = new AddressInput();
|
minAddressField = new AddressInput(program);
|
||||||
minAddressField.setAddressFactory(addressFactory);
|
|
||||||
Dimension minPreferredSize = getPreferredSize();
|
Dimension minPreferredSize = getPreferredSize();
|
||||||
minPreferredSize.width = 200;
|
minPreferredSize.width = 200;
|
||||||
minAddressField.setPreferredSize(minPreferredSize);
|
minAddressField.setPreferredSize(minPreferredSize);
|
||||||
@@ -79,8 +75,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
|||||||
maxLabel.setToolTipText("Enter maximum address to add or remove");
|
maxLabel.setToolTipText("Enter maximum address to add or remove");
|
||||||
addressRangePanel.add(maxLabel);
|
addressRangePanel.add(maxLabel);
|
||||||
|
|
||||||
maxAddressField = new AddressInput();
|
maxAddressField = new AddressInput(program);
|
||||||
maxAddressField.setAddressFactory(addressFactory);
|
|
||||||
Dimension maxPreferredSize = getPreferredSize();
|
Dimension maxPreferredSize = getPreferredSize();
|
||||||
maxPreferredSize.width = 200;
|
maxPreferredSize.width = 200;
|
||||||
minAddressField.setPreferredSize(maxPreferredSize);
|
minAddressField.setPreferredSize(maxPreferredSize);
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package docking.widgets.textfield;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.ToolTipManager;
|
||||||
|
|
||||||
|
import docking.DockingUtils;
|
||||||
|
import docking.util.GraphicsUtils;
|
||||||
|
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||||
|
import generic.theme.Gui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the JTextField mainly to allow hint painting for the current radix mode.
|
||||||
|
*/
|
||||||
|
public class HexDecimalModeTextField extends JTextField {
|
||||||
|
|
||||||
|
private static final String FONT_ID = "font.input.hint";
|
||||||
|
private int hintWidth;
|
||||||
|
private boolean isHexMode;
|
||||||
|
private boolean showNumbericDecoration = true;
|
||||||
|
|
||||||
|
public HexDecimalModeTextField(int columns, Consumer<Boolean> modeConsumer) {
|
||||||
|
super(columns);
|
||||||
|
|
||||||
|
FontMetrics fontMetrics = getFontMetrics(Gui.getFont(FONT_ID));
|
||||||
|
String mode = isHexMode ? "Hex" : "Dec";
|
||||||
|
hintWidth = fontMetrics.stringWidth(mode);
|
||||||
|
|
||||||
|
addKeyListener(new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_M && DockingUtils.isControlModifier(e)) {
|
||||||
|
isHexMode = !isHexMode;
|
||||||
|
modeConsumer.accept(isHexMode);
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// make sure tooltips will be activated
|
||||||
|
ToolTipManager.sharedInstance().registerComponent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getToolTipText(MouseEvent event) {
|
||||||
|
|
||||||
|
int hintStart = getBounds().width - hintWidth;
|
||||||
|
if (event.getX() > hintStart) {
|
||||||
|
String key = DockingUtils.CONTROL_KEY_NAME;
|
||||||
|
return "Press '" + key + "-M' to toggle Hex or Decimal Mode";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHexMode(boolean hexMode) {
|
||||||
|
this.isHexMode = hexMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on or off the faded text that displays the field's radix mode (hex or decimal).
|
||||||
|
*
|
||||||
|
* @param show true to show the radix mode.
|
||||||
|
*/
|
||||||
|
public void setShowNumberMode(boolean show) {
|
||||||
|
this.showNumbericDecoration = show;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
if (!showNumbericDecoration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font savedFont = g.getFont();
|
||||||
|
g.setFont(Gui.getFont(FONT_ID));
|
||||||
|
g.setColor(Messages.HINT);
|
||||||
|
|
||||||
|
Dimension size = getSize();
|
||||||
|
Insets insets = getInsets();
|
||||||
|
int x;
|
||||||
|
if (getHorizontalAlignment() == RIGHT) {
|
||||||
|
x = insets.left;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = size.width - insets.right - hintWidth;
|
||||||
|
}
|
||||||
|
int y = size.height - insets.bottom - 1;
|
||||||
|
String mode = isHexMode ? "Hex" : "Dec";
|
||||||
|
GraphicsUtils.drawString(this, g, mode, x, y);
|
||||||
|
g.setFont(savedFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,20 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package docking.widgets.textfield;
|
package docking.widgets.textfield;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.*;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JTextField;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
|
|
||||||
import docking.DockingUtils;
|
|
||||||
import docking.util.GraphicsUtils;
|
|
||||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
|
||||||
import generic.theme.Gui;
|
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,12 +59,11 @@ import ghidra.util.SystemUtilities;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class IntegerTextField {
|
public class IntegerTextField {
|
||||||
private JTextField textField;
|
private HexDecimalModeTextField textField;
|
||||||
|
|
||||||
private boolean isHexMode = false;
|
private boolean isHexMode = false;
|
||||||
private boolean allowsNegative = true;
|
private boolean allowsNegative = true;
|
||||||
private boolean allowsHexPrefix = true;
|
private boolean allowsHexPrefix = true;
|
||||||
private boolean showNumbericDecoration = true;
|
|
||||||
private BigInteger maxValue;
|
private BigInteger maxValue;
|
||||||
private BigInteger minValue;
|
private BigInteger minValue;
|
||||||
|
|
||||||
@@ -109,9 +104,13 @@ public class IntegerTextField {
|
|||||||
* @param initialValue the initial value
|
* @param initialValue the initial value
|
||||||
*/
|
*/
|
||||||
public IntegerTextField(int columns, BigInteger initialValue) {
|
public IntegerTextField(int columns, BigInteger initialValue) {
|
||||||
textField = new MyTextField(columns);
|
textField = new HexDecimalModeTextField(columns, b -> textFieldHexModeChanged(b));
|
||||||
|
|
||||||
|
AbstractDocument document = (AbstractDocument) textField.getDocument();
|
||||||
|
document.setDocumentFilter(new HexDecimalDocumentFilter());
|
||||||
setValue(initialValue);
|
setValue(initialValue);
|
||||||
textField.getDocument().addDocumentListener(new DocumentListener() {
|
|
||||||
|
document.addDocumentListener(new DocumentListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeUpdate(DocumentEvent e) {
|
public void removeUpdate(DocumentEvent e) {
|
||||||
@@ -266,8 +265,7 @@ public class IntegerTextField {
|
|||||||
* @param show true to show the radix mode.
|
* @param show true to show the radix mode.
|
||||||
*/
|
*/
|
||||||
public void setShowNumberMode(boolean show) {
|
public void setShowNumberMode(boolean show) {
|
||||||
this.showNumbericDecoration = show;
|
textField.setShowNumberMode(show);
|
||||||
textField.repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -278,9 +276,15 @@ public class IntegerTextField {
|
|||||||
* the current value from decimal to hex.
|
* the current value from decimal to hex.
|
||||||
*/
|
*/
|
||||||
public void setHexMode() {
|
public void setHexMode() {
|
||||||
BigInteger currentValue = getValue();
|
BigInteger value = getValue();
|
||||||
isHexMode = true;
|
setHexMode(true);
|
||||||
updateTextField(currentValue);
|
setValue(value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHexMode(boolean hexMode) {
|
||||||
|
this.isHexMode = hexMode;
|
||||||
|
textField.setHexMode(hexMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,9 +295,9 @@ public class IntegerTextField {
|
|||||||
* current value from hex to decimal.
|
* current value from hex to decimal.
|
||||||
*/
|
*/
|
||||||
public void setDecimalMode() {
|
public void setDecimalMode() {
|
||||||
BigInteger currentValue = getValue();
|
BigInteger value = getValue();
|
||||||
isHexMode = false;
|
setHexMode(false);
|
||||||
updateTextField(currentValue);
|
setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -477,6 +481,12 @@ public class IntegerTextField {
|
|||||||
textField.setHorizontalAlignment(alignment);
|
textField.setHorizontalAlignment(alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void textFieldHexModeChanged(boolean hexMode) {
|
||||||
|
BigInteger value = getValue();
|
||||||
|
this.isHexMode = hexMode;
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
private String computeTextForValue(BigInteger value) {
|
private String computeTextForValue(BigInteger value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return "";
|
return "";
|
||||||
@@ -525,15 +535,6 @@ public class IntegerTextField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleMode() {
|
|
||||||
if (isHexMode) {
|
|
||||||
setDecimalMode();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setHexMode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean passesMaxCheck(BigInteger value) {
|
private boolean passesMaxCheck(BigInteger value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return true;
|
return true;
|
||||||
@@ -648,7 +649,7 @@ public class IntegerTextField {
|
|||||||
if (isValidPrefix(valueString)) {
|
if (isValidPrefix(valueString)) {
|
||||||
// When the input is valid, update the hex mode to match how the text was parsed.
|
// When the input is valid, update the hex mode to match how the text was parsed.
|
||||||
// See parseAsHex variable comment above.
|
// See parseAsHex variable comment above.
|
||||||
isHexMode = parseAsHex;
|
setHexMode(parseAsHex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +662,7 @@ public class IntegerTextField {
|
|||||||
if (passesMaxCheck(value) && passesMinCheck(value)) {
|
if (passesMaxCheck(value) && passesMinCheck(value)) {
|
||||||
// When the input is valid, update the hex mode to match how the text was parsed.
|
// When the input is valid, update the hex mode to match how the text was parsed.
|
||||||
// See parseAsHex variable comment above.
|
// See parseAsHex variable comment above.
|
||||||
isHexMode = parseAsHex;
|
setHexMode(parseAsHex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -692,76 +693,4 @@ public class IntegerTextField {
|
|||||||
// so we don't allow negatives
|
// so we don't allow negatives
|
||||||
return value.signum() < 0;
|
return value.signum() < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the JTextField mainly to allow hint painting for the current radix mode.
|
|
||||||
*/
|
|
||||||
private class MyTextField extends JTextField {
|
|
||||||
|
|
||||||
private static final String FONT_ID = "font.input.hint";
|
|
||||||
private int hintWidth;
|
|
||||||
|
|
||||||
public MyTextField(int columns) {
|
|
||||||
super(columns);
|
|
||||||
|
|
||||||
FontMetrics fontMetrics = getFontMetrics(Gui.getFont(FONT_ID));
|
|
||||||
String mode = isHexMode ? "Hex" : "Dec";
|
|
||||||
hintWidth = fontMetrics.stringWidth(mode);
|
|
||||||
|
|
||||||
AbstractDocument document = (AbstractDocument) getDocument();
|
|
||||||
document.setDocumentFilter(new HexDecimalDocumentFilter());
|
|
||||||
|
|
||||||
addKeyListener(new KeyAdapter() {
|
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyEvent e) {
|
|
||||||
if (e.getKeyCode() == KeyEvent.VK_M && DockingUtils.isControlModifier(e)) {
|
|
||||||
toggleMode();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// make sure tooltips will be activated
|
|
||||||
ToolTipManager.sharedInstance().registerComponent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getToolTipText(MouseEvent event) {
|
|
||||||
|
|
||||||
int hintStart = getBounds().width - hintWidth;
|
|
||||||
if (event.getX() > hintStart) {
|
|
||||||
String key = DockingUtils.CONTROL_KEY_NAME;
|
|
||||||
return "Press '" + key + "-M' to toggle Hex or Decimal Mode";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void paintComponent(Graphics g) {
|
|
||||||
super.paintComponent(g);
|
|
||||||
if (!showNumbericDecoration) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Font savedFont = g.getFont();
|
|
||||||
g.setFont(Gui.getFont(FONT_ID));
|
|
||||||
g.setColor(Messages.HINT);
|
|
||||||
|
|
||||||
Dimension size = getSize();
|
|
||||||
Insets insets = getInsets();
|
|
||||||
int x;
|
|
||||||
if (getHorizontalAlignment() == RIGHT) {
|
|
||||||
x = insets.left;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
x = size.width - insets.right - hintWidth;
|
|
||||||
}
|
|
||||||
int y = size.height - insets.bottom - 1;
|
|
||||||
String mode = isHexMode ? "Hex" : "Dec";
|
|
||||||
GraphicsUtils.drawString(this, g, mode, x, y);
|
|
||||||
g.setFont(savedFont);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package generic.expressions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base marker interface for {@link ExpressionGrouper}, {@link ExpressionOperator},
|
||||||
|
* and {@link ExpressionValue}
|
||||||
|
*/
|
||||||
|
public interface ExpressionElement {
|
||||||
|
// marker interface
|
||||||
|
}
|
||||||