Merge remote-tracking branch 'origin/GP-5196_ghidragon_address_expression_and_symbol_names_in_address_input--SQUASHED'

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

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