GP-5196 Adding support for expressions and symbol names in address fields

This commit is contained in:
ghidragon
2024-12-31 16:00:39 -05:00
parent 14527b015e
commit b1d257150c
61 changed files with 2902 additions and 1445 deletions
@@ -398,6 +398,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/SetImageBaseDialog.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/Welcome_to_Ghidra_Help.htm||GHIDRA||||END|
src/main/help/help/topics/Navigation/Navigation.htm||GHIDRA||||END|
@@ -196,6 +196,8 @@
<!-- Formerly The Byte Viewer -->
<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="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" />
@@ -55,8 +55,9 @@
<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
fallthrough.</LI>
<LI>Enter an address
(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;
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>Start Addr</I></B> - Enter the start address of the new memory block.&nbsp; If the
program language defines multiple address spaces, the address space must also be
<P><B><I>Start Address</I></B> - Enter the start address
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>)
of the new memory block.&nbsp; If
the program language defines multiple address spaces, the address space must also be
specified.&nbsp; 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
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>New Start Address -</I></B> Enter the NEW starting address for the block.&nbsp;
<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.&nbsp;
The NEW ending address will be computed.</P>
<P><B><I>New End Address -&nbsp;</I></B> Enter the NEW ending address for the block. The
NEW starting address will be computed.</P>
<P><B><I>New End Address -&nbsp;</I></B> Enter the new ending address
(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
following conditions:</I></P>
@@ -404,11 +409,15 @@
enter the split point:</P>
<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 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>
</UL>
@@ -482,7 +491,9 @@
<BLOCKQUOTE>
<P><B><I>New Start Address -</I></B> A new start address can be entered here.&nbsp; 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.&nbsp; It must
be before the current start address.</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
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>
<P><I><B>Block Length -</B></I> Displays the length of the block.&nbsp; A new value can be
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

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 &lt;CTRL&gt; 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 "&lt; &gt; &lt;= &gt;= == != || &amp;&amp; and !".
These operators generator a numeric value of 0 or 1.</P>
</BLOCKQUOTE>
<H3>Bit Operators</H3>
<BLOCKQUOTE>
<P>Supported bit operators are &lt;&lt;, &gt;&gt;, &amp;, |, ^, 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&lt;&lt;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>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>
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">
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
space. &nbsp;The address offset entry is always
interpretted as a unsigned hex value &nbsp;(i.e., the "0x" entry prefix is assumed).
&nbsp;For those processors with multiple address-spaces, a pull-down is also provided
space. Enter an address
(or <A href="help/topics/Misc/AddressExpressions.htm">Address Expression</A>) to specify
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
</I>OTHER</I> non-loaded space are only included if the <B>Include OTHER overlay spaces</B>
checkbox is selected.<BR>
@@ -124,7 +124,10 @@
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
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>
</DIV>
</DIV>
@@ -4,9 +4,9 @@
* 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.
@@ -117,15 +117,14 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene
}
}
private void addressChanged() {
private void addressChanged(Address address) {
if (changing) {
return;
}
Runnable r = () -> {
Address addr = addrField.getAddress();
if (addr != null || addrField.getValue().length() == 0) {
model.setCurrentFallthrough(addr);
if (address != null || addrField.getText().length() == 0) {
model.setCurrentFallthrough(address);
}
else {
setStatusText("Invalid Address");
@@ -139,9 +138,7 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene
private JPanel create() {
JPanel panel = new JPanel(new BorderLayout(0, 10));
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
addrField = new AddressInput();
addrField.setAddressFactory(model.getProgram().getAddressFactory());
addrField.addChangeListener(e -> addressChanged());
addrField = new AddressInput(model.getProgram(), this::addressChanged);
addrField.addActionListener(e -> model.setCurrentFallthrough(addrField.getAddress()));
panel.add(createHomePanel(), BorderLayout.NORTH);
panel.add(createAddressPanel(), BorderLayout.CENTER);
@@ -4,9 +4,9 @@
* 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.
@@ -148,8 +148,9 @@ class VarnodeLocationCellEditor extends AbstractCellEditor
}
private Component createAddressEditor(VarnodeInfo varnode) {
addressInput = new AddressInput(BorderFactory.createEmptyBorder());
addressInput.setAddressFactory(program.getAddressFactory());
addressInput = new AddressInput(program);
addressInput.setComponentBorders(BorderFactory.createEmptyBorder());
Address address = varnode.getAddress();
if (address != null) {
addressInput.setAddress(address);
@@ -4,9 +4,9 @@
* 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.
@@ -35,7 +35,6 @@ import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlockType;
@@ -69,7 +68,6 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
private JCheckBox overlayCB;
private RegisterField initialValueField;
private JLabel initialValueLabel;
private AddressFactory addrFactory;
private AddressInput baseAddrField; // used for Bit and Byte mapped blocks
private IntegerTextField schemeDestByteCountField; // 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() {
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.add(new GLabel("Block Name:", SwingConstants.RIGHT));
panel.add(buildNameField());
panel.add(new GLabel("Start Addr:", SwingConstants.RIGHT));
panel.add(new GLabel("Start Address:", SwingConstants.RIGHT));
panel.add(buildAddressField());
panel.add(new GLabel("Length:", SwingConstants.RIGHT));
panel.add(buildLengthField());
@@ -422,26 +420,16 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
model.setFileBytes((FileBytes) fileBytesComboBox.getSelectedItem());
}
private void addrChanged() {
Address addr = null;
try {
addr = addrField.getAddress();
}
catch (IllegalArgumentException e) {
// just let it be null
}
model.setStartAddress(addr);
private void addressChanged(Address address) {
model.setStartAddress(address);
}
private void baseAddressChanged() {
Address addr = null;
try {
addr = baseAddrField.getAddress();
}
catch (IllegalArgumentException e) {
// just let it be null
}
model.setBaseAddress(addr);
private void addressError(String errorMessage) {
model.setAddressError(errorMessage);
}
private void baseAddressChanged(Address address) {
model.setBaseAddress(address);
}
private void schemeSrcByteCountChanged() {
@@ -476,12 +464,11 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
}
private JPanel buildMappedPanel() {
Program program = model.getProgram();
JPanel panel = new JPanel(new PairLayout());
baseAddrField = new AddressInput();
baseAddrField.setAddressFactory(addrFactory);
baseAddrField = new AddressInput(program, this::baseAddressChanged);
baseAddrField.setName("Source Addr");
baseAddrField.addChangeListener(ev -> baseAddressChanged());
baseAddrField.setAccessibleName("Source Address");
JPanel schemePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
@@ -504,7 +491,6 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
schemePanel.add(new GLabel(" : "));
schemePanel.add(schemeSrcByteCountField.getComponent());
Program program = model.getProgram();
Address minAddr = program.getMinAddress();
if (minAddr == null) {
minAddr = program.getAddressFactory().getDefaultAddressSpace().getAddress(0);
@@ -561,12 +547,12 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
}
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.setAccessibleName("Memory Block Start Address");
addrFactory = model.getProgram().getAddressFactory();
addrField.setAddressFactory(addrFactory, AddressInput.INCLUDE_ALL_MEMORY_SPACES);
addrField.addChangeListener(ev -> addrChanged());
return addrField;
}
@@ -4,9 +4,9 @@
* 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.
@@ -59,6 +59,7 @@ class AddBlockModel {
private String comment;
private FileBytes fileBytes;
private long fileBytesOffset = -1;
private String addressErrorMessage;
enum InitializedType {
UNINITIALIZED, INITIALIZED_FROM_VALUE, INITIALIZED_FROM_FILE_BYTES;
@@ -90,6 +91,14 @@ class AddBlockModel {
void setStartAddress(Address addr) {
startAddr = addr;
addressErrorMessage = null;
validateInfo();
listener.stateChanged(null);
}
void setAddressError(String errorMessage) {
startAddr = null;
addressErrorMessage = errorMessage;
validateInfo();
listener.stateChanged(null);
}
@@ -432,6 +441,9 @@ class AddBlockModel {
return true;
}
message = "Please enter a valid Start Address";
if (addressErrorMessage != null) {
message = "Invalid Address: " + addressErrorMessage;
}
return false;
}
@@ -4,9 +4,9 @@
* 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.
@@ -18,6 +18,7 @@ package ghidra.app.plugin.core.memory;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ActionListener;
import java.util.function.Consumer;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -30,7 +31,7 @@ import ghidra.app.util.AddressInput;
import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
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.util.HelpLocation;
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_DOWN_TITLE = "Expand Block Down";
private int dialogType;
private AddressFactory addrFactory;
private AddressInput startAddressInput;
private AddressInput endAddressInput;
private JTextField startField;
@@ -66,7 +66,7 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
* @param af
* @param dialogType
*/
ExpandBlockDialog(PluginTool tool, ExpandBlockModel model, MemoryBlock block, AddressFactory af,
ExpandBlockDialog(PluginTool tool, ExpandBlockModel model, MemoryBlock block, Program program,
int dialogType) {
super(dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE, true);
this.tool = tool;
@@ -74,9 +74,8 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
this.dialogType = dialogType;
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP,
dialogType == EXPAND_UP ? EXPAND_UP_TITLE : EXPAND_DOWN_TITLE));
addrFactory = af;
model.setChangeListener(this);
addWorkPanel(create(block));
addWorkPanel(create(block, program));
addOKButton();
addCancelButton();
setOkEnabled(false);
@@ -109,16 +108,16 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
* Create the main work panel.
* @return JPanel
*/
private JPanel create(MemoryBlock block) {
private JPanel create(MemoryBlock block, Program program) {
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.setAddressFactory(addrFactory);
startAddressInput.setAccessibleName("New Start Address");
endAddressInput = new AddressInput();
endAddressInput = new AddressInput(program, listener);
endAddressInput.setName("EndAddress");
endAddressInput.setAddressFactory(addrFactory);
endAddressInput.setAccessibleName("New End Address");
Address start = block.getStart();
@@ -161,9 +160,6 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
}
private void addListeners() {
startAddressInput.addChangeListener(new AddressChangeListener());
endAddressInput.addChangeListener(new AddressChangeListener());
lengthField.setChangeListener(new LengthChangeListener());
ActionListener al = e -> setStatusText("");
@@ -206,10 +202,10 @@ class ExpandBlockDialog extends DialogComponentProvider implements ChangeListene
* Listener on the AddressInput field; update length field when the
* address input field changes.
*/
private class AddressChangeListener implements ChangeListener {
private class AddressChangeListener implements Consumer<Address> {
@Override
public void stateChanged(ChangeEvent event) {
public void accept(Address address) {
if (isChanging) {
return;
}
@@ -690,7 +690,7 @@ class MemoryMapProvider extends ComponentProviderAdapter {
"OTHER overlay blocks can not be split.");
}
else {
SplitBlockDialog d = new SplitBlockDialog(plugin, block, program.getAddressFactory());
SplitBlockDialog d = new SplitBlockDialog(plugin, block, program);
tool.showDialog(d, this);
}
}
@@ -711,7 +711,7 @@ class MemoryMapProvider extends ComponentProviderAdapter {
}
ExpandBlockDialog dialog =
new ExpandBlockDialog(tool, model, block, program.getAddressFactory(), dialogType);
new ExpandBlockDialog(tool, model, block, program, dialogType);
model.initialize(block);
dialog.dispose();
}
@@ -4,9 +4,9 @@
* 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.
@@ -28,7 +28,7 @@ import ghidra.app.util.AddressInput;
import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
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.Swing;
import ghidra.util.layout.PairLayout;
@@ -82,9 +82,9 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
setOkEnabled(false);
changing = true;
if (!isVisible()) {
AddressFactory factory = model.getAddressFactory();
newStartField.setAddressFactory(factory);
newEndField.setAddressFactory(factory);
Program program = model.getProgram();
newStartField.setProgram(program);
newEndField.setProgram(program);
}
Address newStart = model.getNewStartAddress();
if (newStart != null) {
@@ -136,8 +136,8 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
}
private JPanel buildMainPanel() {
JPanel panel = new JPanel(new PairLayout(5, 20, 150));
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JPanel panel = new JPanel(new PairLayout(2, 10, 150));
panel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
blockNameLabel = new GDLabel(".text");
blockNameLabel.setName("blockName"); // name components for junits
@@ -150,15 +150,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
lengthLabel = new GDLabel("4096 (0x1000)");
lengthLabel.setName("length");
newStartField = new AddressInput();
newStartField = new AddressInput(model.getProgram(), this::startChanged);
newStartField.setName("newStart");
newEndField = new AddressInput();
newEndField = new AddressInput(model.getProgram(), this::endChanged);
newEndField.setName("newEnd");
newStartField.addChangeListener(e -> startChanged());
newEndField.addChangeListener(e -> endChanged());
panel.add(new GLabel("Name:", SwingConstants.RIGHT));
panel.add(blockNameLabel);
panel.add(new GLabel("Start Address:", SwingConstants.RIGHT));
@@ -174,13 +171,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
return panel;
}
private void startChanged() {
private void startChanged(Address address) {
if (changing) {
return;
}
Address newStart = newStartField.getAddress();
if (newStart != null) {
model.setNewStartAddress(newStart);
if (address != null) {
model.setNewStartAddress(address);
}
else {
setStatusText("Invalid Address");
@@ -188,13 +184,12 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
}
}
private void endChanged() {
private void endChanged(Address address) {
if (changing) {
return;
}
Address newEnd = newEndField.getAddress();
if (newEnd != null) {
model.setNewEndAddress(newEnd);
if (address != null) {
model.setNewEndAddress(address);
}
else {
setStatusText("Invalid Address");
@@ -4,9 +4,9 @@
* 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.
@@ -18,7 +18,8 @@ package ghidra.app.plugin.core.memory;
import ghidra.app.cmd.memory.MoveBlockListener;
import ghidra.app.cmd.memory.MoveBlockTask;
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.mem.MemoryBlock;
@@ -183,8 +184,8 @@ class MoveBlockModel implements DomainObjectListener {
program = null;
}
AddressFactory getAddressFactory() {
return program.getAddressFactory();
Program getProgram() {
return program;
}
private Address getEndAddress(Address start) {
@@ -4,9 +4,9 @@
* 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.
@@ -27,7 +27,9 @@ import docking.widgets.label.GLabel;
import ghidra.app.plugin.core.misc.RegisterField;
import ghidra.app.util.AddressInput;
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.MemoryBlock;
import ghidra.util.HelpLocation;
@@ -50,16 +52,14 @@ class SplitBlockDialog extends DialogComponentProvider {
private JTextField blockTwoEndField;
private RegisterField blockTwoLengthField;
private MemoryBlock block;
private AddressFactory addrFactory;
private MemoryMapPlugin plugin;
SplitBlockDialog(MemoryMapPlugin plugin, MemoryBlock block, AddressFactory af) {
SplitBlockDialog(MemoryMapPlugin plugin, MemoryBlock block, Program program) {
super("Split Block");
this.plugin = plugin;
this.block = block;
addrFactory = af;
setHelpLocation(new HelpLocation(HelpTopics.MEMORY_MAP, "Split Block"));
addWorkPanel(create());
addWorkPanel(create(program));
addOKButton();
addCancelButton();
setOkEnabled(false);
@@ -89,8 +89,8 @@ class SplitBlockDialog extends DialogComponentProvider {
* Create the work panel.
* @return JPanel
*/
private JPanel create() {
JPanel panelOne = new JPanel(new PairLayout(5, 5, 150));
private JPanel create(Program program) {
JPanel panelOne = new JPanel(new PairLayout(5, 10, 150));
panelOne.setBorder(BorderFactory.createTitledBorder("Block to Split"));
blockOneNameField = new JTextField(10);
blockOneNameField.setName("BlockOneName");
@@ -99,7 +99,7 @@ class SplitBlockDialog extends DialogComponentProvider {
blockOneStartField.setName("BlockOneStart");
blockOneStartField.getAccessibleContext().setAccessibleName("Address of Block To Split");
blockOneEnd = new AddressInput();
blockOneEnd = new AddressInput(program, this::blockOneEndChanged);
blockOneEnd.setName("BlockOneEnd");
blockOneEnd.setAccessibleName("New Block End Adddress");
@@ -121,7 +121,7 @@ class SplitBlockDialog extends DialogComponentProvider {
blockTwoNameField = new JTextField(10);
blockTwoNameField.setName("BlockTwoName");
blockTwoNameField.getAccessibleContext().setAccessibleName("Name of New Block");
blockTwoStart = new AddressInput();
blockTwoStart = new AddressInput(program, this::blockTwoStartChanged);
blockTwoStart.setName("BlockTwoStart");
blockTwoStart.setAccessibleName("New Block Start Address");
blockTwoEndField = new JTextField(10);
@@ -141,11 +141,11 @@ class SplitBlockDialog extends DialogComponentProvider {
panelTwo.add(blockTwoLengthField);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20));
BoxLayout bl = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
mainPanel.setLayout(bl);
mainPanel.add(Box.createVerticalStrut(5));
mainPanel.add(panelOne);
mainPanel.add(Box.createVerticalStrut(10));
mainPanel.add(Box.createVerticalStrut(20));
mainPanel.add(panelTwo);
return mainPanel;
@@ -166,7 +166,6 @@ class SplitBlockDialog extends DialogComponentProvider {
blockOneStartField.setText(startAddr.toString());
blockOneStartField.setEnabled(false);
blockOneEnd.setAddressFactory(addrFactory);
blockOneEnd.setAddress(endAddr);
blockOneEnd.setAddressSpaceEditable(false);
@@ -174,7 +173,6 @@ class SplitBlockDialog extends DialogComponentProvider {
blockTwoNameField.setText(name + ".split");
blockTwoStart.setAddressFactory(addrFactory);
blockTwoStart.setAddress(startAddr);
blockTwoStart.setAddressSpaceEditable(false);
@@ -189,8 +187,6 @@ class SplitBlockDialog extends DialogComponentProvider {
blockOneLengthField.setChangeListener(new LengthChangeListener(blockOneLengthField));
blockTwoLengthField.setChangeListener(new LengthChangeListener(blockTwoLengthField));
blockOneEnd.addChangeListener(new AddressChangeListener(blockOneEnd));
blockTwoStart.addChangeListener(new AddressChangeListener(blockTwoStart));
ActionListener al = e -> setStatusText("");
blockOneLengthField.addActionListener(al);
@@ -307,135 +303,101 @@ class SplitBlockDialog extends DialogComponentProvider {
}
}
/**
* Listener on the AddressInput fields; update other fields when either
* of these fields change.
*/
private class AddressChangeListener implements ChangeListener {
private void blockOneEndChanged(Address end) {
setStatusText("");
boolean isValid = checkBlockOneEndAddress(end);
setOkEnabled(isValid);
}
AddressInput source;
private void blockTwoStartChanged(Address start) {
setStatusText("");
boolean isValid = checkBlockTwoStartChanged(start);
setOkEnabled(isValid);
}
public AddressChangeListener(AddressInput source) {
this.source = source;
private boolean checkBlockOneEndAddress(Address end) {
if (end == null) {
setStatusText("Invalid Address");
return false;
}
@Override
public void stateChanged(ChangeEvent event) {
setStatusText("");
boolean ok = false;
if (source == blockOneEnd) {
ok = blockOneEndChanged();
}
else if (source == blockTwoStart) {
ok = blockTwoStartChanged();
}
setOkEnabled(ok);
Address start = block.getStart();
if (end.compareTo(start) < 0) {
setStatusText("End address must be greater than start");
return false;
}
private Address getAddress() throws InvalidInputException {
AddressInput field = source;
Address addr = field.getAddress();
if (addr == null && field.hasInput()) {
throw new InvalidInputException();
}
return addr;
if (end.compareTo(block.getEnd()) == 0) {
return false;
}
private boolean blockOneEndChanged() {
Address start = block.getStart();
Address end = null;
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;
// 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));
private boolean blockTwoStartChanged() {
Address start = null;
try {
start = getAddress();
}
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;
try {
Address b2Start = end.addNoWrap(1);
blockTwoStart.setAddress(b2Start);
length = block.getEnd().subtract(b2Start) + 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;
}
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");
* 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.
@@ -231,7 +231,7 @@ class EditExternalReferencePanel extends EditReferencePanel {
updateExtLibPath();
extLabel.setText(extLoc.getLabel());
extAddr.setAddressFactory(program.getAddressFactory());
extAddr.setProgram(program);
Address addr = extLoc.getAddress();
if (addr != null) {
extAddr.setAddress(addr);
@@ -260,7 +260,7 @@ class EditExternalReferencePanel extends EditReferencePanel {
extLibPath.setText(null);
extLabel.setText(null);
extAddr.setAddressFactory(program.getAddressFactory());
extAddr.setProgram(program);
extAddr.clear();
extLibName.requestFocus();
@@ -191,7 +191,8 @@ class EditMemoryReferencePanel extends EditReferencePanel {
}
private void initializeToAddressField(Address toAddr) {
toAddressField.setAddressFactory(fromCodeUnit.getProgram().getAddressFactory(), (s) -> {
Program program = fromCodeUnit.getProgram();
toAddressField.setProgram(program, (s) -> {
if (s.isLoadedMemorySpace()) {
return true;
}
@@ -4,9 +4,9 @@
* 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.
@@ -19,8 +19,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import docking.DialogComponentProvider;
import docking.widgets.checkbox.GCheckBox;
@@ -30,7 +28,7 @@ import ghidra.app.util.AddressInput;
import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
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.exception.CancelledException;
import ghidra.util.layout.PairLayout;
@@ -44,7 +42,6 @@ import ghidra.util.layout.PairLayout;
public class OffsetTableDialog extends DialogComponentProvider {
private AddressInput addrInput;
private AddressFactory addrFactory;
private JComboBox<String> comboBox;
private Address defaultAddress;
private JCheckBox signedCheckBox;
@@ -52,15 +49,13 @@ public class OffsetTableDialog extends DialogComponentProvider {
/**
* Construct a new dialog
* @param parent parent of this dialog
* @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);
this.defaultAddress = defaultAddress;
this.addrFactory = addrFactory;
addWorkPanel(buildMainPanel());
addWorkPanel(buildMainPanel(program));
addOKButton();
addCancelButton();
setHelpLocation(new HelpLocation(HelpTopics.REFERENCES, "Create_Offset_References"));
@@ -128,23 +123,16 @@ public class OffsetTableDialog extends DialogComponentProvider {
signedCheckBox.setSelected(isSigned);
}
private JPanel buildMainPanel() {
private JPanel buildMainPanel(Program program) {
JPanel panel = new JPanel(new PairLayout(10, 5));
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
addrInput = new AddressInput();
addrInput = new AddressInput(program, a -> clearStatusText());
addrInput.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
okCallback();
}
});
addrInput.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
clearStatusText();
}
});
addrInput.setAddressFactory(addrFactory);
addrInput.setAddress(defaultAddress);
panel.add(new GLabel("Enter Base Address:", SwingConstants.RIGHT));
@@ -4,9 +4,9 @@
* 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.
@@ -101,10 +101,10 @@ public class OffsetTablePlugin extends Plugin {
true);
return;
}
AddressFactory addressFactory = context.getProgram().getAddressFactory();
Program program = context.getProgram();
Address minAddress = context.getSelection().getMinAddress();
OffsetTableDialog dialog = new OffsetTableDialog(minAddress, addressFactory);
OffsetTableDialog dialog = new OffsetTableDialog(minAddress, program);
dialog.setSelectedSize(lastSelectedSize);
dialog.setSigned(lastSigned);
try {
@@ -4,9 +4,9 @@
* 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.
@@ -16,17 +16,18 @@
package ghidra.app.plugin.core.register;
import java.math.BigInteger;
import java.util.function.Consumer;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import docking.DialogComponentProvider;
import docking.widgets.label.GLabel;
import ghidra.app.util.AddressInput;
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.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.MessageType;
import ghidra.util.layout.PairLayout;
@@ -39,9 +40,9 @@ class EditRegisterValueDialog extends DialogComponentProvider {
private boolean wasCancelled = true;
EditRegisterValueDialog(Register register, Address start, Address end, BigInteger value,
AddressFactory factory) {
Program program) {
super("Edit Register Value Range");
addWorkPanel(buildWorkPanel(register, start, end, value, factory));
addWorkPanel(buildWorkPanel(register, start, end, value, program));
addOKButton();
addCancelButton();
@@ -49,24 +50,15 @@ class EditRegisterValueDialog extends DialogComponentProvider {
}
private JComponent buildWorkPanel(Register register, Address start, Address end,
BigInteger value, AddressFactory factory) {
BigInteger value, Program program) {
JTextField registerField =
new JTextField(register.getName() + " (" + register.getBitLength() + ")");
registerField.setEditable(false);
startAddrField = new AddressInput();
endAddrField = new AddressInput();
ChangeListener changeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateOk();
}
};
startAddrField.setAddressFactory(factory);
endAddrField.setAddressFactory(factory);
startAddrField.addChangeListener(changeListener);
endAddrField.addChangeListener(changeListener);
Consumer<Address> addressChangeListener = a -> updateOk();
startAddrField = new AddressInput(program, addressChangeListener);
endAddrField = new AddressInput(program, addressChangeListener);
registerValueField = new FixedBitSizeValueField(register.getBitLength(), true, false);
startAddrField.setAddress(start);
@@ -4,9 +4,9 @@
* 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.
@@ -89,7 +89,7 @@ class RegisterValuesPanel extends JPanel {
Address end = range.getEndAddress();
BigInteger value = range.getValue();
EditRegisterValueDialog dialog = new EditRegisterValueDialog(selectedRegister, start, end,
value, currentProgram.getAddressFactory());
value, currentProgram);
tool.showDialog(dialog, this);
if (!dialog.wasCancelled()) {
@@ -4,9 +4,9 @@
* 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.
@@ -300,7 +300,7 @@ class EditExternalLocationPanel extends JPanel {
if (extOriginalLabelTextField != null) {
extOriginalLabelTextField.setText(startingOriginalName);
}
extAddressInputWidget.setAddressFactory(program.getAddressFactory());
extAddressInputWidget.setProgram(program);
if (startingLocationAddress != null) {
extAddressInputWidget.setAddress(startingLocationAddress);
}
@@ -2630,7 +2630,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
Address choice = doAsk(Integer.class, title, message, existingValue, lastValue -> {
AskAddrDialog dialog =
new AskAddrDialog(title, message, currentProgram.getAddressFactory(), lastValue);
new AskAddrDialog(title, message, currentProgram, lastValue);
if (dialog.isCanceled()) {
throw new CancelledException();
}
File diff suppressed because it is too large Load Diff
@@ -4,9 +4,9 @@
* 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.
@@ -67,10 +67,7 @@ public class AddressSetEditorPanel extends JPanel {
JLabel minLabel = new GDLabel("Min:");
minLabel.setToolTipText("Enter minimum address to add or remove");
minAddressPanel.add(minLabel, BorderLayout.WEST);
minAddressField = new AddressInput();
minAddressField.setAddressFactory(addressFactory);
ChangeListener listener = e -> validateAddRemoveButton();
minAddressField.addChangeListener(listener);
minAddressField = new AddressInput(addressFactory, a -> validateAddRemoveButton());
minAddressPanel.add(minAddressField, BorderLayout.CENTER);
JPanel maxAddressPanel = new JPanel();
@@ -78,9 +75,7 @@ public class AddressSetEditorPanel extends JPanel {
JLabel maxLabel = new GDLabel("Max:");
maxLabel.setToolTipText("Enter maximum address to add or remove");
maxAddressPanel.add(maxLabel, BorderLayout.WEST);
maxAddressField = new AddressInput();
maxAddressField.setAddressFactory(addressFactory);
maxAddressField.addChangeListener(listener);
maxAddressField = new AddressInput(addressFactory, a -> validateAddRemoveButton());
maxAddressPanel.add(maxAddressField, BorderLayout.CENTER);
maxAddressPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
addRangeButton = new GButton(ADD_ICON);
@@ -338,7 +338,7 @@ public class OptionsEditorPanel extends JPanel {
return null;
}
AddressFactory addressFactory = addressFactoryService.getAddressFactory();
AddressInput addressInput = new AddressInput();
AddressInput addressInput = new AddressInput(a -> option.setValue(a));
addressInput.setName(option.getName());
Address addr = (Address) option.getValue();
if (addr == null && addressFactory != null) {
@@ -347,7 +347,6 @@ public class OptionsEditorPanel extends JPanel {
}
addressInput.setAddressFactory(addressFactory);
addressInput.setAddress(addr);
addressInput.addChangeListener(e -> option.setValue(addressInput.getAddress()));// addressInput.addActionListener(e -> option.setValue(addressInput.getAddress()));
return addressInput;
}
}
@@ -5,9 +5,9 @@
* 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.
@@ -18,9 +18,9 @@ package ghidra.app.util.cparser.CPP;
import java.util.*;
import generic.expressions.ExpressionEvaluator;
import ghidra.app.util.cparser.CPP.PreProcessor.PPToken;
import ghidra.program.model.data.*;
import ghidra.program.util.AddressEvaluator;
import ghidra.util.Msg;
/**
@@ -281,14 +281,13 @@ public class DefineTable {
StringBuffer buf = new StringBuffer(image);
int lastReplPos = pos;
boolean initialListSupplied = initialList != null; // initial list passed in
ArrayList<String> sublist = new ArrayList<String>();
if (initialList != null) {
sublist.addAll(initialList);
}
// don't replace an infinite number of times. Fail safe for possible ininite loop
while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
// clear list of used macros when move past replacement area
@@ -353,7 +352,8 @@ public class DefineTable {
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;
if (sublist == null) {
@@ -451,11 +451,11 @@ public class DefineTable {
argValue + " args processed : " + argsfound);
return replString;
}
// Handle "..." varargs
// if last argument is ellipsis, then is varargs, replace the rest of the params
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;
// Replace __VA_ARGS__ with the rest of params
curArgName = "__VA_ARGS__";
@@ -526,14 +526,14 @@ public class DefineTable {
startpos = end;
}
buf.append(substString.substring(startpos));
// Handle __VA_OPT__(<repl>)
// if varargs and no more params, replace with ""
// if varargs and has vararg params, replace with <repl>
if (isVarArg) {
replace_VaOpt(buf, hadVarArgs);
}
substString = buf.toString();
return substString;
}
@@ -544,28 +544,29 @@ public class DefineTable {
* @param buf string buffer to replace __VA_OPT__(value) within
* @param hadVarArgs
*/
private void replace_VaOpt(StringBuffer buf, boolean hadVarArgs) {
private void replace_VaOpt(StringBuffer buf, boolean hadVarArgs) {
int optIdx = buf.indexOf("__VA_OPT__");
if (optIdx < 0) {
return;
}
int lparen = buf.indexOf("(", optIdx+1);
int lparen = buf.indexOf("(", optIdx + 1);
if (lparen < 0) {
return;
}
int rparen = buf.indexOf(")",lparen+1);
int rparen = buf.indexOf(")", lparen + 1);
if (rparen < 0) {
return;
}
// get in between string.
String replarg = buf.substring(lparen+1, rparen);
String replarg = buf.substring(lparen + 1, rparen);
if (hadVarArgs) {
buf.replace(optIdx, rparen+1, replarg);
} else {
buf.replace(optIdx, rparen+1, "");
buf.replace(optIdx, rparen + 1, replarg);
}
else {
buf.replace(optIdx, rparen + 1, "");
}
}
@@ -629,7 +630,7 @@ public class DefineTable {
public String expand(String image, boolean join) {
return expand(image, join, null);
}
/**
* do the final expansion of "##" concats in the define strings that protect normal macro substitution.
*
@@ -639,7 +640,7 @@ public class DefineTable {
* @return
*/
public String expand(String image, boolean join, ArrayList<String> list) {
image = macroSub(image, 0, list);
// get rid of ## constructs
@@ -705,13 +706,13 @@ public class DefineTable {
Iterator<String> iter = getDefineNames();
while (iter.hasNext()) {
String defName = iter.next();
String strValue = expandDefine(defName);
if (strValue == null) {
// couldn't expand, must have been a macro
continue;
}
// strip off any casting/parentheses
strValue = stripCast(strValue);
@@ -720,7 +721,7 @@ public class DefineTable {
if (lvalue == null) {
try {
lvalue = AddressEvaluator.evaluateToLong(strValue);
lvalue = ExpressionEvaluator.evaluateToLong(strValue);
}
catch (Exception exc) {
// ignore didn't parse well
@@ -738,7 +739,8 @@ public class DefineTable {
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;
// Start the Enum at 8, then resize to fit the value
@@ -751,33 +753,33 @@ public class DefineTable {
CategoryPath path = getCategory(currentCategoryName);
path = new CategoryPath(path, category);
enuum.setCategoryPath(path);
DataType dt = resolveDataType(openDTMgrs, path, enuum);
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++) {
// 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;
}
}
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
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) {
// don't worry about macros
@@ -789,13 +791,13 @@ public class DefineTable {
// check if this is a numeric expression that could be simplified
//
String strValue = getValue(defName);
ArrayList<String> list = new ArrayList();
list.add(defName);
String strExpanded = expand(strValue, true, list);
strValue = strExpanded;
return strValue;
}
@@ -4,9 +4,9 @@
* 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.
@@ -25,19 +25,17 @@ import docking.DockingWindowManager;
import docking.widgets.label.GLabel;
import ghidra.app.util.AddressInput;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program;
public class AskAddrDialog extends DialogComponentProvider {
private boolean isCanceled;
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) {
super(title, true, true, true, false);
addrInput = new AddressInput();
addrInput.setAddressFactory(af);
addrInput.selectDefaultAddressSpace();
addrInput = new AddressInput(program);
if (lastAddr != null) {
addrInput.setAddress(lastAddr);
}
@@ -4,9 +4,9 @@
* 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.
@@ -251,7 +251,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> {
addrField.setValue("0x200");
addrField.setText("0x200");
nameField.setText(".test");
lengthField.setText("0x100");
commentField.setText("this is a block test");
@@ -319,7 +319,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> {
addrField.setValue("0x01001200");
addrField.setText("0x01001200");
nameField.setText(".test");
lengthField.setText("0x100");
commentField.setText("this is a block test");
@@ -354,7 +354,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> {
addrField.setValue("xxxxx");
addrField.setText("xxxxx");
nameField.setText(".test");
lengthField.setText("0x100");
commentField.setText("this is a block test");
@@ -364,7 +364,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
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());
close(d);
}
@@ -768,7 +768,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
assertEquals("Please enter a source address for the bit block", msg);
runSwing(() -> addrField.setValue("01001000"));
runSwing(() -> addrField.setText("01001000"));
}
else {
assertTrue(okButton.isEnabled());
@@ -844,7 +844,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
assertEquals("Please enter a source address for the bit block", msg);
runSwing(() -> addrField.setValue("01001000"));
runSwing(() -> addrField.setText("01001000"));
}
else {
assertTrue(okButton.isEnabled());
@@ -1040,7 +1040,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
// move the block to 0x300
Address newStart = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x300);
Address newEnd = startAddr.getAddressSpace().getAddressInThisSpaceOnly(0x3ff);
runSwing(() -> startField.setValue(newStart));
runSwing(() -> startField.simulateAddressChanged(newStart));
assertEquals(newEnd, endField.getAddress());
assertTrue(okButton.isEnabled());
@@ -1110,7 +1110,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
// enter an invalid address
runSwing(() -> startField.setValue(getAddr(0x0300).toString() + "gggg"));
runSwing(() -> startField.setText(getAddr(0x0300).toString() + "gggg"));
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
assertEquals("Invalid Address", msg);
@@ -1168,7 +1168,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
// enter an invalid address
runSwing(() -> endField.setValue(getAddr(0x0300).toString() + "gggg"));
runSwing(() -> endField.setText(getAddr(0x0300).toString() + "gggg"));
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
assertEquals("Invalid Address", msg);
@@ -1227,8 +1227,8 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
// enter an invalid address
runSwing(() -> {
startField.setValue(getAddr(0x1000).toString());
endField.setValue(getAddr(0x10).toString());
startField.setText(getAddr(0x1000).toString());
endField.setText(getAddr(0x10).toString());
});
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
@@ -1287,7 +1287,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
assertFalse(okButton.isEnabled());
// enter an invalid address
runSwing(() -> startField.setValue("00000000"));
runSwing(() -> startField.setText("00000000"));
assertFalse(okButton.isEnabled());
String msg = findLabelStr(d.getComponent(), "statusLabel");
assertEquals("Block is already at 00000000", msg);
@@ -4,9 +4,9 @@
* 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.
@@ -231,7 +231,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> blockOneEnd.setValue("01003000"));
runSwing(() -> blockOneEnd.setText("01003000"));
assertEquals(0x2001, blockOneLength.getValue().longValue());
assertEquals(getAddr(0x01003001), blockTwoStart.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
@@ -277,7 +277,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> blockTwoStart.setValue("01003000"));
runSwing(() -> blockTwoStart.setText("01003000"));
assertEquals(0x2000, blockOneLength.getValue().longValue());
assertEquals(getAddr(0x01002fff), blockOneEnd.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
@@ -357,7 +357,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> blockOneEnd.setValue("01000"));
runSwing(() -> blockOneEnd.setText("01000"));
assertFalse(okButton.isEnabled());
assertEquals("End address must be greater than start",
findLabelStr(d.getComponent(), "statusLabel"));
@@ -378,7 +378,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> blockTwoStart.setValue("01000"));
runSwing(() -> blockTwoStart.setText("01000"));
assertFalse(okButton.isEnabled());
assertEquals("Start address must be greater than original block start (01001000)",
findLabelStr(d.getComponent(), "statusLabel"));
@@ -531,7 +531,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> start.setValue("00002000"));
runSwing(() -> start.setText("00002000"));
assertEquals("0x1005600", length.getText());
assertTrue(okButton.isEnabled());
@@ -579,7 +579,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertNotNull(length);
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> start.setValue("01201000"));
runSwing(() -> start.setText("01201000"));
assertFalse(okButton.isEnabled());
assertEquals("Start must be less than 01001000",
findLabelStr(d.getComponent(), "statusLabel"));
@@ -681,7 +681,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> start.setValue("01008000"));
runSwing(() -> start.setText("01008000"));
assertEquals("0100f3ff", end.getText());
assertTrue(okButton.isEnabled());
@@ -740,7 +740,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
RegisterField length = (RegisterField) findComponentByName(d.getComponent(), "BlockLength");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> end.setValue("01007700"));
runSwing(() -> end.setText("01007700"));
assertEquals("0x6701", length.getText());
assertTrue(okButton.isEnabled());
@@ -798,7 +798,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
JButton okButton = findButton(d.getComponent(), "OK");
runSwing(() -> end.setValue("01007000"));
runSwing(() -> end.setText("01007000"));
assertFalse(okButton.isEnabled());
assertEquals("End must be greater than 010075ff",
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");
* 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.
@@ -21,7 +21,6 @@ import org.junit.Test;
import docking.widgets.values.AbstractValue;
import ghidra.app.util.AddressInput;
import ghidra.features.base.values.AddressValue;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
@@ -144,7 +143,7 @@ public class AddressValueTest extends AbstractValueIntegrationTest {
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
runSwing(() -> {
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");
* 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.
@@ -43,7 +43,7 @@ public class ValuesMapDialogParseErrorTest extends AbstractValueIntegrationTest
protected void setTextOnAddressInput(AbstractValue<?> nameValue, String text) {
runSwing(() -> {
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");
* 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.
@@ -17,103 +17,146 @@ package ghidra.program.util;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.*;
import generic.test.AbstractGenericTest;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
/**
*
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class AddressEvaluatorTest extends AbstractGhidraHeadedIntegrationTest {
public class AddressEvaluatorTest extends AbstractGenericTest {
AddressFactory addrFactory;
private Program program;
private ProgramBuilder builder;
private Symbol entry;
private Symbol entryInFoo;
public AddressEvaluatorTest() {
super();
}
private Address addr(String address) {
return addrFactory.getAddress(address);
@Before
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
public void testEval() throws Exception {
Program p = createDefaultProgram("Test", ProgramBuilder._TOY_LE, this);
addrFactory = p.getAddressFactory();
int txId = p.startTransaction("Test");
try {
assertEquals(addr("0x19"), AddressEvaluator.evaluate(p, "(2+3)*5"));
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+3*5"));
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+(3*5)"));
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"));
public void testLongValueExpression() {
assertEval(addr("0x19"), "(2+3)*5");
assertEval(addr("0x11"), "2+3*5");
assertEval(addr("0x11"), "2+(3*5)");
assertEval(addr("0x3"), "0-5+8");
assertEval(addr("0x3"), "-5+8");
assertEval(addr("0xfffffffB"), "-5");
assertEval(addr("0x11"), "3+(5+(3*2)+(3))");
}
assertEquals(addr("0x1"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x2)"));
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x1)"));
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) == 0x1)"));
@Test
public void testAssumesHex() {
assertEval(addr("0x30"), "20 + 10");
assertEval(addr("0xf1"), "e1+10");
}
assertEquals(addr("0x1"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) >= 0x1)"));
assertEquals(addr("0x0"), AddressEvaluator.evaluate(p, "(((0x1 | 0x2) & 0x2) <= 0x1)"));
assertEquals(addr("0x4"), AddressEvaluator.evaluate(p, "(4ul)"));
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)"));
@Test
public void testAcceptsHexPrefix() {
assertEval(addr("0x16"), "0x11+5");
assertEval(addr("0x35"), "20+0x15");
}
Symbol s = p.getSymbolTable().createLabel(addr("0x100"), "entry", SourceType.IMPORTED);
Address a = s.getAddress();
a = a.add(10);
assertEquals(a, AddressEvaluator.evaluate(p, "entry+5*2"));
assertEquals(addr("0x101"), AddressEvaluator.evaluate(p, "entry + (entry == 0x100)"));
assertEquals(addr("0x500"), AddressEvaluator.evaluate(p,
"entry + (entry == 0x100) * 0x400 + (entry < 0x100) * 0x500"));
assertEquals(addr("0x600"), AddressEvaluator.evaluate(p,
"entry + (entry > 0x100) * 0x400 + (entry <= 0x100) * 0x500"));
}
finally {
p.endTransaction(txId, true);
p.release(this);
}
@Test
public void testBitWiseExpressions() {
assertEval(addr("0xff00"), "0xffff ^ 0xff");
assertEval(addr("0x123f"), "0xffff & 0x123f");
assertEval(addr("0x1234"), "0x1200 | 0x0034");
assertEval(addr("0xffffffff"), "~ 0x0");
assertEval(addr("0x1201"), "0x1200 | ~(0xfffffffe)");
assertEval(addr("0x480"), "0x1200 >> 2");
assertEval(addr("0x1200"), "0x480 << 2");
assertEval(addr("0x103"), "0x100 | 0x1 | ~(~0x2)");
}
@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
public void testMultiAddrSpace() throws Exception {
Program p = createDefaultProgram("Test", ProgramBuilder._TOY_LE, this);
addrFactory = p.getAddressFactory();
try {
assertEquals(addr("0x19"), AddressEvaluator.evaluate(p, "(2+3)*5"));
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+3*5"));
assertEquals(addr("0x11"), AddressEvaluator.evaluate(p, "2+(3*5)"));
assertEquals(addr("RAM:15"), AddressEvaluator.evaluate(p, "RAM:2 + 0x13"));
}
finally {
p.release(this);
}
assertEval(addr("0x15"), "ram:2 + 0x13");
assertEval(addr("register:0x15"), "register:2 + 0x13");
}
private void assertEval(Address addr, String input) {
assertEquals(addr, AddressEvaluator.evaluate(program, input));
}
private Address addr(String address) {
return program.getAddressFactory().getAddress(address);
}
}
@@ -4,9 +4,9 @@
* 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.
@@ -81,12 +81,11 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
if (provider instanceof ProgramByteViewerComponentProvider) {
Program program = ((ProgramByteViewerComponentProvider) provider).getProgram();
if (program != null) {
addressInputField = new AddressInput();
addressInputField.setAddressFactory(program.getAddressFactory());
addressInputField.showAddressSpaceCombo(false);
addressInputField.setAddress(getAlignmentAddress());
Address alignment = getAlignmentAddress();
addressInputField = new AddressInput(program, a -> update());
addressInputField.setAddressSpaceFilter(s -> s == alignment.getAddressSpace());
addressInputField.setAddress(alignment);
panel.add(addressInputField);
addressInputField.addChangeListener(this);
addressInputField.setAccessibleName("Alignment Address");
}
}
@@ -214,13 +213,13 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider
}
private boolean hasValidFieldValues() {
if (addressInputField.getValue().length() == 0) {
if (addressInputField.getText().length() == 0) {
setStatusText("Enter an alignment address");
return false;
}
Address alignmentAddress = addressInputField.getAddress();
if (alignmentAddress == null) {
setStatusText("Invalid alignment address:" + addressInputField.getValue());
setStatusText("Invalid alignment address:" + addressInputField.getText());
return false;
}
BigInteger bytesPerLine = bytesPerLineField.getValue();
@@ -4,9 +4,9 @@
* 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.
@@ -553,7 +553,7 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
// current offset is 0
assertEquals(program.getMinAddress(), ai.getAddress());
runSwing(() -> ai.setValue("0100100b"));
runSwing(() -> ai.setText("0100100b"));
pressButtonByText(d.getComponent(), "OK");
// verify that offset label on the plugin shows '5'
assertEquals(5, plugin.getProvider().getOffset());
@@ -587,7 +587,7 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
// current offset is 0
assertEquals(program.getMinAddress(), ai.getAddress());
runSwing(() -> ai.setValue("0000:0c06"));
runSwing(() -> ai.setText("0000:0c06"));
pressButtonByText(d.getComponent(), "OK");
assertEquals(10, plugin.getProvider().getOffset());
@@ -4,9 +4,9 @@
* 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.
@@ -55,8 +55,7 @@ public class EditableListingAddress extends DisplayableListingAddress implements
private void buildPanel() {
setLayout(new PairLayout(5, 5, 50));
addressField = new AddressInput();
addressField.setAddressFactory(program.getAddressFactory());
addressField = new AddressInput(program);
if (address != null) {
addressField.setAddress(address);
}
@@ -78,7 +77,7 @@ public class EditableListingAddress extends DisplayableListingAddress implements
Address selectedAddress = addressField.getAddress();
if (selectedAddress == null) {
throw new InvalidInputException(
"\"" + addressField.getValue() + "\" is not a valid address.");
"\"" + addressField.getText() + "\" is not a valid address.");
}
if (!program.getMemory().contains(selectedAddress)) {
throw new InvalidInputException(
@@ -4,9 +4,9 @@
* 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.
@@ -24,7 +24,6 @@ import docking.widgets.label.GDLabel;
import ghidra.app.util.AddressInput;
import ghidra.app.util.HelpTopics;
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.layout.PairLayout;
@@ -32,7 +31,6 @@ import ghidra.util.layout.PairLayout;
public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
private Program program;
private AddressFactory addressFactory;
private AddressRangeListener listener;
private JPanel addressRangePanel;
@@ -45,7 +43,6 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
AddressRangeListener listener) {
super(programIndicator + " Address Range", true, true, true, false);
this.program = program;
addressFactory = program.getAddressFactory();
this.listener = listener;
setHelpLocation(new HelpLocation(HelpTopics.LABEL, "AddEditDialog"));
addWorkPanel(createAddressRangePanel());
@@ -68,8 +65,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
minLabel.setToolTipText("Enter minimum address to add or remove");
addressRangePanel.add(minLabel);
minAddressField = new AddressInput();
minAddressField.setAddressFactory(addressFactory);
minAddressField = new AddressInput(program);
Dimension minPreferredSize = getPreferredSize();
minPreferredSize.width = 200;
minAddressField.setPreferredSize(minPreferredSize);
@@ -79,8 +75,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
maxLabel.setToolTipText("Enter maximum address to add or remove");
addressRangePanel.add(maxLabel);
maxAddressField = new AddressInput();
maxAddressField.setAddressFactory(addressFactory);
maxAddressField = new AddressInput(program);
Dimension maxPreferredSize = getPreferredSize();
maxPreferredSize.width = 200;
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");
* 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.
@@ -15,20 +15,16 @@
*/
package docking.widgets.textfield;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.event.*;
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;
/**
@@ -63,12 +59,11 @@ import ghidra.util.SystemUtilities;
*/
public class IntegerTextField {
private JTextField textField;
private HexDecimalModeTextField textField;
private boolean isHexMode = false;
private boolean allowsNegative = true;
private boolean allowsHexPrefix = true;
private boolean showNumbericDecoration = true;
private BigInteger maxValue;
private BigInteger minValue;
@@ -109,9 +104,13 @@ public class IntegerTextField {
* @param initialValue the initial value
*/
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);
textField.getDocument().addDocumentListener(new DocumentListener() {
document.addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
@@ -266,8 +265,7 @@ public class IntegerTextField {
* @param show true to show the radix mode.
*/
public void setShowNumberMode(boolean show) {
this.showNumbericDecoration = show;
textField.repaint();
textField.setShowNumberMode(show);
}
/**
@@ -278,9 +276,15 @@ public class IntegerTextField {
* the current value from decimal to hex.
*/
public void setHexMode() {
BigInteger currentValue = getValue();
isHexMode = true;
updateTextField(currentValue);
BigInteger value = getValue();
setHexMode(true);
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.
*/
public void setDecimalMode() {
BigInteger currentValue = getValue();
isHexMode = false;
updateTextField(currentValue);
BigInteger value = getValue();
setHexMode(false);
setValue(value);
}
/**
@@ -477,6 +481,12 @@ public class IntegerTextField {
textField.setHorizontalAlignment(alignment);
}
private void textFieldHexModeChanged(boolean hexMode) {
BigInteger value = getValue();
this.isHexMode = hexMode;
setValue(value);
}
private String computeTextForValue(BigInteger value) {
if (value == null) {
return "";
@@ -525,15 +535,6 @@ public class IntegerTextField {
}
}
private void toggleMode() {
if (isHexMode) {
setDecimalMode();
}
else {
setHexMode();
}
}
private boolean passesMaxCheck(BigInteger value) {
if (value == null) {
return true;
@@ -648,7 +649,7 @@ public class IntegerTextField {
if (isValidPrefix(valueString)) {
// When the input is valid, update the hex mode to match how the text was parsed.
// See parseAsHex variable comment above.
isHexMode = parseAsHex;
setHexMode(parseAsHex);
return true;
}
@@ -661,7 +662,7 @@ public class IntegerTextField {
if (passesMaxCheck(value) && passesMinCheck(value)) {
// When the input is valid, update the hex mode to match how the text was parsed.
// See parseAsHex variable comment above.
isHexMode = parseAsHex;
setHexMode(parseAsHex);
return true;
}
}
@@ -692,76 +693,4 @@ public class IntegerTextField {
// so we don't allow negatives
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
}

Some files were not shown because too many files have changed in this diff Show More