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