GP-5310 Created global search and replace feature

This commit is contained in:
ghidragon 2025-02-28 20:08:40 -05:00
parent cc1228bdaa
commit 6fb115358a
93 changed files with 7469 additions and 141 deletions

View file

@ -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.
@ -495,6 +495,11 @@ class ListingDB implements Listing {
return codeMgr.getCommentAddressIterator(commentType, addrSet, forward);
}
@Override
public long getCommentAddressCount() {
return codeMgr.getCommentAddressCount();
}
@Override
public AddressIterator getCommentAddressIterator(AddressSetView addrSet, boolean forward) {
return codeMgr.getCommentAddressIterator(addrSet, forward);
@ -505,6 +510,11 @@ class ListingDB implements Listing {
return codeMgr.getComment(commentType, address);
}
@Override
public CodeUnitComments getAllComments(Address address) {
return codeMgr.getAllComments(address);
}
@Override
public void setComment(Address address, int commentType, String comment) {
codeMgr.setComment(address, commentType, comment);

View file

@ -1239,6 +1239,20 @@ public class CodeManager implements ErrorHandler, ManagerDB {
return new CommentTypeFilterIterator(it, commentType);
}
/**
* Returns the number of addresses that have associated comments.
* @return the number of addresses that have associated comments
*/
public long getCommentAddressCount() {
try {
return commentAdapter.getRecordCount();
}
catch (IOException e) {
program.dbError(e);
}
return 0;
}
/**
* Get a forward iterator over addresses that have comments of the given type.
* @param commentType comment type defined in CodeUnit
@ -2969,8 +2983,8 @@ public class CodeManager implements ErrorHandler, ManagerDB {
// flow following issues, for example creating a function body.
boolean isFallthrough =
(flowType.isJump() && flowAddr.equals(inst.getMaxAddress().next())) &&
inst.hasFallthrough();
inst.hasFallthrough();
if (!isFallthrough) {
mnemonicPrimaryRef = addDefaultMemoryReferenceIfMissing(inst,
Reference.MNEMONIC, flowAddr, flowType, oldRefList, mnemonicPrimaryRef);
@ -3289,6 +3303,30 @@ public class CodeManager implements ErrorHandler, ManagerDB {
return null;
}
/**
* Returns all the comments at the given address.
* @param address the address to get all comments for
* @return all the comments at the given address
*/
public CodeUnitComments getAllComments(Address address) {
try {
long addr = addrMap.getKey(address, false);
DBRecord commentRec = getCommentAdapter().getRecord(addr);
CommentType[] types = CommentType.values();
String[] comments = new String[types.length];
for (CommentType type : types) {
int index = type.ordinal();
comments[index] = commentRec.getString(index);
}
return new CodeUnitComments(comments);
}
catch (IOException e) {
dbError(e);
}
return null;
}
/**
* Set the comment for the given comment type at the specified address.
*

View file

@ -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.
@ -555,4 +555,9 @@ class FragmentDB extends DatabaseObject implements ProgramFragment {
lock.release();
}
}
@Override
public boolean isDeleted() {
return isDeleted(lock);
}
}

View file

@ -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.
@ -922,4 +922,9 @@ class ModuleDB extends DatabaseObject implements ProgramModule {
public String toString() {
return record.getString(ModuleDBAdapter.MODULE_NAME_COL);
}
@Override
public boolean isDeleted() {
return isDeleted(lock);
}
}

View file

@ -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.
@ -39,25 +39,36 @@ public interface CodeUnit extends MemBuffer, PropertySet {
public final static int MNEMONIC = -1;
public static final int NO_COMMENT = -1;
/**
* comment type for end of line
* @deprecated use {@link CommentType#EOL}
*/
@Deprecated
public static final int EOL_COMMENT = 0;
/**
* comment type that goes before a code unit
* @deprecated use {@link CommentType#PRE}
*/
@Deprecated
public static final int PRE_COMMENT = 1;
/**
* comment type that follows after a code unit
* @deprecated use {@link CommentType#POST}
*/
@Deprecated
public static final int POST_COMMENT = 2;
/**
* Property name for plate comment type
* @deprecated use {@link CommentType#POST}
*/
@Deprecated
public static final int PLATE_COMMENT = 3;
/**
* Property name for repeatable comment type
* @deprecated use {@link CommentType#REPEATABLE}
*/
@Deprecated
public static final int REPEATABLE_COMMENT = 4;
// /**
@ -135,9 +146,22 @@ public interface CodeUnit extends MemBuffer, PropertySet {
* that type exists for this codeunit
* @throws IllegalArgumentException if type is not one of the
* three types of comments supported
* @deprecated use {@link #getComment(CommentType)} instead
*/
@Deprecated
public String getComment(int commentType);
/**
* Get the comment for the given type
*
* @param type which type of comment to retrieve
* @return the comment string of the appropriate type or null if no comment of
* that type exists for this code unit
*/
public default String getComment(CommentType type) {
return getComment(type.ordinal());
}
/**
* Get the comment for the given type and parse it into an array of strings
* such that each line is its own string.
@ -149,9 +173,24 @@ public interface CodeUnit extends MemBuffer, PropertySet {
* is returned.
* @throws IllegalArgumentException if type is not one of the
* three types of comments supported
* @deprecated use {@link #getCommentAsArray(CommentType)} instead
*/
@Deprecated
public String[] getCommentAsArray(int commentType);
/**
* Get the comment for the given type and parse it into an array of strings
* such that each line is its own string.
*
* @param type the comment type to retrieve
* @return an array of strings where each item in the array is a line of text
* in the comment. If there is no comment of the requested type, an empty array
* is returned.
*/
public default String[] getCommentAsArray(CommentType type) {
return getCommentAsArray(type.ordinal());
}
/**
* Set the comment for the given comment type. Passing <code>null</code> clears the comment
*
@ -161,9 +200,21 @@ public interface CodeUnit extends MemBuffer, PropertySet {
*
* @throws IllegalArgumentException if type is not one of the
* three types of comments supported
* @deprecated use {@link #setComment(CommentType, String)} instead
*/
@Deprecated
public void setComment(int commentType, String comment);
/**
* Set the comment for the given comment type. Passing <code>null</code> clears the comment
*
* @param type of comment to set
* @param comment comment for code unit; null clears the comment
*/
public default void setComment(CommentType type, String comment) {
setComment(type.ordinal(), comment);
}
/**
* Set the comment (with each line in its own string) for the given comment type
*
@ -175,6 +226,10 @@ public interface CodeUnit extends MemBuffer, PropertySet {
*/
public void setCommentAsArray(int commentType, String[] comment);
public default void setCommentAsArray(CommentType type, String[] comment) {
setCommentAsArray(type.ordinal(), comment);
}
/**
* Get length of this code unit.
* NOTE: If an {@link Instruction#isLengthOverridden() instruction length-override} is

View file

@ -0,0 +1,40 @@
/* ###
* 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.program.model.listing;
/**
* Container for all the comments at an address
*/
public class CodeUnitComments {
private String[] comments;
public CodeUnitComments(String[] comments) {
if (comments.length != CommentType.values().length) {
throw new IllegalArgumentException("comment array size does not match enum size!");
}
this.comments = comments;
}
/**
* Get the comment for the given comment type
* @param type the {@link CommentType} to retrieve
* @return the comment of the given type or null if no comment of that type exists
*/
public String getComment(CommentType type) {
return comments[type.ordinal()];
}
}

View file

@ -0,0 +1,28 @@
/* ###
* 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.program.model.listing;
/**
* Types of comments that be placed at an address or on a {@link CodeUnit}
*/
public enum CommentType {
EOL, // comments that appear at the end of the line
PRE, // comments that appear before the code unit
POST, // comments that appear after the code unit
PLATE, // comments that appear before the code unit with a decorated border
REPEATABLE // comments that appear at locations that refer to the address
// where this comment is defined
}

View file

@ -15,6 +15,11 @@
*/
package ghidra.program.model.listing;
import java.util.ArrayList;
import java.util.List;
import ghidra.program.model.address.Address;
import ghidra.program.util.GroupPath;
import ghidra.util.exception.DuplicateNameException;
/**
@ -34,14 +39,14 @@ public interface Group {
*
* @param comment the comment.
*/
public void setComment(String comment);
public void setComment(String comment);
/**
* Obtains the name that has been associated with this fragment. A fragment will
* always have a name and it will be unique within the set of all fragment and
* module names.
*/
public String getName();
public String getName();
/**
* Sets the name of this fragment.
@ -52,8 +57,8 @@ public interface Group {
* thrown if the name being set is already in use by another fragment or a
* module.
*/
public void setName(String name) throws DuplicateNameException;
public void setName(String name) throws DuplicateNameException;
/**
* Returns whether this fragment contains the given code unit.
*
@ -61,7 +66,7 @@ public interface Group {
*
* @return true if the code unit is in the fragment, false otherwise.
*/
public boolean contains(CodeUnit codeUnit);
public boolean contains(CodeUnit codeUnit);
/**
* Obtains the number of parent's of this fragment. If a fragment is in a module
@ -71,21 +76,55 @@ public interface Group {
*
* @return the number of parents of this fragment.
*/
public int getNumParents();
public int getNumParents();
/**
* Returns a list of the modules which are parents for this group.
*/
public ProgramModule[] getParents();
public ProgramModule[] getParents();
/**
* Returns the names of the modules which are parents to this
* fragment.
*/
public String[] getParentNames();
public String[] getParentNames();
/**
* Returns the name of the tree that this group belongs to.
*/
public String getTreeName();
public String getTreeName();
/**
* Returns true if this group has been deleted from the program
* @return true if this group has been deleted from the program
*/
public boolean isDeleted();
public Address getMinAddress();
public Address getMaxAddress();
/**
* Returns one of many possible GroupPaths for this group. Since Fragments can belong in
* more than one module, there can be multiple legitimate group paths for a group. This method
* arbitrarily returns one valid group path.
* @return one of several possible group paths for this group
*/
public default GroupPath getGroupPath() {
List<String> parentNames = getParentNames(this);
return new GroupPath(parentNames.toArray(new String[parentNames.size()]));
}
private static List<String> getParentNames(Group group) {
Group[] parents = group.getParents();
if (parents == null || parents.length == 0) {
List<String> list = new ArrayList<>();
list.add(group.getName());
return list;
}
Group parent = parents[0];
List<String> names = getParentNames(parent);
names.add(group.getName());
return names;
}
}

View file

@ -144,19 +144,51 @@ public interface Listing {
*/
public CodeUnitIterator getCommentCodeUnitIterator(int commentType, AddressSetView addrSet);
/**
* Get a forward code unit iterator over code units that have the specified
* comment type.
*
* @param type the comment type
* @param addrSet address set to iterate code unit comments over
* @return a CodeUnitIterator that returns all code units from the indicated
* address set that have the specified comment type defined
*/
public default CodeUnitIterator getCommentCodeUnitIterator(CommentType type,
AddressSetView addrSet) {
return getCommentCodeUnitIterator(type.ordinal(), addrSet);
}
/**
* Get a forward iterator over addresses that have the specified comment
* type.
*
* @param commentType type defined in CodeUnit
* @param addrSet address set
* @param addrSet address set to iterate code unit comments over
* @param forward true to iterator from lowest address to highest, false
* highest to lowest
* @return an AddressIterator that returns all addresses from the indicated
* address set that have the specified comment type defined
* @deprecated use {@link #getCommentAddressIterator(CommentType, AddressSetView, boolean)}
*/
@Deprecated
public AddressIterator getCommentAddressIterator(int commentType, AddressSetView addrSet,
boolean forward);
/**
* Get a forward iterator over addresses that have the specified comment
* type.
*
* @param type the type of comment to iterate over
* @param addrSet address set to iterate code unit comments over
* @param forward true to iterator from lowest address to highest, false
* highest to lowest
* @return an AddressIterator that returns all addresses from the indicated
* address set that have the specified comment type defined
*/
public AddressIterator getCommentAddressIterator(int commentType, AddressSetView addrSet,
boolean forward);
public default AddressIterator getCommentAddressIterator(CommentType type,
AddressSetView addrSet, boolean forward) {
return getCommentAddressIterator(type.ordinal(), addrSet, forward);
}
/**
* Get a forward iterator over addresses that have any type of comment.
@ -179,9 +211,30 @@ public interface Listing {
* of that type exists for this code unit
* @throws IllegalArgumentException if type is not one of the types of
* comments supported
* @deprecated use {@link #getComment(CommentType, Address)}
*/
@Deprecated
public String getComment(int commentType, Address address);
/**
* Get all the comments at the given address.
* @param address the address get comments
* @return a CodeUnitComments object that has all the comments at the address.
*/
public CodeUnitComments getAllComments(Address address);
/**
* Get the comment for the given type at the specified address.
*
* @param type the comment type to retrieve
* @param address the address of the comment.
* @return the comment string of the appropriate type or null if no comment
* of that type exists for this code unit
*/
public default String getComment(CommentType type, Address address) {
return getComment(type.ordinal(), address);
}
/**
* Set the comment for the given comment type at the specified address.
*
@ -191,9 +244,24 @@ public interface Listing {
* @param comment comment to set at the address
* @throws IllegalArgumentException if type is not one of the types of
* comments supported
* @deprecated use {@link #setComment(Address, CommentType, String)}
*/
@Deprecated
public void setComment(Address address, int commentType, String comment);
/**
* Set the comment for the given comment type at the specified address.
*
* @param address the address of the comment.
* @param type the type of comment to set
* @param comment comment to set at the address
* @throws IllegalArgumentException if type is not one of the types of
* comments supported
*/
public default void setComment(Address address, CommentType type, String comment) {
setComment(address, type.ordinal(), comment);
}
/**
* get a CodeUnit iterator that will iterate over the entire address space.
*
@ -983,4 +1051,10 @@ public interface Listing {
*/
public CommentHistory[] getCommentHistory(Address addr, int commentType);
/**
* Returns the number of addresses where at least one comment type has been applied.
* @return the number of addresses where at least one comment type has been applied
*/
public long getCommentAddressCount();
}

View file

@ -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.
@ -90,11 +90,21 @@ public class StubListing implements Listing {
throw new UnsupportedOperationException();
}
@Override
public long getCommentAddressCount() {
throw new UnsupportedOperationException();
}
@Override
public String getComment(int commentType, Address address) {
throw new UnsupportedOperationException();
}
@Override
public CodeUnitComments getAllComments(Address address) {
throw new UnsupportedOperationException();
}
@Override
public void setComment(Address address, int commentType, String comment) {
throw new UnsupportedOperationException();

View file

@ -1,13 +1,12 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* 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 +17,7 @@ package ghidra.program.util;
import ghidra.program.model.listing.CodeUnit;
public class CommentType {
public class CommentTypeUtils {
/**
* Get the comment type from the current location. If the cursor