From d7aab23c92e2d1266788185d87f43b0db03ec668 Mon Sep 17 00:00:00 2001 From: comex Date: Sat, 11 May 2019 17:00:37 -0700 Subject: [PATCH 001/140] Call UIManager.getDefaults() instead of UIManager.getLookAndFeel().getDefaults() --- .../main/java/docking/menu/DockingCheckboxMenuItemUI.java | 3 +-- .../src/main/java/docking/menu/DockingMenuItemUI.java | 3 +-- .../Docking/src/main/java/docking/menu/DockingMenuUI.java | 3 +-- .../ghidra/docking/util/DockingWindowsLookAndFeelUtils.java | 5 ++--- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java index 6cfc44548b..bbffa22fda 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java @@ -26,9 +26,8 @@ import javax.swing.plaf.MenuItemUI; public class DockingCheckboxMenuItemUI extends DockingMenuItemUI { public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingCheckboxMenuItemUI result = new DockingCheckboxMenuItemUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java index 6d6c2042d0..d7ad215f24 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java @@ -67,9 +67,8 @@ public class DockingMenuItemUI extends MenuItemUI { protected MenuItemUI ui; public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingMenuItemUI result = new DockingMenuItemUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java index 8b61ac3cb4..7a6a4589c0 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java @@ -22,9 +22,8 @@ import javax.swing.plaf.MenuItemUI; public class DockingMenuUI extends DockingMenuItemUI { public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingMenuUI result = new DockingMenuUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } } diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java index 121a3b0de7..6e7956efe1 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java @@ -204,7 +204,7 @@ public class DockingWindowsLookAndFeelUtils { case NIMBUS_LOOK_AND_FEEL: // fix scroll bar grabber disappearing. See https://bugs.openjdk.java.net/browse/JDK-8134828 // This fix looks like it should not cause harm even if the bug is fixed on the jdk side. - UIDefaults defaults = lookAndFeel.getDefaults(); + UIDefaults defaults = UIManager.getDefaults(); defaults.put("ScrollBar.minimumThumbSize", new Dimension(30, 30)); break; } @@ -275,8 +275,7 @@ public class DockingWindowsLookAndFeelUtils { /** Allows you to globally set the font size (don't use this method!) */ private static void setGlobalFontSizeOverride(int fontSize) { - LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); - UIDefaults defaults = lookAndFeel.getDefaults(); + UIDefaults defaults = UIManager.getDefaults(); Set> set = defaults.entrySet(); Iterator> iterator = set.iterator(); From ca1047cd970f3ef09c3aec6dc756fe0a830e7607 Mon Sep 17 00:00:00 2001 From: Nick Fox Date: Thu, 1 Oct 2020 10:58:55 -0400 Subject: [PATCH 002/140] fix #2283 - 'persistent' spelling error --- .../formats/gfilesystem/FileSystemService.java | 2 +- .../java/ghidra/util/state/VarnodeOperation.java | 2 +- .../Features/Decompiler/ghidra_scripts/GraphAST.java | 2 +- .../ghidra/program/model/pcode/PcodeFactory.java | 2 +- .../ghidra/program/model/pcode/PcodeSyntaxTree.java | 4 ++-- .../java/ghidra/program/model/pcode/Varnode.java | 6 +++--- .../java/ghidra/program/model/pcode/VarnodeAST.java | 12 ++++++------ 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java index b2711c6493..1ada2cecae 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java @@ -56,7 +56,7 @@ import ghidra.util.timer.GTimer; * * Refactor fileInfo -> needs dialog to show properties * Refactor GFile.getInfo() to return Map<> instead of String. - * Persistant filesystem - when reopen tool, filesystems should auto-reopen. + * Persistent filesystem - when reopen tool, filesystems should auto-reopen. * Unify GhidraFileChooser with GFileSystem. * Add "Mounted Filesystems" button to show currently opened GFilesystems? * Dockable filesystem browser in FrontEnd. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java index 0d098c9bc1..df53f942cf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java @@ -170,7 +170,7 @@ public class VarnodeOperation extends Varnode { } @Override - public boolean isPersistant() { + public boolean isPersistent() { return false; } diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java index f1d5d06ff9..badf03d654 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java @@ -128,7 +128,7 @@ public class GraphAST extends GhidraScript { else if (vn.isUnique()) { colorattrib = "Black"; } - else if (vn.isPersistant()) { + else if (vn.isPersistent()) { colorattrib = "DarkOrange"; } else if (vn.isAddrTied()) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java index 11e248eec2..da39b07af5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java @@ -61,7 +61,7 @@ public interface PcodeFactory { public HighSymbol getSymbol(long symbolId); public Varnode setInput(Varnode vn,boolean val); public void setAddrTied(Varnode vn,boolean val); - public void setPersistant(Varnode vn,boolean val); + public void setPersistent(Varnode vn, boolean val); public void setUnaffected(Varnode vn,boolean val); public void setMergeGroup(Varnode vn,short val); public void setDataType(Varnode vn,DataType type); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java index 48cd3429a6..4e1002e758 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java @@ -392,9 +392,9 @@ public class PcodeSyntaxTree implements PcodeFactory { } @Override - public void setPersistant(Varnode vn, boolean val) { + public void setPersistent(Varnode vn, boolean val) { VarnodeAST vnast = (VarnodeAST) vn; - vnast.setPersistant(val); + vnast.setPersistent(val); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java index 58a175c7a9..4e6f867f4b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java @@ -255,9 +255,9 @@ public class Varnode { } /** - * @return is persistant + * @return is persistent */ - public boolean isPersistant() { + public boolean isPersistent() { return false; // Not a valid query with a free varnode } @@ -476,7 +476,7 @@ public class Varnode { } attrstring = el.getAttribute("persists"); if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { - factory.setPersistant(vn, true); + factory.setPersistent(vn, true); } attrstring = el.getAttribute("addrtied"); if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java index 8a837809e4..a3c3241b6a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java @@ -37,7 +37,7 @@ public class VarnodeAST extends Varnode { private boolean bInput; private boolean bAddrTied; - private boolean bPersistant; + private boolean bPersistent; private boolean bUnaffected; private boolean bFree; private int uniqId; // Unique Id for distinguishing otherwise identical varnodes @@ -50,7 +50,7 @@ public class VarnodeAST extends Varnode { super(a, sz); bInput = false; bAddrTied = false; - bPersistant = false; + bPersistent = false; bUnaffected = false; bFree = true; uniqId = id; @@ -70,8 +70,8 @@ public class VarnodeAST extends Varnode { } @Override - public boolean isPersistant() { - return bPersistant; + public boolean isPersistent() { + return bPersistent; } @Override @@ -132,8 +132,8 @@ public class VarnodeAST extends Varnode { def = null; } - public void setPersistant(boolean val) { - bPersistant = val; + public void setPersistent(boolean val) { + bPersistent = val; } public void setUnaffected(boolean val) { From 6609c53a2ff0326e35b00634ec816fe6e78d21af Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Wed, 7 Oct 2020 14:56:58 -0400 Subject: [PATCH 003/140] GP-0 update bug report template with ghidra distro question --- .github/ISSUE_TEMPLATE/bug_report.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 385782a424..2882356cb6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -29,7 +29,8 @@ If applicable, please attach any files that caused problems or log files generat **Environment (please complete the following information):** - OS: [e.g. macOS 10.14.2] - Java Version: [e.g. 11.0] - - Ghidra Version: [e.g. 9.0] + - Ghidra Version: [e.g. 9.1.2] + - Ghidra Origin: [e.g. official ghidra-sre.org distro, third party distro, locally built] **Additional context** Add any other context about the problem here. From 865b156b08c42e03edc5e50a41d7ba41108b3870 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Thu, 12 Nov 2020 01:21:03 +0100 Subject: [PATCH 004/140] Fixed ARM coproc regs for CRn == c1 --- .../ARM/data/languages/ARMinstructions.sinc | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc index a755d7895b..86b48c779e 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc @@ -676,8 +676,9 @@ define pcodeop coproc_moveto_Cache_Type; define pcodeop coproc_moveto_TCM_Status; define pcodeop coproc_moveto_TLB_Type; define pcodeop coproc_moveto_Control; -define pcodeop coproc_moveto_Auxilary_Control; +define pcodeop coproc_moveto_Auxiliary_Control; define pcodeop coproc_moveto_Coprocessor_Access_Control; +define pcodeop coproc_moveto_Secure_Configuration; define pcodeop coproc_moveto_Translation_table_base_0; define pcodeop coproc_moveto_Translation_table_base_1; define pcodeop coproc_moveto_Translation_table_control; @@ -726,8 +727,9 @@ define pcodeop coproc_movefrom_Cache_Type; define pcodeop coproc_movefrom_TCM_Status; define pcodeop coproc_movefrom_TLB_Type; define pcodeop coproc_movefrom_Control; -define pcodeop coproc_movefrom_Auxilary_Control; +define pcodeop coproc_movefrom_Auxiliary_Control; define pcodeop coproc_movefrom_Coprocessor_Access_Control; +define pcodeop coproc_movefrom_Secure_Configuration; define pcodeop coproc_movefrom_Translation_table_base_0; define pcodeop coproc_movefrom_Translation_table_base_1; define pcodeop coproc_movefrom_Translation_table_control; @@ -2941,16 +2943,16 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate :mcr^COND mcrOperands is - $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & mcrOperands { build COND; - coproc_moveto_Auxilary_Control(Rd); + coproc_moveto_Auxiliary_Control(Rd); } :mcr^COND mcrOperands is - $(AMODE) & CRm=2 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & mcrOperands { build COND; @@ -2958,6 +2960,15 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate } +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Secure_Configuration(Rd); +} + + :mcr^COND mcrOperands is $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & mcrOperands @@ -3590,17 +3601,17 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate :mrc^COND mcrOperands is - $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & mcrOperands { build COND; - Rd = coproc_movefrom_Auxilary_Control(); + Rd = coproc_movefrom_Auxiliary_Control(); } :mrc^COND mcrOperands is - $(AMODE) & CRm=2 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & mcrOperands { build COND; @@ -3609,6 +3620,16 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Secure_Configuration(); +} + + + :mrc^COND mcrOperands is $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & mcrOperands From 823887cf89786eb19caadfe49ca546fda3073d63 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Thu, 12 Nov 2020 01:21:30 +0100 Subject: [PATCH 005/140] Added missing CRn == c1, op1 == 0 coproc registers --- .../ARM/data/languages/ARMinstructions.sinc | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc index 86b48c779e..2a4651d775 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc @@ -679,6 +679,8 @@ define pcodeop coproc_moveto_Control; define pcodeop coproc_moveto_Auxiliary_Control; define pcodeop coproc_moveto_Coprocessor_Access_Control; define pcodeop coproc_moveto_Secure_Configuration; +define pcodeop coproc_moveto_Secure_Debug_Enable; +define pcodeop coproc_moveto_Non-Secure_Access_Control; define pcodeop coproc_moveto_Translation_table_base_0; define pcodeop coproc_moveto_Translation_table_base_1; define pcodeop coproc_moveto_Translation_table_control; @@ -730,6 +732,8 @@ define pcodeop coproc_movefrom_Control; define pcodeop coproc_movefrom_Auxiliary_Control; define pcodeop coproc_movefrom_Coprocessor_Access_Control; define pcodeop coproc_movefrom_Secure_Configuration; +define pcodeop coproc_movefrom_Secure_Debug_Enable; +define pcodeop coproc_movefrom_Non-Secure_Access_Control; define pcodeop coproc_movefrom_Translation_table_base_0; define pcodeop coproc_movefrom_Translation_table_base_1; define pcodeop coproc_movefrom_Translation_table_control; @@ -2969,6 +2973,24 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate } +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Secure_Debug_Enable(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Non-Secure_Access_Control(Rd); +} + + :mcr^COND mcrOperands is $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & mcrOperands @@ -3630,6 +3652,26 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Secure_Debug_Enable(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Non-Secure_Access_Control(); +} + + + :mrc^COND mcrOperands is $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & mcrOperands From 6b145561d147e583648067247da9a6ced191423b Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Thu, 12 Nov 2020 01:46:25 +0100 Subject: [PATCH 006/140] Changed Non-Secure to NonSecure, because the dash breaks the build --- Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc index 2a4651d775..3810576019 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc @@ -680,7 +680,7 @@ define pcodeop coproc_moveto_Auxiliary_Control; define pcodeop coproc_moveto_Coprocessor_Access_Control; define pcodeop coproc_moveto_Secure_Configuration; define pcodeop coproc_moveto_Secure_Debug_Enable; -define pcodeop coproc_moveto_Non-Secure_Access_Control; +define pcodeop coproc_moveto_NonSecure_Access_Control; define pcodeop coproc_moveto_Translation_table_base_0; define pcodeop coproc_moveto_Translation_table_base_1; define pcodeop coproc_moveto_Translation_table_control; @@ -733,7 +733,7 @@ define pcodeop coproc_movefrom_Auxiliary_Control; define pcodeop coproc_movefrom_Coprocessor_Access_Control; define pcodeop coproc_movefrom_Secure_Configuration; define pcodeop coproc_movefrom_Secure_Debug_Enable; -define pcodeop coproc_movefrom_Non-Secure_Access_Control; +define pcodeop coproc_movefrom_NonSecure_Access_Control; define pcodeop coproc_movefrom_Translation_table_base_0; define pcodeop coproc_movefrom_Translation_table_base_1; define pcodeop coproc_movefrom_Translation_table_control; @@ -2987,7 +2987,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate mcrOperands { build COND; - coproc_moveto_Non-Secure_Access_Control(Rd); + coproc_moveto_NonSecure_Access_Control(Rd); } @@ -3667,7 +3667,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate mcrOperands { build COND; - Rd = coproc_movefrom_Non-Secure_Access_Control(); + Rd = coproc_movefrom_NonSecure_Access_Control(); } From ad1c5d78196896b990271598725bc26d37024f12 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Fri, 15 Jan 2021 19:24:45 +0000 Subject: [PATCH 007/140] 68000: fix SP postincrement/predecrement with byte operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the address register is the stack pointer and the operand size is byte, the address is incremented/decremented by two to keep the stack pointer aligned to a word boundary. [M68000 Family Programmer’s Reference Manual; 2.2.4 & 2.2.5] fixes #1709 --- Ghidra/Processors/68000/data/languages/68000.sinc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 773ee2c4c6..0a8a413d71 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -417,7 +417,9 @@ eaw: "#"^d16 is mode=7 & regan=4; d16 { export *[const]:2 d16; } eab: regdnb is mode=0 & regdnb { export regdnb; } eab: reganb is mode=1 & reganb { export reganb; } eab: (regan) is mode=2 & regan { export *:1 regan; } +eab: (regan)+ is mode=3 & regan & regan=7 { local tmp = regan; regan = regan + 2; export *:1 tmp; } eab: (regan)+ is mode=3 & regan { local tmp = regan; regan = regan + 1; export *:1 tmp; } +eab: -(regan) is mode=4 & regan & regan=7 { regan = regan - 2; export *:1 regan; } eab: -(regan) is mode=4 & regan { regan = regan - 1; export *:1 regan; } eab: (d16,regan) is mode=5 & regan; d16 { local tmp = regan + d16; export *:1 tmp; } eab: (extw) is mode=6 & regan; extw [ pcmode=0; regtfan=regan; ] { build extw; export *:1 extw; } @@ -488,11 +490,13 @@ e2w: (d32)".l" is savmod2=7 & regsan=1; d32 { export *:2 d32; } e2w: "#"^d16 is savmod2=7 & regsan=4; d16 { export *[const]:2 d16; } # size=byte - # NB- TODO- Manual says that if in predecrement or postincrement mode and the res is the SP, then must inc/dec by 2, not by 1 + # NB- Manual says that if in predecrement or postincrement mode and the res is the SP, then must inc/dec by 2, not by 1 e2b: regsdnb is savmod2=0 & regsdnb { export regsdnb; } e2b: regsanb is savmod2=1 & regsanb { export regsanb; } e2b: (regsan) is savmod2=2 & regsan { export *:1 regsan; } +e2b: (regsan)+ is savmod2=3 & regsan & regsan=7 { local tmp = regsan; regsan = regsan + 2; export *:1 tmp; } e2b: (regsan)+ is savmod2=3 & regsan { local tmp = regsan; regsan = regsan + 1; export *:1 tmp; } +e2b: -(regsan) is savmod2=4 & regsan & regsan=7 { regsan = regsan - 2; export *:1 regsan; } e2b: -(regsan) is savmod2=4 & regsan { regsan = regsan - 1; export *:1 regsan; } e2b: (d16,regsan) is savmod2=5 & regsan; d16 { local tmp = regsan + d16; export *:1 tmp; } e2b: (extw) is savmod2=6; extw [ pcmode=0; eanum=1; ] { build extw; export *:1 extw; } From 4d03a1f05b195c65e155cee5dd88e1d80f848ad7 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Wed, 25 Nov 2020 10:45:39 -0500 Subject: [PATCH 008/140] Initial commit of CustomAttrib blob processing --- .../pe/cli/blobs/CliBlobCustomAttrib.java | 478 ++++++++++++++++++ .../format/pe/cli/streams/CliStreamBlob.java | 11 +- .../pe/cli/streams/CliStreamMetadata.java | 2 +- .../cli/tables/CliTableCustomAttribute.java | 69 ++- 4 files changed, 544 insertions(+), 16 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java new file mode 100644 index 0000000000..66230ab4cb --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -0,0 +1,478 @@ +/* ### + * 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.bin.format.pe.cli.blobs; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +import ghidra.app.util.bin.BinaryReader; +import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliElementType; +import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliParam; +import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; +import ghidra.app.util.bin.format.pe.cli.tables.CliTableCustomAttribute.CliCustomAttributeRow; +import ghidra.app.util.bin.format.pe.cli.tables.CliTableMemberRef.CliMemberRefRow; +import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodDef.CliMethodDefRow; +import ghidra.app.util.bin.format.pe.cli.tables.CliTypeTable; +import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexCustomAttributeType; +import ghidra.program.model.data.*; +import ghidra.util.Msg; +import ghidra.util.exception.InvalidInputException; + +public class CliBlobCustomAttrib extends CliBlob { + + private CliFixedArg[] fixedArgs; + private CliNamedArg[] namedArgs; + private short numNamed; + + // Fixed constants for validating the structure + private final short CLIBLOBCUSTOMATTRIB_PROLOG = 0x0001; + private final byte CLIBLOBCUSTOMATTRIB_TYPE_FIELD = 0x53; + private final byte CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY = 0x54; + + // SerString processing constants to validate and convert the + // length of the string + private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64 = 0x40; + private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128 = 0x80; + private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192 = 0xC0; + + // UTF-8 boundaries that help detect the end of a string where + // lengths aren't specified in FixedArg + private final int CLIBLOBCUSTOMATTRIB_UTF8_LOW = 0x1F; + private final int CLIBLOBCUSTOMATTRIB_UTF8_HIGH = 0x7F; + + private class CliFixedArg { + private CliElementType elem; + private Object value; + + public CliFixedArg(CliElementType elem, Object value) { + this.elem = elem; + this.value = value; + } + + public CliElementType getElem() { + return elem; + } + + public Object getValue() { + return value; + } + } + + private class CliNamedArg { + private int fieldOrProp; + private CliElementType fieldOrPropType; + private String fieldOrPropName; + + public CliNamedArg(int fieldOrProp, CliElementType fieldOrPropType, + String fieldOrPropName) { + this.fieldOrProp = fieldOrProp; + this.fieldOrPropType = fieldOrPropType; + this.fieldOrPropName = fieldOrPropName; + } + + public int getFieldOrProp() { + return fieldOrProp; + } + + public CliElementType getFieldOrPropType() { + return fieldOrPropType; + } + + public String getFieldOrPropName() { + return fieldOrPropName; + } + } + + public CliBlobCustomAttrib(CliBlob blob, CliCustomAttributeRow row, + CliStreamMetadata metadataStream) throws IOException { + super(blob); + + BinaryReader reader = blob.getContentsReader(); + + // Validate the blob prolog + short prolog = reader.readNextShort(); + if (prolog != CLIBLOBCUSTOMATTRIB_PROLOG) { + Msg.warn(this, + getName() + " had unexpected prolog (0x" + Integer.toHexString(prolog) + ")"); + return; + } + + // The location in the blob table for the actual CustomAttrib blob + int valueIndex = row.valueIndex; + + // The entry in the MethodRef or MethodDef table that corresponds to the method + // This is a CustomAttributeType coded index + int typeIndex = row.typeIndex; + + // The entry of the parent table index, also a CustomAttributeType coded index + int parentIndex = row.parentIndex; + + // The FixedArg parameters in the CustomAttrib blob are stored concatenated + // against each other without delimeters or type indicators, so you have to look + // back to the originating method signature to figure out what's what. + + CliParam[] params = null; + try { + // Get the table type and row for the attribute and depending on the type + // get the parameters + CliTypeTable tableType = CliIndexCustomAttributeType.getTableName(typeIndex); + int tableRow = CliIndexCustomAttributeType.getRowIndex(typeIndex); + + if (tableType == CliTypeTable.MemberRef) { + CliMemberRefRow memberRefRow = + (CliMemberRefRow) metadataStream.getTable(tableType).getRow(tableRow); + CliBlob memberRefBlob = + metadataStream.getBlobStream().getBlob(memberRefRow.signatureIndex); + CliSigMethodRef methodRefSig = new CliSigMethodRef(memberRefBlob); + params = methodRefSig.getParams(); + } + else if (tableType == CliTypeTable.MethodDef) { + CliMethodDefRow methodDefRow = + (CliMethodDefRow) metadataStream.getTable(tableType).getRow(tableRow); + CliBlob methodDefBlob = + metadataStream.getBlobStream().getBlob(methodDefRow.sigIndex); + CliSigMethodDef methodDefSig = new CliSigMethodDef(methodDefBlob); + params = methodDefSig.getParamTypes(); + } + } + catch (InvalidInputException e) { + Msg.warn(this, "Unable to process the parameters in " + getName()); + return; + } + + // Process zero to multiple FixedArgs + if (params != null) { + ArrayList processFixedArgs = new ArrayList<>(); + for (CliParam param : params) { + byte elemByte = reader.peekNextByte(); + if (elemByte == CliElementType.ELEMENT_TYPE_I.id()) { + reader.readNextByte(); + + // IntPtr followed by a string of the name of the element, the + // length of which is not specified and must be read until a + // non-printable UTF-8 character is encountered to signal the + // end of the name + + StringBuilder sb = new StringBuilder(); + while ((reader.peekNextByte() > CLIBLOBCUSTOMATTRIB_UTF8_LOW) && + (reader.peekNextByte() < CLIBLOBCUSTOMATTRIB_UTF8_HIGH)) { + sb.append((char) reader.readNextByte()); + } + + processFixedArgs + .add(new CliFixedArg(CliElementType.ELEMENT_TYPE_I, sb.toString())); + } + else { + // Process Elem types + switch (param.getType().baseTypeCode) { + case ELEMENT_TYPE_BOOLEAN: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextByte())); + break; + + case ELEMENT_TYPE_CHAR: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextShort())); + break; + + case ELEMENT_TYPE_I1: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextByte())); + break; + + case ELEMENT_TYPE_U1: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextUnsignedByte())); + break; + + case ELEMENT_TYPE_I2: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextShort())); + break; + + case ELEMENT_TYPE_U2: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextUnsignedShort())); + break; + + case ELEMENT_TYPE_I4: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextInt())); + break; + + case ELEMENT_TYPE_U4: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextUnsignedInt())); + break; + + case ELEMENT_TYPE_I8: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextLong())); + break; + + case ELEMENT_TYPE_U8: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextByteArray(LongLongDataType.dataType.getLength()))); + break; + + case ELEMENT_TYPE_R4: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextByteArray(Float4DataType.dataType.getLength()))); + break; + + case ELEMENT_TYPE_R8: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextByteArray(Float8DataType.dataType.getLength()))); + break; + + case ELEMENT_TYPE_STRING: + int length = readSerStringLength(reader); + processFixedArgs + .add(new CliFixedArg(param.getType().baseTypeCode, new String( + reader.readNextByteArray(length), StandardCharsets.UTF_8))); + break; + + case ELEMENT_TYPE_VALUETYPE: + processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, + reader.readNextInt())); + break; + + default: + Msg.info(this, + "Found a CustomAttrib with an unprocessed element type: " + + param.getRepresentation()); + } + } + } + + fixedArgs = new CliFixedArg[processFixedArgs.size()]; + for (int i = 0; i < fixedArgs.length; i++) { + fixedArgs[i] = processFixedArgs.get(i); + } + } + + // NumNamed + numNamed = reader.readNextShort(); + + // Process zero to multiple NamedArgs here + ArrayList processNamedArgs = new ArrayList<>(); + for (int i = 0; i < numNamed; i++) { + byte fieldOrProp = reader.readNextByte(); + if ((fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_FIELD) && + fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { + Msg.warn(this, "Invalid FieldOrProp value in NamedArg #" + (i + 1) + ": 0x" + + Integer.toHexString(fieldOrProp)); + continue; + } + + CliElementType fieldOrPropType = CliElementType.fromInt(reader.readNextByte()); + + // Account for the null terminator + int nameLen = readSerStringLength(reader) + 1; + String fieldOrPropName = + new String(reader.readNextByteArray(nameLen), StandardCharsets.UTF_8); + + processNamedArgs.add(new CliNamedArg(fieldOrProp, fieldOrPropType, fieldOrPropName)); + } + + if (processNamedArgs.size() > 0) { + namedArgs = new CliNamedArg[processNamedArgs.size()]; + for (int i = 0; i < namedArgs.length; i++) { + namedArgs[i] = processNamedArgs.get(i); + } + } + } + + @Override + public DataType getContentsDataType() { + StructureDataType struct = new StructureDataType(new CategoryPath(PATH), getName(), 0); + struct.add(WORD, "PROLOG", "Magic (0x0001)"); + + // Display the FixedArgs + if (fixedArgs != null) { + for (int i = 0; i < fixedArgs.length; i++) { + switch (fixedArgs[i].elem) { + case ELEMENT_TYPE_CHAR: + struct.add(UTF16, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); + break; + + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_BOOLEAN: + struct.add(BYTE, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); + break; + + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + struct.add(WORD, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); + break; + + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_VALUETYPE: + struct.add(DWORD, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); + break; + + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R8: + struct.add(QWORD, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); + + case ELEMENT_TYPE_STRING: + String s = (String) fixedArgs[i].value; + int l = s.length(); + if (l < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + struct.add(BYTE, "PackedLen", ""); + } + else if (l < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192) { + struct.add(WORD, "PackedLen", ""); + } + else { + struct.add(DWORD, "PackedLen", ""); + + } + struct.add(UTF8, ((String) fixedArgs[i].value).length(), "FixedArg_" + i, + ""); + break; + + case ELEMENT_TYPE_I: + struct.add(BYTE, "ELEMENT_TYPE_I", ""); + struct.add(UTF8, ((String) fixedArgs[i].value).length(), "FixedArg_" + i, + ""); + break; + + default: + Msg.warn(this, "Unprocessed FixedArg element type in CustomAttr #" + + (i + 1) + ": " + fixedArgs[i].getElem().name()); + break; + } + } + } + + struct.add(WORD, "NumNamed", "Number of NamedArgs to follow"); + + // Display the NamedArgs + if (namedArgs != null) { + for (int i = 0; i < numNamed; i++) { + if (namedArgs[i].getFieldOrProp() == CLIBLOBCUSTOMATTRIB_TYPE_FIELD) { + struct.add(BYTE, "FieldOrProp", "FIELD"); + } + else if (namedArgs[i].getFieldOrProp() == CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { + struct.add(BYTE, "FieldOrProp", "PROPERTY"); + } + else { + struct.add(BYTE, "FieldOrProp", "Unknown value"); + } + + struct.add(BYTE, "FieldOrPropType", namedArgs[i].getFieldOrPropType().name()); + + int nameLen = namedArgs[i].getFieldOrPropName().length(); + if (nameLen < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + struct.add(BYTE, "PackedLen", ""); + } + else if (nameLen < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192) { + struct.add(WORD, "PackedLen", ""); + } + else { + struct.add(DWORD, "PackedLen", ""); + + } + + struct.add(UTF8, nameLen, "FieldOrPropName", ""); + } + } + + return struct; + } + + @Override + public String getContentsName() { + return "CustomAttrib"; + } + + @Override + public String getContentsComment() { + return "A CustomAttrib blob stores values of fixed or named parameters supplied when " + + "instantiating a custom attribute"; + } + + @Override + public String getRepresentation() { + return "Blob (" + getContentsDataType().getDisplayName() + ")"; + } + + // SerStrings ("serialized strings") have a length field that varies in size + // based on the length of the string. This measures and decodes the Byte, Word, + // or DWord length field and returns it. + private int readSerStringLength(BinaryReader reader) throws IOException { + byte[] length; + ByteBuffer buf; + + // The first byte is either the size or an indicator that we have more + // size bytes ahead. Values contained in more than one bytes are stored + // big-endian. + byte firstByte = reader.readNextByte(); + + if (firstByte < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + // A size less than 128 indicates this is the only size byte + return firstByte; + } + else if (firstByte < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192) { + // A value in the first byte in range [128 - 191] indicates the size + // is stored as a Word and the value in the highest bit must be unset + length = new byte[] { firstByte, reader.readNextByte() }; + + // Unset the highest bit if it's set + if ((length[1] & + CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + length[1] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128; + } + + // Convert from big-endian + buf = ByteBuffer.wrap(length); + buf.order(ByteOrder.BIG_ENDIAN); + return buf.getShort(); + } + else { + // A value in the first byte > 128 indicates the size is stored as + // a DWord and the first two bits must be unset + length = new byte[4]; + length[0] = firstByte; + length[1] = reader.readNextByte(); + length[2] = reader.readNextByte(); + length[3] = reader.readNextByte(); + + // Unset what will become the highest two bits if they're set + if ((length[3] & + CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + length[3] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128; + } + if ((length[3] & + CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64) { + length[3] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64; + } + + // Convert from big-endian + buf = ByteBuffer.wrap(length); + buf.order(ByteOrder.BIG_ENDIAN); + return buf.getInt(); + } + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java index 1aa101521d..a5f065511a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java @@ -16,11 +16,12 @@ package ghidra.app.util.bin.format.pe.cli.streams; import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; import ghidra.app.util.bin.BinaryReader; +import ghidra.app.util.bin.format.pe.PeUtils; import ghidra.app.util.bin.format.pe.cli.CliStreamHeader; +import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliCustomAttrib; import ghidra.app.util.bin.format.pe.cli.blobs.CliBlob; import ghidra.program.model.address.Address; import ghidra.program.model.data.*; @@ -123,15 +124,15 @@ public class CliStreamBlob extends CliAbstractStream { DataType oldBlobDataType = oldBlobDataComponent.getDataType(); DataType newBlobDataType = updatedBlob.toDataType(); if (oldBlobDataType.getLength() != newBlobDataType.getLength()) { - Msg.error(this, "Cannot replace existing blob at address " + addr + " with " + - updatedBlob.getName() + " because they have different sizes."); + Msg.error(this, "Cannot replace existing " + updatedBlob.getName() + " at address " + addr + " with " + + updatedBlob.getName() + " because they have different sizes (old: " + oldBlobDataType.getLength() + ", new: " + newBlobDataType.getLength() + ")."); return false; } // Update the blob containingStructure.replaceAtOffset(structureOffset, newBlobDataType, updatedBlob.getSize(), updatedBlob.getName(), updatedBlob.getContentsComment()); - + return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java index 65d8faf138..0644f3d572 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java @@ -435,7 +435,7 @@ public class CliStreamMetadata extends CliAbstractStream { table.markup(program, isBinary, monitor, log, ntHeader); } catch (Exception e) { - Msg.error(this, "Failed to markup " + table); + Msg.error(this, "Failed to markup " + table + ": " + e.toString()); } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index 4f5bad550f..37387bdcce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -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,22 +18,35 @@ package ghidra.app.util.bin.format.pe.cli.tables; import java.io.IOException; import ghidra.app.util.bin.BinaryReader; +import ghidra.app.util.bin.format.pe.NTHeader; +import ghidra.app.util.bin.format.pe.cli.blobs.CliBlobCustomAttrib; +import ghidra.app.util.bin.format.pe.cli.streams.CliAbstractStream; import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexCustomAttributeType; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexHasCustomAttribute; +import ghidra.app.util.importer.MessageLog; +import ghidra.program.model.address.Address; import ghidra.program.model.data.CategoryPath; import ghidra.program.model.data.StructureDataType; +import ghidra.program.model.listing.BookmarkType; +import ghidra.program.model.listing.Program; +import ghidra.program.model.util.CodeUnitInsertionException; +import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.InvalidInputException; +import ghidra.util.task.TaskMonitor; /** - * Describes the CustomAttribute table. + * Describes the CustomAttribute table. */ public class CliTableCustomAttribute extends CliAbstractTable { public class CliCustomAttributeRow extends CliAbstractTableRow { public int parentIndex; public int typeIndex; public int valueIndex; - + + private final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODDEF = 0x02; + private final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODREF = 0x03; + public CliCustomAttributeRow(int parentIndex, int typeIndex, int valueIndex) { super(); this.parentIndex = parentIndex; @@ -45,13 +58,17 @@ public class CliTableCustomAttribute extends CliAbstractTable { public String getRepresentation() { String parentRep, typeRep; try { - parentRep = getRowRepresentationSafe(CliIndexHasCustomAttribute.getTableName(parentIndex), CliIndexHasCustomAttribute.getRowIndex(parentIndex)); + parentRep = + getRowRepresentationSafe(CliIndexHasCustomAttribute.getTableName(parentIndex), + CliIndexHasCustomAttribute.getRowIndex(parentIndex)); } catch (InvalidInputException e) { parentRep = Integer.toHexString(parentIndex); } try { - typeRep = getRowRepresentationSafe(CliIndexCustomAttributeType.getTableName(parentIndex), CliIndexCustomAttributeType.getRowIndex(parentIndex)); + typeRep = + getRowRepresentationSafe(CliIndexCustomAttributeType.getTableName(parentIndex), + CliIndexCustomAttributeType.getRowIndex(parentIndex)); } catch (InvalidInputException e) { typeRep = Integer.toHexString(typeIndex); @@ -59,23 +76,55 @@ public class CliTableCustomAttribute extends CliAbstractTable { return String.format("Parent %s Type %s Value %x", parentRep, typeRep, valueIndex); } } - public CliTableCustomAttribute(BinaryReader reader, CliStreamMetadata stream, CliTypeTable tableId) throws IOException { + + public CliTableCustomAttribute(BinaryReader reader, CliStreamMetadata stream, + CliTypeTable tableId) throws IOException { super(reader, stream, tableId); for (int i = 0; i < this.numRows; i++) { - CliCustomAttributeRow row = new CliCustomAttributeRow(CliIndexHasCustomAttribute.readCodedIndex(reader, stream), + CliCustomAttributeRow row = new CliCustomAttributeRow( + CliIndexHasCustomAttribute.readCodedIndex(reader, stream), CliIndexCustomAttributeType.readCodedIndex(reader, stream), readBlobIndex(reader)); rows.add(row); blobs.add(row.valueIndex); } reader.setPointerIndex(this.readerOffset); } - + @Override public StructureDataType getRowDataType() { - StructureDataType rowDt = new StructureDataType(new CategoryPath(PATH), "CustomAttribute Row", 0); + StructureDataType rowDt = + new StructureDataType(new CategoryPath(PATH), "CustomAttribute Row", 0); rowDt.add(CliIndexHasCustomAttribute.toDataType(metadataStream), "Parent", null); rowDt.add(CliIndexCustomAttributeType.toDataType(metadataStream), "Type", null); rowDt.add(metadataStream.getBlobIndexDataType(), "Value", null); return rowDt; } + + @Override + public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log, + NTHeader ntHeader) + throws DuplicateNameException, CodeUnitInsertionException, IOException { + for (CliAbstractTableRow row : rows) { + CliCustomAttributeRow customRow = (CliCustomAttributeRow) row; + Address addr = CliAbstractStream.getStreamMarkupAddress(program, isBinary, monitor, log, + ntHeader, metadataStream.getBlobStream(), customRow.valueIndex); + + // Create CustomAttrib Blob object and bookmark it + CliBlobCustomAttrib blob = new CliBlobCustomAttrib( + metadataStream.getBlobStream().getBlob(customRow.valueIndex), + (CliCustomAttributeRow) row, metadataStream); + metadataStream.getBlobStream().updateBlob(blob, addr, program); + + if (tableType != null) { + program.getBookmarkManager() + .setBookmark(addr, BookmarkType.INFO, "CLI Blob", + "CustomAttrib (" + tableType.name() + ")"); + } + else { + program.getBookmarkManager() + .setBookmark(addr, BookmarkType.INFO, "CLI Blob", + "CustomAttrib (undefined)"); + } + } + } } From efdc2da7f1816ad887bc725bf9d1d0b1b6cb89d0 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Wed, 25 Nov 2020 11:16:07 -0500 Subject: [PATCH 009/140] Static, not just final, the constants --- .../format/pe/cli/blobs/CliBlobCustomAttrib.java | 16 ++++++++-------- .../pe/cli/tables/CliTableCustomAttribute.java | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index 66230ab4cb..b43fe89b9f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -41,20 +41,20 @@ public class CliBlobCustomAttrib extends CliBlob { private short numNamed; // Fixed constants for validating the structure - private final short CLIBLOBCUSTOMATTRIB_PROLOG = 0x0001; - private final byte CLIBLOBCUSTOMATTRIB_TYPE_FIELD = 0x53; - private final byte CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY = 0x54; + private static final short CLIBLOBCUSTOMATTRIB_PROLOG = 0x0001; + private static final byte CLIBLOBCUSTOMATTRIB_TYPE_FIELD = 0x53; + private static final byte CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY = 0x54; // SerString processing constants to validate and convert the // length of the string - private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64 = 0x40; - private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128 = 0x80; - private final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192 = 0xC0; + private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64 = 0x40; + private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128 = 0x80; + private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192 = 0xC0; // UTF-8 boundaries that help detect the end of a string where // lengths aren't specified in FixedArg - private final int CLIBLOBCUSTOMATTRIB_UTF8_LOW = 0x1F; - private final int CLIBLOBCUSTOMATTRIB_UTF8_HIGH = 0x7F; + private static final int CLIBLOBCUSTOMATTRIB_UTF8_LOW = 0x1F; + private static final int CLIBLOBCUSTOMATTRIB_UTF8_HIGH = 0x7F; private class CliFixedArg { private CliElementType elem; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index 37387bdcce..34a5205564 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -44,8 +44,8 @@ public class CliTableCustomAttribute extends CliAbstractTable { public int typeIndex; public int valueIndex; - private final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODDEF = 0x02; - private final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODREF = 0x03; + private static final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODDEF = 0x02; + private static final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODREF = 0x03; public CliCustomAttributeRow(int parentIndex, int typeIndex, int valueIndex) { super(); From 366b94329f96ef9c4a94aff5258c7157b47bd44b Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Mon, 30 Nov 2020 12:05:59 -0500 Subject: [PATCH 010/140] Remove the bookmarks for consistency with GP-327 branch --- .../pe/cli/tables/CliTableCustomAttribute.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index 34a5205564..08afc94565 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -28,7 +28,6 @@ import ghidra.app.util.importer.MessageLog; import ghidra.program.model.address.Address; import ghidra.program.model.data.CategoryPath; import ghidra.program.model.data.StructureDataType; -import ghidra.program.model.listing.BookmarkType; import ghidra.program.model.listing.Program; import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.util.exception.DuplicateNameException; @@ -114,17 +113,6 @@ public class CliTableCustomAttribute extends CliAbstractTable { metadataStream.getBlobStream().getBlob(customRow.valueIndex), (CliCustomAttributeRow) row, metadataStream); metadataStream.getBlobStream().updateBlob(blob, addr, program); - - if (tableType != null) { - program.getBookmarkManager() - .setBookmark(addr, BookmarkType.INFO, "CLI Blob", - "CustomAttrib (" + tableType.name() + ")"); - } - else { - program.getBookmarkManager() - .setBookmark(addr, BookmarkType.INFO, "CLI Blob", - "CustomAttrib (undefined)"); - } } } } From b58e296b7c0b58ad61e64d023eec768b8852ad71 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Mon, 30 Nov 2020 12:07:53 -0500 Subject: [PATCH 011/140] Comment fix --- .../util/bin/format/pe/cli/tables/CliTableCustomAttribute.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index 08afc94565..0904a1ac5a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -108,7 +108,7 @@ public class CliTableCustomAttribute extends CliAbstractTable { Address addr = CliAbstractStream.getStreamMarkupAddress(program, isBinary, monitor, log, ntHeader, metadataStream.getBlobStream(), customRow.valueIndex); - // Create CustomAttrib Blob object and bookmark it + // Create CustomAttrib Blob object CliBlobCustomAttrib blob = new CliBlobCustomAttrib( metadataStream.getBlobStream().getBlob(customRow.valueIndex), (CliCustomAttributeRow) row, metadataStream); From 45c64c565fd8f4b0f3617d0f36137332cc9a5e32 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Thu, 3 Dec 2020 08:52:35 -0500 Subject: [PATCH 012/140] Fixes based on review --- .../pe/cli/blobs/CliBlobCustomAttrib.java | 94 +++++++++---------- .../cli/tables/CliTableCustomAttribute.java | 16 ++-- 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index b43fe89b9f..3d11780f2c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -25,6 +25,7 @@ import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliElementType; import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliParam; import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; +import ghidra.app.util.bin.format.pe.cli.tables.CliAbstractTableRow; import ghidra.app.util.bin.format.pe.cli.tables.CliTableCustomAttribute.CliCustomAttributeRow; import ghidra.app.util.bin.format.pe.cli.tables.CliTableMemberRef.CliMemberRefRow; import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodDef.CliMethodDefRow; @@ -132,19 +133,18 @@ public class CliBlobCustomAttrib extends CliBlob { // Get the table type and row for the attribute and depending on the type // get the parameters CliTypeTable tableType = CliIndexCustomAttributeType.getTableName(typeIndex); - int tableRow = CliIndexCustomAttributeType.getRowIndex(typeIndex); + int tableRowIndex = CliIndexCustomAttributeType.getRowIndex(typeIndex); + CliAbstractTableRow tableRow = metadataStream.getTable(tableType).getRow(tableRowIndex); if (tableType == CliTypeTable.MemberRef) { - CliMemberRefRow memberRefRow = - (CliMemberRefRow) metadataStream.getTable(tableType).getRow(tableRow); + CliMemberRefRow memberRefRow = (CliMemberRefRow) tableRow; CliBlob memberRefBlob = metadataStream.getBlobStream().getBlob(memberRefRow.signatureIndex); CliSigMethodRef methodRefSig = new CliSigMethodRef(memberRefBlob); params = methodRefSig.getParams(); } else if (tableType == CliTypeTable.MethodDef) { - CliMethodDefRow methodDefRow = - (CliMethodDefRow) metadataStream.getTable(tableType).getRow(tableRow); + CliMethodDefRow methodDefRow = (CliMethodDefRow) tableRow; CliBlob methodDefBlob = metadataStream.getBlobStream().getBlob(methodDefRow.sigIndex); CliSigMethodDef methodDefSig = new CliSigMethodDef(methodDefBlob); @@ -180,91 +180,83 @@ public class CliBlobCustomAttrib extends CliBlob { } else { // Process Elem types - switch (param.getType().baseTypeCode) { + CliElementType baseTypeCode = param.getType().baseTypeCode; + switch (baseTypeCode) { case ELEMENT_TYPE_BOOLEAN: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextByte())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); break; case ELEMENT_TYPE_CHAR: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextShort())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); break; case ELEMENT_TYPE_I1: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextByte())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); break; case ELEMENT_TYPE_U1: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextUnsignedByte())); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextUnsignedByte()); break; case ELEMENT_TYPE_I2: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextShort())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); break; case ELEMENT_TYPE_U2: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextUnsignedShort())); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextUnsignedShort()); break; case ELEMENT_TYPE_I4: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextInt())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); break; case ELEMENT_TYPE_U4: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextUnsignedInt())); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextUnsignedInt()); break; case ELEMENT_TYPE_I8: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, reader.readNextLong())); break; case ELEMENT_TYPE_U8: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextByteArray(LongLongDataType.dataType.getLength()))); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(LongLongDataType.dataType.getLength())); break; case ELEMENT_TYPE_R4: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextByteArray(Float4DataType.dataType.getLength()))); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(Float4DataType.dataType.getLength())); break; case ELEMENT_TYPE_R8: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextByteArray(Float8DataType.dataType.getLength()))); + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(Float8DataType.dataType.getLength())); break; case ELEMENT_TYPE_STRING: int length = readSerStringLength(reader); - processFixedArgs - .add(new CliFixedArg(param.getType().baseTypeCode, new String( - reader.readNextByteArray(length), StandardCharsets.UTF_8))); + addFixedArg(processFixedArgs, baseTypeCode, new String( + reader.readNextByteArray(length), StandardCharsets.UTF_8)); break; case ELEMENT_TYPE_VALUETYPE: - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextInt())); + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); break; default: Msg.info(this, - "Found a CustomAttrib with an unprocessed element type: " + + "A CustomAttrib with an unprocessed element type was deteceted: " + param.getRepresentation()); } } } - fixedArgs = new CliFixedArg[processFixedArgs.size()]; - for (int i = 0; i < fixedArgs.length; i++) { - fixedArgs[i] = processFixedArgs.get(i); - } + fixedArgs = processFixedArgs.toArray(CliFixedArg[]::new); } // NumNamed @@ -291,12 +283,7 @@ public class CliBlobCustomAttrib extends CliBlob { processNamedArgs.add(new CliNamedArg(fieldOrProp, fieldOrPropType, fieldOrPropName)); } - if (processNamedArgs.size() > 0) { - namedArgs = new CliNamedArg[processNamedArgs.size()]; - for (int i = 0; i < namedArgs.length; i++) { - namedArgs[i] = processNamedArgs.get(i); - } - } + namedArgs = processNamedArgs.toArray(CliNamedArg[]::new); } @Override @@ -307,7 +294,8 @@ public class CliBlobCustomAttrib extends CliBlob { // Display the FixedArgs if (fixedArgs != null) { for (int i = 0; i < fixedArgs.length; i++) { - switch (fixedArgs[i].elem) { + CliElementType elem = fixedArgs[i].elem; + switch (elem) { case ELEMENT_TYPE_CHAR: struct.add(UTF16, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); break; @@ -370,20 +358,21 @@ public class CliBlobCustomAttrib extends CliBlob { // Display the NamedArgs if (namedArgs != null) { - for (int i = 0; i < numNamed; i++) { - if (namedArgs[i].getFieldOrProp() == CLIBLOBCUSTOMATTRIB_TYPE_FIELD) { + for (CliNamedArg cliNamedArg : namedArgs) { + int fieldOrProp = cliNamedArg.getFieldOrProp(); + if (fieldOrProp == CLIBLOBCUSTOMATTRIB_TYPE_FIELD) { struct.add(BYTE, "FieldOrProp", "FIELD"); } - else if (namedArgs[i].getFieldOrProp() == CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { + else if (fieldOrProp == CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { struct.add(BYTE, "FieldOrProp", "PROPERTY"); } else { struct.add(BYTE, "FieldOrProp", "Unknown value"); } - struct.add(BYTE, "FieldOrPropType", namedArgs[i].getFieldOrPropType().name()); + struct.add(BYTE, "FieldOrPropType", cliNamedArg.getFieldOrPropType().name()); - int nameLen = namedArgs[i].getFieldOrPropName().length(); + int nameLen = cliNamedArg.getFieldOrPropName().length(); if (nameLen < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { struct.add(BYTE, "PackedLen", ""); } @@ -475,4 +464,9 @@ public class CliBlobCustomAttrib extends CliBlob { return buf.getInt(); } } + + private void addFixedArg(ArrayList fixedArgs, CliElementType baseTypeCode, + Object value) { + fixedArgs.add(new CliFixedArg(baseTypeCode, value)); + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index 0904a1ac5a..cdd7ffba0b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -20,8 +20,7 @@ import java.io.IOException; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.format.pe.NTHeader; import ghidra.app.util.bin.format.pe.cli.blobs.CliBlobCustomAttrib; -import ghidra.app.util.bin.format.pe.cli.streams.CliAbstractStream; -import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; +import ghidra.app.util.bin.format.pe.cli.streams.*; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexCustomAttributeType; import ghidra.app.util.bin.format.pe.cli.tables.indexes.CliIndexHasCustomAttribute; import ghidra.app.util.importer.MessageLog; @@ -103,16 +102,19 @@ public class CliTableCustomAttribute extends CliAbstractTable { public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log, NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException, IOException { + CliStreamBlob blobStream = metadataStream.getBlobStream(); + for (CliAbstractTableRow row : rows) { CliCustomAttributeRow customRow = (CliCustomAttributeRow) row; + int valueIndex = customRow.valueIndex; + Address addr = CliAbstractStream.getStreamMarkupAddress(program, isBinary, monitor, log, - ntHeader, metadataStream.getBlobStream(), customRow.valueIndex); + ntHeader, blobStream, valueIndex); // Create CustomAttrib Blob object - CliBlobCustomAttrib blob = new CliBlobCustomAttrib( - metadataStream.getBlobStream().getBlob(customRow.valueIndex), - (CliCustomAttributeRow) row, metadataStream); - metadataStream.getBlobStream().updateBlob(blob, addr, program); + CliBlobCustomAttrib blob = + new CliBlobCustomAttrib(blobStream.getBlob(valueIndex), customRow, metadataStream); + blobStream.updateBlob(blob, addr, program); } } } From 8b73ffdea68ad8532fd49ec3ae68408eaf361971 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Thu, 3 Dec 2020 12:27:23 -0500 Subject: [PATCH 013/140] Finished review comments --- .../pe/cli/blobs/CliBlobCustomAttrib.java | 260 +++++++++--------- 1 file changed, 135 insertions(+), 125 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index 3d11780f2c..7f8d5d7a04 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -157,133 +157,10 @@ public class CliBlobCustomAttrib extends CliBlob { } // Process zero to multiple FixedArgs - if (params != null) { - ArrayList processFixedArgs = new ArrayList<>(); - for (CliParam param : params) { - byte elemByte = reader.peekNextByte(); - if (elemByte == CliElementType.ELEMENT_TYPE_I.id()) { - reader.readNextByte(); - - // IntPtr followed by a string of the name of the element, the - // length of which is not specified and must be read until a - // non-printable UTF-8 character is encountered to signal the - // end of the name - - StringBuilder sb = new StringBuilder(); - while ((reader.peekNextByte() > CLIBLOBCUSTOMATTRIB_UTF8_LOW) && - (reader.peekNextByte() < CLIBLOBCUSTOMATTRIB_UTF8_HIGH)) { - sb.append((char) reader.readNextByte()); - } - - processFixedArgs - .add(new CliFixedArg(CliElementType.ELEMENT_TYPE_I, sb.toString())); - } - else { - // Process Elem types - CliElementType baseTypeCode = param.getType().baseTypeCode; - switch (baseTypeCode) { - case ELEMENT_TYPE_BOOLEAN: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); - break; - - case ELEMENT_TYPE_CHAR: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); - break; - - case ELEMENT_TYPE_I1: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); - break; - - case ELEMENT_TYPE_U1: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextUnsignedByte()); - break; - - case ELEMENT_TYPE_I2: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); - break; - - case ELEMENT_TYPE_U2: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextUnsignedShort()); - break; - - case ELEMENT_TYPE_I4: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); - break; - - case ELEMENT_TYPE_U4: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextUnsignedInt()); - break; - - case ELEMENT_TYPE_I8: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); - processFixedArgs.add(new CliFixedArg(param.getType().baseTypeCode, - reader.readNextLong())); - break; - - case ELEMENT_TYPE_U8: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextByteArray(LongLongDataType.dataType.getLength())); - break; - - case ELEMENT_TYPE_R4: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextByteArray(Float4DataType.dataType.getLength())); - break; - - case ELEMENT_TYPE_R8: - addFixedArg(processFixedArgs, baseTypeCode, - reader.readNextByteArray(Float8DataType.dataType.getLength())); - break; - - case ELEMENT_TYPE_STRING: - int length = readSerStringLength(reader); - addFixedArg(processFixedArgs, baseTypeCode, new String( - reader.readNextByteArray(length), StandardCharsets.UTF_8)); - break; - - case ELEMENT_TYPE_VALUETYPE: - addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); - break; - - default: - Msg.info(this, - "A CustomAttrib with an unprocessed element type was deteceted: " + - param.getRepresentation()); - } - } - } - - fixedArgs = processFixedArgs.toArray(CliFixedArg[]::new); - } - - // NumNamed - numNamed = reader.readNextShort(); + fixedArgs = processFixedArgs(reader, params).toArray(CliFixedArg[]::new); // Process zero to multiple NamedArgs here - ArrayList processNamedArgs = new ArrayList<>(); - for (int i = 0; i < numNamed; i++) { - byte fieldOrProp = reader.readNextByte(); - if ((fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_FIELD) && - fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { - Msg.warn(this, "Invalid FieldOrProp value in NamedArg #" + (i + 1) + ": 0x" + - Integer.toHexString(fieldOrProp)); - continue; - } - - CliElementType fieldOrPropType = CliElementType.fromInt(reader.readNextByte()); - - // Account for the null terminator - int nameLen = readSerStringLength(reader) + 1; - String fieldOrPropName = - new String(reader.readNextByteArray(nameLen), StandardCharsets.UTF_8); - - processNamedArgs.add(new CliNamedArg(fieldOrProp, fieldOrPropType, fieldOrPropName)); - } - - namedArgs = processNamedArgs.toArray(CliNamedArg[]::new); + namedArgs = processNamedArgs(reader).toArray(CliNamedArg[]::new); } @Override @@ -295,6 +172,7 @@ public class CliBlobCustomAttrib extends CliBlob { if (fixedArgs != null) { for (int i = 0; i < fixedArgs.length; i++) { CliElementType elem = fixedArgs[i].elem; + switch (elem) { case ELEMENT_TYPE_CHAR: struct.add(UTF16, "FixedArg_" + i, "Elem (" + fixedArgs[i].getElem() + ")"); @@ -465,8 +343,140 @@ public class CliBlobCustomAttrib extends CliBlob { } } + private ArrayList processFixedArgs(BinaryReader reader, CliParam[] params) + throws IOException { + ArrayList processFixedArgs = new ArrayList<>(); + if (params == null) { + return processFixedArgs; + } + + for (CliParam param : params) { + byte elemByte = reader.peekNextByte(); + if (elemByte == CliElementType.ELEMENT_TYPE_I.id()) { + reader.readNextByte(); + + // IntPtr followed by a string of the name of the element, the + // length of which is not specified and must be read until a + // non-printable UTF-8 character is encountered to signal the + // end of the name + + StringBuilder sb = new StringBuilder(); + while ((reader.peekNextByte() > CLIBLOBCUSTOMATTRIB_UTF8_LOW) && + (reader.peekNextByte() < CLIBLOBCUSTOMATTRIB_UTF8_HIGH)) { + sb.append((char) reader.readNextByte()); + } + + processFixedArgs.add(new CliFixedArg(CliElementType.ELEMENT_TYPE_I, sb.toString())); + } + else { + // Process Elem types + CliElementType baseTypeCode = param.getType().baseTypeCode; + switch (baseTypeCode) { + case ELEMENT_TYPE_BOOLEAN: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); + break; + + case ELEMENT_TYPE_CHAR: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); + break; + + case ELEMENT_TYPE_I1: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); + break; + + case ELEMENT_TYPE_U1: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextUnsignedByte()); + break; + + case ELEMENT_TYPE_I2: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextShort()); + break; + + case ELEMENT_TYPE_U2: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextUnsignedShort()); + break; + + case ELEMENT_TYPE_I4: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); + break; + + case ELEMENT_TYPE_U4: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextUnsignedInt()); + break; + + case ELEMENT_TYPE_I8: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextByte()); + processFixedArgs.add( + new CliFixedArg(param.getType().baseTypeCode, reader.readNextLong())); + break; + + case ELEMENT_TYPE_U8: + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(LongLongDataType.dataType.getLength())); + break; + + case ELEMENT_TYPE_R4: + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(Float4DataType.dataType.getLength())); + break; + + case ELEMENT_TYPE_R8: + addFixedArg(processFixedArgs, baseTypeCode, + reader.readNextByteArray(Float8DataType.dataType.getLength())); + break; + + case ELEMENT_TYPE_STRING: + int length = readSerStringLength(reader); + if (length > 0) { + addFixedArg(processFixedArgs, baseTypeCode, new String( + reader.readNextByteArray(length), StandardCharsets.UTF_8)); + } + break; + + case ELEMENT_TYPE_VALUETYPE: + addFixedArg(processFixedArgs, baseTypeCode, reader.readNextInt()); + break; + + default: + Msg.info(this, + "A CustomAttrib with an unprocessed element type was deteceted: " + + param.getRepresentation()); + } + } + } + + return processFixedArgs; + } + private void addFixedArg(ArrayList fixedArgs, CliElementType baseTypeCode, Object value) { fixedArgs.add(new CliFixedArg(baseTypeCode, value)); } + + private ArrayList processNamedArgs(BinaryReader reader) throws IOException { + numNamed = reader.readNextShort(); + + // Process zero to multiple NamedArgs here + ArrayList processNamedArgs = new ArrayList<>(); + for (int i = 0; i < numNamed; i++) { + byte fieldOrProp = reader.readNextByte(); + if ((fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_FIELD) && + fieldOrProp != CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY) { + Msg.warn(this, "Invalid FieldOrProp value in NamedArg #" + (i + 1) + ": 0x" + + Integer.toHexString(fieldOrProp)); + continue; + } + + CliElementType fieldOrPropType = CliElementType.fromInt(reader.readNextByte()); + + // +1 to account for the null terminator + int nameLen = readSerStringLength(reader) + 1; + String fieldOrPropName = + new String(reader.readNextByteArray(nameLen), StandardCharsets.UTF_8); + + processNamedArgs.add(new CliNamedArg(fieldOrProp, fieldOrPropType, fieldOrPropName)); + } + + return processNamedArgs; + } } From fd940aa265a24e9c89e6b95cc5f7ed37f858c93e Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Thu, 3 Dec 2020 12:31:20 -0500 Subject: [PATCH 014/140] Remove unused constants --- .../util/bin/format/pe/cli/tables/CliTableCustomAttribute.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index cdd7ffba0b..be591fbfe5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -42,9 +42,6 @@ public class CliTableCustomAttribute extends CliAbstractTable { public int typeIndex; public int valueIndex; - private static final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODDEF = 0x02; - private static final byte CLITABLECUSTOMATTRIBUTE_TYPE_METHODREF = 0x03; - public CliCustomAttributeRow(int parentIndex, int typeIndex, int valueIndex) { super(); this.parentIndex = parentIndex; From 490d2fb507ffa607fea29f1a1eb4210bdd1cd23d Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Tue, 26 Jan 2021 18:46:02 +0000 Subject: [PATCH 015/140] GP-414 fixing signing issues --- .../pe/cli/blobs/CliBlobCustomAttrib.java | 69 +++++++++++-------- .../format/pe/cli/streams/CliStreamBlob.java | 33 ++++----- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index 7f8d5d7a04..5d621c5f83 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -52,6 +52,15 @@ public class CliBlobCustomAttrib extends CliBlob { private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128 = 0x80; private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192 = 0xC0; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_ONE = 0x01; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO = 0x02; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO_BITMASK = 0x7F; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR = 0x03; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR_BITMASK = 0x3F; + + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_SHIFT = 0x06; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK = 0x03; + // UTF-8 boundaries that help detect the end of a string where // lengths aren't specified in FixedArg private static final int CLIBLOBCUSTOMATTRIB_UTF8_LOW = 0x1F; @@ -289,7 +298,8 @@ public class CliBlobCustomAttrib extends CliBlob { // based on the length of the string. This measures and decodes the Byte, Word, // or DWord length field and returns it. private int readSerStringLength(BinaryReader reader) throws IOException { - byte[] length; + byte[] lengthBytes; + int length = 0; ByteBuffer buf; // The first byte is either the size or an indicator that we have more @@ -297,50 +307,47 @@ public class CliBlobCustomAttrib extends CliBlob { // big-endian. byte firstByte = reader.readNextByte(); - if (firstByte < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { + // Shift the highest two bits to the bottom and mask off to detect the + // size of the field holding the size of the string (1, 2, or 4 bytes) + byte stringSizeIndicator = (byte) (firstByte >> CLIBLOBCUSTOMATTRIB_STRING_SIZE_SHIFT & + CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK); + + if (stringSizeIndicator <= CLIBLOBCUSTOMATTRIB_STRING_SIZE_ONE) { // A size less than 128 indicates this is the only size byte - return firstByte; + length = firstByte; } - else if (firstByte < CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192) { + else if (stringSizeIndicator == CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO) { // A value in the first byte in range [128 - 191] indicates the size // is stored as a Word and the value in the highest bit must be unset - length = new byte[] { firstByte, reader.readNextByte() }; + lengthBytes = new byte[] { firstByte, reader.readNextByte() }; - // Unset the highest bit if it's set - if ((length[1] & - CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { - length[1] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128; - } + // Unset what will become the highest bit if it's set + lengthBytes[1] = (byte) (lengthBytes[1] & CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO_BITMASK); // Convert from big-endian - buf = ByteBuffer.wrap(length); + buf = ByteBuffer.wrap(lengthBytes); buf.order(ByteOrder.BIG_ENDIAN); - return buf.getShort(); + length = buf.getShort(); } - else { + else if (stringSizeIndicator == CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR) { // A value in the first byte > 128 indicates the size is stored as // a DWord and the first two bits must be unset - length = new byte[4]; - length[0] = firstByte; - length[1] = reader.readNextByte(); - length[2] = reader.readNextByte(); - length[3] = reader.readNextByte(); + lengthBytes = new byte[Integer.BYTES]; + lengthBytes[0] = firstByte; + lengthBytes[1] = reader.readNextByte(); + lengthBytes[2] = reader.readNextByte(); + lengthBytes[3] = reader.readNextByte(); // Unset what will become the highest two bits if they're set - if ((length[3] & - CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128) { - length[3] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128; - } - if ((length[3] & - CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64) == CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64) { - length[3] ^= CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64; - } + lengthBytes[3] = (byte) (lengthBytes[3] & CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR_BITMASK); // Convert from big-endian - buf = ByteBuffer.wrap(length); + buf = ByteBuffer.wrap(lengthBytes); buf.order(ByteOrder.BIG_ENDIAN); - return buf.getInt(); + length = buf.getInt(); } + + return length; } private ArrayList processFixedArgs(BinaryReader reader, CliParam[] params) @@ -361,8 +368,10 @@ public class CliBlobCustomAttrib extends CliBlob { // end of the name StringBuilder sb = new StringBuilder(); - while ((reader.peekNextByte() > CLIBLOBCUSTOMATTRIB_UTF8_LOW) && - (reader.peekNextByte() < CLIBLOBCUSTOMATTRIB_UTF8_HIGH)) { + while (((reader.peekNextByte() & + CLIBLOBCUSTOMATTRIB_UTF8_HIGH) > CLIBLOBCUSTOMATTRIB_UTF8_LOW) && + ((reader.peekNextByte() & + CLIBLOBCUSTOMATTRIB_UTF8_HIGH) < CLIBLOBCUSTOMATTRIB_UTF8_HIGH)) { sb.append((char) reader.readNextByte()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java index a5f065511a..d658fa8d1e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java @@ -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,12 +16,11 @@ package ghidra.app.util.bin.format.pe.cli.streams; import java.io.IOException; -import java.util.*; +import java.util.LinkedHashMap; +import java.util.Map; import ghidra.app.util.bin.BinaryReader; -import ghidra.app.util.bin.format.pe.PeUtils; import ghidra.app.util.bin.format.pe.cli.CliStreamHeader; -import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliCustomAttrib; import ghidra.app.util.bin.format.pe.cli.blobs.CliBlob; import ghidra.program.model.address.Address; import ghidra.program.model.data.*; @@ -41,7 +40,7 @@ public class CliStreamBlob extends CliAbstractStream { /** * Gets the name of this stream. - * + * * @return The name of this stream. */ public static String getName() { @@ -50,9 +49,9 @@ public class CliStreamBlob extends CliAbstractStream { /** * Creates a new Blob stream. - * + * * @param header The stream header associated with this stream. - * @param offset The reader offset where this stream starts. + * @param offset The reader offset where this stream starts. * @param rva The relative virtual address where this stream starts. * @param reader A reader that is used to read the stream. * @throws IOException if there is a problem reading the stream. @@ -85,7 +84,7 @@ public class CliStreamBlob extends CliAbstractStream { /** * Gets the blob at the given index. - * + * * @param index The index of the blob to get. * @return The blob at the given index. Could be null if the index was invalid or * there was a problem reading the blob. @@ -96,7 +95,7 @@ public class CliStreamBlob extends CliAbstractStream { /** * Updates the blob at the given address with the new blob. - * + * * @param updatedBlob The updated blob. * @param addr The address of the blob to update. * @param program The program that will get the update. @@ -114,25 +113,28 @@ public class CliStreamBlob extends CliAbstractStream { // Make sure there is an old blob at the given address int structureOffset = (int) addr.subtract(containingData.getAddress()); - DataTypeComponent oldBlobDataComponent = containingStructure.getComponentAt(structureOffset); + DataTypeComponent oldBlobDataComponent = + containingStructure.getComponentAt(structureOffset); if (oldBlobDataComponent == null) { Msg.error(this, "Existing blob at address " + addr + " was not found."); return false; } - + // Make sure the old blob has the same size as the new blob DataType oldBlobDataType = oldBlobDataComponent.getDataType(); DataType newBlobDataType = updatedBlob.toDataType(); if (oldBlobDataType.getLength() != newBlobDataType.getLength()) { - Msg.error(this, "Cannot replace existing " + updatedBlob.getName() + " at address " + addr + " with " + - updatedBlob.getName() + " because they have different sizes (old: " + oldBlobDataType.getLength() + ", new: " + newBlobDataType.getLength() + ")."); + Msg.error(this, + "Cannot replace existing " + updatedBlob.getName() + " at address " + addr + + " with " + updatedBlob.getName() + " because they have different sizes (old: " + + oldBlobDataType.getLength() + ", new: " + newBlobDataType.getLength() + ")."); return false; } // Update the blob containingStructure.replaceAtOffset(structureOffset, newBlobDataType, updatedBlob.getSize(), updatedBlob.getName(), updatedBlob.getContentsComment()); - + return true; } @@ -149,4 +151,3 @@ public class CliStreamBlob extends CliAbstractStream { return struct; } } - From ec19b5cdc3b31a5dad94347a35ea9d0e303fd246 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Tue, 26 Jan 2021 18:56:28 +0000 Subject: [PATCH 016/140] GP-414 Fixing signing issues --- .../app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java | 4 ++-- .../app/util/bin/format/pe/cli/streams/CliStreamBlob.java | 4 ++-- .../bin/format/pe/cli/tables/CliTableCustomAttribute.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index 5d621c5f83..ded0ec4a33 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -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. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java index d658fa8d1e..b14ffd1ec8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java @@ -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. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java index be591fbfe5..6323c15a43 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableCustomAttribute.java @@ -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. From 317a8a7f68c4adfe5f0a45e09f869d785be90471 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Wed, 10 Feb 2021 16:41:23 +0000 Subject: [PATCH 017/140] Changes to simplify length calculation --- .../pe/cli/blobs/CliBlobCustomAttrib.java | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index ded0ec4a33..0814299b0f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -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. @@ -46,20 +46,16 @@ public class CliBlobCustomAttrib extends CliBlob { private static final byte CLIBLOBCUSTOMATTRIB_TYPE_FIELD = 0x53; private static final byte CLIBLOBCUSTOMATTRIB_TYPE_PROPERTY = 0x54; - // SerString processing constants to validate and convert the - // length of the string - private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_64 = 0x40; private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_128 = 0x80; private static final int CLIBLOBCUSTOMATTRIB_STRING_BOUNDARY_192 = 0xC0; private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_ONE = 0x01; private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO = 0x02; - private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO_BITMASK = 0x7F; private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR = 0x03; - private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR_BITMASK = 0x3F; + private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK = 0x3F; - private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_SHIFT = 0x06; - private static final int CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK = 0x03; + private static final int CLIBLOBCUSTOMATTRIB_STRING_INDICATOR_SHIFT = 0x06; + private static final int CLIBLOBCUSTOMATTRIB_STRING_INDICATOR_BITMASK = 0x03; // UTF-8 boundaries that help detect the end of a string where // lengths aren't specified in FixedArg @@ -308,38 +304,26 @@ public class CliBlobCustomAttrib extends CliBlob { byte firstByte = reader.readNextByte(); // Shift the highest two bits to the bottom and mask off to detect the - // size of the field holding the size of the string (1, 2, or 4 bytes) - byte stringSizeIndicator = (byte) (firstByte >> CLIBLOBCUSTOMATTRIB_STRING_SIZE_SHIFT & - CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK); + // size of the field holding the size of the string (1, 2, or 4 bytes), + // then cut the indicator bits off the first byte of the length. + byte stringSizeIndicator = (byte) (firstByte >> CLIBLOBCUSTOMATTRIB_STRING_INDICATOR_SHIFT & + CLIBLOBCUSTOMATTRIB_STRING_INDICATOR_BITMASK); + firstByte = (byte) (firstByte & CLIBLOBCUSTOMATTRIB_STRING_SIZE_BITMASK); if (stringSizeIndicator <= CLIBLOBCUSTOMATTRIB_STRING_SIZE_ONE) { - // A size less than 128 indicates this is the only size byte length = firstByte; } else if (stringSizeIndicator == CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO) { - // A value in the first byte in range [128 - 191] indicates the size - // is stored as a Word and the value in the highest bit must be unset lengthBytes = new byte[] { firstByte, reader.readNextByte() }; - // Unset what will become the highest bit if it's set - lengthBytes[1] = (byte) (lengthBytes[1] & CLIBLOBCUSTOMATTRIB_STRING_SIZE_TWO_BITMASK); - // Convert from big-endian buf = ByteBuffer.wrap(lengthBytes); buf.order(ByteOrder.BIG_ENDIAN); length = buf.getShort(); } else if (stringSizeIndicator == CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR) { - // A value in the first byte > 128 indicates the size is stored as - // a DWord and the first two bits must be unset - lengthBytes = new byte[Integer.BYTES]; - lengthBytes[0] = firstByte; - lengthBytes[1] = reader.readNextByte(); - lengthBytes[2] = reader.readNextByte(); - lengthBytes[3] = reader.readNextByte(); - - // Unset what will become the highest two bits if they're set - lengthBytes[3] = (byte) (lengthBytes[3] & CLIBLOBCUSTOMATTRIB_STRING_SIZE_FOUR_BITMASK); + lengthBytes = new byte[] { firstByte, reader.readNextByte(), reader.readNextByte(), + reader.readNextByte() }; // Convert from big-endian buf = ByteBuffer.wrap(lengthBytes); From 6d97ccee649c39caad258e6e2a7b16ed6780d2bb Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Fri, 12 Feb 2021 13:50:37 +0900 Subject: [PATCH 018/140] Fix ARM Neon VMRS instruction for little endian --- Ghidra/Processors/ARM/data/languages/ARMneon.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMneon.sinc b/Ghidra/Processors/ARM/data/languages/ARMneon.sinc index 5c2470ae85..aff8f018f7 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMneon.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMneon.sinc @@ -3049,7 +3049,7 @@ define pcodeop VectorCopyNarrow; @if defined(VFPv2) || defined(VFPv3) || defined(SIMD) -:vmrs^COND VRd,fpscr is COND & ( ($(AMODE) & c1627=0xef1 & c0011=0xa10) | ($(TMODE_E) & c1627=0xef1 & c0011=0xa10)) & fpscr & VRd +:vmrs^COND VRd,fpscr is COND & ( ($(AMODE) & c1627=0xef1 & c0011=0xa10) | ($(TMODE_E) & thv_c1627=0xef1 & thv_c0011=0xa10)) & fpscr & VRd { VRd = fpscr; } From 1fbb8a330a17daafdb37d61b5094ab2af8877281 Mon Sep 17 00:00:00 2001 From: Xiaoyin Liu Date: Sat, 18 Jul 2020 18:53:03 +0800 Subject: [PATCH 019/140] Add more non-return functions Add more functions to PEFunctionsThatDoNotReturn. --- Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn b/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn index e8ed7404f4..51c5089410 100644 --- a/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn +++ b/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn @@ -1,7 +1,15 @@ +abort CxxThrowException CxxThrowException@8 CxxFrameHandler3 crtExitProcess ExitProcess +ExitThread exit +FreeLibraryAndExitThread +invalid_parameter_noinfo_noreturn +invoke_watson longjmp +quick_exit +RpcRaiseException +terminate From 849504cda6f78a054e89418d32ed1089d1d9106d Mon Sep 17 00:00:00 2001 From: ghidra007 Date: Fri, 12 Feb 2021 18:48:37 +0000 Subject: [PATCH 020/140] GP-688 RTTI Util improved getVftableCount method to not just rely on pseudoDissasembler but also check if existing function. --- .../src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java index 4fd197d895..864953dbf8 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java @@ -25,8 +25,7 @@ import ghidra.app.util.PseudoDisassembler; import ghidra.app.util.datatype.microsoft.MSDataTypeUtils; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.listing.GhidraClass; -import ghidra.program.model.listing.Program; +import ghidra.program.model.listing.*; import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.symbol.*; @@ -166,7 +165,10 @@ public class RttiUtil { break; } - if (!pseudoDisassembler.isValidSubroutine(referencedAddress, true, false)) { + Function function = program.getFunctionManager().getFunctionAt(referencedAddress); + + if (function == null && + !pseudoDisassembler.isValidSubroutine(referencedAddress, true, false)) { break; // Not pointing to possible function. } From 4904a0e7b549d40fa8f9c8fa9a13af960b2288c9 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Sat, 13 Feb 2021 02:08:02 +0000 Subject: [PATCH 021/140] 68000: fix disassembly of fmove with dynamic k-factor --- Ghidra/Processors/68000/data/languages/68000.sinc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 773ee2c4c6..1979794163 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -1747,7 +1747,7 @@ fcc: "sne" is fcode=0x1e { tmp:1 = $(Z_FP); clearflags_fp(); export tmp; } @define FormatByteWordLongSimple "( ffmt=0 | ffmt=1 | ffmt=4 | ffmt=6 )" -# The following constraint should be used when using fprec (ffmt=7 is not valid) +# The following constraint should be used when using fprec @define FPREC_BWLS "fprec & ( ffmt=0 | ffmt=1 | ffmt=4 | ffmt=6 )" # Byte,Word,Long,Simple only @define FPREC_DXP "fprec & ( ffmt=2 | ffmt=3 | ffmt=5)" # Double,Extended,Packed only @define FPREC_XP "fprec & ( ffmt=2 | ffmt=3)" # Extended,Packed only @@ -1764,6 +1764,7 @@ fprec: "p" is ffmt=3 {} fprec: "w" is ffmt=4 {} fprec: "d" is ffmt=5 {} fprec: "b" is ffmt=6 {} +fprec: "p" is ffmt=7 {} :fabs.^fprec e2l, fdst is op=15 & $(FP_COP) & op68=0 & $(DAT_ALTER_ADDR_MODES); frm=1 & f1515=0 & f1313=0 & fdst & $(FPREC_BWLS) & fopmode=0x18; e2l From b0769bd805b494b4d06d213180d565170ab2ed0a Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 11 Feb 2021 13:29:14 -0500 Subject: [PATCH 022/140] GP-672 - fixed 'wait forever' bug --- .../visualization/DefaultGraphDisplay.java | 23 +---- .../graph/visualization/SetLayoutTask.java | 43 +++++++--- .../docking/action/ToggleDockingAction.java | 5 +- .../builder/MultiStateActionBuilder.java | 29 ++++--- .../docking/menu/MultiStateDockingAction.java | 83 ++++++++++++++----- .../MultipleActionDockingToolbarButton.java | 13 ++- 6 files changed, 120 insertions(+), 76 deletions(-) diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 41a21ce1e2..d2d345fcc9 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -379,7 +379,7 @@ public class DefaultGraphDisplay implements GraphDisplay { new MultiStateActionBuilder("Arrangement", ACTION_OWNER) .description("Arrangement: " + layoutActionStates.get(0).getName()) .toolBarIcon(DefaultDisplayGraphIcons.LAYOUT_ALGORITHM_ICON) - .fireFirstAction(false) + .useCheckboxForIcons(true) .onActionStateChanged((s, t) -> layoutChanged(s.getName())) .addStates(layoutActionStates) .buildAndInstallLocal(componentProvider); @@ -701,11 +701,6 @@ public class DefaultGraphDisplay implements GraphDisplay { } } - /** - * get a {@code List} of {@code ActionState} buttons for the - * configured layout algorithms - * @return a {@code List} of {@code ActionState} buttons - */ private List> getLayoutActionStates() { String[] names = layoutTransitionManager.getLayoutNames(); List> actionStates = new ArrayList<>(); @@ -718,20 +713,10 @@ public class DefaultGraphDisplay implements GraphDisplay { return actionStates; } - /** - * respond to a change in the layout name - * @param layoutName the name of the layout algorithm to apply - */ private void layoutChanged(String layoutName) { - if (layoutTransitionManager != null) { - new TaskLauncher(new SetLayoutTask(viewer, layoutTransitionManager, layoutName), null, - 1000); - } + TaskLauncher.launch(new SetLayoutTask(viewer, layoutTransitionManager, layoutName)); } - /** - * show the dialog with generated filters - */ private void showFilterDialog() { if (filterDialog == null) { if (vertexFilters == null) { @@ -743,10 +728,6 @@ public class DefaultGraphDisplay implements GraphDisplay { componentProvider.getTool().showDialog(filterDialog); } - /** - * add or remove the satellite viewer - * @param context information about the event - */ private void toggleSatellite(ActionContext context) { boolean selected = ((AbstractButton) context.getSourceObject()).isSelected(); graphDisplayProvider.setDefaultSatelliteState(selected); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/SetLayoutTask.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/SetLayoutTask.java index a3745d21f7..dbf54fc9ed 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/SetLayoutTask.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/SetLayoutTask.java @@ -17,6 +17,7 @@ package ghidra.graph.visualization; import java.util.concurrent.CountDownLatch; +import org.jgrapht.Graph; import org.jungrapht.visualization.VisualizationModel; import org.jungrapht.visualization.VisualizationViewer; import org.jungrapht.visualization.layout.event.LayoutStateChange.*; @@ -24,6 +25,7 @@ import org.jungrapht.visualization.layout.model.LayoutModel; import ghidra.service.graph.AttributedEdge; import ghidra.service.graph.AttributedVertex; +import ghidra.util.Msg; import ghidra.util.Swing; import ghidra.util.exception.CancelledException; import ghidra.util.task.*; @@ -48,8 +50,8 @@ public class SetLayoutTask extends Task { @Override public void run(TaskMonitor monitor) throws CancelledException { - // add a callback for when/if the user cancels the layout, use a variable cause - // monitor uses a weak listener list and it would othewise get garbage collected. + // add a callback for when/if the user cancels the layout, use a variable because + // monitor uses a weak listener list and it would otherwise get garbage collected. CancelledListener cancelListener = this::taskCancelled; monitor.addCancelledListener(cancelListener); @@ -60,16 +62,32 @@ public class SetLayoutTask extends Task { Listener listener = this::layoutStateChanged; support.addLayoutStateChangeListener(listener); - // start the layout - needs to be done on swing thread to prevent issues and intermediate + // start the layout - needs to be done on swing thread to prevent issues and intermediate // paints - should be changed in the future to not require it to be on the swing thread. Swing.runNow(() -> layoutTransitionManager.setLayout(layoutName)); - // some of the layouts are done on the calling thread and some aren't. If they are on + waitForLayoutTransition(model); + + support.removeLayoutStateChangeListener(listener); + monitor.removeCancelledListener(cancelListener); + } + + private void waitForLayoutTransition( + VisualizationModel model) { + + Graph graph = model.getGraph(); + if (graph.vertexSet().isEmpty()) { + // note: the underlying graph API will not notify us of the layout state change if the + // graph is empty, so do not wait. + return; + } + + // some of the layouts are done on the calling thread and some aren't. If they are on // the calling thread, then by now, we already got the "done" callback and the "taskDone" // countdown latch has been triggered and won't wait. If, however, the layout has been // diverted to another thread, we want to wait until the layout is completed // There are two ways the latch will be triggered, the layout is completed or the user - // cancles the layout. + // cancels the layout. try { taskDone.await(); } @@ -77,17 +95,17 @@ public class SetLayoutTask extends Task { model.getLayoutAlgorithm().cancel(); } - // clean up the listeners - support.removeLayoutStateChangeListener(listener); - monitor.removeCancelledListener(cancelListener); } /** - * Notfication when the layout algorithm starts and stops. - * @param e the event. If the event.active is true, then the - * algorithm is starting, if false, the algorithm is done. + * Notification when the layout algorithm starts and stops + * @param e the event. If the event.active is true, then the algorithm is starting, if false, + * the algorithm is done. */ private void layoutStateChanged(Event e) { + + Msg.debug(this, "layoutStatechanged(): " + e); + if (!e.active) { // algorithm is done, release the latch taskDone.countDown(); @@ -98,6 +116,9 @@ public class SetLayoutTask extends Task { * Callback if the user cancels the layout */ private void taskCancelled() { + + Msg.debug(this, "taskCancelled()"); + // release the latch and tell the layout algorithm to cancel. taskDone.countDown(); viewer.getVisualizationModel().getLayoutAlgorithm().cancel(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ToggleDockingAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ToggleDockingAction.java index e16802706e..9b7c1e9ecf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/ToggleDockingAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ToggleDockingAction.java @@ -19,7 +19,6 @@ import javax.swing.JButton; import javax.swing.JMenuItem; import docking.*; -import docking.menu.DockingCheckboxMenuItemUI; public abstract class ToggleDockingAction extends DockingAction implements ToggleDockingActionIf { private boolean isSelected; @@ -59,9 +58,7 @@ public abstract class ToggleDockingAction extends DockingAction implements Toggl @Override protected JMenuItem doCreateMenuItem() { - DockingCheckBoxMenuItem menuItem = new DockingCheckBoxMenuItem(isSelected); - menuItem.setUI((DockingCheckboxMenuItemUI) DockingCheckboxMenuItemUI.createUI(menuItem)); - return menuItem; + return new DockingCheckBoxMenuItem(isSelected); } @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/MultiStateActionBuilder.java b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/MultiStateActionBuilder.java index 783c9fdea8..86d8f9806c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/MultiStateActionBuilder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/MultiStateActionBuilder.java @@ -34,8 +34,8 @@ public class MultiStateActionBuilder extends AbstractActionBuilder, ActionContext, MultiStateActionBuilder> { private BiConsumer, EventTrigger> actionStateChangedCallback; + private boolean useCheckboxForIcons; private boolean performActionOnButtonClick = false; - private boolean fireFirstAction = true; private List> states = new ArrayList<>(); @@ -80,6 +80,20 @@ public class MultiStateActionBuilder extends return self(); } + /** + * Overrides the default icons for actions shown in popup menu of the multi-state action. By + * default, the popup menu items will use the icons as provided by the {@link ActionState}. + * By passing true to this method, icons will not be used in the popup menu. Instead, a + * checkbox icon will be used to show the active action state. + * + * @param b true to use a checkbox + * @return this MultiActionDockingActionBuilder (for chaining) + */ + public MultiStateActionBuilder useCheckboxForIcons(boolean b) { + this.useCheckboxForIcons = b; + return self(); + } + /** * Add an action state * @@ -115,17 +129,6 @@ public class MultiStateActionBuilder extends return self(); } - /** - * controls whether the first action added will automatically fire an event or not - * - * @param fireFirstAction do fire an action on the first action. Defaults to {@code true} - * @return this MultiActionDockingActionBuilder (for chaining) - */ - public MultiStateActionBuilder fireFirstAction(boolean fireFirstAction) { - this.fireFirstAction = fireFirstAction; - return self(); - } - @Override public MultiStateDockingAction build() { validate(); @@ -145,7 +148,6 @@ public class MultiStateActionBuilder extends } } }; - action.setFireFirstEvent(fireFirstAction); for (ActionState actionState : states) { action.addActionState(actionState); @@ -153,6 +155,7 @@ public class MultiStateActionBuilder extends decorateAction(action); action.setPerformActionOnPrimaryButtonClick(performActionOnButtonClick); + action.setUseCheckboxForIcons(useCheckboxForIcons); return action; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultiStateDockingAction.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultiStateDockingAction.java index b7e4e15321..4fc055dff0 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultiStateDockingAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultiStateDockingAction.java @@ -53,9 +53,9 @@ public abstract class MultiStateDockingAction extends DockingAction { private int currentStateIndex = 0; private MultiActionDockingActionIf multiActionGenerator; private MultipleActionDockingToolbarButton multipleButton; - private boolean fireFirstEvent = true; private boolean performActionOnPrimaryButtonClick = true; + private boolean useCheckboxForIcons; // A listener that will get called when the button (not the popup) is clicked. Toolbar // actions do not use this listener. @@ -127,6 +127,18 @@ public abstract class MultiStateDockingAction extends DockingAction { } } + /** + * Overrides the default icons for actions shown in popup menu of the multi-state action. By + * default, the popup menu items will use the icons as provided by the {@link ActionState}. + * By passing true to this method, icons will not be used in the popup menu. Instead, a + * checkbox icon will be used to show the active action state. + * + * @param useCheckboxForIcons true to use a checkbox + */ + public void setUseCheckboxForIcons(boolean useCheckboxForIcons) { + this.useCheckboxForIcons = useCheckboxForIcons; + } + @Override public final void actionPerformed(ActionContext context) { if (!performActionOnPrimaryButtonClick) { @@ -137,21 +149,6 @@ public abstract class MultiStateDockingAction extends DockingAction { doActionPerformed(context); } - /** - * @return {@code true} if the first action automatically fire its event - */ - public boolean isFireFirstEvent() { - return fireFirstEvent; - } - - /** - * set the flag to fire an event on the first action - * @param fireFirstEvent whether to fire the event - */ - public void setFireFirstEvent(boolean fireFirstEvent) { - this.fireFirstEvent = fireFirstEvent; - } - /** * This is the callback to be overridden when the child wishes to respond to user button * presses that are on the button and not the drop-down. This will only be called if @@ -175,9 +172,17 @@ public abstract class MultiStateDockingAction extends DockingAction { } protected List getStateActions() { + ActionState selectedState = actionStates.get(currentStateIndex); List actions = new ArrayList<>(actionStates.size()); for (ActionState actionState : actionStates) { - actions.add(new ActionStateAction(actionState)); + + //@formatter:off + boolean isSelected = actionState == selectedState; + DockingActionIf a = useCheckboxForIcons ? + new ActionStateToggleAction(actionState, isSelected) : + new ActionStateAction(actionState, isSelected); + actions.add(a); + //@formatter:on } return actions; } @@ -199,7 +204,7 @@ public abstract class MultiStateDockingAction extends DockingAction { */ public void addActionState(ActionState actionState) { actionStates.add(actionState); - if (actionStates.size() == 1 && fireFirstEvent) { + if (actionStates.size() == 1) { setCurrentActionState(actionState); } } @@ -209,9 +214,7 @@ public abstract class MultiStateDockingAction extends DockingAction { throw new IllegalArgumentException("You must provide at least one ActionState"); } actionStates = new ArrayList<>(newStates); - if (fireFirstEvent) { - setCurrentActionState(actionStates.get(0)); - } + setCurrentActionState(actionStates.get(0)); } public T getCurrentUserData() { @@ -235,7 +238,7 @@ public abstract class MultiStateDockingAction extends DockingAction { } throw new AssertException( - "Attempted to set an action state by a user type not " + "contained herein: " + t); + "Attempted to set an action state by a user type not contained herein: " + t); } public void setCurrentActionState(ActionState actionState) { @@ -318,13 +321,47 @@ public abstract class MultiStateDockingAction extends DockingAction { //================================================================================================== // Inner Classes //================================================================================================== + + private class ActionStateToggleAction extends ToggleDockingAction { + + private final ActionState actionState; + + private ActionStateToggleAction(ActionState actionState, boolean isSelected) { + super(actionState.getName(), "multiStateAction"); + + this.actionState = actionState; + + setSelected(isSelected); + + setMenuBarData( + new MenuData(new String[] { actionState.getName() })); + HelpLocation helpLocation = actionState.getHelpLocation(); + if (helpLocation != null) { + setHelpLocation(helpLocation); + } + } + + @Override + public String getInceptionInformation() { + // we want the debug info for these internal actions to be that of the outer class + return MultiStateDockingAction.this.getInceptionInformation(); + } + + @Override + public void actionPerformed(ActionContext context) { + setCurrentActionStateWithTrigger(actionState, EventTrigger.GUI_ACTION); + } + + } + private class ActionStateAction extends DockingAction { private final ActionState actionState; - private ActionStateAction(ActionState actionState) { + private ActionStateAction(ActionState actionState, boolean isSelected) { super(actionState.getName(), "multiStateAction"); this.actionState = actionState; + setMenuBarData( new MenuData(new String[] { actionState.getName() }, actionState.getIcon())); HelpLocation helpLocation = actionState.getHelpLocation(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java index 8409488aed..ceef1a3092 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java @@ -30,7 +30,7 @@ import docking.*; import docking.action.*; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDHtmlLabel; -import ghidra.util.SystemUtilities; +import ghidra.util.Swing; import resources.ResourceManager; public class MultipleActionDockingToolbarButton extends EmptyBorderButton { @@ -80,7 +80,8 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { * method will effectively let the user click anywhere on the button or its drop-down arrow * to show the popup menu. During normal operation, the user can only show the popup by * clicking the drop-down arrow. - * + * + * @param performActionOnButtonClick true to perform the action when the button is clicked */ public void setPerformActionOnButtonClick(boolean performActionOnButtonClick) { entireButtonShowsPopupMenu = !performActionOnButtonClick; @@ -160,7 +161,11 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { return manager.getActiveComponentProvider(); } - /** Show a popup containing all the actions below the button */ + /** + * Show a popup containing all the actions below the button + * @param listener for the created popup menu + * @return the popup menu that was shown + */ JPopupMenu showPopup(PopupMenuListener listener) { JPopupMenu menu = new JPopupMenu(); List actionList = multipleAction.getActionList(getActionContext()); @@ -307,7 +312,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { // will update the focused window after we click. We need the focus to be // correct before we show, since our menu is built with actions based upon the // focused dude. - SystemUtilities.runSwingLater(() -> popupMenu = showPopup(PopupMouseListener.this)); + Swing.runLater(() -> popupMenu = showPopup(PopupMouseListener.this)); e.consume(); model.setPressed(false); From 303208aa660f51c6a3c9962f510890970b2351e5 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 18 Feb 2021 13:07:18 -0500 Subject: [PATCH 023/140] Program Graph - fixed tooltip line wrapping bug when showing code --- .../src/main/java/ghidra/service/graph/Attributed.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java index af8962e0a1..4b940d78b8 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java @@ -20,6 +20,8 @@ import java.util.Map.Entry; import org.apache.commons.text.StringEscapeUtils; +import com.google.common.base.Splitter; + public class Attributed { /** * cache of the html rendering of the vertex attributes @@ -84,7 +86,7 @@ public class Attributed { /** * Returns the number of attributes defined - * + * * @return the number of attributes defined */ public int size() { @@ -162,7 +164,9 @@ public class Attributed { for (Map.Entry entry : entries) { buf.append(entry.getKey()); buf.append(":"); - buf.append(StringEscapeUtils.escapeHtml4(entry.getValue())); + String value = StringEscapeUtils.escapeHtml4(entry.getValue()); + String split = String.join("
", Splitter.on('\n').split(value)); + buf.append(split); buf.append("
"); } htmlString = buf.toString(); From 4602ff464621f03b42bb56808860b6ea9abf49b5 Mon Sep 17 00:00:00 2001 From: Xiaoyin Liu Date: Wed, 8 Apr 2020 19:29:39 +0800 Subject: [PATCH 024/140] Add missing quotes in launch.bat When set Windows environment variables, they need to be quoted if special characters like & exists in path. Fixes #1726 --- .../RuntimeScripts/Windows/support/launch.bat | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Ghidra/RuntimeScripts/Windows/support/launch.bat b/Ghidra/RuntimeScripts/Windows/support/launch.bat index 9bee1566cf..0fc913c731 100644 --- a/Ghidra/RuntimeScripts/Windows/support/launch.bat +++ b/Ghidra/RuntimeScripts/Windows/support/launch.bat @@ -36,7 +36,7 @@ for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" set DOUBLE_CLI :: '% ~' dereferences the value in param 0 :: 'd' - drive :: 'p' - path (without filename) -set SUPPORT_DIR=%~dp0 +set "SUPPORT_DIR=%~dp0" :: :: Parse arguments @@ -63,20 +63,20 @@ goto showUsage :: :: Production Environment :: -set INSTALL_DIR=%SUPPORT_DIR%..\ -set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar -set LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar -set DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml +set "INSTALL_DIR=%SUPPORT_DIR%..\" +set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar" +set "LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar" +set "DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml" if exist "%INSTALL_DIR%Ghidra" goto continue2 :: :: Development Environment :: -set INSTALL_DIR=%INSTALL_DIR%..\..\..\ -set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main -set LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main -set DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml +set "INSTALL_DIR=%INSTALL_DIR%..\..\..\" +set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main" +set "LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main" +set "DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml" :continue2 From 61096c5fdff1b28790bd19a8e72db28fb1ace44d Mon Sep 17 00:00:00 2001 From: Xiaoyin Liu Date: Fri, 10 Apr 2020 16:44:33 +0800 Subject: [PATCH 025/140] Add one more missing quote around JAVA_CMD --- Ghidra/RuntimeScripts/Windows/support/launch.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/RuntimeScripts/Windows/support/launch.bat b/Ghidra/RuntimeScripts/Windows/support/launch.bat index 0fc913c731..5621f4e895 100644 --- a/Ghidra/RuntimeScripts/Windows/support/launch.bat +++ b/Ghidra/RuntimeScripts/Windows/support/launch.bat @@ -108,7 +108,7 @@ if "%JAVA_HOME%" == "" ( goto exit1 ) ) -set JAVA_CMD=%JAVA_HOME%\bin\java +set "JAVA_CMD=%JAVA_HOME%\bin\java" :: Get the configurable VM arguments from the launch properties for /f "delims=*" %%i in ('java -cp "%LS_CPATH%" LaunchSupport "%INSTALL_DIR%\" -vmargs') do set VMARG_LIST=%VMARG_LIST% %%i From 143f4a0ba14bc717825d1a08682fc863df3da850 Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Thu, 18 Feb 2021 19:51:12 -0500 Subject: [PATCH 026/140] GP-698 check-in of ANALYZED flag fix --- .../app/plugin/core/analysis/AutoAnalysisManager.java | 8 +++++++- .../app/plugin/core/analysis/AutoAnalysisPlugin.java | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java index 01838c2ed7..0ff7a1f3a9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java @@ -1110,7 +1110,13 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl int answer = OptionDialog.showYesNoDialog(tool.getToolFrame(), "Analyze", "" + HTMLUtilities.escapeHTML(program.getDomainFile().getName()) + " has not been analyzed. Would you like to analyze it now?"); - return answer == OptionDialog.OPTION_ONE; // Analyze + boolean analyze = answer == OptionDialog.OPTION_ONE; + if (!analyze) { + // Must set this to false at each fall-out location. Setting it true too early + // results in false positives. It is set true only at the beginning of analysis. + GhidraProgramUtilities.setAnalyzedFlag(program, false); + } + return analyze; } return false; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java index 13e4f68cfa..96cfa1e16f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java @@ -188,12 +188,17 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis analysisMgr.initializeOptions(); // get initial options if (!showOptionsDialog(program)) { + // Must set this to false at each fall-out location. Setting it true too early + // results in false positives. It is set true only at the beginning of analysis. + GhidraProgramUtilities.setAnalyzedFlag(program, false); return; } - GhidraProgramUtilities.setAnalyzedFlag(program, true); analysisMgr.initializeOptions(); // options may have changed + // At this point, any analysis that is done is consider to be true for analyzed. + GhidraProgramUtilities.setAnalyzedFlag(program, true); + // start analysis to set the flag, but it probably won't do more. A bit goofy but better // than the way it was //TODO simplify all this after creating a taskManager per program instead of per tool. From 95b37d2ce1495f8524c89fe829d9a0d7f9ef7e59 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 19 Feb 2021 10:46:20 -0500 Subject: [PATCH 027/140] GP-693: Fixed additional issues with Ghidra and its supporting launch scripts not being able to run correctly on Windows when an ampersand was in the path. Also fixed an issue with svrAdmin.bat and buildGhidraJar.bat not working if the Ghidra path contained a space. --- .../java/ghidra/util/GhidraJarBuilder.java | 16 +++----- .../main/java/ghidra/server/ServerAdmin.java | 26 +++++------- .../Windows/server/ghidraSvr.bat | 40 ++++++++----------- .../Windows/server/svrAdmin.bat | 10 ++--- .../Windows/server/svrInstall.bat | 2 +- .../Windows/server/svrUninstall.bat | 2 +- .../Windows/support/analyzeHeadless.bat | 2 +- .../Windows/support/buildGhidraJar.bat | 4 +- .../Windows/support/createPdbXmlFiles.bat | 8 ++-- .../Windows/support/pythonRun.bat | 2 +- 10 files changed, 47 insertions(+), 65 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java index 7ded06d9a2..3805428083 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java @@ -20,6 +20,7 @@ import java.nio.file.Path; import java.util.*; import java.util.jar.*; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.zip.*; import generic.jar.*; @@ -44,7 +45,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { private static final String LIBS_FILE_MODULE_KEY = "Module: "; // this is set in the buildGhidraJar batch/script files - private static final String GHIDRA_DIR = "Ghidra.Install.Root.Dir"; private static final String INVOCATION_NAME_PROPERTY = "GhidraJarBuilder.Name"; private static HashMap> libsMap = new HashMap<>(); private List rootGhidraDirs = new ArrayList<>(); @@ -961,14 +961,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { System.err.println("arg " + i + ": " + args[i]); } String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY); - String property = System.getProperty(GHIDRA_DIR); StringBuffer buf = new StringBuffer(); buf.append("\nUsage: "); buf.append(invocationName != null ? invocationName : "GhidraJarBuilder "); - if (property == null) { - buf.append(" [ ...] "); - } buf.append( " [-output ] [-srczip ] [-bin ] [-main ]\n"); System.err.println(buf.toString()); @@ -992,18 +988,16 @@ public class GhidraJarBuilder implements GhidraLaunchable { usage(args); } - List ghidraDirs = new ArrayList<>(); + List ghidraDirs = layout.getApplicationRootDirs() + .stream() + .map(f -> f.getFile(false)) + .collect(Collectors.toCollection(ArrayList::new)); File outputFile = null; File srczip = null; File extraBinDir = null; String mainClassArg = null; boolean usingGradle = false; - String property = System.getProperty(GHIDRA_DIR); - if (property != null) { - ghidraDirs.add(new File(property)); - } - for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("-output")) { diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index f5f3580822..080cb3f25b 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -52,7 +52,7 @@ public class ServerAdmin implements GhidraLaunchable { * The following properties may be set: *
 	 *   UserAdmin.invocation - identifies the name of the application used when displaying usage text.
-	 *   UserAdmin.serverDir - identifies the server directory instead of passing on command line.
+	 *   UserAdmin.config - identifies the config file instead of passing on command line.
 	 * 
* @param args command line arguments */ @@ -75,22 +75,19 @@ public class ServerAdmin implements GhidraLaunchable { * The following properties may be set: *
 	 *   UserAdmin.invocation - identifies the name of the application used when displaying usage text.
-	 *   UserAdmin.serverDir - identifies the server directory instead of passing on command line.
+	 *   UserAdmin.config - identifies the config file instead of passing on command line.
 	 * 
* @param args command line arguments */ public void execute(String[] args) { - File serverDir = null; int ix = 0; - if (args.length != 0 && !args[0].startsWith("-")) { - serverDir = new File(args[ix++]); - } - else { - serverDir = getServerDirFromConfig(); - } + String configFilePath = args.length != 0 && !args[0].startsWith("-") ? args[ix++] + : System.getProperty(CONFIG_FILE_PROPERTY); + + serverDir = getServerDirFromConfig(configFilePath); if (serverDir == null || (args.length - ix) == 0) { displayUsage(""); System.exit(-1); @@ -423,13 +420,12 @@ public class ServerAdmin implements GhidraLaunchable { } } - private File getServerDirFromConfig() { - String p = System.getProperty(CONFIG_FILE_PROPERTY); - if (p == null) { + private File getServerDirFromConfig(String configFilePath) { + if (configFilePath == null) { return null; } - propertyUsed = true; - File configFile = new File(p); + + File configFile = new File(configFilePath); if (!configFile.exists()) { System.out.println("Config file not found: " + configFile.getAbsolutePath()); @@ -455,7 +451,7 @@ public class ServerAdmin implements GhidraLaunchable { } } - p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); + String p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); if (p == null) { return null; } diff --git a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat index 98a2bc2310..0d8d500cb7 100644 --- a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat +++ b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat @@ -11,7 +11,7 @@ rem runtime which has been configured into the system PATH ahead of other Java rem it may be necessary to explicitly specify the path to the installation by setting JAVA_HOME rem below: -rem set JAVA_HOME= +rem set "JAVA_HOME=" setlocal enabledelayedexpansion @@ -50,7 +50,7 @@ if "%IS_ADMIN%"=="NO" ( rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" set APP_NAME=ghidraSvr set APP_LONG_NAME=Ghidra Server @@ -64,26 +64,26 @@ if exist "%_REALPATH%..\Ghidra\" goto normal rem NOTE: If adjusting JAVA command assignment - do not attempt to add parameters (e.g., -d64, -version:1.7, etc.) rem Development Environment -set GHIDRA_HOME=%_REALPATH%..\..\..\.. -set WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf -set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data -set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag -set LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main +set "GHIDRA_HOME=%_REALPATH%..\..\..\.." +set "WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf" +set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data" +set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag" +set "LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main" goto lab1 :normal -set GHIDRA_HOME=%_REALPATH%.. -set WRAPPER_CONF=%_REALPATH%server.conf -set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data -set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag -set LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar +set "GHIDRA_HOME=%_REALPATH%.." +set "WRAPPER_CONF=%_REALPATH%server.conf" +set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data" +set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag" +set "LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar" :lab1 rem set WRAPPER_HOME to unpacked yajsw location (crazy FOR syntax to set variable from command output) for /F "usebackq delims=" %%p in (`dir "%DATA_DIR%" /ad /b ^| findstr "^%WRAPPER_NAME_PREFIX%"`) do set WRAPPER_DIRNAME=%%p -set WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME% +set "WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME%" if not exist "%WRAPPER_HOME%\" ( echo. @@ -104,8 +104,8 @@ set ERROR=ERROR: JAVA_HOME is not set and no 'java' command could be found in yo goto reportError :findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA=%JAVA_HOME%\bin\java.exe +set "JAVA_HOME=%JAVA_HOME:"=%" +set "JAVA=%JAVA_HOME%\bin\java.exe" if exist "%JAVA%" goto lab2 set ERROR=ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -122,15 +122,7 @@ if "%JAVA_HOME%" == "" ( ) rem reestablish JAVA path based upon final JAVA_HOME -set JAVA=%JAVA_HOME%\bin\java.exe - -set OS_NAME=win32 -"%JAVA%" -version 2>&1 | findstr /I " 64-Bit " >NUL -if errorlevel 0 ( - set OS_NAME=win64 -) - -set OS_DIR=%GHIDRA_HOME%\%MODULE_DIR%\os\%OS_NAME% +set "JAVA=%JAVA_HOME%\bin\java.exe" :: set DEBUG=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=*:18888 diff --git a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat index ea7993ca45..c561b73062 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat @@ -31,18 +31,18 @@ set MAXMEM=128M :: '% ~' dereferences the value in param 0 :: 'd' - drive :: 'p' - path (without filename) -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" :: Production Environment -set CONFIG=%SCRIPT_DIR%.\server.conf +set "CONFIG=%SCRIPT_DIR%.\server.conf" if exist "%CONFIG%" goto continue :: Development Environment -set CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf +set "CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf" :continue -set VMARGS=-DUserAdmin.invocation="%0" -DUserAdmin.config="%CONFIG%" +set VMARGS=-DUserAdmin.invocation="%0" -call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin %* +call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin "%CONFIG%" %* diff --git a/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat b/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat index 1314f8a174..2df9605318 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat @@ -3,7 +3,7 @@ setlocal rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" call "%_REALPATH%\ghidraSvr" install diff --git a/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat b/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat index 75e1905064..ac5131418b 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat @@ -3,7 +3,7 @@ setlocal rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" call "%_REALPATH%\ghidraSvr" uninstall diff --git a/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat b/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat index aa4545b18b..e972b07cae 100644 --- a/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat +++ b/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat @@ -24,7 +24,7 @@ set VMARG_LIST=-XX:ParallelGCThreads=2 set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2 :: store current path -set filepath=%~dp0 +set "filepath=%~dp0" :: Loop through parameters (if there aren't any, just continue) and store :: in params variable. diff --git a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat index 1e618fa944..d32db375c9 100644 --- a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat +++ b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat @@ -8,9 +8,9 @@ setlocal set LAUNCH_MODE=fg :: Sets SCRIPT_DIR to the directory that contains this file (ends with '\') -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" -set GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra +set "GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra" if exist "%GHIDRA_ROOT_DIR%" goto continue echo This script does not support development mode use diff --git a/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat b/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat index 44826dd39e..10a7c7d8f0 100644 --- a/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat +++ b/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat @@ -11,16 +11,16 @@ setlocal REM Get parent of current folder -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" -set GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra +set "GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra" set OS_DIR=os REM Production Environment if exist "%GHIDRA_DIR%" goto continue REM Development Environment -set GHIDRA_DIR=%SCRIPT_DIR%..\..\.. +set "GHIDRA_DIR=%SCRIPT_DIR%..\..\.." set OS_DIR=build\os :continue @@ -35,7 +35,7 @@ if exist "%PROGRAMFILES(X86)%" ( set OS_TYPE=win32 ) -set PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe +set "PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe" if not exist "%PDB_EXE%" ( echo "%PDB_EXE% not found" diff --git a/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat b/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat index bc934c12a1..650e9f172b 100644 --- a/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat +++ b/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat @@ -26,6 +26,6 @@ set VMARG_LIST=-XX:ParallelGCThreads=2 set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2 :: store current path -set filepath=%~dp0 +set "filepath=%~dp0" call "%filepath%launch.bat" %LAUNCH_MODE% Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %params% From df114d13a624354128a57722d5501d558a806524 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 19 Feb 2021 11:40:08 -0500 Subject: [PATCH 028/140] GP-693: Forgot to change linux scripts where needed --- Ghidra/RuntimeScripts/Linux/server/svrAdmin | 4 ++-- Ghidra/RuntimeScripts/Linux/support/buildGhidraJar | 2 +- Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/RuntimeScripts/Linux/server/svrAdmin b/Ghidra/RuntimeScripts/Linux/server/svrAdmin index 702ca83c49..b9f40d12a4 100755 --- a/Ghidra/RuntimeScripts/Linux/server/svrAdmin +++ b/Ghidra/RuntimeScripts/Linux/server/svrAdmin @@ -45,8 +45,8 @@ fi OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')" if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then - VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") -DUserAdmin.config=\"${CONFIG}\"" - "${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "$@" + VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") " + "${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "${CONFIG}" "$@" else echo "Running svrAdmin with $SUDO as ${OWNER} ..." $SUDO -u $OWNER "$0" "$@" diff --git a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar index 66b87cb0c2..dbe6b52e02 100755 --- a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar +++ b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar @@ -25,7 +25,7 @@ if [ ! -d "${GHIDRA_ROOT_DIR}" ]; then fi # Set required VMARGS for jar builder application -APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}") -DGhidra.Install.Root.Dir=\"${GHIDRA_ROOT_DIR}\" " +APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}") " # Launch jar builder "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" Ghidra "${MAXMEM}" "${APP_VMARGS}" ghidra.util.GhidraJarBuilder -main ghidra.JarRun "$@" diff --git a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat index d32db375c9..3f2d19e94f 100644 --- a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat +++ b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat @@ -18,6 +18,6 @@ exit /B 1 :continue -set APP_VMARGS=-DGhidraJarBuilder.Name=%0 -DGhidra.Install.Root.Dir=%GHIDRA_ROOT_DIR% +set APP_VMARGS=-DGhidraJarBuilder.Name=%0 call "%~dp0launch.bat" %LAUNCH_MODE% Ghidra "" "%APP_VMARGS%" ghidra.util.GhidraJarBuilder -main ghidra.JarRun %* From efa065ac4d80a24699a04f9418379f77824c19f9 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 19 Feb 2021 15:47:24 -0500 Subject: [PATCH 029/140] GP-699 Process ELF init/fini arrays before applying relocations --- .../app/util/opinion/ElfProgramBuilder.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 6198ce639d..21f5216515 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -158,8 +158,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { elf.getLoadAdapter().processElf(this, monitor); - processRelocations(monitor); processEntryPoints(monitor); + + processRelocations(monitor); processImports(monitor); monitor.setMessage("Processing PLT/GOT ..."); @@ -338,11 +339,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { /** * Processes the GNU version section. + * @throws CancelledException */ - private void processGNU(TaskMonitor monitor) { - if (monitor.isCancelled()) { - return; - } + private void processGNU(TaskMonitor monitor) throws CancelledException { + monitor.checkCanceled(); Address versionTableAddr = null; @@ -464,10 +464,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } } - private void processEntryPoints(TaskMonitor monitor) { - if (monitor.isCancelled()) { - return; - } + private void processEntryPoints(TaskMonitor monitor) throws CancelledException { + monitor.checkCanceled(); monitor.setMessage("Creating entry points..."); long entry = elf.e_entry(); // already adjusted for pre-link @@ -587,11 +585,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { return msg; } - private void markupInterpreter(TaskMonitor monitor) { - if (monitor.isCancelled()) { - return; - } - + private void markupInterpreter(TaskMonitor monitor) throws CancelledException { + monitor.checkCanceled(); monitor.setMessage("Processing interpreter..."); Address interpStrAddr = null; @@ -621,10 +616,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { listing.setComment(interpStrAddr, CodeUnit.EOL_COMMENT, "Initial Elf program interpreter"); } - private void processImports(TaskMonitor monitor) { - if (monitor.isCancelled()) { - return; - } + private void processImports(TaskMonitor monitor) throws CancelledException { + monitor.checkCanceled(); monitor.setMessage("Processing imports..."); ExternalManager extManager = program.getExternalManager(); From f4e768171b7e8bdb221fafa9d325ec0f90e79eba Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 19 Feb 2021 16:22:56 -0500 Subject: [PATCH 030/140] GT-3661 reverted modification of ELF section loading and improved pruning --- .../app/util/opinion/ElfProgramBuilder.java | 138 +++++++++--------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index e855b21a16..d14b3c7a2e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -144,11 +144,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { return; } - if (elf.e_shnum() != 0) { - // discard tiny alignment/filler segment fragments when - // section headers are present - pruneDiscardableBlocks(); - } + pruneDiscardableBlocks(); markupElfHeader(monitor); markupProgramHeaders(monitor); @@ -162,8 +158,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { elf.getLoadAdapter().processElf(this, monitor); - processRelocations(monitor); processEntryPoints(monitor); + processRelocations(monitor); processImports(monitor); monitor.setMessage("Processing PLT/GOT ..."); @@ -206,7 +202,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } for (ElfSectionHeader section : sections) { - if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) { + if (section.getType() == ElfSectionHeaderConstants.SHT_NULL || + section.getType() == ElfSectionHeaderConstants.SHT_NOBITS) { continue; } section.getSize(); @@ -218,56 +215,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } } - // Allocate unused file ranges (0: first segment index, segments.length: first section index) - - // Make segment file allocations - for (int i = 0; i < segments.length; i++) { - ElfProgramHeader segment = segments[i]; - if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) { - continue; - } - long size = segment.getFileSize(); - long offset = segment.getOffset(); - if (size == 0 && offset > 0) { - ValueRange valueRange = fileMap.getValueRange(offset); - if (valueRange == null || valueRange.getValue() < -1) { - continue; - } - if (valueRange.getValue() >= 0 && valueRange.getStart() < segment.getOffset()) { - ElfProgramHeader otherSegment = segments[valueRange.getValue()]; - otherSegment.setSize(offset - valueRange.getStart(), 0); // reduce previous segment allocation - } - segment.setSize(valueRange.getEnd() - offset + 1, 0); - fileMap.paintRange(offset, valueRange.getEnd(), i); // allocated to segment - } - } - - // Make section file allocations - int firstSectionIndex = segments.length; - for (int i = 0; i < sections.length; i++) { - ElfSectionHeader section = sections[i]; - if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) { - continue; - } - long size = section.getSize(); - long offset = section.getOffset(); - if (size == 0 && offset > 0) { - ValueRange valueRange = fileMap.getValueRange(offset); - if (valueRange == null || valueRange.getValue() < -1) { - continue; - } - if (valueRange.getValue() >= firstSectionIndex && - valueRange.getStart() < section.getOffset()) { - ElfSectionHeader otherSection = - sections[valueRange.getValue() - firstSectionIndex]; - otherSection.setSize(offset - valueRange.getStart()); // reduce previous section allocation - } - section.setSize(valueRange.getEnd() - offset + 1); - Msg.info(this, "Forced section " + i + " size: " + section.getSize()); - fileMap.paintRange(offset, valueRange.getEnd(), firstSectionIndex + i); // allocated to section - } - } - // Ignore header regions which will always be allocated to blocks int elfHeaderSize = elf.toDataType().getLength(); fileMap.paintRange(0, elfHeaderSize - 1, -4); @@ -302,17 +249,18 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } private void pruneDiscardableBlocks() { - byte[] bytes = new byte[DISCARDABLE_SEGMENT_SIZE]; try { for (MemoryBlock block : memory.getBlocks()) { long size = block.getSize(); - if (size > DISCARDABLE_SEGMENT_SIZE || - !(block.getName().startsWith(SEGMENT_NAME_PREFIX) || - block.getName().startsWith(UNALLOCATED_NAME_PREFIX))) { - continue; + // prune any zero-filled unallocated block or segment blocks smaller than DISCARDABLE_SEGMENT_SIZE + if (!block.getName().startsWith(UNALLOCATED_NAME_PREFIX)) { + // Don't prune segments when sections are absent + if (elf.e_shnum() == 0 || size > DISCARDABLE_SEGMENT_SIZE || + !block.getName().startsWith(SEGMENT_NAME_PREFIX)) { + continue; + } } - block.getBytes(block.getStart(), bytes, 0, (int) size); - if (isZeroedArray(bytes, (int) size)) { + if (isZeroFilledBlock(block)) { Msg.debug(this, "Removing discardable alignment/filler segment at " + block.getStart()); memory.removeBlock(block, TaskMonitor.DUMMY); @@ -324,6 +272,25 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } } + private boolean isZeroFilledBlock(MemoryBlock block) throws MemoryAccessException { + int bufSize = 8 * 1024; + long blockSize = block.getSize(); + if (blockSize < bufSize) { + bufSize = (int) blockSize; + } + byte[] bytes = new byte[bufSize]; + Address addr = block.getStart(); + long cnt = 0; + while (cnt < blockSize) { + int readLen = block.getBytes(addr.add(cnt), bytes, 0, bufSize); + if (readLen <= 0 || !isZeroedArray(bytes, readLen)) { + return false; + } + cnt += readLen; + } + return true; + } + private boolean isZeroedArray(byte[] bytes, int len) { for (int i = 0; i < len; i++) { if (bytes[i] != 0) { @@ -775,6 +742,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { AddressSpace defaultSpace = defaultBase.getAddressSpace(); long defaultBaseOffset = defaultBase.getAddressableWordOffset(); + int totalCount = 0; + for (ElfRelocationTable relocationTable : elf.getRelocationTables()) { + totalCount += relocationTable.getRelocationCount(); + } + monitor.initialize(totalCount); + for (ElfRelocationTable relocationTable : elf.getRelocationTables()) { monitor.checkCanceled(); @@ -811,6 +784,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { log("Failed to identify relocation base address for relocation table 0x" + relocationTable.getAddressOffset() + " [section: " + sectionToBeRelocated.getNameAsString() + "]"); + monitor.incrementProgress(relocationTable.getRelocationCount()); continue; } relocationSpace = sectionLoadAddr.getAddressSpace(); @@ -863,6 +837,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { for (ElfRelocation reloc : relocs) { monitor.checkCanceled(); + monitor.incrementProgress(1); int symbolIndex = reloc.getSymbolIndex(); String symbolName = null; @@ -1318,6 +1293,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { ElfSymbolTable[] symbolTables = elf.getSymbolTables(); + int totalCount = 0; + for (ElfSymbolTable elfSymbolTable : symbolTables) { + totalCount += elfSymbolTable.getSymbolCount(); + } + monitor.initialize(totalCount); + for (ElfSymbolTable elfSymbolTable : symbolTables) { monitor.checkCanceled(); @@ -1352,6 +1333,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { TaskMonitor monitor) throws CancelledException { for (ElfSymbol elfSymbol : symbols) { monitor.checkCanceled(); + monitor.incrementProgress(1); + try { Address address = calculateSymbolAddress(elfSymbol); @@ -2306,9 +2289,17 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { private void processStringTables(TaskMonitor monitor) throws CancelledException { monitor.setMessage("Processing string tables..."); + monitor.setShowProgressValue(false); - for (ElfStringTable stringTable : elf.getStringTables()) { + ElfStringTable[] stringTables = elf.getStringTables(); + long totalLength = 0; + for (ElfStringTable stringTable : stringTables) { + totalLength += stringTable.getLength(); + } + monitor.initialize(totalLength); + + for (ElfStringTable stringTable : stringTables) { monitor.checkCanceled(); Address stringTableAddr = null; @@ -2323,18 +2314,26 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { if (stringTableAddr == null) { // log("Failed to locate string table at file offset 0x" + // Long.toHexString(stringTable.getFileOffset())); + monitor.incrementProgress(stringTable.getLength()); // skipping table continue; } AddressRange rangeConstraint = getMarkupMemoryRangeConstraint(stringTableAddr); if (rangeConstraint == null) { + monitor.incrementProgress(stringTable.getLength()); // skipping table continue; } - long limit = Math.min(stringTable.getLength(), rangeConstraint.getLength()); + long tblLength = stringTable.getLength(); + long limit = Math.min(tblLength, rangeConstraint.getLength()); + if (limit < tblLength) { + monitor.incrementProgress(tblLength - limit); + } markupStringTable(stringTableAddr, limit, monitor); } + + monitor.setShowProgressValue(true); } private void markupStringTable(Address address, long tableBytesLength, TaskMonitor monitor) { @@ -2353,6 +2352,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { address = address.addNoWrap(1); while (!monitor.isCancelled() && address.compareTo(end) < 0) { int length = createString(address); + monitor.incrementProgress(length); address = address.addNoWrap(length); } } @@ -2907,7 +2907,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { for (ElfSectionHeader elfSectionToLoad : sections) { monitor.checkCanceled(); int type = elfSectionToLoad.getType(); - if (type != ElfSectionHeaderConstants.SHN_UNDEF && + if (type != ElfSectionHeaderConstants.SHT_NULL && (includeOtherBlocks || elfSectionToLoad.isAlloc())) { long fileOffset = elfSectionToLoad.getOffset(); if (fileOffset < 0 || fileOffset >= fileBytes.getSize()) { @@ -3004,8 +3004,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { final String blockName = elfSectionToLoad.getNameAsString(); try { - if (loadOffset == -1 || (loadOffset == 0 && - elfSectionToLoad.getType() == ElfSectionHeaderConstants.SHT_NOBITS)) { + if (loadOffset == -1 || + elfSectionToLoad.getType() == ElfSectionHeaderConstants.SHT_NOBITS) { if (!elfSectionToLoad.isAlloc() && elfSectionToLoad.getType() != ElfSectionHeaderConstants.SHT_PROGBITS) { return; // non-allocate at runtime From 90dd0e6dd57c3d10cb83896cb1a338195798447e Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Fri, 19 Feb 2021 17:05:39 -0500 Subject: [PATCH 031/140] GP-698 - ANALYZED flag fixed better --- .../plugin/core/analysis/AutoAnalysisManager.java | 15 ++++++++------- .../plugin/core/analysis/AutoAnalysisPlugin.java | 3 --- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java index 0ff7a1f3a9..d8a52fba89 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisManager.java @@ -1110,13 +1110,14 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl int answer = OptionDialog.showYesNoDialog(tool.getToolFrame(), "Analyze", "" + HTMLUtilities.escapeHTML(program.getDomainFile().getName()) + " has not been analyzed. Would you like to analyze it now?"); - boolean analyze = answer == OptionDialog.OPTION_ONE; - if (!analyze) { - // Must set this to false at each fall-out location. Setting it true too early - // results in false positives. It is set true only at the beginning of analysis. - GhidraProgramUtilities.setAnalyzedFlag(program, false); - } - return analyze; + //Set to false for now. ANALYZED is a tri-valued variable: + // null means not asked. + // false means asked but could still turn true when analysis happens. + // true means analysis has started. + //Setting false here only works due to this code only being reachable + // because of the behavior of GhidraProgramUtilities.shouldAskToAnalyze(program) above. + GhidraProgramUtilities.setAnalyzedFlag(program, false); + return answer == OptionDialog.OPTION_ONE; //Analyze } return false; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java index 96cfa1e16f..802540285e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java @@ -188,9 +188,6 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis analysisMgr.initializeOptions(); // get initial options if (!showOptionsDialog(program)) { - // Must set this to false at each fall-out location. Setting it true too early - // results in false positives. It is set true only at the beginning of analysis. - GhidraProgramUtilities.setAnalyzedFlag(program, false); return; } From aaf3bcef17ccd7bae18b0783f75ce2842743aa2a Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 19 Feb 2021 18:19:50 -0500 Subject: [PATCH 032/140] Test fix for splash screen test --- .../java/docking/DockingWindowManager.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 0f5687979b..4b7d9b4476 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -1735,11 +1735,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } Component bestCenter = getJavaActiveWindow(); - Window bestParent = getParentWindow(bestCenter); - - if (!provider.isModal()) { - bestParent = getBestNonModalParent(provider, bestParent); - } + Window bestParent = getBestParent(provider, bestCenter); // // Note: prefer the active window; allow user's choice of center component when it is @@ -1762,6 +1758,20 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } } + private static Window getBestParent(DialogComponentProvider provider, Component component) { + Window bestParent = getParentWindow(component); + if (!provider.isModal()) { + bestParent = getBestNonModalParent(provider, bestParent); + } + + if (bestParent == null) { + KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + bestParent = kfm.getActiveWindow(); + } + + return bestParent; + } + private static Window getBestNonModalParent(DialogComponentProvider newProvider, Window bestParent) { From 9a4ae5feaf46d82f33fa185bbf8eb076a64877f4 Mon Sep 17 00:00:00 2001 From: Kip Hamiltons Date: Sat, 20 Feb 2021 22:38:22 +1100 Subject: [PATCH 033/140] Changes incorrect to in pcode manual description for SUBPIECE --- Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml | 2 +- GhidraDocs/languages/html/pcodedescription.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml b/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml index 70f219d2f6..4921d8d051 100644 --- a/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml +++ b/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml @@ -926,7 +926,7 @@ This is a truncation operator that understands the endianess of the data. Input1 indicates the number of least significant bytes of input0 to be thrown away. Output is then filled with any remaining bytes of input0 up to the size of output. If the size of -output is smaller than the size of input0 plus the constant input1, +output is smaller than the size of input0 minus the constant input1, then the additional most significant bytes of input0 will also be truncated. diff --git a/GhidraDocs/languages/html/pcodedescription.html b/GhidraDocs/languages/html/pcodedescription.html index 6f038f2318..72f367c268 100644 --- a/GhidraDocs/languages/html/pcodedescription.html +++ b/GhidraDocs/languages/html/pcodedescription.html @@ -625,7 +625,7 @@ This is a truncation operator that understands the endianess of the data. Input1 indicates the number of least significant bytes of input0 to be thrown away. Output is then filled with any remaining bytes of input0 up to the size of output. If the size of -output is smaller than the size of input0 plus the constant input1, +output is smaller than the size of input0 minus the constant input1, then the additional most significant bytes of input0 will also be truncated.

From 24891974e15a88652ccf34382b4fd7e1da8f6388 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Mon, 22 Feb 2021 11:31:18 -0500 Subject: [PATCH 034/140] Corrected conflict --- .../app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java index 0814299b0f..f27e125b47 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliBlobCustomAttrib.java @@ -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. From 01b6027c771ab85a2278624fc1ba8e93bd62159f Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Mon, 22 Feb 2021 13:55:34 +0000 Subject: [PATCH 035/140] GP-697_emteere delayed reading of symbol names to improve memory read performance --- .../app/util/bin/format/elf/ElfSymbol.java | 155 +++++++++++------- .../util/bin/format/elf/ElfSymbolTable.java | 34 ++-- 2 files changed, 122 insertions(+), 67 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java index 297dedfd3b..170c317d97 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java @@ -103,11 +103,24 @@ public class ElfSymbol implements ByteArrayConverter { private String nameAsString; + /** + * create an ElfSymbol() + * Warning! the routine initSymbolName() must be called on the symbol later + * to initialize the string name. This is a performance enhancement. + * + * @param reader to read symbol from + * @param symbolIndex index of the symbol to read + * @param symbolTable symbol table to associate the symbol to + * @param stringTable string table to read symbols from + * @param header else header + * @return newly created ElfSymbol + * + * @throws IOException if an issue with reading occurs + */ public static ElfSymbol createElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex, - ElfSymbolTable symbolTable, ElfStringTable stringTable, ElfHeader header) - throws IOException { + ElfSymbolTable symbolTable, ElfHeader header) throws IOException { ElfSymbol elfSymbol = (ElfSymbol) reader.getFactory().create(ElfSymbol.class); - elfSymbol.initElfSymbol(reader, symbolIndex, symbolTable, stringTable, header); + elfSymbol.initElfSymbol(reader, symbolIndex, symbolTable, header); return elfSymbol; } @@ -117,49 +130,6 @@ public class ElfSymbol implements ByteArrayConverter { public ElfSymbol() { } - private void initElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex, - ElfSymbolTable symbolTable, ElfStringTable stringTable, ElfHeader header) - throws IOException { - this.header = header; - this.symbolTable = symbolTable; - this.symbolTableIndex = symbolIndex; - - if (header.is32Bit()) { - st_name = reader.readNextInt(); - st_value = reader.readNextInt() & Conv.INT_MASK; - st_size = reader.readNextInt() & Conv.INT_MASK; - st_info = reader.readNextByte(); - st_other = reader.readNextByte(); - st_shndx = reader.readNextShort(); - } - else { - st_name = reader.readNextInt(); - st_info = reader.readNextByte(); - st_other = reader.readNextByte(); - st_shndx = reader.readNextShort(); - st_value = reader.readNextLong(); - st_size = reader.readNextLong(); - } - - if (st_name == 0) { - if (getType() == STT_SECTION) { - ElfSectionHeader[] sections = header.getSections(); - if (st_shndx < 0 || st_shndx >= sections.length) { - //invalid section reference... - //this is a bug in objcopy, whereby sections are removed - //but the corresponding section symbols are left behind. - } - else { - ElfSectionHeader section = sections[st_shndx]; - nameAsString = section.getNameAsString(); - } - } - } - else { - nameAsString = stringTable.readString(reader, st_name); - } - } - /** * Creates a new section symbol. * @param header the corresponding ELF header @@ -209,6 +179,69 @@ public class ElfSymbol implements ByteArrayConverter { this.symbolTableIndex = symbolIndex; } + private void initElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex, + ElfSymbolTable symbolTable, ElfHeader header) throws IOException { + this.header = header; + this.symbolTable = symbolTable; + this.symbolTableIndex = symbolIndex; + + if (header.is32Bit()) { + st_name = reader.readNextInt(); + st_value = reader.readNextInt() & Conv.INT_MASK; + st_size = reader.readNextInt() & Conv.INT_MASK; + st_info = reader.readNextByte(); + st_other = reader.readNextByte(); + st_shndx = reader.readNextShort(); + } + else { + st_name = reader.readNextInt(); + st_info = reader.readNextByte(); + st_other = reader.readNextByte(); + st_shndx = reader.readNextShort(); + st_value = reader.readNextLong(); + st_size = reader.readNextLong(); + } + + if (st_name == 0) { + if (getType() == STT_SECTION) { + ElfSectionHeader[] sections = header.getSections(); + if (st_shndx < 0 || st_shndx >= sections.length) { + //invalid section reference... + //this is a bug in objcopy, whereby sections are removed + //but the corresponding section symbols are left behind. + } + else { + ElfSectionHeader section = sections[st_shndx]; + nameAsString = section.getNameAsString(); + } + } + } + else { + // The string name will be initialized later + // in a call to initSymbolName() + } + } + + /** + * Initialize the string name of the symbol. + * + * NOTE: This routine MUST be called for each + * ELFSymbol after the elf symbols have been created. + * + * This is done separately from the initial symbol entry read because + * the string names are in a separate location. If they are read + * at the same time the reading buffer will jump around and significantly + * degrade reading performance. + * + * @param reader to read from + * @param stringTable stringTable to initialize symbol name + */ + public void initSymbolName(FactoryBundledWithBinaryReader reader, ElfStringTable stringTable) { + if (nameAsString == null) { + nameAsString = stringTable.readString(reader, st_name); + } + } + /** * Get the symbol table containing this symbol * @return symbol table @@ -249,27 +282,37 @@ public class ElfSymbol implements ByteArrayConverter { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } ElfSymbol other = (ElfSymbol) obj; - if (st_info != other.st_info) + if (st_info != other.st_info) { return false; - if (st_name != other.st_name) + } + if (st_name != other.st_name) { return false; - if (st_other != other.st_other) + } + if (st_other != other.st_other) { return false; - if (st_shndx != other.st_shndx) + } + if (st_shndx != other.st_shndx) { return false; - if (st_size != other.st_size) + } + if (st_size != other.st_size) { return false; - if (st_value != other.st_value) + } + if (st_value != other.st_value) { return false; - if (symbolTableIndex != other.symbolTableIndex) + } + if (symbolTableIndex != other.symbolTableIndex) { return false; + } return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java index 09eea496c9..fcb4631af9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java @@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import ghidra.app.util.bin.ByteArrayConverter; import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; @@ -96,15 +97,26 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { long entryPos = reader.getPointerIndex(); + // load the all the symbol entries first, don't initialize the string name + // that will be done later to help localize memory access for (int i = 0; i < symbolCount; i++) { // Reposition reader to start of symbol element since ElfSymbol object // may not consume all symbol element data reader.setPointerIndex(entryPos); - ElfSymbol sym = ElfSymbol.createElfSymbol(reader, i, this, stringTable, header); + ElfSymbol sym = ElfSymbol.createElfSymbol(reader, i, this, header); symbolList.add(sym); entryPos += entrySize; } + // sort the entries by the index in the string table, so don't jump around reading + List sortedList = symbolList.stream().sorted( + (o1, o2) -> Integer.compare(o1.getName(), o2.getName())).collect(Collectors.toList()); + + // initialize the Symbol string names from string table + for (ElfSymbol sym : sortedList) { + sym.initSymbolName(reader, stringTable); + } + reader.setPointerIndex(ptr); symbols = new ElfSymbol[symbolList.size()]; @@ -163,9 +175,9 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { * @return the symbol at the specified address */ public ElfSymbol getSymbolAt(long addr) { - for (int i = 0; i < symbols.length; i++) { - if (symbols[i].getValue() == addr) { - return symbols[i]; + for (ElfSymbol symbol : symbols) { + if (symbol.getValue() == addr) { + return symbol; } } return null; @@ -177,9 +189,9 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { */ public ElfSymbol[] getGlobalSymbols() { List list = new ArrayList<>(); - for (int i = 0; i < symbols.length; i++) { - if (symbols[i].getBind() == ElfSymbol.STB_GLOBAL) { - list.add(symbols[i]); + for (ElfSymbol symbol : symbols) { + if (symbol.getBind() == ElfSymbol.STB_GLOBAL) { + list.add(symbol); } } ElfSymbol[] array = new ElfSymbol[list.size()]; @@ -193,11 +205,11 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { */ public String[] getSourceFiles() { List list = new ArrayList<>(); - for (int j = 0; j < symbols.length; j++) { - if (symbols[j].getType() == ElfSymbol.STT_FILE) { - String name = symbols[j].getNameAsString(); + for (ElfSymbol symbol : symbols) { + if (symbol.getType() == ElfSymbol.STT_FILE) { + String name = symbol.getNameAsString(); if (name != null) { - list.add(symbols[j].getNameAsString()); + list.add(symbol.getNameAsString()); } } } From 3d36d914bea71cd65ae621cc671ac69cea2c4d8c Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:22:26 -0500 Subject: [PATCH 036/140] GP-667 fix XmlImport bookmark overwrite existing --- .../ghidra/app/util/xml/BookmarksXmlMgr.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/BookmarksXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/BookmarksXmlMgr.java index be4bb67b8f..99db7273cb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/BookmarksXmlMgr.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/BookmarksXmlMgr.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -16,9 +15,18 @@ */ package ghidra.app.util.xml; +import org.xml.sax.SAXParseException; + import ghidra.app.util.importer.MessageLog; -import ghidra.program.model.address.*; -import ghidra.program.model.listing.*; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressFactory; +import ghidra.program.model.address.AddressFormatException; +import ghidra.program.model.address.AddressIterator; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.listing.Bookmark; +import ghidra.program.model.listing.BookmarkManager; +import ghidra.program.model.listing.BookmarkType; +import ghidra.program.model.listing.Program; import ghidra.util.XmlProgramUtilities; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; @@ -27,8 +35,6 @@ import ghidra.util.xml.XmlWriter; import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; -import org.xml.sax.SAXParseException; - class BookmarksXmlMgr { private BookmarkManager bookmarkMgr; private AddressFactory factory; @@ -97,13 +103,13 @@ class BookmarksXmlMgr { } try { - if (!overwrite) { - if (bookmarkMgr.getBookmark(addr, type, category) != null) { - log.appendMsg("Conflicting '" + type + "' BOOKMARK ignored at: " + addr); - return; - } + boolean hasExistingBookmark = bookmarkMgr.getBookmark(addr, type, category) != null; + if (overwrite || !hasExistingBookmark) { + bookmarkMgr.setBookmark(addr, type, category, comment); + } + if (!overwrite && hasExistingBookmark) { + log.appendMsg("Conflicting '" + type + "' BOOKMARK ignored at: " + addr); } - bookmarkMgr.setBookmark(addr, type, category, comment); } catch (Exception e) { log.appendException(e); From 7868dbc4f992311dcce012bf284f9f6be953347a Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 22 Feb 2021 11:40:32 -0500 Subject: [PATCH 037/140] GP-702: Fixed an exception that occurred when importing Mach-O files that define zero LC_BUILD_VERSION tool entries --- .../util/bin/format/macho/commands/BuildVersionCommand.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/BuildVersionCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/BuildVersionCommand.java index 45d8b4b115..fa918132d3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/BuildVersionCommand.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/BuildVersionCommand.java @@ -80,8 +80,10 @@ public class BuildVersionCommand extends LoadCommand { struct.add(DWORD, "minos", null); struct.add(DWORD, "sdk", null); struct.add(DWORD, "ntools", null); - struct.add(new ArrayDataType(buildToolVersionDataType, ntools, - buildToolVersionDataType.getLength()), "build_tool_version[]", null); + if (ntools > 0) { + struct.add(new ArrayDataType(buildToolVersionDataType, ntools, + buildToolVersionDataType.getLength()), "build_tool_version[]", null); + } struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY)); return struct; } From 1c0ad2c8df09549cc0f891dd13f4aa5f019a00b4 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 22 Feb 2021 16:19:19 -0500 Subject: [PATCH 038/140] GP-705 - Gnu Demangler speed improvement --- .../analysis/AbstractDemanglerAnalyzer.java | 27 ++++++++++++++----- .../demangler/gnu/GnuDemanglerParser.java | 6 +++-- .../ghidra/util/classfinder/ClassPackage.java | 2 +- .../main/datatree/LocalTreeNodeHandler.java | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java index 6722672bfa..7763217f21 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java @@ -57,19 +57,38 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer { public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException { + try { + monitor.setIndeterminate(true); + return doAdded(program, set, monitor, log); + } + finally { + monitor.setIndeterminate(false); + } + } + + private boolean doAdded(Program program, AddressSetView set, TaskMonitor monitor, + MessageLog log) + throws CancelledException { + DemanglerOptions options = getOptions(); if (!validateOptions(options, log)) { log.appendMsg(getName(), "Invalid demangler options--cannot demangle"); return false; } - monitor.initialize(100); + int count = 0; + + String defaultMessage = monitor.getMessage(); SymbolTable symbolTable = program.getSymbolTable(); SymbolIterator it = symbolTable.getPrimarySymbolIterator(set, true); while (it.hasNext()) { monitor.checkCanceled(); + if (++count % 100 == 0) { + monitor.setMessage(defaultMessage + " - " + count + " symbols"); + } + Symbol symbol = it.next(); if (skipSymbol(symbol)) { continue; @@ -81,12 +100,6 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer { if (demangled != null) { apply(program, address, demangled, options, log, monitor); } - - Address min = set.getMinAddress(); - Address max = set.getMaxAddress(); - int distance = (int) (address.getOffset() - min.getOffset()); - int percent = (int) ((distance / max.getOffset()) * 100); - monitor.setProgress(percent); } return true; diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java index 0a8e286903..171b061ecf 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java @@ -244,6 +244,8 @@ public class GnuDemanglerParser { * * Parts: * -required text (capture group 2) + * --note: this uses '++', a possessive quantifier, to help keep the + * backtracking to a minimum * -a space * -'for' or 'to' (capture group 3) * -a space @@ -262,7 +264,7 @@ public class GnuDemanglerParser { * non-virtual thunk to */ private static final Pattern DESCRIPTIVE_PREFIX_PATTERN = - Pattern.compile("((.+ )+(for|to) )(.+)"); + Pattern.compile("((.+ )(for|to) )(.+)"); /** * The c 'decltype' keyword pattern @@ -307,7 +309,7 @@ public class GnuDemanglerParser { // note: this capture group seems to fail with excessive templating String operatorTemplates = "(<.+>){0,1}"; String operatorPrefix = - ".*(.*" + OPERATOR + "(" + alternated + ")\\s*" + operatorTemplates + ".*)\\s*"; + "(.*" + OPERATOR + "(" + alternated + ")\\s*" + operatorTemplates + ")\\s*"; String parameters = "(\\(.*\\))"; String trailing = "(.*)"; diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassPackage.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassPackage.java index ddadfa431e..2a03c777e8 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassPackage.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassPackage.java @@ -78,7 +78,7 @@ class ClassPackage extends ClassLocation { pkg = packageName + "." + pkg; } - monitor.setMessage("scanning package: " + pkg); + monitor.setMessage("Scanning package: " + pkg); children.add(new ClassPackage(rootDir, pkg, monitor)); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java index bcc70cdd84..b91a7d08d6 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java @@ -222,7 +222,7 @@ public final class LocalTreeNodeHandler GTreeNode copyNode = toCopy.get(i); monitor.setMessage( - "Processing file " + i + " of " + size + ": " + copyNode.getName()); + "Processing file " + (i + 1) + " of " + size + ": " + copyNode.getName()); add(destination, copyNode, dropAction, subMonitors[i]); monitor.setProgress(i); From 0ed83875fcb25b57ce16d2fb8a23f307c950140e Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 23 Feb 2021 12:33:16 -0500 Subject: [PATCH 039/140] GP-696 Raised ProgramDB version to 23 (upgrade not required). Implement BigRefList for from-refs --- .../ghidra/program/database/ProgramDB.java | 4 +++- .../database/references/BigRefListV0.java | 21 ++++++++++++------- .../database/references/FromAdapterV0.java | 3 +++ .../references/ReferenceDBManager.java | 1 + 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java index 331393df72..237f44302d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java @@ -96,8 +96,10 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM * 19-Jun-2020 - version 22 - Corrected fixed length indexing implementation causing * change in index table low-level storage for newly * created tables. + * 18-Feb-2021 - version 23 Added support for Big Reflist for tracking FROM references. + * Primarily used for large numbers of Entry Point references. */ - static final int DB_VERSION = 22; + static final int DB_VERSION = 23; /** * UPGRADE_REQUIRED_BFORE_VERSION should be changed to DB_VERSION anytime the diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/BigRefListV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/BigRefListV0.java index e4b5b67c75..4f8e5f2dda 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/BigRefListV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/BigRefListV0.java @@ -62,17 +62,17 @@ class BigRefListV0 extends RefList { * @param address address associated with this list * @param adapter entry record storage adapter * @param addrMap address map for encoding/decoding addresses - * @param program + * @param program associated Program * @param cache RefList object cache * @param isFrom true for from-adapter use, false for to-adapter use - * @throws IOException + * @throws IOException if database IO error occurs */ BigRefListV0(Address address, RecordAdapter adapter, AddressMap addrMap, ProgramDB program, DBObjectCache cache, boolean isFrom) throws IOException { super(addrMap.getKey(address, true), address, adapter, addrMap, program, cache, isFrom); record = ToAdapter.TO_REFS_SCHEMA.createRecord(key); - table = program.getDBHandle().createTable(BASE_TABLE_NAME + Long.toHexString(key), - BIG_REFS_SCHEMA, new int[] { ADDRESS_COL }); + table = program.getDBHandle() + .createTable(getTableName(), BIG_REFS_SCHEMA, new int[] { ADDRESS_COL }); } /** @@ -80,9 +80,10 @@ class BigRefListV0 extends RefList { * @param rec existing refList record * @param adapter entry record storage adapter * @param addrMap address map for encoding/decoding addresses - * @param program + * @param program associated Program * @param cache RefList object cache * @param isFrom true for from-adapter use, false for to-adapter use + * @throws IOException if database IO error occurs */ BigRefListV0(DBRecord rec, RecordAdapter adapter, AddressMap addrMap, ProgramDB program, DBObjectCache cache, boolean isFrom) throws IOException { @@ -91,11 +92,10 @@ class BigRefListV0 extends RefList { if (rec.getBinaryData(ToAdapter.REF_DATA_COL) != null) { throw new IllegalArgumentException("Invalid reference record"); } - String tableName = BASE_TABLE_NAME + Long.toHexString(rec.getKey()); - table = program.getDBHandle().getTable(tableName); + table = program.getDBHandle().getTable(getTableName()); if (table == null) { throw new IOException( - "BigRefList table not found for " + address + " (" + tableName + ")"); + "BigRefList table not found for " + address + " (" + getTableName() + ")"); } if (!isFrom) { refLevel = rec.getByteValue(ToAdapter.REF_LEVEL_COL); @@ -103,6 +103,11 @@ class BigRefListV0 extends RefList { record = rec; } + private String getTableName() { + String prefix = isFrom ? "From" : ""; + return prefix + BASE_TABLE_NAME + Long.toHexString(key); + } + @Override public RefList checkRefListSize(DBObjectCache cache, int newSpaceRequired) { return this; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/FromAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/FromAdapterV0.java index f1597d3dbc..e05b0cf90f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/FromAdapterV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/FromAdapterV0.java @@ -60,6 +60,9 @@ class FromAdapterV0 extends FromAdapter { long fromAddr) throws IOException { DBRecord rec = table.getRecord(fromAddr); if (rec != null) { + if (rec.getBinaryData(REF_DATA_COL) == null) { + return new BigRefListV0(rec, this, addrMap, program, cache, true); + } return new RefListV0(rec, this, addrMap, program, cache, true); } return null; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java index 867e454da0..f3f47f5be9 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java @@ -382,6 +382,7 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan if (fromRefs == null) { fromRefs = fromAdapter.createRefList(program, fromCache, fromAddr); } + fromRefs = fromRefs.checkRefListSize(fromCache, 1); fromRefs.addRef(fromAddr, toAddr, type, opIndex, -1, isPrimary, sourceType, isOffset, isShifted, offsetOrShift); From 9c1fed6a133c3e2a39bf57e97d9f4c4c457d534b Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 23 Feb 2021 12:27:48 -0500 Subject: [PATCH 040/140] GP-710 Added support for additional PIC30 ELF relocations (closes #2792) --- .../elf/relocation/PIC30_ElfRelocationHandler.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java index 6059bd0968..915ad21d31 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java @@ -155,15 +155,25 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler { if (elf.e_machine() == ElfConstants.EM_DSPIC30F) { switch (type) { case R_PIC30_16: // 2 - newValue = (symbolValue + addend + oldShortValue) & 0xffff; + case R_PIC30_FILE_REG_WORD: // 6 + newValue = (symbolValue + addend + oldShortValue); memory.setShort(relocationAddress, (short) newValue); break; case R_PIC30_32: // 3 newValue = symbolValue + addend + oldValue; memory.setInt(relocationAddress, newValue); break; + case R_PIC30_FILE_REG_BYTE: // 4 short + case R_PIC30_FILE_REG: // 5 short + int reloc = symbolValue; + reloc += addend; + reloc += oldShortValue; + reloc &= 0x1fff; + newValue = reloc | (oldShortValue & ~0x1fff); + memory.setShort(relocationAddress, (short) newValue); + break; case R_PIC30_FILE_REG_WORD_WITH_DST: // 7 - int reloc = symbolValue >> 1; + reloc = symbolValue >> 1; reloc += addend; reloc += oldValue >> 4; reloc &= 0x7fff; From 446ade9e0296ec31216f0c4e1adbae44a11218e3 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 23 Feb 2021 13:31:08 -0500 Subject: [PATCH 041/140] Test fix --- .../app/plugin/core/data/ApplyDataTypeToBrowserTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/ApplyDataTypeToBrowserTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/ApplyDataTypeToBrowserTest.java index 4d6ffa774f..768eb98099 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/ApplyDataTypeToBrowserTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/ApplyDataTypeToBrowserTest.java @@ -167,7 +167,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT @Test public void testChooseDataTypeOnDefinedDts() throws Exception { - // + // // Test that apply data on an existing type will offer to clear that type // @@ -206,8 +206,6 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT public void testChooseDataTypeWhereDoesNotFit() throws Exception { goTo("004027e0"); - showDataTypeChooser(); - showDataTypeChooser(); chooseInDialog("_person"); @@ -790,8 +788,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT assertEquals(expectedText, statusText); } - private void dragNDropDataTypeToCurrentBrowserLocation( - final DataType dataType) { + private void dragNDropDataTypeToCurrentBrowserLocation(final DataType dataType) { executeOnSwingWithoutBlocking(() -> { // Simulate the drag-n-drop of the data type onto the location. ProgramLocation programLocation = codeViewerProvider.getLocation(); From 33435048dea3e4b767a42ea0bf6e1da7d26f8686 Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Tue, 23 Feb 2021 15:11:04 -0500 Subject: [PATCH 042/140] GP-695 Improve DWARF analyzer's runOnce, remove parsing of raw Elf --- .../ghidra_scripts/DWARF_ExtractorScript.java | 2 +- .../plugin/core/analysis/DWARFAnalyzer.java | 33 +++++-- .../bin/format/dwarf4/next/DWARFProgram.java | 18 ++-- .../DWARFSectionProviderFactory.java | 7 +- .../sectionprovider/ElfSectionProvider.java | 95 ------------------- 5 files changed, 34 insertions(+), 121 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/ElfSectionProvider.java diff --git a/Ghidra/Features/Base/ghidra_scripts/DWARF_ExtractorScript.java b/Ghidra/Features/Base/ghidra_scripts/DWARF_ExtractorScript.java index 6b4f87803f..59885a6062 100644 --- a/Ghidra/Features/Base/ghidra_scripts/DWARF_ExtractorScript.java +++ b/Ghidra/Features/Base/ghidra_scripts/DWARF_ExtractorScript.java @@ -63,7 +63,7 @@ public class DWARF_ExtractorScript extends GhidraScript { @Override public void run() throws Exception { - if (!DWARFProgram.isDWARF(currentProgram, monitor)) { + if (!DWARFProgram.isDWARF(currentProgram)) { popup("Unable to find DWARF information, aborting"); return; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java index 45627bfbdf..6a501ea5e1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java @@ -34,6 +34,8 @@ import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; public class DWARFAnalyzer extends AbstractAnalyzer { + private static final String DWARF_LOADED_OPTION_NAME = "DWARF Loaded"; + private static final String OPTION_IMPORT_DATATYPES = "Import data types"; private static final String OPTION_IMPORT_DATATYPES_DESC = "Import data types defined in the DWARF debug info."; @@ -84,6 +86,7 @@ public class DWARFAnalyzer extends AbstractAnalyzer { "Automatically extracts DWARF info from an ELF file."; private DWARFImportOptions importOptions = new DWARFImportOptions(); + private long lastTxId = -1; public DWARFAnalyzer() { super(DWARF_ANALYZER_NAME, DWARF_ANALYZER_DESCRIPTION, AnalyzerType.BYTE_ANALYZER); @@ -105,22 +108,24 @@ public class DWARFAnalyzer extends AbstractAnalyzer { public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException { - if (!canAnalyze(program)) { - // Check again because external DWARF data (ie. dSYM files) could have been moved - // between the time canAnalyze() was called the first time and when this method - // is called - log.appendMsg("Unable to find DWARF information, skipping DWARF analysis"); - return false; + long txId = program.getCurrentTransaction().getID(); + if (txId == lastTxId) { + // Only run once per analysis session - as denoted by being in the same transaction + return true; } + lastTxId = txId; - if (DWARFProgram.alreadyDWARFImported(program)) { - Msg.warn(this, "DWARF already imported, skipping. (Detected DWARF program module)"); + Options propList = program.getOptions(Program.PROGRAM_INFO); + boolean alreadyLoaded = propList.getBoolean(DWARF_LOADED_OPTION_NAME, false) || + oldCheckIfDWARFImported(program); + if (alreadyLoaded) { + Msg.info(this, "DWARF already imported, skipping."); return false; } DWARFSectionProvider dsp = DWARFSectionProviderFactory.createSectionProviderFor(program); if (dsp == null) { - // silently return, canAnalyze() was false positive + log.appendMsg("Unable to find DWARF information, skipping DWARF analysis"); return false; } @@ -139,6 +144,7 @@ public class DWARFAnalyzer extends AbstractAnalyzer { DWARFImportSummary parseResults = dp.parse(); parseResults.logSummaryResults(); } + propList.setBoolean(DWARF_LOADED_OPTION_NAME, true); return true; } catch (CancelledException ce) { @@ -157,9 +163,16 @@ public class DWARFAnalyzer extends AbstractAnalyzer { return false; } + private boolean oldCheckIfDWARFImported(Program prog) { + // this was the old way of checking if the DWARF analyzer had already been run. Keep + // it around for a little bit so existing programs that have already imported DWARF data + // don't get re-run. Remove after a release or two. + return DWARFFunctionImporter.hasDWARFProgModule(prog, DWARFProgram.DWARF_ROOT_NAME); + } + @Override public boolean canAnalyze(Program program) { - return DWARFProgram.isDWARF(program, null); + return DWARFProgram.isDWARF(program); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java index 6462efea8e..afd2246961 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java @@ -54,12 +54,8 @@ public class DWARFProgram implements Closeable { private static final int NAME_HASH_REPLACEMENT_SIZE = 8 + 2 + 2; private static final String ELLIPSES_STR = "..."; - public static boolean alreadyDWARFImported(Program prog) { - return DWARFFunctionImporter.hasDWARFProgModule(prog, DWARF_ROOT_NAME); - } - /** - * Returns true if the {@link Program program} probably DWARF information. + * Returns true if the {@link Program program} probably has DWARF information. *

* If the program is an Elf binary, it must have (at least) ".debug_info" and ".debug_abbr" program sections. *

@@ -67,17 +63,17 @@ public class DWARFProgram implements Closeable { * original binary file on the native filesystem. (ie. outside of Ghidra). See the DSymSectionProvider * for more info. *

- * @param program - * @param monitor - * @return + * @param program {@link Program} to test + * @return boolean true if program has DWARF info, false if not */ - public static boolean isDWARF(Program program, TaskMonitor monitor) { + public static boolean isDWARF(Program program) { String format = program.getExecutableFormat(); - if (ElfLoader.ELF_NAME.equals(format)) { + if (ElfLoader.ELF_NAME.equals(format) && + DWARFSectionProviderFactory.createSectionProviderFor(program) != null) { return true; } - else if (MachoLoader.MACH_O_NAME.equals(format) && + if (MachoLoader.MACH_O_NAME.equals(format) && DSymSectionProvider.getDSYMForProgram(program) != null) { return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/DWARFSectionProviderFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/DWARFSectionProviderFactory.java index 7ea6cdce59..7cb75f4a24 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/DWARFSectionProviderFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/DWARFSectionProviderFactory.java @@ -15,14 +15,14 @@ */ package ghidra.app.util.bin.format.dwarf4.next.sectionprovider; -import ghidra.program.model.listing.Program; -import ghidra.util.Msg; - import java.io.Closeable; import java.util.ArrayList; import java.util.List; import java.util.function.Function; +import ghidra.program.model.listing.Program; +import ghidra.util.Msg; + /** * Auto-detects which {@link DWARFSectionProvider} matches a Ghidra program. */ @@ -44,7 +44,6 @@ public class DWARFSectionProviderFactory { static { sectionProviderFactoryFuncs.add(BaseSectionProvider::createSectionProviderFor); sectionProviderFactoryFuncs.add(DSymSectionProvider::createSectionProviderFor); - sectionProviderFactoryFuncs.add(ElfSectionProvider::createSectionProviderFor); } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/ElfSectionProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/ElfSectionProvider.java deleted file mode 100644 index 4eb692cabc..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/sectionprovider/ElfSectionProvider.java +++ /dev/null @@ -1,95 +0,0 @@ -/* ### - * 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.bin.format.dwarf4.next.sectionprovider; - -import ghidra.app.util.bin.*; -import ghidra.app.util.bin.format.elf.*; -import ghidra.app.util.opinion.ElfLoader; -import ghidra.program.model.listing.Program; - -import java.io.File; -import java.io.IOException; - -import generic.continues.RethrowContinuesFactory; - -/** - * Fetches DWARF section data from ELF files, directly, without going through - * the Ghidra memory block api. This section provider usually isn't needed as - * ELF sections are normally provided as Ghidra memory blocks. In case of extra- - * large binaries, Ghidra may not be able to map the debug sections into memory - * and this section provider will allow the DWARF analyzer to still function. - */ -public class ElfSectionProvider implements DWARFSectionProvider { - - private ElfHeader header; - private RandomAccessByteProvider provider; - - public static ElfSectionProvider createSectionProviderFor(Program program) { - if (ElfLoader.ELF_NAME.equals(program.getExecutableFormat())) { - try { - File exePath = new File(program.getExecutablePath()); - return new ElfSectionProvider(exePath); - } - catch (IOException ioe) { - // ignore - } - } - return null; - } - - public ElfSectionProvider(File exeFile) throws IOException { - provider = new RandomAccessByteProvider(exeFile); - try { - // Parse the ELF header to get the sections - header = ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider); - header.parse(); - } - catch (ElfException e) { - provider.close(); - throw new IOException("Error parsing ELF", e); - } - } - - @Override - public ByteProvider getSectionAsByteProvider(String sectionName) throws IOException { - - ElfSectionHeader section = header.getSection("." + sectionName); - - return (section != null) ? new ByteProviderWrapper(section.getReader().getByteProvider(), - section.getOffset(), section.getSize()) : null; - } - - @Override - public void close() { - try { - provider.close(); - } - catch (IOException e) { - // ignore - } - } - - @Override - public boolean hasSection(String... sectionNames) { - for (String sectionName : sectionNames) { - if (header.getSection("." + sectionName) == null) { - return false; - } - } - return true; - } - -} From c545a6fb5a3a1cc1f1c090546d8e24e80363fc7f Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 23 Feb 2021 16:06:02 -0500 Subject: [PATCH 043/140] GP-710 Added register symbol processing to ELF PIC30 import processing. Improved code unit operand format to render memory register name when no reference is present. --- .../program/model/listing/CodeUnitFormat.java | 18 +++++++++++- .../format/elf/extend/PIC30_ElfExtension.java | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java index 2bf413cddd..4124eeec9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java @@ -493,7 +493,8 @@ public class CodeUnitFormat { InstructionScalarInfo info = new InstructionScalarInfo(representations, primaryRef); if (info.hasSingleAddressWithNoScalars()) { int addressIndex = info.getAddressIndex(); - return markupAddressAsScalar(inst, primaryRef, representations, addressIndex); + return markupAddressAsRegister(inst, primaryRef, representations, addressIndex) || + markupAddressAsScalar(inst, primaryRef, representations, addressIndex); } if (info.hasNoScalars()) { @@ -564,6 +565,21 @@ public class CodeUnitFormat { return primaryRef == null; } + private boolean markupAddressAsRegister(Instruction instr, Reference primaryRef, + List representationList, int addressIndex) { + if (primaryRef != null) { + return false; + } + // NOTE: although preferrable, access type/size is not considered + Address addr = (Address) representationList.get(addressIndex); + Register reg = instr.getProgram().getRegister(addr); + if (reg != null) { + representationList.set(addressIndex, reg.getName()); + return true; + } + return false; + } + private boolean markupAddressAsScalar(Instruction instr, Reference primaryRef, List representationList, int addressIndex) { Address addr = (Address) representationList.get(addressIndex); diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java index 8442870220..af2fae7d51 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java @@ -22,7 +22,9 @@ import ghidra.app.util.bin.format.elf.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Language; +import ghidra.program.model.lang.Register; import ghidra.util.exception.CancelledException; +import ghidra.util.exception.NoValueException; import ghidra.util.task.TaskMonitor; public class PIC30_ElfExtension extends ElfExtension { @@ -219,6 +221,32 @@ public class PIC30_ElfExtension extends ElfExtension { return language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace()); } + @Override + public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol) + throws NoValueException { + + if (elfSymbol.getValue() != 0 || !elfSymbol.isGlobal() || + elfSymbol.getSectionHeaderIndex() != 0) { + return null; + } + + String name = elfSymbol.getNameAsString(); + if (name == null) { + return null; + } + + if (name.startsWith("_")) { + name = name.substring(1); + } + + Register reg = elfLoadHelper.getProgram().getRegister(name); + if (reg != null && !reg.getAddress().isRegisterAddress()) { + return reg.getAddress(); // only consider memory-based registers + } + + return null; + } + private static class PIC30FilteredDataInputStream extends FilterInputStream { // BYTES: From 2425feefbc3f539405725d651a0ae35d7072c497 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 23 Feb 2021 16:44:01 -0500 Subject: [PATCH 044/140] GP-705 update regex comment --- .../app/util/demangler/gnu/GnuDemanglerParser.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java index 171b061ecf..5e6029eff8 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java @@ -243,15 +243,12 @@ public class GnuDemanglerParser { * Pattern: text for|to text * * Parts: - * -required text (capture group 2) - * --note: this uses '++', a possessive quantifier, to help keep the - * backtracking to a minimum - * -a space - * -'for' or 'to' (capture group 3) - * -a space + * -required text (capture group 2) -+ + * -'for' or 'to' (capture group 3) | (capture group 1) + * -a space -+ * -optional text (capture group 4) * - * Note: capture group 1 is the combination of groups 2 and 3 + * Note: capture group 1 is the combination of groups 2 and 3 with trailing space * * Examples: * construction vtable for From 2709d718c1f0667bbf990a52475653d62d99ffc8 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 24 Feb 2021 11:20:59 -0500 Subject: [PATCH 045/140] GP-716 - small file tweaks --- .../src/main/java/docking/menu/DockingCheckboxMenuItemUI.java | 1 - .../Docking/src/main/java/docking/menu/DockingMenuUI.java | 1 - 2 files changed, 2 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java index bbffa22fda..11b8ed0883 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java @@ -1,6 +1,5 @@ /* ### * 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. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java index 7a6a4589c0..d53eacd34b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java @@ -1,6 +1,5 @@ /* ### * 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. From 2a8afd529649bbe1bbf6dc929c83b15041e6548b Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 24 Feb 2021 14:14:04 -0500 Subject: [PATCH 046/140] GP-693: Additional improvements --- .../src/main/java/ghidra/server/ServerAdmin.java | 14 +++++++------- Ghidra/RuntimeScripts/Linux/server/svrAdmin | 2 +- Ghidra/RuntimeScripts/Linux/support/buildGhidraJar | 2 +- Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat | 1 - Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat | 2 +- .../Windows/support/buildGhidraJar.bat | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index 080cb3f25b..5905018f95 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -80,14 +80,13 @@ public class ServerAdmin implements GhidraLaunchable { * @param args command line arguments */ public void execute(String[] args) { - File serverDir = null; int ix = 0; String configFilePath = args.length != 0 && !args[0].startsWith("-") ? args[ix++] : System.getProperty(CONFIG_FILE_PROPERTY); - serverDir = getServerDirFromConfig(configFilePath); + File serverDir = getServerDirFromConfig(configFilePath); if (serverDir == null || (args.length - ix) == 0) { displayUsage(""); System.exit(-1); @@ -102,9 +101,7 @@ public class ServerAdmin implements GhidraLaunchable { System.exit(-1); } - if (propertyUsed) { - System.out.println("Using server directory: " + serverDir); - } + System.out.println("Using server directory: " + serverDir); File userFile = new File(serverDir, UserManager.USER_PASSWORD_FILE); if (!serverDir.isDirectory() || !userFile.isFile()) { @@ -421,6 +418,8 @@ public class ServerAdmin implements GhidraLaunchable { } private File getServerDirFromConfig(String configFilePath) { + System.out.println("Using config file: " + configFilePath); + if (configFilePath == null) { return null; } @@ -453,6 +452,7 @@ public class ServerAdmin implements GhidraLaunchable { String p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); if (p == null) { + System.out.println("Failed to find property: " + SERVER_DIR_CONFIG_PROPERTY); return null; } File dir = new File(p); @@ -478,8 +478,8 @@ public class ServerAdmin implements GhidraLaunchable { } String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY); System.err.println("Usage: " + - (invocationName != null ? invocationName : "java " + UserAdmin.class.getName()) + - (propertyUsed ? "" : " ") + " [] [] ..."); + (invocationName != null ? invocationName : "java " + ServerAdmin.class.getName()) + + (invocationName != null ? "" : " ") + " [] [] ..."); System.err.println("\nSupported commands:"); System.err.println(" -add [--p]"); System.err.println( diff --git a/Ghidra/RuntimeScripts/Linux/server/svrAdmin b/Ghidra/RuntimeScripts/Linux/server/svrAdmin index b9f40d12a4..deb47eec9d 100755 --- a/Ghidra/RuntimeScripts/Linux/server/svrAdmin +++ b/Ghidra/RuntimeScripts/Linux/server/svrAdmin @@ -45,7 +45,7 @@ fi OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')" if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then - VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") " + VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}")" "${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "${CONFIG}" "$@" else echo "Running svrAdmin with $SUDO as ${OWNER} ..." diff --git a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar index dbe6b52e02..c378218c75 100755 --- a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar +++ b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar @@ -25,7 +25,7 @@ if [ ! -d "${GHIDRA_ROOT_DIR}" ]; then fi # Set required VMARGS for jar builder application -APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}") " +APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}")" # Launch jar builder "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" Ghidra "${MAXMEM}" "${APP_VMARGS}" ghidra.util.GhidraJarBuilder -main ghidra.JarRun "$@" diff --git a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat index 0d8d500cb7..09a4979711 100644 --- a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat +++ b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat @@ -104,7 +104,6 @@ set ERROR=ERROR: JAVA_HOME is not set and no 'java' command could be found in yo goto reportError :findJavaFromJavaHome -set "JAVA_HOME=%JAVA_HOME:"=%" set "JAVA=%JAVA_HOME%\bin\java.exe" if exist "%JAVA%" goto lab2 diff --git a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat index c561b73062..1f8de1281e 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat @@ -43,6 +43,6 @@ set "CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf" :continue -set VMARGS=-DUserAdmin.invocation="%0" +set VMARGS=-DUserAdmin.invocation=%~n0 call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin "%CONFIG%" %* diff --git a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat index 3f2d19e94f..07f1c4dddc 100644 --- a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat +++ b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat @@ -18,6 +18,6 @@ exit /B 1 :continue -set APP_VMARGS=-DGhidraJarBuilder.Name=%0 +set APP_VMARGS=-DGhidraJarBuilder.Name=%~n0 call "%~dp0launch.bat" %LAUNCH_MODE% Ghidra "" "%APP_VMARGS%" ghidra.util.GhidraJarBuilder -main ghidra.JarRun %* From 650e65cdd5ae91ff78a15203bc41f84f4de23a8a Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Wed, 24 Feb 2021 20:56:09 +0000 Subject: [PATCH 047/140] GP-721_emteere added new define token endian attribute. Added Ghidra category on built plugin extension so it appears when users install --- .../ghidra.xtext.sleigh.feature/category.xml | 6 +++--- .../ghidra.xtext.sleigh.feature/feature.xml | 2 +- .../ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF | 2 +- .../ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF | 3 ++- .../ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF | 2 +- .../ghidra.xtext.sleigh/META-INF/MANIFEST.MF | 2 +- .../GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml | 6 +++++- .../src/ghidra/xtext/sleigh/Sleigh.xtext | 3 ++- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml index 21b6add2a1..5c9a401995 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml @@ -1,7 +1,7 @@ - - + + - + diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml index 65831c9255..16ffc71a33 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF index fffdce6b63..7760ce9751 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh.ide Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh.ide Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh.ide; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: ghidra.xtext.sleigh, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF index 94627e204e..d050e0d5b7 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Require-Bundle: ghidra.xtext.sleigh.ui, org.eclipse.xtext.junit4, org.eclipse.xtext.xbase.junit, org.eclipse.core.runtime, - org.eclipse.ui.workbench;resolution:=optional + org.eclipse.ui.workbench;resolution:=optional, + org.eclipse.xtext.ui.testing Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: ghidra.xtext.sleigh.ui.tests;x-internal=true diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF index 075e0e71af..7d5b41fd0d 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh.ui Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh.ui Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh.ui; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: ghidra.xtext.sleigh, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF index c982b203b5..4fa4632222 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.eclipse.xtext, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml index 26c699fb0e..242ae876f4 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml @@ -1,7 +1,11 @@ - + + + Date: Thu, 25 Feb 2021 11:07:35 -0500 Subject: [PATCH 048/140] GP-722 - updated error dialog to handle unchecked error text --- .../java/docking/DockingErrorDisplay.java | 37 +++++++++++++------ .../src/main/java/docking/ErrLogDialog.java | 15 +++++++- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java index 5647b31906..3fd195d9cc 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java @@ -18,6 +18,8 @@ package docking; import java.awt.Component; import java.awt.Window; +import org.apache.commons.text.WordUtils; + import docking.widgets.OkDialog; import docking.widgets.OptionDialog; import ghidra.util.*; @@ -26,11 +28,11 @@ import ghidra.util.exception.MultipleCauses; public class DockingErrorDisplay implements ErrorDisplay { /** - * Error dialog used to append exceptions. - * + * Error dialog used to append exceptions. + * *

While this dialog is showing all new exceptions will be added to the dialog. When - * this dialog is closed, this reference will be cleared. - * + * this dialog is closed, this reference will be cleared. + * *

Note: all use of this variable must be on the Swing thread to avoid thread * visibility issues. */ @@ -62,23 +64,34 @@ public class DockingErrorDisplay implements ErrorDisplay { Component parent, String title, Object message, Throwable throwable) { int dialogType = OptionDialog.PLAIN_MESSAGE; + String messageString = message != null ? message.toString() : null; - String rawMessage = HTMLUtilities.fromHTML(messageString); + if (messageString != null) { + // prevent excessive message degenerate cases + int maxChars = 1000; + String safeMessage = StringUtilities.trimMiddle(messageString, maxChars); + + // wrap any poorly formatted text that gets displayed in the label; 80-100 chars is + // a reasonable line length based on historical print margins + messageString = WordUtils.wrap(safeMessage, 100, null, true); + } + + String unformattedMessage = HTMLUtilities.fromHTML(messageString); switch (messageType) { case INFO: dialogType = OptionDialog.INFORMATION_MESSAGE; consoleDisplay.displayInfoMessage(errorLogger, originator, parent, title, - rawMessage); + unformattedMessage); break; case WARNING: case ALERT: dialogType = OptionDialog.WARNING_MESSAGE; consoleDisplay.displayWarningMessage(errorLogger, originator, parent, title, - rawMessage, throwable); + unformattedMessage, throwable); break; case ERROR: consoleDisplay.displayErrorMessage(errorLogger, originator, parent, title, - rawMessage, throwable); + unformattedMessage, throwable); dialogType = OptionDialog.ERROR_MESSAGE; break; } @@ -93,8 +106,8 @@ public class DockingErrorDisplay implements ErrorDisplay { return component; } - private void showDialog(final String title, final Throwable throwable, - final int dialogType, final String messageString, final Component parent) { + private void showDialog(final String title, final Throwable throwable, final int dialogType, + final String messageString, final Component parent) { Swing.runIfSwingOrRunLater(() -> { @@ -108,8 +121,8 @@ public class DockingErrorDisplay implements ErrorDisplay { }); } - private void showDialogOnSwing(String title, Throwable throwable, - int dialogType, String messageString, Component parent) { + private void showDialogOnSwing(String title, Throwable throwable, int dialogType, + String messageString, Component parent) { if (activeDialog != null) { activeDialog.addException(messageString, throwable); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java index 0f02fc7c40..3eaf3c950d 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java @@ -43,7 +43,7 @@ import ghidra.util.table.column.GColumnRenderer; import utilities.util.reflection.ReflectionUtilities; /** - * A dialog that takes error text and displays it with an option details button. If there is + * A dialog that takes error text and displays it with an option details button. If there is * an {@link ErrorReporter}, then a button is provided to report the error. */ public class ErrLogDialog extends AbstractErrDialog { @@ -149,7 +149,8 @@ public class ErrLogDialog extends AbstractErrDialog { introPanel.add( new GIconLabel(UIManager.getIcon("OptionPane.errorIcon"), SwingConstants.RIGHT), BorderLayout.WEST); - introPanel.add(new GHtmlLabel(HTMLUtilities.toHTML(message)) { + String html = HTMLUtilities.toHTML(message); + introPanel.add(new GHtmlLabel(html) { @Override public Dimension getPreferredSize() { // rendering HTML the label can expand larger than the screen; keep it reasonable @@ -387,6 +388,16 @@ public class ErrLogDialog extends AbstractErrDialog { textDetails.scrollToBottom(); } + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + + // Cap preferred width to something reasonable; most displays have more than 1000 width. + // Users can still resize as desired + size.width = Math.min(size.width, 1000); + return size; + } + void setError(ErrorEntry e) { error = e; setExceptionMessage(e.getDetailsText()); From db2cd6ba5ab96b6e9e855d41246c9c24b25aaabf Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Thu, 25 Feb 2021 13:52:02 -0500 Subject: [PATCH 049/140] GP-730 Fix SevenZipFileSystem to error correctly w/encrypted file --- .../ghidra/file/formats/sevenzip/SevenZipFileSystem.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java index 912f6b3088..ae4d47fdc9 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java @@ -15,9 +15,10 @@ */ package ghidra.file.formats.sevenzip; -import java.io.*; import java.util.*; +import java.io.*; + import org.apache.commons.io.FilenameUtils; import ghidra.formats.gfilesystem.*; @@ -261,6 +262,9 @@ public class SevenZipFileSystem implements GFileSystem { case UNKNOWN_OPERATION_RESULT: { throw new IOException("Unexpected: 7-Zip returned unknown operation result"); } + case WRONG_PASSWORD: { + throw new IOException("7-Zip wrong password"); + } case OK: default: { // it's all ok! From 04939dab09eca9a976a3a26b09a3f1519d022269 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 25 Feb 2021 14:09:07 -0500 Subject: [PATCH 050/140] GP-723 - Fixed bad parent of confirmation dialog --- .../ghidra/util/task/TaskMonitorComponent.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java index e18ec1a446..7fa2a23752 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java @@ -92,9 +92,9 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Constructor - * + * * @param includeTextField if true, the dialog can display a status progressMessage with progress details - * @param includeCancelButton if true, a cancel button will be displayed + * @param includeCancelButton if true, a cancel button will be displayed */ public TaskMonitorComponent(boolean includeTextField, boolean includeCancelButton) { updateProgressPanelRunnable = () -> updateProgressPanel(); @@ -106,7 +106,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { shouldCancelRunnable = () -> { int currentTaskID = taskID.get(); - boolean userSaysYes = OptionDialog.showYesNoDialog(TaskMonitorComponent.this, "Cancel?", + boolean userSaysYes = OptionDialog.showYesNoDialog(null, "Cancel?", "Do you really want to cancel " + getTaskName() + "?") == OptionDialog.OPTION_ONE; if (userSaysYes && currentTaskID == taskID.get()) { @@ -206,7 +206,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { // a chance to do so. In other words, the background thread will end up // blocking instead of working, which defeats our attempts to never show // a task dialog for fast background tasks. - // + // isIndeterminate.set(indeterminate); Swing.runIfSwingOrRunLater(() -> { boolean newValue = isIndeterminate.get(); @@ -269,7 +269,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Returns true if {@link #setIndeterminate(boolean)} with a value of true has * been called. - * + * * @return true if {@link #setIndeterminate(boolean)} with a value of true has * been called. */ @@ -280,7 +280,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set whether the progress bar should be visible - * + * * @param show true if the progress bar should be visible */ public synchronized void showProgress(boolean show) { @@ -293,7 +293,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set the name of the task; the name shows up in the tool tip for * the cancel button. - * + * * @param name the name of the task */ public void setTaskName(String name) { @@ -303,7 +303,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set the visibility of the cancel button - * + * * @param visible if true, show the cancel button; false otherwise */ public void setCancelButtonVisibility(boolean visible) { @@ -325,7 +325,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Sets the visibility of the progress icon - * + * * @param visible if true, display the progress icon */ public void showProgressIcon(boolean visible) { From ce910a111223a05ca684f3fee362b6ea5da00d6d Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 25 Feb 2021 19:04:33 -0500 Subject: [PATCH 051/140] Revert "GP-710 Added register symbol processing to ELF PIC30 import processing. Improved code unit operand format to render memory register name when no reference is present." This reverts commit c545a6fb5a3a1cc1f1c090546d8e24e80363fc7f. --- .../program/model/listing/CodeUnitFormat.java | 18 +----------- .../format/elf/extend/PIC30_ElfExtension.java | 28 ------------------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java index 4124eeec9a..2bf413cddd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java @@ -493,8 +493,7 @@ public class CodeUnitFormat { InstructionScalarInfo info = new InstructionScalarInfo(representations, primaryRef); if (info.hasSingleAddressWithNoScalars()) { int addressIndex = info.getAddressIndex(); - return markupAddressAsRegister(inst, primaryRef, representations, addressIndex) || - markupAddressAsScalar(inst, primaryRef, representations, addressIndex); + return markupAddressAsScalar(inst, primaryRef, representations, addressIndex); } if (info.hasNoScalars()) { @@ -565,21 +564,6 @@ public class CodeUnitFormat { return primaryRef == null; } - private boolean markupAddressAsRegister(Instruction instr, Reference primaryRef, - List representationList, int addressIndex) { - if (primaryRef != null) { - return false; - } - // NOTE: although preferrable, access type/size is not considered - Address addr = (Address) representationList.get(addressIndex); - Register reg = instr.getProgram().getRegister(addr); - if (reg != null) { - representationList.set(addressIndex, reg.getName()); - return true; - } - return false; - } - private boolean markupAddressAsScalar(Instruction instr, Reference primaryRef, List representationList, int addressIndex) { Address addr = (Address) representationList.get(addressIndex); diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java index af2fae7d51..8442870220 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java @@ -22,9 +22,7 @@ import ghidra.app.util.bin.format.elf.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Language; -import ghidra.program.model.lang.Register; import ghidra.util.exception.CancelledException; -import ghidra.util.exception.NoValueException; import ghidra.util.task.TaskMonitor; public class PIC30_ElfExtension extends ElfExtension { @@ -221,32 +219,6 @@ public class PIC30_ElfExtension extends ElfExtension { return language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace()); } - @Override - public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol) - throws NoValueException { - - if (elfSymbol.getValue() != 0 || !elfSymbol.isGlobal() || - elfSymbol.getSectionHeaderIndex() != 0) { - return null; - } - - String name = elfSymbol.getNameAsString(); - if (name == null) { - return null; - } - - if (name.startsWith("_")) { - name = name.substring(1); - } - - Register reg = elfLoadHelper.getProgram().getRegister(name); - if (reg != null && !reg.getAddress().isRegisterAddress()) { - return reg.getAddress(); // only consider memory-based registers - } - - return null; - } - private static class PIC30FilteredDataInputStream extends FilterInputStream { // BYTES: From cefc2e52ad74bc94784bd5325058edf88ac97f44 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 25 Feb 2021 19:05:05 -0500 Subject: [PATCH 052/140] Revert "GP-710 Added support for additional PIC30 ELF relocations (closes #2792)" This reverts commit 9c1fed6a133c3e2a39bf57e97d9f4c4c457d534b. --- .../elf/relocation/PIC30_ElfRelocationHandler.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java index 915ad21d31..6059bd0968 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java @@ -155,25 +155,15 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler { if (elf.e_machine() == ElfConstants.EM_DSPIC30F) { switch (type) { case R_PIC30_16: // 2 - case R_PIC30_FILE_REG_WORD: // 6 - newValue = (symbolValue + addend + oldShortValue); + newValue = (symbolValue + addend + oldShortValue) & 0xffff; memory.setShort(relocationAddress, (short) newValue); break; case R_PIC30_32: // 3 newValue = symbolValue + addend + oldValue; memory.setInt(relocationAddress, newValue); break; - case R_PIC30_FILE_REG_BYTE: // 4 short - case R_PIC30_FILE_REG: // 5 short - int reloc = symbolValue; - reloc += addend; - reloc += oldShortValue; - reloc &= 0x1fff; - newValue = reloc | (oldShortValue & ~0x1fff); - memory.setShort(relocationAddress, (short) newValue); - break; case R_PIC30_FILE_REG_WORD_WITH_DST: // 7 - reloc = symbolValue >> 1; + int reloc = symbolValue >> 1; reloc += addend; reloc += oldValue >> 4; reloc &= 0x7fff; From a60b89cd867df065357268b98e6b6b54dd364bad Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 23 Feb 2021 12:27:48 -0500 Subject: [PATCH 053/140] GP-710 Added support for additional PIC30 ELF relocations (closes #2792) --- .../elf/relocation/PIC30_ElfRelocationHandler.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java index 6059bd0968..915ad21d31 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/relocation/PIC30_ElfRelocationHandler.java @@ -155,15 +155,25 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler { if (elf.e_machine() == ElfConstants.EM_DSPIC30F) { switch (type) { case R_PIC30_16: // 2 - newValue = (symbolValue + addend + oldShortValue) & 0xffff; + case R_PIC30_FILE_REG_WORD: // 6 + newValue = (symbolValue + addend + oldShortValue); memory.setShort(relocationAddress, (short) newValue); break; case R_PIC30_32: // 3 newValue = symbolValue + addend + oldValue; memory.setInt(relocationAddress, newValue); break; + case R_PIC30_FILE_REG_BYTE: // 4 short + case R_PIC30_FILE_REG: // 5 short + int reloc = symbolValue; + reloc += addend; + reloc += oldShortValue; + reloc &= 0x1fff; + newValue = reloc | (oldShortValue & ~0x1fff); + memory.setShort(relocationAddress, (short) newValue); + break; case R_PIC30_FILE_REG_WORD_WITH_DST: // 7 - int reloc = symbolValue >> 1; + reloc = symbolValue >> 1; reloc += addend; reloc += oldValue >> 4; reloc &= 0x7fff; From bd8d076a55e79a198948d43bf16402ff294247c0 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 23 Feb 2021 16:06:02 -0500 Subject: [PATCH 054/140] GP-710 Added register symbol processing to ELF PIC30 import processing. Improved code unit operand format to render memory register name when no reference is present. --- .../program/model/listing/CodeUnitFormat.java | 18 +++++++++++- .../format/elf/extend/PIC30_ElfExtension.java | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java index 2bf413cddd..4124eeec9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java @@ -493,7 +493,8 @@ public class CodeUnitFormat { InstructionScalarInfo info = new InstructionScalarInfo(representations, primaryRef); if (info.hasSingleAddressWithNoScalars()) { int addressIndex = info.getAddressIndex(); - return markupAddressAsScalar(inst, primaryRef, representations, addressIndex); + return markupAddressAsRegister(inst, primaryRef, representations, addressIndex) || + markupAddressAsScalar(inst, primaryRef, representations, addressIndex); } if (info.hasNoScalars()) { @@ -564,6 +565,21 @@ public class CodeUnitFormat { return primaryRef == null; } + private boolean markupAddressAsRegister(Instruction instr, Reference primaryRef, + List representationList, int addressIndex) { + if (primaryRef != null) { + return false; + } + // NOTE: although preferrable, access type/size is not considered + Address addr = (Address) representationList.get(addressIndex); + Register reg = instr.getProgram().getRegister(addr); + if (reg != null) { + representationList.set(addressIndex, reg.getName()); + return true; + } + return false; + } + private boolean markupAddressAsScalar(Instruction instr, Reference primaryRef, List representationList, int addressIndex) { Address addr = (Address) representationList.get(addressIndex); diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java index 8442870220..af2fae7d51 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/util/bin/format/elf/extend/PIC30_ElfExtension.java @@ -22,7 +22,9 @@ import ghidra.app.util.bin.format.elf.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Language; +import ghidra.program.model.lang.Register; import ghidra.util.exception.CancelledException; +import ghidra.util.exception.NoValueException; import ghidra.util.task.TaskMonitor; public class PIC30_ElfExtension extends ElfExtension { @@ -219,6 +221,32 @@ public class PIC30_ElfExtension extends ElfExtension { return language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace()); } + @Override + public Address calculateSymbolAddress(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol) + throws NoValueException { + + if (elfSymbol.getValue() != 0 || !elfSymbol.isGlobal() || + elfSymbol.getSectionHeaderIndex() != 0) { + return null; + } + + String name = elfSymbol.getNameAsString(); + if (name == null) { + return null; + } + + if (name.startsWith("_")) { + name = name.substring(1); + } + + Register reg = elfLoadHelper.getProgram().getRegister(name); + if (reg != null && !reg.getAddress().isRegisterAddress()) { + return reg.getAddress(); // only consider memory-based registers + } + + return null; + } + private static class PIC30FilteredDataInputStream extends FilterInputStream { // BYTES: From c17448d2f2e5400b5c50dc04f29704a78c9f702b Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 25 Feb 2021 11:15:48 -0500 Subject: [PATCH 055/140] GP-66 - updated goto action to be disabled when there is no program --- .../navigation/GoToAddressLabelPlugin.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java index eef0b65f3c..b77dafd9f5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.KeyEvent; +import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; import ghidra.GhidraOptions; @@ -29,7 +30,7 @@ import ghidra.app.util.HelpTopics; import ghidra.app.util.navigation.GoToAddressLabelDialog; import ghidra.framework.options.*; import ghidra.framework.plugintool.*; -import ghidra.framework.plugintool.util.*; +import ghidra.framework.plugintool.util.PluginStatus; import ghidra.util.HelpLocation; import ghidra.util.bean.opteditor.OptionsVetoException; @@ -91,11 +92,21 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe public void actionPerformed(NavigatableActionContext context) { goToDialog.show(context.getNavigatable(), context.getAddress(), tool); } + + @Override + protected boolean isEnabledForContext(NavigatableActionContext context) { + return context.getProgram() != null; + } + + @Override + public boolean isAddToPopup(ActionContext context) { + return true; + } }; action.setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, action.getName())); - action.setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_NAVIGATION, "Go To..." }, null, "GoTo", - MenuData.NO_MNEMONIC, "2")); // second item in the menu + action.setMenuBarData( + new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Go To..." }, null, "GoTo", + MenuData.NO_MNEMONIC, "2")); // second item in the menu action.setKeyBindingData(new KeyBindingData(KeyEvent.VK_G, 0)); @@ -144,10 +155,11 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe * @param newValue new value of the option */ @Override - public void optionsChanged(ToolOptions options, String opName, Object oldValue, Object newValue) { + public void optionsChanged(ToolOptions options, String opName, Object oldValue, + Object newValue) { if (opName.equals(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES)) { maximumGotoEntries = - options.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); + options.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); if (maximumGotoEntries <= 0) { throw new OptionsVetoException("Search limit must be greater than 0"); } @@ -155,7 +167,7 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe } else if (opName.equals(GhidraOptions.OPTION_NUMERIC_FORMATTING)) { cStyleInput = - options.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); + options.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); goToDialog.setCStyleInput(cStyleInput); } else if (opName.equals(GO_TO_MEMORY)) { @@ -182,20 +194,20 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe ToolOptions opt = tool.getOptions(ToolConstants.TOOL_OPTIONS); // descriptions opt.registerOption(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE, null, - "Interpret value entered in the Go To dialog as either hex, " - + "octal, or binary number."); + "Interpret value entered in the Go To dialog as either hex, " + + "octal, or binary number."); opt.registerOption(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES, null, - "Max number of entries remembered in the go to list."); + "Max number of entries remembered in the go to list."); opt.registerOption(GO_TO_MEMORY, DEFAULT_MEMORY, null, - "Remember the last successful go to input in the " - + "Go To dialog. If this option is enabled, then the " - + "Go To dialog will leave the last " - + "successful go to input in the combo box of the Go " - + "To dialog and will select the " + "value for easy paste replacement."); + "Remember the last successful go to input in the " + + "Go To dialog. If this option is enabled, then the " + + "Go To dialog will leave the last " + + "successful go to input in the combo box of the Go " + + "To dialog and will select the " + "value for easy paste replacement."); // options maximumGotoEntries = - opt.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); + opt.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); cStyleInput = opt.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); goToDialog.setCStyleInput(cStyleInput); From 0d51f0f03e00397630e17b538543a3472dce0957 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 26 Feb 2021 08:29:15 -0500 Subject: [PATCH 056/140] GP-731: Certify --- .../Base/src/main/java/ghidra/util/state/VarnodeOperation.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java index df53f942cf..33872f6f17 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java @@ -1,6 +1,5 @@ /* ### * 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. From 79d437f66da9980febb4325f6fc31219c45cc3e4 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:54:34 -0500 Subject: [PATCH 057/140] GP-734 - Fixed graph-related stack trace --- .../java/ghidra/graph/viewer/popup/PopupRegulator.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java index 50445c0f64..1a004061c8 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java @@ -15,6 +15,7 @@ */ package ghidra.graph.viewer.popup; +import java.awt.Component; import java.awt.Window; import java.awt.event.*; @@ -129,6 +130,13 @@ public class PopupRegulator { return; } + Component c = event.getComponent(); + if (!c.isShowing()) { + // This method is called from a a timer. It is possible that the graph has been + // closed by the time this method is called. + return; + } + ToolTipInfo toolTipInfo = popupSource.getToolTipInfo(event); JComponent toolTipComponent = toolTipInfo.getToolTipComponent(); boolean isCustomJavaTooltip = !(toolTipComponent instanceof JToolTip); From 384240834b1ec252d3298b072b52458f6408ca90 Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Tue, 23 Feb 2021 17:05:12 -0500 Subject: [PATCH 058/140] Ghidra 9.2.3 Release Notes --- .../src/global/docs/ChangeHistory.html | 210 +++++++++++------- 1 file changed, 126 insertions(+), 84 deletions(-) diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html index aabe465742..9eb2c389c2 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html @@ -6,14 +6,60 @@ +

Ghidra 9.2.3 Change History (March 2021)

+

Improvements

+
    +
  • Analysis. Added check for vftable entries in .NEP section and relaxed the requirement that the code must have a return. (GP-649)
  • +
  • Analysis. Corrected flaw in RTTI analyzer determination of size of vftables. (GP-688)
  • +
  • Basic Infrastructure. Updated TLS protocol preference to use the most preferred/recent version available to both sides of an SSL connection (e.g., TLSv1.3) instead of forcing use of TLSv1.2. (GP-622)
  • +
  • Build. Corrected build issues which had prevented users from building Ghidra on an Apple M1 (OS X, AARCH64 architecture). (GP-600, Issue #2653)
  • +
  • Demangler. Increased Gnu Demangler parsing performance by changing some regular expressions. (GP-705)
  • +
  • Eclipse Integration. Updated SleighEditor to support new endian tag on define token definitions. (GP-721)
  • +
  • GUI. Updated the Choose Data Type dialog to apply data types in the same manner as dragging types from the Data Types window. This provides users more control when choosing how to overwrite existing types. (GP-521)
  • +
  • Importer:ELF. Added support for ELF relocation R_X86_64_IRELATIVE. (GP-651, Issue #1189)
  • +
  • Importer:ELF. Sped up loading of ELF files with large symbol tables. (GP-697)
  • +
+
+

Bugs

+
    +
  • Analysis. The RTTI analyzer now runs prior to Reference analysis so that references into vftables are not turned into code or data before the vftables are created. (GP-517)
  • +
  • API. Funtion.getCalledFunctions(TaskMonitor) and Function.getCallingFunctions(TaskMonitor) now support passing null for the task monitor parameter, which previously would have thrown an exception. (GP-589, Issue #2643)
  • +
  • Data Types. Corrected segmented 32-bit pointer datatype address generation for 16:16 x86 far pointers. (GP-534, Issue #2548)
  • +
  • Decompiler. Fixed Decompiler issue where, when a function name extends beyond the line limit, an end-of-line comment could wrap around to additional lines without including additional // comment indicators. (GP-473)
  • +
  • Decompiler. Corrected an exception that could occur when attempting to edit function signature from the Decompiler. (GP-597, Issue #2601)
  • +
  • Eclipse Integration. When installing the SleighEditor into Eclipse, the plugin will now show up under the Ghidra category. Previously the Group Items by Category option had to be turned off before the SleighEditor would appear as a visible entry. (GP-564)
  • +
  • Eclipse Integration. Fixed an issue with Eclipse PyDev breakpoints not catching. (GP-668, Issue #2713)
  • +
  • Eclipse Integration. Fixed an Eclipse GhidraDev exception that occurred when creating a new Ghidra scripting project if a ~/ghidra_scripts directory did not exist. (GP-669)
  • +
  • Emulator. Replaced Java floating point emulation to fix multiple rounding issues. (GP-357, Issue #2414)
  • +
  • Graphing. Fixed issue with graph filters not updating satellite view when changing edge filters. (GP-557)
  • +
  • Graphing. Fixed Function Graph keybindings that did not work when docked in the main Code Browser window. (GP-586, Issue #2641)
  • +
  • GUI. Fixed NPE due to using Go To action when there was no open program in the Listing. (GP-66)
  • +
  • GUI. Fixed bug in Reference Code Viewer options that caused an exception. (GP-620, Issue #2672)
  • +
  • Importer. Fixed exception caused when importing previously exported XML data where the bookmark override option was turned off. (GP-667)
  • +
  • Importer:ELF. Fixed a NullPointerException caused by importing an ELF with an uninitialized .got section. (GP-360, Issue #2416)
  • +
  • Importer:ELF. Added Support for ELF R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS ELF Relocations for ARM. (GP-555, Issue #2510)
  • +
  • Importer:ELF. Corrected ELF processing of .init_array and .fini_array which was incorrectly overadjusting entries for an image base change. (GP-699)
  • +
  • Importer:Mach-O. Corrected Mach-O fat-binary library import issue and resolved error related to unnamed Mach-O segment. (GP-652, Issue #2702)
  • +
  • Importer:Mach-O. Fixed an issue with DYLD Load Command data structures being created in the wrong locations. (GP-689, Issue #2624)
  • +
  • Importer:Mach-O. Fixed an exception that occurred when importing Mach-O files that define zero LC_BUILD_VERSION tool entries. (GP-702, Issue #2192)
  • +
  • PDB. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)
  • +
  • Processors. Added missing RFE instruction in MIPS up to version R3000. (GP-33, Issue #1766)
  • +
  • Processors. ARM instruction VMUL now decodes correctly. (GP-627, Issue #2677)
  • +
  • Processors. Added missing CFINV instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)
  • +
  • Scripting. Fixed analyzeHeadless -scriptPath option that didn't work for Python and other non-Java scripts located in non-default directories. (GP-528, Issue #2561)
  • +
  • Scripting. Fixed concurrency issue with management of scripting bundle paths. (GP-576)
  • +
  • Scripting. Corrected handling for Ghidra Script files which are symlinks that were broken in Ghidra 9.2. (GP-650, Issue #2698)
  • +
+
+

Ghidra 9.2.2 Change History (December 2020)

Bugs

  • Graphing. Fixed issue with Graph filters not working and satellite view sometimes not matching graph. (GP-526)
  • -
  • Importer:MachO. MachO DYLD cache incorrect offset use has been fixed. (GP-550, Issue ##2560)
  • -
  • Listing. Fixed issue where Edit Label action (L key) did not work on primary function symbols. (GP-537)
  • +
  • Importer:Mach-O. Mach-O DYLD cache incorrect offset use has been fixed. (GP-550, Issue #2560)
  • +
  • Listing. Fixed issue where Edit Label action (L key) did not work on primary function symbols. (GP-537)
  • Multi-User. Corrected Ghidra Server build issue for version 9.2.1 which had an improperly generated classpath.frag file. Issue caused server to fail startup with a ClassNotFoundException. (GP-542)
  • -
  • Processors. The V850 JMP instruction has been corrected not to use the PC in the address calculation (GP-548, Issue #2570)
  • +
  • Processors. The V850 JMP instruction has been corrected not to use the PC in the address calculation. (GP-548, Issue #2570)
  • Processors. Removed erroneous VST4 variant, most likely from a copy/paste error. This fixes the ARM Thumb BL instruction disassembly with a negative offset. (GP-549, Issue #2559)
@@ -24,6 +70,7 @@
  • Analysis. Updated RTTI analyzer to find type_info vftable when it cannot be found with its mangled name. This will enable many more Windows programs to have their RTTI structures created that were unable to be parsed in previous Ghidra versions. (GP-141)
  • API. Relaxed memory block naming restrictions and restored ability to have spaces in memory block names. However, if a memory block is flagged as an overlay, the associated overlay space name may be modified to ensure validity and uniqueness. The DuplicateNameException has been removed from all memory block API methods since this was entirely an overlay space concern. Memory block GUI has also been changed eliminate the duplicate block name restriction. (GP-420, Issue #2465)
  • Build. Eliminated the need for installation of bison and flex when performing source-based gradle build of Ghidra or the Decompiler module. The generated files are now included with source files and maintained in source control. A separate gradle Decompiler:generateParsers task, which still requires bison and flex, must be used, explicitly, when changes are made to lex/yacc source files. (GP-467)
  • +
  • Graphing. Fixed issue with exporting graphs to DOT format due to invalid vertex IDs. (GP-280)
  • Graphing. Improved graphing where it did not navigate when clicking on external function nodes. Now it will navigate to the fake function location in the program, which is the location of the pointer to the external function. (GP-493)
  • Listing:Symbols. Removed restriction for naming labels that resemble default label names. (GT-3185, Issue #1057)
  • PDB. Crafted PDB type ID records 0x1608 and 0x1609 with presumed class and struct types and follow-on application of these types. Also fixed up some fall-back data type logic and improved some warning messages to reflect the cause of the conditions. (GP-474, Issue #2523)
  • @@ -37,7 +84,7 @@
  • Decompiler. Fixed issue with the Auto Create/Fill Structure command that caused it to silently miss some pointer accesses. (GP-344)
  • Decompiler. Jump table recovery now takes into account encoded bits, like ARM/THUMB mode transition, that may be present in address tables. (GP-387, Issue #2420)
  • Decompiler. Fixed a bug in the Decompiler renaming action when applied to function references. (GP-477, Issue #2415)
  • -
  • Decompiler. Corrected 8-byte return value storage specification in compiler-spec affecting longlong and double return values. Endianess ordering of r0/r1 was incorrect. (GP-512, Issue #2547)
  • +
  • Decompiler. Corrected 8-byte return value storage specification in compiler-spec affecting longlong and double return values. Endianess ordering of r0/r1 was incorrect. (GP-512, Issue #2547)
  • Graphing. Fixed the Function Graph's drag-to-select-nodes feature. (GP-430)
  • Graphing. Fixed issue where the graph in the satellite view is sometimes truncated. (GP-469)
  • Graphing. Fixed a stack trace issue caused by reusing a graph display window to show a graph that is larger than is allowed. (GP-492)
  • @@ -126,7 +173,7 @@
  • Importer:ELF. Added support for processing Android packed ELF Relocation Tables. (GT-3320, Issue #1192)
  • Importer:ELF. Added ELF import opinion for ARM BE8. (GT-3642, Issue #1187)
  • Importer:ELF. Added support for ELF RELR relocations, such as those produced for Android. (GP-348)
  • -
  • Importer:MachO. DYLD Loader can now load x86_64 DYLD from macOS. (GT-3611, Issue #1566)
  • +
  • Importer:Mach-O. DYLD Loader can now load x86_64 DYLD from macOS. (GT-3611, Issue #1566)
  • Importer:PE. Improved parsing of Microsoft ordinal map files produced with DUMPBIN /EXPORTS (see Ghidra/Features/Base/data/symbols/README.txt). (GT-3235)
  • Jython. Upgraded Jython to version 2.7.2. (GP-109)
  • Listing. In the PCode field of the Listing, accesses of varnodes in the unique space are now always shown with the size of the access. Fixed bug which would cause the PCode emulator to reject valid pcode in rare instances. (GP-196)
  • @@ -282,8 +329,8 @@
  • Disassembly. Corrected potential infinite loop with disassembler caused by branch to self with invalid delay slot instruction. (GT-3511, Issue #1486)
  • GUI. Corrected processor manual display for Microsoft Windows users, which was not displaying processor manual and was, instead, rendering a blank page in web browser. (GT-3444)
  • GUI:Bitfield Editor. Added field comment support to composite bitfield editor. (GT-3410)
  • -
  • Importer:MachO. A MachO loader regression, in Ghidra 9.1.1, when laying down symbols at the correct location, has been fixed. (GT-3487, Issue #1446)
  • -
  • Multi-User:Ghidra Server. Corrected Ghidra Server remote interface errors that occur when running with Java 11.0.6 (and later) release, which would throw RemoteException "Method is not Remote" errors. (GT-3521, Issue #1440)
  • +
  • Importer:Mach-O. A Mach-O loader regression, in Ghidra 9.1.1, when laying down symbols at the correct location, has been fixed. (GT-3487, Issue #1446)
  • +
  • Multi-User:Ghidra Server. Corrected Ghidra Server remote interface errors that occur when running with Java 11.0.6 (and later) release, which would throw RemoteException Method is not Remote errors. (GT-3521, Issue #1440)
  • PDB. Corrected PDB XML generation for zero-length classes and structures and resolved various datatype dependency issues encountered during PDB Analysis. Changed line numbers from hex to decimal. (GT-3462, Issue #1410)
  • Processors. Corrected mnemonic for ARM thumb RSB.w instruction. (GT-3420, Issue #1365)
  • Processors. Corrected issue in M68000 with some move instructions not creating correct array assignments. (GT-3429, Issue #1394)
  • @@ -294,7 +341,7 @@

    Ghidra 9.1.1 Change History (December 2019)

    Improvements

      -
    • Importer:MachO. Improved import/load time of DYLD shared cache files. (GT-3261)
    • +
    • Importer:Mach-O. Improved import/load time of DYLD shared cache files. (GT-3261)
    • Program API. Cached the addresses that correspond to executable memory to improve analysis performance. (GT-3260)
    @@ -331,7 +378,7 @@
  • Eclipse Integration. Added new GhidraSleighEditor Eclipse plugin in the installation directory under Extensions/Eclipse. (GT-113)
  • GUI. Added method for turning off table sorting by control-clicking the only sorted table column. (GT-2763, Issue #87)
  • GUI. Hovering on an address will now show where the byte at that address came from in the imported file. (GT-3016, Issue #154)
  • -
  • Importer:MachO. Added new importer/loader for DYLD-shared cache files. (GT-2343)
  • +
  • Importer:Mach-O. Added new importer/loader for DYLD-shared cache files. (GT-2343)
  • Memory. Added new API to preserve imported program's original bytes and how they map to memory blocks. (GT-2845)
  • Processors. Implemented Intel MCS-96 processor module. (GT-2350)
  • Processors. Added SH1/2/2a sleigh processor specification. (GT-3029, Issue #715)
  • @@ -488,7 +535,7 @@
  • Listing. Cursor in the listing now stays in the proper column after editing a field. (GT-3045, Issue #702)
  • Listing. Fixed a problem with register highlighting that could occur on certain register/sub-register combinations. (GT-3071, Issue #810)
  • Multi-User. Corrected terminate checkout from viewed checkout list which was always terminating first row range based upon number of selected rows and not the actual selected rows. (GT-2903)
  • -
  • Multi-user. Corrected ability for user to cancel checkin/checkout to Ghidra Server. (GT-3208)
  • +
  • Multi-User. Corrected ability for user to cancel checkin/checkout to Ghidra Server. (GT-3208)
  • Multi-User:Ghidra Server. Added proper Ghidra Server interface binding with new -i option. Corrected -ip option to strictly convey remote access hostname to clients. The updated server will only accept connections from Ghidra 9.1 and later clients due to the registry port now employing TLS. (GT-2685, Issue #101, #645)
  • Multi-User:Ghidra Server. Fixed argument-passing bug in svrAdmin script. (GT-3082, Issue #907)
  • Multi-User:Merge. Corrected merge problem affecting modified Function Definition datatypes which could result in a NullPointerException. (GT-2922)
  • @@ -518,7 +565,7 @@
  • Program API. Corrected parameter storage which failed to properly refresh after undo/redo. (GT-3130, Issue #960)
  • Program API. Corrected function parameter ordinal numbering when more than one auto-parameter is present. (GT-3214)
  • Project Manager. Fixed a problem with creating Ghidra projects in Windows root directories (e.g., Z:\). (GT-2585)
  • -
  • Project Manager. Fixed a path traversal vulnerability that could occur when restoring a malicious project archive. (GT-3001, Issue #789)
  • +
  • Project Manager. Fixed a path-traversal vulnerability that could occur when restoring a malicious project archive. (GT-3001, Issue #789)
  • Scripting. GhidraScript.askDomainFile() now correctly throws a CancelledException when the cancel button is clicked. (GT-2841)
  • Scripting. Removed deprecated scripting methods older than 5 releases. (GT-2949)
  • Security. Removed use of nonsecure XMLEncoder/XMLDecoder from Ghidra code base. (GT-3198, Issue #1090)
  • @@ -531,128 +578,123 @@

    Ghidra 9.0.4 Change History (May 2019)

    Bugs

      -
    • Multi-User:Ghidra Server. Corrected severe script error in svrAdmin.bat introduced with 9.0.3 build.
    • -
    • GUI. Restored the default 'p' key binding for creating pointers within the listing display.
    • +
    • Multi-User:Ghidra Server. Corrected severe script error in svrAdmin.bat introduced with 9.0.3 build. (GT-2874)
    • +
    • GUI. Restored the default 'p' key binding for creating pointers within the listing display. (GT-2854)

    Ghidra 9.0.3 Change History (April 2019)

    New Features

      -
    • GUI. Function tags are now viewable from Functions Window table using new column.
    • +
    • GUI. Function tags are now viewable from Functions Window table using new column. (GT-2114)

    Improvements

      -
    • Decompiler. Improved modeling of CFG on Windows 10. (Issue #340)
    • -
    • Patcher. Renamed patch directory to /Ghidra/patch and added README.txt that explains how the patch directory is used.
    • -
    • Search. Updated the Decompiler Data Type Finder to find references to inside of nested array access in a line of Decompiler C output. (Issue #416)
    • -
    • Sleigh. Improved error reporting for SLEIGH compiler. (Issue #364)
    • +
    • Decompiler. Improved modeling of CFG on Windows 10. (GT-2755, Issue #340)
    • +
    • Patcher. Renamed patch directory to /Ghidra/patch and added README.txt that explains how the patch directory is used. (GT-2734)
    • +
    • Search. Updated the Decompiler Data Type Finder to find references inside of nested array access in a line of Decompiler C output. (GT-2756, Issue #416)
    • +
    • Sleigh. Improved error reporting for SLEIGH compiler. (GT-2820, Issue #364)

    Bugs

      -
    • Analysis. Code that checks for thunks no longer throws an exception if the PC is not set for the processor.
    • -
    • Analysis. Made a fix to enable Apply button when changing tool options. (Issue #40)
    • -
    • Data Types. Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed.
    • -
    • Decompiler. Fixed dynamic variables and equates in 16-bit x86 programs. (Issue #336)
    • -
    • Decompiler:Java. Fixed DEX decompilation regression issue. (Issue #350)
    • -
    • Eclipse Integration. Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (Issues #283, #383)
    • +
    • Analysis. Code that checks for thunks no longer throws an exception if the PC is not set for the processor. (GT-2730)
    • +
    • Analysis. Made a fix to enable Apply button when changing tool options. (GT-2801, Issue #40)
    • +
    • Data Types. Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed. (GT-2736)
    • +
    • Decompiler. Fixed dynamic variables and equates in 16-bit x86 programs. (GT-2745, Issue #336)
    • +
    • Decompiler:Java. Fixed DEX decompilation regression issue. (Issue #350, GT-2743)
    • +
    • Eclipse Integration. Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (GT-2721, Issues #283, #383)
    • GUI. Improved documentation on how to deal with HiDPI monitor issues in Linux. In the <ghidra_installation>/support/launch.properties file, change VMARGS=-Dsun.java2d.xrender from false to true.
    • -
    • Importer. Fixed an exception that occurred when batch importing APK files. (Issue #426)
    • -
    • Multi-User:Ghidra Server. Restored ability to execute svrAdmin script in development mode.
    • -
    • Processors. The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (Issue #201)
    • -
    • Processors. The 68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (Issue #227)
    • -
    • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (Issue #407)
    • +
    • Importer. Fixed an exception that occurred when batch importing APK files. (GT-2767, Issue #426)
    • +
    • Multi-User:Ghidra Server. Restored ability to execute svrAdmin script in development mode. (GT-2740)
    • +
    • Processors. The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (GT-2759, Issue #201)
    • +
    • Processors. The M68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (GT-2807, Issue #227)
    • +
    • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (GT-2754. Issue #407)

    Ghidra 9.0.2 Change History (April 2019)

    Bugs

      -
    • Analysis. Constant reference analysis boundary controls for speculative references has been fixed. Speculative references are references created from computed constants passed as parameters, stored to a location, or from indexed offsets from a register. (Issue #228)
    • -
    • Decompiler. Fixed rendering bug in the Decompiler when the "Find" dialog is closed. (Issue #282)
    • -
    • Decompiler. Fixed decompiler handling of Function Definition data types. (Issue #247)
    • -
    • Decompiler. Fixed "Free Varnode" exception in RuleConditionalMove. (Issue #294)
    • -
    • Diff. Fixed exceptions that can occur in the Diff View for programs with overlays.
    • -
    • Documentation. Corrected the spelling of "listener" throughout the source code. (Issue #235)
    • -
    • Exporter. Exporting a selection as Intel Hex will now allow a selection of any length. Previously this was restricted to multiples of 16 bytes. (Issue #260)
    • -
    • GUI. Fixed exception that occurs after disabling MyProgramChangesDisplayPlugin.
    • -
    • GUI. Updated the "Open Program" dialog to disallow file drop operations. (Issue #252) -
    • Multi-User:Ghidra Server. Corrected bug introduced into ghidraSvr.bat which could prevent Ghidra Server startup (Issue #279)
    • -
    • Processors. The ARM Thumb CMP.W and LSL instructions have been changed to correctly decode. There are still issues to work out with Unpredictable execution when Rd is the PC. (Issue #280)
    • -
    • Scripting. MultiInstructionMemReference script has been corrected to consider input and output registers when placing a reference on an instruction.
    • +
    • Analysis. Constant reference analysis boundary controls for speculative references has been fixed. Speculative references are references created from computed constants passed as parameters, stored to a location, or from indexed offsets from a register. (GT-2723, Issue #228)
    • +
    • Decompiler. Fixed Decompiler handling of Function Definition data types. (GT-2704, Issue #247)
    • +
    • Decompiler. Fixed rendering bug in the Decompiler when the "Find" dialog is closed. (GT-2716, Issue #282)
    • +
    • Decompiler. Fixed "Free Varnode" exception in RuleConditionalMove. (GT-2726, Issue #294)
    • +
    • Diff. Fixed exceptions that can occur in the Diff View for programs with overlays. (GT-2706)
    • +
    • Documentation. Corrected the spelling of "listener" throughout the source code. (GT-2702, Issue #235)
    • +
    • Exporter. Exporting a selection as Intel Hex will now allow a selection of any length. Previously this was restricted to multiples of 16 bytes. (GT-2703, Issue #260)
    • +
    • GUI. Fixed exception that occurs after disabling MyProgramChangesDisplayPlugin. (GT-2712)
    • +
    • GUI. Updated the "Open Program" dialog to disallow file drop operations. (GT-2705, Issue #252)
    • +
    • Multi-User:Ghidra Server. Corrected bug introduced into ghidraSvr.bat which could prevent Ghidra Server startup. (GT-2717, Issue #279)
    • +
    • Processors. The ARM Thumb CMP.W and LSL instructions have been changed to correctly decode. There are still issues to work out with Unpredictable execution when Rd is the PC. (GT-2722, Issue #280)
    • +
    • Scripting. MultiInstructionMemReference script has been corrected to consider input and output registers when placing a reference on an instruction. (GT-2723)

    Security

      -
    • Basic Infrastructure. Added a property to support/launch.properties to prevent log4j from using jansi.dll on Windows. (Issue #286)
    • +
    • Basic Infrastructure. Added a property to support/launch.properties to prevent log4j from using jansi.dll on Windows. (GT-2725, Issue #286)

    Ghidra 9.0.1 Change History (March 2019)

    New Features

      -
    • Scripting. Created a script to show all equates within the current selection. (Issue #111)
    • +
    • Scripting. Created ShowEquatesInSelectionScript to show all equates within the current selection. (GT-2651, Issue #111)

    Improvements

      -
    • Basic Infrastructure. Updated commons-compress library to version 1.18. (Issue #171)
    • -
    • Eclipse Integration. Ghidra now connects to the Eclipse GhidraDev plugin on 127.0.0.1 rather than localhost.
    • -
    • GUI. Turned on font anti-aliasing by default for Linux. (Issue #212)
    • -
    • GUI. Fixed Options Dialog slow scrolling speed. (Issue #27)
    • -
    • Importer:ELF. Corrected bug in ELF loader which can improperly process the GOT, PLT and relocations - when multiple symbol tables exist within the ELF binary. (Issue #52)
    • -
    • Multi-User:Ghidra Server. Corrected the Ghidra Server service wrapper (YAJSW) configuration for - Mac OS X to prevent a startup timeout condition which could occur.
    • -
    • Processors. Added ARM/Thumb SRS instruction decodes for undefined modes. (Issue #216)
    • +
    • Basic Infrastructure. Updated commons-compress library to version 1.18. (GT-2657, Issue #171)
    • +
    • Eclipse Integration. Ghidra now connects to the Eclipse GhidraDev plugin on 127.0.0.1 rather than localhost. (GT-2691)
    • +
    • GUI. Turned on font anti-aliasing by default for Linux. (GT-2674, Issue #212)
    • +
    • GUI. Fixed Options Dialog slow scrolling speed. (GT-2679, Issue #27)
    • +
    • Importer:ELF. Corrected bug in ELF loader which can improperly process the GOT, PLT and relocations when multiple symbol tables exist within the ELF binary. (GT-2646, Issue #52)
    • +
    • Multi-User:Ghidra Server. Corrected the Ghidra Server service wrapper (YAJSW) configuration for Mac OS X to prevent a startup timeout condition which could occur. (GT-2637)
    • +
    • Processors. Added ARM/Thumb SRS instruction decodes for undefined modes. (GT-2676, Issue #216)

    Bugs

      -
    • API. Fixed equals method on Varnode class. (Issue #97)
    • -
    • API. Fixed a bug in MaskImpl.comlementMask(). (Issue #187)
    • -
    • Basic Infrastructure. Fixed special character handling in idaxml.py. (Issue #75)
    • -
    • Basic Infrastructure. Ghidra now forces the locale to en_US by default. Only the en_US is currently supported. - This fixes certain unexpected exceptions. (Issue #209)
    • -
    • Diff. Fixed exceptions occasionally encountered when starting a Diff session. (Issue #211)
    • -
    • Documentation. Fixed javadoc search box redirecting to broken links. (Issue #129)
    • -
    • Function Graph. Fixed Function Graph exception when generating tooltip. (Issue #65)
    • -
    • GUI. Updated window placement to keep windows on screen. (Issue #41)
    • -
    • GUI. Add/Edit References dialog now restricts users to creating refs in valid memory address spaces.
    • -
    • GUI. Fixed exception when exiting Ghidra while a table is being edited. (Issue #51)
    • -
    • GUI. Fixed some touchpad scrolling issues. (Issue #2)
    • -
    • GUI. Fixed stack trace in the Data Type Manager's tooltip generation. (Issue #133)
    • -
    • GUI. User key binding settings for the Recently Used and Define Pointer actions no longer lost after re-launching tool. (Issue #152)
    • -
    • GUI. Toolbar buttons now respond to fast clicking.
    • -
    • Importer:MachO. The MachoLoader can now find import libraries found in Universal Binary files. (Issue #136)
    • -
    • Importer:PE. The PeLoader now correctly parses the GuardCFFunctionTable when entries are more than 4 bytes each. (Issue #220)
    • -
    • Multi-User:Ghidra Server. Removed support for native OS authentication from Ghidra Server (removed modes -a2 and -a3) - due to incompatibility with newer OS releases including Windows 10 and Windows Server 2016. Re-introduction of this will be - considered for a future release.
    • -
    • PDB. Corrected NPE error when processing PDB files. (Issues #138, #188)
    • -
    • Processors. Added missing PowerPC VLE conditional branch instructions: e_bdnz and e_bdz. (Issue #103)
    • -
    • Processors. Fixed instruction semantics for several instructions and added Control Flow Enforcement, NOP variants, CMP variants, UD1, and - prefixed call instructions to X86 processor specification. (Issues #22, #53, #158, #157)
    • -
    • Processors. The 68000 MOVE instruction now correctly sets the CF and VF flags. (Issue #163)
    • -
    • Processors. Added four missing MOVEM instruction variants to the 68000 processor. (Issue #219)
    • -
    • Processors. An incorrect usage of X instead of Y in indexed mode for the 6502 has been corrected.(Issue #201)
    • -
    • Processors. Added support for ARM Thumb half BL instruction on processor variants prior to v6. (Issue #39)
    • -
    • Scripting. Fixed a bug in ImportSymbolsScript.py that prevented it from running. (Issue #170)
    • +
    • API. Fixed equals method on Varnode class. (GT-2648, Issue #97)
    • +
    • API. Fixed a bug in MaskImpl.complementMask(). (GT-2694, Issue #187)
    • +
    • Basic Infrastructure. Fixed special character handling in idaxml.py. (GT-2669, Issue #75)
    • +
    • Basic Infrastructure. Ghidra now forces the locale to en_US by default. Only the en_US is currently supported. This fixes certain unexpected exceptions. (GT-2680, Issue #209)
    • +
    • Diff. Fixed exception occasionally encountered when starting a Diff session. (GT-2672, Issue #211)
    • +
    • Documentation. Fixed javadoc search box redirecting to broken links. (GT-2655, Issue #129)
    • +
    • Function Graph. Fixed Function Graph exception when generating tooltip. (GT-2650, Issue #65)
    • +
    • GUI. Updated window placement to keep windows on screen. (GT-1516, Issue #41)
    • +
    • GUI. Add/Edit References dialog now restricts users to creating refs in valid memory address spaces. (GT-2638)
    • +
    • GUI. Fixed exception when exiting Ghidra while a table is being edited. (GT-2642, Issue #51)
    • +
    • GUI. Fixed some touchpad scrolling issues. (GT-2647, Issue #2)
    • +
    • GUI. Fixed stack trace in the Data Type Manager's tooltip generation. (GT-2656, Issue #133)
    • +
    • GUI. User key binding settings for the Recently Used and Define Pointer actions no longer lost after re-launching tool. (GT-2659, Issue #152)
    • +
    • GUI. Toolbar buttons now respond to fast clicking. (GT-2689)
    • +
    • Importer:Mach-O. The Mach-O loader can now find import libraries found in Universal Binary files. (GT-2663, Issue #136)
    • +
    • Importer:PE. The PeLoader now correctly parses the GuardCFFunctionTable when table entries are more than 4 bytes each. (GT-2671, Issue #220)
    • +
    • Multi-User:Ghidra Server. Removed support for native OS authentication from Ghidra Server (removed modes -a2 and -a3) due to incompatibility with newer OS releases including Windows 10 and Windows Server 2016. Re-introduction of this will be considered for a future release. (GT-2653)
    • +
    • PDB. Corrected NPE error when processing PDB files. (GT-2673, Issues #138, #188)
    • +
    • Processors. Added missing PowerPC VLE conditional branch instructions: e_bdnz and e_bdz. (GT-2652, Issue #103)
    • +
    • Processors. Fixed instruction semantics for several instructions and added Control Flow Enforcement, NOP variants, CMP variants, UD1, and prefixed call instructions to X86 processor specification. (GT-2660, Issues #22, #53, #158, #157)
    • +
    • Processors. The M68000 MOVE instruction now correctly sets the CF and VF flags. (GT-2661, Issue #163)
    • +
    • Processors. Added four missing MOVEM instruction variants to the M68000 processor. (GT-2675, Issue #219)
    • +
    • Processors. An incorrect usage of X instead of Y in indexed mode for the 6502 has been corrected. (GT-2677, Issue #201)
    • +
    • Processors. PPC VLE now disassembles base PPC instructions that are valid in VLE mode. (GT-2681, Issue #127)
    • +
    • Processors. Added support for ARM Thumb half BL instruction on processor variants prior to v6. (GT-2684, Issue #39)
    • +
    • Scripting. Fixed a bug in ImportSymbolsScript.py that prevented it from running. (GT-2668, Issue #170)

    Security

      -
    • Basic Infrastructure. Running Ghidra in debug mode no longer opens remotely accessible ports by default. (Issue #6)
    • -
    • GUI. The Defined Strings plugin no longer renders HTML in its table. (Issue #45)
    • -
    • Project Manager. Fixed an XXE vulnerability affecting projects and many other saved components. (Issue #71)
    • +
    • Basic Infrastructure. Running Ghidra in debug mode no longer opens remotely accessible ports by default. (GT-2641, Issue #6)
    • +
    • GUI. The Defined Strings plugin no longer renders HTML in its table. (GT-2686, Issue #45)
    • +
    • Project Manager. Fixed an XXE vulnerability affecting projects and many other saved components. (GT-2643, Issue #71)
    From 8eac3ca38b0e2678666e0dd1392778bcc06fc5de Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 2 Mar 2021 12:53:49 -0500 Subject: [PATCH 059/140] Test fixes for atypical test path --- .../Docking/src/main/java/docking/test/AbstractDockingTest.java | 2 +- .../widgets/table/threaded/IncrementalThreadedTableTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java index 775c4f8407..a732c3e492 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java @@ -2017,7 +2017,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { // ThreadedTableModelUpdateMgr Object updateManager = getInstanceField("updateManager", model); SwingUpdateManager sum = - (SwingUpdateManager) getInstanceField("updateManager", updateManager); + (SwingUpdateManager) getInstanceField("addRemoveUpdater", updateManager); Worker worker = (Worker) getInstanceField("worker", model); String workerState = worker == null ? "" : Boolean.toString(worker.isBusy()); return "Table model busy state - Swing Update Manager? " + sum.isBusy() + "; worker?" + diff --git a/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/table/threaded/IncrementalThreadedTableTest.java b/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/table/threaded/IncrementalThreadedTableTest.java index 753f57a90c..f30a2034fb 100644 --- a/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/table/threaded/IncrementalThreadedTableTest.java +++ b/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/table/threaded/IncrementalThreadedTableTest.java @@ -515,7 +515,7 @@ public class IncrementalThreadedTableTest extends AbstractThreadedTableTest { if (isBusy) { SwingUpdateManager sum = - (SwingUpdateManager) getInstanceField("updateManager", tableUpdateManager); + (SwingUpdateManager) getInstanceField("addRemoveUpdater", tableUpdateManager); spy.record("\t\tSwingUpdateManager busy?: " + sum.isBusy()); if (sum.isBusy()) { From aa61e6e1b52cede6b240bfea31accd4ea834041f Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 2 Mar 2021 12:43:32 -0500 Subject: [PATCH 060/140] GP-745 - Fixed stack trace when adding new category to a filtered tree Closes #2799 --- .../datamgr/DataTypeManagerPluginTest.java | 28 ++++++++++++++++++- .../tree/tasks/GTreeStartEditingTask.java | 15 +++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java index 9ed0d7ada6..e7adb329df 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java @@ -205,7 +205,33 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe waitForSwing(); waitForTree(); - runSwing(() -> jTree.stopEditing()); + + // verify that the tree opens a new node with the default + // category name is "New Category" + assertEquals(childCount + 1, miscNode.getChildCount()); + GTreeNode node = miscNode.getChild("New Category"); + assertNotNull(node); + } + + @Test + public void testCreateCategory_WhileFiltered() throws Exception { + // select a category + GTreeNode miscNode = programNode.getChild("MISC"); + assertNotNull(miscNode); + expandNode(miscNode); + + int childCount = miscNode.getChildCount(); + selectNode(miscNode); + + filterTree(miscNode.getName()); + + DockingActionIf action = getAction(plugin, "New Category"); + assertTrue(action.isEnabledForContext(treeContext)); + + // select "New Category" action + DataTypeTestUtils.performAction(action, tree, false); + + waitForDialogComponent("Cannot Edit Tree Node"); // verify that the tree opens a new node with the default // category name is "New Category" diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java index 8d8ba4e8aa..3132cce3bf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java @@ -60,16 +60,15 @@ public class GTreeStartEditingTask extends GTreeTask { private void edit() { + if (tree.isFiltered()) { + Msg.showWarn(getClass(), tree, "Cannot Edit Tree Node", + "Can't edit tree node \"" + childName + "\" while tree is filtered."); + return; + } + GTreeNode editNode = parent.getChild(childName); if (editNode == null) { - if (tree.isFiltered()) { - Msg.showWarn(getClass(), tree, "Cannot Edit Tree Node", - "Can't edit tree node \"" + childName + "\" while tree is filtered."); - } - else { - Msg.debug(this, - "Can't find node \"" + childName + "\" to edit."); - } + Msg.debug(this, "Can't find node \"" + childName + "\" to edit."); return; } From cffc1787ae3a0c37c588c3b3221d16aff2cb13a4 Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Tue, 2 Mar 2021 17:43:16 -0500 Subject: [PATCH 061/140] GP-732 - Added key binding support for showing context menu --- .../main/java/docking/ActionToGuiMapper.java | 5 +- .../main/java/docking/DockableComponent.java | 27 ++++---- .../java/docking/DockingWindowManager.java | 28 +++++++++ .../main/java/docking/PopupActionManager.java | 22 +++---- .../main/java/docking/PopupMenuContext.java | 61 +++++++++++++++++++ .../docking/action/KeyBindingsManager.java | 4 +- .../docking/action/ShowContextMenuAction.java | 52 ++++++++++++++++ .../java/docking/actions/ToolActions.java | 4 ++ .../java/ghidra/util/ReservedKeyBindings.java | 9 ++- 9 files changed, 179 insertions(+), 33 deletions(-) create mode 100644 Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java create mode 100644 Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java b/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java index b048f0cf42..87d7fa763b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java @@ -15,7 +15,6 @@ */ package docking; -import java.awt.event.MouseEvent; import java.util.LinkedHashSet; import java.util.Set; @@ -134,7 +133,7 @@ public class ActionToGuiMapper { return menuGroupMap; } - public void showPopupMenu(ComponentPlaceholder componentInfo, MouseEvent e) { - popupActionManager.popupMenu(componentInfo, e); + public void showPopupMenu(ComponentPlaceholder componentInfo, PopupMenuContext popupContext) { + popupActionManager.popupMenu(componentInfo, popupContext); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java index 55538b0f9e..c0963c8883 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java @@ -67,17 +67,17 @@ public class DockableComponent extends JPanel implements ContainerListener { @Override public void mousePressed(MouseEvent e) { componentSelected((Component) e.getSource()); - processPopupMouseEvent(e); + showContextMenu(e); } @Override public void mouseReleased(MouseEvent e) { - processPopupMouseEvent(e); + showContextMenu(e); } @Override public void mouseClicked(MouseEvent e) { - processPopupMouseEvent(e); + showContextMenu(e); } }; @@ -146,24 +146,27 @@ public class DockableComponent extends JPanel implements ContainerListener { return focusedComponent; } - private void processPopupMouseEvent(final MouseEvent e) { + void showContextMenu(PopupMenuContext popupContext) { + actionMgr.showPopupMenu(placeholder, popupContext); + } + + private void showContextMenu(MouseEvent e) { Component component = e.getComponent(); if (component == null) { - return; + return; // not sure this can happen } // get the bounds to see if the clicked point is over the component - Rectangle bounds = component.getBounds(); // get bounds to get width and height - + Rectangle bounds = component.getBounds(); if (component instanceof JComponent) { ((JComponent) component).computeVisibleRect(bounds); } Point point = e.getPoint(); boolean withinBounds = bounds.contains(point); - if (e.isPopupTrigger() && withinBounds) { - actionMgr.showPopupMenu(placeholder, e); + PopupMenuContext popupContext = new PopupMenuContext(e); + actionMgr.showPopupMenu(placeholder, popupContext); } } @@ -476,17 +479,11 @@ public class DockableComponent extends JPanel implements ContainerListener { return null; } - /** - * @see java.awt.event.ContainerListener#componentAdded(java.awt.event.ContainerEvent) - */ @Override public void componentAdded(ContainerEvent e) { initializeComponents(e.getChild()); } - /** - * @see java.awt.event.ContainerListener#componentRemoved(java.awt.event.ContainerEvent) - */ @Override public void componentRemoved(ContainerEvent e) { deinitializeComponents(e.getChild()); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 4b7d9b4476..873c75d020 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -2172,6 +2172,34 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder objectUnderMouse = null; } + /** + * Shows a popup menu over the given component. If this given component is not part of the + * docking windows hierarchy, then no action is taken. + * + * @param component the component + */ + public static void showContextMenu(Component component) { + + DockingWindowManager dwm = getInstance(component); + if (dwm == null) { + return; + } + + DockableComponent dockableComponent = dwm.getDockableComponent(component); + if (dockableComponent == null) { + return; + } + + Rectangle bounds = dockableComponent.getBounds(); + + bounds.x = 0; + bounds.y = 0; + int x = (int) bounds.getCenterX(); + int y = (int) bounds.getCenterY(); + PopupMenuContext popupContext = new PopupMenuContext(dockableComponent, new Point(x, y)); + dockableComponent.showContextMenu(popupContext); + } + public void contextChanged(ComponentProvider provider) { if (provider == null) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java b/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java index af93a7677a..5a712f2b76 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java @@ -16,6 +16,7 @@ package docking; import java.awt.Component; +import java.awt.Point; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -67,28 +68,27 @@ public class PopupActionManager implements PropertyChangeListener { } } - void popupMenu(ComponentPlaceholder info, MouseEvent e) { + void popupMenu(ComponentPlaceholder placeholder, PopupMenuContext popupContext) { - if (e.isConsumed()) { - return; - } - ComponentProvider popupProvider = info.getProvider(); - ActionContext actionContext = popupProvider.getActionContext(e); + MouseEvent event = popupContext.getEvent(); + ComponentProvider popupProvider = placeholder.getProvider(); + ActionContext actionContext = popupProvider.getActionContext(event); if (actionContext == null) { actionContext = new ActionContext(); } - actionContext.setSourceObject(e.getSource()); - actionContext.setMouseEvent(e); + actionContext.setSourceObject(popupContext.getSource()); + actionContext.setMouseEvent(event); - Iterator localActions = info.getActions(); + Iterator localActions = placeholder.getActions(); JPopupMenu popupMenu = createPopupMenu(localActions, actionContext); if (popupMenu == null) { return; // no matching actions } - Component c = (Component) e.getSource(); - popupMenu.show(c, e.getX(), e.getY()); + Component c = popupContext.getComponent(); + Point p = popupContext.getPoint(); + popupMenu.show(c, p.x, p.y); } protected JPopupMenu createPopupMenu(Iterator localActions, diff --git a/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java b/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java new file mode 100644 index 0000000000..16c87cbd7f --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java @@ -0,0 +1,61 @@ +/* ### + * 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; + +import java.awt.Component; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.util.Objects; + +/** + * A class that holds information used to show a popup menu + */ +public class PopupMenuContext { + + private Component component; + private MouseEvent event; + private Point point; + + PopupMenuContext(MouseEvent event) { + this.event = event; + this.component = Objects.requireNonNull(event.getComponent()); + this.point = event.getPoint(); + } + + PopupMenuContext(Component component, Point point) { + this.component = Objects.requireNonNull(component); + this.point = point; + } + + public MouseEvent getEvent() { + return event; + } + + public Component getComponent() { + return component; + } + + public Point getPoint() { + return new Point(point); + } + + public Object getSource() { + if (event != null) { + return event.getSource(); + } + return component; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java index f29071f815..e433c7705a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java @@ -17,8 +17,7 @@ package docking.action; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import javax.swing.Action; import javax.swing.KeyStroke; @@ -61,6 +60,7 @@ public class KeyBindingsManager implements PropertyChangeListener { public void addReservedAction(DockingActionIf action) { KeyStroke keyBinding = action.getKeyBinding(); + Objects.requireNonNull(keyBinding); addReservedKeyBinding(action, keyBinding); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java new file mode 100644 index 0000000000..469e521057 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java @@ -0,0 +1,52 @@ +/* ### + * 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.action; + +import java.awt.*; + +import javax.swing.KeyStroke; + +import docking.ActionContext; +import docking.DockingWindowManager; + +/** + * An action to trigger a context menu over the focus owner. This allows context menus to be + * triggered from the keyboard. + */ +public class ShowContextMenuAction extends DockingAction { + + public ShowContextMenuAction(KeyStroke keyStroke) { + super("Show Context Menu", DockingWindowManager.DOCKING_WINDOWS_OWNER); + setKeyBindingData(new KeyBindingData(keyStroke)); + } + + @Override + public void actionPerformed(ActionContext context) { + + KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + Window window = kfm.getActiveWindow(); + if (window == null) { + return; + } + + // use the focused component to determine what should get the context menu + Component focusOwner = kfm.getFocusOwner(); + if (focusOwner != null) { + DockingWindowManager.showContextMenu(focusOwner); + } + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java index 592d545f81..bec2cc41cb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java @@ -91,6 +91,10 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener { keyBindingsManager.addReservedAction(new HelpAction(false, ReservedKeyBindings.HELP_KEY2)); keyBindingsManager.addReservedAction( new HelpAction(true, ReservedKeyBindings.HELP_INFO_KEY)); + keyBindingsManager.addReservedAction( + new ShowContextMenuAction(ReservedKeyBindings.CONTEXT_MENU_KEY1)); + keyBindingsManager.addReservedAction( + new ShowContextMenuAction(ReservedKeyBindings.CONTEXT_MENU_KEY2)); // these are diagnostic if (SystemUtilities.isInDevelopmentMode()) { diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java b/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java index c081d5ff99..025c116c48 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -34,6 +33,11 @@ public class ReservedKeyBindings { public static final KeyStroke HELP_INFO_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_F1, DockingUtils.CONTROL_KEY_MODIFIER_MASK); + public static final KeyStroke CONTEXT_MENU_KEY1 = + KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_DOWN_MASK); + public static final KeyStroke CONTEXT_MENU_KEY2 = + KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0); + public static final KeyStroke FOCUS_INFO_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_F2, DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); @@ -50,7 +54,8 @@ public class ReservedKeyBindings { code == KeyEvent.VK_CAPS_LOCK || code == KeyEvent.VK_TAB || HELP_KEY1.equals(keyStroke) || HELP_KEY2.equals(keyStroke) || HELP_INFO_KEY.equals(keyStroke) || UPDATE_KEY_BINDINGS_KEY.equals(keyStroke) || - FOCUS_INFO_KEY.equals(keyStroke) || FOCUS_CYCLE_INFO_KEY.equals(keyStroke)) { + FOCUS_INFO_KEY.equals(keyStroke) || FOCUS_CYCLE_INFO_KEY.equals(keyStroke) || + CONTEXT_MENU_KEY1.equals(keyStroke) || CONTEXT_MENU_KEY2.equals(keyStroke)) { return true; } From 364ff3f8ac140d6d82055cdc303d02a9d92b5bd1 Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:05:31 -0500 Subject: [PATCH 062/140] GP-724 fix setting "PDB Loaded" flag --- .../ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java index 2d10d2f3eb..5d2d894236 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java @@ -15,9 +15,10 @@ */ package ghidra.app.util.pdb.pdbapplicator; -import java.math.BigInteger; import java.util.*; +import java.math.BigInteger; + import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.util.NamespaceUtils; import ghidra.app.util.SymbolPath; @@ -204,7 +205,7 @@ public class PdbApplicator { throw new PdbException("Invalid Restriction"); } - if (program == null) { + if (program != null) { Options options = program.getOptions(Program.PROGRAM_INFO); options.setBoolean(PdbParserConstants.PDB_LOADED, true); } From 1f198f5cd4ddcfe84ee748502999730c979ce35f Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 2 Mar 2021 19:03:59 -0500 Subject: [PATCH 063/140] ChangeHistory update --- .../Public_Release/src/global/docs/ChangeHistory.html | 1 + 1 file changed, 1 insertion(+) diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html index 9eb2c389c2..dc38d983fe 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html @@ -43,6 +43,7 @@
  • Importer:Mach-O. Fixed an issue with DYLD Load Command data structures being created in the wrong locations. (GP-689, Issue #2624)
  • Importer:Mach-O. Fixed an exception that occurred when importing Mach-O files that define zero LC_BUILD_VERSION tool entries. (GP-702, Issue #2192)
  • PDB. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)
  • +
  • PDB. Fix PDB Universal analyzer to set the run-once flag when finished. (GP-724)
  • Processors. Added missing RFE instruction in MIPS up to version R3000. (GP-33, Issue #1766)
  • Processors. ARM instruction VMUL now decodes correctly. (GP-627, Issue #2677)
  • Processors. Added missing CFINV instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)
  • From 9a37a3a19a9be19c3f848d6ce36cdf0135a2695e Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 3 Mar 2021 07:55:44 -0500 Subject: [PATCH 064/140] Corrected processor ordering for movups pcode --- Ghidra/Processors/x86/data/languages/ia.sinc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 4e7e69d3f9..89c390ff40 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -5712,10 +5712,10 @@ define pcodeop movmskps; :MOVUPS XmmReg2, XmmReg1 is vexMode=0 & mandover=0 & byte=0x0F; byte=0x11; xmmmod = 3 & XmmReg1 & XmmReg2 { - XmmReg1[0,32] = XmmReg2[0,32]; - XmmReg1[32,32] = XmmReg2[32,32]; - XmmReg1[64,32] = XmmReg2[64,32]; - XmmReg1[96,32] = XmmReg2[96,32]; + XmmReg2[0,32] = XmmReg1[0,32]; + XmmReg2[32,32] = XmmReg1[32,32]; + XmmReg2[64,32] = XmmReg1[64,32]; + XmmReg2[96,32] = XmmReg1[96,32]; } :MULPD XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x59; m128 & XmmReg ... From 76b66e2a53c6c2e766acea7fe55d00ca8d34d5d3 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:22:36 -0500 Subject: [PATCH 065/140] added javadoc and improved root predicate for loop vertices. changed CIRCLE symbol name GP-625 updated module IP for jungrapht 1.2 missing comma changed jungrapht version to 1.2 changed favored edge and comparator rename for updates to exp layouts updates for graph display api generalization renamed exp layout added placeholders for exp layouts removed problematic changes to layouts allow edge selection to be enabled. Begin to organize default graph api symbols in GraphDisplay updates full fix for GP-625 --- .../Decompiler/ghidra_scripts/GraphAST.java | 12 ++- .../core/decompile/actions/ASTGraphTask.java | 9 +- Ghidra/Features/GraphServices/Module.manifest | 4 +- Ghidra/Features/GraphServices/build.gradle | 6 +- .../visualization/DefaultGraphDisplay.java | 96 ++++++++++++++----- .../graph/visualization/LayoutFunction.java | 61 ++++++++++-- .../LayoutTransitionManager.java | 62 +++++------- .../visualization/mouse/JgtGraphMouse.java | 8 +- .../mouse/JgtSatelliteGraphMouse.java | 10 +- .../mouse/JgtSelectingGraphMousePlugin.java | 10 +- .../src/main/resources/jungrapht.properties | 12 +-- .../ghidra/service/graph/GraphDisplay.java | 46 +++++++++ 12 files changed, 235 insertions(+), 101 deletions(-) diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java index ed2f6f1df1..ddad023997 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java @@ -31,6 +31,7 @@ import ghidra.program.model.pcode.*; import ghidra.service.graph.*; import ghidra.util.Msg; import java.util.*; +import static ghidra.service.graph.GraphDisplay.*; public class GraphAST extends GhidraScript { protected static final String COLOR_ATTRIBUTE = "Color"; @@ -66,11 +67,12 @@ public class GraphAST extends GhidraScript { buildGraph(); Map properties = new HashMap<>(); - properties.put("selectedVertexColor", "0xFF1493"); - properties.put("selectedEdgeColor", "0xFF1493"); - properties.put("initialLayoutAlgorithm", "Hierarchical MinCross Coffman Graham"); - properties.put("displayVerticesAsIcons", "false"); - properties.put("vertexLabelPosition", "S"); + properties.put(SELECTED_VERTEX_COLOR, "0xFF1493"); + properties.put(SELECTED_EDGE_COLOR, "0xFF1493"); + properties.put(INITIAL_LAYOUT_ALGORITHM, "Hierarchical MinCross Coffman Graham"); + properties.put(DISPLAY_VERTICES_AS_ICONS, "false"); + properties.put(VERTEX_LABEL_POSITION, "S"); + properties.put(ENABLE_EDGE_SELECTION, "true"); GraphDisplay graphDisplay = graphDisplayBroker.getDefaultGraphDisplay(false, properties, monitor); // graphDisplay.defineVertexAttribute(CODE_ATTRIBUTE); // diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java index ebe02584e0..0a6a4e7db3 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java @@ -34,6 +34,8 @@ import ghidra.util.exception.GraphException; import ghidra.util.task.Task; import ghidra.util.task.TaskMonitor; +import static ghidra.service.graph.GraphDisplay.*; + public class ASTGraphTask extends Task { enum GraphType { CONTROL_FLOW_GRAPH("AST Control Flow"), DATA_FLOW_GRAPH("AST Data Flow"); @@ -104,9 +106,10 @@ public class ASTGraphTask extends Task { createControlFlowGraph(graph, monitor); } Map properties = new HashMap<>(); - properties.put("selectedVertexColor", "0xFF1493"); - properties.put("selectedEdgeColor", "0xFF1493"); - properties.put("initialLayoutAlgorithm", "Hierarchical MinCross Coffman Graham"); + properties.put(SELECTED_VERTEX_COLOR, "0xFF1493"); + properties.put(SELECTED_EDGE_COLOR, "0xFF1493"); + properties.put(INITIAL_LAYOUT_ALGORITHM, "Hierarchical MinCross Coffman Graham"); + properties.put(ENABLE_EDGE_SELECTION, "true"); GraphDisplay display = graphService.getDefaultGraphDisplay(!newGraph, properties, monitor); ASTGraphDisplayListener displayListener = new ASTGraphDisplayListener(tool, display, hfunction, graphType); diff --git a/Ghidra/Features/GraphServices/Module.manifest b/Ghidra/Features/GraphServices/Module.manifest index 361687fc49..ad8b9ffc53 100644 --- a/Ghidra/Features/GraphServices/Module.manifest +++ b/Ghidra/Features/GraphServices/Module.manifest @@ -1,7 +1,7 @@ EXCLUDE FROM GHIDRA JAR: true -MODULE FILE LICENSE: lib/jungrapht-visualization-1.1.jar BSD -MODULE FILE LICENSE: lib/jungrapht-layout-1.1.jar BSD +MODULE FILE LICENSE: lib/jungrapht-visualization-1.2.jar BSD +MODULE FILE LICENSE: lib/jungrapht-layout-1.2.jar BSD MODULE FILE LICENSE: lib/jgrapht-core-1.5.0.jar LGPL 2.1 MODULE FILE LICENSE: lib/jgrapht-io-1.5.0.jar LGPL 2.1 MODULE FILE LICENSE: lib/jheaps-0.13.jar Apache License 2.0 diff --git a/Ghidra/Features/GraphServices/build.gradle b/Ghidra/Features/GraphServices/build.gradle index 9d3c632bf9..2c53c410ca 100644 --- a/Ghidra/Features/GraphServices/build.gradle +++ b/Ghidra/Features/GraphServices/build.gradle @@ -12,9 +12,9 @@ dependencies { compile project(":Base") // jungrapht - exclude slf4j which produces a conflict with other uses with Ghidra - compile ("com.github.tomnelson:jungrapht-visualization:1.1") { exclude group: "org.slf4j", module: "slf4j-api" } - compile ("com.github.tomnelson:jungrapht-layout:1.1") { exclude group: "org.slf4j", module: "slf4j-api" } - + compile ("com.github.tomnelson:jungrapht-visualization:1.2") { exclude group: "org.slf4j", module: "slf4j-api" } + compile ("com.github.tomnelson:jungrapht-layout:1.2") { exclude group: "org.slf4j", module: "slf4j-api" } + compile "org.jgrapht:jgrapht-core:1.5.0" // not using jgrapht-io code that depends on antlr, so exclude antlr diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 41a21ce1e2..4bf2416581 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -103,28 +103,33 @@ public class DefaultGraphDisplay implements GraphDisplay { private static final String ACTION_OWNER = "GraphServices"; - /* - A handful of properties that can be set via the constructor - */ - private static final String SELECTED_VERTEX_COLOR = "selectedVertexColor"; - private static final String SELECTED_EDGE_COLOR = "selectedEdgeColor"; - private static final String INITIAL_LAYOUT_ALGORITHM = "initialLayoutAlgorithm"; - private static final String DISPLAY_VERTICES_AS_ICONS = "displayVerticesAsIcons"; - private static final String VERTEX_LABEL_POSITION = "vertexLabelPosition"; - private static final int MAX_NODES = Integer.getInteger("maxNodes", 10000); private static final Dimension PREFERRED_VIEW_SIZE = new Dimension(1000, 1000); private static final Dimension PREFERRED_LAYOUT_SIZE = new Dimension(3000, 3000); private Logger log = Logger.getLogger(DefaultGraphDisplay.class.getName()); - private Map displayProperties = new HashMap<>(); + private Map displayProperties; private Set addedActions = new LinkedHashSet<>(); private GraphDisplayListener listener = new DummyGraphDisplayListener(); private String title; private AttributedGraph graph; + private static String DEFAULT_EDGE_TYPE_PRIORITY_LIST = + "Fall-Through,"+ + "Conditional-Return,"+ + "Unconditional-Jump,"+ + "Conditional-Jump,"+ + "Unconditional-Call,"+ + "Conditional-Call,"+ + "Terminator,"+ + "Computed,"+ + "Indirection,"+ + "Entry"; + + private static String DEFAULT_FAVORED_EDGES = "Fall-Through"; + /** * a unique id for this {@link GraphDisplay} */ @@ -219,7 +224,9 @@ public class DefaultGraphDisplay implements GraphDisplay { viewer.getComponent().add(satelliteViewer.getComponent()); } layoutTransitionManager = - new LayoutTransitionManager(viewer, this::isRoot); + new LayoutTransitionManager(viewer, this::isRoot, + getEdgeTypePriorityList(), + getFavoredEdgePredicate()); viewer.getComponent().addComponentListener(new ComponentAdapter() { @Override @@ -252,6 +259,19 @@ public class DefaultGraphDisplay implements GraphDisplay { return Colors.getHexColor(property); } + private List getEdgeTypePriorityList() { + return Arrays.asList(displayProperties + .getOrDefault(EDGE_TYPE_PRIORITY_LIST, DEFAULT_EDGE_TYPE_PRIORITY_LIST) + .split(",")); + } + + private Predicate getFavoredEdgePredicate() { + String[] favoredEdges = displayProperties.getOrDefault(FAVORED_EDGES, DEFAULT_FAVORED_EDGES) + .split(","); + return attributedEdge -> Arrays.stream(favoredEdges) + .anyMatch(s -> s.equals(attributedEdge.getAttribute("EdgeType"))); + } + JComponent getComponent() { JComponent component = viewer.getComponent(); component.setFocusable(true); @@ -486,7 +506,7 @@ public class DefaultGraphDisplay implements GraphDisplay { "Extends the current selection by including the target/source vertices " + "of all edges whose source/target is selected") .keyBinding("ctrl C") - .enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) && + .enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) || !isAllSelected(getTargetVerticesFromSelected())) .onAction(c -> growSelection(getAllComponentVerticesFromSelected())) .buildAndInstallLocal(componentProvider); @@ -610,6 +630,23 @@ public class DefaultGraphDisplay implements GraphDisplay { private void growSelection(Set vertices) { viewer.getSelectedVertexState().select(vertices); + selectEdgesConnecting(vertices); + } + + // select all the edges that connect the supplied vertices + private void selectEdgesConnecting(Collection vertices) { + viewer.getSelectedEdgeState().select( + graph.edgeSet() + .stream() + .filter( + e -> { + AttributedVertex source = graph.getEdgeSource(e); + AttributedVertex target = graph.getEdgeTarget(e); + return vertices.contains(source) + && vertices.contains(target); + }) + .collect(Collectors.toSet())); + } private boolean isAllSelected(Set vertices) { @@ -617,8 +654,8 @@ public class DefaultGraphDisplay implements GraphDisplay { } private Set getSourceVerticesFromSelected() { - Set sources = new HashSet<>(); Set selectedVertices = getSelectedVertices(); + Set sources = new HashSet<>(selectedVertices); for (AttributedVertex v : selectedVertices) { Set edges = graph.incomingEdgesOf(v); edges.forEach(e -> sources.add(graph.getEdgeSource(e))); @@ -635,8 +672,8 @@ public class DefaultGraphDisplay implements GraphDisplay { } private Set getTargetVerticesFromSelected() { - Set targets = new HashSet<>(); Set selectedVertices = getSelectedVertices(); + Set targets = new HashSet<>(selectedVertices); for (AttributedVertex v : selectedVertices) { Set edges = graph.outgoingEdgesOf(v); edges.forEach(e -> targets.add(graph.getEdgeTarget(e))); @@ -674,9 +711,20 @@ public class DefaultGraphDisplay implements GraphDisplay { return upstream; } + /** + * Gather all source and target vertices until there are no more available. + * @return all the vertices in the component(s) of the selected vertices + */ public Set getAllComponentVerticesFromSelected() { - Set componentVertices = getAllDownstreamVerticesFromSelected(); - componentVertices.addAll(getAllUpstreamVerticesFromSelected()); + Set componentVertices = new HashSet<>(viewer.getSelectedVertices()); + Set downstream = getAllDownstreamVerticesFromSelected(); + Set upstream = getAllUpstreamVerticesFromSelected(); + while (!downstream.isEmpty() || !upstream.isEmpty()) { + componentVertices.addAll(downstream); + componentVertices.addAll(upstream); + downstream = getAllDownstreamVerticesFromSelected(); + upstream = getAllUpstreamVerticesFromSelected(); + } return componentVertices; } @@ -974,13 +1022,14 @@ public class DefaultGraphDisplay implements GraphDisplay { /** * Determines if a vertex is a root. For our purpose, a root either has no incoming edges - * or has at least one outgoing "favored" edge and no incoming "favored" edge + * or if all edges of a vertex are 'loop' edges * @param vertex the vertex to test if it is a root * @return true if the vertex is a root */ private boolean isRoot(AttributedVertex vertex) { Set incomingEdgesOf = graph.incomingEdgesOf(vertex); - return incomingEdgesOf.isEmpty(); + return incomingEdgesOf.isEmpty() || + graph.incomingEdgesOf(vertex).equals(graph.outgoingEdgesOf(vertex)); } /** @@ -1249,12 +1298,6 @@ public class DefaultGraphDisplay implements GraphDisplay { setVertexPreferences(vv); - // the selectedEdgeState will be controlled by the vertices that are selected. - // if both endpoints of an edge are selected, select that edge. - vv.setSelectedEdgeState( - new VertexEndpointsSelectedEdgeSelectedState<>(vv.getVisualizationModel()::getGraph, - vv.getSelectedVertexState())); - // selected edges will be drawn with a wider stroke renderContext.setEdgeStrokeFunction( e -> isSelected(e) ? new BasicStroke(20.f) @@ -1278,7 +1321,6 @@ public class DefaultGraphDisplay implements GraphDisplay { // cause the lightweight (optimized) renderer to use the vertex shapes instead // of using default shapes. - if (vertexRenderer instanceof LightweightVertexRenderer) { Function vertexShapeFunction = renderContext.getVertexShapeFunction(); @@ -1301,7 +1343,9 @@ public class DefaultGraphDisplay implements GraphDisplay { vv.getComponent().removeMouseListener(mouseListener); } - graphMouse = new JgtGraphMouse(this); + graphMouse = new JgtGraphMouse(this, + Boolean.parseBoolean(displayProperties.getOrDefault(ENABLE_EDGE_SELECTION, + "false"))); vv.setGraphMouse(graphMouse); return vv; diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java index c248961f26..00690e8436 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java @@ -15,7 +15,9 @@ */ package ghidra.graph.visualization; +import java.util.Comparator; import java.util.function.Function; +import java.util.function.Predicate; import org.jungrapht.visualization.layout.algorithms.*; import org.jungrapht.visualization.layout.algorithms.repulsion.BarnesHutFRRepulsion; @@ -36,22 +38,38 @@ class LayoutFunction static final String KAMADA_KAWAI = "Force Balanced"; static final String FRUCTERMAN_REINGOLD = "Force Directed"; - static final String CIRCLE_MINCROSS = "Circle"; + static final String CIRCLE = "Circle"; static final String TIDIER_TREE = "Compact Hierarchical"; static final String TIDIER_RADIAL_TREE = "Compact Radial"; static final String MIN_CROSS_TOP_DOWN = "Hierarchical MinCross Top Down"; static final String MIN_CROSS_LONGEST_PATH = "Hierarchical MinCross Longest Path"; static final String MIN_CROSS_NETWORK_SIMPLEX = "Hierarchical MinCross Network Simplex"; static final String MIN_CROSS_COFFMAN_GRAHAM = "Hierarchical MinCross Coffman Graham"; + static final String EXP_MIN_CROSS_TOP_DOWN = "Experimental Hierarchical MinCross Top Down"; + static final String EXP_MIN_CROSS_LONGEST_PATH = "Experimental Hierarchical MinCross Longest Path"; + static final String EXP_MIN_CROSS_NETWORK_SIMPLEX = "Experimental Hierarchical MinCross Network Simplex"; + static final String EXP_MIN_CROSS_COFFMAN_GRAHAM = "Experimental Hierarchical MinCross Coffman Graham"; static final String TREE = "Hierarchical"; static final String RADIAL = "Radial"; static final String BALLOON = "Balloon"; static final String GEM = "Gem (Graph Embedder)"; + Predicate favoredEdgePredicate; + Comparator edgeTypeComparator; + + LayoutFunction(Comparator edgeTypeComparator, Predicate favoredEdgePredicate) { + this.edgeTypeComparator = edgeTypeComparator; + this.favoredEdgePredicate = favoredEdgePredicate; + } + public String[] getNames() { return new String[] { TIDIER_TREE, TREE, TIDIER_RADIAL_TREE, MIN_CROSS_TOP_DOWN, MIN_CROSS_LONGEST_PATH, - MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE_MINCROSS, + MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE, + EXP_MIN_CROSS_TOP_DOWN, + EXP_MIN_CROSS_LONGEST_PATH, + EXP_MIN_CROSS_NETWORK_SIMPLEX, + EXP_MIN_CROSS_COFFMAN_GRAHAM, KAMADA_KAWAI, FRUCTERMAN_REINGOLD, RADIAL, BALLOON, GEM }; } @@ -67,27 +85,56 @@ class LayoutFunction case FRUCTERMAN_REINGOLD: return FRLayoutAlgorithm. builder() .repulsionContractBuilder(BarnesHutFRRepulsion.builder()); - case CIRCLE_MINCROSS: + case CIRCLE: return CircleLayoutAlgorithm. builder() - .reduceEdgeCrossing(true); + .reduceEdgeCrossing(false); case TIDIER_RADIAL_TREE: return TidierRadialTreeLayoutAlgorithm - . edgeAwareBuilder(); + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator); case MIN_CROSS_TOP_DOWN: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.TOP_DOWN); case MIN_CROSS_LONGEST_PATH: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.LONGEST_PATH); case MIN_CROSS_NETWORK_SIMPLEX: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.NETWORK_SIMPLEX); case MIN_CROSS_COFFMAN_GRAHAM: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .layering(Layering.COFFMAN_GRAHAM); + case EXP_MIN_CROSS_TOP_DOWN: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.TOP_DOWN); + case EXP_MIN_CROSS_LONGEST_PATH: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.LONGEST_PATH); + case EXP_MIN_CROSS_NETWORK_SIMPLEX: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.NETWORK_SIMPLEX); + case EXP_MIN_CROSS_COFFMAN_GRAHAM: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) .layering(Layering.COFFMAN_GRAHAM); case RADIAL: return RadialTreeLayoutAlgorithm @@ -103,7 +150,9 @@ class LayoutFunction case TIDIER_TREE: default: return TidierTreeLayoutAlgorithm - . edgeAwareBuilder(); + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator); + } } } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java index c500ba8f51..6849d81829 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java @@ -38,7 +38,7 @@ import ghidra.service.graph.AttributedVertex; */ class LayoutTransitionManager { - LayoutFunction layoutFunction = new LayoutFunction(); + LayoutFunction layoutFunction; /** * the {@link VisualizationServer} used to display graphs using the requested {@link LayoutAlgorithm} */ @@ -49,24 +49,6 @@ class LayoutTransitionManager { */ Predicate rootPredicate; - public static final List EDGE_PRIORITY_LIST = - List.of( - "Fall-Through", - "Conditional-Return", - "Unconditional-Jump", - "Conditional-Jump", - "Unconditional-Call", - "Conditional-Call", - "Terminator", - "Computed", - "Indirection", - "Entry"); - /** - * a {@link Comparator} to sort edges during layout graph traversal - * The default uses the {@code EDGE_PRIORTITY_LIST } - */ - Comparator edgeComparator = new EdgeComparator(EDGE_PRIORITY_LIST); - /** * a {@link Function} to provide {@link Rectangle} (and thus bounds} for vertices */ @@ -81,47 +63,54 @@ class LayoutTransitionManager { LayoutPaintable.RadialRings radialLayoutRings; - /** * Create an instance with passed parameters * @param visualizationServer displays the graph * @param rootPredicate selects root vertices + * @param edgeTypePriorityList a {@code List} of EdgeType names in priority order + * @param favoredEdgePredicate q {@code Predicate} that will cause certain EdgeTypes to be favored during layout */ public LayoutTransitionManager( VisualizationServer visualizationServer, - Predicate rootPredicate) { + Predicate rootPredicate, + List edgeTypePriorityList, + Predicate favoredEdgePredicate) { this.visualizationServer = visualizationServer; this.rootPredicate = rootPredicate; - this.renderContext = visualizationServer.getRenderContext(); this.vertexBoundsFunction = visualizationServer.getRenderContext().getVertexBoundsFunction(); - } - - public void setEdgeComparator(Comparator edgeComparator) { - this.edgeComparator = edgeComparator; + this.layoutFunction = new LayoutFunction(new EdgeComparator(edgeTypePriorityList), + favoredEdgePredicate); } /** * set the layout in order to configure the requested {@link LayoutAlgorithm} * @param layoutName the name of the layout algorithm to use */ - @SuppressWarnings("unchecked") public void setLayout(String layoutName) { LayoutAlgorithm.Builder builder = layoutFunction.apply(layoutName); LayoutAlgorithm layoutAlgorithm = builder.build(); + // layout algorithm considers the size of vertices if (layoutAlgorithm instanceof VertexBoundsFunctionConsumer) { ((VertexBoundsFunctionConsumer) layoutAlgorithm) .setVertexBoundsFunction(vertexBoundsFunction); } + // mincross layouts are 'layered'. put some bounds on the number of + // iterations of the level cross function based on the size of the graph + // very large graphs do not improve enough to out-weigh the cost of + // repeated iterations if (layoutAlgorithm instanceof Layered) { ((Layered) layoutAlgorithm) .setMaxLevelCrossFunction(g -> Math.max(1, Math.min(10, 500 / g.vertexSet().size()))); } + // tree layouts need a way to determine which vertices are roots + // especially when the graph is not a DAG if (layoutAlgorithm instanceof TreeLayout) { ((TreeLayout) layoutAlgorithm).setRootPredicate(rootPredicate); } // remove any previously added layout paintables + // and apply paintables to these 2 algorithms removePaintable(radialLayoutRings); removePaintable(balloonLayoutRings); if (layoutAlgorithm instanceof BalloonLayoutAlgorithm) { @@ -138,9 +127,7 @@ class LayoutTransitionManager { visualizationServer.addPreRenderPaintable(radialLayoutRings); } - if (layoutAlgorithm instanceof EdgeSorting) { - ((EdgeSorting) layoutAlgorithm).setEdgeComparator(edgeComparator); - } + // apply the layout algorithm LayoutAlgorithmTransition.apply(visualizationServer, layoutAlgorithm); } @@ -151,7 +138,10 @@ class LayoutTransitionManager { } } - @SuppressWarnings("unchecked") + /** + * Supplies the {@code LayoutAlgorithm} to be used for the initial @{code Graph} visualization + * @return + */ public LayoutAlgorithm getInitialLayoutAlgorithm() { LayoutAlgorithm initialLayoutAlgorithm = layoutFunction.apply(TIDIER_TREE).build(); @@ -159,12 +149,6 @@ class LayoutTransitionManager { if (initialLayoutAlgorithm instanceof TreeLayout) { ((TreeLayout) initialLayoutAlgorithm) .setRootPredicate(rootPredicate); - ((TreeLayout) initialLayoutAlgorithm) - .setVertexBoundsFunction(vertexBoundsFunction); - } - if (initialLayoutAlgorithm instanceof EdgeSorting) { - ((EdgeSorting) initialLayoutAlgorithm) - .setEdgeComparator(edgeComparator); } if (initialLayoutAlgorithm instanceof VertexBoundsFunctionConsumer) { ((VertexBoundsFunctionConsumer) initialLayoutAlgorithm) @@ -173,6 +157,10 @@ class LayoutTransitionManager { return initialLayoutAlgorithm; } + /** + * Supplies a {@code String[]} array of the supported layout names + * @return + */ public String[] getLayoutNames() { return layoutFunction.getNames(); } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java index b198d513b1..fc77954316 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java @@ -29,12 +29,14 @@ import ghidra.service.graph.AttributedVertex; public class JgtGraphMouse extends DefaultGraphMouse { private DefaultGraphDisplay graphDisplay; + private boolean allowEdgeSelection; // TODO we should not need the graph display for any mouse plugins, but the API is net yet // robust enough to communicate fully without it - public JgtGraphMouse(DefaultGraphDisplay graphDisplay) { + public JgtGraphMouse(DefaultGraphDisplay graphDisplay, boolean allowEdgeSelection) { super(DefaultGraphMouse.builder()); this.graphDisplay = graphDisplay; + this.allowEdgeSelection = allowEdgeSelection; } @Override @@ -54,13 +56,13 @@ public class JgtGraphMouse extends DefaultGraphMouse()); // add(new SelectingGraphMousePlugin<>()); add(new RegionSelectingGraphMousePlugin<>()); // the grab/pan feature - add(new TranslatingGraphMousePlugin(InputEvent.BUTTON1_DOWN_MASK)); + add(TranslatingGraphMousePlugin.builder().translatingMask(InputEvent.BUTTON1_DOWN_MASK).build()); // scaling add(new ScalingGraphMousePlugin()); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java index da8f9dab09..668777ea9d 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java @@ -39,19 +39,21 @@ public class JgtSatelliteGraphMouse // // JUNGRAPHT CHANGE 3 // + // disable single selection in satellite view by setting masks to 0 SelectingGraphMousePlugin mySelectingPlugin = - new JgtSelectingGraphMousePlugin(singleSelectionMask, addSingleSelectionMask); + new JgtSelectingGraphMousePlugin(0, 0); mySelectingPlugin.setLocked(true); selectingPlugin = mySelectingPlugin; regionSelectingPlugin = RegionSelectingGraphMousePlugin.builder() .regionSelectionMask(regionSelectionMask) - .addRegionSelectionMask(addRegionSelectionMask) + .toggleRegionSelectionMask(toggleRegionSelectionMask) .regionSelectionCompleteMask(regionSelectionCompleteMask) - .addRegionSelectionCompleteMask(addRegionSelectionCompleteMask) + .toggleRegionSelectionCompleteMask(toggleRegionSelectionCompleteMask) .build(); - translatingPlugin = new SatelliteTranslatingGraphMousePlugin(translatingMask); + translatingPlugin = SatelliteTranslatingGraphMousePlugin.builder() + .translatingMask(translatingMask).build(); add(selectingPlugin); add(regionSelectingPlugin); add(translatingPlugin); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java index e2f15d4917..680a2c0199 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java @@ -54,8 +54,10 @@ public class JgtSelectingGraphMousePlugin this.pickFootprintPaintable = dummyPickFootprintPaintable; } - public JgtSelectingGraphMousePlugin(int singleSelectionMask, int addSingleSelectionMask) { - super(singleSelectionMask, addSingleSelectionMask); + public JgtSelectingGraphMousePlugin(int singleSelectionMask, int toggleSingleSelectionMask) { + super(SelectingGraphMousePlugin.builder() + .singleSelectionMask(singleSelectionMask) + .toggleSingleSelectionMask(toggleSingleSelectionMask)); // // JUNGRAPHT CHANGE 1 @@ -89,7 +91,6 @@ public class JgtSelectingGraphMousePlugin selectedVertexState.clear(); } selectedVertexState.select(vertex); - deselectedVertex = null; } else { // If this vertex is still around in mouseReleased, it will be deselected @@ -99,9 +100,6 @@ public class JgtSelectingGraphMousePlugin // // JUNGRAPHT CHANGE 2 HERE // - if (addToSelection) { - deselectedVertex = vertex; - } } e.consume(); return true; diff --git a/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties b/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties index 707a0815ae..1adeb4b1d0 100644 --- a/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties +++ b/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties @@ -13,8 +13,8 @@ jungrapht.satelliteBackgroundTransparent=false jungrapht.satelliteLensColor= 0xFAFAFA jungrapht.pickedEdgeColor=0xFF0000 -jungrapht.edgeArrowLength=30 -jungrapht.edgeArrowWidth=20 +jungrapht.edgeArrowLength=50 +jungrapht.edgeArrowWidth=40 # default spacing for tree layouts jungrapht.treeLayoutHorizontalSpacing=2 @@ -34,7 +34,7 @@ jungrapht.lensStrokeWidth=10.0 # when scale is < .1, switch to lightweight rendering jungrapht.lightweightScaleThreshold=.1 # under 50 vertices will use heavyweight rendering all the time -jungrapht.lightweightCountThreshold=50 +jungrapht.lightweightCountThreshold=80 # default pixels spacings for vertices jungrapht.mincross.horizontalOffset=10 @@ -69,12 +69,12 @@ jungrapht.edgeSpatialSupport=RTREE # the mask for single vertex/edge selection jungrapht.singleSelectionMask=MB1 # the mask to augment the selection with a single vertex/edge -jungrapht.addSingleSelectionMask=MB1_MENU +jungrapht.toggleSingleSelectionMask=MB1_MENU # the mask to select vertices within a region jungrapht.regionSelectionMask=MB1_MENU # the mask to augment the selection with vertices in a region -jungrapht.addRegionSelectionMask=MB1_SHIFT_MENU +jungrapht.toggleRegionSelectionMask=MB1_SHIFT_MENU # the mask to indicate that the selection region is complete/closed and selection may commence jungrapht.regionSelectionCompleteMask=MENU # the mask to indicate that the selection region for augmentation is complete/closed and selection may commence -jungrapht.addRegionSelectionCompleteMask=SHIFT_MENU +jungrapht.toggleRegionSelectionCompleteMask=SHIFT_MENU diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java index 696671614e..0f1358f53f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java @@ -34,6 +34,52 @@ public interface GraphDisplay { public static final int ALIGN_CENTER = 1; // aligns graph text to the center public static final int ALIGN_RIGHT = 2; // aligns graph text to the right + /** + * values are color names or rgb in hex '0xFF0000' is red + */ + String SELECTED_VERTEX_COLOR = "selectedVertexColor"; + /** + * values are color names or rgb in hex '0xFF0000' is red + */ + String SELECTED_EDGE_COLOR = "selectedEdgeColor"; + /** + * values are defined as String symbols in LayoutFunction class + * + * KAMADA_KAWAI,FRUCTERMAN_REINGOLD,CIRCLE_MINCROSS,TIDIER_TREE,TIDIER_RADIAL_TREE, + * MIN_CROSS_TOP_DOWN,MIN_CROSS_LONGEST_PATH,MIN_CROSS_NETWORK_SIMPLEX,MIN_CROSS_COFFMAN_GRAHAM, + * EXP_MIN_CROSS_TOP_DOWN,EXP_MIN_CROSS_LONGEST_PATH,EXP_MIN_CROSS_NETWORK_SIMPLEX, + * EXP_MIN_CROSS_COFFMAN_GRAHAM,TREE,RADIAL,BALLOON,GEM + * + * may have no meaning for a different graph visualization library + */ + String INITIAL_LAYOUT_ALGORITHM = "initialLayoutAlgorithm"; + /** + * true or false + * may have no meaning for a different graph visualization library + */ + String DISPLAY_VERTICES_AS_ICONS = "displayVerticesAsIcons"; + /** + * values are the strings N,NE,E,SE,S,SW,W,NW,AUTO,CNTR + * may have no meaning for a different graph visualization library + */ + String VERTEX_LABEL_POSITION = "vertexLabelPosition"; + /** + * true or false, whether edge selection via a mouse click is enabled. + * May not be supported by another graph visualization library + */ + String ENABLE_EDGE_SELECTION = "enableEdgeSelection"; + /** + * a comma-separated list of edge type names in priority order + */ + String EDGE_TYPE_PRIORITY_LIST = "edgeTypePriorityList"; + /** + * a comma-separated list of edge type names. + * any will be considered a favored edge for the min-cross layout + * algorithms. + * May have no meaning with a different graph visualization library + */ + String FAVORED_EDGES = "favoredEdges"; + /** * Sets a {@link GraphDisplayListener} to be notified when the user changes the vertex focus * or selects one or more nodes in a graph window From f883870d455226514af17c91c2c821d209822bb1 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 3 Mar 2021 13:50:49 -0500 Subject: [PATCH 066/140] Set version 9.2.3 --- Ghidra/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/application.properties b/Ghidra/application.properties index 2c8be02f9e..7bae91e8f5 100644 --- a/Ghidra/application.properties +++ b/Ghidra/application.properties @@ -1,5 +1,5 @@ application.name=Ghidra -application.version=9.2.2 +application.version=9.2.3 application.release.name=DEV application.layout.version=1 application.gradle.min=5.0 From 2136e710484425524a1e68b1c632cedaacd94035 Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:41:18 -0500 Subject: [PATCH 067/140] GP-751 OverlayAddressSpace for VarnodeContext and clean-up code --- .../ghidra/program/util/VarnodeContext.java | 48 +++++++++++-------- .../model/address/DefaultAddressFactory.java | 46 +++++++++++------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java index e88dfc8cdf..760bf5fd60 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java @@ -47,20 +47,20 @@ public class VarnodeContext implements ProcessorContext { protected DisassemblerContextImpl spaceContext; // holds temp memory values for computation - protected HashMap memoryVals = new HashMap(); + protected HashMap memoryVals = new HashMap<>(); // holds temp values for computation - private HashMap tempVals = new HashMap(); - protected HashMap tempUniqueVals = new HashMap(); + private HashMap tempVals = new HashMap<>(); + protected HashMap tempUniqueVals = new HashMap<>(); protected boolean keepTempUniqueValues = false; - protected HashSet clearVals = new HashSet(); + protected HashSet clearVals = new HashSet<>(); // locations where registers were last set to a constant value - protected HashMap lastSet = new HashMap(); + protected HashMap lastSet = new HashMap<>(); // all locations where a register was last explicitly set to a value, not just has the value - protected HashMap allLastSet = new HashMap(); + protected HashMap allLastSet = new HashMap<>(); protected Program program; protected VarnodeTranslator trans; // translator for varnodes<-->registers @@ -68,7 +68,7 @@ public class VarnodeContext implements ProcessorContext { protected Varnode[] retVarnodes = null; // varnodes used to return values protected Varnode stackVarnode = null; // varnode that represents the stack protected Register stackReg = null; - private HashSet validSymbolicStackNames = new HashSet(); // list of stack related register names + private HashSet validSymbolicStackNames = new HashSet<>(); // list of stack related register names protected static final NotFoundException notFoundExc = new NotFoundException(); @@ -88,9 +88,7 @@ public class VarnodeContext implements ProcessorContext { this.program = program; // make a copy, because we could be making new spaces. - // TODO: This could be a problem if some of the Pcode comes up with Overlay Address Spaces. - // TODO: This doesn't get Stack space, or other overlay spaces... - this.addrFactory = new OffsetAddressFactory(program.getLanguage().getAddressFactory()); + this.addrFactory = new OffsetAddressFactory(program.getAddressFactory()); BAD_ADDRESS = addrFactory.getAddress(getAddressSpace("BAD_ADDRESS_SPACE"), 0); @@ -168,7 +166,7 @@ public class VarnodeContext implements ProcessorContext { currentAddress = toAddr; - this.lastSet = new HashMap(); // clear out any interim last sets... rely on allLastSet now + this.lastSet = new HashMap<>(); // clear out any interim last sets... rely on allLastSet now offsetContext.flowStart(fromAddr, toAddr); spaceContext.flowStart(fromAddr, toAddr); @@ -755,10 +753,10 @@ public class VarnodeContext implements ProcessorContext { } if (clearContext) { if (!keepTempUniqueValues) { - tempUniqueVals = new HashMap(); + tempUniqueVals = new HashMap<>(); } - tempVals = new HashMap(); - clearVals = new HashSet(); + tempVals = new HashMap<>(); + clearVals = new HashSet<>(); } } @@ -867,9 +865,6 @@ public class VarnodeContext implements ProcessorContext { public Varnode getVarnode(int spaceID, long offset, int size) { AddressSpace space = addrFactory.getAddressSpace(spaceID); - if (space == null) { - return new Varnode(null, size); - } Address target = space.getTruncatedAddress(offset, true); Varnode vt = new Varnode(target, size); return vt; @@ -1242,8 +1237,7 @@ public class VarnodeContext implements ProcessorContext { throws NotFoundException { // degenerate case, don't need to know the value if (val1.equals(val2)) { - return createVarnode(0, addrFactory.getConstantSpace().getSpaceID(), - val1.getSize()); + return createVarnode(0, addrFactory.getConstantSpace().getSpaceID(), val1.getSize()); } int spaceID = val1.getSpace(); long valbase = 0; @@ -1442,7 +1436,7 @@ public class VarnodeContext implements ProcessorContext { class OffsetAddressFactory extends DefaultAddressFactory { OffsetAddressFactory(AddressFactory baseFactory) { - super(baseFactory.getAllAddressSpaces()); + super(filterSpaces(baseFactory.getAllAddressSpaces())); } private int getNextUniqueID() { @@ -1471,4 +1465,18 @@ class OffsetAddressFactory extends DefaultAddressFactory { int type = AddressSpace.ID_TYPE_MASK & spaceID; return (type == AddressSpace.TYPE_SYMBOL); } + + private static AddressSpace[] filterSpaces(AddressSpace[] allSpaces) { + List spaces = new ArrayList<>(); + for (AddressSpace space : allSpaces) { + int type = space.getType(); + if (type == AddressSpace.TYPE_VARIABLE || type == AddressSpace.TYPE_STACK || + type == AddressSpace.TYPE_EXTERNAL || type == AddressSpace.TYPE_JOIN) { + continue; + } + spaces.add(space); + } + return spaces.toArray(new AddressSpace[0]); + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/DefaultAddressFactory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/DefaultAddressFactory.java index c9843c836e..da49972291 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/DefaultAddressFactory.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/DefaultAddressFactory.java @@ -59,9 +59,9 @@ public class DefaultAddressFactory implements AddressFactory { */ public DefaultAddressFactory(AddressSpace[] addrSpaces, AddressSpace defaultSpace) { memoryAddressSet = new AddressSet(); - spaces = new ArrayList(addrSpaces.length); - spaceLookup = new IntObjectHashtable(); - spaceNameTable = new HashMap(); + spaces = new ArrayList<>(addrSpaces.length); + spaceLookup = new IntObjectHashtable<>(); + spaceNameTable = new HashMap<>(); for (AddressSpace space : addrSpaces) { checkReservedSpace(space); @@ -78,9 +78,6 @@ public class DefaultAddressFactory implements AddressFactory { else if (space.getType() == AddressSpace.TYPE_UNIQUE) { uniqueSpace = space; } - else if (space.getType() == AddressSpace.TYPE_STACK) { - throw new IllegalArgumentException("Stack space should not be specified"); - } else if (space.getType() == AddressSpace.TYPE_REGISTER) { if (registerSpace != null || !space.getName().equalsIgnoreCase("register")) { // Ghidra address encoding only handles a single register space @@ -89,9 +86,6 @@ public class DefaultAddressFactory implements AddressFactory { } registerSpace = space; } - else if (space.getType() == AddressSpace.TYPE_VARIABLE) { - throw new IllegalArgumentException("Variable space must be defined by language"); - } // build up an address set for all possible "real" addresses if (space.isMemorySpace()) { memoryAddressSet.addRange(space.getMinAddress(), space.getMaxAddress()); @@ -118,17 +112,38 @@ public class DefaultAddressFactory implements AddressFactory { } private void checkReservedSpace(AddressSpace space) { + checkReservedVariable(space); + checkReservedJoin(space); + checkReservedExternal(space); + checkReservedStack(space); + } + + private void checkReservedVariable(AddressSpace space) { if (space.getType() == AddressSpace.TYPE_VARIABLE || - space.getName().equalsIgnoreCase(AddressSpace.VARIABLE_SPACE.getName()) || - space.getName().equals("join")) { + space.getName().equalsIgnoreCase(AddressSpace.VARIABLE_SPACE.getName())) { throw new IllegalArgumentException("Variable space should not be specified"); } + } + + private void checkReservedJoin(AddressSpace space) { + if (space.getType() == AddressSpace.TYPE_JOIN || space.getName().equals("join")) { + throw new IllegalArgumentException("Join space should not be specified"); + } + } + + private void checkReservedExternal(AddressSpace space) { if (space.getType() == AddressSpace.TYPE_EXTERNAL || space.getName().equalsIgnoreCase(AddressSpace.EXTERNAL_SPACE.getName())) { throw new IllegalArgumentException("External space should not be specified"); } } - + + private void checkReservedStack(AddressSpace space) { + if (space.getType() == AddressSpace.TYPE_STACK) { + throw new IllegalArgumentException("Stack space should not be specified"); + } + } + /** * @see ghidra.program.model.address.AddressFactory#getAddress(java.lang.String) */ @@ -159,7 +174,7 @@ public class DefaultAddressFactory implements AddressFactory { } return null; } - + @Override public Address[] getAllAddresses(String addrString) { return getAllAddresses(addrString, true); @@ -167,8 +182,8 @@ public class DefaultAddressFactory implements AddressFactory { @Override public Address[] getAllAddresses(String addrString, boolean caseSensitive) { - ArrayList
    loadedMemoryList = new ArrayList
    (); - ArrayList
    otherList = new ArrayList
    (); + ArrayList
    loadedMemoryList = new ArrayList<>(); + ArrayList
    otherList = new ArrayList<>(); for (AddressSpace space : spaces) { // Only parse against true physical spaces first @@ -210,7 +225,6 @@ public class DefaultAddressFactory implements AddressFactory { return defaultSpace; } - @Override public AddressSpace[] getAddressSpaces() { return getPhysicalSpaces();// we avoid returning analysis spaces here From 813d91adec740f164e0cceaaae67a0ada999d41a Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 2 Mar 2021 17:54:38 -0500 Subject: [PATCH 068/140] Fixed intermittent splash screen test failure; updated dialog parenting to not allow a hidden window to be a parent --- .../java/docking/DockingWindowManager.java | 22 ++-- .../docking/framework/SplashScreenTest.java | 107 ++++++------------ 2 files changed, 49 insertions(+), 80 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 4b7d9b4476..7623b3bd39 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -1765,8 +1765,11 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } if (bestParent == null) { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - bestParent = kfm.getActiveWindow(); + bestParent = getJavaActiveWindow(); + } + + if (bestParent != null && !bestParent.isShowing()) { + bestParent = null; // don't let non-showing windows be parents } return bestParent; @@ -1775,8 +1778,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder private static Window getBestNonModalParent(DialogComponentProvider newProvider, Window bestParent) { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window activeWindow = kfm.getActiveWindow(); + Window activeWindow = getJavaActiveWindow(); if (!(activeWindow instanceof DockingDialog)) { return bestParent; } @@ -1937,13 +1939,19 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder private static Window getJavaActiveWindow() { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - return kfm.getActiveWindow(); + Window activeWindow = kfm.getActiveWindow(); + if (activeWindow == null) { + return null; + } + if (!activeWindow.isShowing()) { + return null; // don't let non-showing windows be considered active + } + return activeWindow; } private static Window getActiveNonTransientWindow() { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window bestWindow = kfm.getActiveWindow(); + Window bestWindow = getJavaActiveWindow(); if (bestWindow instanceof DockingDialog) { // We do not want Task Dialogs becoming parents, as they will get closed when the // task is finished, closing any other child dialogs, which means that dialogs such diff --git a/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java b/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java index c3ef15bca8..0dbdf2655b 100644 --- a/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java +++ b/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java @@ -30,71 +30,43 @@ import docking.*; import docking.test.AbstractDockingTest; import docking.widgets.PasswordDialog; import generic.test.category.NightlyCategory; -import ghidra.util.Msg; // The splash screen is sensitive to windows being activated/deactivated, so don't run // when other test windows may be open @Category(NightlyCategory.class) public class SplashScreenTest extends AbstractDockingTest { - private AboutDialog aboutDialog; - @After public void tearDown() { - Msg.debug(this, "tearDown() - open windows before closing"); - printOpenWindows(); - runSwing(() -> SplashScreen.disposeSplashScreen()); - - closeAllWindows(); - printOpenWindows(); - - Msg.debug(this, "tearDown() - open windows after closing"); + disposeAllWindows(); } - @Test - public void testShowInfoWindow() throws Exception { - // no parent - showModalInfoWindow(null); - - ensureInfoWindowVisible(); - hideInfoWindow(); - - // not visible parent - JFrame parentFrame = new JFrame("InfoWindowTest.testShowInfoWindow Frame"); - parentFrame.setBounds(-100, -100, 0, 0); - showModalInfoWindow(parentFrame); - - ensureInfoWindowVisible(); - hideInfoWindow(); - - // visible parent - parentFrame.setVisible(true); - showModalInfoWindow(parentFrame); - - ensureInfoWindowVisible(); - hideInfoWindow(); + private void disposeAllWindows() { + for (Window window : getAllWindows()) { + runSwing(window::dispose); + } } @Test public void testShowAndHideSplashScreen() { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); showSplashScreen(false); - ensureSpashScreenVisible(false); + assertSpashScreenVisible(false); showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); showSplashScreen(false); - ensureSpashScreenVisible(false); + assertSpashScreenVisible(false); } @Test public void testUpdateSplashScreenStatus() { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); JLabel statusLabel = (JLabel) getInstanceField("statusLabel", SplashScreen.class); @@ -120,24 +92,24 @@ public class SplashScreenTest extends AbstractDockingTest { public void testSplashScreenPasswordModality_SharedParent() throws Exception { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); // show a modal dialog with no parent (this will use the Splash Screen's parent) showModalPasswordDialog(null); // When the splash screen and the dialog share a parent, then the dialog should NOT // cause the splash screen to go away - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); } @Test public void testSplashScreenPasswordModality_UnsharedParent() throws Exception { // show the splash screen showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); DockingFrame frame = new DockingFrame("Modal Parent Frame"); - frame.setVisible(true); + show(frame); showModalPasswordDialog(frame); ensureSplashScreenWillClose(); @@ -147,6 +119,10 @@ public class SplashScreenTest extends AbstractDockingTest { // Private Methods //================================================================================================== + private void show(JFrame frame) { + runSwing(() -> frame.setVisible(true)); + } + private void ensureSplashScreenWillClose() { waitForCondition(() -> { SplashScreen splash = getSplash(); @@ -155,42 +131,44 @@ public class SplashScreenTest extends AbstractDockingTest { } private DockingDialog showModalPasswordDialog(Frame parentFrame) throws Exception { + String dialogTitle = "InfoWindowTest.testSplashScreenPasswordModality() Dialog"; DialogComponentProvider passwordDialog = runSwing(() -> new PasswordDialog(dialogTitle, "Server Type", "Server Name", "Prompt", null, null)); + if (parentFrame == null) { + // null means to share the parent + Object splashParent = getInstanceField("hiddenFrame", SplashScreen.class); + parentFrame = (Frame) splashParent; + } + + Frame finalParent = parentFrame; executeOnSwingWithoutBlocking( - () -> DockingWindowManager.showDialog(parentFrame, passwordDialog)); + () -> { + DockingDialog dialog = + DockingDialog.createDialog(finalParent, passwordDialog, finalParent); + dialog.setVisible(true); + }); JDialog dialog = waitForJDialog(dialogTitle); assertNotNull(dialog); - Window dialogWindow = SwingUtilities.windowForComponent(dialog); - Msg.debug(this, "Created modal dialog with parent: " + getTitleForWindow(dialogWindow) + - " - id: " + System.identityHashCode(dialogWindow)); - return (DockingDialog) dialog; } - // handles showing the modal info window, which must be done from a thread outside of the - // test thread - private void showModalInfoWindow(final JFrame parentFrame) { - // create a thread to show the modal dialog so that the current thread doesn't block - aboutDialog = runSwing(() -> new AboutDialog()); - executeOnSwingWithoutBlocking(() -> DockingWindowManager.showDialog(null, aboutDialog)); - } - private void showSplashScreen(final boolean makeVisible) { if (makeVisible) { SplashScreen splash = runSwing(() -> SplashScreen.showSplashScreen()); assertNotNull("Failed showing splash screen", splash); + waitForSwing(); return; } SplashScreen.disposeSplashScreen(); + waitForSwing(); } - private void ensureSpashScreenVisible(boolean visible) { + private void assertSpashScreenVisible(boolean visible) { // get the 'splashWindow' and make sure that it is not null and that it is visible SplashScreen splashScreen = getSplash(); @@ -206,23 +184,6 @@ public class SplashScreenTest extends AbstractDockingTest { // timing issue debug waitForCondition(() -> splashScreen.isVisible()); - - if (!splashScreen.isVisible()) { - - // this can happen if other OS windows trigger the splash window to be hidden - printOpenWindows(); - fail("The splash screen is not visible when expected to be so - " + splashScreen); - } - } - - private void ensureInfoWindowVisible() { - // get the 'infoDialog' and make sure that it is not null and that it is visible - assertTrue("The info dialog is not visible after it was supposed to " + "have been shown.", - aboutDialog.isVisible()); - } - - private void hideInfoWindow() throws Exception { - runSwing(() -> aboutDialog.close()); } private SplashScreen getSplash() { From b5f950bb2c09f85c746fef15d90bc7bfdcfff930 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Thu, 4 Mar 2021 11:55:11 -0500 Subject: [PATCH 069/140] Removed unneeded SuperH4 dummy exports --- Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc index cfb4adc8af..724c889b7f 100644 --- a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc +++ b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc @@ -518,15 +518,15 @@ N_0t_dbr1: @^N_0^"+,"^DBR is N_0 & DBR { export N_0; } N_0t_bank1: @^N_0^"+" is N_0 { export N_0; } -FR0_t: fr0 is OP_0 & fr0 { x:4 = 0; export x; } # dummy export, just looking for the display +FR0_t: fr0 is OP_0 & fr0 { export fr0; } XMTRX_t: "xmtrx" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display -mach_t: MACH is OP_0 & MACH { x:4 = 0; export x; } # dummy export, just looking for the display +mach_t: MACH is OP_0 & MACH { export MACH; } -macl_t: MACL is OP_0 & MACL { x:4 = 0; export x; } # dummy export, just looking for the display +macl_t: MACL is OP_0 & MACL { export MACL; } -fpul_t: FPUL is OP_0 & FPUL { x:4 = 0; export x; } # dummy export, just looking for the display +fpul_t: FPUL is OP_0 & FPUL { export FPUL; } fpscr_t: "FPSCR" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display From 5afc1bebec7b5da270a6a648b7677f4de819b7da Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:34:04 -0500 Subject: [PATCH 070/140] GP-747 - Keybinding 'fix' for difference in key codes for Left/Right Alt keys on some OSes Closes #2008 --- .../plugintool/dialog/KeyBindingsTest.java | 40 +++++++++++++++++++ .../docking/action/KeyBindingsManager.java | 39 +++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/plugintool/dialog/KeyBindingsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/plugintool/dialog/KeyBindingsTest.java index 7b90f6c136..5c339b36bb 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/plugintool/dialog/KeyBindingsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/plugintool/dialog/KeyBindingsTest.java @@ -27,10 +27,12 @@ import javax.swing.table.*; import org.junit.*; +import docking.DockingWindowManager; import docking.KeyEntryTextField; import docking.action.DockingActionIf; import docking.tool.util.DockingToolConstants; import docking.widgets.MultiLineLabel; +import generic.test.TestUtils; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.framework.plugintool.PluginTool; import ghidra.test.AbstractGhidraHeadedIntegrationTest; @@ -233,6 +235,44 @@ public class KeyBindingsTest extends AbstractGhidraHeadedIntegrationTest { assertEquals(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), getKeyStroke(action1)); } + @Test + public void testSetKeyBinding_AltGraphFix() throws Exception { + + // + // This test is verifying a hack that was put in to fix the difference in 'Alt' key handling + // on Windows (https://bugs.openjdk.java.net/browse/JDK-8194873). + // Create an action and set the keybinding to use the 'Alt' modifier. + // Verify that the action will also get mapped to the 'Alt Graph' modifier. + // + + // verify that no action is mapped to the new binding + int keyCode = KeyEvent.VK_0; + int modifiers = InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK; + KeyEvent keyEvent = + new KeyEvent(dialog, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), modifiers, + keyCode, KeyEvent.CHAR_UNDEFINED); + KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(keyEvent); + DockingWindowManager dwm = DockingWindowManager.getActiveInstance(); + Action action = + (Action) TestUtils.invokeInstanceMethod("getActionForKeyStroke", dwm, keyStroke); + assertNull(action); + + // set the new binding that uses the 'Alt' key + selectRowForAction(action1); + triggerActionKey(keyField, InputEvent.ALT_DOWN_MASK, keyCode); + String keyStrokeString = KeyEntryTextField.parseKeyStroke( + KeyStroke.getKeyStroke(keyCode, InputEvent.ALT_DOWN_MASK)); + assertEquals(keyStrokeString, keyField.getText()); + apply(); + assertEquals(KeyStroke.getKeyStroke(keyCode, InputEvent.ALT_DOWN_MASK), + getKeyStroke(action1)); + + // verify the additional binding for 'Alt Graph' + action = + (Action) TestUtils.invokeInstanceMethod("getActionForKeyStroke", dwm, keyStroke); + assertNotNull(action); + } + @Test public void testClearKeyBinding1() throws Exception { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java index e433c7705a..f2e9140e5c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java @@ -15,6 +15,7 @@ */ package docking.action; +import java.awt.event.InputEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; @@ -76,14 +77,48 @@ public class KeyBindingsManager implements PropertyChangeListener { private void addKeyBinding(ComponentProvider provider, DockingActionIf action, KeyStroke keyStroke) { + if (ReservedKeyBindings.isReservedKeystroke(keyStroke)) { throw new AssertException("Cannot assign action to a reserved keystroke. " + "Action: " + action.getName() + " - Keystroke: " + keyStroke); } - DockingKeyBindingAction existingAction = dockingKeyMap.get(keyStroke); + // map standard keybinding to action + doAddKeyBinding(provider, action, keyStroke); + + fixupAltGraphKeyStrokeMapping(provider, action, keyStroke); + } + + private void fixupAltGraphKeyStrokeMapping(ComponentProvider provider, DockingActionIf action, + KeyStroke keyStroke) { + + // special case + int modifiers = keyStroke.getModifiers(); + if ((modifiers & InputEvent.ALT_DOWN_MASK) == InputEvent.ALT_DOWN_MASK) { + // + // Also register the 'Alt' binding with the 'Alt Graph' mask. This fixes the but + // on Windows (https://bugs.openjdk.java.net/browse/JDK-8194873) + // that have different key codes for the left and right Alt keys. + // + modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; + KeyStroke updateKeyStroke = + KeyStroke.getKeyStroke(keyStroke.getKeyCode(), modifiers, false); + doAddKeyBinding(provider, action, updateKeyStroke, keyStroke); + } + } + + private void doAddKeyBinding(ComponentProvider provider, DockingActionIf action, + KeyStroke keyStroke) { + doAddKeyBinding(provider, action, keyStroke, keyStroke); + } + + private void doAddKeyBinding(ComponentProvider provider, DockingActionIf action, + KeyStroke mappingKeyStroke, KeyStroke actionKeyStroke) { + + DockingKeyBindingAction existingAction = dockingKeyMap.get(mappingKeyStroke); if (existingAction == null) { - dockingKeyMap.put(keyStroke, new MultipleKeyAction(tool, provider, action, keyStroke)); + dockingKeyMap.put(mappingKeyStroke, + new MultipleKeyAction(tool, provider, action, actionKeyStroke)); return; } From b428631bf452c45d5b325ea4021027cb29dda6e5 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 4 Mar 2021 19:12:00 -0500 Subject: [PATCH 071/140] Corrected certification header --- .../framework/util/MultiReleaseContent.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java b/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java index f7ec50de6a..0e6909f086 100644 --- a/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java +++ b/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java @@ -1,7 +1,8 @@ /* ### * IP: Apache License 2.0 - * - * This is fix for a bug found in the Felix Framework: + */ +/*** + * This is fix for a bug found in the Felix Framework: * * https://issues.apache.org/jira/browse/FELIX-6297 * @@ -9,8 +10,8 @@ * * THIS FILE SHOULD BE REMOVED WHEN THE ISSUE IS ADDRESSED. * - */ -/* + *** + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -30,24 +31,15 @@ */ package org.apache.felix.framework.util; -import org.apache.felix.framework.cache.Content; -import org.osgi.framework.Version; - import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.jar.Attributes; +import java.util.*; import java.util.jar.Manifest; +import org.apache.felix.framework.cache.Content; +import org.osgi.framework.Version; + public class MultiReleaseContent implements Content { private final Content m_content; From 5c65fb102d61954ac74d78b6462fb5e98fc05086 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 5 Mar 2021 18:07:16 -0500 Subject: [PATCH 072/140] GP-752 - Add option to disable showing of automatic function comments --- .../java/ghidra/app/util/DisplayableEol.java | 34 ++++---- .../app/util/exporter/ProgramTextWriter.java | 8 +- .../viewer/field/EolCommentFieldFactory.java | 17 +++- .../core/comments/DisplayableEolTest.java | 79 +++++++++++++++++-- 4 files changed, 112 insertions(+), 26 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java index c2dad1ca28..2457f84129 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java @@ -36,7 +36,6 @@ import ghidra.program.util.*; */ public class DisplayableEol { - private static final String VAR_ARGS = "..."; private static final String POINTER_ARROW = "-> "; public static final int MY_EOLS = 0; @@ -48,19 +47,16 @@ public class DisplayableEol { private boolean alwaysShowRepeatable = false; private boolean alwaysShowRefRepeats = false; private boolean alwaysShowAutomatic = false; + private boolean showAutomaticFunctions; private boolean operandsFollowPointerRefs = false; private int maxDisplayLines; private int totalCommentsFound; private boolean useAbbreviatedAutomatic; - /** - * Construct a new DisplayableEol. - * @param cu code unit that may have end of line or repeatable comments. - */ public DisplayableEol(CodeUnit cu, boolean alwaysShowRepeatable, boolean alwaysShowRefRepeats, boolean alwaysShowAutomatic, boolean operandsFollowPointerRefs, int maxDisplayLines, - boolean useAbbreviatedAutomatic) { + boolean useAbbreviatedAutomatic, boolean showAutomaticFunctions) { this.codeUnit = cu; this.alwaysShowRepeatable = alwaysShowRepeatable; this.alwaysShowRefRepeats = alwaysShowRefRepeats; @@ -68,6 +64,7 @@ public class DisplayableEol { this.operandsFollowPointerRefs = operandsFollowPointerRefs; this.maxDisplayLines = maxDisplayLines; this.useAbbreviatedAutomatic = useAbbreviatedAutomatic; + this.showAutomaticFunctions = showAutomaticFunctions; initComments(); } @@ -118,7 +115,8 @@ public class DisplayableEol { } /** - * Return whether the associated code unit has an end of line comment. + * Return whether the associated code unit has an end of line comment + * @return whether the associated code unit has an end of line comment */ public boolean hasEOL() { return (displayCommentArrays[MY_EOLS] != null) && @@ -126,7 +124,8 @@ public class DisplayableEol { } /** - * Return whether the associated code unit has a repeatable comment. + * Return whether the associated code unit has a repeatable comment + * @return whether the associated code unit has a repeatable comment */ public boolean hasRepeatable() { return (displayCommentArrays[MY_REPEATABLES] != null) && @@ -135,7 +134,9 @@ public class DisplayableEol { /** * Return whether any memory reference from this code unit has a repeatable - * comment at the reference's to address. + * comment at the reference's to address + * @return whether any memory reference from this code unit has a repeatable + * comment at the reference's to address */ public boolean hasReferencedRepeatable() { return (displayCommentArrays[REF_REPEATABLES] != null) && @@ -143,10 +144,10 @@ public class DisplayableEol { } /** - * Return whether this code unit has an automatic comment. - * (i.e. any memory reference from this code unit has a - * function defined at the reference's to address, or if the to - * address is a pointer.) + * Return whether this code unit has an automatic comment. For example, a memory reference + * from this code unit has a function defined at the reference's to address, or if the to + * address is a pointer. + * @return whether this code unit has an automatic comment */ public boolean hasAutomatic() { return (displayCommentArrays[MY_AUTOMATIC] != null) && @@ -367,6 +368,10 @@ public class DisplayableEol { private boolean handleDirectFlow(Set set, Reference reference, Program program, Address toAddr) { + if (!showAutomaticFunctions) { + return false; + } + RefType type = reference.getReferenceType(); if (!type.isFlow()) { return false; @@ -537,7 +542,8 @@ public class DisplayableEol { } /** - * Return all the comments (End of Line, Repeatable, Referenced Repeatables, and Referenced Data). + * Return all the comments + * @return the comments */ public String[] getComments() { ArrayList list = new ArrayList<>(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ProgramTextWriter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ProgramTextWriter.java index aed2306b5c..e17d76ca5c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ProgramTextWriter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ProgramTextWriter.java @@ -290,7 +290,7 @@ class ProgramTextWriter { if (options.isShowComments()) { DisplayableEol displayableEol = new DisplayableEol(currentCodeUnit, false, false, - false, true, 6 /* arbitrary! */, true); + false, true, 6 /* arbitrary! */, true, true); String[] eol = displayableEol.getComments(); if (eol != null && eol.length > 0) { len = options.getAddrWidth() + options.getBytesWidth() + @@ -618,8 +618,10 @@ class ProgramTextWriter { if (options.isHTML()) { Reference ref = - cu.getProgram().getReferenceManager().getPrimaryReferenceFrom(cuAddress, - i); + cu.getProgram() + .getReferenceManager() + .getPrimaryReferenceFrom(cuAddress, + i); addReferenceLinkedText(ref, opReps[i], true); } else { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java index 1a87e82a97..aaf563dc69 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java @@ -58,6 +58,8 @@ public class EolCommentFieldFactory extends FieldFactory { GROUP_TITLE + Options.DELIMITER + "Always Show the Automatic Comment"; public static final String USE_ABBREVIATED_AUTOMITIC_COMMENT_MSG = GROUP_TITLE + Options.DELIMITER + "Use Abbreviated Automatic Comments"; + public static final String SHOW_FUNCTION_AUTOMITIC_COMMENT_MSG = + GROUP_TITLE + Options.DELIMITER + "Show Function Reference Automatic Comments"; public final static String ENABLE_PREPEND_REF_ADDRESS_MSG = GROUP_TITLE + Options.DELIMITER + "Prepend the Address to Each Referenced Comment"; public static final Color DEFAULT_COLOR = Color.BLUE; @@ -69,6 +71,7 @@ public class EolCommentFieldFactory extends FieldFactory { private boolean alwaysShowRefRepeatables; private boolean alwaysShowAutomatic; private boolean useAbbreviatedAutomatic; + private boolean showAutomaticFunctions; private boolean prependRefAddress; private Color repeatableCommentColor; private Color automaticCommentColor; @@ -92,7 +95,7 @@ public class EolCommentFieldFactory extends FieldFactory { /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. */ @@ -126,6 +129,9 @@ public class EolCommentFieldFactory extends FieldFactory { "aren't any EOL or repeatable comments."); fieldOptions.registerOption(USE_ABBREVIATED_AUTOMITIC_COMMENT_MSG, true, hl, "When showing automatic comments, show the smallest amount of information possible"); + fieldOptions.registerOption(SHOW_FUNCTION_AUTOMITIC_COMMENT_MSG, true, hl, + "When showing automatic comments, show direct function references"); + fieldOptions.registerOption(ENABLE_PREPEND_REF_ADDRESS_MSG, false, hl, "Displays the address before each referenced repeatable comment."); @@ -153,6 +159,9 @@ public class EolCommentFieldFactory extends FieldFactory { alwaysShowAutomatic = fieldOptions.getBoolean(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, false); useAbbreviatedAutomatic = fieldOptions.getBoolean(USE_ABBREVIATED_AUTOMITIC_COMMENT_MSG, true); + showAutomaticFunctions = + fieldOptions.getBoolean(SHOW_FUNCTION_AUTOMITIC_COMMENT_MSG, true); + prependRefAddress = fieldOptions.getBoolean(ENABLE_PREPEND_REF_ADDRESS_MSG, false); fieldOptions.getOptions(GROUP_TITLE).setOptionsHelpLocation(hl); @@ -300,7 +309,7 @@ public class EolCommentFieldFactory extends FieldFactory { DisplayableEol displayableEol = new DisplayableEol(cu, alwaysShowRepeatable, alwaysShowRefRepeatables, alwaysShowAutomatic, codeUnitFormatOptions.followReferencedPointers(), - maxDisplayLines, useAbbreviatedAutomatic); + maxDisplayLines, useAbbreviatedAutomatic, showAutomaticFunctions); ArrayList elementList = new ArrayList<>(); // This Code Unit's End of Line Comment @@ -500,7 +509,7 @@ public class EolCommentFieldFactory extends FieldFactory { DisplayableEol displayableEol = new DisplayableEol(cu, alwaysShowRepeatable, alwaysShowRefRepeatables, alwaysShowAutomatic, codeUnitFormatOptions.followReferencedPointers(), - maxDisplayLines, useAbbreviatedAutomatic); + maxDisplayLines, useAbbreviatedAutomatic, showAutomaticFunctions); // Hold position in connected tool if navigating within semicolon. int numLeadColumns = 0; @@ -537,7 +546,7 @@ public class EolCommentFieldFactory extends FieldFactory { DisplayableEol displayableEol = new DisplayableEol((CodeUnit) obj, alwaysShowRepeatable, alwaysShowRefRepeatables, alwaysShowAutomatic, codeUnitFormatOptions.followReferencedPointers(), - maxDisplayLines, useAbbreviatedAutomatic); + maxDisplayLines, useAbbreviatedAutomatic, showAutomaticFunctions); ListingTextField btf = (ListingTextField) bf; diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/comments/DisplayableEolTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/comments/DisplayableEolTest.java index ba13aa118b..f3c26b48dc 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/comments/DisplayableEolTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/comments/DisplayableEolTest.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.comments; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.nio.charset.StandardCharsets; @@ -32,6 +32,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.Listing; +import ghidra.program.model.symbol.RefType; import ghidra.program.model.symbol.SourceType; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.util.exception.RollbackException; @@ -60,6 +61,9 @@ public class DisplayableEolTest extends AbstractGenericTest { // testReferenceToOffcutStringData_UseAbbreviatedCommentOption() builder.createEncodedString("1001234", "one.two", StandardCharsets.US_ASCII, false); + // testReferenceToFunction() + builder.createFunction("0x1001050"); + program = builder.getProgram(); } @@ -68,7 +72,8 @@ public class DisplayableEolTest extends AbstractGenericTest { Listing listing = program.getListing(); CodeUnit cu = listing.getCodeUnitAt(addr("0x110")); - DisplayableEol displayableEol = new DisplayableEol(cu, true, true, true, false, 5, true); + DisplayableEol displayableEol = + new DisplayableEol(cu, true, true, true, false, 5, true, true); String[] comments = displayableEol.getAutomaticComment(); assertEquals(1, comments.length); @@ -84,7 +89,8 @@ public class DisplayableEolTest extends AbstractGenericTest { Listing listing = program.getListing(); CodeUnit cu = listing.getCodeUnitAt(addr("0x1001000")); - DisplayableEol displayableEol = new DisplayableEol(cu, true, true, true, false, 5, true); + DisplayableEol displayableEol = + new DisplayableEol(cu, true, true, true, false, 5, true, true); String[] comments = displayableEol.getAutomaticComment(); assertEquals(1, comments.length); @@ -107,7 +113,31 @@ public class DisplayableEolTest extends AbstractGenericTest { boolean useAbbreviatedComments = false; DisplayableEol displayableEol = - new DisplayableEol(cu, true, true, true, false, 5, useAbbreviatedComments); + new DisplayableEol(cu, true, true, true, false, 5, useAbbreviatedComments, true); + + String[] comments = displayableEol.getAutomaticComment(); + assertEquals(1, comments.length); + assertEquals("= \"one.two\"", comments[0]); + } + + @Test + public void testReferenceToFunction_ShowAutomaticFunctionsOff() throws Exception { + + Address dataStartAddress = addr("0x1001234"); + Address offcutAddress = dataStartAddress.add(2); + Command cmd = + new AddMemRefCmd(addr("0x1001000"), offcutAddress, SourceType.USER_DEFINED, 0, true); + applyCmd(cmd); + + Listing listing = program.getListing(); + CodeUnit cu = listing.getCodeUnitAt(addr("0x1001000")); + + // with this at false, all of the string will be rendered + boolean useAbbreviatedComments = false; + boolean showAutoFunctions = false; + DisplayableEol displayableEol = + new DisplayableEol(cu, true, true, true, false, 5, useAbbreviatedComments, + showAutoFunctions); String[] comments = displayableEol.getAutomaticComment(); assertEquals(1, comments.length); @@ -133,13 +163,52 @@ public class DisplayableEolTest extends AbstractGenericTest { boolean useAbbreviatedComments = true; DisplayableEol displayableEol = - new DisplayableEol(cu, true, true, true, false, 5, useAbbreviatedComments); + new DisplayableEol(cu, true, true, true, false, 5, useAbbreviatedComments, true); String[] comments = displayableEol.getAutomaticComment(); assertEquals(1, comments.length); assertEquals("= \"two\"", comments[0]);// full string is one.two } + @Test + public void testReferenceToFunction_ShowAutomaticFunctions() throws Exception { + + Address from = addr("0x1001000"); + Address toFunction = addr("0x1001050"); + + applyCmd(new AddMemRefCmd(from, toFunction, RefType.UNCONDITIONAL_CALL, SourceType.ANALYSIS, + 0, true)); + + Listing listing = program.getListing(); + CodeUnit cu = listing.getCodeUnitAt(from); + boolean showAutoFunctions = true; + DisplayableEol displayableEol = + new DisplayableEol(cu, true, true, true, false, 5, false, showAutoFunctions); + + String[] comments = displayableEol.getAutomaticComment(); + assertEquals(1, comments.length); + assertEquals("undefined FUN_01001050()", comments[0]); + } + + @Test + public void testReferenceToFunction_DontShowAutomaticFunctions() throws Exception { + + Address from = addr("0x1001000"); + Address toFunction = addr("0x1001050"); + + applyCmd(new AddMemRefCmd(from, toFunction, RefType.UNCONDITIONAL_CALL, SourceType.ANALYSIS, + 0, true)); + + Listing listing = program.getListing(); + CodeUnit cu = listing.getCodeUnitAt(from); + boolean showAutoFunctions = false; + DisplayableEol displayableEol = + new DisplayableEol(cu, true, true, true, false, 5, false, showAutoFunctions); + + String[] comments = displayableEol.getAutomaticComment(); + assertEquals(0, comments.length); + } + public boolean applyCmd(Command cmd) throws RollbackException { return AbstractGhidraHeadlessIntegrationTest.applyCmd(program, cmd); } From c905c203f0300abdd8ef12ca847ec65111b6bd17 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 5 Mar 2021 18:20:15 -0500 Subject: [PATCH 073/140] GP-0 experiment with test failure setting --- gradle/javaTestProject.gradle | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gradle/javaTestProject.gradle b/gradle/javaTestProject.gradle index dee67dc475..ee57176b04 100644 --- a/gradle/javaTestProject.gradle +++ b/gradle/javaTestProject.gradle @@ -125,7 +125,12 @@ def initTestJVM(Task task, String rootDirName) { mkdir testOutputDir } // If false, testing will halt when an error is found. - task.ignoreFailures true + // TODO: test.java provides test task for nightly jUnits - setting this + // here can cause sub-project builds to proceed even when tests fail. + // If test report not generated that task could be changed to always + // run even on failure (e.g., options.failOnError(false) ) + // task.ignoreFailures true + task.failFast false // If false, then tests are re-run every time, even if no code has changed. task.outputs.upToDateWhen {false} From bba3218d69992692162579669fd85fe9066325b6 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 8 Mar 2021 11:59:09 -0500 Subject: [PATCH 074/140] GP-755 - Function Graph - fixed bug that caused preferred width of some nodes to get incorrectly calculated Closes #1008 --- .../functiongraph/graph/vertex/FGVertexListingPanel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java index 6e48cd2a4e..a45a2e077c 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java @@ -141,6 +141,7 @@ public class FGVertexListingPanel extends ListingPanel { @Override public Dimension getPreferredSize() { + Dimension preferredSize = super.getPreferredSize(); if (preferredSize.equals(lastParentPreferredSize) && preferredSizeCache != null) { return preferredSizeCache; @@ -164,8 +165,8 @@ public class FGVertexListingPanel extends ListingPanel { private List getAllLayouts(LayoutModel layoutModel) { List list = new ArrayList<>(); - Layout layout = layoutModel.getLayout(BigInteger.ZERO); - BigInteger index = BigInteger.ONE; + BigInteger index = BigInteger.ZERO; + Layout layout = layoutModel.getLayout(index); while (layout != null) { list.add(layout); index = layoutModel.getIndexAfter(index); From 1c356782d4bfcf7ba49324e3a81a9ff65f5b991d Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 8 Mar 2021 12:18:19 -0500 Subject: [PATCH 075/140] GP-756 - Function Graph - fixed exception that can happen when showing a graph popup for a component that was hidden before the timer expired Closes #1643 --- .../app/plugin/core/hover/AbstractHoverProvider.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractHoverProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractHoverProvider.java index 564268be37..3eccd3e4bf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractHoverProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractHoverProvider.java @@ -139,6 +139,13 @@ public abstract class AbstractHoverProvider implements HoverProvider { return; } + Component component = event.getComponent(); + if (!component.isShowing()) { + // This can happen since we are using a timer. When the timer fires, the source + // component may have been hidden. + return; + } + ProgramLocation loc = getHoverLocation(fieldLocation, field, fieldBounds, event); for (HoverService hoverService : hoverServices) { JComponent comp = hoverService.getHoverComponent(program, loc, fieldLocation, field); From e619d8ab723a3e1dea5c5e60406ad24d907cd0a7 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 8 Mar 2021 12:32:19 -0500 Subject: [PATCH 076/140] GP-757 - Function Graph - fixed bug that colored the entire vertex when only the entry point had a color applied Closes #1080 --- .../core/functiongraph/ToolBasedColorProvider.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/ToolBasedColorProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/ToolBasedColorProvider.java index c4e9012afc..f5ba5c8d0b 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/ToolBasedColorProvider.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/ToolBasedColorProvider.java @@ -22,6 +22,7 @@ import ghidra.app.plugin.core.colorizer.ColorizingService; import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex; import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphVertexAttributes; import ghidra.framework.options.SaveState; +import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.Program; class ToolBasedColorProvider implements FGColorProvider { @@ -102,6 +103,15 @@ class ToolBasedColorProvider implements FGColorProvider { // The loading/saving of colors is handled automatically by the service, but this is // for the background of the code units stored in the DB. We still have to let this // vertex know that it has a custom background. + + AddressSetView addresses = vertex.getAddresses(); + AddressSetView allColorAddress = service.getAllBackgroundColorAddresses(); + if (!allColorAddress.contains(addresses)) { + // sparse colors for the addresses of this node; assume this has not been colored + // from the function graph, but from the service for individual addresses. + return; + } + Color savedColor = service.getBackgroundColor(vertex.getVertexAddress()); if (savedColor != null) { vertex.restoreColor(savedColor); From 9e785c25ec04fa6f4f77d66771334540123cbeb7 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 8 Mar 2021 18:15:27 -0500 Subject: [PATCH 077/140] GP-757 - Function Graph - added options to set background color for graph view and for the vertices Closes #1324 --- .../plugin/core/functiongraph/FGProvider.java | 4 +++ .../functiongraph/FunctionGraphPlugin.java | 2 ++ .../core/functiongraph/graph/FGComponent.java | 27 +++++++++++++------ .../functiongraph/graph/FGPrimaryViewer.java | 1 - .../vertex/AbstractGraphComponentPanel.java | 3 --- .../functiongraph/graph/vertex/FGVertex.java | 6 ++--- .../graph/vertex/FGVertexListingPanel.java | 6 +++++ .../GroupedFunctionGraphComponentPanel.java | 15 +++++++++++ .../vertex/ListingGraphComponentPanel.java | 18 +++++++++++-- .../core/functiongraph/mvc/FGController.java | 7 ++++- .../plugin/core/functiongraph/mvc/FGView.java | 1 - .../mvc/FunctionGraphOptions.java | 24 ++++++++++++++++- .../ghidra/graph/viewer/GraphComponent.java | 22 ++++++++++++--- .../java/ghidra/graph/viewer/GraphViewer.java | 7 ++++- .../graph/viewer/SatelliteGraphViewer.java | 12 ++++++++- .../ghidra/graph/viewer/VisualGraphView.java | 11 +++++--- .../viewer/options/VisualGraphOptions.java | 13 +++++++++ ...TestGraphAlgorithmSteppingViewerPanel.java | 1 - 18 files changed, 150 insertions(+), 30 deletions(-) diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java index 40d6e65325..509ca88a7e 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java @@ -578,6 +578,10 @@ public class FGProvider extends VisualGraphComponentProvider // the base class builds. // super(data.getFunctionGraph()); + setGraphOptions(functionGraphView.getController().getFunctionGraphOptions()); + setGraph(data.getFunctionGraph()); this.functionGraphView = functionGraphView; @@ -217,13 +220,19 @@ public class FGComponent extends GraphComponent edgeLabelRenderer.setRotateEdgeLabels(false); renderContext.setEdgeLabelRenderer(edgeLabelRenderer); - // Give user notice when seeing the graph for a non-function. - Function function = functionGraphData.getFunction(); - if (function instanceof UndefinedFunction) { - viewer.setBackground(UNDEFINED_FUNCTION_COLOR); - } - else { - viewer.setBackground(Color.WHITE); + viewer.setGraphOptions(options); + Color bgColor = options.getGraphBackgroundColor(); + if (bgColor.equals(VisualGraphOptions.DEFAULT_GRAPH_BACKGROUND_COLOR)) { + + // Give user notice when seeing the graph for a non-function. Don't do this if the + // user has manually set the background color (this would require another option). + Function function = functionGraphData.getFunction(); + if (function instanceof UndefinedFunction) { + viewer.setBackground(UNDEFINED_FUNCTION_COLOR); + } + else { + viewer.setBackground(Color.WHITE); + } } return viewer; @@ -248,6 +257,8 @@ public class FGComponent extends GraphComponent renderContext.setVertexFillPaintTransformer(new FGVertexPickableBackgroundPaintTransformer( pickedVertexState, Color.YELLOW, START_COLOR, END_COLOR)); + viewer.setGraphOptions(options); + return viewer; } @@ -274,7 +285,7 @@ public class FGComponent extends GraphComponent //================================================================================================== public FunctionGraphOptions getFucntionGraphOptions() { - return functionGraphView.getController().getFunctionGraphOptions(); + return (FunctionGraphOptions) options; } public void ensureCursorVisible(FGVertex vertex) { diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGPrimaryViewer.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGPrimaryViewer.java index 611f88165c..f72c883e72 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGPrimaryViewer.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGPrimaryViewer.java @@ -33,7 +33,6 @@ public class FGPrimaryViewer extends GraphViewer { super(layout, size); setVertexTooltipProvider(new FGVertexTooltipProvider()); - setGraphOptions(graphComponent.getFucntionGraphOptions()); } @Override diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/AbstractGraphComponentPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/AbstractGraphComponentPanel.java index 694821e678..bab59ea77b 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/AbstractGraphComponentPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/AbstractGraphComponentPanel.java @@ -140,9 +140,6 @@ public abstract class AbstractGraphComponentPanel extends JPanel { } Component header = getHeader(); - if (clickedComponent == null) { - return false; - } return SwingUtilities.isDescendingFrom(clickedComponent, header); } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java index 8dc6ef9bd5..aa91525a45 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java @@ -98,7 +98,7 @@ public interface FGVertex extends VisualVertex { * grouped, but that it has been part of a group and can be put back into its group form * again. * - * @param groupMember True if this vertex is a associate with a group + * @param groupInfo True if this vertex is a associate with a group */ public void updateGroupAssociationStatus(GroupHistoryInfo groupInfo); @@ -190,8 +190,8 @@ public interface FGVertex extends VisualVertex { public void refreshDisplay(); /** - * Refresh the vertex's display information if the given address is the entry point - * of the vertex. + * Refresh the vertex's display information if the given address is the vertex entry point + * @param address the addresses */ public void refreshDisplayForAddress(Address address); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java index 6e48cd2a4e..9a14f74849 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertexListingPanel.java @@ -15,6 +15,7 @@ */ package ghidra.app.plugin.core.functiongraph.graph.vertex; +import java.awt.Color; import java.awt.Dimension; import java.math.BigInteger; import java.util.ArrayList; @@ -23,6 +24,7 @@ import java.util.List; import docking.widgets.fieldpanel.*; import ghidra.app.plugin.core.functiongraph.FGColorProvider; import ghidra.app.plugin.core.functiongraph.mvc.FGController; +import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphOptions; import ghidra.app.util.viewer.format.FormatManager; import ghidra.app.util.viewer.listingpanel.*; import ghidra.program.model.address.AddressSetView; @@ -66,6 +68,10 @@ public class FGVertexListingPanel extends ListingPanel { ListingModel model = getListingModel(); model.addListener(listener); + FunctionGraphOptions options = controller.getFunctionGraphOptions(); + Color color = options.getDefaultVertexBackgroundColor(); + setTextBackgroundColor(color); + FGColorProvider colorProvider = controller.getColorProvider(); if (!colorProvider.isUsingCustomColors()) { enablePropertyBasedColorModel(true); // turn on user colors in the graph diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/GroupedFunctionGraphComponentPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/GroupedFunctionGraphComponentPanel.java index f179bd1969..968d389383 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/GroupedFunctionGraphComponentPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/GroupedFunctionGraphComponentPanel.java @@ -382,6 +382,7 @@ public class GroupedFunctionGraphComponentPanel extends AbstractGraphComponentPa } private void doSetBackgroundColor(Color color) { + setBackground(color); contentPanel.setBackground(color); userTextArea.setBackground(color); controller.removeColor(vertex); @@ -561,12 +562,26 @@ public class GroupedFunctionGraphComponentPanel extends AbstractGraphComponentPa @Override void refreshDisplay() { + + updateDefaultBackgroundColor(); + Set vertices = groupVertex.getVertices(); for (FGVertex v : vertices) { v.refreshDisplay(); } } + private void updateDefaultBackgroundColor() { + FunctionGraphOptions options = controller.getFunctionGraphOptions(); + Color newBgColor = options.getDefaultGroupBackgroundColor(); + if (!defaultBackgroundColor.equals(newBgColor)) { + defaultBackgroundColor = newBgColor; + if (userDefinedColor == null) { + doSetBackgroundColor(defaultBackgroundColor); + } + } + } + @Override void refreshDisplayForAddress(Address address) { Set vertices = groupVertex.getVertices(); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java index 1d5441d98b..7ef201fd55 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java @@ -251,6 +251,19 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel { title = createTitle(); genericHeader.setTitle(title); previewListingPanel = null; + + updateDefaultBackgroundColor(); + } + + private void updateDefaultBackgroundColor() { + FunctionGraphOptions options = controller.getFunctionGraphOptions(); + Color newBgColor = options.getDefaultVertexBackgroundColor(); + if (!defaultBackgroundColor.equals(newBgColor)) { + defaultBackgroundColor = newBgColor; + if (userDefinedColor == null) { + listingPanel.setTextBackgroundColor(defaultBackgroundColor); + } + } } @Override @@ -522,8 +535,9 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel { tooltipTitleLabel.setText("From: " + getTitle()); } - previewListingPanel.getFieldPanel().setBackgroundColorModel( - new HighlightingColorModel(address, getColorForEdge(edge))); + previewListingPanel.getFieldPanel() + .setBackgroundColorModel( + new HighlightingColorModel(address, getColorForEdge(edge))); } private void initializeToolTipComponent(Address goToAddress) { diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java index 7a797bc665..ba72707128 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java @@ -332,7 +332,8 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi } private boolean shouldSaveVertexChanges() { - return functionGraphOptions.getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES; + return functionGraphOptions + .getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES; } @Override @@ -634,6 +635,10 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi viewSettings.setLocation(location); } + public void optionsChanged() { + view.optionsChanged(); + } + public void refreshDisplayWithoutRebuilding() { view.refreshDisplayWithoutRebuilding(); } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGView.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGView.java index 1fb83715dd..ad09052a7e 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGView.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGView.java @@ -73,7 +73,6 @@ public class FGView extends VisualGraphView { protected void installGraphViewer() { FGComponent newFgComponent = createGraphComponent(); - newFgComponent.setGraphOptions(controller.getFunctionGraphOptions()); setGraphComponent(newFgComponent); // we must assign the variable here, as the call to setGraphComponent() will call diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java index a5f62e1c36..51b6773a9a 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java @@ -70,6 +70,10 @@ public class FunctionGraphOptions extends VisualGraphOptions { "
  • Never - do not automatically relayout the graph


  • " + "See help for more"; + private static final String DEFAULT_VERTEX_BACKGROUND_COLOR_KEY = "Default Vertex Color"; + private static final String DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION = + "The default background color applied to each vertex"; + private static final String DEFAULT_GROUP_BACKGROUND_COLOR_KEY = "Default Group Color"; private static final String DEFAULT_GROUP_BACKGROUND_COLOR_DESCRPTION = "The default background color applied to newly created group vertices"; @@ -80,11 +84,14 @@ public class FunctionGraphOptions extends VisualGraphOptions { "Signals that any user color changes to a group vertex will apply that same color to " + "all grouped vertices as well."; + public static final Color DEFAULT_VERTEX_BACKGROUND_COLOR = Color.WHITE; public static final Color DEFAULT_GROUP_BACKGROUND_COLOR = new Color(226, 255, 155); private static final Color HOVER_HIGHLIGHT_FALL_THROUGH_COLOR = new Color(255, 127, 127); private static final Color HOVER_HIGHLIGHT_UNCONDITIONAL_COLOR = new Color(127, 127, 255); private static final Color HOVER_HIGHLIGHT_CONDITIONAL_COLOR = Color.GREEN; + private Color defaultVertexBackgroundColor = DEFAULT_VERTEX_BACKGROUND_COLOR; + private boolean updateGroupColorsAutomatically = true; private Color defaultGroupBackgroundColor = DEFAULT_GROUP_BACKGROUND_COLOR; @@ -104,6 +111,10 @@ public class FunctionGraphOptions extends VisualGraphOptions { private Map layoutOptionsByName = new HashMap<>(); + public Color getDefaultVertexBackgroundColor() { + return defaultVertexBackgroundColor; + } + public Color getDefaultGroupBackgroundColor() { return defaultGroupBackgroundColor; } @@ -174,6 +185,12 @@ public class FunctionGraphOptions extends VisualGraphOptions { options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help, SCROLL_WHEEL_PANS_DESCRIPTION); + options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, + help, GRAPH_BACKGROUND_COLOR_DESCRPTION); + + options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR, + help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION); + options.registerOption(DEFAULT_GROUP_BACKGROUND_COLOR_KEY, DEFAULT_GROUP_BACKGROUND_COLOR, help, DEFAULT_GROUP_BACKGROUND_COLOR_DESCRPTION); @@ -242,6 +259,12 @@ public class FunctionGraphOptions extends VisualGraphOptions { scrollWheelPans = options.getBoolean(SCROLL_WHEEL_PANS_KEY, scrollWheelPans); + graphBackgroundColor = + options.getColor(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR); + + defaultVertexBackgroundColor = + options.getColor(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR); + defaultGroupBackgroundColor = options.getColor(DEFAULT_GROUP_BACKGROUND_COLOR_KEY, DEFAULT_GROUP_BACKGROUND_COLOR); @@ -308,5 +331,4 @@ public class FunctionGraphOptions extends VisualGraphOptions { public void setLayoutOptions(String layoutName, FGLayoutOptions options) { layoutOptionsByName.put(layoutName, options); } - } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java index f594fa9702..4c8ca78c84 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java @@ -124,7 +124,7 @@ public class GraphComponent, G e // a cache to prevent unnecessary layout calculations private Dimension lastSize; - private VisualGraphOptions options = new VisualGraphOptions(); + protected VisualGraphOptions options = new VisualGraphOptions(); public GraphComponent(G graph) { @@ -208,9 +208,7 @@ public class GraphComponent, G e renderContext.setVertexFillPaintTransformer( new PickableVertexPaintTransformer<>(pickedVertexState, Color.WHITE, Color.YELLOW)); - viewer.setBackground(Color.WHITE); - - viewer.setGraphOptions(new VisualGraphOptions()); + viewer.setGraphOptions(options); return viewer; } @@ -297,6 +295,8 @@ public class GraphComponent, G e SatelliteGraphViewer viewer = createSatelliteGraphViewer(masterViewer, viewerSize); + viewer.setGraphOptions(options); + viewer.setMinimumSize(viewerSize); viewer.setMaximumSize(viewerSize); @@ -525,6 +525,15 @@ public class GraphComponent, G e public void setGraphOptions(VisualGraphOptions options) { this.options = options; + + // the viewers may be null if called during initialization + if (primaryViewer != null) { + primaryViewer.setGraphOptions(options); + } + + if (satelliteViewer != null) { + satelliteViewer.setGraphOptions(options); + } } public boolean isUninitialized() { @@ -562,6 +571,11 @@ public class GraphComponent, G e return mainPanel; } + public void optionsChanged() { + primaryViewer.optionsChanged(); + satelliteViewer.optionsChanged(); + } + public void repaint() { mainPanel.repaint(); } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java index 98d9905e67..b205417372 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java @@ -88,7 +88,7 @@ public class GraphViewer> gPickedState = new GPickedState<>((MultiPickedState) pickedState); setPickedVertexState(gPickedState); - popupRegulator = new PopupRegulator(new GraphViewerPopupSource()); + popupRegulator = new PopupRegulator<>(new GraphViewerPopupSource()); } private void buildUpdater() { @@ -158,6 +158,11 @@ public class GraphViewer> public void setGraphOptions(VisualGraphOptions options) { this.options = options; + optionsChanged(); + } + + public void optionsChanged() { + setBackground(options.getGraphBackgroundColor()); } public VisualGraphOptions getOptions() { diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java index 7abe574565..c178f7d2ac 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java @@ -21,6 +21,7 @@ import edu.uci.ics.jung.visualization.control.SatelliteVisualizationViewer; import edu.uci.ics.jung.visualization.renderers.Renderer; import ghidra.graph.viewer.event.mouse.VisualGraphPluggableGraphMouse; import ghidra.graph.viewer.event.mouse.VisualGraphSatelliteGraphMouse; +import ghidra.graph.viewer.options.VisualGraphOptions; import ghidra.graph.viewer.renderer.VisualGraphRenderer; import ghidra.graph.viewer.renderer.VisualVertexSatelliteRenderer; @@ -36,6 +37,7 @@ public class SatelliteGraphViewer graphViewer; private boolean docked; + private VisualGraphOptions options; public SatelliteGraphViewer(GraphViewer master, Dimension preferredSize) { super(master, preferredSize); @@ -73,6 +75,15 @@ public class SatelliteGraphViewer(); } + public void setGraphOptions(VisualGraphOptions options) { + this.options = options; + optionsChanged(); + } + + public void optionsChanged() { + setBackground(options.getGraphBackgroundColor()); + } + @SuppressWarnings("unchecked") @Override public VisualGraphPluggableGraphMouse getGraphMouse() { @@ -87,5 +98,4 @@ public class SatelliteGraphViewerbut does not actually perform a layout. * @param newLayoutProvider the new provider @@ -201,7 +207,6 @@ public class VisualGraphView newGraphComponent = new GraphComponent<>(graph); - newGraphComponent.setGraphOptions(new VisualGraphOptions()); setGraphComponent(newGraphComponent); } @@ -522,7 +527,7 @@ public class VisualGraphView newSource = getPrimaryGraphViewer(); - return new MouseEvent(newSource, e.getID(), e.getWhen(), e.getModifiers(), + return new MouseEvent(newSource, e.getID(), e.getWhen(), e.getModifiersEx(), (int) viewerPoint.getX(), (int) viewerPoint.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java index 458c445409..ef7aab20bd 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java @@ -15,10 +15,16 @@ */ package ghidra.graph.viewer.options; +import java.awt.Color; + import docking.DockingUtils; public class VisualGraphOptions { + public static final String GRAPH_BACKGROUND_COLOR_KEY = "Graph Background Color"; + public static final String GRAPH_BACKGROUND_COLOR_DESCRPTION = + "The graph display background color"; + public static final String SHOW_ANIMATION_OPTIONS_KEY = "Use Animation"; public static final String SHOW_ANIMATION_DESCRIPTION = "Signals to the Function Graph to " + "use animated transitions for certain operations, like navigation."; @@ -48,6 +54,9 @@ public class VisualGraphOptions { "new graphs and already rendered graphs are zoomed and positioned. See the help for " + "more details."; + public static final Color DEFAULT_GRAPH_BACKGROUND_COLOR = Color.WHITE; + protected Color graphBackgroundColor = DEFAULT_GRAPH_BACKGROUND_COLOR; + protected boolean useAnimation = true; protected boolean scrollWheelPans = false; @@ -59,6 +68,10 @@ public class VisualGraphOptions { protected ViewRestoreOption viewRestoreOption = ViewRestoreOption.START_FULLY_ZOOMED_OUT; + public Color getGraphBackgroundColor() { + return graphBackgroundColor; + } + public boolean getScrollWheelPans() { return scrollWheelPans; } diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/TestGraphAlgorithmSteppingViewerPanel.java b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/TestGraphAlgorithmSteppingViewerPanel.java index f83fad28a7..6f490e53a0 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/TestGraphAlgorithmSteppingViewerPanel.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/TestGraphAlgorithmSteppingViewerPanel.java @@ -151,7 +151,6 @@ public class TestGraphAlgorithmSteppingViewerPanel> extend tvg.setLayout(layout); viewer = new GraphViewer<>(layout, new Dimension(400, 400)); - viewer.setBackground(Color.WHITE); viewer.setGraphOptions(new VisualGraphOptions()); Renderer, AlgorithmTestSteppingEdge> renderer = From 859e09e4bcd2c6c03e169a3bb7a52d38b4de5484 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 9 Mar 2021 08:19:37 -0500 Subject: [PATCH 078/140] GP-757 - Function Graph - review fixes --- .../plugin/core/functiongraph/graph/FGComponent.java | 6 ++++-- .../core/functiongraph/graph/vertex/FGVertex.java | 12 +++++++----- .../ghidra/graph/viewer/SatelliteGraphViewer.java | 7 +++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java index df54fdde86..5ff8fb5e7d 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java @@ -224,8 +224,10 @@ public class FGComponent extends GraphComponent Color bgColor = options.getGraphBackgroundColor(); if (bgColor.equals(VisualGraphOptions.DEFAULT_GRAPH_BACKGROUND_COLOR)) { - // Give user notice when seeing the graph for a non-function. Don't do this if the - // user has manually set the background color (this would require another option). + // Give user notice when seeing the graph for a non-function (such as an undefined + // function), as this is typical for Ghidra UI widgets. + // Don't do this if the user has manually set the background color (this would require + // another option). Function function = functionGraphData.getFunction(); if (function instanceof UndefinedFunction) { viewer.setBackground(UNDEFINED_FUNCTION_COLOR); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java index aa91525a45..2ba6a0d9fb 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/FGVertex.java @@ -93,15 +93,17 @@ public interface FGVertex extends VisualVertex { public void clearColor(); /** - * Signals to this vertex that it is associated with a group. False implies that this vertex - * is not and has not been part of a group. True signals that this vertex is not currently - * grouped, but that it has been part of a group and can be put back into its group form - * again. + * Signals to this vertex that it is associated with a group * - * @param groupInfo True if this vertex is a associate with a group + * @param groupInfo the new group info for this vertex; null if the vertex is no longer part + * of a group */ public void updateGroupAssociationStatus(GroupHistoryInfo groupInfo); + /** + * The group info for this vertex if it is in a group; null if not in a group + * @return the group info or null + */ public GroupHistoryInfo getGroupInfo(); /** diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java index c178f7d2ac..71f04eb432 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/SatelliteGraphViewer.java @@ -75,11 +75,18 @@ public class SatelliteGraphViewer(); } + /** + * The options for this viewer + * @param options the options + */ public void setGraphOptions(VisualGraphOptions options) { this.options = options; optionsChanged(); } + /** + * Called to signal that the options used by this viewer have changed + */ public void optionsChanged() { setBackground(options.getGraphBackgroundColor()); } From 32e2ef2ee75d0ea6cac5bfd414ae9dfc01053a71 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Wed, 10 Mar 2021 08:34:29 -0500 Subject: [PATCH 079/140] GP-729 Decode RUNTIME_INFO and UNWIND_INFO structures in the PE .pdata section --- .github/ISSUE_TEMPLATE/bug_report.md | 3 +- .../src/global/docs/ChangeHistory.html | 211 ++++--- .../Base/data/PEFunctionsThatDoNotReturn | 8 + .../navigation/GoToAddressLabelPlugin.java | 44 +- .../app/util/bin/format/pe/FileHeader.java | 553 ++++++++++-------- .../pe/ImageRuntimeFunctionEntries.java | 486 +++++++++++++++ .../app/util/bin/format/pe/NTHeader.java | 19 +- .../ghidra/app/util/opinion/PeLoader.java | 81 ++- .../gfilesystem/FileSystemService.java | 2 +- .../ghidra/util/state/VarnodeOperation.java | 3 +- .../datamgr/DataTypeManagerPluginTest.java | 28 +- .../Decompiler/ghidra_scripts/GraphAST.java | 14 +- .../Decompiler/src/main/doc/pcoderef.xml | 2 +- .../core/decompile/actions/ASTGraphTask.java | 9 +- .../formats/sevenzip/SevenZipFileSystem.java | 6 +- .../demangler/gnu/GnuDemanglerParser.java | 15 +- Ghidra/Features/GraphServices/Module.manifest | 4 +- Ghidra/Features/GraphServices/build.gradle | 6 +- .../visualization/DefaultGraphDisplay.java | 96 ++- .../graph/visualization/LayoutFunction.java | 61 +- .../LayoutTransitionManager.java | 62 +- .../visualization/mouse/JgtGraphMouse.java | 8 +- .../mouse/JgtSatelliteGraphMouse.java | 10 +- .../mouse/JgtSelectingGraphMousePlugin.java | 10 +- .../src/main/resources/jungrapht.properties | 12 +- .../util/pdb/pdbapplicator/PdbApplicator.java | 5 +- .../main/java/docking/ActionToGuiMapper.java | 5 +- .../main/java/docking/DockableComponent.java | 27 +- .../java/docking/DockingErrorDisplay.java | 37 +- .../java/docking/DockingWindowManager.java | 50 +- .../src/main/java/docking/ErrLogDialog.java | 15 +- .../main/java/docking/PopupActionManager.java | 22 +- .../main/java/docking/PopupMenuContext.java | 61 ++ .../docking/action/KeyBindingsManager.java | 4 +- .../docking/action/ShowContextMenuAction.java | 52 ++ .../java/docking/actions/ToolActions.java | 4 + .../menu/DockingCheckboxMenuItemUI.java | 4 +- .../java/docking/menu/DockingMenuItemUI.java | 3 +- .../main/java/docking/menu/DockingMenuUI.java | 4 +- .../docking/test/AbstractDockingTest.java | 2 +- .../tree/tasks/GTreeStartEditingTask.java | 15 +- .../util/DockingWindowsLookAndFeelUtils.java | 5 +- .../java/ghidra/util/ReservedKeyBindings.java | 9 +- .../util/task/TaskMonitorComponent.java | 18 +- .../docking/framework/SplashScreenTest.java | 107 ++-- .../graph/viewer/popup/PopupRegulator.java | 8 + .../program/model/pcode/PcodeFactory.java | 2 +- .../program/model/pcode/PcodeSyntaxTree.java | 4 +- .../ghidra/program/model/pcode/Varnode.java | 6 +- .../program/model/pcode/VarnodeAST.java | 12 +- .../ghidra/service/graph/GraphDisplay.java | 46 ++ .../ghidra.xtext.sleigh.feature/category.xml | 6 +- .../ghidra.xtext.sleigh.feature/feature.xml | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../META-INF/MANIFEST.MF | 3 +- .../META-INF/MANIFEST.MF | 2 +- .../ghidra.xtext.sleigh/META-INF/MANIFEST.MF | 2 +- .../ghidra.xtext.sleigh/plugin.xml | 6 +- .../src/ghidra/xtext/sleigh/Sleigh.xtext | 3 +- .../languages/html/pcodedescription.html | 2 +- 60 files changed, 1630 insertions(+), 678 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries.java create mode 100644 Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java create mode 100644 Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 385782a424..2882356cb6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -29,7 +29,8 @@ If applicable, please attach any files that caused problems or log files generat **Environment (please complete the following information):** - OS: [e.g. macOS 10.14.2] - Java Version: [e.g. 11.0] - - Ghidra Version: [e.g. 9.0] + - Ghidra Version: [e.g. 9.1.2] + - Ghidra Origin: [e.g. official ghidra-sre.org distro, third party distro, locally built] **Additional context** Add any other context about the problem here. diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html index aabe465742..dc38d983fe 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html @@ -6,14 +6,61 @@ +

    Ghidra 9.2.3 Change History (March 2021)

    +

    Improvements

    +
      +
    • Analysis. Added check for vftable entries in .NEP section and relaxed the requirement that the code must have a return. (GP-649)
    • +
    • Analysis. Corrected flaw in RTTI analyzer determination of size of vftables. (GP-688)
    • +
    • Basic Infrastructure. Updated TLS protocol preference to use the most preferred/recent version available to both sides of an SSL connection (e.g., TLSv1.3) instead of forcing use of TLSv1.2. (GP-622)
    • +
    • Build. Corrected build issues which had prevented users from building Ghidra on an Apple M1 (OS X, AARCH64 architecture). (GP-600, Issue #2653)
    • +
    • Demangler. Increased Gnu Demangler parsing performance by changing some regular expressions. (GP-705)
    • +
    • Eclipse Integration. Updated SleighEditor to support new endian tag on define token definitions. (GP-721)
    • +
    • GUI. Updated the Choose Data Type dialog to apply data types in the same manner as dragging types from the Data Types window. This provides users more control when choosing how to overwrite existing types. (GP-521)
    • +
    • Importer:ELF. Added support for ELF relocation R_X86_64_IRELATIVE. (GP-651, Issue #1189)
    • +
    • Importer:ELF. Sped up loading of ELF files with large symbol tables. (GP-697)
    • +
    +
    +

    Bugs

    +
      +
    • Analysis. The RTTI analyzer now runs prior to Reference analysis so that references into vftables are not turned into code or data before the vftables are created. (GP-517)
    • +
    • API. Funtion.getCalledFunctions(TaskMonitor) and Function.getCallingFunctions(TaskMonitor) now support passing null for the task monitor parameter, which previously would have thrown an exception. (GP-589, Issue #2643)
    • +
    • Data Types. Corrected segmented 32-bit pointer datatype address generation for 16:16 x86 far pointers. (GP-534, Issue #2548)
    • +
    • Decompiler. Fixed Decompiler issue where, when a function name extends beyond the line limit, an end-of-line comment could wrap around to additional lines without including additional // comment indicators. (GP-473)
    • +
    • Decompiler. Corrected an exception that could occur when attempting to edit function signature from the Decompiler. (GP-597, Issue #2601)
    • +
    • Eclipse Integration. When installing the SleighEditor into Eclipse, the plugin will now show up under the Ghidra category. Previously the Group Items by Category option had to be turned off before the SleighEditor would appear as a visible entry. (GP-564)
    • +
    • Eclipse Integration. Fixed an issue with Eclipse PyDev breakpoints not catching. (GP-668, Issue #2713)
    • +
    • Eclipse Integration. Fixed an Eclipse GhidraDev exception that occurred when creating a new Ghidra scripting project if a ~/ghidra_scripts directory did not exist. (GP-669)
    • +
    • Emulator. Replaced Java floating point emulation to fix multiple rounding issues. (GP-357, Issue #2414)
    • +
    • Graphing. Fixed issue with graph filters not updating satellite view when changing edge filters. (GP-557)
    • +
    • Graphing. Fixed Function Graph keybindings that did not work when docked in the main Code Browser window. (GP-586, Issue #2641)
    • +
    • GUI. Fixed NPE due to using Go To action when there was no open program in the Listing. (GP-66)
    • +
    • GUI. Fixed bug in Reference Code Viewer options that caused an exception. (GP-620, Issue #2672)
    • +
    • Importer. Fixed exception caused when importing previously exported XML data where the bookmark override option was turned off. (GP-667)
    • +
    • Importer:ELF. Fixed a NullPointerException caused by importing an ELF with an uninitialized .got section. (GP-360, Issue #2416)
    • +
    • Importer:ELF. Added Support for ELF R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS ELF Relocations for ARM. (GP-555, Issue #2510)
    • +
    • Importer:ELF. Corrected ELF processing of .init_array and .fini_array which was incorrectly overadjusting entries for an image base change. (GP-699)
    • +
    • Importer:Mach-O. Corrected Mach-O fat-binary library import issue and resolved error related to unnamed Mach-O segment. (GP-652, Issue #2702)
    • +
    • Importer:Mach-O. Fixed an issue with DYLD Load Command data structures being created in the wrong locations. (GP-689, Issue #2624)
    • +
    • Importer:Mach-O. Fixed an exception that occurred when importing Mach-O files that define zero LC_BUILD_VERSION tool entries. (GP-702, Issue #2192)
    • +
    • PDB. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)
    • +
    • PDB. Fix PDB Universal analyzer to set the run-once flag when finished. (GP-724)
    • +
    • Processors. Added missing RFE instruction in MIPS up to version R3000. (GP-33, Issue #1766)
    • +
    • Processors. ARM instruction VMUL now decodes correctly. (GP-627, Issue #2677)
    • +
    • Processors. Added missing CFINV instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)
    • +
    • Scripting. Fixed analyzeHeadless -scriptPath option that didn't work for Python and other non-Java scripts located in non-default directories. (GP-528, Issue #2561)
    • +
    • Scripting. Fixed concurrency issue with management of scripting bundle paths. (GP-576)
    • +
    • Scripting. Corrected handling for Ghidra Script files which are symlinks that were broken in Ghidra 9.2. (GP-650, Issue #2698)
    • +
    +
    +

    Ghidra 9.2.2 Change History (December 2020)

    Bugs

    • Graphing. Fixed issue with Graph filters not working and satellite view sometimes not matching graph. (GP-526)
    • -
    • Importer:MachO. MachO DYLD cache incorrect offset use has been fixed. (GP-550, Issue ##2560)
    • -
    • Listing. Fixed issue where Edit Label action (L key) did not work on primary function symbols. (GP-537)
    • +
    • Importer:Mach-O. Mach-O DYLD cache incorrect offset use has been fixed. (GP-550, Issue #2560)
    • +
    • Listing. Fixed issue where Edit Label action (L key) did not work on primary function symbols. (GP-537)
    • Multi-User. Corrected Ghidra Server build issue for version 9.2.1 which had an improperly generated classpath.frag file. Issue caused server to fail startup with a ClassNotFoundException. (GP-542)
    • -
    • Processors. The V850 JMP instruction has been corrected not to use the PC in the address calculation (GP-548, Issue #2570)
    • +
    • Processors. The V850 JMP instruction has been corrected not to use the PC in the address calculation. (GP-548, Issue #2570)
    • Processors. Removed erroneous VST4 variant, most likely from a copy/paste error. This fixes the ARM Thumb BL instruction disassembly with a negative offset. (GP-549, Issue #2559)
    @@ -24,6 +71,7 @@
  • Analysis. Updated RTTI analyzer to find type_info vftable when it cannot be found with its mangled name. This will enable many more Windows programs to have their RTTI structures created that were unable to be parsed in previous Ghidra versions. (GP-141)
  • API. Relaxed memory block naming restrictions and restored ability to have spaces in memory block names. However, if a memory block is flagged as an overlay, the associated overlay space name may be modified to ensure validity and uniqueness. The DuplicateNameException has been removed from all memory block API methods since this was entirely an overlay space concern. Memory block GUI has also been changed eliminate the duplicate block name restriction. (GP-420, Issue #2465)
  • Build. Eliminated the need for installation of bison and flex when performing source-based gradle build of Ghidra or the Decompiler module. The generated files are now included with source files and maintained in source control. A separate gradle Decompiler:generateParsers task, which still requires bison and flex, must be used, explicitly, when changes are made to lex/yacc source files. (GP-467)
  • +
  • Graphing. Fixed issue with exporting graphs to DOT format due to invalid vertex IDs. (GP-280)
  • Graphing. Improved graphing where it did not navigate when clicking on external function nodes. Now it will navigate to the fake function location in the program, which is the location of the pointer to the external function. (GP-493)
  • Listing:Symbols. Removed restriction for naming labels that resemble default label names. (GT-3185, Issue #1057)
  • PDB. Crafted PDB type ID records 0x1608 and 0x1609 with presumed class and struct types and follow-on application of these types. Also fixed up some fall-back data type logic and improved some warning messages to reflect the cause of the conditions. (GP-474, Issue #2523)
  • @@ -37,7 +85,7 @@
  • Decompiler. Fixed issue with the Auto Create/Fill Structure command that caused it to silently miss some pointer accesses. (GP-344)
  • Decompiler. Jump table recovery now takes into account encoded bits, like ARM/THUMB mode transition, that may be present in address tables. (GP-387, Issue #2420)
  • Decompiler. Fixed a bug in the Decompiler renaming action when applied to function references. (GP-477, Issue #2415)
  • -
  • Decompiler. Corrected 8-byte return value storage specification in compiler-spec affecting longlong and double return values. Endianess ordering of r0/r1 was incorrect. (GP-512, Issue #2547)
  • +
  • Decompiler. Corrected 8-byte return value storage specification in compiler-spec affecting longlong and double return values. Endianess ordering of r0/r1 was incorrect. (GP-512, Issue #2547)
  • Graphing. Fixed the Function Graph's drag-to-select-nodes feature. (GP-430)
  • Graphing. Fixed issue where the graph in the satellite view is sometimes truncated. (GP-469)
  • Graphing. Fixed a stack trace issue caused by reusing a graph display window to show a graph that is larger than is allowed. (GP-492)
  • @@ -126,7 +174,7 @@
  • Importer:ELF. Added support for processing Android packed ELF Relocation Tables. (GT-3320, Issue #1192)
  • Importer:ELF. Added ELF import opinion for ARM BE8. (GT-3642, Issue #1187)
  • Importer:ELF. Added support for ELF RELR relocations, such as those produced for Android. (GP-348)
  • -
  • Importer:MachO. DYLD Loader can now load x86_64 DYLD from macOS. (GT-3611, Issue #1566)
  • +
  • Importer:Mach-O. DYLD Loader can now load x86_64 DYLD from macOS. (GT-3611, Issue #1566)
  • Importer:PE. Improved parsing of Microsoft ordinal map files produced with DUMPBIN /EXPORTS (see Ghidra/Features/Base/data/symbols/README.txt). (GT-3235)
  • Jython. Upgraded Jython to version 2.7.2. (GP-109)
  • Listing. In the PCode field of the Listing, accesses of varnodes in the unique space are now always shown with the size of the access. Fixed bug which would cause the PCode emulator to reject valid pcode in rare instances. (GP-196)
  • @@ -282,8 +330,8 @@
  • Disassembly. Corrected potential infinite loop with disassembler caused by branch to self with invalid delay slot instruction. (GT-3511, Issue #1486)
  • GUI. Corrected processor manual display for Microsoft Windows users, which was not displaying processor manual and was, instead, rendering a blank page in web browser. (GT-3444)
  • GUI:Bitfield Editor. Added field comment support to composite bitfield editor. (GT-3410)
  • -
  • Importer:MachO. A MachO loader regression, in Ghidra 9.1.1, when laying down symbols at the correct location, has been fixed. (GT-3487, Issue #1446)
  • -
  • Multi-User:Ghidra Server. Corrected Ghidra Server remote interface errors that occur when running with Java 11.0.6 (and later) release, which would throw RemoteException "Method is not Remote" errors. (GT-3521, Issue #1440)
  • +
  • Importer:Mach-O. A Mach-O loader regression, in Ghidra 9.1.1, when laying down symbols at the correct location, has been fixed. (GT-3487, Issue #1446)
  • +
  • Multi-User:Ghidra Server. Corrected Ghidra Server remote interface errors that occur when running with Java 11.0.6 (and later) release, which would throw RemoteException Method is not Remote errors. (GT-3521, Issue #1440)
  • PDB. Corrected PDB XML generation for zero-length classes and structures and resolved various datatype dependency issues encountered during PDB Analysis. Changed line numbers from hex to decimal. (GT-3462, Issue #1410)
  • Processors. Corrected mnemonic for ARM thumb RSB.w instruction. (GT-3420, Issue #1365)
  • Processors. Corrected issue in M68000 with some move instructions not creating correct array assignments. (GT-3429, Issue #1394)
  • @@ -294,7 +342,7 @@

    Ghidra 9.1.1 Change History (December 2019)

    Improvements

      -
    • Importer:MachO. Improved import/load time of DYLD shared cache files. (GT-3261)
    • +
    • Importer:Mach-O. Improved import/load time of DYLD shared cache files. (GT-3261)
    • Program API. Cached the addresses that correspond to executable memory to improve analysis performance. (GT-3260)
    @@ -331,7 +379,7 @@
  • Eclipse Integration. Added new GhidraSleighEditor Eclipse plugin in the installation directory under Extensions/Eclipse. (GT-113)
  • GUI. Added method for turning off table sorting by control-clicking the only sorted table column. (GT-2763, Issue #87)
  • GUI. Hovering on an address will now show where the byte at that address came from in the imported file. (GT-3016, Issue #154)
  • -
  • Importer:MachO. Added new importer/loader for DYLD-shared cache files. (GT-2343)
  • +
  • Importer:Mach-O. Added new importer/loader for DYLD-shared cache files. (GT-2343)
  • Memory. Added new API to preserve imported program's original bytes and how they map to memory blocks. (GT-2845)
  • Processors. Implemented Intel MCS-96 processor module. (GT-2350)
  • Processors. Added SH1/2/2a sleigh processor specification. (GT-3029, Issue #715)
  • @@ -488,7 +536,7 @@
  • Listing. Cursor in the listing now stays in the proper column after editing a field. (GT-3045, Issue #702)
  • Listing. Fixed a problem with register highlighting that could occur on certain register/sub-register combinations. (GT-3071, Issue #810)
  • Multi-User. Corrected terminate checkout from viewed checkout list which was always terminating first row range based upon number of selected rows and not the actual selected rows. (GT-2903)
  • -
  • Multi-user. Corrected ability for user to cancel checkin/checkout to Ghidra Server. (GT-3208)
  • +
  • Multi-User. Corrected ability for user to cancel checkin/checkout to Ghidra Server. (GT-3208)
  • Multi-User:Ghidra Server. Added proper Ghidra Server interface binding with new -i option. Corrected -ip option to strictly convey remote access hostname to clients. The updated server will only accept connections from Ghidra 9.1 and later clients due to the registry port now employing TLS. (GT-2685, Issue #101, #645)
  • Multi-User:Ghidra Server. Fixed argument-passing bug in svrAdmin script. (GT-3082, Issue #907)
  • Multi-User:Merge. Corrected merge problem affecting modified Function Definition datatypes which could result in a NullPointerException. (GT-2922)
  • @@ -518,7 +566,7 @@
  • Program API. Corrected parameter storage which failed to properly refresh after undo/redo. (GT-3130, Issue #960)
  • Program API. Corrected function parameter ordinal numbering when more than one auto-parameter is present. (GT-3214)
  • Project Manager. Fixed a problem with creating Ghidra projects in Windows root directories (e.g., Z:\). (GT-2585)
  • -
  • Project Manager. Fixed a path traversal vulnerability that could occur when restoring a malicious project archive. (GT-3001, Issue #789)
  • +
  • Project Manager. Fixed a path-traversal vulnerability that could occur when restoring a malicious project archive. (GT-3001, Issue #789)
  • Scripting. GhidraScript.askDomainFile() now correctly throws a CancelledException when the cancel button is clicked. (GT-2841)
  • Scripting. Removed deprecated scripting methods older than 5 releases. (GT-2949)
  • Security. Removed use of nonsecure XMLEncoder/XMLDecoder from Ghidra code base. (GT-3198, Issue #1090)
  • @@ -531,128 +579,123 @@

    Ghidra 9.0.4 Change History (May 2019)

    Bugs

      -
    • Multi-User:Ghidra Server. Corrected severe script error in svrAdmin.bat introduced with 9.0.3 build.
    • -
    • GUI. Restored the default 'p' key binding for creating pointers within the listing display.
    • +
    • Multi-User:Ghidra Server. Corrected severe script error in svrAdmin.bat introduced with 9.0.3 build. (GT-2874)
    • +
    • GUI. Restored the default 'p' key binding for creating pointers within the listing display. (GT-2854)

    Ghidra 9.0.3 Change History (April 2019)

    New Features

      -
    • GUI. Function tags are now viewable from Functions Window table using new column.
    • +
    • GUI. Function tags are now viewable from Functions Window table using new column. (GT-2114)

    Improvements

      -
    • Decompiler. Improved modeling of CFG on Windows 10. (Issue #340)
    • -
    • Patcher. Renamed patch directory to /Ghidra/patch and added README.txt that explains how the patch directory is used.
    • -
    • Search. Updated the Decompiler Data Type Finder to find references to inside of nested array access in a line of Decompiler C output. (Issue #416)
    • -
    • Sleigh. Improved error reporting for SLEIGH compiler. (Issue #364)
    • +
    • Decompiler. Improved modeling of CFG on Windows 10. (GT-2755, Issue #340)
    • +
    • Patcher. Renamed patch directory to /Ghidra/patch and added README.txt that explains how the patch directory is used. (GT-2734)
    • +
    • Search. Updated the Decompiler Data Type Finder to find references inside of nested array access in a line of Decompiler C output. (GT-2756, Issue #416)
    • +
    • Sleigh. Improved error reporting for SLEIGH compiler. (GT-2820, Issue #364)

    Bugs

      -
    • Analysis. Code that checks for thunks no longer throws an exception if the PC is not set for the processor.
    • -
    • Analysis. Made a fix to enable Apply button when changing tool options. (Issue #40)
    • -
    • Data Types. Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed.
    • -
    • Decompiler. Fixed dynamic variables and equates in 16-bit x86 programs. (Issue #336)
    • -
    • Decompiler:Java. Fixed DEX decompilation regression issue. (Issue #350)
    • -
    • Eclipse Integration. Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (Issues #283, #383)
    • +
    • Analysis. Code that checks for thunks no longer throws an exception if the PC is not set for the processor. (GT-2730)
    • +
    • Analysis. Made a fix to enable Apply button when changing tool options. (GT-2801, Issue #40)
    • +
    • Data Types. Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed. (GT-2736)
    • +
    • Decompiler. Fixed dynamic variables and equates in 16-bit x86 programs. (GT-2745, Issue #336)
    • +
    • Decompiler:Java. Fixed DEX decompilation regression issue. (Issue #350, GT-2743)
    • +
    • Eclipse Integration. Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (GT-2721, Issues #283, #383)
    • GUI. Improved documentation on how to deal with HiDPI monitor issues in Linux. In the <ghidra_installation>/support/launch.properties file, change VMARGS=-Dsun.java2d.xrender from false to true.
    • -
    • Importer. Fixed an exception that occurred when batch importing APK files. (Issue #426)
    • -
    • Multi-User:Ghidra Server. Restored ability to execute svrAdmin script in development mode.
    • -
    • Processors. The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (Issue #201)
    • -
    • Processors. The 68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (Issue #227)
    • -
    • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (Issue #407)
    • +
    • Importer. Fixed an exception that occurred when batch importing APK files. (GT-2767, Issue #426)
    • +
    • Multi-User:Ghidra Server. Restored ability to execute svrAdmin script in development mode. (GT-2740)
    • +
    • Processors. The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (GT-2759, Issue #201)
    • +
    • Processors. The M68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (GT-2807, Issue #227)
    • +
    • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (GT-2754. Issue #407)

    Ghidra 9.0.2 Change History (April 2019)

    Bugs

      -
    • Analysis. Constant reference analysis boundary controls for speculative references has been fixed. Speculative references are references created from computed constants passed as parameters, stored to a location, or from indexed offsets from a register. (Issue #228)
    • -
    • Decompiler. Fixed rendering bug in the Decompiler when the "Find" dialog is closed. (Issue #282)
    • -
    • Decompiler. Fixed decompiler handling of Function Definition data types. (Issue #247)
    • -
    • Decompiler. Fixed "Free Varnode" exception in RuleConditionalMove. (Issue #294)
    • -
    • Diff. Fixed exceptions that can occur in the Diff View for programs with overlays.
    • -
    • Documentation. Corrected the spelling of "listener" throughout the source code. (Issue #235)
    • -
    • Exporter. Exporting a selection as Intel Hex will now allow a selection of any length. Previously this was restricted to multiples of 16 bytes. (Issue #260)
    • -
    • GUI. Fixed exception that occurs after disabling MyProgramChangesDisplayPlugin.
    • -
    • GUI. Updated the "Open Program" dialog to disallow file drop operations. (Issue #252) -
    • Multi-User:Ghidra Server. Corrected bug introduced into ghidraSvr.bat which could prevent Ghidra Server startup (Issue #279)
    • -
    • Processors. The ARM Thumb CMP.W and LSL instructions have been changed to correctly decode. There are still issues to work out with Unpredictable execution when Rd is the PC. (Issue #280)
    • -
    • Scripting. MultiInstructionMemReference script has been corrected to consider input and output registers when placing a reference on an instruction.
    • +
    • Analysis. Constant reference analysis boundary controls for speculative references has been fixed. Speculative references are references created from computed constants passed as parameters, stored to a location, or from indexed offsets from a register. (GT-2723, Issue #228)
    • +
    • Decompiler. Fixed Decompiler handling of Function Definition data types. (GT-2704, Issue #247)
    • +
    • Decompiler. Fixed rendering bug in the Decompiler when the "Find" dialog is closed. (GT-2716, Issue #282)
    • +
    • Decompiler. Fixed "Free Varnode" exception in RuleConditionalMove. (GT-2726, Issue #294)
    • +
    • Diff. Fixed exceptions that can occur in the Diff View for programs with overlays. (GT-2706)
    • +
    • Documentation. Corrected the spelling of "listener" throughout the source code. (GT-2702, Issue #235)
    • +
    • Exporter. Exporting a selection as Intel Hex will now allow a selection of any length. Previously this was restricted to multiples of 16 bytes. (GT-2703, Issue #260)
    • +
    • GUI. Fixed exception that occurs after disabling MyProgramChangesDisplayPlugin. (GT-2712)
    • +
    • GUI. Updated the "Open Program" dialog to disallow file drop operations. (GT-2705, Issue #252)
    • +
    • Multi-User:Ghidra Server. Corrected bug introduced into ghidraSvr.bat which could prevent Ghidra Server startup. (GT-2717, Issue #279)
    • +
    • Processors. The ARM Thumb CMP.W and LSL instructions have been changed to correctly decode. There are still issues to work out with Unpredictable execution when Rd is the PC. (GT-2722, Issue #280)
    • +
    • Scripting. MultiInstructionMemReference script has been corrected to consider input and output registers when placing a reference on an instruction. (GT-2723)

    Security

      -
    • Basic Infrastructure. Added a property to support/launch.properties to prevent log4j from using jansi.dll on Windows. (Issue #286)
    • +
    • Basic Infrastructure. Added a property to support/launch.properties to prevent log4j from using jansi.dll on Windows. (GT-2725, Issue #286)

    Ghidra 9.0.1 Change History (March 2019)

    New Features

      -
    • Scripting. Created a script to show all equates within the current selection. (Issue #111)
    • +
    • Scripting. Created ShowEquatesInSelectionScript to show all equates within the current selection. (GT-2651, Issue #111)

    Improvements

      -
    • Basic Infrastructure. Updated commons-compress library to version 1.18. (Issue #171)
    • -
    • Eclipse Integration. Ghidra now connects to the Eclipse GhidraDev plugin on 127.0.0.1 rather than localhost.
    • -
    • GUI. Turned on font anti-aliasing by default for Linux. (Issue #212)
    • -
    • GUI. Fixed Options Dialog slow scrolling speed. (Issue #27)
    • -
    • Importer:ELF. Corrected bug in ELF loader which can improperly process the GOT, PLT and relocations - when multiple symbol tables exist within the ELF binary. (Issue #52)
    • -
    • Multi-User:Ghidra Server. Corrected the Ghidra Server service wrapper (YAJSW) configuration for - Mac OS X to prevent a startup timeout condition which could occur.
    • -
    • Processors. Added ARM/Thumb SRS instruction decodes for undefined modes. (Issue #216)
    • +
    • Basic Infrastructure. Updated commons-compress library to version 1.18. (GT-2657, Issue #171)
    • +
    • Eclipse Integration. Ghidra now connects to the Eclipse GhidraDev plugin on 127.0.0.1 rather than localhost. (GT-2691)
    • +
    • GUI. Turned on font anti-aliasing by default for Linux. (GT-2674, Issue #212)
    • +
    • GUI. Fixed Options Dialog slow scrolling speed. (GT-2679, Issue #27)
    • +
    • Importer:ELF. Corrected bug in ELF loader which can improperly process the GOT, PLT and relocations when multiple symbol tables exist within the ELF binary. (GT-2646, Issue #52)
    • +
    • Multi-User:Ghidra Server. Corrected the Ghidra Server service wrapper (YAJSW) configuration for Mac OS X to prevent a startup timeout condition which could occur. (GT-2637)
    • +
    • Processors. Added ARM/Thumb SRS instruction decodes for undefined modes. (GT-2676, Issue #216)

    Bugs

      -
    • API. Fixed equals method on Varnode class. (Issue #97)
    • -
    • API. Fixed a bug in MaskImpl.comlementMask(). (Issue #187)
    • -
    • Basic Infrastructure. Fixed special character handling in idaxml.py. (Issue #75)
    • -
    • Basic Infrastructure. Ghidra now forces the locale to en_US by default. Only the en_US is currently supported. - This fixes certain unexpected exceptions. (Issue #209)
    • -
    • Diff. Fixed exceptions occasionally encountered when starting a Diff session. (Issue #211)
    • -
    • Documentation. Fixed javadoc search box redirecting to broken links. (Issue #129)
    • -
    • Function Graph. Fixed Function Graph exception when generating tooltip. (Issue #65)
    • -
    • GUI. Updated window placement to keep windows on screen. (Issue #41)
    • -
    • GUI. Add/Edit References dialog now restricts users to creating refs in valid memory address spaces.
    • -
    • GUI. Fixed exception when exiting Ghidra while a table is being edited. (Issue #51)
    • -
    • GUI. Fixed some touchpad scrolling issues. (Issue #2)
    • -
    • GUI. Fixed stack trace in the Data Type Manager's tooltip generation. (Issue #133)
    • -
    • GUI. User key binding settings for the Recently Used and Define Pointer actions no longer lost after re-launching tool. (Issue #152)
    • -
    • GUI. Toolbar buttons now respond to fast clicking.
    • -
    • Importer:MachO. The MachoLoader can now find import libraries found in Universal Binary files. (Issue #136)
    • -
    • Importer:PE. The PeLoader now correctly parses the GuardCFFunctionTable when entries are more than 4 bytes each. (Issue #220)
    • -
    • Multi-User:Ghidra Server. Removed support for native OS authentication from Ghidra Server (removed modes -a2 and -a3) - due to incompatibility with newer OS releases including Windows 10 and Windows Server 2016. Re-introduction of this will be - considered for a future release.
    • -
    • PDB. Corrected NPE error when processing PDB files. (Issues #138, #188)
    • -
    • Processors. Added missing PowerPC VLE conditional branch instructions: e_bdnz and e_bdz. (Issue #103)
    • -
    • Processors. Fixed instruction semantics for several instructions and added Control Flow Enforcement, NOP variants, CMP variants, UD1, and - prefixed call instructions to X86 processor specification. (Issues #22, #53, #158, #157)
    • -
    • Processors. The 68000 MOVE instruction now correctly sets the CF and VF flags. (Issue #163)
    • -
    • Processors. Added four missing MOVEM instruction variants to the 68000 processor. (Issue #219)
    • -
    • Processors. An incorrect usage of X instead of Y in indexed mode for the 6502 has been corrected.(Issue #201)
    • -
    • Processors. Added support for ARM Thumb half BL instruction on processor variants prior to v6. (Issue #39)
    • -
    • Scripting. Fixed a bug in ImportSymbolsScript.py that prevented it from running. (Issue #170)
    • +
    • API. Fixed equals method on Varnode class. (GT-2648, Issue #97)
    • +
    • API. Fixed a bug in MaskImpl.complementMask(). (GT-2694, Issue #187)
    • +
    • Basic Infrastructure. Fixed special character handling in idaxml.py. (GT-2669, Issue #75)
    • +
    • Basic Infrastructure. Ghidra now forces the locale to en_US by default. Only the en_US is currently supported. This fixes certain unexpected exceptions. (GT-2680, Issue #209)
    • +
    • Diff. Fixed exception occasionally encountered when starting a Diff session. (GT-2672, Issue #211)
    • +
    • Documentation. Fixed javadoc search box redirecting to broken links. (GT-2655, Issue #129)
    • +
    • Function Graph. Fixed Function Graph exception when generating tooltip. (GT-2650, Issue #65)
    • +
    • GUI. Updated window placement to keep windows on screen. (GT-1516, Issue #41)
    • +
    • GUI. Add/Edit References dialog now restricts users to creating refs in valid memory address spaces. (GT-2638)
    • +
    • GUI. Fixed exception when exiting Ghidra while a table is being edited. (GT-2642, Issue #51)
    • +
    • GUI. Fixed some touchpad scrolling issues. (GT-2647, Issue #2)
    • +
    • GUI. Fixed stack trace in the Data Type Manager's tooltip generation. (GT-2656, Issue #133)
    • +
    • GUI. User key binding settings for the Recently Used and Define Pointer actions no longer lost after re-launching tool. (GT-2659, Issue #152)
    • +
    • GUI. Toolbar buttons now respond to fast clicking. (GT-2689)
    • +
    • Importer:Mach-O. The Mach-O loader can now find import libraries found in Universal Binary files. (GT-2663, Issue #136)
    • +
    • Importer:PE. The PeLoader now correctly parses the GuardCFFunctionTable when table entries are more than 4 bytes each. (GT-2671, Issue #220)
    • +
    • Multi-User:Ghidra Server. Removed support for native OS authentication from Ghidra Server (removed modes -a2 and -a3) due to incompatibility with newer OS releases including Windows 10 and Windows Server 2016. Re-introduction of this will be considered for a future release. (GT-2653)
    • +
    • PDB. Corrected NPE error when processing PDB files. (GT-2673, Issues #138, #188)
    • +
    • Processors. Added missing PowerPC VLE conditional branch instructions: e_bdnz and e_bdz. (GT-2652, Issue #103)
    • +
    • Processors. Fixed instruction semantics for several instructions and added Control Flow Enforcement, NOP variants, CMP variants, UD1, and prefixed call instructions to X86 processor specification. (GT-2660, Issues #22, #53, #158, #157)
    • +
    • Processors. The M68000 MOVE instruction now correctly sets the CF and VF flags. (GT-2661, Issue #163)
    • +
    • Processors. Added four missing MOVEM instruction variants to the M68000 processor. (GT-2675, Issue #219)
    • +
    • Processors. An incorrect usage of X instead of Y in indexed mode for the 6502 has been corrected. (GT-2677, Issue #201)
    • +
    • Processors. PPC VLE now disassembles base PPC instructions that are valid in VLE mode. (GT-2681, Issue #127)
    • +
    • Processors. Added support for ARM Thumb half BL instruction on processor variants prior to v6. (GT-2684, Issue #39)
    • +
    • Scripting. Fixed a bug in ImportSymbolsScript.py that prevented it from running. (GT-2668, Issue #170)

    Security

      -
    • Basic Infrastructure. Running Ghidra in debug mode no longer opens remotely accessible ports by default. (Issue #6)
    • -
    • GUI. The Defined Strings plugin no longer renders HTML in its table. (Issue #45)
    • -
    • Project Manager. Fixed an XXE vulnerability affecting projects and many other saved components. (Issue #71)
    • +
    • Basic Infrastructure. Running Ghidra in debug mode no longer opens remotely accessible ports by default. (GT-2641, Issue #6)
    • +
    • GUI. The Defined Strings plugin no longer renders HTML in its table. (GT-2686, Issue #45)
    • +
    • Project Manager. Fixed an XXE vulnerability affecting projects and many other saved components. (GT-2643, Issue #71)
    diff --git a/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn b/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn index e8ed7404f4..51c5089410 100644 --- a/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn +++ b/Ghidra/Features/Base/data/PEFunctionsThatDoNotReturn @@ -1,7 +1,15 @@ +abort CxxThrowException CxxThrowException@8 CxxFrameHandler3 crtExitProcess ExitProcess +ExitThread exit +FreeLibraryAndExitThread +invalid_parameter_noinfo_noreturn +invoke_watson longjmp +quick_exit +RpcRaiseException +terminate diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java index eef0b65f3c..b77dafd9f5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.KeyEvent; +import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; import ghidra.GhidraOptions; @@ -29,7 +30,7 @@ import ghidra.app.util.HelpTopics; import ghidra.app.util.navigation.GoToAddressLabelDialog; import ghidra.framework.options.*; import ghidra.framework.plugintool.*; -import ghidra.framework.plugintool.util.*; +import ghidra.framework.plugintool.util.PluginStatus; import ghidra.util.HelpLocation; import ghidra.util.bean.opteditor.OptionsVetoException; @@ -91,11 +92,21 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe public void actionPerformed(NavigatableActionContext context) { goToDialog.show(context.getNavigatable(), context.getAddress(), tool); } + + @Override + protected boolean isEnabledForContext(NavigatableActionContext context) { + return context.getProgram() != null; + } + + @Override + public boolean isAddToPopup(ActionContext context) { + return true; + } }; action.setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, action.getName())); - action.setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_NAVIGATION, "Go To..." }, null, "GoTo", - MenuData.NO_MNEMONIC, "2")); // second item in the menu + action.setMenuBarData( + new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Go To..." }, null, "GoTo", + MenuData.NO_MNEMONIC, "2")); // second item in the menu action.setKeyBindingData(new KeyBindingData(KeyEvent.VK_G, 0)); @@ -144,10 +155,11 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe * @param newValue new value of the option */ @Override - public void optionsChanged(ToolOptions options, String opName, Object oldValue, Object newValue) { + public void optionsChanged(ToolOptions options, String opName, Object oldValue, + Object newValue) { if (opName.equals(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES)) { maximumGotoEntries = - options.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); + options.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); if (maximumGotoEntries <= 0) { throw new OptionsVetoException("Search limit must be greater than 0"); } @@ -155,7 +167,7 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe } else if (opName.equals(GhidraOptions.OPTION_NUMERIC_FORMATTING)) { cStyleInput = - options.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); + options.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); goToDialog.setCStyleInput(cStyleInput); } else if (opName.equals(GO_TO_MEMORY)) { @@ -182,20 +194,20 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe ToolOptions opt = tool.getOptions(ToolConstants.TOOL_OPTIONS); // descriptions opt.registerOption(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE, null, - "Interpret value entered in the Go To dialog as either hex, " - + "octal, or binary number."); + "Interpret value entered in the Go To dialog as either hex, " + + "octal, or binary number."); opt.registerOption(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES, null, - "Max number of entries remembered in the go to list."); + "Max number of entries remembered in the go to list."); opt.registerOption(GO_TO_MEMORY, DEFAULT_MEMORY, null, - "Remember the last successful go to input in the " - + "Go To dialog. If this option is enabled, then the " - + "Go To dialog will leave the last " - + "successful go to input in the combo box of the Go " - + "To dialog and will select the " + "value for easy paste replacement."); + "Remember the last successful go to input in the " + + "Go To dialog. If this option is enabled, then the " + + "Go To dialog will leave the last " + + "successful go to input in the combo box of the Go " + + "To dialog and will select the " + "value for easy paste replacement."); // options maximumGotoEntries = - opt.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); + opt.getInt(GhidraOptions.OPTION_MAX_GO_TO_ENTRIES, DEFAULT_MAX_GOTO_ENTRIES); cStyleInput = opt.getBoolean(GhidraOptions.OPTION_NUMERIC_FORMATTING, DEFAULT_C_STYLE); goToDialog.setCStyleInput(cStyleInput); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java index 2a9cfebdd2..7d1dd90681 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/FileHeader.java @@ -22,6 +22,7 @@ import java.util.List; import ghidra.app.util.bin.StructConverter; import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY; import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol; import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbolAux; import ghidra.program.model.data.*; @@ -45,7 +46,7 @@ import ghidra.util.exception.DuplicateNameException; * WORD Characteristics; // MANDATORY * } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; * - * + * */ public class FileHeader implements StructConverter { /** @@ -55,128 +56,131 @@ public class FileHeader implements StructConverter { /** * The size of the IMAGE_FILE_HEADER in bytes. */ - public final static int IMAGE_SIZEOF_FILE_HEADER = 20; + public final static int IMAGE_SIZEOF_FILE_HEADER = 20; /** * Relocation info stripped from file. */ - public final static int IMAGE_FILE_RELOCS_STRIPPED = 0x0001; - /** - * File is executable (no unresolved externel references). - */ - public final static int IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; - /** - * Line nunbers stripped from file. - */ - public final static int IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004; - /** - * Local symbols stripped from file. - */ - public final static int IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008; - /** - * Agressively trim working set - */ - public final static int IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010; - /** - * App can handle >2gb addresses - */ - public final static int IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; - /** - * Bytes of machine word are reversed. - */ - public final static int IMAGE_FILE_BYTES_REVERSED_LO = 0x0080; - /** - * 32 bit word machine. - */ - public final static int IMAGE_FILE_32BIT_MACHINE = 0x0100; - /** - * Debugging info stripped from file in .DBG file - */ - public final static int IMAGE_FILE_DEBUG_STRIPPED = 0x0200; - /** - * If Image is on removable media, copy and run from the swap file. - */ - public final static int IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400; - /** - * If Image is on Net, copy and run from the swap file. - */ - public final static int IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800; - /** - * System File. - */ - public final static int IMAGE_FILE_SYSTEM = 0x1000; - /** - * File is a DLL. - */ - public final static int IMAGE_FILE_DLL = 0x2000; - /** - * File should only be run on a UP machine - */ - public final static int IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000; - /** - * Bytes of machine word are reversed. - */ - public final static int IMAGE_FILE_BYTES_REVERSED_HI = 0x8000; + public final static int IMAGE_FILE_RELOCS_STRIPPED = 0x0001; + /** + * File is executable (no unresolved externel references). + */ + public final static int IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; + /** + * Line nunbers stripped from file. + */ + public final static int IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004; + /** + * Local symbols stripped from file. + */ + public final static int IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008; + /** + * Agressively trim working set + */ + public final static int IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010; + /** + * App can handle >2gb addresses + */ + public final static int IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; + /** + * Bytes of machine word are reversed. + */ + public final static int IMAGE_FILE_BYTES_REVERSED_LO = 0x0080; + /** + * 32 bit word machine. + */ + public final static int IMAGE_FILE_32BIT_MACHINE = 0x0100; + /** + * Debugging info stripped from file in .DBG file + */ + public final static int IMAGE_FILE_DEBUG_STRIPPED = 0x0200; + /** + * If Image is on removable media, copy and run from the swap file. + */ + public final static int IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400; + /** + * If Image is on Net, copy and run from the swap file. + */ + public final static int IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800; + /** + * System File. + */ + public final static int IMAGE_FILE_SYSTEM = 0x1000; + /** + * File is a DLL. + */ + public final static int IMAGE_FILE_DLL = 0x2000; + /** + * File should only be run on a UP machine. + */ + public final static int IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000; + /** + * Bytes of machine word are reversed. + */ + public final static int IMAGE_FILE_BYTES_REVERSED_HI = 0x8000; - public final static String [] CHARACTERISTICS = { - "Relocation info stripped from file", - "File is executable (i.e. no unresolved externel references)", - "Line nunbers stripped from file", - "Local symbols stripped from file", - "Agressively trim working set", - "App can handle >2gb addresses", - "Bytes of machine word are reversed", - "32 bit word machine", - "Debugging info stripped from file in .DBG file", - "If Image is on removable media, copy and run from the swap file", - "If Image is on Net, copy and run from the swap file", - "System file", - "File is a DLL", - "File should only be run on a UP machine", - "Bytes of machine word are reversed" - }; + /** + * Magic value in LordPE's Symbol Table pointer field. + */ + private final static int LORDPE_SYMBOL_TABLE = 0x726F4C5B; + /** + * Magic value in LordPE's Number of Symbols field. + */ + private final static int LORDPE_NUMBER_OF_SYMBOLS = 0x5D455064; - private short machine; - private short numberOfSections; - private int timeDateStamp; - private int pointerToSymbolTable; - private int numberOfSymbols; - private short sizeOfOptionalHeader; // delta between start of OptionalHeader and start of section table - private short characteristics; + public final static String[] CHARACTERISTICS = { "Relocation info stripped from file", + "File is executable (i.e. no unresolved externel references)", + "Line nunbers stripped from file", "Local symbols stripped from file", + "Agressively trim working set", "App can handle >2gb addresses", + "Bytes of machine word are reversed", "32 bit word machine", + "Debugging info stripped from file in .DBG file", + "If Image is on removable media, copy and run from the swap file", + "If Image is on Net, copy and run from the swap file", "System file", "File is a DLL", + "File should only be run on a UP machine", "Bytes of machine word are reversed" }; - private SectionHeader [] sectionHeaders; - private Listsymbols = new ArrayList<>(); + private short machine; + private short numberOfSections; + private int timeDateStamp; + private int pointerToSymbolTable; + private int numberOfSymbols; + private short sizeOfOptionalHeader; // delta between start of OptionalHeader and start of section table + private short characteristics; - private FactoryBundledWithBinaryReader reader; - private int startIndex; - private NTHeader ntHeader; + private SectionHeader[] sectionHeaders; + private List symbols = new ArrayList<>(); + private List<_IMAGE_RUNTIME_FUNCTION_ENTRY> irfes = new ArrayList<>(); - static FileHeader createFileHeader( - FactoryBundledWithBinaryReader reader, int startIndex, - NTHeader ntHeader) throws IOException { - FileHeader fileHeader = (FileHeader) reader.getFactory().create(FileHeader.class); - fileHeader.initFileHeader(reader, startIndex, ntHeader); - return fileHeader; - } + private FactoryBundledWithBinaryReader reader; + private int startIndex; + private NTHeader ntHeader; - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public FileHeader() {} + static FileHeader createFileHeader(FactoryBundledWithBinaryReader reader, int startIndex, + NTHeader ntHeader) throws IOException { + FileHeader fileHeader = (FileHeader) reader.getFactory().create(FileHeader.class); + fileHeader.initFileHeader(reader, startIndex, ntHeader); + return fileHeader; + } - private void initFileHeader(FactoryBundledWithBinaryReader reader, int startIndex, NTHeader ntHeader) throws IOException { - this.reader = reader; - this.startIndex = startIndex; - this.ntHeader = ntHeader; + /** + * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. + */ + public FileHeader() { + } + + private void initFileHeader(FactoryBundledWithBinaryReader reader, int startIndex, + NTHeader ntHeader) throws IOException { + this.reader = reader; + this.startIndex = startIndex; + this.ntHeader = ntHeader; + + parse(); + } - parse(); - } - /** * Returns the architecture type of the computer. * @return the architecture type of the computer */ - public short getMachine() { + public short getMachine() { return machine; } @@ -184,131 +188,137 @@ public class FileHeader implements StructConverter { * Returns a string representation of the architecture type of the computer. * @return a string representation of the architecture type of the computer */ - public String getMachineName() { - return MachineName.getName(machine); - } - + public String getMachineName() { + return MachineName.getName(machine); + } + /** - * Returns the number of sections. + * Returns the number of sections. * Sections equate to Ghidra memory blocks. * @return the number of sections */ - public int getNumberOfSections() { - return numberOfSections; - } + public int getNumberOfSections() { + return numberOfSections; + } /** * Returns the array of section headers. * @return the array of section headers */ - public SectionHeader [] getSectionHeaders() { - if (sectionHeaders == null) { - return new SectionHeader[0]; - } - return sectionHeaders; - } + public SectionHeader[] getSectionHeaders() { + if (sectionHeaders == null) { + return new SectionHeader[0]; + } + return sectionHeaders; + } /** * Returns the array of symbols. * @return the array of symbols */ - public List getSymbols() { + public List getSymbols() { return symbols; } + public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getImageRuntimeFunctionEntries() { + return irfes; + } + /** * Returns the section header that contains the specified virtual address. * @param virtualAddr the virtual address * @return the section header that contains the specified virtual address */ - public SectionHeader getSectionHeaderContaining(int virtualAddr) { - for (SectionHeader sectionHeader : sectionHeaders) { - int start = sectionHeader.getVirtualAddress(); - int end = sectionHeader.getVirtualAddress()+sectionHeader.getVirtualSize()-1; - if (virtualAddr >= start && virtualAddr <= end) { - return sectionHeader; - } - } - return null; - } + public SectionHeader getSectionHeaderContaining(int virtualAddr) { + for (SectionHeader sectionHeader : sectionHeaders) { + int start = sectionHeader.getVirtualAddress(); + int end = sectionHeader.getVirtualAddress() + sectionHeader.getVirtualSize() - 1; + if (virtualAddr >= start && virtualAddr <= end) { + return sectionHeader; + } + } + return null; + } /** * Returns the section header at the specified position in the array. * @param index index of section header to return * @return the section header at the specified position in the array, or null if invalid */ - public SectionHeader getSectionHeader(int index) { + public SectionHeader getSectionHeader(int index) { if (index >= 0 && index < sectionHeaders.length) { - return sectionHeaders[index]; - } - return null; - } + return sectionHeaders[index]; + } + return null; + } /** * Returns the time stamp of the image. * @return the time stamp of the image */ - public int getTimeDateStamp() { - return timeDateStamp; - } + public int getTimeDateStamp() { + return timeDateStamp; + } /** * Returns the file offset of the COFF symbol table * @return the file offset of the COFF symbol table */ - public int getPointerToSymbolTable() { - return pointerToSymbolTable; - } + public int getPointerToSymbolTable() { + return pointerToSymbolTable; + } /** * Returns the number of symbols in the COFF symbol table * @return the number of symbols in the COFF symbol table */ - public int getNumberOfSymbols() { - return numberOfSymbols; - } + public int getNumberOfSymbols() { + return numberOfSymbols; + } /** * Returns the size of the optional header data * @return the size of the optional header, in bytes */ - public int getSizeOfOptionalHeader() { + public int getSizeOfOptionalHeader() { return sizeOfOptionalHeader; } /** - * Returns a set of bit flags indicating attributes of the file. + * Returns a set of bit flags indicating attributes of the file. * @return a set of bit flags indicating attributes */ - public int getCharacteristics() { - return characteristics; - } + public int getCharacteristics() { + return characteristics; + } /** * Returns the file pointer to the section headers. * @return the file pointer to the section headers */ - public int getPointerToSections() { - short sizeOptHdr = ntHeader.getFileHeader().sizeOfOptionalHeader; + public int getPointerToSections() { + short sizeOptHdr = ntHeader.getFileHeader().sizeOfOptionalHeader; int ptrToSections = startIndex + IMAGE_SIZEOF_FILE_HEADER + sizeOptHdr; - int testSize = ntHeader.getOptionalHeader().is64bit() - ? Constants.IMAGE_SIZEOF_NT_OPTIONAL64_HEADER - : Constants.IMAGE_SIZEOF_NT_OPTIONAL32_HEADER; - if (sizeOptHdr != testSize) { + int testSize = + ntHeader.getOptionalHeader().is64bit() ? Constants.IMAGE_SIZEOF_NT_OPTIONAL64_HEADER + : Constants.IMAGE_SIZEOF_NT_OPTIONAL32_HEADER; + if (sizeOptHdr != testSize) { Msg.warn(this, "Non-standard optional header size: " + sizeOptHdr + " bytes"); - } + } return ptrToSections; - } + } - void processSections(OptionalHeader optHeader) throws IOException { - long oldIndex = reader.getPointerIndex(); + void processSections(OptionalHeader optHeader) throws IOException { + long oldIndex = reader.getPointerIndex(); - int tmpIndex = getPointerToSections(); - if (numberOfSections < 0) { - Msg.error(this, "Number of sections = "+numberOfSections); - } else if (optHeader.getFileAlignment() == 0) { - Msg.error(this, "File alignment == 0: section processing skipped"); - } else { + int tmpIndex = getPointerToSections(); + if (numberOfSections < 0) { + Msg.error(this, "Number of sections = " + numberOfSections); + } + else if (optHeader.getFileAlignment() == 0) { + Msg.error(this, "File alignment == 0: section processing skipped"); + } + else { sectionHeaders = new SectionHeader[numberOfSections]; for (int i = 0; i < numberOfSections; ++i) { sectionHeaders[i] = SectionHeader.createSectionHeader(reader, tmpIndex); @@ -330,8 +340,8 @@ public class FileHeader implements StructConverter { optHeader.getSectionAlignment()); if (virtualAddress == alignedVirtualAddress) { if (sizeOfRawData > virtualSize) { - sectionHeaders[i].setVirtualSize( - Math.min(sizeOfRawData, alignedVirtualSize)); + sectionHeaders[i] + .setVirtualSize(Math.min(sizeOfRawData, alignedVirtualSize)); } } else { @@ -341,68 +351,101 @@ public class FileHeader implements StructConverter { } } - reader.setPointerIndex(oldIndex); - } + reader.setPointerIndex(oldIndex); + } - void processSymbols() throws IOException { - if (isLordPE()) { - return; - } + void processImageRuntimeFunctionEntries() throws IOException { + FileHeader fh = ntHeader.getFileHeader(); + SectionHeader[] sections = fh.getSectionHeaders(); - long oldIndex = reader.getPointerIndex(); + // Look for an exception handler section for an array of + // RUNTIME_FUNCTION structures, bail if one isn't found + SectionHeader irfeHeader = null; + for (SectionHeader header : sections) { + if (header.getName().equals(".pdata")) { + irfeHeader = header; + break; + } + } - int tmpIndex = getPointerToSymbolTable(); - if (!ntHeader.checkRVA(tmpIndex)) { - Msg.error(this, "Invalid file index "+Integer.toHexString(tmpIndex)); - return; - } + if (irfeHeader == null) { + return; + } - if ( numberOfSymbols < 0 || numberOfSymbols > reader.length()) { - Msg.error(this, "Invalid symbol count "+Integer.toHexString(numberOfSymbols)); - return; - } + long oldIndex = reader.getPointerIndex(); - int stringTableIndex = tmpIndex + DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL * numberOfSymbols; - - for (int i = 0; i < numberOfSymbols; ++i) { - if (!ntHeader.checkRVA(tmpIndex)) { - Msg.error(this, "Invalid file index "+Integer.toHexString(tmpIndex)); - break; - } + int start = irfeHeader.getPointerToRawData(); + reader.setPointerIndex(start); - DebugCOFFSymbol symbol = DebugCOFFSymbol.createDebugCOFFSymbol(reader, tmpIndex, stringTableIndex); + ImageRuntimeFunctionEntries entries = + ImageRuntimeFunctionEntries.createImageRuntimeFunctionEntries(reader, start, ntHeader); + irfes = entries.getRuntimeFunctionEntries(); - tmpIndex += DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL; + reader.setPointerIndex(oldIndex); + } - tmpIndex += (DebugCOFFSymbolAux.IMAGE_SIZEOF_AUX_SYMBOL * symbol.getNumberOfAuxSymbols()); + void processSymbols() throws IOException { + if (isLordPE()) { + return; + } - int numberOfAuxSymbols = symbol.getNumberOfAuxSymbols(); + long oldIndex = reader.getPointerIndex(); + + int tmpIndex = getPointerToSymbolTable(); + if (!ntHeader.checkRVA(tmpIndex)) { + Msg.error(this, "Invalid file index " + Integer.toHexString(tmpIndex)); + return; + } + + if (numberOfSymbols < 0 || numberOfSymbols > reader.length()) { + Msg.error(this, "Invalid symbol count " + Integer.toHexString(numberOfSymbols)); + return; + } + + int stringTableIndex = tmpIndex + DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL * numberOfSymbols; + + for (int i = 0; i < numberOfSymbols; ++i) { + if (!ntHeader.checkRVA(tmpIndex)) { + Msg.error(this, "Invalid file index " + Integer.toHexString(tmpIndex)); + break; + } + + DebugCOFFSymbol symbol = + DebugCOFFSymbol.createDebugCOFFSymbol(reader, tmpIndex, stringTableIndex); + + tmpIndex += DebugCOFFSymbol.IMAGE_SIZEOF_SYMBOL; + + tmpIndex += + (DebugCOFFSymbolAux.IMAGE_SIZEOF_AUX_SYMBOL * symbol.getNumberOfAuxSymbols()); + + int numberOfAuxSymbols = symbol.getNumberOfAuxSymbols(); i += numberOfAuxSymbols > 0 ? numberOfAuxSymbols : 0; - symbols.add( symbol ); - } + symbols.add(symbol); + } - reader.setPointerIndex(oldIndex); - } + reader.setPointerIndex(oldIndex); + } - public boolean isLordPE() { - if (getPointerToSymbolTable() == 0x726F4C5B && getNumberOfSymbols() == 0x5D455064) { - return true; - } - return false; - } + public boolean isLordPE() { + if (getPointerToSymbolTable() == LORDPE_SYMBOL_TABLE && + getNumberOfSymbols() == LORDPE_NUMBER_OF_SYMBOLS) { + return true; + } + return false; + } - private void parse() throws IOException { - reader.setPointerIndex(startIndex); + private void parse() throws IOException { + reader.setPointerIndex(startIndex); - machine = reader.readNextShort(); - numberOfSections = reader.readNextShort(); - timeDateStamp = reader.readNextInt (); - pointerToSymbolTable = reader.readNextInt (); - numberOfSymbols = reader.readNextInt (); - sizeOfOptionalHeader = reader.readNextShort(); - characteristics = reader.readNextShort(); - } + machine = reader.readNextShort(); + numberOfSections = reader.readNextShort(); + timeDateStamp = reader.readNextInt(); + pointerToSymbolTable = reader.readNextInt(); + numberOfSymbols = reader.readNextInt(); + sizeOfOptionalHeader = reader.readNextShort(); + characteristics = reader.readNextShort(); + } /** * @see ghidra.app.util.bin.StructConverter#toDataType() @@ -411,22 +454,22 @@ public class FileHeader implements StructConverter { public DataType toDataType() throws DuplicateNameException { StructureDataType struct = new StructureDataType(NAME, 0); - struct.add(WORD,2,"Machine",getMachineName()); - struct.add(WORD,2,"NumberOfSections",null); - struct.add(DWORD,4,"TimeDateStamp",null); - struct.add(DWORD,4,"PointerToSymbolTable",null); - struct.add(DWORD,4,"NumberOfSymbols",null); - struct.add(WORD,2,"SizeOfOptionalHeader",null); - struct.add(WORD,2,"Characteristics",null); + struct.add(WORD, 2, "Machine", getMachineName()); + struct.add(WORD, 2, "NumberOfSections", null); + struct.add(DWORD, 4, "TimeDateStamp", null); + struct.add(DWORD, 4, "PointerToSymbolTable", null); + struct.add(DWORD, 4, "NumberOfSymbols", null); + struct.add(WORD, 2, "SizeOfOptionalHeader", null); + struct.add(WORD, 2, "Characteristics", null); struct.setCategoryPath(new CategoryPath("/PE")); return struct; } - private void setSectionHeaders(SectionHeader [] sectionHeaders) { + private void setSectionHeaders(SectionHeader[] sectionHeaders) { this.sectionHeaders = sectionHeaders; - numberOfSections = (short)sectionHeaders.length; + numberOfSections = (short) sectionHeaders.length; } void writeHeader(RandomAccessFile raf, DataConverter dc) throws IOException { @@ -436,7 +479,7 @@ public class FileHeader implements StructConverter { raf.write(dc.getBytes(pointerToSymbolTable)); raf.write(dc.getBytes(numberOfSymbols)); raf.write(dc.getBytes(sizeOfOptionalHeader)); - raf.write(dc.getBytes(characteristics)); + raf.write(dc.getBytes(characteristics)); } /** @@ -449,61 +492,61 @@ public class FileHeader implements StructConverter { * @throws RuntimeException if the memory block is uninitialized */ public void addSection(MemoryBlock block, OptionalHeader optionalHeader) { - DataDirectory [] directories = optionalHeader.getDataDirectories(); - - DataDirectory [] dataDirectories = optionalHeader.getDataDirectories(); + DataDirectory[] directories = optionalHeader.getDataDirectories(); + DataDirectory[] dataDirectories = optionalHeader.getDataDirectories(); SecurityDataDirectory sdd = null; if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY) { - sdd = (SecurityDataDirectory)dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY]; + sdd = + (SecurityDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY]; if (sdd != null && sdd.getSize() > 0) { - sdd.updatePointers( PortableExecutable.computeAlignment( (int)block.getSize( ), optionalHeader.getFileAlignment( ) ) ); + sdd.updatePointers(PortableExecutable.computeAlignment((int) block.getSize(), + optionalHeader.getFileAlignment())); } } - - int lastPos = computeAlignedNewPosition( optionalHeader, directories ); + int lastPos = computeAlignedNewPosition(optionalHeader, directories); SectionHeader newSection = new SectionHeader(block, optionalHeader, lastPos); - SectionHeader [] newSectionHeaders = new SectionHeader[sectionHeaders.length + 1]; - System.arraycopy(sectionHeaders, 0, newSectionHeaders, 0, sectionHeaders.length); + SectionHeader[] newSectionHeaders = new SectionHeader[sectionHeaders.length + 1]; + System.arraycopy(sectionHeaders, 0, newSectionHeaders, 0, sectionHeaders.length); newSectionHeaders[sectionHeaders.length] = newSection; setSectionHeaders(newSectionHeaders); int firstSectionStart = sectionHeaders[0].getPointerToRawData(); - int lastSectionEnd = sectionHeaders[sectionHeaders.length-1].getPointerToRawData() - +sectionHeaders[sectionHeaders.length-1].getSizeOfRawData(); + int lastSectionEnd = sectionHeaders[sectionHeaders.length - 1].getPointerToRawData() + + sectionHeaders[sectionHeaders.length - 1].getSizeOfRawData(); - for (int i = 0 ; i < directories.length ; i++) { - if (directories[i] == null || - directories[i].getSize() == 0 || + for (int i = 0; i < directories.length; i++) { + if (directories[i] == null || directories[i].getSize() == 0 || directories[i].isContainedInSection()) { continue; } if (directories[i].getVirtualAddress() < firstSectionStart) { if (i != OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) { - throw new RuntimeException("PE - Unexpected directory before sections: "+i); + throw new RuntimeException("PE - Unexpected directory before sections: " + i); } } if (directories[i].getVirtualAddress() > lastSectionEnd) { if (i != OptionalHeader.IMAGE_DIRECTORY_ENTRY_SECURITY) { - throw new RuntimeException("PE - Unexpected directory after sections: "+i); + throw new RuntimeException("PE - Unexpected directory after sections: " + i); } } } int offset = 0; - if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) { - BoundImportDataDirectory bidd = (BoundImportDataDirectory)dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]; + BoundImportDataDirectory bidd = + (BoundImportDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]; if (bidd != null && bidd.getSize() > 0) { bidd.updatePointers(SectionHeader.IMAGE_SIZEOF_SECTION_HEADER); int endptr = bidd.getVirtualAddress() + bidd.getSize() - 1; if (endptr >= sectionHeaders[0].getPointerToRawData()) { - int alignedPtr = PortableExecutable.computeAlignment(endptr, optionalHeader.getFileAlignment()); + int alignedPtr = PortableExecutable.computeAlignment(endptr, + optionalHeader.getFileAlignment()); offset = alignedPtr - sectionHeaders[0].getPointerToRawData(); for (SectionHeader sectionHeader : sectionHeaders) { sectionHeader.updatePointers(offset); @@ -514,9 +557,9 @@ public class FileHeader implements StructConverter { } } - if (dataDirectories.length > OptionalHeader.IMAGE_DIRECTORY_ENTRY_DEBUG) { - DebugDataDirectory ddd = (DebugDataDirectory)dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_DEBUG]; + DebugDataDirectory ddd = + (DebugDataDirectory) dataDirectories[OptionalHeader.IMAGE_DIRECTORY_ENTRY_DEBUG]; if (ddd != null && ddd.getSize() > 0) { if (ddd.getVirtualAddress() > newSection.getVirtualAddress()) { if (sdd != null && sdd.getSize() > 0) { @@ -530,12 +573,12 @@ public class FileHeader implements StructConverter { } if (block.isExecute()) { - optionalHeader.setSizeOfCode(optionalHeader.getSizeOfCode() + - newSection.getSizeOfRawData()); + optionalHeader + .setSizeOfCode(optionalHeader.getSizeOfCode() + newSection.getSizeOfRawData()); } else { - optionalHeader.setSizeOfInitializedData(optionalHeader.getSizeOfInitializedData() + - newSection.getSizeOfRawData()); + optionalHeader.setSizeOfInitializedData( + optionalHeader.getSizeOfInitializedData() + newSection.getSizeOfRawData()); } int soi = newSection.getVirtualAddress() + newSection.getSizeOfRawData(); @@ -543,7 +586,8 @@ public class FileHeader implements StructConverter { optionalHeader.setSizeOfImage(soi); } - private int computeAlignedNewPosition( OptionalHeader optionalHeader, DataDirectory [] directories ) { + private int computeAlignedNewPosition(OptionalHeader optionalHeader, + DataDirectory[] directories) { int lastPos = 0; for (SectionHeader sectionHeader : sectionHeaders) { if (sectionHeader.getPointerToRawData() + sectionHeader.getSizeOfRawData() > lastPos) { @@ -551,14 +595,13 @@ public class FileHeader implements StructConverter { } } for (DataDirectory directorie : directories) { - if (directorie == null || - directorie.getSize() == 0) { + if (directorie == null || directorie.getSize() == 0) { continue; } if (directorie.rvaToPointer() + directorie.getSize() > lastPos) { lastPos = directorie.rvaToPointer() + directorie.getSize(); } } - return PortableExecutable.computeAlignment( lastPos, optionalHeader.getFileAlignment( ) ); + return PortableExecutable.computeAlignment(lastPos, optionalHeader.getFileAlignment()); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries.java new file mode 100644 index 0000000000..7a372d9d19 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries.java @@ -0,0 +1,486 @@ +/* ### + * 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.bin.format.pe; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import ghidra.app.util.bin.StructConverter; +import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.program.model.data.*; +import ghidra.util.exception.DuplicateNameException; + +/** + * typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { + * DWORD BeginAddress; + * DWORD EndAddress; + * union { + * DWORD UnwindInfoAddress; + * DWORD UnwindData; + * } DUMMYUNIONNAME; + * } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION, _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY; + * + * #define UNW_FLAG_NHANDLER 0x0 + * #define UNW_FLAG_EHANDLER 0x1 + * #define UNW_FLAG_UHANDLER 0x2 + * #define UNW_FLAG_CHAININFO 0x4 + * + * typedef struct _UNWIND_INFO { + * UCHAR Version : 3; + * UCHAR Flags : 5; + * UCHAR SizeOfProlog; + * UCHAR CountOfUnwindCodes; + * UCHAR FrameRegister : 4; + * UCHAR FrameOffset : 4; + * UNWIND_CODE UnwindCode[1]; + * + * // + * // The unwind codes are followed by an optional DWORD aligned field that + * // contains the exception handler address or the address of chained unwind + * // information. If an exception handler address is specified, then it is + * // followed by the language specified exception handler data. + * // + * // union { + * // ULONG ExceptionHandler; + * // ULONG FunctionEntry; + * // }; + * // + * // ULONG ExceptionData[]; + * // + * } UNWIND_INFO, *PUNWIND_INFO; + */ +public class ImageRuntimeFunctionEntries { + private final static int UNWIND_INFO_VERSION_BITMASK = 0x07; + private final static int UNWIND_INFO_FLAGS_SHIFT = 0x03; + private final static int UNWIND_INFO_FRAME_REGISTER_MASK = 0x0F; + private final static int UNWIND_INFO_FRAME_OFFSET_SHIFT = 0x04; + private final static int UNWIND_INFO_OPCODE_MASK = 0x0F; + private final static int UNWIND_INFO_OPCODE_INFO_SHIFT = 0x04; + private final static int UNWIND_INFO_SIZE = 0x0C; + + List<_IMAGE_RUNTIME_FUNCTION_ENTRY> functionEntries = new ArrayList<>(); + + static ImageRuntimeFunctionEntries createImageRuntimeFunctionEntries( + FactoryBundledWithBinaryReader reader, long index, NTHeader ntHeader) + throws IOException { + ImageRuntimeFunctionEntries imageRuntimeFunctionEntriesSection = + (ImageRuntimeFunctionEntries) reader.getFactory() + .create(ImageRuntimeFunctionEntries.class); + imageRuntimeFunctionEntriesSection.initImageRuntimeFunctionEntries(reader, index, ntHeader); + return imageRuntimeFunctionEntriesSection; + } + + /** + * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. + */ + public ImageRuntimeFunctionEntries() { + } + + private void initImageRuntimeFunctionEntries(FactoryBundledWithBinaryReader reader, long index, + NTHeader ntHeader) throws IOException { + + int entryCount = 0; + + // Find the exception handler data section. This is an unbounded array of + // RUNTIME_INFO structures one after another and there's no count field + // to tell us how many there are, so get the maximum number there could be + // based on the size of the section. + FileHeader fh = ntHeader.getFileHeader(); + for (SectionHeader section : fh.getSectionHeaders()) { + if (section.getName().contentEquals(".pdata")) { + entryCount = section.getSizeOfRawData() / UNWIND_INFO_SIZE; + break; + } + } + + if (entryCount == 0) { + return; + } + + long origIndex = reader.getPointerIndex(); + + reader.setPointerIndex(index); + + for (int i = 0; i < entryCount; i++) { + _IMAGE_RUNTIME_FUNCTION_ENTRY entry = new _IMAGE_RUNTIME_FUNCTION_ENTRY(); + entry.beginAddress = reader.readNextUnsignedInt(); + entry.endAddress = reader.readNextUnsignedInt(); + entry.unwindInfoAddressOrData = reader.readNextUnsignedInt(); + + // When the size of the section is bigger than the number of structures + // the structure data fields will all be null, signaling the end of the + // array of structures. Break out here. + if (entry.beginAddress == 0 && entry.endAddress == 0 && + entry.unwindInfoAddressOrData == 0) { + break; + } + + // Read and process the UNWIND_INFO structures the RUNTIME_INFO + // structures point to + entry.unwindInfo = readUnwindInfo(reader, entry.unwindInfoAddressOrData, ntHeader); + + functionEntries.add(entry); + } + + reader.setPointerIndex(origIndex); + } + + private UNWIND_INFO readUnwindInfo(FactoryBundledWithBinaryReader reader, long offset, + NTHeader ntHeader) throws IOException { + long origIndex = reader.getPointerIndex(); + + long pointer = ntHeader.rvaToPointer(offset); + UNWIND_INFO unwindInfo = new UNWIND_INFO(pointer); + + if (pointer < 0) { + return unwindInfo; + } + + reader.setPointerIndex(pointer); + byte splitByte = reader.readNextByte(); + unwindInfo.version = (byte) (splitByte & UNWIND_INFO_VERSION_BITMASK); + unwindInfo.flags = (byte) (splitByte >> UNWIND_INFO_FLAGS_SHIFT); + + unwindInfo.sizeOfProlog = reader.readNextByte(); + unwindInfo.countOfUnwindCodes = reader.readNextByte(); + + splitByte = reader.readNextByte(); + unwindInfo.frameRegister = (byte) (splitByte & UNWIND_INFO_FRAME_REGISTER_MASK); + unwindInfo.frameOffset = (byte) (splitByte >> UNWIND_INFO_FRAME_OFFSET_SHIFT); + + unwindInfo.unwindCodes = new UNWIND_CODE[unwindInfo.countOfUnwindCodes]; + for (int i = 0; i < unwindInfo.countOfUnwindCodes; i++) { + UNWIND_CODE code = new UNWIND_CODE(); + code.offsetInProlog = reader.readNextByte(); + + int opCodeData = reader.readNextUnsignedByte(); + code.opCode = UNWIND_CODE_OPCODE.fromInt((opCodeData & UNWIND_INFO_OPCODE_MASK)); + code.opInfoRegister = + UNWIND_CODE_OPINFO_REGISTER.fromInt(opCodeData >> UNWIND_INFO_OPCODE_INFO_SHIFT); + + unwindInfo.unwindCodes[i] = code; + } + + // You can have an exception handler and/or an unwind handler, or you + // can have chained exception handling info only. + if (unwindInfo.hasExceptionHandler() || unwindInfo.hasUnwindHandler()) { + if (unwindInfo.hasExceptionHandler()) { + unwindInfo.exceptionHandlerFunction = reader.readNextInt(); + } + if (unwindInfo.hasUnwindHandler()) { + unwindInfo.unwindHandlerFunction = reader.readNextInt(); + } + } + else if (unwindInfo.hasChainedUnwindInfo()) { + unwindInfo.unwindHandlerChainInfo = new _IMAGE_RUNTIME_FUNCTION_ENTRY(); + unwindInfo.unwindHandlerChainInfo.beginAddress = reader.readNextInt(); + unwindInfo.unwindHandlerChainInfo.endAddress = reader.readNextInt(); + unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData = reader.readNextInt(); + + // Follow the chain to the referenced UNWIND_INFO structure until we + // get to the end + unwindInfo.unwindHandlerChainInfo.unwindInfo = readUnwindInfo(reader, + unwindInfo.unwindHandlerChainInfo.unwindInfoAddressOrData, ntHeader); + } + + reader.setPointerIndex(origIndex); + + return unwindInfo; + } + + public List<_IMAGE_RUNTIME_FUNCTION_ENTRY> getRuntimeFunctionEntries() { + return functionEntries; + } + + public class _IMAGE_RUNTIME_FUNCTION_ENTRY { + public long beginAddress; + public long endAddress; + public long unwindInfoAddressOrData; + public UNWIND_INFO unwindInfo; + } + + public enum UNWIND_CODE_OPCODE { + UWOP_PUSH_NONVOL(0x00), + UWOP_ALLOC_LARGE(0x01), + UWOP_ALLOC_SMALL(0x02), + UWOP_SET_FPREG(0x03), + UWOP_SAVE_NONVOL(0x04), + UWOP_SAVE_NONVOL_FAR(0x05), + UWOP_SAVE_XMM(0x06), + UWOP_SAVE_XMM_FAR(0x07), + UWOP_SAVE_XMM128(0x08), + UWOP_SAVE_XMM128_FAR(0x09), + UWOP_PUSH_MACHFRAME(0x0A); + + private final int id; + + UNWIND_CODE_OPCODE(int value) { + id = value; + } + + public int id() { + return id; + } + + public static UNWIND_CODE_OPCODE fromInt(int id) { + UNWIND_CODE_OPCODE[] values = UNWIND_CODE_OPCODE.values(); + for (UNWIND_CODE_OPCODE value : values) { + if (value.id == id) { + return value; + } + } + return null; + } + } + + public enum UNWIND_CODE_OPINFO_REGISTER { + UNWIND_OPINFO_REGISTER_RAX(0x00), + UNWIND_OPINFO_REGISTER_RCX(0x01), + UNWIND_OPINFO_REGISTER_RDX(0x02), + UNWIND_OPINFO_REGISTER_RBX(0x03), + UNWIND_OPINFO_REGISTER_RSP(0x04), + UNWIND_OPINFO_REGISTER_RBP(0x05), + UNWIND_OPINFO_REGISTER_RSI(0x06), + UNWIND_OPINFO_REGISTER_RDI(0x07), + UNWIND_OPINFO_REGISTER_R8(0x08), + UNWIND_OPINFO_REGISTER_R9(0x09), + UNWIND_OPINFO_REGISTER_R10(0x0A), + UNWIND_OPINFO_REGISTER_R11(0x0B), + UNWIND_OPINFO_REGISTER_R12(0x0C), + UNWIND_OPINFO_REGISTER_R13(0x0D), + UNWIND_OPINFO_REGISTER_R14(0x0E), + UNWIND_OPINFO_REGISTER_R15(0x0F); + + private final int id; + + UNWIND_CODE_OPINFO_REGISTER(int value) { + id = value; + } + + public int id() { + return id; + } + + public static UNWIND_CODE_OPINFO_REGISTER fromInt(int id) { + UNWIND_CODE_OPINFO_REGISTER[] values = UNWIND_CODE_OPINFO_REGISTER.values(); + for (UNWIND_CODE_OPINFO_REGISTER value : values) { + if (value.id == id) { + return value; + } + } + return null; + } + } + + public class UNWIND_CODE { + public byte offsetInProlog; + public UNWIND_CODE_OPCODE opCode; + public UNWIND_CODE_OPINFO_REGISTER opInfoRegister; + } + + public class UNWIND_INFO implements StructConverter { + private static final String NAME = "UNWIND_INFO"; + + private final static int UNW_FLAG_NHANDLER = 0x0; + private final static int UNW_FLAG_EHANDLER = 0x1; + private final static int UNW_FLAG_UHANDLER = 0x2; + private final static int UNW_FLAG_CHAININFO = 0x4; + + private final static int UNWIND_VERSION_FIELD_LENGTH = 0x03; + private final static int UNWIND_FLAGS_FIELD_LENGTH = 0x05; + private final static int UNWIND_FRAME_REGISTER_LENGTH = 0x04; + private final static int UNWIND_OP_FIELD_LENGTH = 0x04; + + byte version; + byte flags; + byte sizeOfProlog; + byte countOfUnwindCodes; + byte frameRegister; + byte frameOffset; + UNWIND_CODE[] unwindCodes; + int exceptionHandlerFunction; + int unwindHandlerFunction; + _IMAGE_RUNTIME_FUNCTION_ENTRY unwindHandlerChainInfo; + + long startOffset; + + public UNWIND_INFO(long offset) { + startOffset = offset; + } + + @Override + public DataType toDataType() throws DuplicateNameException, IOException { + StructureDataType struct = new StructureDataType(NAME + "_" + startOffset, 0); + try { + StructureDataType vf = new StructureDataType("VersionFlags", 0); + vf.insertBitField(0, 1, 0, BYTE, UNWIND_VERSION_FIELD_LENGTH, "Version", null); + vf.insertBitField(0, 1, UNWIND_VERSION_FIELD_LENGTH, defineFlagsField(), + UNWIND_FLAGS_FIELD_LENGTH, "Flags", null); + + struct.add(vf, "Version + Flags", null); + } + catch (InvalidDataTypeException e) { + struct.add(BYTE, "Version + Flags", null); + } + + struct.add(BYTE, "SizeOfProlog", null); + struct.add(BYTE, "CountOfUnwindCodes", null); + + try { + StructureDataType fr = new StructureDataType("FrameRegisterAndOffset", 0); + fr.insertBitField(0, 1, 0, BYTE, UNWIND_FRAME_REGISTER_LENGTH, "FrameRegister", + null); + fr.insertBitField(0, 1, UNWIND_FRAME_REGISTER_LENGTH, BYTE, + UNWIND_FRAME_REGISTER_LENGTH, "FrameOffset", null); + struct.add(fr, "FrameRegister + FrameOffset", null); + } + catch (InvalidDataTypeException e) { + struct.add(BYTE, "FrameRegister + FrameOffset", null); + } + + for (int i = 0; i < countOfUnwindCodes; i++) { + StructureDataType unwindCode = new StructureDataType("UnwindCode", 0); + unwindCode.add(BYTE, "OffsetInProlog", null); + + StructureDataType unwindCodeInfo = new StructureDataType("UnwindCodeInfo", 0); + try { + if (unwindCodes[i].opCode != null) { + unwindCodeInfo.insertBitField(0, 1, 0, defineUnwindOpCodeField(), + UNWIND_OP_FIELD_LENGTH, "UnwindOpCode", null); + } + else { + unwindCodeInfo.insertBitField(0, 1, 0, BYTE, UNWIND_OP_FIELD_LENGTH, + "UnwindOpCode", null); + } + + if (unwindCodes[i].opInfoRegister != null) { + unwindCodeInfo.insertBitField(0, 1, UNWIND_OP_FIELD_LENGTH, + defineUnwindCodeRegisterField(), UNWIND_OP_FIELD_LENGTH, "OpInfo", + null); + } + else { + unwindCodeInfo.insertBitField(0, 1, UNWIND_OP_FIELD_LENGTH, BYTE, + UNWIND_OP_FIELD_LENGTH, "OpInfo", null); + } + } + catch (InvalidDataTypeException e) { + } + unwindCode.add(unwindCodeInfo, "UnwindCodeInfo", null); + + struct.add(unwindCode, "UnwindCode", null); + } + + if (hasExceptionHandler() || hasUnwindHandler()) { + if (hasExceptionHandler()) { + struct.add(IBO32, "ExceptionHandler", null); + } + if (hasUnwindHandler()) { + struct.add(IBO32, "UnwindHandler", null); + } + } + else { + if (hasChainedUnwindInfo()) { + struct.add(IBO32, "FunctionStartAddress", null); + struct.add(IBO32, "FunctionEndAddress", null); + struct.add(IBO32, "FunctionUnwindInfoAddress", null); + } + } + + return struct; + } + + public boolean hasExceptionHandler() { + return (flags & UNW_FLAG_EHANDLER) == UNW_FLAG_EHANDLER; + } + + public boolean hasUnwindHandler() { + return (flags & UNW_FLAG_UHANDLER) == UNW_FLAG_UHANDLER; + } + + public boolean hasChainedUnwindInfo() { + return (flags & UNW_FLAG_CHAININFO) == UNW_FLAG_CHAININFO; + } + + private EnumDataType defineFlagsField() { + EnumDataType flagsField = new EnumDataType("Flags", 5); + flagsField.add("UNW_FLAG_NHANDLER", UNW_FLAG_NHANDLER); + flagsField.add("UNW_FLAG_EHANDLER", UNW_FLAG_EHANDLER); + flagsField.add("UNW_FLAG_UHANDLER", UNW_FLAG_UHANDLER); + flagsField.add("UNW_FLAG_CHAININFO", UNW_FLAG_CHAININFO); + + return flagsField; + } + + private EnumDataType defineUnwindOpCodeField() { + EnumDataType unwindOpCodeField = new EnumDataType("UNWIND_CODE_OPCODE", 4); + unwindOpCodeField.add("UWOP_PUSH_NONVOL", UNWIND_CODE_OPCODE.UWOP_PUSH_NONVOL.id); + unwindOpCodeField.add("UWOP_ALLOC_LARGE", UNWIND_CODE_OPCODE.UWOP_ALLOC_LARGE.id); + unwindOpCodeField.add("UWOP_ALLOC_SMALL", UNWIND_CODE_OPCODE.UWOP_ALLOC_SMALL.id); + unwindOpCodeField.add("UWOP_SET_FPREG", UNWIND_CODE_OPCODE.UWOP_SET_FPREG.id); + unwindOpCodeField.add("UWOP_SAVE_NONVOL", UNWIND_CODE_OPCODE.UWOP_SAVE_NONVOL.id); + unwindOpCodeField.add("UWOP_SAVE_NONVOL_FAR", + UNWIND_CODE_OPCODE.UWOP_SAVE_NONVOL_FAR.id); + unwindOpCodeField.add("UWOP_SAVE_XMM", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM.id); + unwindOpCodeField.add("UWOP_SAVE_XMM_FAR", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM_FAR.id); + unwindOpCodeField.add("UWOP_SAVE_XMM128", UNWIND_CODE_OPCODE.UWOP_SAVE_XMM128.id); + unwindOpCodeField.add("UWOP_SAVE_XMM128_FAR", + UNWIND_CODE_OPCODE.UWOP_SAVE_XMM128_FAR.id); + unwindOpCodeField.add("UWOP_PUSH_MACHFRAME", UNWIND_CODE_OPCODE.UWOP_PUSH_MACHFRAME.id); + + return unwindOpCodeField; + } + + private EnumDataType defineUnwindCodeRegisterField() { + EnumDataType unwindCodeRegisterField = + new EnumDataType("UNWIND_CODE_OPINFO_REGISTER", 4); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RAX", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RAX.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RCX", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RCX.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RDX", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RDX.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RBX", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RBX.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RSP", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RSP.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RBP", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RBP.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RSI", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RSI.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_RDI", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_RDI.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R8", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R8.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R9", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R9.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R10", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R10.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R11", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R11.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R12", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R12.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R13", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R13.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R14", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R14.id); + unwindCodeRegisterField.add("UNWIND_OPINFO_REGISTER_R15", + UNWIND_CODE_OPINFO_REGISTER.UNWIND_OPINFO_REGISTER_R15.id); + + return unwindCodeRegisterField; + } + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java index 0912d75484..e88d1fe976 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/NTHeader.java @@ -30,7 +30,7 @@ import ghidra.util.task.TaskMonitorAdapter; /** * A class to represent the IMAGE_NT_HEADERS32 and - * IMAGE_NT_HEADERS64 structs as defined in + * IMAGE_NT_HEADERS64 structs as defined in * winnt.h. *
      * typedef struct _IMAGE_NT_HEADERS {
    @@ -39,8 +39,8 @@ import ghidra.util.task.TaskMonitorAdapter;
      *    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
      * };
      * 
    - * - * + * + * */ public class NTHeader implements StructConverter, OffsetValidator { /** @@ -82,8 +82,8 @@ public class NTHeader implements StructConverter, OffsetValidator { public NTHeader() { } - private void initNTHeader(FactoryBundledWithBinaryReader reader, int index, SectionLayout layout, - boolean advancedProcess, boolean parseCliHeaders) + private void initNTHeader(FactoryBundledWithBinaryReader reader, int index, + SectionLayout layout, boolean advancedProcess, boolean parseCliHeaders) throws InvalidNTHeaderException, IOException { this.reader = reader; this.index = index; @@ -172,9 +172,9 @@ public class NTHeader implements StructConverter, OffsetValidator { //low alignment mode? // if (optionalHeader != null) { - if (optionalHeader.getFileAlignment() == optionalHeader.getSectionAlignment() - && optionalHeader.getSectionAlignment() < 800 - && optionalHeader.getFileAlignment() > 1) { + if (optionalHeader.getFileAlignment() == optionalHeader.getSectionAlignment() && + optionalHeader.getSectionAlignment() < 800 && + optionalHeader.getFileAlignment() > 1) { return rva; } } @@ -270,6 +270,7 @@ public class NTHeader implements StructConverter, OffsetValidator { fileHeader.processSections(optionalHeader); fileHeader.processSymbols(); + fileHeader.processImageRuntimeFunctionEntries(); if (advancedProcess) { optionalHeader.processDataDirectories(TaskMonitorAdapter.DUMMY_MONITOR); @@ -278,7 +279,7 @@ public class NTHeader implements StructConverter, OffsetValidator { void writeHeader(RandomAccessFile raf, DataConverter dc) throws IOException { - raf.seek( index ); + raf.seek(index); raf.write(dc.getBytes(signature)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java index f7f1141135..ad4317876c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PeLoader.java @@ -28,6 +28,7 @@ import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.format.mz.DOSHeader; import ghidra.app.util.bin.format.pe.*; import ghidra.app.util.bin.format.pe.ImageCor20Header.ImageCor20Flags; +import ghidra.app.util.bin.format.pe.ImageRuntimeFunctionEntries._IMAGE_RUNTIME_FUNCTION_ENTRY; import ghidra.app.util.bin.format.pe.PortableExecutable.SectionLayout; import ghidra.app.util.bin.format.pe.debug.DebugCOFFSymbol; import ghidra.app.util.bin.format.pe.debug.DebugDirectoryParser; @@ -148,6 +149,7 @@ public class PeLoader extends AbstractPeDebugLoader { processProperties(optionalHeader, program, monitor); processComments(program.getListing(), monitor); processSymbols(fileHeader, sectionToAddress, program, monitor, log); + processImageRuntimeFunctionEntries(fileHeader, program, monitor, log); processEntryPoints(ntHeader, program, monitor); String compiler = CompilerOpinion.getOpinion(pe, provider).toString(); @@ -248,24 +250,74 @@ public class PeLoader extends AbstractPeDebugLoader { setComment(CodeUnit.EOL_COMMENT, start, section.getName()); start = start.add(dt.getLength()); } - -// for (int i = 0; i < datadirs.length; ++i) { -// if (datadirs[i] == null || datadirs[i].getSize() == 0) { -// continue; -// } -// -// if (datadirs[i].hasParsedCorrectly()) { -// start = datadirs[i].getMarkupAddress(program, true); -// dt = datadirs[i].toDataType(); -// DataUtilities.createData(program, start, dt, true, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); -// } -// } } catch (Exception e1) { Msg.error(this, "Error laying down header structures " + e1); } } + private void processImageRuntimeFunctionEntries(FileHeader fileHeader, Program program, + TaskMonitor monitor, MessageLog log) { + + // Check to see that we have exception data to process + SectionHeader irfeHeader = null; + for (SectionHeader header : fileHeader.getSectionHeaders()) { + if (header.getName().contains(".pdata")) { + irfeHeader = header; + break; + } + } + + if (irfeHeader == null) { + return; + } + + Address start = program.getImageBase().add(irfeHeader.getVirtualAddress()); + + List<_IMAGE_RUNTIME_FUNCTION_ENTRY> irfes = fileHeader.getImageRuntimeFunctionEntries(); + if (irfes == null) { + return; + } + + StructureDataType dt = new StructureDataType(".PDATA", 0); + dt.setCategoryPath(new CategoryPath("/PE")); + + // Lay an array of RUNTIME_INFO structure out over the data + StructureDataType irfeStruct = new StructureDataType("_IMAGE_RUNTIME_FUNCTION_ENTRY", 0); + irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "BeginAddress", null); + irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "EndAddress", null); + irfeStruct.add(ghidra.app.util.bin.StructConverter.IBO32, "UnwindInfoAddressOrData", null); + + ArrayDataType irfeArray = + new ArrayDataType(irfeStruct, irfes.size(), irfeStruct.getLength()); + + try { + DataUtilities.createData(program, start, irfeArray, irfeArray.getLength(), true, + DataUtilities.ClearDataMode.CHECK_FOR_SPACE); + } + catch (CodeUnitInsertionException e) { + return; + } + + // Each RUNTIME_INFO contains an address to an UNWIND_INFO structure + // which also needs to be laid out. When they contain chaining data + // they're recursive but the toDataType() function handles that. + for (_IMAGE_RUNTIME_FUNCTION_ENTRY entry : irfes) { + if (entry.unwindInfoAddressOrData > 0) { + try { + dt = (StructureDataType) entry.unwindInfo.toDataType(); + start = program.getImageBase().add(entry.unwindInfoAddressOrData); + + DataUtilities.createData(program, start, dt, dt.getLength(), true, + DataUtilities.ClearDataMode.CHECK_FOR_SPACE); + } + catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { + continue; + } + } + } + } + private void processSymbols(FileHeader fileHeader, Map sectionToAddress, Program program, TaskMonitor monitor, MessageLog log) { List symbols = fileHeader.getSymbols(); @@ -493,7 +545,7 @@ public class PeLoader extends AbstractPeDebugLoader { break; } - // Get address of current position in the import address table + // Get address of current position in the import address table Address iatAddr = iatBaseAddr.add(offset); Data iatData = listing.getDataAt(iatAddr); if (iatData == null || !(iatData.getValue() instanceof Address)) { @@ -506,8 +558,7 @@ public class PeLoader extends AbstractPeDebugLoader { importInfo.getName(), null, SourceType.IMPORTED, 0, RefType.DATA); } catch (DuplicateNameException | InvalidInputException e) { - log.appendMsg( - "Failed to create Delay Load external function at: " + iatAddr); + log.appendMsg("Failed to create Delay Load external function at: " + iatAddr); } // Create delay load proxy function diff --git a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java index b2711c6493..1ada2cecae 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java @@ -56,7 +56,7 @@ import ghidra.util.timer.GTimer; * * Refactor fileInfo -> needs dialog to show properties * Refactor GFile.getInfo() to return Map<> instead of String. - * Persistant filesystem - when reopen tool, filesystems should auto-reopen. + * Persistent filesystem - when reopen tool, filesystems should auto-reopen. * Unify GhidraFileChooser with GFileSystem. * Add "Mounted Filesystems" button to show currently opened GFilesystems? * Dockable filesystem browser in FrontEnd. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java index 0d098c9bc1..33872f6f17 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/state/VarnodeOperation.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -170,7 +169,7 @@ public class VarnodeOperation extends Varnode { } @Override - public boolean isPersistant() { + public boolean isPersistent() { return false; } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java index 9ed0d7ada6..e7adb329df 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPluginTest.java @@ -205,7 +205,33 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe waitForSwing(); waitForTree(); - runSwing(() -> jTree.stopEditing()); + + // verify that the tree opens a new node with the default + // category name is "New Category" + assertEquals(childCount + 1, miscNode.getChildCount()); + GTreeNode node = miscNode.getChild("New Category"); + assertNotNull(node); + } + + @Test + public void testCreateCategory_WhileFiltered() throws Exception { + // select a category + GTreeNode miscNode = programNode.getChild("MISC"); + assertNotNull(miscNode); + expandNode(miscNode); + + int childCount = miscNode.getChildCount(); + selectNode(miscNode); + + filterTree(miscNode.getName()); + + DockingActionIf action = getAction(plugin, "New Category"); + assertTrue(action.isEnabledForContext(treeContext)); + + // select "New Category" action + DataTypeTestUtils.performAction(action, tree, false); + + waitForDialogComponent("Cannot Edit Tree Node"); // verify that the tree opens a new node with the default // category name is "New Category" diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java index ed2f6f1df1..aa610ac733 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java @@ -31,6 +31,7 @@ import ghidra.program.model.pcode.*; import ghidra.service.graph.*; import ghidra.util.Msg; import java.util.*; +import static ghidra.service.graph.GraphDisplay.*; public class GraphAST extends GhidraScript { protected static final String COLOR_ATTRIBUTE = "Color"; @@ -66,11 +67,12 @@ public class GraphAST extends GhidraScript { buildGraph(); Map properties = new HashMap<>(); - properties.put("selectedVertexColor", "0xFF1493"); - properties.put("selectedEdgeColor", "0xFF1493"); - properties.put("initialLayoutAlgorithm", "Hierarchical MinCross Coffman Graham"); - properties.put("displayVerticesAsIcons", "false"); - properties.put("vertexLabelPosition", "S"); + properties.put(SELECTED_VERTEX_COLOR, "0xFF1493"); + properties.put(SELECTED_EDGE_COLOR, "0xFF1493"); + properties.put(INITIAL_LAYOUT_ALGORITHM, "Hierarchical MinCross Coffman Graham"); + properties.put(DISPLAY_VERTICES_AS_ICONS, "false"); + properties.put(VERTEX_LABEL_POSITION, "S"); + properties.put(ENABLE_EDGE_SELECTION, "true"); GraphDisplay graphDisplay = graphDisplayBroker.getDefaultGraphDisplay(false, properties, monitor); // graphDisplay.defineVertexAttribute(CODE_ATTRIBUTE); // @@ -137,7 +139,7 @@ public class GraphAST extends GhidraScript { else if (vn.isUnique()) { colorattrib = "Black"; } - else if (vn.isPersistant()) { + else if (vn.isPersistent()) { colorattrib = "DarkOrange"; } else if (vn.isAddrTied()) { diff --git a/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml b/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml index 70f219d2f6..4921d8d051 100644 --- a/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml +++ b/Ghidra/Features/Decompiler/src/main/doc/pcoderef.xml @@ -926,7 +926,7 @@ This is a truncation operator that understands the endianess of the data. Input1 indicates the number of least significant bytes of input0 to be thrown away. Output is then filled with any remaining bytes of input0 up to the size of output. If the size of -output is smaller than the size of input0 plus the constant input1, +output is smaller than the size of input0 minus the constant input1, then the additional most significant bytes of input0 will also be truncated. diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java index ebe02584e0..0a6a4e7db3 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java @@ -34,6 +34,8 @@ import ghidra.util.exception.GraphException; import ghidra.util.task.Task; import ghidra.util.task.TaskMonitor; +import static ghidra.service.graph.GraphDisplay.*; + public class ASTGraphTask extends Task { enum GraphType { CONTROL_FLOW_GRAPH("AST Control Flow"), DATA_FLOW_GRAPH("AST Data Flow"); @@ -104,9 +106,10 @@ public class ASTGraphTask extends Task { createControlFlowGraph(graph, monitor); } Map properties = new HashMap<>(); - properties.put("selectedVertexColor", "0xFF1493"); - properties.put("selectedEdgeColor", "0xFF1493"); - properties.put("initialLayoutAlgorithm", "Hierarchical MinCross Coffman Graham"); + properties.put(SELECTED_VERTEX_COLOR, "0xFF1493"); + properties.put(SELECTED_EDGE_COLOR, "0xFF1493"); + properties.put(INITIAL_LAYOUT_ALGORITHM, "Hierarchical MinCross Coffman Graham"); + properties.put(ENABLE_EDGE_SELECTION, "true"); GraphDisplay display = graphService.getDefaultGraphDisplay(!newGraph, properties, monitor); ASTGraphDisplayListener displayListener = new ASTGraphDisplayListener(tool, display, hfunction, graphType); diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java index 912f6b3088..ae4d47fdc9 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java @@ -15,9 +15,10 @@ */ package ghidra.file.formats.sevenzip; -import java.io.*; import java.util.*; +import java.io.*; + import org.apache.commons.io.FilenameUtils; import ghidra.formats.gfilesystem.*; @@ -261,6 +262,9 @@ public class SevenZipFileSystem implements GFileSystem { case UNKNOWN_OPERATION_RESULT: { throw new IOException("Unexpected: 7-Zip returned unknown operation result"); } + case WRONG_PASSWORD: { + throw new IOException("7-Zip wrong password"); + } case OK: default: { // it's all ok! diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java index 3417362362..6b64a95ae4 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java @@ -239,16 +239,13 @@ public class GnuDemanglerParser { * Pattern: text for|to text * * Parts: - * -required text (capture group 2) - * --note: this uses '++', a possessive quantifier, to help keep the - * backtracking to a minimum - * -a space - * -'for' or 'to' (capture group 3) - * -a space + * -required text (capture group 2) -+ + * -'for' or 'to' (capture group 3) | (capture group 1) + * -a space -+ * -optional text (capture group 4) - * - * Note: capture group 1 is the combination of groups 2 and 3 - * + * + * Note: capture group 1 is the combination of groups 2 and 3 with trailing space + * * Examples: * construction vtable for * vtable for diff --git a/Ghidra/Features/GraphServices/Module.manifest b/Ghidra/Features/GraphServices/Module.manifest index 361687fc49..ad8b9ffc53 100644 --- a/Ghidra/Features/GraphServices/Module.manifest +++ b/Ghidra/Features/GraphServices/Module.manifest @@ -1,7 +1,7 @@ EXCLUDE FROM GHIDRA JAR: true -MODULE FILE LICENSE: lib/jungrapht-visualization-1.1.jar BSD -MODULE FILE LICENSE: lib/jungrapht-layout-1.1.jar BSD +MODULE FILE LICENSE: lib/jungrapht-visualization-1.2.jar BSD +MODULE FILE LICENSE: lib/jungrapht-layout-1.2.jar BSD MODULE FILE LICENSE: lib/jgrapht-core-1.5.0.jar LGPL 2.1 MODULE FILE LICENSE: lib/jgrapht-io-1.5.0.jar LGPL 2.1 MODULE FILE LICENSE: lib/jheaps-0.13.jar Apache License 2.0 diff --git a/Ghidra/Features/GraphServices/build.gradle b/Ghidra/Features/GraphServices/build.gradle index 9d3c632bf9..2c53c410ca 100644 --- a/Ghidra/Features/GraphServices/build.gradle +++ b/Ghidra/Features/GraphServices/build.gradle @@ -12,9 +12,9 @@ dependencies { compile project(":Base") // jungrapht - exclude slf4j which produces a conflict with other uses with Ghidra - compile ("com.github.tomnelson:jungrapht-visualization:1.1") { exclude group: "org.slf4j", module: "slf4j-api" } - compile ("com.github.tomnelson:jungrapht-layout:1.1") { exclude group: "org.slf4j", module: "slf4j-api" } - + compile ("com.github.tomnelson:jungrapht-visualization:1.2") { exclude group: "org.slf4j", module: "slf4j-api" } + compile ("com.github.tomnelson:jungrapht-layout:1.2") { exclude group: "org.slf4j", module: "slf4j-api" } + compile "org.jgrapht:jgrapht-core:1.5.0" // not using jgrapht-io code that depends on antlr, so exclude antlr diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index d2d345fcc9..de890a5582 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -103,28 +103,33 @@ public class DefaultGraphDisplay implements GraphDisplay { private static final String ACTION_OWNER = "GraphServices"; - /* - A handful of properties that can be set via the constructor - */ - private static final String SELECTED_VERTEX_COLOR = "selectedVertexColor"; - private static final String SELECTED_EDGE_COLOR = "selectedEdgeColor"; - private static final String INITIAL_LAYOUT_ALGORITHM = "initialLayoutAlgorithm"; - private static final String DISPLAY_VERTICES_AS_ICONS = "displayVerticesAsIcons"; - private static final String VERTEX_LABEL_POSITION = "vertexLabelPosition"; - private static final int MAX_NODES = Integer.getInteger("maxNodes", 10000); private static final Dimension PREFERRED_VIEW_SIZE = new Dimension(1000, 1000); private static final Dimension PREFERRED_LAYOUT_SIZE = new Dimension(3000, 3000); private Logger log = Logger.getLogger(DefaultGraphDisplay.class.getName()); - private Map displayProperties = new HashMap<>(); + private Map displayProperties; private Set addedActions = new LinkedHashSet<>(); private GraphDisplayListener listener = new DummyGraphDisplayListener(); private String title; private AttributedGraph graph; + private static String DEFAULT_EDGE_TYPE_PRIORITY_LIST = + "Fall-Through,"+ + "Conditional-Return,"+ + "Unconditional-Jump,"+ + "Conditional-Jump,"+ + "Unconditional-Call,"+ + "Conditional-Call,"+ + "Terminator,"+ + "Computed,"+ + "Indirection,"+ + "Entry"; + + private static String DEFAULT_FAVORED_EDGES = "Fall-Through"; + /** * a unique id for this {@link GraphDisplay} */ @@ -219,7 +224,9 @@ public class DefaultGraphDisplay implements GraphDisplay { viewer.getComponent().add(satelliteViewer.getComponent()); } layoutTransitionManager = - new LayoutTransitionManager(viewer, this::isRoot); + new LayoutTransitionManager(viewer, this::isRoot, + getEdgeTypePriorityList(), + getFavoredEdgePredicate()); viewer.getComponent().addComponentListener(new ComponentAdapter() { @Override @@ -252,6 +259,19 @@ public class DefaultGraphDisplay implements GraphDisplay { return Colors.getHexColor(property); } + private List getEdgeTypePriorityList() { + return Arrays.asList(displayProperties + .getOrDefault(EDGE_TYPE_PRIORITY_LIST, DEFAULT_EDGE_TYPE_PRIORITY_LIST) + .split(",")); + } + + private Predicate getFavoredEdgePredicate() { + String[] favoredEdges = displayProperties.getOrDefault(FAVORED_EDGES, DEFAULT_FAVORED_EDGES) + .split(","); + return attributedEdge -> Arrays.stream(favoredEdges) + .anyMatch(s -> s.equals(attributedEdge.getAttribute("EdgeType"))); + } + JComponent getComponent() { JComponent component = viewer.getComponent(); component.setFocusable(true); @@ -486,7 +506,7 @@ public class DefaultGraphDisplay implements GraphDisplay { "Extends the current selection by including the target/source vertices " + "of all edges whose source/target is selected") .keyBinding("ctrl C") - .enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) && + .enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) || !isAllSelected(getTargetVerticesFromSelected())) .onAction(c -> growSelection(getAllComponentVerticesFromSelected())) .buildAndInstallLocal(componentProvider); @@ -610,6 +630,23 @@ public class DefaultGraphDisplay implements GraphDisplay { private void growSelection(Set vertices) { viewer.getSelectedVertexState().select(vertices); + selectEdgesConnecting(vertices); + } + + // select all the edges that connect the supplied vertices + private void selectEdgesConnecting(Collection vertices) { + viewer.getSelectedEdgeState().select( + graph.edgeSet() + .stream() + .filter( + e -> { + AttributedVertex source = graph.getEdgeSource(e); + AttributedVertex target = graph.getEdgeTarget(e); + return vertices.contains(source) + && vertices.contains(target); + }) + .collect(Collectors.toSet())); + } private boolean isAllSelected(Set vertices) { @@ -617,8 +654,8 @@ public class DefaultGraphDisplay implements GraphDisplay { } private Set getSourceVerticesFromSelected() { - Set sources = new HashSet<>(); Set selectedVertices = getSelectedVertices(); + Set sources = new HashSet<>(selectedVertices); for (AttributedVertex v : selectedVertices) { Set edges = graph.incomingEdgesOf(v); edges.forEach(e -> sources.add(graph.getEdgeSource(e))); @@ -635,8 +672,8 @@ public class DefaultGraphDisplay implements GraphDisplay { } private Set getTargetVerticesFromSelected() { - Set targets = new HashSet<>(); Set selectedVertices = getSelectedVertices(); + Set targets = new HashSet<>(selectedVertices); for (AttributedVertex v : selectedVertices) { Set edges = graph.outgoingEdgesOf(v); edges.forEach(e -> targets.add(graph.getEdgeTarget(e))); @@ -674,9 +711,20 @@ public class DefaultGraphDisplay implements GraphDisplay { return upstream; } + /** + * Gather all source and target vertices until there are no more available. + * @return all the vertices in the component(s) of the selected vertices + */ public Set getAllComponentVerticesFromSelected() { - Set componentVertices = getAllDownstreamVerticesFromSelected(); - componentVertices.addAll(getAllUpstreamVerticesFromSelected()); + Set componentVertices = new HashSet<>(viewer.getSelectedVertices()); + Set downstream = getAllDownstreamVerticesFromSelected(); + Set upstream = getAllUpstreamVerticesFromSelected(); + while (!downstream.isEmpty() || !upstream.isEmpty()) { + componentVertices.addAll(downstream); + componentVertices.addAll(upstream); + downstream = getAllDownstreamVerticesFromSelected(); + upstream = getAllUpstreamVerticesFromSelected(); + } return componentVertices; } @@ -955,13 +1003,14 @@ public class DefaultGraphDisplay implements GraphDisplay { /** * Determines if a vertex is a root. For our purpose, a root either has no incoming edges - * or has at least one outgoing "favored" edge and no incoming "favored" edge + * or if all edges of a vertex are 'loop' edges * @param vertex the vertex to test if it is a root * @return true if the vertex is a root */ private boolean isRoot(AttributedVertex vertex) { Set incomingEdgesOf = graph.incomingEdgesOf(vertex); - return incomingEdgesOf.isEmpty(); + return incomingEdgesOf.isEmpty() || + graph.incomingEdgesOf(vertex).equals(graph.outgoingEdgesOf(vertex)); } /** @@ -1230,12 +1279,6 @@ public class DefaultGraphDisplay implements GraphDisplay { setVertexPreferences(vv); - // the selectedEdgeState will be controlled by the vertices that are selected. - // if both endpoints of an edge are selected, select that edge. - vv.setSelectedEdgeState( - new VertexEndpointsSelectedEdgeSelectedState<>(vv.getVisualizationModel()::getGraph, - vv.getSelectedVertexState())); - // selected edges will be drawn with a wider stroke renderContext.setEdgeStrokeFunction( e -> isSelected(e) ? new BasicStroke(20.f) @@ -1259,7 +1302,6 @@ public class DefaultGraphDisplay implements GraphDisplay { // cause the lightweight (optimized) renderer to use the vertex shapes instead // of using default shapes. - if (vertexRenderer instanceof LightweightVertexRenderer) { Function vertexShapeFunction = renderContext.getVertexShapeFunction(); @@ -1282,7 +1324,9 @@ public class DefaultGraphDisplay implements GraphDisplay { vv.getComponent().removeMouseListener(mouseListener); } - graphMouse = new JgtGraphMouse(this); + graphMouse = new JgtGraphMouse(this, + Boolean.parseBoolean(displayProperties.getOrDefault(ENABLE_EDGE_SELECTION, + "false"))); vv.setGraphMouse(graphMouse); return vv; diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java index c248961f26..00690e8436 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutFunction.java @@ -15,7 +15,9 @@ */ package ghidra.graph.visualization; +import java.util.Comparator; import java.util.function.Function; +import java.util.function.Predicate; import org.jungrapht.visualization.layout.algorithms.*; import org.jungrapht.visualization.layout.algorithms.repulsion.BarnesHutFRRepulsion; @@ -36,22 +38,38 @@ class LayoutFunction static final String KAMADA_KAWAI = "Force Balanced"; static final String FRUCTERMAN_REINGOLD = "Force Directed"; - static final String CIRCLE_MINCROSS = "Circle"; + static final String CIRCLE = "Circle"; static final String TIDIER_TREE = "Compact Hierarchical"; static final String TIDIER_RADIAL_TREE = "Compact Radial"; static final String MIN_CROSS_TOP_DOWN = "Hierarchical MinCross Top Down"; static final String MIN_CROSS_LONGEST_PATH = "Hierarchical MinCross Longest Path"; static final String MIN_CROSS_NETWORK_SIMPLEX = "Hierarchical MinCross Network Simplex"; static final String MIN_CROSS_COFFMAN_GRAHAM = "Hierarchical MinCross Coffman Graham"; + static final String EXP_MIN_CROSS_TOP_DOWN = "Experimental Hierarchical MinCross Top Down"; + static final String EXP_MIN_CROSS_LONGEST_PATH = "Experimental Hierarchical MinCross Longest Path"; + static final String EXP_MIN_CROSS_NETWORK_SIMPLEX = "Experimental Hierarchical MinCross Network Simplex"; + static final String EXP_MIN_CROSS_COFFMAN_GRAHAM = "Experimental Hierarchical MinCross Coffman Graham"; static final String TREE = "Hierarchical"; static final String RADIAL = "Radial"; static final String BALLOON = "Balloon"; static final String GEM = "Gem (Graph Embedder)"; + Predicate favoredEdgePredicate; + Comparator edgeTypeComparator; + + LayoutFunction(Comparator edgeTypeComparator, Predicate favoredEdgePredicate) { + this.edgeTypeComparator = edgeTypeComparator; + this.favoredEdgePredicate = favoredEdgePredicate; + } + public String[] getNames() { return new String[] { TIDIER_TREE, TREE, TIDIER_RADIAL_TREE, MIN_CROSS_TOP_DOWN, MIN_CROSS_LONGEST_PATH, - MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE_MINCROSS, + MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE, + EXP_MIN_CROSS_TOP_DOWN, + EXP_MIN_CROSS_LONGEST_PATH, + EXP_MIN_CROSS_NETWORK_SIMPLEX, + EXP_MIN_CROSS_COFFMAN_GRAHAM, KAMADA_KAWAI, FRUCTERMAN_REINGOLD, RADIAL, BALLOON, GEM }; } @@ -67,27 +85,56 @@ class LayoutFunction case FRUCTERMAN_REINGOLD: return FRLayoutAlgorithm. builder() .repulsionContractBuilder(BarnesHutFRRepulsion.builder()); - case CIRCLE_MINCROSS: + case CIRCLE: return CircleLayoutAlgorithm. builder() - .reduceEdgeCrossing(true); + .reduceEdgeCrossing(false); case TIDIER_RADIAL_TREE: return TidierRadialTreeLayoutAlgorithm - . edgeAwareBuilder(); + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator); case MIN_CROSS_TOP_DOWN: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.TOP_DOWN); case MIN_CROSS_LONGEST_PATH: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.LONGEST_PATH); case MIN_CROSS_NETWORK_SIMPLEX: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) .layering(Layering.NETWORK_SIMPLEX); case MIN_CROSS_COFFMAN_GRAHAM: return EiglspergerLayoutAlgorithm . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .layering(Layering.COFFMAN_GRAHAM); + case EXP_MIN_CROSS_TOP_DOWN: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.TOP_DOWN); + case EXP_MIN_CROSS_LONGEST_PATH: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.LONGEST_PATH); + case EXP_MIN_CROSS_NETWORK_SIMPLEX: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) + .layering(Layering.NETWORK_SIMPLEX); + case EXP_MIN_CROSS_COFFMAN_GRAHAM: + return EiglspergerLayoutAlgorithm + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator) + .favoredEdgePredicate(favoredEdgePredicate) .layering(Layering.COFFMAN_GRAHAM); case RADIAL: return RadialTreeLayoutAlgorithm @@ -103,7 +150,9 @@ class LayoutFunction case TIDIER_TREE: default: return TidierTreeLayoutAlgorithm - . edgeAwareBuilder(); + . edgeAwareBuilder() + .edgeComparator(edgeTypeComparator); + } } } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java index c500ba8f51..6849d81829 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/LayoutTransitionManager.java @@ -38,7 +38,7 @@ import ghidra.service.graph.AttributedVertex; */ class LayoutTransitionManager { - LayoutFunction layoutFunction = new LayoutFunction(); + LayoutFunction layoutFunction; /** * the {@link VisualizationServer} used to display graphs using the requested {@link LayoutAlgorithm} */ @@ -49,24 +49,6 @@ class LayoutTransitionManager { */ Predicate rootPredicate; - public static final List EDGE_PRIORITY_LIST = - List.of( - "Fall-Through", - "Conditional-Return", - "Unconditional-Jump", - "Conditional-Jump", - "Unconditional-Call", - "Conditional-Call", - "Terminator", - "Computed", - "Indirection", - "Entry"); - /** - * a {@link Comparator} to sort edges during layout graph traversal - * The default uses the {@code EDGE_PRIORTITY_LIST } - */ - Comparator edgeComparator = new EdgeComparator(EDGE_PRIORITY_LIST); - /** * a {@link Function} to provide {@link Rectangle} (and thus bounds} for vertices */ @@ -81,47 +63,54 @@ class LayoutTransitionManager { LayoutPaintable.RadialRings radialLayoutRings; - /** * Create an instance with passed parameters * @param visualizationServer displays the graph * @param rootPredicate selects root vertices + * @param edgeTypePriorityList a {@code List} of EdgeType names in priority order + * @param favoredEdgePredicate q {@code Predicate} that will cause certain EdgeTypes to be favored during layout */ public LayoutTransitionManager( VisualizationServer visualizationServer, - Predicate rootPredicate) { + Predicate rootPredicate, + List edgeTypePriorityList, + Predicate favoredEdgePredicate) { this.visualizationServer = visualizationServer; this.rootPredicate = rootPredicate; - this.renderContext = visualizationServer.getRenderContext(); this.vertexBoundsFunction = visualizationServer.getRenderContext().getVertexBoundsFunction(); - } - - public void setEdgeComparator(Comparator edgeComparator) { - this.edgeComparator = edgeComparator; + this.layoutFunction = new LayoutFunction(new EdgeComparator(edgeTypePriorityList), + favoredEdgePredicate); } /** * set the layout in order to configure the requested {@link LayoutAlgorithm} * @param layoutName the name of the layout algorithm to use */ - @SuppressWarnings("unchecked") public void setLayout(String layoutName) { LayoutAlgorithm.Builder builder = layoutFunction.apply(layoutName); LayoutAlgorithm layoutAlgorithm = builder.build(); + // layout algorithm considers the size of vertices if (layoutAlgorithm instanceof VertexBoundsFunctionConsumer) { ((VertexBoundsFunctionConsumer) layoutAlgorithm) .setVertexBoundsFunction(vertexBoundsFunction); } + // mincross layouts are 'layered'. put some bounds on the number of + // iterations of the level cross function based on the size of the graph + // very large graphs do not improve enough to out-weigh the cost of + // repeated iterations if (layoutAlgorithm instanceof Layered) { ((Layered) layoutAlgorithm) .setMaxLevelCrossFunction(g -> Math.max(1, Math.min(10, 500 / g.vertexSet().size()))); } + // tree layouts need a way to determine which vertices are roots + // especially when the graph is not a DAG if (layoutAlgorithm instanceof TreeLayout) { ((TreeLayout) layoutAlgorithm).setRootPredicate(rootPredicate); } // remove any previously added layout paintables + // and apply paintables to these 2 algorithms removePaintable(radialLayoutRings); removePaintable(balloonLayoutRings); if (layoutAlgorithm instanceof BalloonLayoutAlgorithm) { @@ -138,9 +127,7 @@ class LayoutTransitionManager { visualizationServer.addPreRenderPaintable(radialLayoutRings); } - if (layoutAlgorithm instanceof EdgeSorting) { - ((EdgeSorting) layoutAlgorithm).setEdgeComparator(edgeComparator); - } + // apply the layout algorithm LayoutAlgorithmTransition.apply(visualizationServer, layoutAlgorithm); } @@ -151,7 +138,10 @@ class LayoutTransitionManager { } } - @SuppressWarnings("unchecked") + /** + * Supplies the {@code LayoutAlgorithm} to be used for the initial @{code Graph} visualization + * @return + */ public LayoutAlgorithm getInitialLayoutAlgorithm() { LayoutAlgorithm initialLayoutAlgorithm = layoutFunction.apply(TIDIER_TREE).build(); @@ -159,12 +149,6 @@ class LayoutTransitionManager { if (initialLayoutAlgorithm instanceof TreeLayout) { ((TreeLayout) initialLayoutAlgorithm) .setRootPredicate(rootPredicate); - ((TreeLayout) initialLayoutAlgorithm) - .setVertexBoundsFunction(vertexBoundsFunction); - } - if (initialLayoutAlgorithm instanceof EdgeSorting) { - ((EdgeSorting) initialLayoutAlgorithm) - .setEdgeComparator(edgeComparator); } if (initialLayoutAlgorithm instanceof VertexBoundsFunctionConsumer) { ((VertexBoundsFunctionConsumer) initialLayoutAlgorithm) @@ -173,6 +157,10 @@ class LayoutTransitionManager { return initialLayoutAlgorithm; } + /** + * Supplies a {@code String[]} array of the supported layout names + * @return + */ public String[] getLayoutNames() { return layoutFunction.getNames(); } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java index b198d513b1..fc77954316 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtGraphMouse.java @@ -29,12 +29,14 @@ import ghidra.service.graph.AttributedVertex; public class JgtGraphMouse extends DefaultGraphMouse { private DefaultGraphDisplay graphDisplay; + private boolean allowEdgeSelection; // TODO we should not need the graph display for any mouse plugins, but the API is net yet // robust enough to communicate fully without it - public JgtGraphMouse(DefaultGraphDisplay graphDisplay) { + public JgtGraphMouse(DefaultGraphDisplay graphDisplay, boolean allowEdgeSelection) { super(DefaultGraphMouse.builder()); this.graphDisplay = graphDisplay; + this.allowEdgeSelection = allowEdgeSelection; } @Override @@ -54,13 +56,13 @@ public class JgtGraphMouse extends DefaultGraphMouse()); // add(new SelectingGraphMousePlugin<>()); add(new RegionSelectingGraphMousePlugin<>()); // the grab/pan feature - add(new TranslatingGraphMousePlugin(InputEvent.BUTTON1_DOWN_MASK)); + add(TranslatingGraphMousePlugin.builder().translatingMask(InputEvent.BUTTON1_DOWN_MASK).build()); // scaling add(new ScalingGraphMousePlugin()); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java index da8f9dab09..668777ea9d 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSatelliteGraphMouse.java @@ -39,19 +39,21 @@ public class JgtSatelliteGraphMouse // // JUNGRAPHT CHANGE 3 // + // disable single selection in satellite view by setting masks to 0 SelectingGraphMousePlugin mySelectingPlugin = - new JgtSelectingGraphMousePlugin(singleSelectionMask, addSingleSelectionMask); + new JgtSelectingGraphMousePlugin(0, 0); mySelectingPlugin.setLocked(true); selectingPlugin = mySelectingPlugin; regionSelectingPlugin = RegionSelectingGraphMousePlugin.builder() .regionSelectionMask(regionSelectionMask) - .addRegionSelectionMask(addRegionSelectionMask) + .toggleRegionSelectionMask(toggleRegionSelectionMask) .regionSelectionCompleteMask(regionSelectionCompleteMask) - .addRegionSelectionCompleteMask(addRegionSelectionCompleteMask) + .toggleRegionSelectionCompleteMask(toggleRegionSelectionCompleteMask) .build(); - translatingPlugin = new SatelliteTranslatingGraphMousePlugin(translatingMask); + translatingPlugin = SatelliteTranslatingGraphMousePlugin.builder() + .translatingMask(translatingMask).build(); add(selectingPlugin); add(regionSelectingPlugin); add(translatingPlugin); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java index e2f15d4917..680a2c0199 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/mouse/JgtSelectingGraphMousePlugin.java @@ -54,8 +54,10 @@ public class JgtSelectingGraphMousePlugin this.pickFootprintPaintable = dummyPickFootprintPaintable; } - public JgtSelectingGraphMousePlugin(int singleSelectionMask, int addSingleSelectionMask) { - super(singleSelectionMask, addSingleSelectionMask); + public JgtSelectingGraphMousePlugin(int singleSelectionMask, int toggleSingleSelectionMask) { + super(SelectingGraphMousePlugin.builder() + .singleSelectionMask(singleSelectionMask) + .toggleSingleSelectionMask(toggleSingleSelectionMask)); // // JUNGRAPHT CHANGE 1 @@ -89,7 +91,6 @@ public class JgtSelectingGraphMousePlugin selectedVertexState.clear(); } selectedVertexState.select(vertex); - deselectedVertex = null; } else { // If this vertex is still around in mouseReleased, it will be deselected @@ -99,9 +100,6 @@ public class JgtSelectingGraphMousePlugin // // JUNGRAPHT CHANGE 2 HERE // - if (addToSelection) { - deselectedVertex = vertex; - } } e.consume(); return true; diff --git a/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties b/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties index 707a0815ae..1adeb4b1d0 100644 --- a/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties +++ b/Ghidra/Features/GraphServices/src/main/resources/jungrapht.properties @@ -13,8 +13,8 @@ jungrapht.satelliteBackgroundTransparent=false jungrapht.satelliteLensColor= 0xFAFAFA jungrapht.pickedEdgeColor=0xFF0000 -jungrapht.edgeArrowLength=30 -jungrapht.edgeArrowWidth=20 +jungrapht.edgeArrowLength=50 +jungrapht.edgeArrowWidth=40 # default spacing for tree layouts jungrapht.treeLayoutHorizontalSpacing=2 @@ -34,7 +34,7 @@ jungrapht.lensStrokeWidth=10.0 # when scale is < .1, switch to lightweight rendering jungrapht.lightweightScaleThreshold=.1 # under 50 vertices will use heavyweight rendering all the time -jungrapht.lightweightCountThreshold=50 +jungrapht.lightweightCountThreshold=80 # default pixels spacings for vertices jungrapht.mincross.horizontalOffset=10 @@ -69,12 +69,12 @@ jungrapht.edgeSpatialSupport=RTREE # the mask for single vertex/edge selection jungrapht.singleSelectionMask=MB1 # the mask to augment the selection with a single vertex/edge -jungrapht.addSingleSelectionMask=MB1_MENU +jungrapht.toggleSingleSelectionMask=MB1_MENU # the mask to select vertices within a region jungrapht.regionSelectionMask=MB1_MENU # the mask to augment the selection with vertices in a region -jungrapht.addRegionSelectionMask=MB1_SHIFT_MENU +jungrapht.toggleRegionSelectionMask=MB1_SHIFT_MENU # the mask to indicate that the selection region is complete/closed and selection may commence jungrapht.regionSelectionCompleteMask=MENU # the mask to indicate that the selection region for augmentation is complete/closed and selection may commence -jungrapht.addRegionSelectionCompleteMask=SHIFT_MENU +jungrapht.toggleRegionSelectionCompleteMask=SHIFT_MENU diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java index 2d10d2f3eb..5d2d894236 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbApplicator.java @@ -15,9 +15,10 @@ */ package ghidra.app.util.pdb.pdbapplicator; -import java.math.BigInteger; import java.util.*; +import java.math.BigInteger; + import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.util.NamespaceUtils; import ghidra.app.util.SymbolPath; @@ -204,7 +205,7 @@ public class PdbApplicator { throw new PdbException("Invalid Restriction"); } - if (program == null) { + if (program != null) { Options options = program.getOptions(Program.PROGRAM_INFO); options.setBoolean(PdbParserConstants.PDB_LOADED, true); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java b/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java index b048f0cf42..87d7fa763b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ActionToGuiMapper.java @@ -15,7 +15,6 @@ */ package docking; -import java.awt.event.MouseEvent; import java.util.LinkedHashSet; import java.util.Set; @@ -134,7 +133,7 @@ public class ActionToGuiMapper { return menuGroupMap; } - public void showPopupMenu(ComponentPlaceholder componentInfo, MouseEvent e) { - popupActionManager.popupMenu(componentInfo, e); + public void showPopupMenu(ComponentPlaceholder componentInfo, PopupMenuContext popupContext) { + popupActionManager.popupMenu(componentInfo, popupContext); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java index 55538b0f9e..c0963c8883 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java @@ -67,17 +67,17 @@ public class DockableComponent extends JPanel implements ContainerListener { @Override public void mousePressed(MouseEvent e) { componentSelected((Component) e.getSource()); - processPopupMouseEvent(e); + showContextMenu(e); } @Override public void mouseReleased(MouseEvent e) { - processPopupMouseEvent(e); + showContextMenu(e); } @Override public void mouseClicked(MouseEvent e) { - processPopupMouseEvent(e); + showContextMenu(e); } }; @@ -146,24 +146,27 @@ public class DockableComponent extends JPanel implements ContainerListener { return focusedComponent; } - private void processPopupMouseEvent(final MouseEvent e) { + void showContextMenu(PopupMenuContext popupContext) { + actionMgr.showPopupMenu(placeholder, popupContext); + } + + private void showContextMenu(MouseEvent e) { Component component = e.getComponent(); if (component == null) { - return; + return; // not sure this can happen } // get the bounds to see if the clicked point is over the component - Rectangle bounds = component.getBounds(); // get bounds to get width and height - + Rectangle bounds = component.getBounds(); if (component instanceof JComponent) { ((JComponent) component).computeVisibleRect(bounds); } Point point = e.getPoint(); boolean withinBounds = bounds.contains(point); - if (e.isPopupTrigger() && withinBounds) { - actionMgr.showPopupMenu(placeholder, e); + PopupMenuContext popupContext = new PopupMenuContext(e); + actionMgr.showPopupMenu(placeholder, popupContext); } } @@ -476,17 +479,11 @@ public class DockableComponent extends JPanel implements ContainerListener { return null; } - /** - * @see java.awt.event.ContainerListener#componentAdded(java.awt.event.ContainerEvent) - */ @Override public void componentAdded(ContainerEvent e) { initializeComponents(e.getChild()); } - /** - * @see java.awt.event.ContainerListener#componentRemoved(java.awt.event.ContainerEvent) - */ @Override public void componentRemoved(ContainerEvent e) { deinitializeComponents(e.getChild()); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java index 5647b31906..3fd195d9cc 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingErrorDisplay.java @@ -18,6 +18,8 @@ package docking; import java.awt.Component; import java.awt.Window; +import org.apache.commons.text.WordUtils; + import docking.widgets.OkDialog; import docking.widgets.OptionDialog; import ghidra.util.*; @@ -26,11 +28,11 @@ import ghidra.util.exception.MultipleCauses; public class DockingErrorDisplay implements ErrorDisplay { /** - * Error dialog used to append exceptions. - * + * Error dialog used to append exceptions. + * *

    While this dialog is showing all new exceptions will be added to the dialog. When - * this dialog is closed, this reference will be cleared. - * + * this dialog is closed, this reference will be cleared. + * *

    Note: all use of this variable must be on the Swing thread to avoid thread * visibility issues. */ @@ -62,23 +64,34 @@ public class DockingErrorDisplay implements ErrorDisplay { Component parent, String title, Object message, Throwable throwable) { int dialogType = OptionDialog.PLAIN_MESSAGE; + String messageString = message != null ? message.toString() : null; - String rawMessage = HTMLUtilities.fromHTML(messageString); + if (messageString != null) { + // prevent excessive message degenerate cases + int maxChars = 1000; + String safeMessage = StringUtilities.trimMiddle(messageString, maxChars); + + // wrap any poorly formatted text that gets displayed in the label; 80-100 chars is + // a reasonable line length based on historical print margins + messageString = WordUtils.wrap(safeMessage, 100, null, true); + } + + String unformattedMessage = HTMLUtilities.fromHTML(messageString); switch (messageType) { case INFO: dialogType = OptionDialog.INFORMATION_MESSAGE; consoleDisplay.displayInfoMessage(errorLogger, originator, parent, title, - rawMessage); + unformattedMessage); break; case WARNING: case ALERT: dialogType = OptionDialog.WARNING_MESSAGE; consoleDisplay.displayWarningMessage(errorLogger, originator, parent, title, - rawMessage, throwable); + unformattedMessage, throwable); break; case ERROR: consoleDisplay.displayErrorMessage(errorLogger, originator, parent, title, - rawMessage, throwable); + unformattedMessage, throwable); dialogType = OptionDialog.ERROR_MESSAGE; break; } @@ -93,8 +106,8 @@ public class DockingErrorDisplay implements ErrorDisplay { return component; } - private void showDialog(final String title, final Throwable throwable, - final int dialogType, final String messageString, final Component parent) { + private void showDialog(final String title, final Throwable throwable, final int dialogType, + final String messageString, final Component parent) { Swing.runIfSwingOrRunLater(() -> { @@ -108,8 +121,8 @@ public class DockingErrorDisplay implements ErrorDisplay { }); } - private void showDialogOnSwing(String title, Throwable throwable, - int dialogType, String messageString, Component parent) { + private void showDialogOnSwing(String title, Throwable throwable, int dialogType, + String messageString, Component parent) { if (activeDialog != null) { activeDialog.addException(messageString, throwable); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 4b7d9b4476..b85ab9ec69 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -1765,8 +1765,11 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } if (bestParent == null) { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - bestParent = kfm.getActiveWindow(); + bestParent = getJavaActiveWindow(); + } + + if (bestParent != null && !bestParent.isShowing()) { + bestParent = null; // don't let non-showing windows be parents } return bestParent; @@ -1775,8 +1778,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder private static Window getBestNonModalParent(DialogComponentProvider newProvider, Window bestParent) { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window activeWindow = kfm.getActiveWindow(); + Window activeWindow = getJavaActiveWindow(); if (!(activeWindow instanceof DockingDialog)) { return bestParent; } @@ -1937,13 +1939,19 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder private static Window getJavaActiveWindow() { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - return kfm.getActiveWindow(); + Window activeWindow = kfm.getActiveWindow(); + if (activeWindow == null) { + return null; + } + if (!activeWindow.isShowing()) { + return null; // don't let non-showing windows be considered active + } + return activeWindow; } private static Window getActiveNonTransientWindow() { - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window bestWindow = kfm.getActiveWindow(); + Window bestWindow = getJavaActiveWindow(); if (bestWindow instanceof DockingDialog) { // We do not want Task Dialogs becoming parents, as they will get closed when the // task is finished, closing any other child dialogs, which means that dialogs such @@ -2172,6 +2180,34 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder objectUnderMouse = null; } + /** + * Shows a popup menu over the given component. If this given component is not part of the + * docking windows hierarchy, then no action is taken. + * + * @param component the component + */ + public static void showContextMenu(Component component) { + + DockingWindowManager dwm = getInstance(component); + if (dwm == null) { + return; + } + + DockableComponent dockableComponent = dwm.getDockableComponent(component); + if (dockableComponent == null) { + return; + } + + Rectangle bounds = dockableComponent.getBounds(); + + bounds.x = 0; + bounds.y = 0; + int x = (int) bounds.getCenterX(); + int y = (int) bounds.getCenterY(); + PopupMenuContext popupContext = new PopupMenuContext(dockableComponent, new Point(x, y)); + dockableComponent.showContextMenu(popupContext); + } + public void contextChanged(ComponentProvider provider) { if (provider == null) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java index 0f02fc7c40..3eaf3c950d 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogDialog.java @@ -43,7 +43,7 @@ import ghidra.util.table.column.GColumnRenderer; import utilities.util.reflection.ReflectionUtilities; /** - * A dialog that takes error text and displays it with an option details button. If there is + * A dialog that takes error text and displays it with an option details button. If there is * an {@link ErrorReporter}, then a button is provided to report the error. */ public class ErrLogDialog extends AbstractErrDialog { @@ -149,7 +149,8 @@ public class ErrLogDialog extends AbstractErrDialog { introPanel.add( new GIconLabel(UIManager.getIcon("OptionPane.errorIcon"), SwingConstants.RIGHT), BorderLayout.WEST); - introPanel.add(new GHtmlLabel(HTMLUtilities.toHTML(message)) { + String html = HTMLUtilities.toHTML(message); + introPanel.add(new GHtmlLabel(html) { @Override public Dimension getPreferredSize() { // rendering HTML the label can expand larger than the screen; keep it reasonable @@ -387,6 +388,16 @@ public class ErrLogDialog extends AbstractErrDialog { textDetails.scrollToBottom(); } + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + + // Cap preferred width to something reasonable; most displays have more than 1000 width. + // Users can still resize as desired + size.width = Math.min(size.width, 1000); + return size; + } + void setError(ErrorEntry e) { error = e; setExceptionMessage(e.getDetailsText()); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java b/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java index af93a7677a..5a712f2b76 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/PopupActionManager.java @@ -16,6 +16,7 @@ package docking; import java.awt.Component; +import java.awt.Point; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -67,28 +68,27 @@ public class PopupActionManager implements PropertyChangeListener { } } - void popupMenu(ComponentPlaceholder info, MouseEvent e) { + void popupMenu(ComponentPlaceholder placeholder, PopupMenuContext popupContext) { - if (e.isConsumed()) { - return; - } - ComponentProvider popupProvider = info.getProvider(); - ActionContext actionContext = popupProvider.getActionContext(e); + MouseEvent event = popupContext.getEvent(); + ComponentProvider popupProvider = placeholder.getProvider(); + ActionContext actionContext = popupProvider.getActionContext(event); if (actionContext == null) { actionContext = new ActionContext(); } - actionContext.setSourceObject(e.getSource()); - actionContext.setMouseEvent(e); + actionContext.setSourceObject(popupContext.getSource()); + actionContext.setMouseEvent(event); - Iterator localActions = info.getActions(); + Iterator localActions = placeholder.getActions(); JPopupMenu popupMenu = createPopupMenu(localActions, actionContext); if (popupMenu == null) { return; // no matching actions } - Component c = (Component) e.getSource(); - popupMenu.show(c, e.getX(), e.getY()); + Component c = popupContext.getComponent(); + Point p = popupContext.getPoint(); + popupMenu.show(c, p.x, p.y); } protected JPopupMenu createPopupMenu(Iterator localActions, diff --git a/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java b/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java new file mode 100644 index 0000000000..16c87cbd7f --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java @@ -0,0 +1,61 @@ +/* ### + * 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; + +import java.awt.Component; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.util.Objects; + +/** + * A class that holds information used to show a popup menu + */ +public class PopupMenuContext { + + private Component component; + private MouseEvent event; + private Point point; + + PopupMenuContext(MouseEvent event) { + this.event = event; + this.component = Objects.requireNonNull(event.getComponent()); + this.point = event.getPoint(); + } + + PopupMenuContext(Component component, Point point) { + this.component = Objects.requireNonNull(component); + this.point = point; + } + + public MouseEvent getEvent() { + return event; + } + + public Component getComponent() { + return component; + } + + public Point getPoint() { + return new Point(point); + } + + public Object getSource() { + if (event != null) { + return event.getSource(); + } + return component; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java index f29071f815..e433c7705a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java @@ -17,8 +17,7 @@ package docking.action; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import javax.swing.Action; import javax.swing.KeyStroke; @@ -61,6 +60,7 @@ public class KeyBindingsManager implements PropertyChangeListener { public void addReservedAction(DockingActionIf action) { KeyStroke keyBinding = action.getKeyBinding(); + Objects.requireNonNull(keyBinding); addReservedKeyBinding(action, keyBinding); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java new file mode 100644 index 0000000000..469e521057 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowContextMenuAction.java @@ -0,0 +1,52 @@ +/* ### + * 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.action; + +import java.awt.*; + +import javax.swing.KeyStroke; + +import docking.ActionContext; +import docking.DockingWindowManager; + +/** + * An action to trigger a context menu over the focus owner. This allows context menus to be + * triggered from the keyboard. + */ +public class ShowContextMenuAction extends DockingAction { + + public ShowContextMenuAction(KeyStroke keyStroke) { + super("Show Context Menu", DockingWindowManager.DOCKING_WINDOWS_OWNER); + setKeyBindingData(new KeyBindingData(keyStroke)); + } + + @Override + public void actionPerformed(ActionContext context) { + + KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + Window window = kfm.getActiveWindow(); + if (window == null) { + return; + } + + // use the focused component to determine what should get the context menu + Component focusOwner = kfm.getFocusOwner(); + if (focusOwner != null) { + DockingWindowManager.showContextMenu(focusOwner); + } + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java index 592d545f81..bec2cc41cb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java @@ -91,6 +91,10 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener { keyBindingsManager.addReservedAction(new HelpAction(false, ReservedKeyBindings.HELP_KEY2)); keyBindingsManager.addReservedAction( new HelpAction(true, ReservedKeyBindings.HELP_INFO_KEY)); + keyBindingsManager.addReservedAction( + new ShowContextMenuAction(ReservedKeyBindings.CONTEXT_MENU_KEY1)); + keyBindingsManager.addReservedAction( + new ShowContextMenuAction(ReservedKeyBindings.CONTEXT_MENU_KEY2)); // these are diagnostic if (SystemUtilities.isInDevelopmentMode()) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java index 6cfc44548b..11b8ed0883 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingCheckboxMenuItemUI.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -26,9 +25,8 @@ import javax.swing.plaf.MenuItemUI; public class DockingCheckboxMenuItemUI extends DockingMenuItemUI { public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingCheckboxMenuItemUI result = new DockingCheckboxMenuItemUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java index e03acac259..c692839a0b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuItemUI.java @@ -58,9 +58,8 @@ public class DockingMenuItemUI extends MenuItemUI { protected MenuItemUI ui; public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingMenuItemUI result = new DockingMenuItemUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java index 8b61ac3cb4..d53eacd34b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingMenuUI.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -22,9 +21,8 @@ import javax.swing.plaf.MenuItemUI; public class DockingMenuUI extends DockingMenuItemUI { public static ComponentUI createUI(JComponent c) { - LookAndFeel underlying = UIManager.getLookAndFeel(); DockingMenuUI result = new DockingMenuUI(); - result.ui = (MenuItemUI) underlying.getDefaults().getUI(c); + result.ui = (MenuItemUI) UIManager.getDefaults().getUI(c); return result; } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java index 775c4f8407..a732c3e492 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java @@ -2017,7 +2017,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { // ThreadedTableModelUpdateMgr Object updateManager = getInstanceField("updateManager", model); SwingUpdateManager sum = - (SwingUpdateManager) getInstanceField("updateManager", updateManager); + (SwingUpdateManager) getInstanceField("addRemoveUpdater", updateManager); Worker worker = (Worker) getInstanceField("worker", model); String workerState = worker == null ? "" : Boolean.toString(worker.isBusy()); return "Table model busy state - Swing Update Manager? " + sum.isBusy() + "; worker?" + diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java index 8d8ba4e8aa..3132cce3bf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/tasks/GTreeStartEditingTask.java @@ -60,16 +60,15 @@ public class GTreeStartEditingTask extends GTreeTask { private void edit() { + if (tree.isFiltered()) { + Msg.showWarn(getClass(), tree, "Cannot Edit Tree Node", + "Can't edit tree node \"" + childName + "\" while tree is filtered."); + return; + } + GTreeNode editNode = parent.getChild(childName); if (editNode == null) { - if (tree.isFiltered()) { - Msg.showWarn(getClass(), tree, "Cannot Edit Tree Node", - "Can't edit tree node \"" + childName + "\" while tree is filtered."); - } - else { - Msg.debug(this, - "Can't find node \"" + childName + "\" to edit."); - } + Msg.debug(this, "Can't find node \"" + childName + "\" to edit."); return; } diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java index 1d9ef7bb95..4e49418168 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/DockingWindowsLookAndFeelUtils.java @@ -204,7 +204,7 @@ public class DockingWindowsLookAndFeelUtils { case NIMBUS_LOOK_AND_FEEL: // fix scroll bar grabber disappearing. See https://bugs.openjdk.java.net/browse/JDK-8134828 // This fix looks like it should not cause harm even if the bug is fixed on the jdk side. - UIDefaults defaults = lookAndFeel.getDefaults(); + UIDefaults defaults = UIManager.getDefaults(); defaults.put("ScrollBar.minimumThumbSize", new Dimension(30, 30)); // (see NimbusDefaults for key values that can be changed here) @@ -277,8 +277,7 @@ public class DockingWindowsLookAndFeelUtils { /** Allows you to globally set the font size (don't use this method!) */ private static void setGlobalFontSizeOverride(int fontSize) { - LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); - UIDefaults defaults = lookAndFeel.getDefaults(); + UIDefaults defaults = UIManager.getDefaults(); Set> set = defaults.entrySet(); Iterator> iterator = set.iterator(); diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java b/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java index c081d5ff99..025c116c48 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/util/ReservedKeyBindings.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -34,6 +33,11 @@ public class ReservedKeyBindings { public static final KeyStroke HELP_INFO_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_F1, DockingUtils.CONTROL_KEY_MODIFIER_MASK); + public static final KeyStroke CONTEXT_MENU_KEY1 = + KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_DOWN_MASK); + public static final KeyStroke CONTEXT_MENU_KEY2 = + KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0); + public static final KeyStroke FOCUS_INFO_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_F2, DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); @@ -50,7 +54,8 @@ public class ReservedKeyBindings { code == KeyEvent.VK_CAPS_LOCK || code == KeyEvent.VK_TAB || HELP_KEY1.equals(keyStroke) || HELP_KEY2.equals(keyStroke) || HELP_INFO_KEY.equals(keyStroke) || UPDATE_KEY_BINDINGS_KEY.equals(keyStroke) || - FOCUS_INFO_KEY.equals(keyStroke) || FOCUS_CYCLE_INFO_KEY.equals(keyStroke)) { + FOCUS_INFO_KEY.equals(keyStroke) || FOCUS_CYCLE_INFO_KEY.equals(keyStroke) || + CONTEXT_MENU_KEY1.equals(keyStroke) || CONTEXT_MENU_KEY2.equals(keyStroke)) { return true; } diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java index e18ec1a446..7fa2a23752 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java @@ -92,9 +92,9 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Constructor - * + * * @param includeTextField if true, the dialog can display a status progressMessage with progress details - * @param includeCancelButton if true, a cancel button will be displayed + * @param includeCancelButton if true, a cancel button will be displayed */ public TaskMonitorComponent(boolean includeTextField, boolean includeCancelButton) { updateProgressPanelRunnable = () -> updateProgressPanel(); @@ -106,7 +106,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { shouldCancelRunnable = () -> { int currentTaskID = taskID.get(); - boolean userSaysYes = OptionDialog.showYesNoDialog(TaskMonitorComponent.this, "Cancel?", + boolean userSaysYes = OptionDialog.showYesNoDialog(null, "Cancel?", "Do you really want to cancel " + getTaskName() + "?") == OptionDialog.OPTION_ONE; if (userSaysYes && currentTaskID == taskID.get()) { @@ -206,7 +206,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { // a chance to do so. In other words, the background thread will end up // blocking instead of working, which defeats our attempts to never show // a task dialog for fast background tasks. - // + // isIndeterminate.set(indeterminate); Swing.runIfSwingOrRunLater(() -> { boolean newValue = isIndeterminate.get(); @@ -269,7 +269,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Returns true if {@link #setIndeterminate(boolean)} with a value of true has * been called. - * + * * @return true if {@link #setIndeterminate(boolean)} with a value of true has * been called. */ @@ -280,7 +280,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set whether the progress bar should be visible - * + * * @param show true if the progress bar should be visible */ public synchronized void showProgress(boolean show) { @@ -293,7 +293,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set the name of the task; the name shows up in the tool tip for * the cancel button. - * + * * @param name the name of the task */ public void setTaskName(String name) { @@ -303,7 +303,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Set the visibility of the cancel button - * + * * @param visible if true, show the cancel button; false otherwise */ public void setCancelButtonVisibility(boolean visible) { @@ -325,7 +325,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { /** * Sets the visibility of the progress icon - * + * * @param visible if true, display the progress icon */ public void showProgressIcon(boolean visible) { diff --git a/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java b/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java index c3ef15bca8..0dbdf2655b 100644 --- a/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java +++ b/Ghidra/Framework/Docking/src/test.slow/java/docking/framework/SplashScreenTest.java @@ -30,71 +30,43 @@ import docking.*; import docking.test.AbstractDockingTest; import docking.widgets.PasswordDialog; import generic.test.category.NightlyCategory; -import ghidra.util.Msg; // The splash screen is sensitive to windows being activated/deactivated, so don't run // when other test windows may be open @Category(NightlyCategory.class) public class SplashScreenTest extends AbstractDockingTest { - private AboutDialog aboutDialog; - @After public void tearDown() { - Msg.debug(this, "tearDown() - open windows before closing"); - printOpenWindows(); - runSwing(() -> SplashScreen.disposeSplashScreen()); - - closeAllWindows(); - printOpenWindows(); - - Msg.debug(this, "tearDown() - open windows after closing"); + disposeAllWindows(); } - @Test - public void testShowInfoWindow() throws Exception { - // no parent - showModalInfoWindow(null); - - ensureInfoWindowVisible(); - hideInfoWindow(); - - // not visible parent - JFrame parentFrame = new JFrame("InfoWindowTest.testShowInfoWindow Frame"); - parentFrame.setBounds(-100, -100, 0, 0); - showModalInfoWindow(parentFrame); - - ensureInfoWindowVisible(); - hideInfoWindow(); - - // visible parent - parentFrame.setVisible(true); - showModalInfoWindow(parentFrame); - - ensureInfoWindowVisible(); - hideInfoWindow(); + private void disposeAllWindows() { + for (Window window : getAllWindows()) { + runSwing(window::dispose); + } } @Test public void testShowAndHideSplashScreen() { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); showSplashScreen(false); - ensureSpashScreenVisible(false); + assertSpashScreenVisible(false); showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); showSplashScreen(false); - ensureSpashScreenVisible(false); + assertSpashScreenVisible(false); } @Test public void testUpdateSplashScreenStatus() { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); JLabel statusLabel = (JLabel) getInstanceField("statusLabel", SplashScreen.class); @@ -120,24 +92,24 @@ public class SplashScreenTest extends AbstractDockingTest { public void testSplashScreenPasswordModality_SharedParent() throws Exception { showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); // show a modal dialog with no parent (this will use the Splash Screen's parent) showModalPasswordDialog(null); // When the splash screen and the dialog share a parent, then the dialog should NOT // cause the splash screen to go away - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); } @Test public void testSplashScreenPasswordModality_UnsharedParent() throws Exception { // show the splash screen showSplashScreen(true); - ensureSpashScreenVisible(true); + assertSpashScreenVisible(true); DockingFrame frame = new DockingFrame("Modal Parent Frame"); - frame.setVisible(true); + show(frame); showModalPasswordDialog(frame); ensureSplashScreenWillClose(); @@ -147,6 +119,10 @@ public class SplashScreenTest extends AbstractDockingTest { // Private Methods //================================================================================================== + private void show(JFrame frame) { + runSwing(() -> frame.setVisible(true)); + } + private void ensureSplashScreenWillClose() { waitForCondition(() -> { SplashScreen splash = getSplash(); @@ -155,42 +131,44 @@ public class SplashScreenTest extends AbstractDockingTest { } private DockingDialog showModalPasswordDialog(Frame parentFrame) throws Exception { + String dialogTitle = "InfoWindowTest.testSplashScreenPasswordModality() Dialog"; DialogComponentProvider passwordDialog = runSwing(() -> new PasswordDialog(dialogTitle, "Server Type", "Server Name", "Prompt", null, null)); + if (parentFrame == null) { + // null means to share the parent + Object splashParent = getInstanceField("hiddenFrame", SplashScreen.class); + parentFrame = (Frame) splashParent; + } + + Frame finalParent = parentFrame; executeOnSwingWithoutBlocking( - () -> DockingWindowManager.showDialog(parentFrame, passwordDialog)); + () -> { + DockingDialog dialog = + DockingDialog.createDialog(finalParent, passwordDialog, finalParent); + dialog.setVisible(true); + }); JDialog dialog = waitForJDialog(dialogTitle); assertNotNull(dialog); - Window dialogWindow = SwingUtilities.windowForComponent(dialog); - Msg.debug(this, "Created modal dialog with parent: " + getTitleForWindow(dialogWindow) + - " - id: " + System.identityHashCode(dialogWindow)); - return (DockingDialog) dialog; } - // handles showing the modal info window, which must be done from a thread outside of the - // test thread - private void showModalInfoWindow(final JFrame parentFrame) { - // create a thread to show the modal dialog so that the current thread doesn't block - aboutDialog = runSwing(() -> new AboutDialog()); - executeOnSwingWithoutBlocking(() -> DockingWindowManager.showDialog(null, aboutDialog)); - } - private void showSplashScreen(final boolean makeVisible) { if (makeVisible) { SplashScreen splash = runSwing(() -> SplashScreen.showSplashScreen()); assertNotNull("Failed showing splash screen", splash); + waitForSwing(); return; } SplashScreen.disposeSplashScreen(); + waitForSwing(); } - private void ensureSpashScreenVisible(boolean visible) { + private void assertSpashScreenVisible(boolean visible) { // get the 'splashWindow' and make sure that it is not null and that it is visible SplashScreen splashScreen = getSplash(); @@ -206,23 +184,6 @@ public class SplashScreenTest extends AbstractDockingTest { // timing issue debug waitForCondition(() -> splashScreen.isVisible()); - - if (!splashScreen.isVisible()) { - - // this can happen if other OS windows trigger the splash window to be hidden - printOpenWindows(); - fail("The splash screen is not visible when expected to be so - " + splashScreen); - } - } - - private void ensureInfoWindowVisible() { - // get the 'infoDialog' and make sure that it is not null and that it is visible - assertTrue("The info dialog is not visible after it was supposed to " + "have been shown.", - aboutDialog.isVisible()); - } - - private void hideInfoWindow() throws Exception { - runSwing(() -> aboutDialog.close()); } private SplashScreen getSplash() { diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java index 50445c0f64..1a004061c8 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/popup/PopupRegulator.java @@ -15,6 +15,7 @@ */ package ghidra.graph.viewer.popup; +import java.awt.Component; import java.awt.Window; import java.awt.event.*; @@ -129,6 +130,13 @@ public class PopupRegulator { return; } + Component c = event.getComponent(); + if (!c.isShowing()) { + // This method is called from a a timer. It is possible that the graph has been + // closed by the time this method is called. + return; + } + ToolTipInfo toolTipInfo = popupSource.getToolTipInfo(event); JComponent toolTipComponent = toolTipInfo.getToolTipComponent(); boolean isCustomJavaTooltip = !(toolTipComponent instanceof JToolTip); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java index 11e248eec2..da39b07af5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeFactory.java @@ -61,7 +61,7 @@ public interface PcodeFactory { public HighSymbol getSymbol(long symbolId); public Varnode setInput(Varnode vn,boolean val); public void setAddrTied(Varnode vn,boolean val); - public void setPersistant(Varnode vn,boolean val); + public void setPersistent(Varnode vn, boolean val); public void setUnaffected(Varnode vn,boolean val); public void setMergeGroup(Varnode vn,short val); public void setDataType(Varnode vn,DataType type); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java index 48cd3429a6..4e1002e758 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeSyntaxTree.java @@ -392,9 +392,9 @@ public class PcodeSyntaxTree implements PcodeFactory { } @Override - public void setPersistant(Varnode vn, boolean val) { + public void setPersistent(Varnode vn, boolean val) { VarnodeAST vnast = (VarnodeAST) vn; - vnast.setPersistant(val); + vnast.setPersistent(val); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java index 58a175c7a9..4e6f867f4b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java @@ -255,9 +255,9 @@ public class Varnode { } /** - * @return is persistant + * @return is persistent */ - public boolean isPersistant() { + public boolean isPersistent() { return false; // Not a valid query with a free varnode } @@ -476,7 +476,7 @@ public class Varnode { } attrstring = el.getAttribute("persists"); if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { - factory.setPersistant(vn, true); + factory.setPersistent(vn, true); } attrstring = el.getAttribute("addrtied"); if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java index 8a837809e4..a3c3241b6a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java @@ -37,7 +37,7 @@ public class VarnodeAST extends Varnode { private boolean bInput; private boolean bAddrTied; - private boolean bPersistant; + private boolean bPersistent; private boolean bUnaffected; private boolean bFree; private int uniqId; // Unique Id for distinguishing otherwise identical varnodes @@ -50,7 +50,7 @@ public class VarnodeAST extends Varnode { super(a, sz); bInput = false; bAddrTied = false; - bPersistant = false; + bPersistent = false; bUnaffected = false; bFree = true; uniqId = id; @@ -70,8 +70,8 @@ public class VarnodeAST extends Varnode { } @Override - public boolean isPersistant() { - return bPersistant; + public boolean isPersistent() { + return bPersistent; } @Override @@ -132,8 +132,8 @@ public class VarnodeAST extends Varnode { def = null; } - public void setPersistant(boolean val) { - bPersistant = val; + public void setPersistent(boolean val) { + bPersistent = val; } public void setUnaffected(boolean val) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java index 696671614e..0f1358f53f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java @@ -34,6 +34,52 @@ public interface GraphDisplay { public static final int ALIGN_CENTER = 1; // aligns graph text to the center public static final int ALIGN_RIGHT = 2; // aligns graph text to the right + /** + * values are color names or rgb in hex '0xFF0000' is red + */ + String SELECTED_VERTEX_COLOR = "selectedVertexColor"; + /** + * values are color names or rgb in hex '0xFF0000' is red + */ + String SELECTED_EDGE_COLOR = "selectedEdgeColor"; + /** + * values are defined as String symbols in LayoutFunction class + * + * KAMADA_KAWAI,FRUCTERMAN_REINGOLD,CIRCLE_MINCROSS,TIDIER_TREE,TIDIER_RADIAL_TREE, + * MIN_CROSS_TOP_DOWN,MIN_CROSS_LONGEST_PATH,MIN_CROSS_NETWORK_SIMPLEX,MIN_CROSS_COFFMAN_GRAHAM, + * EXP_MIN_CROSS_TOP_DOWN,EXP_MIN_CROSS_LONGEST_PATH,EXP_MIN_CROSS_NETWORK_SIMPLEX, + * EXP_MIN_CROSS_COFFMAN_GRAHAM,TREE,RADIAL,BALLOON,GEM + * + * may have no meaning for a different graph visualization library + */ + String INITIAL_LAYOUT_ALGORITHM = "initialLayoutAlgorithm"; + /** + * true or false + * may have no meaning for a different graph visualization library + */ + String DISPLAY_VERTICES_AS_ICONS = "displayVerticesAsIcons"; + /** + * values are the strings N,NE,E,SE,S,SW,W,NW,AUTO,CNTR + * may have no meaning for a different graph visualization library + */ + String VERTEX_LABEL_POSITION = "vertexLabelPosition"; + /** + * true or false, whether edge selection via a mouse click is enabled. + * May not be supported by another graph visualization library + */ + String ENABLE_EDGE_SELECTION = "enableEdgeSelection"; + /** + * a comma-separated list of edge type names in priority order + */ + String EDGE_TYPE_PRIORITY_LIST = "edgeTypePriorityList"; + /** + * a comma-separated list of edge type names. + * any will be considered a favored edge for the min-cross layout + * algorithms. + * May have no meaning with a different graph visualization library + */ + String FAVORED_EDGES = "favoredEdges"; + /** * Sets a {@link GraphDisplayListener} to be notified when the user changes the vertex focus * or selects one or more nodes in a graph window diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml index 21b6add2a1..5c9a401995 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/category.xml @@ -1,7 +1,7 @@ - - + + - + diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml index 65831c9255..16ffc71a33 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF index fffdce6b63..7760ce9751 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh.ide Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh.ide Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh.ide; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: ghidra.xtext.sleigh, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF index 94627e204e..d050e0d5b7 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Require-Bundle: ghidra.xtext.sleigh.ui, org.eclipse.xtext.junit4, org.eclipse.xtext.xbase.junit, org.eclipse.core.runtime, - org.eclipse.ui.workbench;resolution:=optional + org.eclipse.ui.workbench;resolution:=optional, + org.eclipse.xtext.ui.testing Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: ghidra.xtext.sleigh.ui.tests;x-internal=true diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF index 075e0e71af..7d5b41fd0d 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh.ui Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh.ui Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh.ui; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: ghidra.xtext.sleigh, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF index c982b203b5..4fa4632222 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: ghidra.xtext.sleigh Bundle-ManifestVersion: 2 Bundle-Name: ghidra.xtext.sleigh Bundle-Vendor: Ghidra -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.0.1.qualifier Bundle-SymbolicName: ghidra.xtext.sleigh; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.eclipse.xtext, diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml index 26c699fb0e..242ae876f4 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/plugin.xml @@ -1,7 +1,11 @@ - + + + up to the size of output. If the size of -output is smaller than the size of input0 plus the constant input1, +output is smaller than the size of input0 minus the constant input1, then the additional most significant bytes of input0 will also be truncated.

    From 511ab0b1329773a3cb3398376f4ecb0b3fe9cd4d Mon Sep 17 00:00:00 2001 From: Florian Magin Date: Thu, 11 Mar 2021 16:12:05 +0100 Subject: [PATCH 080/140] Fix INSx.REP instruction Co-authored-by: Sam Lerner --- Ghidra/Processors/x86/data/languages/ia.sinc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 89c390ff40..8995203399 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -2732,10 +2732,10 @@ enterFrames: low5 is low5 { tmp:1 = low5; export tmp; } :INC Rmr32 is vexMode=0 & opsize=1 & row = 4 & page = 0 & Rmr32 { OF = scarry(Rmr32,1); Rmr32 = Rmr32 + 1; resultflags( Rmr32); } @endif -:INSB^rep^reptail eseDI1,DX is vexMode=0 & rep & reptail & byte=0x6c & eseDI1 & DX { eseDI1 = in(DX); } -:INSW^rep^reptail eseDI2,DX is vexMode=0 & rep & reptail & opsize=0 & byte=0x6d & eseDI2 & DX { eseDI2 = in(DX); } -:INSD^rep^reptail eseDI4,DX is vexMode=0 & rep & reptail & opsize=1 & byte=0x6d & eseDI4 & DX { eseDI4 = in(DX); } -:INSD^rep^reptail eseDI4,DX is vexMode=0 & rep & reptail & opsize=2 & byte=0x6d & eseDI4 & DX { eseDI4 = in(DX); } +:INSB^rep^reptail eseDI1,DX is vexMode=0 & rep & reptail & byte=0x6c & eseDI1 & DX { build rep; build eseDI1; eseDI1 = in(DX); build reptail; } +:INSW^rep^reptail eseDI2,DX is vexMode=0 & rep & reptail & opsize=0 & byte=0x6d & eseDI2 & DX { build rep; build eseDI2; eseDI2 = in(DX); build reptail; } +:INSD^rep^reptail eseDI4,DX is vexMode=0 & rep & reptail & opsize=1 & byte=0x6d & eseDI4 & DX { build rep; build eseDI4; eseDI4 = in(DX); build reptail; } +:INSD^rep^reptail eseDI4,DX is vexMode=0 & rep & reptail & opsize=2 & byte=0x6d & eseDI4 & DX { build rep; build eseDI4; eseDI4 = in(DX); build reptail; } :INT1 is vexMode=0 & byte=0xf1 { tmp:1 = 0x1; intloc:$(SIZE) = swi(tmp); call [intloc]; return [0:1]; } :INT3 is vexMode=0 & byte=0xcc { tmp:1 = 0x3; intloc:$(SIZE) = swi(tmp); call [intloc]; return [0:1]; } @@ -3208,9 +3208,9 @@ define pcodeop swap_bytes; :OUT DX,AX is vexMode=0 & opsize=0 & byte=0xef & DX & AX { out(DX,AX); } :OUT DX,EAX is vexMode=0 & byte=0xef & DX & EAX { out(DX,EAX); } -:OUTSB^rep^reptail DX,dseSI1 is vexMode=0 & rep & reptail & byte=0x6e & DX & dseSI1 { out(dseSI1,DX); } -:OUTSW^rep^reptail DX,dseSI2 is vexMode=0 & rep & reptail & opsize=0 & byte=0x6f & DX & dseSI2 { out(dseSI2,DX); } -:OUTSD^rep^reptail DX,dseSI4 is vexMode=0 & rep & reptail & byte=0x6f & DX & dseSI4 { out(dseSI4,DX); } +:OUTSB^rep^reptail DX,dseSI1 is vexMode=0 & rep & reptail & byte=0x6e & DX & dseSI1 { build rep; build dseSI1; out(dseSI1,DX); build reptail;} +:OUTSW^rep^reptail DX,dseSI2 is vexMode=0 & rep & reptail & opsize=0 & byte=0x6f & DX & dseSI2 { build rep; build dseSI2; out(dseSI2,DX); build reptail;} +:OUTSD^rep^reptail DX,dseSI4 is vexMode=0 & rep & reptail & byte=0x6f & DX & dseSI4 { build rep; build dseSI4; out(dseSI4,DX); build reptail;} :PAUSE is vexMode=0 & opsize=0 & $(PRE_F3) & byte=0x90 { } :PAUSE is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x90 { } From ecb46d0acd1de4e57dce7fbb5b45aed8ac2d1739 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Thu, 11 Mar 2021 13:01:02 -0500 Subject: [PATCH 081/140] GP-765: Fixing bad datatype for PE Delay Load imports --- .../ghidra/app/util/bin/StructConverter.java | 4 ++++ .../format/pe/DelayImportDataDirectory.java | 22 +++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/StructConverter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/StructConverter.java index b58676d8a0..23259ebcfe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/StructConverter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/StructConverter.java @@ -71,6 +71,10 @@ public interface StructConverter { * Reusable 32-bit image base offset datatype. */ public final static DataType IBO32 = new ImageBaseOffset32DataType(); + /** + * Reusable 64-bit image base offset datatype. + */ + public final static DataType IBO64 = new ImageBaseOffset64DataType(); /** * Returns a structure datatype representing the diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/DelayImportDataDirectory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/DelayImportDataDirectory.java index 24c8a3d42a..376604e513 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/DelayImportDataDirectory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/DelayImportDataDirectory.java @@ -136,13 +136,13 @@ public class DelayImportDataDirectory extends DataDirectory { createSymbol(program, tmpAddr, SymbolUtilities.getAddressAppendedName( DelayImportDescriptor.NAME + "_IAT", tmpAddr)); markupThunk(program, isBinary, space, descriptor, descriptor.getAddressOfIAT(), - descriptor.getThunksIAT(), monitor, log); + descriptor.getThunksIAT(), true, monitor, log); tmpAddr = addr(space, isBinary, descriptor, descriptor.getAddressOfINT()); createSymbol(program, tmpAddr, SymbolUtilities.getAddressAppendedName( DelayImportDescriptor.NAME + "_INT", tmpAddr)); markupThunk(program, isBinary, space, descriptor, descriptor.getAddressOfINT(), - descriptor.getThunksINT(), monitor, log); + descriptor.getThunksINT(), false, monitor, log); // This table is optional if (descriptor.getAddressOfBoundIAT() != 0) { @@ -150,7 +150,7 @@ public class DelayImportDataDirectory extends DataDirectory { createSymbol(program, tmpAddr, SymbolUtilities.getAddressAppendedName( DelayImportDescriptor.NAME + "_Bound_IAT", tmpAddr)); markupThunk(program, isBinary, space, descriptor, descriptor.getAddressOfBoundIAT(), - descriptor.getThunksBoundIAT(), monitor, log); + descriptor.getThunksBoundIAT(), false, monitor, log); } // This table is optional @@ -159,8 +159,8 @@ public class DelayImportDataDirectory extends DataDirectory { createSymbol(program, tmpAddr, SymbolUtilities.getAddressAppendedName( DelayImportDescriptor.NAME + "_Unload_IAT", tmpAddr)); markupThunk(program, isBinary, space, descriptor, - descriptor.getAddressOfOriginalIAT(), descriptor.getThunksUnloadIAT(), monitor, - log); + descriptor.getAddressOfOriginalIAT(), descriptor.getThunksUnloadIAT(), false, + monitor, log); } @@ -224,9 +224,11 @@ public class DelayImportDataDirectory extends DataDirectory { DelayImportDescriptor descriptor, long ptr, List thunks, + boolean isIAT, TaskMonitor monitor, MessageLog log) { + boolean is64bit = ntHeader.getOptionalHeader().is64bit(); long thunkPtr = va(ptr, isBinary); if (!descriptor.isUsingRVA()) { thunkPtr -= ntHeader.getOptionalHeader().getImageBase(); @@ -237,12 +239,14 @@ public class DelayImportDataDirectory extends DataDirectory { return; } DataType dt; - if (thunk.getAddressOfData() == 0) { - dt = ntHeader.getOptionalHeader().is64bit() ? QWORD : DWORD; + if (thunk.isOrdinal() || thunk.getAddressOfData() == 0) { + dt = is64bit ? QWORD : DWORD; + } + else if (isIAT) { + dt = is64bit ? Pointer64DataType.dataType : Pointer32DataType.dataType; } else { - dt = ntHeader.getOptionalHeader().is64bit() ? Pointer64DataType.dataType - : Pointer32DataType.dataType; + dt = is64bit ? IBO64 : IBO32; } Address thunkAddress = space.getAddress(thunkPtr); From 470ef71ba8f18ece2828f1489badcdb1a8c81e07 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 11 Mar 2021 14:47:57 -0500 Subject: [PATCH 082/140] Improve ApplicationLayout use for standalone apps --- .../framework/DockingApplicationLayout.java | 55 ++++++++----- .../plugintool/StandAloneApplication.java | 80 +++++++++++-------- 2 files changed, 80 insertions(+), 55 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java index 7e0975539c..21758d2c8c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java @@ -16,12 +16,12 @@ package docking.framework; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Objects; +import java.util.*; import generic.jar.ResourceFile; import ghidra.framework.ApplicationProperties; import ghidra.util.SystemUtilities; +import util.CollectionUtils; import utility.application.ApplicationLayout; import utility.application.ApplicationUtilities; import utility.module.ModuleUtilities; @@ -34,16 +34,6 @@ public class DockingApplicationLayout extends ApplicationLayout { private static final String NO_RELEASE_NAME = "NO_RELEASE"; - /** - * Constructs a new docking application layout object with the given name. - * - * @param name The name of the application. - * @throws FileNotFoundException if there was a problem getting a user directory. - */ - public DockingApplicationLayout(String name) throws FileNotFoundException { - this(name, "0.1"); - } - /** * Constructs a new docking application layout object with the given name and version. * @@ -57,24 +47,31 @@ public class DockingApplicationLayout extends ApplicationLayout { /** * Constructs a new docking application layout object with the given set of application - * properties. + * properties. The default Ghidra application root directory(s) will be used. * * @param applicationProperties The properties object that will be read system properties. * @throws FileNotFoundException if there was a problem getting a user directory. */ public DockingApplicationLayout(ApplicationProperties applicationProperties) throws FileNotFoundException { + this(getDefaultApplicationRootDirs(), applicationProperties); + } + + /** + * Constructs a new docking application layout object with the given set of application + * properties. + * + * @param applicationRootDirs list of application root directories which should be + * used to idenitfy modules and resources. The first entry will be treated as the + * installation root. + * @param applicationProperties The properties object that will be read system properties. + * @throws FileNotFoundException if there was a problem getting a user directory. + */ + public DockingApplicationLayout(Collection applicationRootDirs, + ApplicationProperties applicationProperties) throws FileNotFoundException { this.applicationProperties = Objects.requireNonNull(applicationProperties); - - // Application root directories - if (SystemUtilities.isInDevelopmentMode()) { - applicationRootDirs = ApplicationUtilities.findDefaultApplicationRootDirs(); - } - else { - applicationRootDirs = new ArrayList<>(); - applicationRootDirs.add(new ResourceFile(System.getProperty("user.dir"))); - } + this.applicationRootDirs = applicationRootDirs; // Application installation directory applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile(); @@ -97,4 +94,18 @@ public class DockingApplicationLayout extends ApplicationLayout { applicationInstallationDir); } + /** + * Get the default list of Application directories. In repo-based + * development mode this includes the root Ghidra directory within each repo. + * When not in development mode, the requirement is that the current working + * directory correspond to the installation root. The first entry will be + * the primary root in both cases. + * @return root directories + */ + public static Collection getDefaultApplicationRootDirs() { + if (SystemUtilities.isInDevelopmentMode()) { + return ApplicationUtilities.findDefaultApplicationRootDirs(); + } + return CollectionUtils.asList(new ResourceFile(System.getProperty("user.dir"))); + } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java index 1d5e24c673..a66fb1f0d0 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java @@ -33,7 +33,6 @@ import ghidra.framework.model.ToolServices; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.classfinder.ClassSearcher; -import ghidra.util.exception.AssertException; import ghidra.util.exception.CancelledException; import ghidra.util.xml.GenericXMLOutputter; import ghidra.util.xml.XmlUtilities; @@ -52,7 +51,6 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat /** * Creates a new application using the given properties filename. The * filename is expected reside in the current working directory. - * *

    * The given properties file is expected to have the * {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and @@ -60,43 +58,59 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat * set. * * @param propertiesFilename the name of the properties file. + * @throws IOException error causing application initialization failure */ - public StandAloneApplication(String propertiesFilename) { - - try { - ApplicationProperties properties = ApplicationProperties.fromFile(propertiesFilename); - String name = properties.getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY); - if (name == null) { - Msg.error(this, - "The application.name property is not set in " + propertiesFilename); - } - - String version = - properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY); - if (version == null) { - Msg.error(this, - "The application.name property is not set in " + propertiesFilename); - } - - ApplicationLayout applicationLayout = new DockingApplicationLayout(properties); - init(applicationLayout); - } - catch (IOException e) { - throw new AssertException(e); - } + public StandAloneApplication(String propertiesFilename) throws IOException { + this(new DockingApplicationLayout(readApplicationProperties(propertiesFilename))); } - public StandAloneApplication(String name, String version) { + /** + * Creates a new application using the specified application name + * and version. + * @param name application name + * @param version application version + * @throws IOException error causing application initialization failure + */ + public StandAloneApplication(String name, String version) throws IOException { + this(new DockingApplicationLayout(name, version)); + } - // Setup application layout - try { - ApplicationLayout applicationLayout = new DockingApplicationLayout(name, version); - init(applicationLayout); - } - catch (IOException e) { - throw new AssertException(e); + /** + * reates a new application using the given application layout + * and associated application properties. + * @param applicationLayout application layout + */ + public StandAloneApplication(ApplicationLayout applicationLayout) { + init(applicationLayout); + } + + /** + * Read {@link ApplicationProperties} from the specified file path relative + * to the current working directory. + *

    + * The given properties file is expected to have the + * {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and + * {@link ApplicationProperties#APPLICATION_VERSION_PROPERTY} properties + * set. + * @param propertiesFilename the name of the properties file. + * @return application properties + * @throws IOException if file read error occurs + */ + public static ApplicationProperties readApplicationProperties(String propertiesFilename) + throws IOException { + ApplicationProperties properties = ApplicationProperties.fromFile(propertiesFilename); + String name = properties.getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY); + if (name == null) { + Msg.error(StandAloneApplication.class, + "The application.name property is not set in " + propertiesFilename); } + String version = properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY); + if (version == null) { + Msg.error(StandAloneApplication.class, + "The application.name property is not set in " + propertiesFilename); + } + return properties; } private void init(ApplicationLayout applicationLayout) { From 415a27ccc7f6bd98b948a94fff2840b8efa6f07f Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 12 Mar 2021 11:39:03 -0500 Subject: [PATCH 083/140] GP-693: Simplifying GhidraJarBuilder --- .../ghidra_scripts/BuildGhidraJarScript.java | 14 +- .../java/ghidra/util/GhidraJarBuilder.java | 155 +++++------------- 2 files changed, 44 insertions(+), 125 deletions(-) diff --git a/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java b/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java index b6a3f8e809..675904cb82 100644 --- a/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java +++ b/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java @@ -17,10 +17,9 @@ //@category Examples import java.io.File; -import java.util.*; +import java.util.List; import generic.jar.ApplicationModule; -import generic.jar.ResourceFile; import ghidra.app.script.GhidraScript; import ghidra.framework.Application; import ghidra.util.GhidraJarBuilder; @@ -32,8 +31,7 @@ public class BuildGhidraJarScript extends GhidraScript { @Override public void run() throws Exception { - GhidraJarBuilder builder = - new GhidraJarBuilder(toFiles(Application.getApplicationRootDirectories())); + GhidraJarBuilder builder = new GhidraJarBuilder(Application.getApplicationLayout()); builder.setMainClass("ghidra.JarRun"); // default is ghidra.JarRun, only here if you want // to change it to something else. @@ -69,12 +67,4 @@ public class BuildGhidraJarScript extends GhidraScript { // uncomment the following line to create a src zip for debugging. // builder.buildSrcZip(new File(installDir, "GhidraSrc.zip"), monitor); } - - private List toFiles(Collection resourceFiles) { - List fileList = new ArrayList<>(); - for (ResourceFile resourceFile : resourceFiles) { - fileList.add(resourceFile.getFile(true)); - } - return fileList; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java index 3805428083..3cd2c75ed3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java @@ -20,33 +20,29 @@ import java.nio.file.Path; import java.util.*; import java.util.jar.*; import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.zip.*; import generic.jar.*; import ghidra.GhidraApplicationLayout; import ghidra.GhidraLaunchable; -import ghidra.framework.Application; -import ghidra.framework.HeadlessGhidraApplicationConfiguration; +import ghidra.framework.*; import ghidra.framework.plugintool.dialog.ExtensionUtils; import ghidra.util.classfinder.ClassFinder; import ghidra.util.classfinder.ClassSearcher; import ghidra.util.exception.AssertException; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import ghidra.util.task.TaskMonitorAdapter; import utilities.util.FileUtilities; +import utility.application.ApplicationLayout; import utility.module.ModuleUtilities; public class GhidraJarBuilder implements GhidraLaunchable { private static final String ROOT = "_Root/"; private static final String ROOT_GHIDRA = "_Root/Ghidra/"; - private static final String LIBS_FILE_MODULE_KEY = "Module: "; // this is set in the buildGhidraJar batch/script files private static final String INVOCATION_NAME_PROPERTY = "GhidraJarBuilder.Name"; - private static HashMap> libsMap = new HashMap<>(); private List rootGhidraDirs = new ArrayList<>(); private List allModules; private Set includedModules = new HashSet<>(); @@ -57,19 +53,18 @@ public class GhidraJarBuilder implements GhidraLaunchable { private Pattern extensionPointSuffixPattern; private List extensionPointClasses = new ArrayList<>(); private ClassLoader classLoader; - private boolean inGradleMode = false; private Set processedJars = new HashSet<>(); public GhidraJarBuilder() { // Required for GhidraLaunchable } - public GhidraJarBuilder(List rootDirs) throws IOException { - for (File file : rootDirs) { - File rgd = file.getCanonicalFile(); + public GhidraJarBuilder(ApplicationLayout layout) throws IOException { + for (ResourceFile file : layout.getApplicationRootDirs()) { + File rgd = file.getFile(false).getCanonicalFile(); rootGhidraDirs.add(rgd); } - allModules = findAllModules(); + allModules = findAllModules(layout); Collections.sort(allModules); for (ApplicationModule module : allModules) { if (includeByDefault(module)) { @@ -203,7 +198,7 @@ public class GhidraJarBuilder implements GhidraLaunchable { for (ApplicationModule module : moduleList) { writeModuleClassesAndResources(jar, module); - if (!excludeHelp && !inGradleMode) { + if (!excludeHelp) { writeModuleHelp(jar, module); } } @@ -360,16 +355,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { private void writeModuleClassesAndResources(Jar jar, ApplicationModule module) throws CancelledException, IOException { - if (inGradleMode) { - File gradleBuildFileForModule = - new File(module.getModuleDir(), "build/libs/" + module.getName() + ".jar"); - processJarFile(jar, gradleBuildFileForModule, module); - File gradleBuildFileForGPLModule = - new File(module.getModuleDir(), "build/data/lib/" + module.getName() + ".jar"); - processJarFile(jar, gradleBuildFileForGPLModule, module); - processExternalLibs(jar, module); - return; - } // NOTE: This only works in a distribution where the 3rd party jars live in each // module's libs directory File binDir = new File(module.getModuleDir(), "bin/main"); @@ -380,18 +365,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { processLibDir(jar, module); } - private void processExternalLibs(Jar jar, ApplicationModule module) - throws CancelledException, IOException { - List list = libsMap.get(module.getName()); - if (list == null) { - return; - } - for (String libPath : list) { - File file = new File(libPath); - processJarFile(jar, file, module); - } - } - private void processLibDir(Jar jar, ApplicationModule module) throws CancelledException, IOException { File libDir = new File(module.getModuleDir(), "lib"); @@ -585,16 +558,40 @@ public class GhidraJarBuilder implements GhidraLaunchable { } return manifest; } - - private List findAllModules() { + + private List findAllModules(ApplicationLayout layout) throws IOException { List modules = new ArrayList<>(); - for (File appRoot : rootGhidraDirs) { - findModules(appRoot, appRoot, modules); - findModules(appRoot, new File(appRoot, "../GPL"), modules); - + + // Add GPL root directories + List rootDirs = new ArrayList<>(rootGhidraDirs); + for (File rootDir : rootGhidraDirs) { + rootDirs.add(new File(rootDir.getParentFile(), "GPL")); } + + for (GModule module : layout.getModules().values()) { + File moduleDir = module.getModuleRoot().getFile(false).getCanonicalFile(); + File rootDir = getModuleRootDir(moduleDir); + modules.add(new ApplicationModule(rootDir, moduleDir)); + } + return modules; } + + private File getModuleRootDir(File moduleDir) { + // Add GPL directories + List rootDirs = new ArrayList<>(rootGhidraDirs); + for (File rootDir : rootGhidraDirs) { + rootDirs.add(new File(rootDir.getParentFile(), "GPL")); + } + + // Check each root directory to see if it contains the module + for (File rootDir : rootDirs) { + if (FileUtilities.isPathContainedWithin(rootDir, moduleDir)) { + return rootDir; + } + } + throw new AssertException("Module root directory could not be determined: " + moduleDir); + } private String getPathFromRoot(String rootPath, File file) { String filePath = file.getAbsolutePath(); @@ -604,23 +601,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { return filePath.substring(rootPath.length() + 1); } - private void findModules(File rootAppDir, File dir, List modules) { - File moduleManifest = new File(dir, "Module.manifest"); - if (moduleManifest.exists()) { - ApplicationModule module = new ApplicationModule(rootAppDir, dir); - modules.add(module); - return; // modules can't live in other modules; - } - File[] listFiles = dir.listFiles(); - if (listFiles != null) { - for (File file : listFiles) { - if (file.isDirectory()) { - findModules(rootAppDir, file, modules); - } - } - } - } - private void checkExtensionPointClass(String path, InputStream inputStream) { // remove .class path = path.substring(0, path.length() - 6); @@ -931,31 +911,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { } } - private static void parseLibsFile(String libsFilePath) { - try { - List lines = FileUtilities.getLines(new File(libsFilePath)); - - List libPaths = new ArrayList<>(); - String currentModule = null; - for (String line : lines) { - if (line.startsWith(LIBS_FILE_MODULE_KEY)) { - if (currentModule != null) { - libsMap.put(currentModule, libPaths); - libPaths = new ArrayList<>(); - } - currentModule = line.substring(LIBS_FILE_MODULE_KEY.length()).trim(); - } - else { - libPaths.add(line.trim()); - } - } - } - catch (IOException e) { - System.err.println("Could not read lib paths file: " + libsFilePath); - System.exit(0); - } - } - private static void usage(String[] args) { for (int i = 0; i < args.length; i++) { System.err.println("arg " + i + ": " + args[i]); @@ -964,7 +919,7 @@ public class GhidraJarBuilder implements GhidraLaunchable { StringBuffer buf = new StringBuffer(); buf.append("\nUsage: "); - buf.append(invocationName != null ? invocationName : "GhidraJarBuilder "); + buf.append(invocationName != null ? invocationName : "GhidraJarBuilder"); buf.append( " [-output ] [-srczip ] [-bin ] [-main ]\n"); System.err.println(buf.toString()); @@ -988,15 +943,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { usage(args); } - List ghidraDirs = layout.getApplicationRootDirs() - .stream() - .map(f -> f.getFile(false)) - .collect(Collectors.toCollection(ArrayList::new)); File outputFile = null; File srczip = null; File extraBinDir = null; String mainClassArg = null; - boolean usingGradle = false; for (int i = 0; i < args.length; i++) { String arg = args[i]; @@ -1024,28 +974,14 @@ public class GhidraJarBuilder implements GhidraLaunchable { } mainClassArg = args[++i]; } - else if (arg.equals("-gradle")) { - if (i == args.length - 1) { - usage(args); - } - usingGradle = true; - parseLibsFile(args[++i]); - } - else if (arg.startsWith("-")) { + else { usage(args); } - else { - ghidraDirs.add(new File(arg)); - } - } - if (ghidraDirs.isEmpty()) { - usage(args); } if (outputFile == null) { outputFile = new File("ghidra.jar"); } - System.out.println("Ghidra dirs = " + ghidraDirs); System.out.println("Output file = " + outputFile); if (srczip != null) { System.out.println("Source Zip File = " + srczip); @@ -1055,13 +991,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { } try { - GhidraJarBuilder builder = new GhidraJarBuilder(ghidraDirs); + GhidraJarBuilder builder = new GhidraJarBuilder(layout); if (mainClassArg != null) { builder.setMainClass(mainClassArg); } - if (usingGradle) { - builder.setGradleMode(); - } builder.addExcludedFileExtension(".pdf"); // builder.addExcludedFileExtension(".htm"); @@ -1076,10 +1009,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { System.out.println("Exclude " + module.getName()); } - builder.buildJar(outputFile, extraBinDir, TaskMonitorAdapter.DUMMY_MONITOR); + builder.buildJar(outputFile, extraBinDir, TaskMonitor.DUMMY); if (srczip != null) { - builder.buildSrcZip(srczip, TaskMonitorAdapter.DUMMY_MONITOR); + builder.buildSrcZip(srczip, TaskMonitor.DUMMY); } } catch (Exception e) { @@ -1093,8 +1026,4 @@ public class GhidraJarBuilder implements GhidraLaunchable { return new File(ghidraRootDir, "application.properties"); } - private void setGradleMode() { - inGradleMode = true; - } - } From d7dc20ba411499c765d0474ec05afdc8959001f8 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 12 Mar 2021 13:16:01 -0500 Subject: [PATCH 084/140] GT-693: Removing unneeded code --- .../Base/src/main/java/ghidra/util/GhidraJarBuilder.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java index 3cd2c75ed3..5dd1622017 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java @@ -562,12 +562,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { private List findAllModules(ApplicationLayout layout) throws IOException { List modules = new ArrayList<>(); - // Add GPL root directories - List rootDirs = new ArrayList<>(rootGhidraDirs); - for (File rootDir : rootGhidraDirs) { - rootDirs.add(new File(rootDir.getParentFile(), "GPL")); - } - for (GModule module : layout.getModules().values()) { File moduleDir = module.getModuleRoot().getFile(false).getCanonicalFile(); File rootDir = getModuleRootDir(moduleDir); @@ -578,7 +572,7 @@ public class GhidraJarBuilder implements GhidraLaunchable { } private File getModuleRootDir(File moduleDir) { - // Add GPL directories + // Look in GPL directories too List rootDirs = new ArrayList<>(rootGhidraDirs); for (File rootDir : rootGhidraDirs) { rootDirs.add(new File(rootDir.getParentFile(), "GPL")); From 229c30084e16948416bef3755569800ee11ec39a Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:18:33 -0500 Subject: [PATCH 085/140] GP-768 - Function Graph - condense before edge routing --- .../CodeBrowserClipboardProvider.java | 23 +- .../graph/layout/DecompilerNestedLayout.java | 285 +++++++++++------- .../layout/AbstractVisualGraphLayout.java | 93 +++--- .../viewer/renderer/VisualGraphRenderer.java | 21 +- 4 files changed, 250 insertions(+), 172 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java index eb3e5a4c09..216a85bbd6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java @@ -24,6 +24,8 @@ import java.util.concurrent.CopyOnWriteArraySet; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.apache.commons.lang3.StringUtils; + import docking.ActionContext; import docking.ComponentProvider; import docking.dnd.GenericDataFlavor; @@ -303,12 +305,9 @@ public class CodeBrowserClipboardProvider extends ByteCopier private Transferable copyAddress() { AddressSetView addressSet = getSelectedAddresses(); - StringBuilder buffy = new StringBuilder(); AddressIterator it = addressSet.getAddresses(true); - while (it.hasNext()) { - buffy.append(it.next()).append('\n'); - } - return createStringTransferable(buffy.toString()); + String joined = StringUtils.join((Iterator

    ) it, "\n"); + return createStringTransferable(joined); } protected Transferable copyCode(TaskMonitor monitor) { @@ -377,8 +376,8 @@ public class CodeBrowserClipboardProvider extends ByteCopier private boolean pasteLabelsComments(Transferable pasteData, boolean pasteLabels, boolean pasteComments) { try { - List list = (List) pasteData.getTransferData( - CodeUnitInfoTransferable.localDataTypeFlavor); + List list = + (List) pasteData.getTransferData(CodeUnitInfoTransferable.localDataTypeFlavor); List infos = CollectionUtils.asList(list, CodeUnitInfo.class); Command cmd = new CodeUnitInfoPasteCmd(currentLocation.getAddress(), infos, pasteLabels, pasteComments); @@ -420,7 +419,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier return pasteOperandField((OperandFieldLocation) currentLocation, labelName); } - // try pasting onto something that is not a label + // try pasting onto something that is not a label return maybePasteNonLabelString(labelName); } @@ -451,12 +450,12 @@ public class CodeBrowserClipboardProvider extends ByteCopier String oldName = symbol.getName(); Namespace namespace = symbol.getParentNamespace(); Address symbolAddress = symbol.getAddress(); - RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, - namespace, SourceType.USER_DEFINED); + RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, namespace, + SourceType.USER_DEFINED); return tool.execute(cmd, currentProgram); } - // try pasting onto something that is not a label + // try pasting onto something that is not a label return maybePasteNonLabelString(labelName); } @@ -646,7 +645,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier //================================================================================================== // Unsupported Operations -//================================================================================================== +//================================================================================================== @Override public void lostOwnership(Transferable transferable) { diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java index 761c18f743..e3a40d8ff3 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java @@ -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. @@ -38,6 +38,7 @@ import ghidra.app.plugin.core.functiongraph.graph.jung.renderer.DNLArticulatedEd import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex; import ghidra.app.plugin.core.functiongraph.graph.vertex.GroupedFunctionGraphVertex; import ghidra.graph.VisualGraph; +import ghidra.graph.viewer.GraphViewerUtils; import ghidra.graph.viewer.layout.*; import ghidra.graph.viewer.vertex.VisualGraphVertexShapeTransformer; import ghidra.program.model.address.Address; @@ -52,19 +53,19 @@ import ghidra.util.task.TaskMonitor; /** * A layout that uses the decompiler to show code nesting based upon conditional logic. - * + * *

    Edges returning to the default code flow are painted lighter to de-emphasize them. This * could be made into an option. - * - *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. + * + *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. * Simple routing will reduce edge noise as much as possible by combining/overlapping edges that * flow towards the bottom of the function (returning code flow). Also, edges may fall behind * vertices for some functions. Complex routing allows the user to visually follow the flow * of an individual edge. Complex routing will prevent edges from overlapping and will route - * edges around vertices. Simple routing is better when the layout of the vertices is - * important to the user; complex routing is better when edges/relationships are more + * edges around vertices. Simple routing is better when the layout of the vertices is + * important to the user; complex routing is better when edges/relationships are more * important to the user. - * + * * TODO ideas: * -paint fallthrough differently for all, or just for those returning to the baseline */ @@ -113,7 +114,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override protected double getCondenseFactor() { - // our layout needs more spacing because we have custom edge routing that we want to + // our layout needs more spacing because we have custom edge routing that we want to // stand out return .3; } @@ -201,7 +202,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { continue; } - // + // // Special case: fallthrough--don't label this...not sure how to tell fallthrough. For // now assume that any column below or backwards is fallthrough. However, // do label fallthrough if it is the only edge. @@ -231,10 +232,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Map> newEdgeArticulations = new HashMap<>(); - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method below is + // bit for that effect using this offset value. The getEdgeOffset() method below is // updated for the condense factor. int edgeOffset = isCondensedLayout() ? (int) (VERTEX_TO_EDGE_ARTICULATION_PADDING * (1 - getCondenseFactor())) @@ -242,7 +243,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Vertex2dFactory vertex2dFactory = new Vertex2dFactory(transformer, vertexLayoutLocations, layoutToGridMap, edgeOffset); - // + // // Route our edges! // for (FGEdge e : edges) { @@ -262,11 +263,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { DecompilerBlock loop = block.getParentLoop(); if (loop != null) { - Set vertices = loop.getVertices(); - - Column outermostCol = getOutermostCol(layoutToGridMap, vertices); - Column loopEndColumn = layoutToGridMap.nextColumn(outermostCol); - List articulations = routeLoopEdge(start, end, loopEndColumn); + List articulations = + routeUpwardLoop(layoutToGridMap, vertex2dFactory, start, end, loop); newEdgeArticulations.put(e, articulations); continue; } @@ -275,31 +273,31 @@ public class DecompilerNestedLayout extends AbstractFGLayout { List articulations = new ArrayList<>(); // - // Basic routing: + // Basic routing: // -leave the bottom of the start vertex // -first bend at some constant offset // -move to right or left, to above the end vertex // -second bend above the end vertex at previous constant offset - // - // Edges start/end on the vertex center. If we offset them to avoid + // + // Edges start/end on the vertex center. If we offset them to avoid // overlapping, then they produce angles when only using two articulations. // Thus, we create articulations that are behind the vertices to remove // the angles. This points will not be seen. // - // + // // Complex routing: // -this mode will route edges around vertices - // + // // One goal for complex edge routing is to prevent overlapping (simple edge routing // prefers overlapping to reduce lines). To prevent overlapping we will use different - // offset x and y values, depending upon the start and end vertex row and column + // offset x and y values, depending upon the start and end vertex row and column // locations. Specifically, for a given edge direction there will be a bias: // -Edge to the right - leave from the right; arrive to the left // -Edge to the left - leave from the left; arrive to the right // -Edge straight down - go straight down // // For each of the above offsets, there will be an amplifier based upon row/column - // distance from start to end vertex. This has the effect that larger vertex + // distance from start to end vertex. This has the effect that larger vertex // distances will have a larger offset/spacing. // @@ -331,14 +329,78 @@ public class DecompilerNestedLayout extends AbstractFGLayout { return newEdgeArticulations; } + private List routeUpwardLoop(LayoutLocationMap layoutToGridMap, + Vertex2dFactory vertex2dFactory, Vertex2d start, Vertex2d end, DecompilerBlock loop) { + Set loopVertices = loop.getVertices(); + FGVertex rightmostLoopVertex = + getRightmostVertex(layoutToGridMap, vertex2dFactory, loopVertices); + + int startRow = start.rowIndex; + int endRow = end.rowIndex; + int startColumn = Math.min(start.columnIndex, end.columnIndex); + int endColumn = Math.max(start.columnIndex, end.columnIndex); + + Column rightmostLoopColumn = layoutToGridMap.col(rightmostLoopVertex); + endColumn = Math.max(endColumn, rightmostLoopColumn.index); + + // Look for any vertices that are no part of the loop, but are placed inside + // of the loop bounds. This can happen in a graph when the decompiler uses + // goto statements. Use the loop's rightmost vertex to establish the loops + // right edge and then use that to check for any stray non-loop vertices. + List interlopers = + getVerticesInBounds(vertex2dFactory, startRow, endRow, startColumn, endColumn); + + // place the right x position to the right of the rightmost vertex, not + // extending past the next column + FGVertex rightmostVertex = getRightmostVertex(interlopers); + Column rightmostColumn = layoutToGridMap.col(rightmostVertex); + Column nextColumn = layoutToGridMap.nextColumn(rightmostColumn); + Vertex2d rightmostV2d = vertex2dFactory.get(rightmostVertex); + + // the padding used for these two lines is somewhat arbitrary and may be changed + double rightSide = rightmostV2d.getRight() + GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING; + double x = Math.min(rightSide, + nextColumn.x - GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING_CONDENSED); + + List articulations = routeLoopEdge(start, end, x); + return articulations; + } + + private List getVerticesInBounds(Vertex2dFactory vertex2dFactory, int startRow, + int endRow, int startColumn, int endColumn) { + + if (startRow > endRow) { // going upwards + int temp = endRow; + endRow = startRow; + startRow = temp; + } + + List toCheck = new LinkedList<>(); + for (int row = startRow; row < endRow + 1; row++) { + + for (int col = startColumn; col < endColumn + 1; col++) { + + // assume any other vertex in our column can clip (it will not clip when + // the 'spacing' above pushes the edge away from this column, like for + // large row delta values) + Vertex2d otherVertex = vertex2dFactory.get(row, col); + if (otherVertex != null) { + toCheck.add(otherVertex); + } + } + } + + return toCheck; + } + private void routeToTheRightGoingUpwards(Vertex2d start, Vertex2d end, Vertex2dFactory vertex2dFactory, List articulations) { // - // For routing to the right and back up we will leave the start vertex from the right side + // For routing to the right and back up we will leave the start vertex from the right side // and enter the end vertex on the right side. As the vertices get further apart, we will - // space them further in towards the center. - // + // space them further in towards the center. + // int delta = start.rowIndex - end.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -347,11 +409,9 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } int distanceSpacing = delta * multiplier; - // Condensing Note: we have guilty knowledge that our parent class my condense the - // vertices and edges towards the center of the graph after we calculate positions. - // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is - // updated for the condense factor. + // Condensing is when the graph will pull nodes closer together on the x axis to + // reduce whitespace and make the entire graph easier to see. In this case, update + // the offset to avoid running into the moved vertices. int exaggerationFactor = 1; if (isCondensedLayout()) { exaggerationFactor = 2; // determined by trial-and-error; can be made into an option @@ -369,7 +429,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { y1 = Math.min(y1, startCenterY); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double startRightX = start.getRight(); double x2 = startRightX + VERTEX_BORDER_THICKNESS; // start at the end @@ -434,10 +494,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // For routing to the left we will leave the start vertex from just left of center and - // enter the end vertex on the top, towards the right. As the vertices get further apart, - // we will space them further in towards the center of the end vertex. This will keep + // enter the end vertex on the top, towards the right. As the vertices get further apart, + // we will space them further in towards the center of the end vertex. This will keep // edges with close endpoints from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -499,7 +559,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // enter the end vertex on the left side. As the vertices get further apart, we will // space them further in towards the center. This will keep edges with close endpoints // from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; if (delta < 0) { @@ -529,7 +589,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y1 = start.getY(); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double x2 = x1; double y2 = end.getTop() + VERTEX_BORDER_THICKNESS; @@ -556,19 +616,6 @@ public class DecompilerNestedLayout extends AbstractFGLayout { private void routeAroundColumnVertices(Vertex2d start, Vertex2d end, Vertex2dFactory vertex2dFactory, List articulations, double edgeX) { - Column column = vertex2dFactory.getColumn(edgeX); - int columnIndex = 0; - if (column != null) { - // a null column happens with a negative x value that is outside of any column - columnIndex = column.index; - } - - routeAroundColumnVertices(start, end, columnIndex, vertex2dFactory, articulations, edgeX); - } - - private void routeAroundColumnVertices(Vertex2d start, Vertex2d end, int column, - Vertex2dFactory vertex2dFactory, List articulations, double edgeX) { - if (useSimpleRouting()) { return; } @@ -582,14 +629,34 @@ public class DecompilerNestedLayout extends AbstractFGLayout { startRow = end.rowIndex; } + int startColumn = Math.min(start.columnIndex, end.columnIndex); + int endColumn = Math.max(start.columnIndex, end.columnIndex); + if (goingDown) { + endRow -= 1; + endColumn -= 1; + + if (start.columnIndex <= end.columnIndex) { + startRow += 1; + } + } + else { + // going up we swing out to the right; grab the column that is out to the right + Column rightColumn = vertex2dFactory.getColumn(edgeX); + endColumn = rightColumn.index; + } + List toCheck = new LinkedList<>(); - for (int row = startRow + 1; row < endRow; row++) { - // assume any other vertex in our column can clip (it will not clip when - // the 'spacing' above pushes the edge away from this column, like for - // large row delta values) - Vertex2d otherVertex = vertex2dFactory.get(row, column); - if (otherVertex != null) { - toCheck.add(otherVertex); + for (int row = startRow; row < endRow + 1; row++) { + + for (int col = startColumn; col < endColumn + 1; col++) { + + // assume any other vertex in our column can clip (it will not clip when + // the 'spacing' above pushes the edge away from this column, like for + // large row delta values) + Vertex2d otherVertex = vertex2dFactory.get(row, col); + if (otherVertex != null) { + toCheck.add(otherVertex); + } } } @@ -605,11 +672,9 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING; int distanceSpacing = padding + delta; // adding the delta makes overlap less likely - // Condensing Note: we have guilty knowledge that our parent class my condense the - // vertices and edges towards the center of the graph after we calculate positions. - // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is - // updated for the condense factor. + // Condensing is when the graph will pull nodes closer together on the x axis to + // reduce whitespace and make the entire graph easier to see. In this case, update + // the offset to avoid running into the moved vertices. int vertexToEdgeOffset = otherVertex.getEdgeOffset(); int exaggerationFactor = 1; if (isCondensedLayout()) { @@ -629,20 +694,20 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // no need to check the 'y' value, as the end vertex is above/below this one if (vertexClipper.isClippingX(otherVertex, edgeX)) { - /* + /* Must route around this vertex - new points: -p1 - just above the intersection point -p2 - just past the left edge -p3 - just past the bottom of the vertex -p4 - back at the original x value - + | .___| | .-----. | | | | '-----' '---. - | + | */ // p1 - same x; y just above vertex @@ -650,19 +715,19 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y = vertexClipper.getTopOffset(otherVertex, vertexToEdgeOffset); articulations.add(new Point2D.Double(x, y)); - // Maybe merge points if they are too close together. Visually, many lines - // moving around intersecting vertices looks busy. When the intersecting + // Maybe merge points if they are too close together. Visually, many lines + // moving around intersecting vertices looks busy. When the intersecting // vertices are close together, we remove some of the articulations in order to // smooth out the edges. if (articulations.size() > 2) { - /* + /* The last articulation is the one added before this method was called, which - lies just below the intersecting vertex. The articulation before that is - the one that is the one that is sending the x value straight into the + lies just below the intersecting vertex. The articulation before that is + the one that is the one that is sending the x value straight into the intersecting vertex. Delete that point as well so that the entire edge is shifted to the outside of the intersecting vertex. This will get repeated - for each vertex that is intersecting. + for each vertex that is intersecting. */ Point2D previousArticulation = articulations.get(articulations.size() - 2); int closenessHeight = 50; @@ -696,15 +761,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout { return !getLayoutOptions().useEdgeRoutingAroundVertices(); } - private List routeLoopEdge(Vertex2d start, Vertex2d end, Column loopEndColumn) { + private List routeLoopEdge(Vertex2d start, Vertex2d end, double x) { // going backwards List articulations = new ArrayList<>(); - // loop first point - same y coord as the vertex; x is the middle of the next col - int halfWidth = loopEndColumn.getPaddedWidth(isCondensedLayout()) >> 1; - double x = loopEndColumn.x + halfWidth; // middle of the column - int startRow = start.rowIndex; int endRow = end.rowIndex; if (startRow > endRow) { // going upwards @@ -720,7 +781,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Point2D first = new Point2D.Double(x, y1); articulations.add(first); - // loop second point - same y coord as destination; + // loop second point - same y coord as destination; // x is the col after the outermost dominated vertex Point2D endVertexPoint = end.center; @@ -739,21 +800,37 @@ public class DecompilerNestedLayout extends AbstractFGLayout { e.setDefaultAlpha(.25); } - private Column getOutermostCol(LayoutLocationMap layoutLocations, - Set vertices) { + private FGVertex getRightmostVertex(LayoutLocationMap layoutLocations, + Vertex2dFactory vertex2dFactory, Set vertices) { - Column outermost = null; + List points = new ArrayList<>(); for (FGVertex v : vertices) { - Column col = layoutLocations.col(v); - if (outermost == null) { - outermost = col; + Vertex2d v2d = vertex2dFactory.get(v); + points.add(v2d); + } + + FGVertex v = getRightmostVertex(points); + return v; + } + + private FGVertex getRightmostVertex(Collection points) { + + Vertex2d rightmost = null; + for (Vertex2d v2d : points) { + if (rightmost == null) { + rightmost = v2d; } - else if (col.x > outermost.x) { - outermost = col; + else { + // the rightmost is that which extends furthest to the right + double current = rightmost.getRight(); + double other = v2d.getRight(); + if (other > current) { + rightmost = v2d; + } } } - return outermost; + return rightmost.v; } @Override @@ -840,8 +917,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout { BlockCopy copy = (BlockCopy) child; StringBuilder buffy = new StringBuilder(); - buffy.append(printDepth(depth, depth + 1)).append(' ').append(ID).append( - " plain - ").append(copy.getRef()); + buffy.append(printDepth(depth, depth + 1)) + .append(' ') + .append(ID) + .append(" plain - ") + .append(copy.getRef()); debug(buffy.toString()); } @@ -958,7 +1038,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { //================================================================================================== // Inner Classes -//================================================================================================== +//================================================================================================== /** * Encapsulates knowledge of edge direction (up/down, left/right) and uses that knowledge @@ -1060,7 +1140,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } /** - * A class that represents 2D information about the contained vertex, such as location, + * A class that represents 2D information about the contained vertex, such as location, * bounds, row and column of the layout grid. */ private class Vertex2d { @@ -1207,8 +1287,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int row = startRow; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { row = ((DecompilerBlockGraph) block).setRows(row); } @@ -1229,8 +1308,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { String getChildrenString(int depth) { StringBuilder buffy = new StringBuilder(); int childCount = 0; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { String blockName = block.getName(); @@ -1315,8 +1393,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override DecompilerBlock getBlock(FGVertex vertex) { // - // Note: we currently allow grouping in this layout. When we search for a vertex, - // we have to check each vertex inside of the given group *and* each vertex + // Note: we currently allow grouping in this layout. When we search for a vertex, + // we have to check each vertex inside of the given group *and* each vertex // inside of the vertex that belongs to this decompiler block. // if (vertex instanceof GroupedFunctionGraphVertex) { @@ -1447,9 +1525,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // The 'list' structure for children's nesting: // -all nodes are at the same level // - for (int i = 0; i < allChildren.size(); i++) { + for (DecompilerBlock block : allChildren) { int column = col; - DecompilerBlock block = allChildren.get(i); block.setCol(column); } @@ -1477,8 +1554,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // -each successive condition is another level nested // int column = col; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); column++; } @@ -1515,11 +1591,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // The 'do' structure for children's nesting: - // -all blocks nested + // -all blocks nested // int column = col + 1; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java index 0fba3848f2..afecdf2477 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java @@ -44,36 +44,36 @@ import ghidra.util.task.TaskMonitor; * A base layout that marries the Visual Graph and Jung layout interfaces. This class allows * you to create new layouts while stubbing the Jung layout methods. * - *

    This class essentially takes in client-produced grid row and column indices and + *

    This class essentially takes in client-produced grid row and column indices and * produces layout locations for those values. * - *

    This an implementation the Jung {@link Layout} interface that handles most of the + *

    This an implementation the Jung {@link Layout} interface that handles most of the * layout implementation for you. Things to know: *

      *
    • You should call initialize() inside of your constructor
    • - *
    • You must implement {@link #performInitialGridLayout(VisualGraph)} - this is where + *
    • You must implement {@link #performInitialGridLayout(VisualGraph)} - this is where * you align your vertices (and optionally edge articulations) on a grid. This grid * will be translated into layout space points for you.
    • - *
    • If you wish to use articulation points in your edges, you must override - * {@link #usesEdgeArticulations()} to return true.
    • + *
    • If you wish to use articulation points in your edges, you must override + * {@link #usesEdgeArticulations()} to return true.
    • *
    - * + * *

    By default, this class will create x-position values that - * are aligned with the column's x-position. You can override + * are aligned with the column's x-position. You can override * {@link #getVertexLocation(VisualVertex, Column, Row, Rectangle)} in order to center the * vertex within its column - * {@link #getCenteredVertexLocation(VisualVertex, Column, Row, Rectangle)}. Also note though + * {@link #getCenteredVertexLocation(VisualVertex, Column, Row, Rectangle)}. Also note though * that if your layout returns true for {@link #isCondensedLayout()}, - * then the centering will be condensed and slightly off. - * + * then the centering will be condensed and slightly off. + * * @param the vertex type * @param the edge type - * + * * @see GridLocationMap * @see LayoutPositions */ //@formatter:off -public abstract class AbstractVisualGraphLayout> extends AbstractLayout implements VisualGraphLayout { @@ -106,9 +106,9 @@ public abstract class AbstractVisualGraphLayout newLayout) { @@ -260,7 +260,7 @@ public abstract class AbstractVisualGraphLayout bends = edgesToBends.get(e); if (bends == null) { - // New edge is not in the old graph. This can happen if the old graph has + // New edge is not in the old graph. This can happen if the old graph has // grouped vertices and some edges have been removed. continue; } @@ -313,14 +313,7 @@ public abstract class AbstractVisualGraphLayout vertexLayoutLocations = positionVerticesInLayoutSpace(transformer, vertices, layoutLocations); - Map> edgeLayoutArticulationLocations = - positionEdgeArticulationsInLayoutSpace(transformer, vertexLayoutLocations, edges, - layoutLocations); - - // DEGUG triggers grid lines to be printed; useful for debugging -// VisualGraphRenderer.DEBUG_ROW_COL_MAP.put((Graph) visualGraph, -// layoutLocations.copy()); - + Map> edgeLayoutArticulationLocations = new HashMap<>(); Rectangle graphBounds = getTotalGraphSize(vertexLayoutLocations, edgeLayoutArticulationLocations, transformer); double centerX = graphBounds.getCenterX(); @@ -332,6 +325,12 @@ public abstract class AbstractVisualGraphLayout> 1); int y = row.y + (row.getPaddedHeight(isCondensed) >> 1); @@ -464,8 +463,8 @@ public abstract class AbstractVisualGraphLayout transformer, double centerX, double centerY) { // - // Note: we move the articulations and vertices closer together on the x-axis. We do - // not move the y-axis, as that is already as close together as we would like at + // Note: we move the articulations and vertices closer together on the x-axis. We do + // not move the y-axis, as that is already as close together as we would like at // this point. // double condenseFactor = getCondenseFactor(); @@ -496,14 +495,14 @@ public abstract class AbstractVisualGraphLayout> 1; // half width int myHeight = vertexBounds.height >> 1; // half height double x = vertexPoint.getX(); @@ -635,20 +634,20 @@ public abstract class AbstractVisualGraphLayout the vertex type - * @param the edge type + * @param the edge type */ public class VisualGraphRenderer> extends edu.uci.ics.jung.visualization.renderers.BasicRenderer { @@ -44,7 +44,8 @@ public class VisualGraphRenderer /** * Used for displaying grid information for graph layouts */ - public static Map, LayoutLocationMap> DEBUG_ROW_COL_MAP = new HashMap<>(); + public static Map, LayoutLocationMap> DEBUG_ROW_COL_MAP = + new HashMap<>(); private Renderer.EdgeLabel edgeLabelRenderer = new BasicEdgeLabelRenderer<>(); @@ -122,11 +123,15 @@ public class VisualGraphRenderer edgeLabelRenderer.labelEdge(rc, layout, e, xform.apply(e)); } + @SuppressWarnings({ "unchecked", "rawtypes" }) // the types in the cast matter not private void paintLayoutGridCells(RenderContext renderContext, Layout layout) { // to enable this debug, search java files for commented-out uses of 'DEBUG_ROW_COL_MAP' - Graph graph = layout.getGraph(); - LayoutLocationMap locationMap = DEBUG_ROW_COL_MAP.get(graph); + Layout key = layout; + if (layout instanceof ObservableCachingLayout) { + key = ((ObservableCachingLayout) layout).getDelegate(); + } + LayoutLocationMap locationMap = DEBUG_ROW_COL_MAP.get(key); if (locationMap == null) { return; } From e19d59cac74a0cee509f1e559258098cd064b6a0 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:26:35 -0500 Subject: [PATCH 086/140] GP-769 - Function Graph - added option to not used dimming for return flow edges --- .../FunctionGraphPlugin/Function_Graph.html | 16 +++ .../Function_Graph_Layouts.html | 7 ++ .../mvc/FunctionGraphOptions.java | 6 +- .../graph/layout/DNLayoutOptions.java | 18 ++- .../graph/layout/DecompilerNestedLayout.java | 118 +++++++++--------- 5 files changed, 103 insertions(+), 62 deletions(-) diff --git a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html index 9e5de3196f..b66dce8c8f 100644 --- a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html +++ b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html @@ -840,6 +840,22 @@ location when zooming from the middle-mouse. The default for this option is off, which triggers zoom to work from the center of the graph, regardless of the mouse location.

    +

    The View Settings option describes how the graph will be zoomed when it is first + loaded. The values are:

    + +
      +
    • Start Fully Zoomed Out - always start fully zoomed out so that the entire + graph can be seen.
    • + +
    • Start Fully Zoomed In/B> - always start fully zoomed in on the vertex containing + the current location.
    • + +
    • Remember User Settings - keep the zoom level where the user previously left + it.
    • +
    +
    +
    +

    There are various edge color and highlight color options available to change. The highlight colors are those to be used when the flow animations take place.

    diff --git a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html index 2f2eab68a8..6e71260598 100644 --- a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html +++ b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html @@ -49,6 +49,13 @@ notes on how edges are routed for this layout.)

    + +
    +

    The Use Dim Return Edges option makes default code block return flow edges + lighter than conditional edges. This makes it easier for users to scan the + graph and ignore return flows. +

    +
    diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java index 51b6773a9a..ea22f1cf44 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java @@ -42,7 +42,7 @@ public class FunctionGraphOptions extends VisualGraphOptions { private static final String EDGE_COLOR_CONDITIONAL_JUMP_KEY = "Edge Color - Conditional Jump "; //@formatter:off - private static final String NAVIGATION_HISTORY_KEY = "Navigation History"; + private static final String NAVIGATION_HISTORY_KEY = "Navigation History"; private static final String NAVIGATION_HISTORY_DESCRIPTION = "Determines how the navigation history will be updated when using the Function Graph. " + "The basic options are:" + @@ -185,8 +185,8 @@ public class FunctionGraphOptions extends VisualGraphOptions { options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help, SCROLL_WHEEL_PANS_DESCRIPTION); - options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, - help, GRAPH_BACKGROUND_COLOR_DESCRPTION); + options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, help, + GRAPH_BACKGROUND_COLOR_DESCRPTION); options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR, help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION); diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java index 1467a84781..1549c2cd9a 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java @@ -31,7 +31,12 @@ public class DNLayoutOptions implements FGLayoutOptions { "edges should be routed around any intersecting vertex. When toggled off, edges will " + "pass through any intersecting vertices."; + private static final String DIM_RETURN_EDGES_KEY = "Use Dim Return Edges"; + private static final String DIM_RETURN_EDGES_DESCRIPTION = + "Signals to lighten the default return edges."; + private boolean useEdgeRoutingAroundVertices; + private boolean useDimmedReturnEdges = true; @Override public void registerOptions(Options options) { @@ -40,21 +45,32 @@ public class DNLayoutOptions implements FGLayoutOptions { options.registerOption(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices, help, USE_EDGE_ROUTING_AROUND_VERTICES_DESCRIPTION); + + options.registerOption(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges, help, + DIM_RETURN_EDGES_DESCRIPTION); } @Override public void loadOptions(Options options) { useEdgeRoutingAroundVertices = options.getBoolean(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices); + + useDimmedReturnEdges = options.getBoolean(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges); + } public boolean useEdgeRoutingAroundVertices() { return useEdgeRoutingAroundVertices; } + public boolean useDimmedReturnEdges() { + return useDimmedReturnEdges; + } + @Override public boolean optionChangeRequiresRelayout(String optionName) { // format: 'Nested Code Layout.Route Edges....' - return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY); + return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY) || + optionName.endsWith(DIM_RETURN_EDGES_KEY); } } diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java index 761c18f743..365444132e 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java @@ -52,19 +52,19 @@ import ghidra.util.task.TaskMonitor; /** * A layout that uses the decompiler to show code nesting based upon conditional logic. - * + * *

    Edges returning to the default code flow are painted lighter to de-emphasize them. This * could be made into an option. - * - *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. + * + *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. * Simple routing will reduce edge noise as much as possible by combining/overlapping edges that * flow towards the bottom of the function (returning code flow). Also, edges may fall behind * vertices for some functions. Complex routing allows the user to visually follow the flow * of an individual edge. Complex routing will prevent edges from overlapping and will route - * edges around vertices. Simple routing is better when the layout of the vertices is - * important to the user; complex routing is better when edges/relationships are more + * edges around vertices. Simple routing is better when the layout of the vertices is + * important to the user; complex routing is better when edges/relationships are more * important to the user. - * + * * TODO ideas: * -paint fallthrough differently for all, or just for those returning to the baseline */ @@ -113,7 +113,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override protected double getCondenseFactor() { - // our layout needs more spacing because we have custom edge routing that we want to + // our layout needs more spacing because we have custom edge routing that we want to // stand out return .3; } @@ -201,7 +201,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { continue; } - // + // // Special case: fallthrough--don't label this...not sure how to tell fallthrough. For // now assume that any column below or backwards is fallthrough. However, // do label fallthrough if it is the only edge. @@ -231,10 +231,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Map> newEdgeArticulations = new HashMap<>(); - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method below is + // bit for that effect using this offset value. The getEdgeOffset() method below is // updated for the condense factor. int edgeOffset = isCondensedLayout() ? (int) (VERTEX_TO_EDGE_ARTICULATION_PADDING * (1 - getCondenseFactor())) @@ -242,7 +242,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Vertex2dFactory vertex2dFactory = new Vertex2dFactory(transformer, vertexLayoutLocations, layoutToGridMap, edgeOffset); - // + // // Route our edges! // for (FGEdge e : edges) { @@ -275,31 +275,31 @@ public class DecompilerNestedLayout extends AbstractFGLayout { List articulations = new ArrayList<>(); // - // Basic routing: + // Basic routing: // -leave the bottom of the start vertex // -first bend at some constant offset // -move to right or left, to above the end vertex // -second bend above the end vertex at previous constant offset - // - // Edges start/end on the vertex center. If we offset them to avoid + // + // Edges start/end on the vertex center. If we offset them to avoid // overlapping, then they produce angles when only using two articulations. // Thus, we create articulations that are behind the vertices to remove // the angles. This points will not be seen. // - // + // // Complex routing: // -this mode will route edges around vertices - // + // // One goal for complex edge routing is to prevent overlapping (simple edge routing // prefers overlapping to reduce lines). To prevent overlapping we will use different - // offset x and y values, depending upon the start and end vertex row and column + // offset x and y values, depending upon the start and end vertex row and column // locations. Specifically, for a given edge direction there will be a bias: // -Edge to the right - leave from the right; arrive to the left // -Edge to the left - leave from the left; arrive to the right // -Edge straight down - go straight down // // For each of the above offsets, there will be an amplifier based upon row/column - // distance from start to end vertex. This has the effect that larger vertex + // distance from start to end vertex. This has the effect that larger vertex // distances will have a larger offset/spacing. // @@ -335,10 +335,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Vertex2dFactory vertex2dFactory, List articulations) { // - // For routing to the right and back up we will leave the start vertex from the right side + // For routing to the right and back up we will leave the start vertex from the right side // and enter the end vertex on the right side. As the vertices get further apart, we will - // space them further in towards the center. - // + // space them further in towards the center. + // int delta = start.rowIndex - end.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -347,10 +347,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } int distanceSpacing = delta * multiplier; - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is + // bit for that effect using this offset value. The getEdgeOffset() method is // updated for the condense factor. int exaggerationFactor = 1; if (isCondensedLayout()) { @@ -369,7 +369,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { y1 = Math.min(y1, startCenterY); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double startRightX = start.getRight(); double x2 = startRightX + VERTEX_BORDER_THICKNESS; // start at the end @@ -434,10 +434,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // For routing to the left we will leave the start vertex from just left of center and - // enter the end vertex on the top, towards the right. As the vertices get further apart, - // we will space them further in towards the center of the end vertex. This will keep + // enter the end vertex on the top, towards the right. As the vertices get further apart, + // we will space them further in towards the center of the end vertex. This will keep // edges with close endpoints from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -499,7 +499,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // enter the end vertex on the left side. As the vertices get further apart, we will // space them further in towards the center. This will keep edges with close endpoints // from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; if (delta < 0) { @@ -529,7 +529,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y1 = start.getY(); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double x2 = x1; double y2 = end.getTop() + VERTEX_BORDER_THICKNESS; @@ -605,10 +605,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING; int distanceSpacing = padding + delta; // adding the delta makes overlap less likely - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is + // bit for that effect using this offset value. The getEdgeOffset() method is // updated for the condense factor. int vertexToEdgeOffset = otherVertex.getEdgeOffset(); int exaggerationFactor = 1; @@ -629,20 +629,20 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // no need to check the 'y' value, as the end vertex is above/below this one if (vertexClipper.isClippingX(otherVertex, edgeX)) { - /* + /* Must route around this vertex - new points: -p1 - just above the intersection point -p2 - just past the left edge -p3 - just past the bottom of the vertex -p4 - back at the original x value - + | .___| | .-----. | | | | '-----' '---. - | + | */ // p1 - same x; y just above vertex @@ -650,19 +650,19 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y = vertexClipper.getTopOffset(otherVertex, vertexToEdgeOffset); articulations.add(new Point2D.Double(x, y)); - // Maybe merge points if they are too close together. Visually, many lines - // moving around intersecting vertices looks busy. When the intersecting + // Maybe merge points if they are too close together. Visually, many lines + // moving around intersecting vertices looks busy. When the intersecting // vertices are close together, we remove some of the articulations in order to // smooth out the edges. if (articulations.size() > 2) { - /* + /* The last articulation is the one added before this method was called, which - lies just below the intersecting vertex. The articulation before that is - the one that is the one that is sending the x value straight into the + lies just below the intersecting vertex. The articulation before that is + the one that is the one that is sending the x value straight into the intersecting vertex. Delete that point as well so that the entire edge is shifted to the outside of the intersecting vertex. This will get repeated - for each vertex that is intersecting. + for each vertex that is intersecting. */ Point2D previousArticulation = articulations.get(articulations.size() - 2); int closenessHeight = 50; @@ -720,7 +720,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Point2D first = new Point2D.Double(x, y1); articulations.add(first); - // loop second point - same y coord as destination; + // loop second point - same y coord as destination; // x is the col after the outermost dominated vertex Point2D endVertexPoint = end.center; @@ -733,6 +733,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { private void lighten(FGEdge e) { + if (!getLayoutOptions().useDimmedReturnEdges()) { + return; + } + // assumption: edges that move to the left in this layout are return flows that happen // after the code block has been executed. We dim those a bit so that they // produce less clutter. @@ -840,8 +844,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout { BlockCopy copy = (BlockCopy) child; StringBuilder buffy = new StringBuilder(); - buffy.append(printDepth(depth, depth + 1)).append(' ').append(ID).append( - " plain - ").append(copy.getRef()); + buffy.append(printDepth(depth, depth + 1)) + .append(' ') + .append(ID) + .append(" plain - ") + .append(copy.getRef()); debug(buffy.toString()); } @@ -958,7 +965,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { //================================================================================================== // Inner Classes -//================================================================================================== +//================================================================================================== /** * Encapsulates knowledge of edge direction (up/down, left/right) and uses that knowledge @@ -1060,7 +1067,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } /** - * A class that represents 2D information about the contained vertex, such as location, + * A class that represents 2D information about the contained vertex, such as location, * bounds, row and column of the layout grid. */ private class Vertex2d { @@ -1207,8 +1214,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int row = startRow; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { row = ((DecompilerBlockGraph) block).setRows(row); } @@ -1229,8 +1235,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { String getChildrenString(int depth) { StringBuilder buffy = new StringBuilder(); int childCount = 0; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { String blockName = block.getName(); @@ -1315,8 +1320,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override DecompilerBlock getBlock(FGVertex vertex) { // - // Note: we currently allow grouping in this layout. When we search for a vertex, - // we have to check each vertex inside of the given group *and* each vertex + // Note: we currently allow grouping in this layout. When we search for a vertex, + // we have to check each vertex inside of the given group *and* each vertex // inside of the vertex that belongs to this decompiler block. // if (vertex instanceof GroupedFunctionGraphVertex) { @@ -1447,9 +1452,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // The 'list' structure for children's nesting: // -all nodes are at the same level // - for (int i = 0; i < allChildren.size(); i++) { + for (DecompilerBlock block : allChildren) { int column = col; - DecompilerBlock block = allChildren.get(i); block.setCol(column); } @@ -1477,8 +1481,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // -each successive condition is another level nested // int column = col; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); column++; } @@ -1515,11 +1518,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // The 'do' structure for children's nesting: - // -all blocks nested + // -all blocks nested // int column = col + 1; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); } From faac13437e7b8f70616bc208c48a5e18925a0890 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 12 Mar 2021 15:29:11 -0500 Subject: [PATCH 087/140] GP-774 - fixed potential deadlock in dt db manager --- .../database/data/DataTypeManagerDB.java | 78 ++++++++++++------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index 5ae5403822..d13259b763 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -1695,34 +1695,41 @@ abstract public class DataTypeManagerDB implements DataTypeManager { @Override public void disassociate(DataType dataType) { - UniversalID oldDtID = dataType.getUniversalID(); - SourceArchive sourceArchive = dataType.getSourceArchive(); - sourceArchive = resolveSourceArchive(sourceArchive); - UniversalID id = sourceArchive == null ? DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID - : sourceArchive.getSourceArchiveID(); - if (id.equals(getUniversalID())) { - id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID; - } - if (id == DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID) { - // Already local data type so no source archive associated. - return; - } - // Set the source archive to null indicating no associated archive. - dataType.setSourceArchive(null); + lock.acquire(); + try { + UniversalID oldDtID = dataType.getUniversalID(); + SourceArchive sourceArchive = dataType.getSourceArchive(); + sourceArchive = resolveSourceArchive(sourceArchive); + UniversalID id = sourceArchive == null ? DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID + : sourceArchive.getSourceArchiveID(); + if (id.equals(getUniversalID())) { + id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID; + } + if (id == DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID) { + // Already local data type so no source archive associated. + return; + } - // Set the datatype's universal ID to a newly generated universal ID, - // since we no longer want the source archive data type's universal ID. - if (dataType instanceof DataTypeDB) { - DataTypeDB dt = (DataTypeDB) dataType; - dt.setUniversalID(UniversalIdGenerator.nextID()); + // Set the source archive to null indicating no associated archive. + dataType.setSourceArchive(null); + + // Set the datatype's universal ID to a newly generated universal ID, + // since we no longer want the source archive data type's universal ID. + if (dataType instanceof DataTypeDB) { + DataTypeDB dt = (DataTypeDB) dataType; + dt.setUniversalID(UniversalIdGenerator.nextID()); + } + + if (oldDtID != null) { + idsToDataTypeMap.removeDataType(sourceArchive, oldDtID); + } + + dataTypeChanged(dataType); } - - if (oldDtID != null) { - idsToDataTypeMap.removeDataType(sourceArchive, oldDtID); + finally { + lock.release(); } - - dataTypeChanged(dataType); } private Collection filterOutNonSourceSettableDataTypes( @@ -2694,9 +2701,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } try { creatingDataType++; - DBRecord record = functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(), - DEFAULT_DATATYPE_ID, funDef.hasVarArgs(), funDef.getGenericCallingConvention(), - sourceArchiveIdValue, universalIdValue, funDef.getLastChangeTime()); + DBRecord record = + functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(), + DEFAULT_DATATYPE_ID, funDef.hasVarArgs(), funDef.getGenericCallingConvention(), + sourceArchiveIdValue, universalIdValue, funDef.getLastChangeTime()); FunctionDefinitionDB funDefDb = new FunctionDefinitionDB(this, dtCache, functionDefAdapter, paramAdapter, record); @@ -3696,7 +3704,13 @@ abstract public class DataTypeManagerDB implements DataTypeManager { @Override public DataType getDataType(SourceArchive sourceArchive, UniversalID datatypeID) { UniversalID sourceID = sourceArchive == null ? null : sourceArchive.getSourceArchiveID(); - return idsToDataTypeMap.getDataType(sourceID, datatypeID); + lock.acquire(); + try { + return idsToDataTypeMap.getDataType(sourceID, datatypeID); + } + finally { + lock.release(); + } } @Override @@ -3829,7 +3843,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { monitor.setProgress(0); monitor.setMaximum(orderedComposites.size()); monitor.setMessage("Updating Datatype Sizes..."); - + int count = 0; for (CompositeDB c : orderedComposites) { monitor.checkCanceled(); @@ -4162,7 +4176,11 @@ abstract public class DataTypeManagerDB implements DataTypeManager { Map idMap = map.computeIfAbsent(sourceID, k -> new ConcurrentHashMap<>()); - final UniversalID sourceArchiveID = sourceID; + UniversalID sourceArchiveID = sourceID; + + // note: this call is atomic and has a lock on the 'idMap'. It may call to a method + // that requires a db lock. As such, the call to computeIfAbsent() must be + // made while holding the db lock. return idMap.computeIfAbsent(dataTypeID, k -> findDataTypeForIDs(sourceArchiveID, dataTypeID)); } From b9291831809bb671e6bc981e6dbaeed0e63f9774 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 12 Mar 2021 16:06:30 -0500 Subject: [PATCH 088/140] GP-771 - fixed regression that caused table header popup to stop working --- .../src/main/java/docking/DockableComponent.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java index c0963c8883..d485574655 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java @@ -151,6 +151,10 @@ public class DockableComponent extends JPanel implements ContainerListener { } private void showContextMenu(MouseEvent e) { + if (e.isConsumed()) { + return; + } + Component component = e.getComponent(); if (component == null) { return; // not sure this can happen @@ -190,7 +194,7 @@ public class DockableComponent extends JPanel implements ContainerListener { /** * Returns the component provider attached to this dockable component; null if this object * has been disposed - * + * * @return the provider */ public ComponentProvider getComponentProvider() { @@ -255,7 +259,7 @@ public class DockableComponent extends JPanel implements ContainerListener { public synchronized void dragEnter(DropTargetDragEvent dtde) { super.dragEnter(dtde); - // On Mac, sometimes this component is not showing, + // On Mac, sometimes this component is not showing, // which causes exception in the translate method. if (!isShowing()) { dtde.rejectDrag(); @@ -278,7 +282,7 @@ public class DockableComponent extends JPanel implements ContainerListener { public synchronized void dragOver(DropTargetDragEvent dtde) { super.dragOver(dtde); - // On Mac, sometimes this component is not showing, + // On Mac, sometimes this component is not showing, // which causes exception in the translate method. if (!isShowing()) { dtde.rejectDrag(); @@ -457,7 +461,7 @@ public class DockableComponent extends JPanel implements ContainerListener { private void componentSelected(Component component) { if (!component.isFocusable()) { - // In this case, Java will not change focus for us, so we need to tell the DWM to + // In this case, Java will not change focus for us, so we need to tell the DWM to // change the active DockableComponent requestFocus(); } From 4bd4dde6be76c9e515b0a3af76181230e5175104 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 12 Mar 2021 16:26:21 -0500 Subject: [PATCH 089/140] GP-775 - fixed Program Tree UI freeze when clicking with really large items on clipboard --- .../programtree/ProgramTreeActionManager.java | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java index 0b1cbca5e5..9fc43dcb7c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java @@ -267,8 +267,8 @@ class ProgramTreeActionManager implements ClipboardOwner { }; goToViewAction.setEnabled(false); - goToViewAction.setPopupMenuData( - new MenuData(new String[] { "Go To in View" }, null, "aview")); + goToViewAction + .setPopupMenuData(new MenuData(new String[] { "Go To in View" }, null, "aview")); list.add(goToViewAction); @@ -282,8 +282,8 @@ class ProgramTreeActionManager implements ClipboardOwner { }; removeViewAction.setEnabled(false); - removeViewAction.setPopupMenuData( - new MenuData(new String[] { "Remove from View" }, null, "aview")); + removeViewAction + .setPopupMenuData(new MenuData(new String[] { "Remove from View" }, null, "aview")); list.add(removeViewAction); @@ -297,8 +297,8 @@ class ProgramTreeActionManager implements ClipboardOwner { }; replaceViewAction.setEnabled(false); - replaceViewAction.setPopupMenuData( - new MenuData(new String[] { "Replace View" }, null, "aview")); + replaceViewAction + .setPopupMenuData(new MenuData(new String[] { "Replace View" }, null, "aview")); list.add(replaceViewAction); @@ -446,8 +446,8 @@ class ProgramTreeActionManager implements ClipboardOwner { collapseAction.setEnabled(false); // ACTIONS - auto generated - collapseAction.setPopupMenuData( - new MenuData(new String[] { "Collapse All" }, null, "expand")); + collapseAction + .setPopupMenuData(new MenuData(new String[] { "Collapse All" }, null, "expand")); list.add(collapseAction); @@ -577,8 +577,7 @@ class ProgramTreeActionManager implements ClipboardOwner { return; } - for (int i = 0; i < list.size(); i++) { - ProgramNode node = list.get(i); + for (ProgramNode node : list) { if (tree.getModel().getRoot() != node.getRoot()) { break; } @@ -979,8 +978,7 @@ class ProgramTreeActionManager implements ClipboardOwner { ArrayList list = tree.getSortedSelection(); CompoundCmd compCmd = new CompoundCmd("Merge with Parent"); String treeName = tree.getTreeName(); - for (int i = 0; i < list.size(); i++) { - ProgramNode node = list.get(i); + for (ProgramNode node : list) { tree.removeSelectionPath(node.getTreePath()); ProgramNode parentNode = (ProgramNode) node.getParent(); if (node.isModule() && parentNode != null) { @@ -1036,7 +1034,7 @@ class ProgramTreeActionManager implements ClipboardOwner { ProgramNode node = (ProgramNode) tree.getLastSelectedPathComponent(); // if the node has not been yet visited, then when the group is added via the - // command below, the new child node in the parent will not be found + // command below, the new child node in the parent will not be found node.visit(); String name = tree.getNewFolderName(); @@ -1242,14 +1240,15 @@ class ProgramTreeActionManager implements ClipboardOwner { @SuppressWarnings("unchecked") // the cast is safe, since we checked the flavor private boolean isPasteOk(ProgramNode destNode) { - Transferable t = null; + boolean isCutOperation = false; + Clipboard systemClipboard = GClipboard.getSystemClipboard(); + if (!systemClipboard.isDataFlavorAvailable(TreeTransferable.localTreeNodeFlavor)) { + return false; + } try { - t = GClipboard.getSystemClipboard().getContents(this); - if (t == null) { - return false; - } + // we will put items on the 'tempClipboard' when the cut action is executed Transferable temp = tempClipboard.getContents(this); isCutOperation = (temp != null); } @@ -1258,26 +1257,16 @@ class ProgramTreeActionManager implements ClipboardOwner { return false; } - if (!t.isDataFlavorSupported(TreeTransferable.localTreeNodeFlavor)) { - return false; - } - try { - if (!t.isDataFlavorSupported(TreeTransferable.localTreeNodeFlavor)) { - return false; - } List list = - (List) t.getTransferData(TreeTransferable.localTreeNodeFlavor); - + (List) systemClipboard.getData(TreeTransferable.localTreeNodeFlavor); if (list == null) { // SCR 7990--something bad has happened to the copy buffer return false; } boolean pasteEnabled = false; - for (int i = 0; i < list.size(); i++) { - ProgramNode pasteNode = list.get(i); - + for (ProgramNode pasteNode : list) { boolean pasteAllowed = pasteMgr.isPasteAllowed(destNode, pasteNode, isCutOperation); if (isCutOperation && !pasteAllowed) { // for cut operation all nodes must be able to be pasted at destNode From 4c77329bc5a811707db8d4d56bcef429bc972d95 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 15 Mar 2021 12:31:33 -0400 Subject: [PATCH 090/140] GP-779: Fixing issue with how GhidraJarBuilder finds extension points --- .../Base/src/main/java/ghidra/util/GhidraJarBuilder.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java index 7ded06d9a2..3b10795966 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java @@ -275,6 +275,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { sb.append(".*("); String between = ""; for (String suffix : suffixes) { + suffix = suffix.trim(); + if (suffix.isEmpty()) { + continue; + } sb.append(between); sb.append(suffix); between = "|"; From 81297343212b9a6167a39fedc80702f20cd25bde Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 15 Mar 2021 19:40:16 -0400 Subject: [PATCH 091/140] GP-775 - review fixes --- .../core/programtree/ProgramTreeActionManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java index 9fc43dcb7c..a437dab6d0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreeActionManager.java @@ -641,11 +641,12 @@ class ProgramTreeActionManager implements ClipboardOwner { try { Clipboard systemClipboard = GClipboard.getSystemClipboard(); - Transferable t = systemClipboard.getContents(this); - if (t == null) { + if (!systemClipboard.isDataFlavorAvailable(TreeTransferable.localTreeNodeFlavor)) { return; } - if (!t.isDataFlavorSupported(TreeTransferable.localTreeNodeFlavor)) { + + Object data = systemClipboard.getData(TreeTransferable.localTreeNodeFlavor); + if (data == null) { return; } @@ -658,9 +659,8 @@ class ProgramTreeActionManager implements ClipboardOwner { } private void doClearSystemClipboard(Clipboard systemClipboard) { - // for some reason setting the contents to null for the - // system clipboard causes a NullPointerException, so just - // set it with an empty transferable. + // for some reason setting the contents to null for the system clipboard causes a + // NullPointerException, so just set it with an empty transferable. TreeTransferable dummyContents = new TreeTransferable(new ProgramNode[0]); systemClipboard.setContents(dummyContents, (clipboard, contents) -> { // a dummy implementation that will not prevent this plugin from being From d1d0e8832ba90dcdcc704dfccada95953750a791 Mon Sep 17 00:00:00 2001 From: jmlagor <73651947+jmlagor@users.noreply.github.com> Date: Tue, 16 Mar 2021 09:20:50 -0400 Subject: [PATCH 092/140] Correct processing for pointers, function pointers, custom modifiers, ValueTyes, static methods, MethodRefs, MethodDefs, and PInvokes found in mixed binaries --- .../format/pe/cli/blobs/CliAbstractSig.java | 363 +++++++++++++----- .../bin/format/pe/cli/blobs/CliSigField.java | 4 +- .../format/pe/cli/blobs/CliSigMethodDef.java | 10 +- .../format/pe/cli/blobs/CliSigMethodRef.java | 15 +- .../format/pe/cli/methods/CliMethodDef.java | 97 +++-- .../format/pe/cli/streams/CliStreamBlob.java | 4 +- .../pe/cli/streams/CliStreamMetadata.java | 44 +-- .../format/pe/cli/tables/CliTableField.java | 13 +- .../pe/cli/tables/CliTableMethodDef.java | 316 ++++++++++++--- .../format/pe/cli/tables/CliTableParam.java | 21 +- .../pe/cli/tables/CliTableStandAloneSig.java | 5 +- 11 files changed, 671 insertions(+), 221 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java index e82c38b122..303b5138b7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java @@ -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. @@ -107,12 +107,12 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable ELEMENT_TYPE_VALUETYPE(0x11), ELEMENT_TYPE_VAR(0x13), // "Class type variable VAR" (0x16), - + ELEMENT_TYPE_MVAR(0x1e), // Method type variable MVAR - + ELEMENT_TYPE_INTERNAL(0x21), // Internal (generated internally, "will not be persisted in any way") ELEMENT_TYPE_MAX(0x22), - + */ switch (typeCode) { @@ -431,32 +431,95 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public class CliTypeFnPtr extends CliSigType { - private CliAbstractSig sig; - private boolean isDefSig; // true => MethodDef, false => MethodRef + private long dataOffset; + + private CliRetType retType; + private CliParam params[]; + private int sizeOfCount; + private byte flags; + private int genericParamCount; + private int sizeOfGenericCount; + + private int sentinelIndex; // SENTINEL is before the parameter index in this field + + private final int FNPTR_FLAGS_DEFAULT = 0x00; + private final int FNPTR_FLAGS_VARARG = 0x05; + private final int FNPTR_FLAGS_GENERIC = 0x10; + private final int FNPTR_FLAGS_HASTHIS = 0x20; + private final int FNPTR_FLAGS_EXPLICITTHIS = 0x40; public CliTypeFnPtr(BinaryReader reader, CliElementType typeCode) throws IOException { super(typeCode); - // TODO: MethodDef and MethodRef sig need to have static isX(reader) methods so I can tell the difference - //sig = new CliSigMethodRef(blob); // MethodRef is just Def plus possible sentinel and minus potential XORed args in the first byte + + sentinelIndex = -1; + + dataOffset = reader.getPointerIndex(); + + // Flags is similar to a MethodDef unless vararg is used. + flags = reader.readNextByte(); + + if ((flags & FNPTR_FLAGS_GENERIC) == FNPTR_FLAGS_GENERIC) { + long origIndex = reader.getPointerIndex(); + genericParamCount = decodeCompressedUnsignedInt(reader); + sizeOfGenericCount = (int) (reader.getPointerIndex() - origIndex); + } + + long origIndex = reader.getPointerIndex(); + int paramCount = decodeCompressedUnsignedInt(reader); + this.sizeOfCount = (int) (reader.getPointerIndex() - origIndex); + + try { + retType = new CliRetType(reader); + } + catch (InvalidInputException e) { + retType = null; + } + params = new CliParam[paramCount]; + + for (int i = 0; i < paramCount; i++) { + if (reader.peekNextByte() == CliElementType.ELEMENT_TYPE_SENTINEL.id()) { + reader.readNextByte(); + sentinelIndex = i; + } + try { + params[i] = new CliParam(reader); + } + catch (InvalidInputException e) { + params[i] = null; + } + } } @Override public String getRepresentation() { - return "FnPtr " + sig.getRepresentation(); + return "FnPtr " /*+ sig.getRepresentation()*/; } @Override public String getShortRepresentation() { - return "FnPtr " + sig.getShortRepresentation(); + return "FnPtr " /*+ sig.getShortRepresentation()*/; } @Override public DataType getDefinitionDataType() { - StructureDataType struct = new StructureDataType(new CategoryPath(PATH), "FnPtr", 0); - struct.add(CliTypeCodeDataType.dataType, "FnPtr", "FnPtr"); - struct.add(DWORD, "MethodDefOrRef", "index into blob heap"); + StructureDataType struct = + new StructureDataType(new CategoryPath(PATH), "FnPtr_" + dataOffset, 0); + struct.add(CliTypeCodeDataType.dataType, CliElementType.ELEMENT_TYPE_FNPTR.toString(), + ""); + struct.add(BYTE, "Flags", "ORed VARARG/GENERIC/HASTHIS/EXPLICITTHIS"); + + if (genericParamCount > 0) { + struct.add(getDataTypeForBytes(sizeOfGenericCount), "GenParamCount", + "Number of generic paramameters for the method"); + } + struct.add(getDataTypeForBytes(sizeOfCount), "ParamCount", + "Number of parameter types to follow RetType"); + struct.add(retType.getDefinitionDataType(), "RetType", null); + + for (int i = 0; i < params.length; i++) { + struct.add(params[i].getDefinitionDataType(), "Param" + i, null); + } return struct; - // TODO: Return the correct size of a signature reference (always 4B in this context perchance?) } } @@ -552,17 +615,18 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public class CliTypeVarOrMvar extends CliSigType { + private long dataOffset; private int number; private int numberBytes; public CliTypeVarOrMvar(BinaryReader reader, CliElementType typeCode) throws IOException { super(typeCode); - long origIndex = reader.getPointerIndex(); + dataOffset = reader.getPointerIndex(); number = decodeCompressedUnsignedInt(reader); long endIndex = reader.getPointerIndex(); - numberBytes = (int) (endIndex - origIndex); + numberBytes = (int) (endIndex - dataOffset); } @Override @@ -572,9 +636,9 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable @Override public DataType getDefinitionDataType() { - StructureDataType struct = - new StructureDataType(new CategoryPath(PATH), "VarOrMvar", 0); - struct.add(BYTE, "Type", "Var or Mvar"); + StructureDataType struct = new StructureDataType(new CategoryPath(PATH), + baseTypeCode.toString() + "_" + dataOffset, 0); + struct.add(CliTypeCodeDataType.dataType, baseTypeCode.toString(), ""); struct.add(getDataTypeForBytes(numberBytes), "number", null); return struct; } @@ -582,16 +646,24 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable public class CliTypePtr extends CliSigType { private List customMods = new ArrayList<>(); - private CliElementType typeCode; + private CliSigType type; + private long dataOffset; - public CliTypePtr(BinaryReader reader, CliElementType typeCode) throws IOException { + public CliTypePtr(BinaryReader reader, CliElementType typeCode) + throws IOException, InvalidInputException { super(typeCode); + dataOffset = reader.getPointerIndex(); + while (CliCustomMod.isCustomMod(reader)) { customMods.add(new CliCustomMod(reader)); } - typeCode = CliElementType.fromInt(reader.readNextByte()); + type = readCliType(reader); + } + + public CliSigType getType() { + return type; } @Override @@ -601,17 +673,22 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable modsRep += mod.toString() + ", "; } modsRep = modsRep.substring(0, modsRep.length() - 2); - return String.format("Ptr %s %s", modsRep, typeCode.toString()); + return String.format("Ptr %s %s", modsRep, type.toString()); } @Override public DataType getDefinitionDataType() { - StructureDataType struct = new StructureDataType(new CategoryPath(PATH), "Ptr", 0); - struct.add(CliTypeCodeDataType.dataType, "TypeCode", "Ptr"); + StructureDataType struct = new StructureDataType(new CategoryPath(PATH), + CliElementType.ELEMENT_TYPE_PTR.toString() + "_" + dataOffset, 0); + struct.add(CliTypeCodeDataType.dataType, CliElementType.ELEMENT_TYPE_PTR.toString(), + ""); + for (CliCustomMod mod : customMods) { struct.add(mod.getDefinitionDataType()); } - struct.add(CliTypeCodeDataType.dataType, "Type", "type or void"); + + struct.add(type.getDefinitionDataType(), type.baseTypeCode.toString(), ""); + return struct; } } @@ -682,6 +759,19 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable typeBytes = (int) (endIndex - origIndex); } + public CliTypeTable getTable() { + try { + return CliIndexTypeDefOrRef.getTableName(encodedType); + } + catch (InvalidInputException e) { + return null; + } + } + + public int getRowIndex() { + return CliIndexTypeDefOrRef.getRowIndex(encodedType); + } + @Override public String getRepresentation() { return "ValueType " + Integer.toHexString(encodedType); @@ -714,12 +804,17 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable @Override public DataType getDefinitionDataType() { + String tableName = getTable().name(); + StructureDataType struct = new StructureDataType(new CategoryPath(PATH), "ValueType", 0); struct.add(CliTypeCodeDataType.dataType, "ValueType", "ValueType"); - struct.add(getDataTypeForBytes(typeBytes), "Type", "TypeDefOrRefOrSpecEncoded"); + struct.add(getDataTypeForBytes(typeBytes), "TypeDefOrRefEncoded", + tableName + ": Row 0x" + Integer.toHexString(getRowIndex())); + return struct; } + } public CliSigType readCliType(BinaryReader reader) throws IOException, InvalidInputException { @@ -761,10 +856,11 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } } - // The CustomMod signature part contains a required CMOD option (CMOD_OPT or CMOD_REQD) then a compressed TypeDefOrRefOrSpecEncoded - public static class CliCustomMod { + // The CustomMod signature part contains a required CMOD + // option (CMOD_OPT or CMOD_REQD) then a compressed TypeDefOrRefOrSpecEncoded + public static class CliCustomMod implements CliRepresentable { private CliElementType cmod; - private int typeEncoded; + private int encodedType; private int sizeOfCount; public static boolean isCustomMod(BinaryReader reader) throws IOException { @@ -776,7 +872,7 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable cmod = CliElementType.fromInt(reader.readNextByte()); long origIndex = reader.getPointerIndex(); - typeEncoded = decodeCompressedUnsignedInt(reader); + encodedType = decodeCompressedUnsignedInt(reader); long endIndex = reader.getPointerIndex(); sizeOfCount = (int) (endIndex - origIndex); @@ -787,12 +883,12 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public int getTypeEncoded() { - return typeEncoded; + return encodedType; } public CliTypeTable getTable() { try { - return CliIndexTypeDefOrRef.getTableName(typeEncoded); + return CliIndexTypeDefOrRef.getTableName(encodedType); } catch (InvalidInputException e) { return null; @@ -800,7 +896,7 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public int getRowIndex() { - return CliIndexTypeDefOrRef.getRowIndex(typeEncoded); + return CliIndexTypeDefOrRef.getRowIndex(encodedType); } public CliAbstractTableRow getRow(CliStreamMetadata stream) { @@ -808,25 +904,40 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public DataType getDefinitionDataType() { - StructureDataType struct = new StructureDataType(new CategoryPath(PATH), - CliCustomMod.class.getSimpleName(), 0); - struct.add(BYTE, "CMOD", "CMOD_OPT or CMOD_REQD"); - struct.add(getDataTypeForBytes(this.sizeOfCount), "Type", - "TypeDefOrRefOrSpec encoded type"); + StructureDataType struct = + new StructureDataType(new CategoryPath(PATH), "CustomMod", 0); + + String tableName = getTable().name(); + + struct.add(CliTypeCodeDataType.dataType, cmod.toString(), null); + struct.add(getDataTypeForBytes(this.sizeOfCount), "TypeDefOrRefEncoded", + tableName + ": Row 0x" + Integer.toHexString(getRowIndex())); return struct; } + @Override public String getRepresentation(CliStreamMetadata stream) { return String.format("%s %s", cmod.toString(), getRow(stream)); } + @Override public String getRepresentation() { - return String.format("%s %x", cmod.toString(), typeEncoded); + return String.format("%s %x", cmod.toString(), encodedType); + } + + @Override + public String getShortRepresentation() { + return getRepresentation(); + } + + @Override + public String getShortRepresentation(CliStreamMetadata stream) { + return getRepresentation(stream); } } // The only possible constraint is ELEMENT_TYPE_PINNED (CliTypeCode.Pinned) - public static class CliConstraint { + public static class CliConstraint implements CliRepresentable { private CliElementType constraint; public static boolean isConstraint(BinaryReader reader) throws IOException { @@ -841,6 +952,7 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable return constraint; } + @Override public String getRepresentation() { if (constraint == CliElementType.ELEMENT_TYPE_PINNED) { return constraint.toString(); @@ -848,36 +960,96 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable return String.format("Invalid Constraint (%s - %x)", constraint.toString(), constraint.id()); } + + @Override + public String getShortRepresentation() { + return getRepresentation(); + } + + @Override + public String getRepresentation(CliStreamMetadata stream) { + return getRepresentation(); + } + + @Override + public String getShortRepresentation(CliStreamMetadata stream) { + return getRepresentation(); + } + } + + // The only possible result is ELEMENT_TYPE_BYREF + public static class CliByRef implements CliRepresentable { + private CliElementType byRef; + + public static boolean isByRef(BinaryReader reader) throws IOException { + return (reader.peekNextByte() == CliElementType.ELEMENT_TYPE_BYREF.id()); + } + + public CliByRef(BinaryReader reader) throws IOException { + byRef = CliElementType.fromInt(reader.readNextByte()); + } + + public CliElementType getByRef() { + return byRef; + } + + @Override + public String getRepresentation() { + if (byRef == CliElementType.ELEMENT_TYPE_BYREF) { + return byRef.toString(); + } + return String.format("Invalid ByRef (%s - %x)", byRef.toString(), byRef.id()); + } + + @Override + public String getShortRepresentation() { + return getRepresentation(); + } + + @Override + public String getRepresentation(CliStreamMetadata stream) { + return getRepresentation(); + } + + @Override + public String getShortRepresentation(CliStreamMetadata stream) { + return getRepresentation(); + } } public class CliTypeBase implements CliRepresentable { - private List customMods = new ArrayList<>(); - private boolean constraint = false; - private boolean byRef = false; + private List modifiers = new ArrayList<>(); + private CliSigType type; + private long dataOffset = 0; private boolean isVoidAllowed = false; public CliTypeBase(BinaryReader reader, boolean isRetType) throws IOException, InvalidInputException { + dataOffset = reader.getPointerIndex(); + this.isVoidAllowed = isRetType; - // Get any custom modifiers - while (CliCustomMod.isCustomMod(reader)) { - customMods.add(new CliCustomMod(reader)); - } + // Check for any of the modifiers, which can repeat out of order + // before encountering the base type + while (CliCustomMod.isCustomMod(reader) || CliConstraint.isConstraint(reader) || + CliByRef.isByRef(reader)) { - // Check to see if it's a constrained variable - if (CliConstraint.isConstraint(reader)) { - constraint = true; - reader.readNextByte(); - } + // Get any custom modifiers + while (CliCustomMod.isCustomMod(reader)) { + modifiers.add(new CliCustomMod(reader)); + } - // Check to see if it's a ByRef - byte byRefCheck = reader.peekNextByte(); - if (byRefCheck == CliElementType.ELEMENT_TYPE_BYREF.id()) { - byRef = true; - reader.readNextByte(); + // Check to see if it's a constrained variable + if (CliConstraint.isConstraint(reader)) { + modifiers.add(new CliConstraint(reader)); + } + + // Check to see if it's a ByRef + if (CliByRef.isByRef(reader)) { + modifiers.add(new CliByRef(reader)); + } } type = readCliType(reader); @@ -888,34 +1060,48 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public List getCustomMods() { + List customMods = new ArrayList(); + for (CliRepresentable mod : modifiers) { + if (mod instanceof CliCustomMod) { + customMods.add((CliCustomMod) mod); + } + } + return customMods; } public boolean isByRef() { - return byRef; + for (CliRepresentable mod : modifiers) { + if (mod instanceof CliByRef) { + return true; + } + } + return false; } public boolean isConstrained() { - return constraint; + for (CliRepresentable mod : modifiers) { + if (mod instanceof CliConstraint) { + return true; + } + } + return false; } private String getRepresentationCommon(CliStreamMetadata stream, boolean shortRep) { String rep = ""; - for (CliCustomMod mod : customMods) { - rep += mod.getRepresentation() + "; "; - } - - if (customMods.size() > 0) { - rep = rep.substring(0, rep.length() - 2) + " "; - } - - if (constraint) { - rep += "constrained "; - } - - if (byRef) { - rep += "byref "; + for (CliRepresentable mod : modifiers) { + if (mod instanceof CliCustomMod) { + CliCustomMod customMod = (CliCustomMod) mod; + rep += customMod.getRepresentation() + "; "; + } + else if (mod instanceof CliConstraint) { + rep += "constrained "; + } + else if (mod instanceof CliByRef) { + rep += "byref "; + } } // The one special case value we have is the SENTINEL, which @@ -952,20 +1138,25 @@ public abstract class CliAbstractSig extends CliBlob implements CliRepresentable } public DataType getDefinitionDataType() { - StructureDataType struct = new StructureDataType(new CategoryPath(PATH), "Type", 0); + StructureDataType struct = + new StructureDataType(new CategoryPath(PATH), "Type_" + dataOffset, 0); - for (CliCustomMod mod : customMods) { - struct.add(mod.getDefinitionDataType(), "CustomMod", null); + for (CliRepresentable mod : modifiers) { + if (mod instanceof CliCustomMod) { + CliCustomMod customMod = (CliCustomMod) mod; + struct.add(customMod.getDefinitionDataType(), "CustomMod", null); + } + else if (mod instanceof CliConstraint) { + struct.add(CliTypeCodeDataType.dataType, + CliElementType.ELEMENT_TYPE_PINNED.toString(), "Constrained"); + } + else if (mod instanceof CliByRef) { + struct.add(CliTypeCodeDataType.dataType, + CliElementType.ELEMENT_TYPE_BYREF.toString(), "By Reference"); + } } - if (constraint) { - struct.add(BYTE, "CONSTRAINT", "Constrained"); - } - - if (byRef) { - struct.add(BYTE, "BYREF", "By reference"); - } - struct.add(type.getDefinitionDataType(), "Type", null); + struct.add(type.getDefinitionDataType(), type.baseTypeCode.toString(), null); return struct; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigField.java index 22a4331886..19f00c6ff2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigField.java @@ -26,12 +26,14 @@ import ghidra.util.exception.InvalidInputException; public class CliSigField extends CliAbstractSig { private CliParam type; + private long dataOffset; private static final byte CLISIGFIELD_PROLOG = 0x06; public CliSigField(CliBlob blob) throws IOException { super(blob); BinaryReader reader = getContentsReader(); + dataOffset = reader.getPointerIndex(); byte prolog = reader.readNextByte(); if (prolog != CLISIGFIELD_PROLOG) { @@ -67,7 +69,7 @@ public class CliSigField extends CliAbstractSig { public DataType getContentsDataType() { StructureDataType struct = new StructureDataType(new CategoryPath(PATH), getName(), 0); struct.add(BYTE, "FIELD", "Magic (0x06)"); - struct.add(type.getDefinitionDataType(), "Type", null); + struct.add(type.getDefinitionDataType(), type.getType().baseTypeCode.toString(), null); return struct; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodDef.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodDef.java index 6ffb69f5d9..687ba588f8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodDef.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodDef.java @@ -85,17 +85,19 @@ public class CliSigMethodDef extends CliAbstractSig { @Override public DataType getContentsDataType() { StructureDataType struct = new StructureDataType(new CategoryPath(PATH), getName(), 0); - struct.add(BYTE, "flags", "ORed calling convention and THIS presence"); // TODO: enum + struct.add(BYTE, "Flags", "ORed VARARG/GENERIC/HASTHIS/EXPLICITTHIS"); // TODO: enum if (genericParamCount > 0) { struct.add(getDataTypeForBytes(sizeOfGenericCount), "GenParamCount", "Number of generic paramameters for the method"); } struct.add(getDataTypeForBytes(sizeOfCount), "Count", - "Number of param types to follow RetType"); + "Number of parameter types to follow RetType"); struct.add(retType.getDefinitionDataType(), "RetType", null); - for (CliParam param : params) { - struct.add(param.getDefinitionDataType(), null, null); + + for (int i = 0; i < params.length; i++) { + struct.add(params[i].getDefinitionDataType(), "Param" + i, null); } + return struct; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodRef.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodRef.java index 7e423ff732..c5e3734dbb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodRef.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliSigMethodRef.java @@ -23,7 +23,7 @@ import ghidra.program.model.data.*; import ghidra.util.exception.InvalidInputException; public class CliSigMethodRef extends CliAbstractSig { - + private long dataOffset; private CliRetType retType; private CliParam params[]; private int sizeOfCount; @@ -45,6 +45,8 @@ public class CliSigMethodRef extends CliAbstractSig { // Flags is similar to a MethodDef unless vararg is used. BinaryReader reader = getContentsReader(); + dataOffset = reader.getPointerIndex(); + flags = reader.readNextByte(); if ((flags & METHODREFSIG_FLAGS_GENERIC) == METHODREFSIG_FLAGS_GENERIC) { @@ -90,16 +92,21 @@ public class CliSigMethodRef extends CliAbstractSig { @Override public DataType getContentsDataType() { StructureDataType struct = new StructureDataType(new CategoryPath(PATH), getName(), 0); - struct.add(BYTE, "FirstByte", "ORed VARARG and HASTHIS/EXPLICITTHIS"); + struct.add(BYTE, "Flags", "ORed VARARG/GENERIC/HASTHIS/EXPLICITTHIS"); if (genericParamCount > 0) { struct.add(getDataTypeForBytes(sizeOfGenericCount), "GenParamCount", "Number of generic paramameters for the method"); } struct.add(getDataTypeForBytes(sizeOfCount), "ParamCount", - "Number of param types to follow RetType"); + "Number of parameter types to follow RetType"); struct.add(retType.getDefinitionDataType(), "RetType", null); for (int i = 0; i < params.length; i++) { - struct.add(params[i].getDefinitionDataType(), "Type" + i, null); + if (sentinelIndex == i) { + struct.add(CliTypeCodeDataType.dataType, + CliElementType.ELEMENT_TYPE_SENTINEL.toString(), "SENTINEL"); + } + + struct.add(params[i].getDefinitionDataType(), "Param" + i, null); } return struct; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/methods/CliMethodDef.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/methods/CliMethodDef.java index a8186c6ecb..fb63c99122 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/methods/CliMethodDef.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/methods/CliMethodDef.java @@ -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,69 +24,81 @@ import ghidra.program.model.data.*; import ghidra.util.exception.DuplicateNameException; public class CliMethodDef implements StructConverter { - + public static final String PATH = "/PE/CLI/Methods/MethodDefs"; private Address addr; - private boolean isFatHeader; - private boolean hasMoreSections; - private boolean initLocals; + public enum HeaderFormat { + Fat, Tiny + } + + private int headerFlags; + private HeaderFormat headerFormat; + private int headerSize; // Size of this header private int maxStack; // Max number of items on operand stack private int methodSize; // Size of method body (code) private int localVarSigTok; - + + private static final int CLIMETHODDEF_HEADER_FLAGS_SHIFT = 0x08; + private static final int CLIMETHODDEF_HEADER_FLAGS_MASK = 0x0FFF; + private static final int CLIMETHODDEF_HEADER_SIZE_SHIFT = 0x0C; + private static final int CLIMETHODDEF_HEADER_SIZE_FAT_MULTIPLIER = 0x04; + private static final byte CorILMethod_TinyFormat = 0x2; private static final byte CorILMethod_FatFormat = 0x3; private static final byte CorILMethod_MoreSects = 0x8; private static final byte CorILMethod_InitLocals = 0x10; - + public CliMethodDef(Address addr, BinaryReader reader) throws IOException { this.addr = addr; // Read first byte, see if tiny or fat. - byte one = reader.readNextByte(); - if ((one & CorILMethod_FatFormat) == CorILMethod_FatFormat) { - isFatHeader = true; - if ((one & CorILMethod_MoreSects) == CorILMethod_MoreSects) - hasMoreSections = true; - if ((one & CorILMethod_InitLocals) == CorILMethod_InitLocals) - initLocals = true; - byte two = reader.readNextByte(); // TODO: need to read byte two? Seems to only have header length (in the wrong order?? >_<) + int firstByte = reader.readNextUnsignedByte(); + if ((firstByte & CorILMethod_FatFormat) == CorILMethod_FatFormat) { + headerFormat = HeaderFormat.Fat; + + // The header flags are stored across 12 bits, the top 4 bits + // indicate the size of the header + headerFlags = + (firstByte << CLIMETHODDEF_HEADER_FLAGS_SHIFT) + reader.readNextUnsignedByte(); + headerSize = headerFlags >> CLIMETHODDEF_HEADER_SIZE_SHIFT; + headerFlags = (headerFlags & CLIMETHODDEF_HEADER_FLAGS_MASK); + + // The raw header size bits indicate: "Size of this header + // expressed as the count of 4-bytes integers occupied." + headerSize = headerSize * CLIMETHODDEF_HEADER_SIZE_FAT_MULTIPLIER; + maxStack = reader.readNextShort(); methodSize = reader.readNextInt(); localVarSigTok = reader.readNextInt(); } - else if ((one & CorILMethod_TinyFormat) == CorILMethod_TinyFormat) { - isFatHeader = false; - hasMoreSections = false; - initLocals = false; + else if ((firstByte & CorILMethod_TinyFormat) == CorILMethod_TinyFormat) { + headerFormat = HeaderFormat.Tiny; + headerSize = 1; + headerFlags = 0; maxStack = 8; - methodSize = (((one & ~0x3) & 0xff) >> 2); // Mask off first 2 bits, right shift to get 6 length bits. 0xff mask to convert to right sign. + methodSize = (((firstByte & ~0x3) & 0xff) >> 2); // Mask off first 2 bits, right shift to get 6 length bits. 0xff mask to convert to right sign. } } - - private void fillTinyHeaderType(Structure struct) { - struct.add(BYTE, "Size+Flags", "L.S. Bits 0:1 Flags, Bits 2:7 Size of method in Bytes"); - } - - private void fillFatHeaderType(Structure struct) { - struct.add( WORD, "Size+Flags", "L.S. Bits 0:3 Size of hdr in B, Bits 4:15 Flags"); - struct.add( WORD, "MaxStack", "Maximum number of items on the operand stack"); - struct.add(DWORD, "CodeSize", "Size of actual method body in B"); - struct.add(DWORD, "LocalVarSigTok", "Signature for the local variables of the method. 0 means no locals. References standalone signature in Metadata tables, which references #Blob heap."); - } - + @Override public DataType toDataType() throws DuplicateNameException, IOException { - StructureDataType struct = - new StructureDataType(new CategoryPath(PATH), "MethodDefHdr_" + addr, 0); - if (isFatHeader) { - fillFatHeaderType(struct); + StructureDataType struct; + + if (headerFormat == HeaderFormat.Fat) { + struct = new StructureDataType(new CategoryPath(PATH), "MethodDefHdr_Fat", 0); + struct.add(WORD, "Size+Flags", "L.S. Bits 0:3 Size of hdr in bytes, Bits 4:15 Flags"); + struct.add(WORD, "MaxStack", "Maximum number of items on the operand stack"); + struct.add(DWORD, "CodeSize", "Size of actual method body in bytes"); + struct.add(DWORD, "LocalVarSigTok", + "Signature for the local variables of the method. 0 means no locals. References standalone signature in Metadata tables, which references #Blob heap."); } else { - fillTinyHeaderType(struct); + struct = new StructureDataType(new CategoryPath(PATH), "MethodDefHdr_Tiny", 0); + struct.add(BYTE, "Size+Flags", "L.S. Bits 0:1 Flags, Bits 2:7 Size of method in Bytes"); } + return struct; } @@ -95,7 +107,14 @@ public class CliMethodDef implements StructConverter { } public boolean hasMoreSections() { - return hasMoreSections; + return (headerFlags & CorILMethod_MoreSects) == CorILMethod_MoreSects; } + public boolean hasLocals() { + return (headerFlags & CorILMethod_InitLocals) == CorILMethod_InitLocals; + } + + public HeaderFormat getHeaderFormat() { + return headerFormat; + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java index 7432ac7ed7..87b3ea13f2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamBlob.java @@ -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. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java index 65d8faf138..5b6b437656 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliStreamMetadata.java @@ -35,7 +35,7 @@ import ghidra.util.task.TaskMonitor; /** * The Metadata stream is giant and complicated. It is made up of {@link CliAbstractTable}s. - * + * * @see CliTypeTable */ public class CliStreamMetadata extends CliAbstractStream { @@ -55,7 +55,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the name of this stream. - * + * * @return The name of this stream. */ public static String getName() { @@ -64,13 +64,13 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Creates a new Metadata stream. - * + * * @param header The stream header associated with this stream. * @param guidStream The GUID stream. * @param userStringsStream The user strings stream. * @param stringsStream The strings stream. * @param blobStream The blob stream. - * @param fileOffset The file offset where this stream starts. + * @param fileOffset The file offset where this stream starts. * @param rva The relative virtual address where this stream starts. * @param reader A reader that is set to the start of the stream. * @throws IOException if there is a problem reading the stream. @@ -133,7 +133,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the GUID stream. - * + * * @return The GUID stream. Could be null if one doesn't exist. */ public CliStreamGuid getGuidStream() { @@ -142,7 +142,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the user strings stream. - * + * * @return The user strings stream. Could be null if one doesn't exist. */ public CliStreamUserStrings getUserStringsStream() { @@ -151,7 +151,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the strings stream. - * + * * @return The strings stream. Could be null if one doesn't exist. */ public CliStreamStrings getStringsStream() { @@ -160,7 +160,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the blob stream. - * + * * @return The blob stream. Could be null if one doesn't exist. */ public CliStreamBlob getBlobStream() { @@ -170,7 +170,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Creates a new {@link CliAbstractTable} from the table at the current reader index * with the given table type. - * + * * @param tableType The type of table to create. * @return A new table with the given type. Could be null if we don't support the table type. * @throws IOException if there was an issue reading the new table. @@ -300,7 +300,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the major version. - * + * * @return The major version. */ public short getMajorVersion() { @@ -309,7 +309,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the minor version. - * + * * @return The minor version. */ public short getMinorVersion() { @@ -318,7 +318,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the sorted field. - * + * * @return The sorted field. */ public long getSorted() { @@ -327,7 +327,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the valid field. - * + * * @return The valid field. */ public long getValid() { @@ -336,7 +336,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the table with the provided table type from the metadata stream. - * + * * @param tableType The type of table to get. * @return The table with the provided table type. Could be null if it doesn't exist. */ @@ -360,7 +360,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the table with the provided table type id from the metadata stream. - * + * * @param tableId The id of the table type to get. * @return The table with the provided table id. Could be null if it doesn't exist. */ @@ -370,9 +370,9 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the number of rows in the table with the given table type. - * + * * @param tableType The type of table to get the number of rows of. - * @return The number of rows in the table with the given table type. Could be 0 if + * @return The number of rows in the table with the given table type. Could be 0 if * the table of the given type was not found. */ public int getNumberRowsForTable(CliTypeTable tableType) { @@ -383,7 +383,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the data type of the index into the string stream. Will be either * {@link DWordDataType} or {@link WordDataType}. - * + * * @return The data type of the index into the string stream. */ public DataType getStringIndexDataType() { @@ -393,7 +393,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the data type of the index into the GUID stream. Will be either * {@link DWordDataType} or {@link WordDataType}. - * + * * @return The data type of the index into the string stream. */ public DataType getGuidIndexDataType() { @@ -403,7 +403,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the data type of the index into the Blob stream. Will be either * {@link DWordDataType} or {@link WordDataType}. - * + * * @return The data type of the index into the string stream. */ public DataType getBlobIndexDataType() { @@ -413,7 +413,7 @@ public class CliStreamMetadata extends CliAbstractStream { /** * Gets the data type of the index into a metadata table. Will be either * {@link DWordDataType} or {@link WordDataType}. - * + * * @return The data type of the index into the string stream. */ public DataType getTableIndexDataType(CliTypeTable table) { @@ -435,7 +435,7 @@ public class CliStreamMetadata extends CliAbstractStream { table.markup(program, isBinary, monitor, log, ntHeader); } catch (Exception e) { - Msg.error(this, "Failed to markup " + table); + Msg.error(this, "Failed to markup " + table + ": " + e.getMessage()); } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableField.java index 93f2102206..2122af05cc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableField.java @@ -30,6 +30,7 @@ import ghidra.program.model.data.CategoryPath; import ghidra.program.model.data.StructureDataType; import ghidra.program.model.listing.Program; import ghidra.program.model.util.CodeUnitInsertionException; +import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; import ghidra.util.task.TaskMonitor; @@ -100,16 +101,24 @@ public class CliTableField extends CliAbstractTable { public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log, NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException, IOException { + int fieldRowIndex = 0; for (CliAbstractTableRow row : rows) { CliFieldRow fieldRow = (CliFieldRow) row; + fieldRowIndex++; - // Create FieldSig object and bookmark it + // Create FieldSig object Address sigAddr = CliAbstractStream.getStreamMarkupAddress(program, isBinary, monitor, log, ntHeader, metadataStream.getBlobStream(), fieldRow.sigIndex); CliSigField fieldSig = new CliSigField(metadataStream.getBlobStream().getBlob(fieldRow.sigIndex)); - metadataStream.getBlobStream().updateBlob(fieldSig, sigAddr, program); + + if (!metadataStream.getBlobStream().updateBlob(fieldSig, sigAddr, program)) { + Msg.warn(CliTableField.class, + "Couldn't update FieldSig blob " + + metadataStream.getStringsStream().getString(fieldRow.nameIndex) + + " at Field table index " + fieldRowIndex); + } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableMethodDef.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableMethodDef.java index 4ea7aaf787..f6a841479a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableMethodDef.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableMethodDef.java @@ -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,14 +16,13 @@ package ghidra.app.util.bin.format.pe.cli.tables; import java.io.IOException; -import java.util.Arrays; -import java.util.List; +import java.util.*; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.MemoryByteProvider; import ghidra.app.util.bin.format.pe.NTHeader; import ghidra.app.util.bin.format.pe.PeUtils; -import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.CliParam; +import ghidra.app.util.bin.format.pe.cli.blobs.CliAbstractSig.*; import ghidra.app.util.bin.format.pe.cli.blobs.CliBlob; import ghidra.app.util.bin.format.pe.cli.blobs.CliSigMethodDef; import ghidra.app.util.bin.format.pe.cli.methods.CliMethodDef; @@ -31,6 +30,8 @@ import ghidra.app.util.bin.format.pe.cli.methods.CliMethodExtraSections; import ghidra.app.util.bin.format.pe.cli.streams.CliAbstractStream; import ghidra.app.util.bin.format.pe.cli.streams.CliStreamMetadata; import ghidra.app.util.bin.format.pe.cli.tables.CliTableParam.CliParamRow; +import ghidra.app.util.bin.format.pe.cli.tables.CliTableTypeDef.CliTypeDefRow; +import ghidra.app.util.bin.format.pe.cli.tables.CliTableTypeRef.CliTypeRefRow; import ghidra.app.util.bin.format.pe.cli.tables.flags.CliFlags.CliEnumMethodAttributes; import ghidra.app.util.bin.format.pe.cli.tables.flags.CliFlags.CliEnumMethodImplAttributes; import ghidra.app.util.importer.MessageLog; @@ -40,6 +41,7 @@ import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.listing.Function.FunctionUpdateType; import ghidra.program.model.symbol.SourceType; +import ghidra.program.model.symbol.SymbolUtilities; import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; @@ -52,6 +54,8 @@ import ghidra.util.task.TaskMonitor; */ public class CliTableMethodDef extends CliAbstractTable { + private static final int CLITABLEMETHODDEF_PINVOKE_JUMP_LENGTH = 0x06; + public class CliMethodDefRow extends CliAbstractTableRow { public int RVA; public short ImplFlags; // MethodImplAttributes @@ -63,6 +67,42 @@ public class CliTableMethodDef extends CliAbstractTable { private static final int NEXT_ROW_PARAM_INIT_VALUE = -1; private int nextRowParamIndex = NEXT_ROW_PARAM_INIT_VALUE; + private static final int METHODIMPLATTRIBUTES_CODETYPE_IL = 0x00; + private static final int METHODIMPLATTRIBUTES_CODETYPE_NATIVE = 0x01; + private static final int METHODIMPLATTRIBUTES_CODETYPE_OPTIL = 0x02; + private static final int METHODIMPLATTRIBUTES_CODETYPE_RUNTIME = 0x03; + private static final int METHODIMPLATTRIBUTES_MANAGED_MANAGED = 0x00; + private static final int METHODIMPLATTRIBUTES_MANAGED_UNMANAGED = 0x04; + private static final int METHODIMPLATTRIBUTES_FORWARDREF = 0x10; + private static final int METHODIMPLATTRIBUTES_PRESERVESIG = 0x80; + private static final int METHODIMPLATTRIBUTES_INTERNALCALL = 0x1000; + private static final int METHODIMPLATTRIBUTES_SYNCHRONIZED = 0x20; + private static final int METHODIMPLATTRIBUTES_NOINLINING = 0x08; + private static final int METHODIMPLATTRIBUTES_AGGRESSIVEINLINING = 0x1000; + private static final int METHODIMPLATTRIBUTES_MAXMETHODIMPLVAL = 0xffff; + + private static final int METHODATTRIBUTES_MEMBERACCESS_COMPILERCONTROLLED = 0x00; + private static final int METHODATTRIBUTES_MEMBERACCESS_PRIVATE = 0x01; + private static final int METHODATTRIBUTES_MEMBERACCESS_FAMANDASSEM = 0x02; + private static final int METHODATTRIBUTES_MEMBERACCESS_ASSEM = 0x03; + private static final int METHODATTRIBUTES_MEMBERACCESS_FAMILY = 0x04; + private static final int METHODATTRIBUTES_MEMBERACCESS_FAMORASSEM = 0x05; + private static final int METHODATTRIBUTES_MEMBERACCESS_PUBLIC = 0x06; + private static final int METHODATTRIBUTES_STATIC = 0x10; + private static final int METHODATTRIBUTES_FINAL = 0x20; + private static final int METHODATTRIBUTES_VIRTUAL = 0x40; + private static final int METHODATTRIBUTES_HIDEBYSIG = 0x80; + private static final int METHODATTRIBUTES_VTABLELAYOUT_REUSESLOT = 0x0000; + private static final int METHODATTRIBUTES_VTABLELAYOUT_NEWSLOT = 0x0100; + private static final int METHODATTRIBUTES_STRICT = 0x0200; + private static final int METHODATTRIBUTES_ABSTRACT = 0x0400; + private static final int METHODATTRIBUTES_SPECIALNAME = 0x0800; + private static final int METHODATTRIBUTES_PINVOKEIMPL = 0x2000; + private static final int METHODATTRIBUTES_UNMANAGEDEXPORT = 0x08; + private static final int METHODATTRIBUTES_RTSPECIALNAME = 0x1000; + private static final int METHODATTRIBUTES_HASSECURITY = 0x4000; + private static final int METHODATTRIBUTES_REQUIRESECOBJECT = 0x8000; + public CliMethodDefRow(int rva, short implFlags, short flags, int nameIndex, int sigIndex, int paramIndex) { this.RVA = rva; @@ -141,6 +181,28 @@ public class CliTableMethodDef extends CliAbstractTable { CliEnumMethodImplAttributes.dataType.getName(ImplFlags & 0xffff), CliEnumMethodAttributes.dataType.getName(Flags & 0xffff)); } + + // Static functions have four parameters but the first is an implied + // pointer to the object they're associated with. It's not in the + // ParameterTable and looking for the extra parameter will walk + // you into the parameter of another function. + boolean isStatic() { + return (Flags & METHODATTRIBUTES_STATIC) == METHODATTRIBUTES_STATIC; + } + + boolean isPInvokeImpl() { + return (Flags & METHODATTRIBUTES_PINVOKEIMPL) == METHODATTRIBUTES_PINVOKEIMPL; + } + + boolean isNative() { + return (ImplFlags & + METHODIMPLATTRIBUTES_CODETYPE_NATIVE) == METHODIMPLATTRIBUTES_CODETYPE_NATIVE; + } + + boolean isManaged() { + return (ImplFlags & + METHODIMPLATTRIBUTES_CODETYPE_IL) == METHODIMPLATTRIBUTES_CODETYPE_IL; + } } public CliTableMethodDef(BinaryReader reader, CliStreamMetadata stream, CliTypeTable tableId) @@ -159,7 +221,7 @@ public class CliTableMethodDef extends CliAbstractTable { } lastRow = row; } - reader.setPointerIndex(this.readerOffset); // TODO: why do this, also elsewhere + reader.setPointerIndex(this.readerOffset); } @Override @@ -167,54 +229,64 @@ public class CliTableMethodDef extends CliAbstractTable { NTHeader ntHeader) throws DuplicateNameException, CodeUnitInsertionException, IOException { - int rvaZero = 0; - + int methodRowIndex = 0; for (CliAbstractTableRow method : rows) { + methodRowIndex++; + CliMethodDefRow methodRow = (CliMethodDefRow) method; // This indicates the method is abstract, runtime, or PInvokeImpl if (methodRow.RVA == 0) { - rvaZero++; continue; } Address addr = PeUtils.getMarkupAddress(program, isBinary, ntHeader, methodRow.RVA); + Address startAddr = addr; + Address endAddr = addr; - // Create MethodDef at this RVA - BinaryReader reader = - new BinaryReader(new MemoryByteProvider(program.getMemory(), addr), - !program.getMemory().isBigEndian()); - CliMethodDef methodDef = new CliMethodDef(addr, reader); - - PeUtils.createData(program, addr, methodDef.toDataType(), log); - - // Get the function's address space, default to zero-length just in case - Address startAddr = addr.add(methodDef.toDataType().getLength()); - Address endAddr = startAddr; - if (methodDef.getMethodSize() > 0) { - endAddr = startAddr.add(methodDef.getMethodSize() - 1); + if (methodRow.isPInvokeImpl() && methodRow.isNative()) { + endAddr = startAddr.add(CLITABLEMETHODDEF_PINVOKE_JUMP_LENGTH - 1); } + else { + // Create MethodDef at this RVA + BinaryReader reader = + new BinaryReader(new MemoryByteProvider(program.getMemory(), addr), + !program.getMemory().isBigEndian()); + CliMethodDef methodDef = new CliMethodDef(addr, reader); + + DataType methodDefDataType = methodDef.toDataType(); + PeUtils.createData(program, addr, methodDefDataType, log); + + // Get the function's address space, default to zero-length just in case + startAddr = addr.add(methodDefDataType.getLength()); + endAddr = startAddr; + if (methodDef.getMethodSize() > 0) { + endAddr = startAddr.add(methodDef.getMethodSize() - 1); + } + + // Do extra data sections in MethodDef + if (methodDef.hasMoreSections()) { + int extraSectionOffset = + methodDefDataType.getLength() + methodDef.getMethodSize(); + + // Round up to the next offset divisible by 4 + extraSectionOffset = ((extraSectionOffset + 3) / 4) * 4; + + reader.setPointerIndex(extraSectionOffset); + CliMethodExtraSections extraSections = new CliMethodExtraSections(reader); + Address extraSectionAddr = addr.add(extraSectionOffset); + PeUtils.createData(program, extraSectionAddr, extraSections.toDataType(), log); + } + } + AddressSetView funcAddrSet = new AddressSet(startAddr, endAddr); // Let Ghidra assign a default function name and then try to decode the // real one if it exists String funcName = null; if (methodRow.nameIndex > 0) { - funcName = metadataStream.getStringsStream().getString(methodRow.nameIndex); - } - - // Do extra data sections in MethodDef - if (methodDef.hasMoreSections()) { - int extraSectionOffset = - methodDef.toDataType().getLength() + methodDef.getMethodSize(); - - // Round up to the next offset divisible by 4 - extraSectionOffset = ((extraSectionOffset + 3) / 4) * 4; - - reader.setPointerIndex(extraSectionOffset); - CliMethodExtraSections extraSections = new CliMethodExtraSections(reader); - Address extraSectionAddr = addr.add(extraSectionOffset); - PeUtils.createData(program, extraSectionAddr, extraSections.toDataType(), log); + funcName = SymbolUtilities.replaceInvalidChars( + metadataStream.getStringsStream().getString(methodRow.nameIndex), true); } // Get the function signature blob @@ -227,27 +299,136 @@ public class CliTableMethodDef extends CliAbstractTable { metadataStream.getBlobStream().updateBlob(methodSig, sigAddr, program); DataType returnType = methodSig.getReturnType().getExecutionDataType(); - // Pull apart the function parameter names and types + int maxSequence = 0; int stackOffset = 0; CliParam paramTypes[] = methodSig.getParamTypes(); + int paramCount = paramTypes.length; CliTableParam paramTable = (CliTableParam) metadataStream.getTable(CliTypeTable.Param); - ParameterImpl parameters[] = new ParameterImpl[paramTypes.length]; - for (int i = 0; i < paramTypes.length; i++) { + // Store the parameters in a Hashtable because by the time processing + // finishes the number of actual parameters might change + HashMap parameterList = new HashMap(); + + // Some Static function first parameters being pointers to a ValueType + // have the same number of parameters specified, but one or more are implied + // pointers to the object they're associated with. It's not in the Parameter + // Table and looking for the extra parameter in the table will walk you + // into the parameter list of another function. + ParameterImpl staticParameter = null; + if (methodRow.isStatic() && paramCount > 0) { + CliParam staticParam = paramTypes[0]; + String paramName = ""; + + // Walk the path from the ELEMENT_TYPE_PTR to the ELEMENT_TYPE_VALUETYPE + if (staticParam.getType() instanceof CliTypePtr) { + CliTypePtr ptrToValueType = (CliTypePtr) staticParam.getType(); + if (ptrToValueType.getType() instanceof CliTypeValueType) { + CliTypeValueType valueType = (CliTypeValueType) ptrToValueType.getType(); + + // Get the table and row specifying the type name + CliTypeTable tableType = valueType.getTable(); + int rowIndex = valueType.getRowIndex(); + + int paramNameStringIndex = 0; + CliAbstractTable table = metadataStream.getTable(tableType); + CliAbstractTableRow row = table.getRow(rowIndex); + if (tableType.id() == tableType.TypeDef.id()) { + CliTypeDefRow typeDefRow = (CliTypeDefRow) row; + paramNameStringIndex = typeDefRow.typeNameIndex; + } + else if (tableType.id() == tableType.TypeRef.id()) { + CliTypeRefRow typeRefRow = (CliTypeRefRow) row; + paramNameStringIndex = typeRefRow.typeNameIndex; + } + + if (paramNameStringIndex > 0) { + paramName = + metadataStream.getStringsStream().getString(paramNameStringIndex); + paramName = SymbolUtilities.replaceInvalidChars(paramName, true); + + DataType dataType = staticParam.getExecutionDataType(); + + try { + staticParameter = + new ParameterImpl(paramName, dataType, stackOffset, program); + } + catch (InvalidInputException e) { + Msg.warn(this, "Error processing parameter \"" + paramName + + "\" in function \"" + funcName + "\": " + e.getMessage()); + } + + stackOffset += dataType.getLength(); + + paramCount--; + } + } + } + } + + // Pull apart the function's Param table entries + for (int i = 0; i < paramCount; i++) { CliParamRow paramRow = (CliParamRow) paramTable.getRow(methodRow.paramIndex + i); - String paramName = metadataStream.getStringsStream().getString(paramRow.nameIndex); + if (paramRow.sequence > maxSequence) { + maxSequence = paramRow.sequence; + } + + String paramName = SymbolUtilities.replaceInvalidChars( + metadataStream.getStringsStream().getString(paramRow.nameIndex), true); + DataType dataType = paramTypes[i].getExecutionDataType(); - try { - parameters[i] = new ParameterImpl(paramName, dataType, stackOffset, program); - } - catch (InvalidInputException e) { - Msg.warn(this, "Error processing parameter \"" + paramName + - "\" in function \"" + funcName + "\": " + e.getMessage()); + if (paramRow.sequence == 0) { + // Parameters with a 0 sequence number are the return type, + // reduce the size of the array and put any previously discovered + // parameters into it + returnType = dataType; } + else { + // Parameters are placed in the proper order based on the sequence + // field (1-based) to compensate for some static methods having an implied + // first parameter that won't be represented in the Parameter Table + // and some return types that are represented as parameters. + try { + parameterList.put((int) paramRow.sequence, + new ParameterImpl(paramName, dataType, stackOffset, program)); + } + catch (InvalidInputException e) { + Msg.warn(this, "Error processing parameter \"" + paramName + + "\" in function \"" + funcName + "\": " + e.getMessage()); + } - stackOffset += dataType.getLength(); + stackOffset += dataType.getLength(); + } + } + + ParameterImpl[] parameters = new ParameterImpl[maxSequence]; + parameterList.forEach((key, value) -> + // Sequences are 1-based + parameters[key - 1] = value); + + // For static functions, fill in the pointer to ValueType + // parameters that are implied before the actual parameters + if (methodRow.isStatic()) { + if (staticParameter != null) { + for (int i = 0; i < parameters.length; i++) { + if (parameters[i] == null) { + ParameterImpl param = null; + try { + param = new ParameterImpl(staticParameter.getName() + i, + staticParameter.getDataType(), staticParameter.getStackOffset(), + staticParameter.getProgram()); + } + catch (InvalidInputException e1) { + Msg.warn(this, + "Couldn't clone " + staticParameter.getName() + + " implied static function parameter in function : " + + funcName + "in position " + i); + } + parameters[i] = param; + } + } + } } try { @@ -257,15 +438,44 @@ public class CliTableMethodDef extends CliAbstractTable { newFunc.updateFunction(null, null, FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.ANALYSIS, parameters); } + catch (NullPointerException e) { + Msg.warn(this, "Error processing function \"" + funcName + "\" (" + methodRowIndex + + "): Bad parameters provided"); + } catch (InvalidInputException e) { - Msg.warn(this, "Error processing function \"" + funcName + "\""); + Msg.warn(this, "Error processing function \" (\" + methodRowIndex + \")" + + funcName + "\": Invalid function"); } catch (OverlappingFunctionException e) { - Msg.warn(this, "Error processing function \"" + funcName + "\""); + String err = "Error processing function \" (\" + methodRowIndex + \")" + funcName + + "\": Overlapping function (" + startAddr + ", " + endAddr + ": "; + + Function existingFuncA = program.getFunctionManager().getFunctionAt(startAddr); + Function existingFuncB = program.getFunctionManager().getFunctionAt(endAddr); + + if (existingFuncA != null && existingFuncB == null) { + err = err + existingFuncA.getName(); + } + else if (existingFuncA == null && existingFuncB != null) { + err = err + existingFuncB.getName(); + } + else if (existingFuncA != null && existingFuncA == existingFuncB) { + err = err + existingFuncA.getName(); + } + + err = err + ")"; + + Msg.warn(this, err); + } + catch (DuplicateNameException e) { + String paramNames = ""; + for (int i = 0; i < parameters.length - 1; i++) { + paramNames += parameters[i].getName() + ", "; + } + paramNames += parameters[parameters.length - 1].getName(); + Msg.warn(this, "Error processing function \"" + funcName + "\" (" + methodRowIndex + + "): Duplicate parameter name (" + paramNames + ")"); } - } - if (rvaZero > 0) { - Msg.warn(this, rvaZero + " methods with RVA 0"); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableParam.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableParam.java index 097258ec86..875acf1a9b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableParam.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableParam.java @@ -31,7 +31,14 @@ public class CliTableParam extends CliAbstractTable { public short flags; public short sequence; public int nameIndex; - + + private static final int PARAMATTRIBUTES_IN = 0x1; + private static final int PARAMATTRIBUTES_OUT = 0x2; + private static final int PARAMATTRIBUTES_OPTIONAL = 0x10; + private static final int PARAMATTRIBUTES_HASDEFAULT = 0x1000; + private static final int PARAMATTRIBUTES_HASFIELDMARSHAL = 0x2000; + private static final int PARAMATTRIBUTES_UNUSED = 0xCFE0; + public CliParamRow(short flags, short sequence, int nameIndex) { super(); this.flags = flags; @@ -46,11 +53,13 @@ public class CliTableParam extends CliAbstractTable { CliEnumParamAttributes.dataType.getName(flags & 0xffff), sequence); } } - - public CliTableParam(BinaryReader reader, CliStreamMetadata stream, CliTypeTable tableId) throws IOException { + + public CliTableParam(BinaryReader reader, CliStreamMetadata stream, CliTypeTable tableId) + throws IOException { super(reader, stream, tableId); for (int i = 0; i < this.numRows; i++) { - CliParamRow row = new CliParamRow(reader.readNextShort(), reader.readNextShort(), readStringIndex(reader)); + CliParamRow row = new CliParamRow(reader.readNextShort(), reader.readNextShort(), + readStringIndex(reader)); rows.add(row); strings.add(row.nameIndex); } @@ -59,9 +68,9 @@ public class CliTableParam extends CliAbstractTable { @Override public StructureDataType getRowDataType() { - StructureDataType rowDt = new StructureDataType(new CategoryPath(PATH), "ParamRow",0); + StructureDataType rowDt = new StructureDataType(new CategoryPath(PATH), "ParamRow", 0); rowDt.add(CliEnumParamAttributes.dataType, "Flags", "bitmask of type ParamAttributes"); - rowDt.add( WORD, "Sequence", "constant"); + rowDt.add(WORD, "Sequence", "constant"); rowDt.add(metadataStream.getStringIndexDataType(), "Name", "index into String heap"); return rowDt; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableStandAloneSig.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableStandAloneSig.java index 025eae5acf..aefe83d791 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableStandAloneSig.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/tables/CliTableStandAloneSig.java @@ -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,6 +90,7 @@ public class CliTableStandAloneSig extends CliAbstractTable { throws DuplicateNameException, CodeUnitInsertionException, IOException { for (CliAbstractTableRow row : rows) { Integer sigIndex = ((CliStandAloneSigRow) row).signatureIndex; + CliBlob blob = metadataStream.getBlobStream().getBlob(((CliStandAloneSigRow) row).signatureIndex); Address sigAddr = CliAbstractStream.getStreamMarkupAddress(program, isBinary, monitor, From c216d9d4da56125d0cfaa998a86e762e138f2e9b Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Tue, 16 Mar 2021 11:43:34 -0400 Subject: [PATCH 093/140] GP-751 - Fix-up for OverlayAddressSpace construction --- .../ghidra/program/util/VarnodeContext.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java index 760bf5fd60..e0d1e22cc1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java @@ -34,8 +34,7 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.ReferenceIterator; import ghidra.util.Msg; -import ghidra.util.exception.DuplicateNameException; -import ghidra.util.exception.NotFoundException; +import ghidra.util.exception.*; public class VarnodeContext implements ProcessorContext { @@ -88,7 +87,7 @@ public class VarnodeContext implements ProcessorContext { this.program = program; // make a copy, because we could be making new spaces. - this.addrFactory = new OffsetAddressFactory(program.getAddressFactory()); + this.addrFactory = new OffsetAddressFactory(program); BAD_ADDRESS = addrFactory.getAddress(getAddressSpace("BAD_ADDRESS_SPACE"), 0); @@ -1435,8 +1434,24 @@ public class VarnodeContext implements ProcessorContext { class OffsetAddressFactory extends DefaultAddressFactory { - OffsetAddressFactory(AddressFactory baseFactory) { - super(filterSpaces(baseFactory.getAllAddressSpaces())); + OffsetAddressFactory(Program program) { + // We are only calling super with the address spaces from the language first, and then + // following up to explicitly add more spaces due to the treatment of memory address + // spaces by DefaultAddressFactory when constructed vs. when added later. + // If there is more than one memory address space (e.g., TYPE_RAM, TYPE_CODE, or + // TYPE_OTHER), then addresses are output with the space name prefix, which we do not want. + super(program.getLanguage().getAddressFactory().getAllAddressSpaces(), + program.getLanguage().getAddressFactory().getDefaultAddressSpace()); + for (AddressSpace space : program.getAddressFactory().getAllAddressSpaces()) { + if (space.isLoadedMemorySpace() && getAddressSpace(space.getName()) == null) { + try { + addAddressSpace(space); + } + catch (DuplicateNameException e) { + throw new AssertException("Duplicate name should not occur."); + } + } + } } private int getNextUniqueID() { @@ -1466,17 +1481,4 @@ class OffsetAddressFactory extends DefaultAddressFactory { return (type == AddressSpace.TYPE_SYMBOL); } - private static AddressSpace[] filterSpaces(AddressSpace[] allSpaces) { - List spaces = new ArrayList<>(); - for (AddressSpace space : allSpaces) { - int type = space.getType(); - if (type == AddressSpace.TYPE_VARIABLE || type == AddressSpace.TYPE_STACK || - type == AddressSpace.TYPE_EXTERNAL || type == AddressSpace.TYPE_JOIN) { - continue; - } - spaces.add(space); - } - return spaces.toArray(new AddressSpace[0]); - } - } From b8f1b241ba41720bfb559d058217951ff805b99e Mon Sep 17 00:00:00 2001 From: "Jason P. Leasure" Date: Wed, 17 Mar 2021 13:17:46 -0400 Subject: [PATCH 094/140] parse $GHIDRA_HOME in analyzeHeadless -scriptPath, fixes GP-781 --- .../app/util/headless/HeadlessAnalyzer.java | 35 +++++++++++++------ .../Common/support/analyzeHeadlessREADME.html | 4 +-- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java index e18ca98a78..f63589fdac 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java @@ -293,9 +293,10 @@ public class HeadlessAnalyzer { } } - GhidraScriptUtil.initialize(new BundleHost(), options.scriptPaths); + List parsedScriptPaths = parseScriptPaths(options.scriptPaths); + GhidraScriptUtil.initialize(new BundleHost(), parsedScriptPaths); try { - initializeScriptPaths(); + showConfiguredScriptPaths(); compileScripts(); Msg.info(HeadlessAnalyzer.class, "HEADLESS: execution starts"); @@ -400,9 +401,10 @@ public class HeadlessAnalyzer { } } - GhidraScriptUtil.initialize(new BundleHost(), options.scriptPaths); + List parsedScriptPaths = parseScriptPaths(options.scriptPaths); + GhidraScriptUtil.initialize(new BundleHost(), parsedScriptPaths); try { - initializeScriptPaths(); + showConfiguredScriptPaths(); compileScripts(); Msg.info(HeadlessAnalyzer.class, "HEADLESS: execution starts"); @@ -668,10 +670,23 @@ public class HeadlessAnalyzer { } } - /** - * Gather paths where scripts may be found. - */ - private void initializeScriptPaths() { + private List parseScriptPaths(List scriptPaths) { + List parsedScriptPaths = new ArrayList<>(); + for (String path : scriptPaths) { + ResourceFile pathFile = Path.fromPathString(path); + String absPath = pathFile.getAbsolutePath(); + if (pathFile.exists()) { + parsedScriptPaths.add(absPath); + } + else { + + Msg.warn(this, "REPORT: Could not find -scriptPath entry, skipping: " + absPath); + } + } + return parsedScriptPaths; + } + + private void showConfiguredScriptPaths() { StringBuffer buf = new StringBuffer("HEADLESS Script Paths:"); for (ResourceFile dir : GhidraScriptUtil.getScriptSourceDirectories()) { buf.append("\n "); @@ -856,8 +871,8 @@ public class HeadlessAnalyzer { Class c = Class.forName(className, true, classLoaderForDotClassScripts); // Get parent folder to pass to GhidraScript - File parentFile = new File( - c.getResource(c.getSimpleName() + ".class").toURI()).getParentFile(); + File parentFile = new File(c.getResource(c.getSimpleName() + ".class").toURI()) + .getParentFile(); currScript = (GhidraScript) c.getConstructor().newInstance(); currScript.setScriptArgs(scriptArgs); diff --git a/Ghidra/RuntimeScripts/Common/support/analyzeHeadlessREADME.html b/Ghidra/RuntimeScripts/Common/support/analyzeHeadlessREADME.html index 00b7bd9cb9..dfbea0d5de 100644 --- a/Ghidra/RuntimeScripts/Common/support/analyzeHeadlessREADME.html +++ b/Ghidra/RuntimeScripts/Common/support/analyzeHeadlessREADME.html @@ -313,7 +313,7 @@ The Headless Analyzer uses the command-line parameters discussed below. See -scriptPath "<path1>[;<path2>...]"
    Specifies the search path(s) for scripts, including secondary scripts (a script invoked from - another script). A path may start with $GHIDRA_SCRIPT, which corresponds + another script). A path may start with $GHIDRA_HOME, which corresponds to the Ghidra installation directory, or $USER_HOME, which corresponds to the user's home directory. On Unix systems, these home variables must be escaped using a '\' (backslash) character. @@ -344,7 +344,7 @@ The Headless Analyzer uses the command-line parameters discussed below. See -propertiesPath "<path1>[;<path2>…]"
    Specifies path(s) that contain .properties files used by scripts or - secondary/subscripts. A path may start with $GHIDRA_SCRIPT, which + secondary/subscripts. A path may start with $GHIDRA_HOME, which corresponds to the Ghidra installation directory, or $USER_HOME, which corresponds to the user's home directory. On Unix systems these home variables must be escaped with a '\' character. From d2c39513c3b9ca65fa9587e5ac41036e45483501 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Mon, 15 Mar 2021 13:26:11 -0400 Subject: [PATCH 095/140] Handle changes to allow for certification headers on bash type source files (e.g., *.py) and gradle files --- .../java/ghidra/util/datastruct/Range.java | 0 gradle/certification.manifest | 1 - gradle/support/ip.gradle | 57 ++++++++++++++++--- 3 files changed, 48 insertions(+), 10 deletions(-) rename Ghidra/Framework/{Generic => Utility}/src/main/java/ghidra/util/datastruct/Range.java (100%) diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/Range.java b/Ghidra/Framework/Utility/src/main/java/ghidra/util/datastruct/Range.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/Range.java rename to Ghidra/Framework/Utility/src/main/java/ghidra/util/datastruct/Range.java diff --git a/gradle/certification.manifest b/gradle/certification.manifest index 430baa7114..0970bcd7da 100644 --- a/gradle/certification.manifest +++ b/gradle/certification.manifest @@ -23,7 +23,6 @@ support/distributionCommon.gradle||GHIDRA||||END| support/eclipseLauncher.gradle||GHIDRA||||END| support/extensionCommon.gradle||GHIDRA||||END| support/fetchDependencies.gradle||GHIDRA||||END| -support/ip.gradle||GHIDRA||||END| support/jacoco.excludes.src.txt||GHIDRA||||END| support/loadApplicationProperties.gradle||GHIDRA||||END| support/settingsUtil.gradle||GHIDRA||||END| diff --git a/gradle/support/ip.gradle b/gradle/support/ip.gradle index 2125091554..1e4bbe6e05 100644 --- a/gradle/support/ip.gradle +++ b/gradle/support/ip.gradle @@ -1,4 +1,18 @@ - +/* ### + * 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. + */ /********************************************************************************* * ip.gradle * @@ -152,12 +166,13 @@ def addToMap(Map> map, String ip, String path) { /********************************************************************************* * checks if a file supports a C style header based on its extension. *********************************************************************************/ -def isSourceFile(File file) { +def isCSourceFile(File file) { String filename = file.getName().toLowerCase(); return filename.endsWith(".java") || filename.endsWith(".c") || + filename.endsWith(".gradle") || filename.endsWith(".groovy") || filename.endsWith(".cpp") || filename.endsWith(".cc") || @@ -166,16 +181,38 @@ def isSourceFile(File file) { filename.endsWith(".l") || filename.endsWith(".hh") || filename.endsWith(".css") || - filename.endsWith(".jj"); + filename.endsWith(".jj") || + filename.endsWith(".proto"); +} + +/********************************************************************************* + * checks if a file supports a Bash style header based on its extension. + *********************************************************************************/ +def isBashSourceFile(File file) { + + String filename = file.getName().toLowerCase(); + + // NOTE: bash/shell scripts without extension will not utilize a header + return filename.endsWith(".py") || + filename.endsWith(".sh") || + filename.endsWith(".bash") || + filename.endsWith(".command"); } /********************************************************************************* - * Gets the ip for a file in the module from its header (or certification.manifest + * Gets the ip for a file in the module from its header (or certification.manifest) *********************************************************************************/ def getIp(File projectDir, File file) { - if (isSourceFile(file)) { - return getIpForSourceFile(file); + if (isCSourceFile(file)) { + return getIpForSourceFile(file, " * IP:"); + } + if (isBashSourceFile(file)) { + String ip = getIpForSourceFile(file, "# IP:"); + // allow transition from certification.manifest entry + if (ip != null) { + return ip; + } } return getIpForNonSourceFile(projectDir, file); } @@ -183,12 +220,14 @@ def getIp(File projectDir, File file) { /********************************************************************************* * Gets the ip from a file that has a certification header *********************************************************************************/ -def getIpForSourceFile(File file) { +def getIpForSourceFile(File file, String prefix) { + // IP marking occurs within first 4-lines of file String ip =null String line; + int lineNum = 0; file.withReader { reader -> - while((line = reader.readLine()) != null) { - if (line.startsWith(" * IP:")) { + while(++lineNum < 5 && (line = reader.readLine()) != null) { + if (line.startsWith(prefix)) { ip = line.substring(7).trim(); break; } From 162f2033953d8b5cd57d440aa2e1c3763bbae80b Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 17 Mar 2021 18:22:43 -0400 Subject: [PATCH 096/140] Updated certification headers --- GPL/CabExtract/build.gradle | 5 +++- GPL/CabExtract/certification.manifest | 2 -- GPL/CabExtract/settings.gradle | 3 +++ GPL/DMG/build.gradle | 3 +++ GPL/DMG/certification.manifest | 2 -- GPL/DMG/settings.gradle | 3 +++ GPL/DemanglerGnu/build.gradle | 3 +++ GPL/DemanglerGnu/certification.manifest | 2 -- GPL/DemanglerGnu/settings.gradle | 3 +++ GPL/GnuDisassembler/build.gradle | 3 +++ GPL/GnuDisassembler/buildGdis.gradle | 3 +++ GPL/GnuDisassembler/certification.manifest | 3 --- GPL/GnuDisassembler/settings.gradle | 3 +++ GPL/certification.local.manifest | 3 --- GPL/gpl.gradle | 4 ++- GPL/nativeBuildProperties.gradle | 3 +++ GPL/vsconfig.gradle | 15 +++++++++++ .../Public_Release/build.gradle | 15 +++++++++++ .../Public_Release/certification.manifest | 1 - .../Extensions/SampleTablePlugin/build.gradle | 15 +++++++++++ .../SampleTablePlugin/certification.manifest | 1 - Ghidra/Extensions/SleighDevTools/build.gradle | 15 +++++++++++ .../SleighDevTools/certification.manifest | 6 ----- .../SleighDevTools/pcodetest/build.py | 15 +++++++++++ .../SleighDevTools/pcodetest/defaults.py | 16 +++++++++++- .../SleighDevTools/pcodetest/pcode_defs.py | 16 +++++++++++- .../SleighDevTools/pcodetest/pcodetest.py | 15 +++++++++++ .../SleighDevTools/pcodetest/tpp.py | 15 +++++++++++ .../Extensions/bundle_examples/build.gradle | 15 +++++++++++ .../bundle_examples/certification.manifest | 1 - Ghidra/Extensions/sample/build.gradle | 15 +++++++++++ .../Extensions/sample/certification.manifest | 1 - Ghidra/Features/Base/build.gradle | 15 +++++++++++ Ghidra/Features/Base/certification.manifest | 3 --- .../ghidra_scripts/RecursiveStringFinder.py | 15 +++++++++++ .../Base/ghidra_scripts/mark_in_out.py | 15 +++++++++++ Ghidra/Features/BytePatterns/build.gradle | 15 +++++++++++ .../BytePatterns/certification.manifest | 1 - Ghidra/Features/ByteViewer/build.gradle | 17 ++++++++++++- .../ByteViewer/certification.manifest | 1 - Ghidra/Features/DebugUtils/build.gradle | 15 +++++++++++ .../DebugUtils/certification.manifest | 1 - Ghidra/Features/Decompiler/build.gradle | 15 +++++++++++ .../Decompiler/certification.manifest | 2 -- .../Decompiler/src/decompile/build.gradle | 15 +++++++++++ .../Features/DecompilerDependent/build.gradle | 15 +++++++++++ .../certification.manifest | 1 - Ghidra/Features/FileFormats/build.gradle | 15 +++++++++++ .../FileFormats/certification.manifest | 1 - Ghidra/Features/FunctionGraph/build.gradle | 15 +++++++++++ .../FunctionGraph/certification.manifest | 1 - .../build.gradle | 15 +++++++++++ .../certification.manifest | 1 - Ghidra/Features/FunctionID/build.gradle | 15 +++++++++++ .../FunctionID/certification.manifest | 1 - Ghidra/Features/GhidraServer/build.gradle | 15 +++++++++++ .../GhidraServer/certification.manifest | 2 -- Ghidra/Features/GnuDemangler/build.gradle | 15 +++++++++++ .../GnuDemangler/certification.manifest | 3 --- .../Features/GraphFunctionCalls/build.gradle | 15 +++++++++++ .../GraphFunctionCalls/certification.manifest | 1 - Ghidra/Features/GraphServices/build.gradle | 15 +++++++++++ .../GraphServices/certification.manifest | 1 - .../MicrosoftCodeAnalyzer/build.gradle | 15 +++++++++++ .../certification.manifest | 1 - .../Features/MicrosoftDemangler/build.gradle | 15 +++++++++++ .../MicrosoftDemangler/certification.manifest | 1 - Ghidra/Features/MicrosoftDmang/build.gradle | 15 +++++++++++ .../MicrosoftDmang/certification.manifest | 1 - Ghidra/Features/PDB/build.gradle | 15 +++++++++++ Ghidra/Features/PDB/certification.manifest | 1 - Ghidra/Features/ProgramDiff/build.gradle | 15 +++++++++++ .../ProgramDiff/certification.manifest | 1 - Ghidra/Features/ProgramGraph/build.gradle | 15 +++++++++++ .../ProgramGraph/certification.manifest | 1 - Ghidra/Features/Python/build.gradle | 15 +++++++++++ Ghidra/Features/Python/certification.manifest | 20 --------------- .../AddCommentToProgramScriptPy.py | 15 +++++++++++ .../Python/ghidra_scripts/AskScriptPy.py | 15 +++++++++++ .../CallAnotherScriptForAllProgramsPy.py | 15 +++++++++++ .../ghidra_scripts/CallAnotherScriptPy.py | 15 +++++++++++ .../ghidra_scripts/ChooseDataTypeScriptPy.py | 15 +++++++++++ .../ghidra_scripts/ExampleColorScriptPy.py | 15 +++++++++++ .../ghidra_scripts/FormatExampleScriptPy.py | 15 +++++++++++ .../ghidra_scripts/ImportSymbolsScript.py | 15 +++++++++++ .../ghidra_scripts/PrintNonZeroPurge.py | 15 +++++++++++ .../ToolPropertiesExampleScriptPy.py | 15 +++++++++++ .../ghidra_scripts/external_module_callee.py | 15 +++++++++++ .../ghidra_scripts/external_module_caller.py | 15 +++++++++++ .../Python/ghidra_scripts/ghidra_basics.py | 15 +++++++++++ .../Python/ghidra_scripts/jython_basics.py | 15 +++++++++++ .../Python/ghidra_scripts/python_basics.py | 15 +++++++++++ .../Features/Python/python-src/ghidradoc.py | 15 +++++++++++ .../Features/Python/python-src/introspect.py | 3 +++ .../Features/Python/python-src/jintrospect.py | 3 +++ .../Python/python-src/sitecustomize.py | 15 +++++++++++ Ghidra/Features/Recognizers/build.gradle | 15 +++++++++++ .../Recognizers/certification.manifest | 1 - Ghidra/Features/SourceCodeLookup/build.gradle | 15 +++++++++++ .../SourceCodeLookup/certification.manifest | 1 - Ghidra/Features/VersionTracking/build.gradle | 15 +++++++++++ .../VersionTracking/certification.manifest | 1 - Ghidra/Framework/DB/build.gradle | 15 +++++++++++ Ghidra/Framework/DB/certification.manifest | 1 - Ghidra/Framework/Docking/build.gradle | 15 +++++++++++ .../Framework/Docking/certification.manifest | 1 - Ghidra/Framework/FileSystem/build.gradle | 15 +++++++++++ .../FileSystem/certification.manifest | 1 - Ghidra/Framework/Generic/build.gradle | 15 +++++++++++ .../Framework/Generic/certification.manifest | 1 - Ghidra/Framework/Graph/build.gradle | 15 +++++++++++ Ghidra/Framework/Graph/certification.manifest | 1 - Ghidra/Framework/Help/build.gradle | 15 +++++++++++ Ghidra/Framework/Help/certification.manifest | 1 - Ghidra/Framework/Project/build.gradle | 15 +++++++++++ .../Framework/Project/certification.manifest | 1 - .../Framework/SoftwareModeling/build.gradle | 15 +++++++++++ .../SoftwareModeling/certification.manifest | 1 - Ghidra/Framework/Utility/build.gradle | 15 +++++++++++ .../Framework/Utility/certification.manifest | 1 - Ghidra/Processors/6502/build.gradle | 15 +++++++++++ Ghidra/Processors/6502/certification.manifest | 1 - Ghidra/Processors/68000/build.gradle | 15 +++++++++++ .../Processors/68000/certification.manifest | 1 - Ghidra/Processors/6805/build.gradle | 15 +++++++++++ Ghidra/Processors/6805/certification.manifest | 1 - Ghidra/Processors/8048/build.gradle | 15 +++++++++++ Ghidra/Processors/8048/certification.manifest | 1 - Ghidra/Processors/8051/build.gradle | 17 ++++++++++++- Ghidra/Processors/8051/certification.manifest | 1 - Ghidra/Processors/8085/build.gradle | 15 +++++++++++ Ghidra/Processors/8085/certification.manifest | 1 - Ghidra/Processors/AARCH64/build.gradle | 15 +++++++++++ .../Processors/AARCH64/certification.manifest | 1 - Ghidra/Processors/ARM/build.gradle | 15 +++++++++++ Ghidra/Processors/ARM/certification.manifest | 1 - Ghidra/Processors/Atmel/build.gradle | 15 +++++++++++ .../Processors/Atmel/certification.manifest | 1 - Ghidra/Processors/CP1600/build.gradle | 15 +++++++++++ .../Processors/CP1600/certification.manifest | 1 - Ghidra/Processors/CR16/build.gradle | 15 +++++++++++ Ghidra/Processors/CR16/certification.manifest | 1 - Ghidra/Processors/DATA/build.gradle | 15 +++++++++++ Ghidra/Processors/DATA/certification.manifest | 1 - Ghidra/Processors/Dalvik/build.gradle | 15 +++++++++++ .../Processors/Dalvik/certification.manifest | 1 - Ghidra/Processors/HCS08/build.gradle | 17 ++++++++++++- .../Processors/HCS08/certification.manifest | 1 - Ghidra/Processors/HCS12/build.gradle | 15 +++++++++++ .../Processors/HCS12/certification.manifest | 1 - Ghidra/Processors/JVM/build.gradle | 15 +++++++++++ Ghidra/Processors/JVM/certification.manifest | 1 - Ghidra/Processors/M8C/build.gradle | 15 +++++++++++ Ghidra/Processors/M8C/certification.manifest | 1 - Ghidra/Processors/MCS96/build.gradle | 17 ++++++++++++- .../Processors/MCS96/certification.manifest | 1 - Ghidra/Processors/MIPS/build.gradle | 15 +++++++++++ Ghidra/Processors/MIPS/certification.manifest | 1 - Ghidra/Processors/PA-RISC/build.gradle | 15 +++++++++++ .../Processors/PA-RISC/certification.manifest | 1 - Ghidra/Processors/PIC/build.gradle | 15 +++++++++++ Ghidra/Processors/PIC/certification.manifest | 1 - Ghidra/Processors/PowerPC/build.gradle | 15 +++++++++++ .../Processors/PowerPC/certification.manifest | 1 - Ghidra/Processors/RISCV/build.gradle | 15 +++++++++++ .../Processors/RISCV/certification.manifest | 2 -- Ghidra/Processors/RISCV/scripts/binutil.py | 15 +++++++++++ Ghidra/Processors/Sparc/build.gradle | 15 +++++++++++ .../Processors/Sparc/certification.manifest | 1 - Ghidra/Processors/SuperH/build.gradle | 15 +++++++++++ .../Processors/SuperH/certification.manifest | 1 - Ghidra/Processors/SuperH4/build.gradle | 17 ++++++++++++- .../Processors/SuperH4/certification.manifest | 1 - Ghidra/Processors/TI_MSP430/build.gradle | 15 +++++++++++ .../TI_MSP430/certification.manifest | 1 - Ghidra/Processors/Toy/build.gradle | 15 +++++++++++ Ghidra/Processors/Toy/certification.manifest | 1 - Ghidra/Processors/V850/build.gradle | 15 +++++++++++ Ghidra/Processors/V850/certification.manifest | 1 - Ghidra/Processors/Z80/build.gradle | 15 +++++++++++ Ghidra/Processors/Z80/certification.manifest | 1 - Ghidra/Processors/tricore/build.gradle | 15 +++++++++++ .../Processors/tricore/certification.manifest | 1 - Ghidra/Processors/x86/build.gradle | 15 +++++++++++ Ghidra/Processors/x86/certification.manifest | 1 - .../server/jaas_external_program.example.sh | 15 +++++++++++ .../Common/support/buildExtension.gradle | 15 +++++++++++ Ghidra/RuntimeScripts/Linux/support/launch.sh | 15 +++++++++++ Ghidra/RuntimeScripts/build.gradle | 15 +++++++++++ Ghidra/RuntimeScripts/certification.manifest | 4 --- Ghidra/Test/IntegrationTest/build.gradle | 15 +++++++++++ .../IntegrationTest/certification.manifest | 1 - .../BuildFiles/JsonDoclet/build.gradle | 15 +++++++++++ GhidraBuild/BuildFiles/build.gradle | 17 ++++++++++++- GhidraBuild/BuildFiles/certification.manifest | 2 -- .../GhidraDev/GhidraDevFeature/build.gradle | 17 ++++++++++++- .../GhidraDev/GhidraDevPlugin/build.gradle | 15 +++++++++++ .../GhidraDev/certification.manifest | 2 -- .../GhidraSleighEditor/certification.manifest | 6 ----- .../ghidra.xtext.sleigh.feature/build.gradle | 15 +++++++++++ .../ghidra.xtext.sleigh.ide/build.gradle | 15 +++++++++++ .../ghidra.xtext.sleigh.tests/build.gradle | 15 +++++++++++ .../ghidra.xtext.sleigh.ui.tests/build.gradle | 15 +++++++++++ .../ghidra.xtext.sleigh.ui/build.gradle | 15 +++++++++++ .../ghidra.xtext.sleigh/build.gradle | 15 +++++++++++ .../IDAPro/Python/6xx/loaders/xmlldr.py | 15 +++++++++++ .../IDAPro/Python/6xx/plugins/xmlexp.py | 15 +++++++++++ .../IDAPro/Python/7xx/loaders/xml_loader.py | 15 +++++++++++ .../IDAPro/Python/7xx/plugins/xml_exporter.py | 15 +++++++++++ .../IDAPro/Python/7xx/plugins/xml_importer.py | 15 +++++++++++ .../IDAPro/Python/7xx/python/idaxml.py | 15 +++++++++++ GhidraBuild/IDAPro/build.gradle | 17 ++++++++++++- GhidraBuild/IDAPro/certification.manifest | 7 ------ GhidraBuild/LaunchSupport/build.gradle | 17 ++++++++++++- .../LaunchSupport/certification.manifest | 1 - GhidraBuild/Skeleton/build.gradle | 17 ++++++++++++- GhidraBuild/Skeleton/buildTemplate.gradle | 15 +++++++++++ GhidraBuild/Skeleton/certification.manifest | 2 -- GhidraDocs/build.gradle | 17 ++++++++++++- GhidraDocs/certification.manifest | 1 - build.gradle | 15 +++++++++++ certification.local.manifest | 2 -- gradle/certification.manifest | 25 ------------------- gradle/distributableGPLExtension.gradle | 15 +++++++++++ gradle/distributableGPLModule.gradle | 15 +++++++++++ gradle/distributableGhidraExtension.gradle | 15 +++++++++++ gradle/distributableGhidraModule.gradle | 15 +++++++++++ gradle/externalGhidraExtension.gradle | 15 +++++++++++ gradle/helpProject.gradle | 15 +++++++++++ gradle/jacocoProject.gradle | 17 ++++++++++++- gradle/javaProject.gradle | 15 +++++++++++ gradle/javaTestProject.gradle | 17 ++++++++++++- gradle/nativeProject.gradle | 15 +++++++++++ gradle/processorProject.gradle | 17 ++++++++++++- gradle/root/distribution.gradle | 15 +++++++++++ gradle/root/eclipse.gradle | 15 +++++++++++ gradle/root/jacoco.gradle | 17 ++++++++++++- gradle/root/prepDev.gradle | 17 +++++++++++-- gradle/root/svg.gradle | 16 +++++++++++- gradle/root/test.gradle | 15 +++++++++++ gradle/root/usage.gradle | 16 +++++++++++- gradle/support/distributionCommon.gradle | 15 +++++++++++ gradle/support/eclipseLauncher.gradle | 15 +++++++++++ gradle/support/extensionCommon.gradle | 17 ++++++++++++- gradle/support/fetchDependencies.gradle | 15 +++++++++++ .../support/loadApplicationProperties.gradle | 16 +++++++++++- gradle/support/settingsUtil.gradle | 16 +++++++++++- gradle/support/testUtils.gradle | 15 +++++++++++ settings.gradle | 15 +++++++++++ 249 files changed, 2306 insertions(+), 192 deletions(-) diff --git a/GPL/CabExtract/build.gradle b/GPL/CabExtract/build.gradle index 95b36dd4d4..46994edbc7 100644 --- a/GPL/CabExtract/build.gradle +++ b/GPL/CabExtract/build.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ apply from: file("../gpl.gradle").getCanonicalPath() if (findProject(':Generic') != null) { @@ -57,4 +60,4 @@ if (['linux64', 'osx64'].contains(currentPlatform)) { delete file("build/unpack/${cabextract}") } } -} \ No newline at end of file +} diff --git a/GPL/CabExtract/certification.manifest b/GPL/CabExtract/certification.manifest index d63ae0e1ac..aa851666c6 100644 --- a/GPL/CabExtract/certification.manifest +++ b/GPL/CabExtract/certification.manifest @@ -2,6 +2,4 @@ ##MODULE IP: GPL 3 ##MODULE IP: Public Domain Module.manifest||Public Domain||||END| -build.gradle||Public Domain||||END| data/cabextract-1.6.tar.gz||GPL 3||||END| -settings.gradle||Public Domain||||END| diff --git a/GPL/CabExtract/settings.gradle b/GPL/CabExtract/settings.gradle index e69de29bb2..1092a7aaab 100644 --- a/GPL/CabExtract/settings.gradle +++ b/GPL/CabExtract/settings.gradle @@ -0,0 +1,3 @@ +/* ### + * IP: Public Domain + */ diff --git a/GPL/DMG/build.gradle b/GPL/DMG/build.gradle index d66cd2d0f2..690d55e941 100644 --- a/GPL/DMG/build.gradle +++ b/GPL/DMG/build.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ apply from: file("../gpl.gradle").getCanonicalPath() if (findProject(':Generic') != null) { diff --git a/GPL/DMG/certification.manifest b/GPL/DMG/certification.manifest index 7311651d24..d7bac0f1d3 100644 --- a/GPL/DMG/certification.manifest +++ b/GPL/DMG/certification.manifest @@ -3,7 +3,6 @@ ##MODULE IP: LGPL 2.1 ##MODULE IP: Public Domain Module.manifest||Public Domain||||END| -build.gradle||Public Domain||||END| data/lib/catacombae_csframework.jar||LGPL 2.1||||END| data/lib/catacombae_hfsx.jar||GPL 3||||END| data/lib/catacombae_hfsx_dmglib.jar||GPL 3||||END| @@ -16,4 +15,3 @@ data/os/win64/llio_amd64.dll||GPL 3||||END| data/os/win64/llio_i386.dll||GPL 3||||END| data/os/win64/llio_ia64.dll||GPL 3||||END| data/server_memory.cfg||Public Domain||||END| -settings.gradle||Public Domain||||END| diff --git a/GPL/DMG/settings.gradle b/GPL/DMG/settings.gradle index e69de29bb2..1092a7aaab 100644 --- a/GPL/DMG/settings.gradle +++ b/GPL/DMG/settings.gradle @@ -0,0 +1,3 @@ +/* ### + * IP: Public Domain + */ diff --git a/GPL/DemanglerGnu/build.gradle b/GPL/DemanglerGnu/build.gradle index 6244215680..0e9f80bb3f 100644 --- a/GPL/DemanglerGnu/build.gradle +++ b/GPL/DemanglerGnu/build.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ apply from: file("../gpl.gradle").getCanonicalPath() if (findProject(':Generic') != null) { diff --git a/GPL/DemanglerGnu/certification.manifest b/GPL/DemanglerGnu/certification.manifest index f3ecf6e571..6f2767e5f8 100644 --- a/GPL/DemanglerGnu/certification.manifest +++ b/GPL/DemanglerGnu/certification.manifest @@ -5,7 +5,5 @@ ##MODULE IP: LGPL 3.0 ##MODULE IP: Public Domain Module.manifest||Public Domain||||END| -build.gradle||Public Domain||||END| -settings.gradle||Public Domain||||END| src/demangler_gnu_v2_24/README.txt||Public Domain||||END| src/demangler_gnu_v2_33_1/README.txt||Public Domain||||END| diff --git a/GPL/DemanglerGnu/settings.gradle b/GPL/DemanglerGnu/settings.gradle index e69de29bb2..1092a7aaab 100644 --- a/GPL/DemanglerGnu/settings.gradle +++ b/GPL/DemanglerGnu/settings.gradle @@ -0,0 +1,3 @@ +/* ### + * IP: Public Domain + */ diff --git a/GPL/GnuDisassembler/build.gradle b/GPL/GnuDisassembler/build.gradle index e3261bf24e..0fd000d05e 100644 --- a/GPL/GnuDisassembler/build.gradle +++ b/GPL/GnuDisassembler/build.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ // If extension module does not reside within the Ghidra GPL directory, the Ghidra installation directory // must be specified either by setting the GHIDRA_INSTALL_DIR environment variable or Gradle // project property: diff --git a/GPL/GnuDisassembler/buildGdis.gradle b/GPL/GnuDisassembler/buildGdis.gradle index 2859dd073f..d145467092 100644 --- a/GPL/GnuDisassembler/buildGdis.gradle +++ b/GPL/GnuDisassembler/buildGdis.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ /******************************************************************************************* * build.gradle file that applies this script must define two properties * 1) binutilsLocation - the folder where the original binutils.zip lives diff --git a/GPL/GnuDisassembler/certification.manifest b/GPL/GnuDisassembler/certification.manifest index f439b820d8..5ef30394a2 100644 --- a/GPL/GnuDisassembler/certification.manifest +++ b/GPL/GnuDisassembler/certification.manifest @@ -4,10 +4,7 @@ .project||GHIDRA||||END| Module.manifest||Public Domain||||END| README.txt||Public Domain||||END| -build.gradle||Public Domain||||END| -buildGdis.gradle||Public Domain||||END| data/arm_test1.s||Public Domain||||END| data/big.elf||Public Domain||||END| data/little.elf||Public Domain||||END| extension.properties||Public Domain||||END| -settings.gradle||Public Domain||||END| diff --git a/GPL/GnuDisassembler/settings.gradle b/GPL/GnuDisassembler/settings.gradle index e69de29bb2..1092a7aaab 100644 --- a/GPL/GnuDisassembler/settings.gradle +++ b/GPL/GnuDisassembler/settings.gradle @@ -0,0 +1,3 @@ +/* ### + * IP: Public Domain + */ diff --git a/GPL/certification.local.manifest b/GPL/certification.local.manifest index 1d8b8c1740..6f4737a251 100644 --- a/GPL/certification.local.manifest +++ b/GPL/certification.local.manifest @@ -1,5 +1,2 @@ ##VERSION: 2.0 ##MODULE IP: Public Domain -gpl.gradle||Public Domain||||END| -nativeBuildProperties.gradle||Public Domain||||END| -vsconfig.gradle||GHIDRA||||END| diff --git a/GPL/gpl.gradle b/GPL/gpl.gradle index 9428b3bdf4..4dafd461f7 100644 --- a/GPL/gpl.gradle +++ b/GPL/gpl.gradle @@ -1,4 +1,6 @@ - +/* ### + * IP: Public Domain + */ // BIN_REPO only useable in full Ghidra source configuration project.ext.BIN_REPO = file("../../../ghidra.bin").absolutePath diff --git a/GPL/nativeBuildProperties.gradle b/GPL/nativeBuildProperties.gradle index 759e2c0ceb..36b9a07875 100644 --- a/GPL/nativeBuildProperties.gradle +++ b/GPL/nativeBuildProperties.gradle @@ -1,3 +1,6 @@ +/* ### + * IP: Public Domain + */ /**************************************************************************** * nativeBuildProperties.gradle * diff --git a/GPL/vsconfig.gradle b/GPL/vsconfig.gradle index a3e4d3c6d8..a57b7eb54a 100644 --- a/GPL/vsconfig.gradle +++ b/GPL/vsconfig.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /**************************************************************************** * Establish Visual Studio configuration environment for Windows native builds * diff --git a/Ghidra/Configurations/Public_Release/build.gradle b/Ghidra/Configurations/Public_Release/build.gradle index 9b1f4a62db..defe20000a 100644 --- a/Ghidra/Configurations/Public_Release/build.gradle +++ b/Ghidra/Configurations/Public_Release/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Configurations/Public_Release/certification.manifest b/Ghidra/Configurations/Public_Release/certification.manifest index 2e4833ec30..3a50c1b4a9 100644 --- a/Ghidra/Configurations/Public_Release/certification.manifest +++ b/Ghidra/Configurations/Public_Release/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/PDB_SYMBOL_SERVER_URLS.pdburl||GHIDRA||||END| src/global/docs/ChangeHistory.html||GHIDRA||||END| src/global/docs/UserAgreement.html||GHIDRA||||END| diff --git a/Ghidra/Extensions/SampleTablePlugin/build.gradle b/Ghidra/Extensions/SampleTablePlugin/build.gradle index b49b2ef531..5950dcfe29 100644 --- a/Ghidra/Extensions/SampleTablePlugin/build.gradle +++ b/Ghidra/Extensions/SampleTablePlugin/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraExtension.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" diff --git a/Ghidra/Extensions/SampleTablePlugin/certification.manifest b/Ghidra/Extensions/SampleTablePlugin/certification.manifest index 147e3af647..b9b2c11b56 100644 --- a/Ghidra/Extensions/SampleTablePlugin/certification.manifest +++ b/Ghidra/Extensions/SampleTablePlugin/certification.manifest @@ -2,7 +2,6 @@ ##MODULE IP: FAMFAMFAM Icons - CC 2.5 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| extension.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| diff --git a/Ghidra/Extensions/SleighDevTools/build.gradle b/Ghidra/Extensions/SleighDevTools/build.gradle index 189b77a16f..4dbcca1cae 100644 --- a/Ghidra/Extensions/SleighDevTools/build.gradle +++ b/Ghidra/Extensions/SleighDevTools/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraExtension.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" diff --git a/Ghidra/Extensions/SleighDevTools/certification.manifest b/Ghidra/Extensions/SleighDevTools/certification.manifest index 07bcf00587..4dc3953d2b 100644 --- a/Ghidra/Extensions/SleighDevTools/certification.manifest +++ b/Ghidra/Extensions/SleighDevTools/certification.manifest @@ -1,14 +1,12 @@ ##VERSION: 2.0 .project||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/LanguageMap.txt||GHIDRA||||END| extension.properties||GHIDRA||||END| pcodetest/.gitignore||GHIDRA||||END| pcodetest/README.txt||GHIDRA||||END| pcodetest/build||GHIDRA||||END| -pcodetest/build.py||GHIDRA||||END| pcodetest/c_src/BIOPS.test||GHIDRA||||END| pcodetest/c_src/BIOPS2.test||GHIDRA||||END| pcodetest/c_src/BIOPS4.test||GHIDRA||||END| @@ -28,7 +26,3 @@ pcodetest/c_src/PointerManipulation.test||GHIDRA||||END| pcodetest/c_src/StructUnionManipulation.test||GHIDRA||||END| pcodetest/c_src/misc.test||GHIDRA||||END| pcodetest/c_src/msp430x.ld||GHIDRA||||END| -pcodetest/defaults.py||GHIDRA||||END| -pcodetest/pcode_defs.py||GHIDRA||||END| -pcodetest/pcodetest.py||GHIDRA||||END| -pcodetest/tpp.py||GHIDRA||||END| diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py index 988edb84b6..ee663bb3ea 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py @@ -1,3 +1,18 @@ +## ### +# 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. +## import os import shutil import subprocess diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py index 16bd50ef87..1505aa8e20 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py @@ -1,4 +1,18 @@ - +## ### +# 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. +## # Default values can be modified here, or (in # some cases) on the build command line (see ./build --help) diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index 4a8e096ec6..c8cf6cc787 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -1,4 +1,18 @@ - +## ### +# 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. +## # The available pcode tests are recorded here as instances of the 'name' # python class. diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py index dfc796f48d..628a8759a4 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py @@ -1,3 +1,18 @@ +## ### +# 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. +## import os import glob import re diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/tpp.py b/Ghidra/Extensions/SleighDevTools/pcodetest/tpp.py index d574530166..6c6246eabe 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/tpp.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/tpp.py @@ -1,4 +1,19 @@ #!/usr/bin/python +## ### +# 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. +## import re import os diff --git a/Ghidra/Extensions/bundle_examples/build.gradle b/Ghidra/Extensions/bundle_examples/build.gradle index 7d477c15a9..4fce7fc287 100644 --- a/Ghidra/Extensions/bundle_examples/build.gradle +++ b/Ghidra/Extensions/bundle_examples/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /* This extension is different from the others. It produces a zip containing * directories of source bundles and jar bundles. * - Each source directory is added as a sourceset so that the eclipse plugin diff --git a/Ghidra/Extensions/bundle_examples/certification.manifest b/Ghidra/Extensions/bundle_examples/certification.manifest index b951f42732..7cbc96e96a 100644 --- a/Ghidra/Extensions/bundle_examples/certification.manifest +++ b/Ghidra/Extensions/bundle_examples/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| extension.properties||GHIDRA||||END| scripts_jar1/META-INF/MANIFEST.MF||GHIDRA||||END| scripts_jar2/META-INF/MANIFEST.MF||GHIDRA||||END| diff --git a/Ghidra/Extensions/sample/build.gradle b/Ghidra/Extensions/sample/build.gradle index b0e9354f12..a6a9893a0c 100644 --- a/Ghidra/Extensions/sample/build.gradle +++ b/Ghidra/Extensions/sample/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraExtension.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" diff --git a/Ghidra/Extensions/sample/certification.manifest b/Ghidra/Extensions/sample/certification.manifest index 4e6d44c844..f76dd9c0ce 100644 --- a/Ghidra/Extensions/sample/certification.manifest +++ b/Ghidra/Extensions/sample/certification.manifest @@ -2,7 +2,6 @@ ##MODULE IP: FAMFAMFAM Icons - CC 2.5 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| data/README.txt||GHIDRA||||END| extension.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| diff --git a/Ghidra/Features/Base/build.gradle b/Ghidra/Features/Base/build.gradle index 2a77bdc815..f306645e5f 100644 --- a/Ghidra/Features/Base/build.gradle +++ b/Ghidra/Features/Base/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/Base/certification.manifest b/Ghidra/Features/Base/certification.manifest index 5ce773a23f..050d44108b 100644 --- a/Ghidra/Features/Base/certification.manifest +++ b/Ghidra/Features/Base/certification.manifest @@ -13,7 +13,6 @@ .launch/Ghidra Code Coverage.launch||GHIDRA||||END| .launch/Ghidra.launch||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ElfFunctionsThatDoNotReturn||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/MachOFunctionsThatDoNotReturn||GHIDRA||||END| @@ -79,8 +78,6 @@ data/typeinfo/win32/windows_vs12_64.gdt||GHIDRA||||END| data/x64_linux_syscall_numbers||GHIDRA||||END| data/x86_linux_syscall_numbers||GHIDRA||||END| ghidra_scripts/AskScript.properties||GHIDRA||||END| -ghidra_scripts/RecursiveStringFinder.py||GHIDRA||||END| -ghidra_scripts/mark_in_out.py||GHIDRA||reviewed||END| ghidra_scripts/world.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| diff --git a/Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py b/Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py index da27f23e7d..91bd2c455b 100644 --- a/Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py +++ b/Ghidra/Features/Base/ghidra_scripts/RecursiveStringFinder.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #Given a function, find all strings used within all called funtions. # @category: Strings diff --git a/Ghidra/Features/Base/ghidra_scripts/mark_in_out.py b/Ghidra/Features/Base/ghidra_scripts/mark_in_out.py index 1e0fdbf719..8e9020ea18 100644 --- a/Ghidra/Features/Base/ghidra_scripts/mark_in_out.py +++ b/Ghidra/Features/Base/ghidra_scripts/mark_in_out.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Sets up IOPORT IN/OUT references for the Program #@category Instructions # Before running this script, you should have created an OVERLAY memory diff --git a/Ghidra/Features/BytePatterns/build.gradle b/Ghidra/Features/BytePatterns/build.gradle index df3b454780..cc529c7b50 100644 --- a/Ghidra/Features/BytePatterns/build.gradle +++ b/Ghidra/Features/BytePatterns/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/BytePatterns/certification.manifest b/Ghidra/Features/BytePatterns/certification.manifest index cf7fce5f69..67172590b3 100644 --- a/Ghidra/Features/BytePatterns/certification.manifest +++ b/Ghidra/Features/BytePatterns/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| data/test/FileBitPatternInfoReaderTestFile1.xml||GHIDRA||||END| data/test/FileBitPatternInfoReaderTestFile2.xml||GHIDRA||||END| ghidra_scripts/DumpFunctionPatternInfoScript.properties||GHIDRA||||END| diff --git a/Ghidra/Features/ByteViewer/build.gradle b/Ghidra/Features/ByteViewer/build.gradle index 7a790643e9..3a96f46ae1 100644 --- a/Ghidra/Features/ByteViewer/build.gradle +++ b/Ghidra/Features/ByteViewer/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" @@ -11,4 +26,4 @@ dependencies { compile project(':Base') helpPath project(path: ':Base', configuration: 'helpPath') // this module's help has links to Base help files -} \ No newline at end of file +} diff --git a/Ghidra/Features/ByteViewer/certification.manifest b/Ghidra/Features/ByteViewer/certification.manifest index 8639408513..65455bf81c 100644 --- a/Ghidra/Features/ByteViewer/certification.manifest +++ b/Ghidra/Features/ByteViewer/certification.manifest @@ -2,7 +2,6 @@ ##MODULE IP: FAMFAMFAM Icons - CC 2.5 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||reviewed||END| src/main/help/help/TOC_Source.xml||GHIDRA||reviewed||END| src/main/help/help/shared/arrow.gif||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/DebugUtils/build.gradle b/Ghidra/Features/DebugUtils/build.gradle index 258686549f..3dac0627cd 100644 --- a/Ghidra/Features/DebugUtils/build.gradle +++ b/Ghidra/Features/DebugUtils/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/DebugUtils/certification.manifest b/Ghidra/Features/DebugUtils/certification.manifest index e9c2fe2942..59819fa1e4 100644 --- a/Ghidra/Features/DebugUtils/certification.manifest +++ b/Ghidra/Features/DebugUtils/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Features/Decompiler/build.gradle b/Ghidra/Features/Decompiler/build.gradle index d0251eb6a9..a416ea1970 100644 --- a/Ghidra/Features/Decompiler/build.gradle +++ b/Ghidra/Features/Decompiler/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" diff --git a/Ghidra/Features/Decompiler/certification.manifest b/Ghidra/Features/Decompiler/certification.manifest index eaf5caa7ce..a1cc54689c 100644 --- a/Ghidra/Features/Decompiler/certification.manifest +++ b/Ghidra/Features/Decompiler/certification.manifest @@ -4,10 +4,8 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/decompile/.cproject||GHIDRA||||END| src/decompile/.project||GHIDRA||||END| -src/decompile/build.gradle||GHIDRA||||END| src/decompile/cpp/.gitignore||GHIDRA||||END| src/decompile/cpp/Doxyfile||GHIDRA|||Most of this file is autogenerated by doxygen which falls under the GPL - output from GPL products are NOT GPL! - mjbell4|END| src/decompile/cpp/Makefile||GHIDRA||||END| diff --git a/Ghidra/Features/Decompiler/src/decompile/build.gradle b/Ghidra/Features/Decompiler/src/decompile/build.gradle index 2d63c1643e..7ed460d20c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/build.gradle +++ b/Ghidra/Features/Decompiler/src/decompile/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' eclipse.project { name '_Decompiler' diff --git a/Ghidra/Features/DecompilerDependent/build.gradle b/Ghidra/Features/DecompilerDependent/build.gradle index f8070d5792..a822d75ba4 100644 --- a/Ghidra/Features/DecompilerDependent/build.gradle +++ b/Ghidra/Features/DecompilerDependent/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/DecompilerDependent/certification.manifest b/Ghidra/Features/DecompilerDependent/certification.manifest index ab3e50857c..b40809b58c 100644 --- a/Ghidra/Features/DecompilerDependent/certification.manifest +++ b/Ghidra/Features/DecompilerDependent/certification.manifest @@ -1,4 +1,3 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| diff --git a/Ghidra/Features/FileFormats/build.gradle b/Ghidra/Features/FileFormats/build.gradle index 37d1527f4f..d979e482c0 100644 --- a/Ghidra/Features/FileFormats/build.gradle +++ b/Ghidra/Features/FileFormats/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/FileFormats/certification.manifest b/Ghidra/Features/FileFormats/certification.manifest index b8636d6502..1a4990d500 100644 --- a/Ghidra/Features/FileFormats/certification.manifest +++ b/Ghidra/Features/FileFormats/certification.manifest @@ -8,7 +8,6 @@ ##MODULE IP: LGPL 2.1 ##MODULE IP: Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/android/eclipse-classpath||GHIDRA||reviewed||END| data/android/eclipse-project||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/FunctionGraph/build.gradle b/Ghidra/Features/FunctionGraph/build.gradle index d21bcf1347..1048607047 100644 --- a/Ghidra/Features/FunctionGraph/build.gradle +++ b/Ghidra/Features/FunctionGraph/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/FunctionGraph/certification.manifest b/Ghidra/Features/FunctionGraph/certification.manifest index aa2f88ebac..138c1e59c0 100644 --- a/Ghidra/Features/FunctionGraph/certification.manifest +++ b/Ghidra/Features/FunctionGraph/certification.manifest @@ -5,7 +5,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/build.gradle b/Ghidra/Features/FunctionGraphDecompilerExtension/build.gradle index 705253752f..5b7397bead 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/build.gradle +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/certification.manifest b/Ghidra/Features/FunctionGraphDecompilerExtension/certification.manifest index 23bc67e990..3629bb9ec9 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/certification.manifest +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/certification.manifest @@ -1,4 +1,3 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/resources/images/function_graph_code_flow.png||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/FunctionID/build.gradle b/Ghidra/Features/FunctionID/build.gradle index 71eeaddc7b..8345178732 100644 --- a/Ghidra/Features/FunctionID/build.gradle +++ b/Ghidra/Features/FunctionID/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/FunctionID/certification.manifest b/Ghidra/Features/FunctionID/certification.manifest index 324f29eb26..65d28a3a44 100644 --- a/Ghidra/Features/FunctionID/certification.manifest +++ b/Ghidra/Features/FunctionID/certification.manifest @@ -2,7 +2,6 @@ ##MODULE IP: BSD ##MODULE IP: Nuvola Icons - LGPL 2.1 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/building_fid.txt||GHIDRA||||END| data/common_symbols_win32.txt||GHIDRA|||Symbols used to generate fiddb files distributed with Ghidra|END| data/common_symbols_win64.txt||GHIDRA|||Symbols used to generate fiddb files distributed with Ghidra|END| diff --git a/Ghidra/Features/GhidraServer/build.gradle b/Ghidra/Features/GhidraServer/build.gradle index 9abd33ea21..7f063bac42 100644 --- a/Ghidra/Features/GhidraServer/build.gradle +++ b/Ghidra/Features/GhidraServer/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/GhidraServer/certification.manifest b/Ghidra/Features/GhidraServer/certification.manifest index 004e0b7c13..0a7c81fcee 100644 --- a/Ghidra/Features/GhidraServer/certification.manifest +++ b/Ghidra/Features/GhidraServer/certification.manifest @@ -3,7 +3,5 @@ ##MODULE IP: LGPL 2.1 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| -data/jaas-modules-src-1.0.3.zip||LGPL 2.1|||File corresponds to original distribution with all binary product files removed.|END| os/readme.txt||GHIDRA||||END| src/main/java/ghidra/server/remote/ServerHelp.txt||GHIDRA||||END| diff --git a/Ghidra/Features/GnuDemangler/build.gradle b/Ghidra/Features/GnuDemangler/build.gradle index 45eb344084..1a31ae95e7 100644 --- a/Ghidra/Features/GnuDemangler/build.gradle +++ b/Ghidra/Features/GnuDemangler/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/GnuDemangler/certification.manifest b/Ghidra/Features/GnuDemangler/certification.manifest index 400bcc053d..62ecec86f6 100644 --- a/Ghidra/Features/GnuDemangler/certification.manifest +++ b/Ghidra/Features/GnuDemangler/certification.manifest @@ -1,7 +1,4 @@ ##VERSION: 2.0 ##MODULE IP: BSD Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/test/resources/ghidra/app/util/demangler/gnu_mangled_names.txt||GHIDRA||reviewed||END| -src/test/resources/ghidra/app/util/demangler/gnu_mangled_names_macho.txt||GHIDRA||reviewed||END| -src/test/resources/ghidra/app/util/demangler/libMagick.symbols.txt||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/GraphFunctionCalls/build.gradle b/Ghidra/Features/GraphFunctionCalls/build.gradle index ef8e24e133..34325a620b 100644 --- a/Ghidra/Features/GraphFunctionCalls/build.gradle +++ b/Ghidra/Features/GraphFunctionCalls/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/GraphFunctionCalls/certification.manifest b/Ghidra/Features/GraphFunctionCalls/certification.manifest index a3e271c0d9..f6a0d9a87d 100644 --- a/Ghidra/Features/GraphFunctionCalls/certification.manifest +++ b/Ghidra/Features/GraphFunctionCalls/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| src/main/help/help/shared/close16.gif||GHIDRA||||END| diff --git a/Ghidra/Features/GraphServices/build.gradle b/Ghidra/Features/GraphServices/build.gradle index c41037b56d..d7234786cb 100644 --- a/Ghidra/Features/GraphServices/build.gradle +++ b/Ghidra/Features/GraphServices/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/GraphServices/certification.manifest b/Ghidra/Features/GraphServices/certification.manifest index 37be0115f7..f41d2ff5a7 100644 --- a/Ghidra/Features/GraphServices/certification.manifest +++ b/Ghidra/Features/GraphServices/certification.manifest @@ -7,7 +7,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/build.gradle b/Ghidra/Features/MicrosoftCodeAnalyzer/build.gradle index 36d50efec7..7e508f2b37 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/build.gradle +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/certification.manifest b/Ghidra/Features/MicrosoftCodeAnalyzer/certification.manifest index e9c2fe2942..59819fa1e4 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/certification.manifest +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Features/MicrosoftDemangler/build.gradle b/Ghidra/Features/MicrosoftDemangler/build.gradle index ab96797b2a..0d5d134cae 100644 --- a/Ghidra/Features/MicrosoftDemangler/build.gradle +++ b/Ghidra/Features/MicrosoftDemangler/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/MicrosoftDemangler/certification.manifest b/Ghidra/Features/MicrosoftDemangler/certification.manifest index e9c2fe2942..59819fa1e4 100644 --- a/Ghidra/Features/MicrosoftDemangler/certification.manifest +++ b/Ghidra/Features/MicrosoftDemangler/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Features/MicrosoftDmang/build.gradle b/Ghidra/Features/MicrosoftDmang/build.gradle index 87a2a0dd15..131b145bb9 100644 --- a/Ghidra/Features/MicrosoftDmang/build.gradle +++ b/Ghidra/Features/MicrosoftDmang/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" //apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/MicrosoftDmang/certification.manifest b/Ghidra/Features/MicrosoftDmang/certification.manifest index 8330c8c6dd..99d26fe55e 100644 --- a/Ghidra/Features/MicrosoftDmang/certification.manifest +++ b/Ghidra/Features/MicrosoftDmang/certification.manifest @@ -1,4 +1,3 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/java/mdemangler/MDMang_README.txt||GHIDRA||||END| diff --git a/Ghidra/Features/PDB/build.gradle b/Ghidra/Features/PDB/build.gradle index 8afedd266e..d3271f86bf 100644 --- a/Ghidra/Features/PDB/build.gradle +++ b/Ghidra/Features/PDB/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/PDB/certification.manifest b/Ghidra/Features/PDB/certification.manifest index 8dc5fd6c32..fa7172b4dc 100644 --- a/Ghidra/Features/PDB/certification.manifest +++ b/Ghidra/Features/PDB/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/global/docs/README_PDB.html||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| diff --git a/Ghidra/Features/ProgramDiff/build.gradle b/Ghidra/Features/ProgramDiff/build.gradle index bc6c9a3c5e..44f4a26937 100644 --- a/Ghidra/Features/ProgramDiff/build.gradle +++ b/Ghidra/Features/ProgramDiff/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/ProgramDiff/certification.manifest b/Ghidra/Features/ProgramDiff/certification.manifest index 8e74d3e6b9..94046642d7 100644 --- a/Ghidra/Features/ProgramDiff/certification.manifest +++ b/Ghidra/Features/ProgramDiff/certification.manifest @@ -6,7 +6,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||reviewed||END| src/main/help/help/shared/close16.gif||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/ProgramGraph/build.gradle b/Ghidra/Features/ProgramGraph/build.gradle index 9909b6bc9f..7f842dba2f 100644 --- a/Ghidra/Features/ProgramGraph/build.gradle +++ b/Ghidra/Features/ProgramGraph/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/ProgramGraph/certification.manifest b/Ghidra/Features/ProgramGraph/certification.manifest index f262a9f816..1bee5353de 100644 --- a/Ghidra/Features/ProgramGraph/certification.manifest +++ b/Ghidra/Features/ProgramGraph/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| diff --git a/Ghidra/Features/Python/build.gradle b/Ghidra/Features/Python/build.gradle index def510cae4..e90207c471 100644 --- a/Ghidra/Features/Python/build.gradle +++ b/Ghidra/Features/Python/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/Python/certification.manifest b/Ghidra/Features/Python/certification.manifest index e9152e4cfa..bbb9356524 100644 --- a/Ghidra/Features/Python/certification.manifest +++ b/Ghidra/Features/Python/certification.manifest @@ -2,26 +2,6 @@ ##MODULE IP: Jython License ##MODULE IP: LGPL 2.1 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| -ghidra_scripts/AddCommentToProgramScriptPy.py||GHIDRA||||END| -ghidra_scripts/AskScriptPy.py||GHIDRA||||END| -ghidra_scripts/CallAnotherScriptForAllProgramsPy.py||GHIDRA||||END| -ghidra_scripts/CallAnotherScriptPy.py||GHIDRA||||END| -ghidra_scripts/ChooseDataTypeScriptPy.py||GHIDRA||||END| -ghidra_scripts/ExampleColorScriptPy.py||GHIDRA||||END| -ghidra_scripts/FormatExampleScriptPy.py||GHIDRA||||END| -ghidra_scripts/ImportSymbolsScript.py||GHIDRA||||END| -ghidra_scripts/PrintNonZeroPurge.py||GHIDRA||reviewed||END| -ghidra_scripts/ToolPropertiesExampleScriptPy.py||GHIDRA||||END| -ghidra_scripts/external_module_callee.py||GHIDRA||||END| -ghidra_scripts/external_module_caller.py||GHIDRA||||END| -ghidra_scripts/ghidra_basics.py||GHIDRA||||END| -ghidra_scripts/jython_basics.py||GHIDRA||||END| -ghidra_scripts/python_basics.py||GHIDRA||||END| -python-src/ghidradoc.py||GHIDRA||||END| -python-src/introspect.py||LGPL 2.1||||END| -python-src/jintrospect.py||LGPL 2.1||||END| -python-src/sitecustomize.py||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/topics/Python/images/erase16.png||GHIDRA||||END| src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END| diff --git a/Ghidra/Features/Python/ghidra_scripts/AddCommentToProgramScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/AddCommentToProgramScriptPy.py index c7e8ef9abe..d85657ca4f 100644 --- a/Ghidra/Features/Python/ghidra_scripts/AddCommentToProgramScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/AddCommentToProgramScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Adds a comment to a program. # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py index 122973722c..b3a237b220 100644 --- a/Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/AskScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # An example of asking for user input. # Note the ability to pre-populate values for some of these variables when AskScript.properties file exists. diff --git a/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptForAllProgramsPy.py b/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptForAllProgramsPy.py index 55817241d5..82c32790d2 100644 --- a/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptForAllProgramsPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptForAllProgramsPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Shows how to run a script on all of the programs within the current project. # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptPy.py index bd2b61a954..c0d423af61 100644 --- a/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/CallAnotherScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Example of a script calling another script. # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/ChooseDataTypeScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/ChooseDataTypeScriptPy.py index cff79f88ca..be36f8fdf9 100644 --- a/Ghidra/Features/Python/ghidra_scripts/ChooseDataTypeScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/ChooseDataTypeScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Example of a script prompting the user for a data type. # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/ExampleColorScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/ExampleColorScriptPy.py index 7e7bc27996..39da09d7ce 100644 --- a/Ghidra/Features/Python/ghidra_scripts/ExampleColorScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/ExampleColorScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # An example of how to color the listing background # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/FormatExampleScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/FormatExampleScriptPy.py index f9930d6398..01192093a3 100644 --- a/Ghidra/Features/Python/ghidra_scripts/FormatExampleScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/FormatExampleScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # An example using the Python string formatting. # See FormatExampleScript.java for examples of using the printf() method. diff --git a/Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py b/Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py index f0e952f62f..b0a05f4e62 100644 --- a/Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py +++ b/Ghidra/Features/Python/ghidra_scripts/ImportSymbolsScript.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Imports a file with lines in the form "symbolName 0xADDRESS function_or_label" where "f" indicates a function and "l" a label # @author unkown; edited by matedealer # @category Data diff --git a/Ghidra/Features/Python/ghidra_scripts/PrintNonZeroPurge.py b/Ghidra/Features/Python/ghidra_scripts/PrintNonZeroPurge.py index c6ccbb9e4b..a92323676a 100644 --- a/Ghidra/Features/Python/ghidra_scripts/PrintNonZeroPurge.py +++ b/Ghidra/Features/Python/ghidra_scripts/PrintNonZeroPurge.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Prints out all the functions in the program that have a non-zero stack purge size for func in currentProgram.getFunctionManager().getFunctions(currentProgram.evaluateAddress("0"), 1): diff --git a/Ghidra/Features/Python/ghidra_scripts/ToolPropertiesExampleScriptPy.py b/Ghidra/Features/Python/ghidra_scripts/ToolPropertiesExampleScriptPy.py index c68205a514..ff082b2ea6 100644 --- a/Ghidra/Features/Python/ghidra_scripts/ToolPropertiesExampleScriptPy.py +++ b/Ghidra/Features/Python/ghidra_scripts/ToolPropertiesExampleScriptPy.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Writes properties to the tool. # DISCLAIMER: This is a recreation of a Java Ghidra script for example diff --git a/Ghidra/Features/Python/ghidra_scripts/external_module_callee.py b/Ghidra/Features/Python/ghidra_scripts/external_module_callee.py index 2527b0f456..0444128956 100644 --- a/Ghidra/Features/Python/ghidra_scripts/external_module_callee.py +++ b/Ghidra/Features/Python/ghidra_scripts/external_module_callee.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Example of being imported by a Ghidra Python script/module # @category: Examples.Python diff --git a/Ghidra/Features/Python/ghidra_scripts/external_module_caller.py b/Ghidra/Features/Python/ghidra_scripts/external_module_caller.py index f5e437550b..cbe32a5b86 100644 --- a/Ghidra/Features/Python/ghidra_scripts/external_module_caller.py +++ b/Ghidra/Features/Python/ghidra_scripts/external_module_caller.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Example of importing an external Ghidra Python module # @category: Examples.Python diff --git a/Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py b/Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py index f074006572..8828e19c10 100644 --- a/Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py +++ b/Ghidra/Features/Python/ghidra_scripts/ghidra_basics.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Examples of basic Ghidra scripting in Python # @category: Examples.Python diff --git a/Ghidra/Features/Python/ghidra_scripts/jython_basics.py b/Ghidra/Features/Python/ghidra_scripts/jython_basics.py index 5153ee826b..3dc3cd8347 100644 --- a/Ghidra/Features/Python/ghidra_scripts/jython_basics.py +++ b/Ghidra/Features/Python/ghidra_scripts/jython_basics.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Examples of Jython-specific functionality # @category: Examples.Python diff --git a/Ghidra/Features/Python/ghidra_scripts/python_basics.py b/Ghidra/Features/Python/ghidra_scripts/python_basics.py index e6a7e1ea15..dff8d2f2b5 100644 --- a/Ghidra/Features/Python/ghidra_scripts/python_basics.py +++ b/Ghidra/Features/Python/ghidra_scripts/python_basics.py @@ -1,3 +1,18 @@ +## ### +# 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. +## # Examples of basic Python # @category: Examples.Python diff --git a/Ghidra/Features/Python/python-src/ghidradoc.py b/Ghidra/Features/Python/python-src/ghidradoc.py index 02a9bd9224..38b6d6f569 100644 --- a/Ghidra/Features/Python/python-src/ghidradoc.py +++ b/Ghidra/Features/Python/python-src/ghidradoc.py @@ -1,3 +1,18 @@ +## ### +# 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. +## """ Ties the Ghidra documentation into the builtin Python help. """ diff --git a/Ghidra/Features/Python/python-src/introspect.py b/Ghidra/Features/Python/python-src/introspect.py index 572e72a2dc..cf5097b321 100644 --- a/Ghidra/Features/Python/python-src/introspect.py +++ b/Ghidra/Features/Python/python-src/introspect.py @@ -1,3 +1,6 @@ +## ### +# IP: LGPL 2.1 +## """ Provides a variety of introspective-type support functions for things like call tips and command auto completion. diff --git a/Ghidra/Features/Python/python-src/jintrospect.py b/Ghidra/Features/Python/python-src/jintrospect.py index 78a4e5ac5f..0ffb437501 100644 --- a/Ghidra/Features/Python/python-src/jintrospect.py +++ b/Ghidra/Features/Python/python-src/jintrospect.py @@ -1,3 +1,6 @@ +## ### +# IP: LGPL 2.1 +## """Extend introspect.py for Java based Jython classes.""" from introspect import * diff --git a/Ghidra/Features/Python/python-src/sitecustomize.py b/Ghidra/Features/Python/python-src/sitecustomize.py index a894635986..f558061867 100644 --- a/Ghidra/Features/Python/python-src/sitecustomize.py +++ b/Ghidra/Features/Python/python-src/sitecustomize.py @@ -1,3 +1,18 @@ +## ### +# 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. +## """ User-supplied customizations go here. """ diff --git a/Ghidra/Features/Recognizers/build.gradle b/Ghidra/Features/Recognizers/build.gradle index aa500309c1..d1249469ba 100644 --- a/Ghidra/Features/Recognizers/build.gradle +++ b/Ghidra/Features/Recognizers/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Features/Recognizers/certification.manifest b/Ghidra/Features/Recognizers/certification.manifest index f71f17ca25..895ac4b698 100644 --- a/Ghidra/Features/Recognizers/certification.manifest +++ b/Ghidra/Features/Recognizers/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Features/SourceCodeLookup/build.gradle b/Ghidra/Features/SourceCodeLookup/build.gradle index a7af785046..84fdd5747a 100644 --- a/Ghidra/Features/SourceCodeLookup/build.gradle +++ b/Ghidra/Features/SourceCodeLookup/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/SourceCodeLookup/certification.manifest b/Ghidra/Features/SourceCodeLookup/certification.manifest index 74b0c57419..f9dc882491 100644 --- a/Ghidra/Features/SourceCodeLookup/certification.manifest +++ b/Ghidra/Features/SourceCodeLookup/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||reviewed||END| src/main/help/help/shared/close16.gif||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/VersionTracking/build.gradle b/Ghidra/Features/VersionTracking/build.gradle index 4ea07d1ea0..69651c5307 100644 --- a/Ghidra/Features/VersionTracking/build.gradle +++ b/Ghidra/Features/VersionTracking/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle" diff --git a/Ghidra/Features/VersionTracking/certification.manifest b/Ghidra/Features/VersionTracking/certification.manifest index ff365641b7..1c3c497aa1 100644 --- a/Ghidra/Features/VersionTracking/certification.manifest +++ b/Ghidra/Features/VersionTracking/certification.manifest @@ -4,7 +4,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||reviewed||END| src/main/docs/VTClasses.png||GHIDRA||reviewed||END| src/main/docs/VTGuiImpl.png||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/DB/build.gradle b/Ghidra/Framework/DB/build.gradle index 5b9a44c1b1..52b09a8c59 100644 --- a/Ghidra/Framework/DB/build.gradle +++ b/Ghidra/Framework/DB/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/DB/certification.manifest b/Ghidra/Framework/DB/certification.manifest index e9c2fe2942..59819fa1e4 100644 --- a/Ghidra/Framework/DB/certification.manifest +++ b/Ghidra/Framework/DB/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Framework/Docking/build.gradle b/Ghidra/Framework/Docking/build.gradle index 1e5d0bc936..8b9cb8f350 100644 --- a/Ghidra/Framework/Docking/build.gradle +++ b/Ghidra/Framework/Docking/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/Docking/certification.manifest b/Ghidra/Framework/Docking/certification.manifest index 09bc1820c1..73dbb93274 100644 --- a/Ghidra/Framework/Docking/certification.manifest +++ b/Ghidra/Framework/Docking/certification.manifest @@ -9,7 +9,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| src/main/java/docking/dnd/package.html||GHIDRA||reviewed||END| src/main/java/docking/options/editor/package.html||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/FileSystem/build.gradle b/Ghidra/Framework/FileSystem/build.gradle index d06d61d66d..71d812923b 100644 --- a/Ghidra/Framework/FileSystem/build.gradle +++ b/Ghidra/Framework/FileSystem/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/FileSystem/certification.manifest b/Ghidra/Framework/FileSystem/certification.manifest index 5fc5d93192..00b0b476dc 100644 --- a/Ghidra/Framework/FileSystem/certification.manifest +++ b/Ghidra/Framework/FileSystem/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 ##MODULE IP: Christian Plattner Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| src/main/java/ghidra/framework/client/package.html||GHIDRA||reviewed||END| src/main/java/ghidra/framework/store/db/package.html||GHIDRA||reviewed||END| src/main/java/ghidra/framework/store/local/package.html||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/Generic/build.gradle b/Ghidra/Framework/Generic/build.gradle index 85bd661429..3d08b7b2ee 100644 --- a/Ghidra/Framework/Generic/build.gradle +++ b/Ghidra/Framework/Generic/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import org.gradle.plugins.ide.eclipse.model.Container; apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" diff --git a/Ghidra/Framework/Generic/certification.manifest b/Ghidra/Framework/Generic/certification.manifest index a876cd6b97..98b3050263 100644 --- a/Ghidra/Framework/Generic/certification.manifest +++ b/Ghidra/Framework/Generic/certification.manifest @@ -13,7 +13,6 @@ .classpath||GHIDRA||||END| .gitignore||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| src/main/java/ghidra/framework/options/package.html||GHIDRA||||END| src/main/java/ghidra/util/datastruct/package.html||GHIDRA||||END| diff --git a/Ghidra/Framework/Graph/build.gradle b/Ghidra/Framework/Graph/build.gradle index 5299bfee78..aac38c8cfc 100644 --- a/Ghidra/Framework/Graph/build.gradle +++ b/Ghidra/Framework/Graph/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/Graph/certification.manifest b/Ghidra/Framework/Graph/certification.manifest index fce51b0701..88fad779eb 100644 --- a/Ghidra/Framework/Graph/certification.manifest +++ b/Ghidra/Framework/Graph/certification.manifest @@ -4,7 +4,6 @@ ##MODULE IP: LGPL 2.1 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| src/main/docs/README.txt||GHIDRA||||END| src/main/docs/VerticesAndEdges.png||GHIDRA||||END| diff --git a/Ghidra/Framework/Help/build.gradle b/Ghidra/Framework/Help/build.gradle index 8c093c2fd0..3edc1d384e 100644 --- a/Ghidra/Framework/Help/build.gradle +++ b/Ghidra/Framework/Help/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/Help/certification.manifest b/Ghidra/Framework/Help/certification.manifest index c278982bf7..3f4edc2be2 100644 --- a/Ghidra/Framework/Help/certification.manifest +++ b/Ghidra/Framework/Help/certification.manifest @@ -1,4 +1,3 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| build.files/buildLocalHelp.xml||GHIDRA||||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Framework/Project/build.gradle b/Ghidra/Framework/Project/build.gradle index ae475dda9d..ff761f1295 100644 --- a/Ghidra/Framework/Project/build.gradle +++ b/Ghidra/Framework/Project/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/Project/certification.manifest b/Ghidra/Framework/Project/certification.manifest index e5e4012a60..33fb5791dc 100644 --- a/Ghidra/Framework/Project/certification.manifest +++ b/Ghidra/Framework/Project/certification.manifest @@ -6,7 +6,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| src/main/java/ghidra/framework/cmd/package.html||GHIDRA||reviewed||END| src/main/java/ghidra/framework/data/package.html||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/SoftwareModeling/build.gradle b/Ghidra/Framework/SoftwareModeling/build.gradle index e6fcb43727..69b99eef0b 100644 --- a/Ghidra/Framework/SoftwareModeling/build.gradle +++ b/Ghidra/Framework/SoftwareModeling/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/SoftwareModeling/certification.manifest b/Ghidra/Framework/SoftwareModeling/certification.manifest index d467ee2798..7cbd0c11ee 100644 --- a/Ghidra/Framework/SoftwareModeling/certification.manifest +++ b/Ghidra/Framework/SoftwareModeling/certification.manifest @@ -4,7 +4,6 @@ ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| Sleigh.launch||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/charset_info.xml||GHIDRA||||END| data/languages/Steps to creation of Format Opinion.txt||GHIDRA||||END| diff --git a/Ghidra/Framework/Utility/build.gradle b/Ghidra/Framework/Utility/build.gradle index aec793639f..8c93d86ce6 100644 --- a/Ghidra/Framework/Utility/build.gradle +++ b/Ghidra/Framework/Utility/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Framework/Utility/certification.manifest b/Ghidra/Framework/Utility/certification.manifest index e9c2fe2942..59819fa1e4 100644 --- a/Ghidra/Framework/Utility/certification.manifest +++ b/Ghidra/Framework/Utility/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Processors/6502/build.gradle b/Ghidra/Processors/6502/build.gradle index 19922fb763..1e81b0c56d 100644 --- a/Ghidra/Processors/6502/build.gradle +++ b/Ghidra/Processors/6502/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/6502/certification.manifest b/Ghidra/Processors/6502/certification.manifest index 5d52c8a399..dd4024fa4b 100644 --- a/Ghidra/Processors/6502/certification.manifest +++ b/Ghidra/Processors/6502/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/6502.cspec||GHIDRA||||END| data/languages/6502.ldefs||GHIDRA||||END| data/languages/6502.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/68000/build.gradle b/Ghidra/Processors/68000/build.gradle index 4a4f702375..698ab158ff 100644 --- a/Ghidra/Processors/68000/build.gradle +++ b/Ghidra/Processors/68000/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/68000/certification.manifest b/Ghidra/Processors/68000/certification.manifest index 1ddea5457a..a774c7da11 100644 --- a/Ghidra/Processors/68000/certification.manifest +++ b/Ghidra/Processors/68000/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/68000.cspec||GHIDRA||||END| data/languages/68000.ldefs||GHIDRA||||END| data/languages/68000.opinion||GHIDRA||||END| diff --git a/Ghidra/Processors/6805/build.gradle b/Ghidra/Processors/6805/build.gradle index 6410b3cefd..e8bd414da7 100644 --- a/Ghidra/Processors/6805/build.gradle +++ b/Ghidra/Processors/6805/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/6805/certification.manifest b/Ghidra/Processors/6805/certification.manifest index c74eab693d..c78ef5c3de 100644 --- a/Ghidra/Processors/6805/certification.manifest +++ b/Ghidra/Processors/6805/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/6805.cspec||GHIDRA||||END| data/languages/6805.ldefs||GHIDRA||||END| data/languages/6805.pspec||GHIDRA||reviewed||END| diff --git a/Ghidra/Processors/8048/build.gradle b/Ghidra/Processors/8048/build.gradle index 7820c04b5f..191d1c55ca 100644 --- a/Ghidra/Processors/8048/build.gradle +++ b/Ghidra/Processors/8048/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/8048/certification.manifest b/Ghidra/Processors/8048/certification.manifest index 66aeeec38b..04a77a7ea4 100644 --- a/Ghidra/Processors/8048/certification.manifest +++ b/Ghidra/Processors/8048/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/8048.cspec||GHIDRA||||END| data/languages/8048.ldefs||GHIDRA||||END| data/languages/8048.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/8051/build.gradle b/Ghidra/Processors/8051/build.gradle index 5df5cecacf..81c27c5989 100644 --- a/Ghidra/Processors/8051/build.gradle +++ b/Ghidra/Processors/8051/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" @@ -7,4 +22,4 @@ eclipse.project.name = 'Processors 8051' dependencies { compile project(':Base') -} \ No newline at end of file +} diff --git a/Ghidra/Processors/8051/certification.manifest b/Ghidra/Processors/8051/certification.manifest index 6a6e7a6b09..fc6cfe4588 100644 --- a/Ghidra/Processors/8051/certification.manifest +++ b/Ghidra/Processors/8051/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/80251.cspec||GHIDRA||||END| data/languages/80251.pspec||GHIDRA||reviewed||END| data/languages/80251.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/8085/build.gradle b/Ghidra/Processors/8085/build.gradle index 38b2f7e46c..746a524019 100644 --- a/Ghidra/Processors/8085/build.gradle +++ b/Ghidra/Processors/8085/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/8085/certification.manifest b/Ghidra/Processors/8085/certification.manifest index ea3416f72a..e3af5827ad 100644 --- a/Ghidra/Processors/8085/certification.manifest +++ b/Ghidra/Processors/8085/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/8085.cspec||GHIDRA||||END| data/languages/8085.ldefs||GHIDRA||reviewed||END| data/languages/8085.pspec||GHIDRA||reviewed||END| diff --git a/Ghidra/Processors/AARCH64/build.gradle b/Ghidra/Processors/AARCH64/build.gradle index 5b7ba0fbb8..a184b52203 100644 --- a/Ghidra/Processors/AARCH64/build.gradle +++ b/Ghidra/Processors/AARCH64/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/AARCH64/certification.manifest b/Ghidra/Processors/AARCH64/certification.manifest index f5f4ede4a3..3b92c67ff2 100644 --- a/Ghidra/Processors/AARCH64/certification.manifest +++ b/Ghidra/Processors/AARCH64/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/aarch64-pltThunks.xml||GHIDRA||||END| data/languages/AARCH64.cspec||GHIDRA||||END| data/languages/AARCH64.dwarf||GHIDRA||||END| diff --git a/Ghidra/Processors/ARM/build.gradle b/Ghidra/Processors/ARM/build.gradle index 8d5255a939..1bcf1dd9ce 100644 --- a/Ghidra/Processors/ARM/build.gradle +++ b/Ghidra/Processors/ARM/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/ARM/certification.manifest b/Ghidra/Processors/ARM/certification.manifest index 834c26df97..40ae34598a 100644 --- a/Ghidra/Processors/ARM/certification.manifest +++ b/Ghidra/Processors/ARM/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/ARM.cspec||GHIDRA||||END| data/languages/ARM.dwarf||GHIDRA||||END| data/languages/ARM.gdis||GHIDRA||||END| diff --git a/Ghidra/Processors/Atmel/build.gradle b/Ghidra/Processors/Atmel/build.gradle index efc171ec2a..87e8fafedd 100644 --- a/Ghidra/Processors/Atmel/build.gradle +++ b/Ghidra/Processors/Atmel/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/Atmel/certification.manifest b/Ghidra/Processors/Atmel/certification.manifest index c5845744c7..92392fc879 100644 --- a/Ghidra/Processors/Atmel/certification.manifest +++ b/Ghidra/Processors/Atmel/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/atmega256.pspec||GHIDRA||||END| data/languages/avr32.opinion||GHIDRA||||END| data/languages/avr32a.cspec||GHIDRA||||END| diff --git a/Ghidra/Processors/CP1600/build.gradle b/Ghidra/Processors/CP1600/build.gradle index 1ca31f7030..c873bc7447 100644 --- a/Ghidra/Processors/CP1600/build.gradle +++ b/Ghidra/Processors/CP1600/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/CP1600/certification.manifest b/Ghidra/Processors/CP1600/certification.manifest index a1b17c8f45..ec1036e386 100644 --- a/Ghidra/Processors/CP1600/certification.manifest +++ b/Ghidra/Processors/CP1600/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/CP1600.cspec||GHIDRA||||END| data/languages/CP1600.ldefs||GHIDRA||||END| data/languages/CP1600.opinion||GHIDRA||||END| diff --git a/Ghidra/Processors/CR16/build.gradle b/Ghidra/Processors/CR16/build.gradle index 9be96730e1..c14ddbda40 100644 --- a/Ghidra/Processors/CR16/build.gradle +++ b/Ghidra/Processors/CR16/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/CR16/certification.manifest b/Ghidra/Processors/CR16/certification.manifest index a45e792966..722e9fa2d1 100644 --- a/Ghidra/Processors/CR16/certification.manifest +++ b/Ghidra/Processors/CR16/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/CR16.cspec||GHIDRA||||END| data/languages/CR16.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/DATA/build.gradle b/Ghidra/Processors/DATA/build.gradle index c284bfba59..b6979754d2 100644 --- a/Ghidra/Processors/DATA/build.gradle +++ b/Ghidra/Processors/DATA/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/DATA/certification.manifest b/Ghidra/Processors/DATA/certification.manifest index 6ea30740ec..9dd5cce35c 100644 --- a/Ghidra/Processors/DATA/certification.manifest +++ b/Ghidra/Processors/DATA/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/data-be-64.slaspec||GHIDRA||||END| data/languages/data-le-64.slaspec||GHIDRA||||END| data/languages/data-ptr16.cspec||GHIDRA||||END| diff --git a/Ghidra/Processors/Dalvik/build.gradle b/Ghidra/Processors/Dalvik/build.gradle index ad5025cd4f..04d0d1c4b6 100644 --- a/Ghidra/Processors/Dalvik/build.gradle +++ b/Ghidra/Processors/Dalvik/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/Dalvik/certification.manifest b/Ghidra/Processors/Dalvik/certification.manifest index 2edfe5ab2f..27441d891a 100644 --- a/Ghidra/Processors/Dalvik/certification.manifest +++ b/Ghidra/Processors/Dalvik/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/Dalvik.cspec||GHIDRA||||END| data/languages/Dalvik.ldefs||GHIDRA||||END| data/languages/Dalvik.opinion||GHIDRA||||END| diff --git a/Ghidra/Processors/HCS08/build.gradle b/Ghidra/Processors/HCS08/build.gradle index 1179f4c831..abfbc53f50 100644 --- a/Ghidra/Processors/HCS08/build.gradle +++ b/Ghidra/Processors/HCS08/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' @@ -5,4 +20,4 @@ eclipse.project.name = 'Processors HCS08' sleighCompileOptions = [ '-l' -] \ No newline at end of file +] diff --git a/Ghidra/Processors/HCS08/certification.manifest b/Ghidra/Processors/HCS08/certification.manifest index 1e7ebca2c6..45829ad2f2 100644 --- a/Ghidra/Processors/HCS08/certification.manifest +++ b/Ghidra/Processors/HCS08/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 .project||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/HC05-M68HC05TB.pspec||GHIDRA||||END| data/languages/HC05.ldefs||GHIDRA||||END| data/languages/HC05.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/HCS12/build.gradle b/Ghidra/Processors/HCS12/build.gradle index 6b09957287..ac4fd90b60 100644 --- a/Ghidra/Processors/HCS12/build.gradle +++ b/Ghidra/Processors/HCS12/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/HCS12/certification.manifest b/Ghidra/Processors/HCS12/certification.manifest index 929bc8b859..f937883ee8 100644 --- a/Ghidra/Processors/HCS12/certification.manifest +++ b/Ghidra/Processors/HCS12/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 .project||NONE||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/HCS12.cspec||GHIDRA||||END| data/languages/HCS12.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/JVM/build.gradle b/Ghidra/Processors/JVM/build.gradle index c5386f521c..9b79a6d7e9 100644 --- a/Ghidra/Processors/JVM/build.gradle +++ b/Ghidra/Processors/JVM/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/JVM/certification.manifest b/Ghidra/Processors/JVM/certification.manifest index bdccd4e08c..797321d013 100644 --- a/Ghidra/Processors/JVM/certification.manifest +++ b/Ghidra/Processors/JVM/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/JVM.cspec||GHIDRA||||END| diff --git a/Ghidra/Processors/M8C/build.gradle b/Ghidra/Processors/M8C/build.gradle index 802ade22af..81d067d214 100644 --- a/Ghidra/Processors/M8C/build.gradle +++ b/Ghidra/Processors/M8C/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/M8C/certification.manifest b/Ghidra/Processors/M8C/certification.manifest index 609af3616b..23e0908606 100644 --- a/Ghidra/Processors/M8C/certification.manifest +++ b/Ghidra/Processors/M8C/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 .project||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/m8c.cspec||GHIDRA||||END| data/languages/m8c.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/MCS96/build.gradle b/Ghidra/Processors/MCS96/build.gradle index 5a07259134..f202e53bfe 100644 --- a/Ghidra/Processors/MCS96/build.gradle +++ b/Ghidra/Processors/MCS96/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' @@ -5,4 +20,4 @@ eclipse.project.name = 'Processors MCS96' sleighCompileOptions = [ '-l' -] \ No newline at end of file +] diff --git a/Ghidra/Processors/MCS96/certification.manifest b/Ghidra/Processors/MCS96/certification.manifest index a5f509ce48..58727804c3 100644 --- a/Ghidra/Processors/MCS96/certification.manifest +++ b/Ghidra/Processors/MCS96/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 .project||NONE||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/MCS96.cspec||GHIDRA||||END| data/languages/MCS96.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/MIPS/build.gradle b/Ghidra/Processors/MIPS/build.gradle index 55ce8fe56b..248ec6c368 100644 --- a/Ghidra/Processors/MIPS/build.gradle +++ b/Ghidra/Processors/MIPS/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/MIPS/certification.manifest b/Ghidra/Processors/MIPS/certification.manifest index 7b7adb054a..182ff5a607 100644 --- a/Ghidra/Processors/MIPS/certification.manifest +++ b/Ghidra/Processors/MIPS/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/MIPS.opinion||GHIDRA||||END| data/languages/mips.dwarf||GHIDRA||||END| data/languages/mips.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/PA-RISC/build.gradle b/Ghidra/Processors/PA-RISC/build.gradle index 469e3de76f..b76c05a131 100644 --- a/Ghidra/Processors/PA-RISC/build.gradle +++ b/Ghidra/Processors/PA-RISC/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/PA-RISC/certification.manifest b/Ghidra/Processors/PA-RISC/certification.manifest index c61d4e2694..46653811f0 100644 --- a/Ghidra/Processors/PA-RISC/certification.manifest +++ b/Ghidra/Processors/PA-RISC/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/pa-risc.ldefs||GHIDRA||||END| data/languages/pa-risc.opinion||GHIDRA||||END| data/languages/pa-risc.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/PIC/build.gradle b/Ghidra/Processors/PIC/build.gradle index 035249f479..ad06dc5e85 100644 --- a/Ghidra/Processors/PIC/build.gradle +++ b/Ghidra/Processors/PIC/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/PIC/certification.manifest b/Ghidra/Processors/PIC/certification.manifest index 02c390faf2..6169980ba8 100644 --- a/Ghidra/Processors/PIC/certification.manifest +++ b/Ghidra/Processors/PIC/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/PIC24.cspec||GHIDRA||||END| data/languages/PIC24.ldefs||GHIDRA||||END| data/languages/PIC24.opinion||GHIDRA||||END| diff --git a/Ghidra/Processors/PowerPC/build.gradle b/Ghidra/Processors/PowerPC/build.gradle index 234b8724b9..6d2e93f237 100644 --- a/Ghidra/Processors/PowerPC/build.gradle +++ b/Ghidra/Processors/PowerPC/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/PowerPC/certification.manifest b/Ghidra/Processors/PowerPC/certification.manifest index 9ec01974b6..c8d1018562 100644 --- a/Ghidra/Processors/PowerPC/certification.manifest +++ b/Ghidra/Processors/PowerPC/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/4xx.sinc||GHIDRA||||END| data/languages/FPRC.sinc||GHIDRA||||END| data/languages/PowerPC.opinion||GHIDRA||||END| diff --git a/Ghidra/Processors/RISCV/build.gradle b/Ghidra/Processors/RISCV/build.gradle index 9f5dcab806..44af91475f 100644 --- a/Ghidra/Processors/RISCV/build.gradle +++ b/Ghidra/Processors/RISCV/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/RISCV/certification.manifest b/Ghidra/Processors/RISCV/certification.manifest index aff3d4083a..bfd5d6e090 100644 --- a/Ghidra/Processors/RISCV/certification.manifest +++ b/Ghidra/Processors/RISCV/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/RV32G.pspec||GHIDRA||||END| data/languages/RV32GC.pspec||GHIDRA||||END| data/languages/RV32I.pspec||GHIDRA||||END| @@ -49,4 +48,3 @@ data/languages/riscv64.cspec||GHIDRA||||END| data/languages/riscv64.dwarf||GHIDRA||||END| data/patterns/patterncontraints.xml||GHIDRA||||END| data/patterns/riscv_gc_patterns.xml||GHIDRA||||END| -scripts/binutil.py||GHIDRA||||END| diff --git a/Ghidra/Processors/RISCV/scripts/binutil.py b/Ghidra/Processors/RISCV/scripts/binutil.py index 7ebffaf5a3..d54e0965db 100644 --- a/Ghidra/Processors/RISCV/scripts/binutil.py +++ b/Ghidra/Processors/RISCV/scripts/binutil.py @@ -1,4 +1,19 @@ #!/usr/bin/env python3 +## ### +# 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. +## """Script to generate base RISC-V SLEIGH for Ghidra module Just an artifact to keep around for the development at this point as a lot of diff --git a/Ghidra/Processors/Sparc/build.gradle b/Ghidra/Processors/Sparc/build.gradle index c7cdb84a55..4446cb87ec 100644 --- a/Ghidra/Processors/Sparc/build.gradle +++ b/Ghidra/Processors/Sparc/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/Sparc/certification.manifest b/Ghidra/Processors/Sparc/certification.manifest index 27e7452c7f..07c1863138 100644 --- a/Ghidra/Processors/Sparc/certification.manifest +++ b/Ghidra/Processors/Sparc/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/Sparc.opinion||GHIDRA||||END| data/languages/SparcV9.ldefs||GHIDRA||||END| data/languages/SparcV9.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/SuperH/build.gradle b/Ghidra/Processors/SuperH/build.gradle index 939d907a81..ac2896e57c 100644 --- a/Ghidra/Processors/SuperH/build.gradle +++ b/Ghidra/Processors/SuperH/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/SuperH/certification.manifest b/Ghidra/Processors/SuperH/certification.manifest index 2b74928187..4b01ebe8d5 100644 --- a/Ghidra/Processors/SuperH/certification.manifest +++ b/Ghidra/Processors/SuperH/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/sh-1.slaspec||GHIDRA||||END| data/languages/sh-2.slaspec||GHIDRA||||END| data/languages/sh-2a.slaspec||GHIDRA||||END| diff --git a/Ghidra/Processors/SuperH4/build.gradle b/Ghidra/Processors/SuperH4/build.gradle index c8c9ab6cbd..0d6c873afc 100644 --- a/Ghidra/Processors/SuperH4/build.gradle +++ b/Ghidra/Processors/SuperH4/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" @@ -8,4 +23,4 @@ eclipse.project.name = 'Processors SuperH4' dependencies { compile project(':Base') -} \ No newline at end of file +} diff --git a/Ghidra/Processors/SuperH4/certification.manifest b/Ghidra/Processors/SuperH4/certification.manifest index 915d68d36f..aec5c94df1 100644 --- a/Ghidra/Processors/SuperH4/certification.manifest +++ b/Ghidra/Processors/SuperH4/certification.manifest @@ -1,7 +1,6 @@ ##VERSION: 2.0 .project||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/SuperH4.cspec||GHIDRA||||END| data/languages/SuperH4.ldefs||GHIDRA||||END| diff --git a/Ghidra/Processors/TI_MSP430/build.gradle b/Ghidra/Processors/TI_MSP430/build.gradle index 1a7595747d..27bb5d2cbe 100644 --- a/Ghidra/Processors/TI_MSP430/build.gradle +++ b/Ghidra/Processors/TI_MSP430/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/TI_MSP430/certification.manifest b/Ghidra/Processors/TI_MSP430/certification.manifest index 9d0f42245b..6f3226852c 100644 --- a/Ghidra/Processors/TI_MSP430/certification.manifest +++ b/Ghidra/Processors/TI_MSP430/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/TI430Common.sinc||GHIDRA||||END| data/languages/TI430X.sinc||GHIDRA||||END| data/languages/TI_MSP430.cspec||GHIDRA||||END| diff --git a/Ghidra/Processors/Toy/build.gradle b/Ghidra/Processors/Toy/build.gradle index b0dda1d293..ef4e13d4fd 100644 --- a/Ghidra/Processors/Toy/build.gradle +++ b/Ghidra/Processors/Toy/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/Toy/certification.manifest b/Ghidra/Processors/Toy/certification.manifest index 46becba890..c9e9252d33 100644 --- a/Ghidra/Processors/Toy/certification.manifest +++ b/Ghidra/Processors/Toy/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/old/ToyV00BE64.lang||GHIDRA||||END| data/languages/old/ToyV0BE64.trans||GHIDRA||||END| data/languages/old/ToyV0LE64.lang||GHIDRA||||END| diff --git a/Ghidra/Processors/V850/build.gradle b/Ghidra/Processors/V850/build.gradle index 3eb5e73f9b..b5b745ae39 100644 --- a/Ghidra/Processors/V850/build.gradle +++ b/Ghidra/Processors/V850/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" diff --git a/Ghidra/Processors/V850/certification.manifest b/Ghidra/Processors/V850/certification.manifest index 1e043949c1..f824c150ff 100644 --- a/Ghidra/Processors/V850/certification.manifest +++ b/Ghidra/Processors/V850/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/Helpers/Conditions.sinc||GHIDRA||||END| data/languages/Helpers/Extras.sinc||GHIDRA||||END| data/languages/Helpers/Macros.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/Z80/build.gradle b/Ghidra/Processors/Z80/build.gradle index e8e3ba898e..b59b151b6f 100644 --- a/Ghidra/Processors/Z80/build.gradle +++ b/Ghidra/Processors/Z80/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Processors/Z80/certification.manifest b/Ghidra/Processors/Z80/certification.manifest index 28c793bab7..9a5ecf115a 100644 --- a/Ghidra/Processors/Z80/certification.manifest +++ b/Ghidra/Processors/Z80/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/z180.pspec||GHIDRA||||END| data/languages/z180.slaspec||GHIDRA||||END| data/languages/z182.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/tricore/build.gradle b/Ghidra/Processors/tricore/build.gradle index 66e9def252..99c345a72c 100644 --- a/Ghidra/Processors/tricore/build.gradle +++ b/Ghidra/Processors/tricore/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/tricore/certification.manifest b/Ghidra/Processors/tricore/certification.manifest index 7829345bae..16fb071bb3 100644 --- a/Ghidra/Processors/tricore/certification.manifest +++ b/Ghidra/Processors/tricore/certification.manifest @@ -2,7 +2,6 @@ .classpath||GHIDRA||||END| .project||GHIDRA||||END| Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/build.xml||GHIDRA||||END| data/languages/tc172x.pspec||GHIDRA||||END| data/languages/tc176x.pspec||GHIDRA||||END| diff --git a/Ghidra/Processors/x86/build.gradle b/Ghidra/Processors/x86/build.gradle index 756d4b965f..536eaed49a 100644 --- a/Ghidra/Processors/x86/build.gradle +++ b/Ghidra/Processors/x86/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" diff --git a/Ghidra/Processors/x86/certification.manifest b/Ghidra/Processors/x86/certification.manifest index 521374d29f..f5a07f0c15 100644 --- a/Ghidra/Processors/x86/certification.manifest +++ b/Ghidra/Processors/x86/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| data/languages/adx.sinc||GHIDRA||||END| data/languages/avx.sinc||GHIDRA||||END| data/languages/avx2.sinc||GHIDRA||||END| diff --git a/Ghidra/RuntimeScripts/Common/server/jaas_external_program.example.sh b/Ghidra/RuntimeScripts/Common/server/jaas_external_program.example.sh index a0600edb60..91c297390f 100755 --- a/Ghidra/RuntimeScripts/Common/server/jaas_external_program.example.sh +++ b/Ghidra/RuntimeScripts/Common/server/jaas_external_program.example.sh @@ -1,4 +1,19 @@ #!/bin/bash +## ### +# 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. +## # This is a trivial example to show how the Ghidra ExternalProgramLoginModule # communicates with the external authenticator. diff --git a/Ghidra/RuntimeScripts/Common/support/buildExtension.gradle b/Ghidra/RuntimeScripts/Common/support/buildExtension.gradle index 90fd5f4dd9..672d7302be 100644 --- a/Ghidra/RuntimeScripts/Common/support/buildExtension.gradle +++ b/Ghidra/RuntimeScripts/Common/support/buildExtension.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import org.apache.tools.ant.filters.ReplaceTokens defaultTasks 'buildExtension' diff --git a/Ghidra/RuntimeScripts/Linux/support/launch.sh b/Ghidra/RuntimeScripts/Linux/support/launch.sh index 8f4d75b0b7..b0837b2df3 100755 --- a/Ghidra/RuntimeScripts/Linux/support/launch.sh +++ b/Ghidra/RuntimeScripts/Linux/support/launch.sh @@ -1,4 +1,19 @@ #!/usr/bin/env bash +## ### +# 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. +## umask 027 diff --git a/Ghidra/RuntimeScripts/build.gradle b/Ghidra/RuntimeScripts/build.gradle index 012bb04f61..d497811043 100644 --- a/Ghidra/RuntimeScripts/build.gradle +++ b/Ghidra/RuntimeScripts/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' eclipse.project.name = '_Runtime Scripts' diff --git a/Ghidra/RuntimeScripts/certification.manifest b/Ghidra/RuntimeScripts/certification.manifest index 3b8f49b719..c01853669d 100644 --- a/Ghidra/RuntimeScripts/certification.manifest +++ b/Ghidra/RuntimeScripts/certification.manifest @@ -1,11 +1,9 @@ ##VERSION: 2.0 ##MODULE IP: Copyright Distribution Permitted Common/server/jaas.conf||GHIDRA||||END| -Common/server/jaas_external_program.example.sh||GHIDRA||||END| Common/server/server.conf||GHIDRA||||END| Common/server/svrREADME.html||GHIDRA||||END| Common/support/analyzeHeadlessREADME.html||GHIDRA||||END| -Common/support/buildExtension.gradle||GHIDRA||||END| Common/support/buildGhidraJarREADME.txt||GHIDRA||||END| Common/support/debug.log4j.xml||GHIDRA||||END| Common/support/launch.properties||GHIDRA||||END| @@ -18,7 +16,6 @@ Linux/support/analyzeHeadless||GHIDRA||||END| Linux/support/buildGhidraJar||GHIDRA||||END| Linux/support/convertStorage||GHIDRA||||END| Linux/support/ghidraDebug||GHIDRA||||END| -Linux/support/launch.sh||GHIDRA||||END| Linux/support/pythonRun||GHIDRA||||END| Linux/support/sleigh||GHIDRA||||END| Windows/ghidraRun.bat||GHIDRA||||END| @@ -36,4 +33,3 @@ Windows/support/ghidraDebug.bat||GHIDRA||||END| Windows/support/launch.bat||GHIDRA||||END| Windows/support/pythonRun.bat||GHIDRA||||END| Windows/support/sleigh.bat||GHIDRA||||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Test/IntegrationTest/build.gradle b/Ghidra/Test/IntegrationTest/build.gradle index c0cec14bc2..45de9287d5 100644 --- a/Ghidra/Test/IntegrationTest/build.gradle +++ b/Ghidra/Test/IntegrationTest/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply plugin: 'eclipse' diff --git a/Ghidra/Test/IntegrationTest/certification.manifest b/Ghidra/Test/IntegrationTest/certification.manifest index 4a077a2f88..a59e5aca65 100644 --- a/Ghidra/Test/IntegrationTest/certification.manifest +++ b/Ghidra/Test/IntegrationTest/certification.manifest @@ -1,3 +1,2 @@ ##VERSION: 2.0 -build.gradle||GHIDRA||||END| src/test.slow/resources/ghidra/pcodeCPort/slgh_compile/pcode1.xml||GHIDRA||||END| diff --git a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle index 8ab4a767e2..815417fb5e 100644 --- a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle +++ b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' eclipse.project.name = '_JsonDoclet' diff --git a/GhidraBuild/BuildFiles/build.gradle b/GhidraBuild/BuildFiles/build.gradle index 0e3f0d7214..292c0e7986 100644 --- a/GhidraBuild/BuildFiles/build.gradle +++ b/GhidraBuild/BuildFiles/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' eclipse { @@ -12,4 +27,4 @@ eclipse { } } } -} \ No newline at end of file +} diff --git a/GhidraBuild/BuildFiles/certification.manifest b/GhidraBuild/BuildFiles/certification.manifest index 06abe1b568..c3dd2b2844 100644 --- a/GhidraBuild/BuildFiles/certification.manifest +++ b/GhidraBuild/BuildFiles/certification.manifest @@ -1,6 +1,4 @@ ##VERSION: 2.0 JsonDoclet/Module.manifest||GHIDRA||||END| -JsonDoclet/build.gradle||GHIDRA||||END| -build.gradle||GHIDRA||||END| sleighDevBuild.template||GHIDRA||||END| sleighDistBuild.template||GHIDRA||||END| diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/build.gradle b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/build.gradle index 3261835dbf..26daae9eba 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ //This project requires the eclpse PDE plugin. To create eclipse files for this project, run // "gradle eclipse -PeclipsePDE" if (hasProperty("eclipsePDE")) { @@ -9,4 +24,4 @@ if (hasProperty("eclipsePDE")) { natures 'org.eclipse.pde.FeatureNature' } } -} \ No newline at end of file +} diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/build.gradle b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/build.gradle index b2b80562ff..aecbcd515e 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' //This project requires the eclpse PDE plugin. To create eclipse files for this project, run diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest b/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest index 48ee7d8325..cdf4498a19 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest +++ b/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest @@ -1,6 +1,5 @@ ##VERSION: 2.0 ##MODULE IP: FAMFAMFAM Icons - CC 2.5 -GhidraDevFeature/build.gradle||GHIDRA||||END| GhidraDevFeature/build.properties||GHIDRA||||END| GhidraDevFeature/category.xml||GHIDRA||||END| GhidraDevFeature/feature.xml||GHIDRA||||END| @@ -8,7 +7,6 @@ GhidraDevPlugin/.launch/GhidraDev.launch||GHIDRA||||END| GhidraDevPlugin/GhidraDev.target||GHIDRA||||END| GhidraDevPlugin/GhidraDev_README.html||GHIDRA||||END| GhidraDevPlugin/META-INF/MANIFEST.MF||GHIDRA||||END| -GhidraDevPlugin/build.gradle||GHIDRA||||END| GhidraDevPlugin/build.properties||GHIDRA||||END| GhidraDevPlugin/build_README.txt||GHIDRA||||END| GhidraDevPlugin/icons/GhidraIcon16.png||GHIDRA||||END| diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/certification.manifest b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/certification.manifest index c9394c62e0..d6d7358245 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/certification.manifest +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/certification.manifest @@ -1,25 +1,20 @@ ##VERSION: 2.0 -ghidra.xtext.sleigh.feature/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh.feature/build.properties||GHIDRA||||END| ghidra.xtext.sleigh.feature/category.xml||GHIDRA||||END| ghidra.xtext.sleigh.feature/feature.xml||GHIDRA||||END| ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF||GHIDRA||||END| -ghidra.xtext.sleigh.ide/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh.ide/build.properties||GHIDRA||||END| ghidra.xtext.sleigh.ide/src/ghidra/xtext/sleigh/ide/SleighIdeModule.xtend||GHIDRA||||END| ghidra.xtext.sleigh.ide/src/ghidra/xtext/sleigh/ide/SleighIdeSetup.xtend||GHIDRA||||END| ghidra.xtext.sleigh.tests/META-INF/MANIFEST.MF||GHIDRA||||END| -ghidra.xtext.sleigh.tests/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh.tests/build.properties||GHIDRA||||END| ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/CrossReferenceTest.xtend||GHIDRA||||END| ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighMacroTest.xtend||GHIDRA||||END| ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighParsingTest.xtend||GHIDRA||||END| ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighScopeTest.xtend||GHIDRA||||END| ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF||GHIDRA||||END| -ghidra.xtext.sleigh.ui.tests/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh.ui.tests/build.properties||GHIDRA||||END| ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF||GHIDRA||||END| -ghidra.xtext.sleigh.ui/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh.ui/build.properties||GHIDRA||||END| ghidra.xtext.sleigh.ui/plugin.xml||GHIDRA||||END| ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighEObjectHoverProvider.xtend||GHIDRA||||END| @@ -35,7 +30,6 @@ ghidra.xtext.sleigh/.launch/Generate Sleigh (sleigh) Language Infrastructure.lau ghidra.xtext.sleigh/.launch/Launch Runtime Eclipse.launch||GHIDRA||||END| ghidra.xtext.sleigh/GhidraSleighEditor_README.html||GHIDRA||||END| ghidra.xtext.sleigh/META-INF/MANIFEST.MF||GHIDRA||||END| -ghidra.xtext.sleigh/build.gradle||GHIDRA||||END| ghidra.xtext.sleigh/build.properties||GHIDRA||||END| ghidra.xtext.sleigh/build_README.txt||GHIDRA||||END| ghidra.xtext.sleigh/plugin.xml||GHIDRA||||END| diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/build.gradle index 631144ce56..e8ad62df30 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run // "gradle eclipse -PeclipseDSL" if (hasProperty("eclipseDSL")) { diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/build.gradle index 47fb6a0d3c..9a87b581e8 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ide/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.tests/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.tests/build.gradle index 2868767233..2f69570f49 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.tests/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.tests/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/build.gradle index f297a4d46d..4519100b82 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui.tests/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/build.gradle index d6088f4ca0..c8e4725925 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.ui/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run diff --git a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/build.gradle b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/build.gradle index 534e0c6d0f..da8cc46393 100644 --- a/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/build.gradle +++ b/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' // This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run diff --git a/GhidraBuild/IDAPro/Python/6xx/loaders/xmlldr.py b/GhidraBuild/IDAPro/Python/6xx/loaders/xmlldr.py index df43daa5b8..bfff5ac148 100644 --- a/GhidraBuild/IDAPro/Python/6xx/loaders/xmlldr.py +++ b/GhidraBuild/IDAPro/Python/6xx/loaders/xmlldr.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # xmlldr.py - IDA XML Import loader and plugin #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/Python/6xx/plugins/xmlexp.py b/GhidraBuild/IDAPro/Python/6xx/plugins/xmlexp.py index 8e1807e572..727fcd70d7 100644 --- a/GhidraBuild/IDAPro/Python/6xx/plugins/xmlexp.py +++ b/GhidraBuild/IDAPro/Python/6xx/plugins/xmlexp.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # xmlexp.py - IDA XML Exporter plugin #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/Python/7xx/loaders/xml_loader.py b/GhidraBuild/IDAPro/Python/7xx/loaders/xml_loader.py index a565d71c88..9e65fbc437 100644 --- a/GhidraBuild/IDAPro/Python/7xx/loaders/xml_loader.py +++ b/GhidraBuild/IDAPro/Python/7xx/loaders/xml_loader.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # xmlldr.py - IDA XML loader #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/Python/7xx/plugins/xml_exporter.py b/GhidraBuild/IDAPro/Python/7xx/plugins/xml_exporter.py index 15ac96eb6f..9cb46b2073 100644 --- a/GhidraBuild/IDAPro/Python/7xx/plugins/xml_exporter.py +++ b/GhidraBuild/IDAPro/Python/7xx/plugins/xml_exporter.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # xmlexp.py - IDA XML Exporter plugin #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/Python/7xx/plugins/xml_importer.py b/GhidraBuild/IDAPro/Python/7xx/plugins/xml_importer.py index e727334f8e..5ac1458405 100644 --- a/GhidraBuild/IDAPro/Python/7xx/plugins/xml_importer.py +++ b/GhidraBuild/IDAPro/Python/7xx/plugins/xml_importer.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # xmlimp.py - IDA XML Importer plugin #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/Python/7xx/python/idaxml.py b/GhidraBuild/IDAPro/Python/7xx/python/idaxml.py index 51fc8eba99..5a88be0742 100644 --- a/GhidraBuild/IDAPro/Python/7xx/python/idaxml.py +++ b/GhidraBuild/IDAPro/Python/7xx/python/idaxml.py @@ -1,3 +1,18 @@ +## ### +# 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. +## #--------------------------------------------------------------------- # idaxml.py - IDA XML classes #--------------------------------------------------------------------- diff --git a/GhidraBuild/IDAPro/build.gradle b/GhidraBuild/IDAPro/build.gradle index 4967345270..2f25130c0d 100644 --- a/GhidraBuild/IDAPro/build.gradle +++ b/GhidraBuild/IDAPro/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' eclipse.project.name = '_IDAPro' @@ -16,4 +31,4 @@ rootProject.assembleDistribution { from (this.project.file("Python/6xx/loaders/xmlldr.py")) { into "Extensions/IDAPro/Python/6xx/plugins" } -} \ No newline at end of file +} diff --git a/GhidraBuild/IDAPro/certification.manifest b/GhidraBuild/IDAPro/certification.manifest index 875b575e1f..d04b9197b3 100644 --- a/GhidraBuild/IDAPro/certification.manifest +++ b/GhidraBuild/IDAPro/certification.manifest @@ -1,11 +1,4 @@ ##VERSION: 2.0 Python/6xx/README.html||GHIDRA||||END| -Python/6xx/loaders/xmlldr.py||GHIDRA||||END| -Python/6xx/plugins/xmlexp.py||GHIDRA||||END| Python/7xx/README.html||GHIDRA||||END| -Python/7xx/loaders/xml_loader.py||GHIDRA||||END| -Python/7xx/plugins/xml_exporter.py||GHIDRA||||END| -Python/7xx/plugins/xml_importer.py||GHIDRA||||END| -Python/7xx/python/idaxml.py||GHIDRA||||END| README.html||GHIDRA||||END| -build.gradle||GHIDRA||||END| diff --git a/GhidraBuild/LaunchSupport/build.gradle b/GhidraBuild/LaunchSupport/build.gradle index 2c2db6bd07..50a8688d0f 100644 --- a/GhidraBuild/LaunchSupport/build.gradle +++ b/GhidraBuild/LaunchSupport/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' apply plugin: 'eclipse' eclipse.project.name = '_LaunchSupport' @@ -11,4 +26,4 @@ rootProject.assembleDistribution { from (jar) { into "support" } -} \ No newline at end of file +} diff --git a/GhidraBuild/LaunchSupport/certification.manifest b/GhidraBuild/LaunchSupport/certification.manifest index 50bf3491fd..69b99b93b0 100644 --- a/GhidraBuild/LaunchSupport/certification.manifest +++ b/GhidraBuild/LaunchSupport/certification.manifest @@ -1,2 +1 @@ ##VERSION: 2.0 -build.gradle||GHIDRA||||END| diff --git a/GhidraBuild/Skeleton/build.gradle b/GhidraBuild/Skeleton/build.gradle index 0843e819fd..e07647e262 100644 --- a/GhidraBuild/Skeleton/build.gradle +++ b/GhidraBuild/Skeleton/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply plugin: 'eclipse' @@ -23,4 +38,4 @@ rootProject.assembleDistribution { rename "buildTemplate.gradle", "build.gradle" into "Extensions/Ghidra/Skeleton" } -} \ No newline at end of file +} diff --git a/GhidraBuild/Skeleton/buildTemplate.gradle b/GhidraBuild/Skeleton/buildTemplate.gradle index e827d9996f..7bf7fc7579 100644 --- a/GhidraBuild/Skeleton/buildTemplate.gradle +++ b/GhidraBuild/Skeleton/buildTemplate.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ // Builds a Ghidra Extension for a given Ghidra installation. // // An absolute path to the Ghidra installation directory must be supplied either by setting the diff --git a/GhidraBuild/Skeleton/certification.manifest b/GhidraBuild/Skeleton/certification.manifest index e0904abf9f..6c75084577 100644 --- a/GhidraBuild/Skeleton/certification.manifest +++ b/GhidraBuild/Skeleton/certification.manifest @@ -1,7 +1,5 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| -buildTemplate.gradle||GHIDRA||||END| data/README.txt||GHIDRA||||END| data/buildLanguage.xml||GHIDRA||||END| data/languages/skel.cspec||GHIDRA||||END| diff --git a/GhidraDocs/build.gradle b/GhidraDocs/build.gradle index 8a693653da..4e8583e0eb 100644 --- a/GhidraDocs/build.gradle +++ b/GhidraDocs/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'java' apply plugin: 'eclipse' eclipse.project.name = '_GhidraDocs' @@ -22,4 +37,4 @@ rootProject.assembleDistribution { into "docs" } -} \ No newline at end of file +} diff --git a/GhidraDocs/certification.manifest b/GhidraDocs/certification.manifest index 96c7da486b..57bee25cd5 100644 --- a/GhidraDocs/certification.manifest +++ b/GhidraDocs/certification.manifest @@ -75,7 +75,6 @@ GhidraClass/Intermediate/VersionTracking.html||GHIDRA|||This file contains mostl GhidraClass/Intermediate/VersionTracking_withNotes.html||Public Domain|||Slight modification of code that is available for distribution, without restrictions, (original extremely permissive wtf license allows us to change IP to Public Domain),from https://github.com/paulrouget/dzslides.|END| GhidraCodingStandards.html||GHIDRA||||END| InstallationGuide.html||GHIDRA||||END| -build.gradle||GHIDRA||||END| images/B.gif||GHIDRA||||END| images/D.gif||GHIDRA||||END| images/F.gif||GHIDRA||||END| diff --git a/build.gradle b/build.gradle index ecd372c4a5..066143562d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply plugin: 'eclipse' apply from: 'gradle/root/eclipse.gradle' diff --git a/certification.local.manifest b/certification.local.manifest index beb26db281..c58275165b 100644 --- a/certification.local.manifest +++ b/certification.local.manifest @@ -8,5 +8,3 @@ DevGuide.md||GHIDRA||||END| LICENSE||GHIDRA||||END| NOTICE||GHIDRA||||END| README.md||GHIDRA||||END| -build.gradle||GHIDRA||||END| -settings.gradle||GHIDRA||||END| diff --git a/gradle/certification.manifest b/gradle/certification.manifest index 0970bcd7da..a759e0d876 100644 --- a/gradle/certification.manifest +++ b/gradle/certification.manifest @@ -1,29 +1,4 @@ ##VERSION: 2.0 README.txt||GHIDRA||||END| -distributableGPLExtension.gradle||GHIDRA||||END| -distributableGPLModule.gradle||GHIDRA||||END| -distributableGhidraExtension.gradle||GHIDRA||||END| -distributableGhidraModule.gradle||GHIDRA||||END| -externalGhidraExtension.gradle||GHIDRA||||END| -helpProject.gradle||GHIDRA||||END| -jacocoProject.gradle||GHIDRA||||END| -javaProject.gradle||GHIDRA||||END| -javaTestProject.gradle||GHIDRA||||END| -nativeProject.gradle||GHIDRA||||END| -processorProject.gradle||GHIDRA||||END| -root/distribution.gradle||GHIDRA||||END| -root/eclipse.gradle||GHIDRA||||END| -root/jacoco.gradle||GHIDRA||||END| -root/prepDev.gradle||GHIDRA||||END| -root/svg.gradle||GHIDRA||||END| -root/test.gradle||GHIDRA||||END| -root/usage.gradle||GHIDRA||||END| support/app_config_breakout.txt||GHIDRA||||END| -support/distributionCommon.gradle||GHIDRA||||END| -support/eclipseLauncher.gradle||GHIDRA||||END| -support/extensionCommon.gradle||GHIDRA||||END| -support/fetchDependencies.gradle||GHIDRA||||END| support/jacoco.excludes.src.txt||GHIDRA||||END| -support/loadApplicationProperties.gradle||GHIDRA||||END| -support/settingsUtil.gradle||GHIDRA||||END| -support/testUtils.gradle||GHIDRA||||END| diff --git a/gradle/distributableGPLExtension.gradle b/gradle/distributableGPLExtension.gradle index 5c6534342e..8958e009a3 100644 --- a/gradle/distributableGPLExtension.gradle +++ b/gradle/distributableGPLExtension.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if it has content that should be included in a distribution as an extension. Including this diff --git a/gradle/distributableGPLModule.gradle b/gradle/distributableGPLModule.gradle index a7a8e8b6c7..a0d09be4ea 100644 --- a/gradle/distributableGPLModule.gradle +++ b/gradle/distributableGPLModule.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" rootProject.assembleDistribution { diff --git a/gradle/distributableGhidraExtension.gradle b/gradle/distributableGhidraExtension.gradle index d124e67444..fb029f2782 100644 --- a/gradle/distributableGhidraExtension.gradle +++ b/gradle/distributableGhidraExtension.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if it has content that should be included in a distribution as an extension. Including this diff --git a/gradle/distributableGhidraModule.gradle b/gradle/distributableGhidraModule.gradle index 3506d50080..c9d48fd315 100644 --- a/gradle/distributableGhidraModule.gradle +++ b/gradle/distributableGhidraModule.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if it has content that should be included in a distribution. (Unless the content should be included diff --git a/gradle/externalGhidraExtension.gradle b/gradle/externalGhidraExtension.gradle index 61366d55ae..abda7a1d7e 100644 --- a/gradle/externalGhidraExtension.gradle +++ b/gradle/externalGhidraExtension.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/support/distributionCommon.gradle" apply from: "$rootProject.projectDir/gradle/support/extensionCommon.gradle" diff --git a/gradle/helpProject.gradle b/gradle/helpProject.gradle index d33a7b903f..a965467ed1 100644 --- a/gradle/helpProject.gradle +++ b/gradle/helpProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if they have content for the Ghidra help system. A gradle project can include help support by adding diff --git a/gradle/jacocoProject.gradle b/gradle/jacocoProject.gradle index 27f4760a08..ca1fc9d21c 100644 --- a/gradle/jacocoProject.gradle +++ b/gradle/jacocoProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects that should be included when running jacoco @@ -32,4 +47,4 @@ clean { logger.debug("Deleting jacoco report directory: $rootProject.buildDir/reports/jacoco/") file("$rootProject.buildDir/reports/jacoco/").deleteDir() // delete jacocoReport, jacocoBranchReport output } -} \ No newline at end of file +} diff --git a/gradle/javaProject.gradle b/gradle/javaProject.gradle index 0dc2cb30f7..fa43117602 100644 --- a/gradle/javaProject.gradle +++ b/gradle/javaProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if they have java code. diff --git a/gradle/javaTestProject.gradle b/gradle/javaTestProject.gradle index dee67dc475..800cc4aed5 100644 --- a/gradle/javaTestProject.gradle +++ b/gradle/javaTestProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects that should be included if this module has tests that should be included when running all the Ghidra tests. @@ -193,4 +208,4 @@ def endTestTimer(Task task) { long secs = (elapsedMS - (hrs * msPerHour) - (mins * msPerMin)) / 1000; println ":" + task.project.name + ":" + task.name + " elapsed time: " + String.format("%d:%02d:%02d", hrs, mins, secs); -} \ No newline at end of file +} diff --git a/gradle/nativeProject.gradle b/gradle/nativeProject.gradle index 978025b513..fb2a369aa1 100644 --- a/gradle/nativeProject.gradle +++ b/gradle/nativeProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if they have native code (C or C++). diff --git a/gradle/processorProject.gradle b/gradle/processorProject.gradle index 357fc44d25..139d062fa6 100644 --- a/gradle/processorProject.gradle +++ b/gradle/processorProject.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /***************************************************************************************** This file is a "mix-in" gradle script that individual gradle projects should include if they have processor definitions. @@ -258,4 +273,4 @@ def resolveSleighArg(String arg, boolean useDevPath) { newArg += modulePath newArg += tail return newArg -} \ No newline at end of file +} diff --git a/gradle/root/distribution.gradle b/gradle/root/distribution.gradle index cd32b10fcf..a9dd82212b 100644 --- a/gradle/root/distribution.gradle +++ b/gradle/root/distribution.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import org.apache.tools.ant.filters.* /********************************************************************************* diff --git a/gradle/root/eclipse.gradle b/gradle/root/eclipse.gradle index 7cb2c61c66..51d76b4122 100644 --- a/gradle/root/eclipse.gradle +++ b/gradle/root/eclipse.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ eclipse { project { name = '___root' diff --git a/gradle/root/jacoco.gradle b/gradle/root/jacoco.gradle index 5fa4220144..e195bc2f4a 100644 --- a/gradle/root/jacoco.gradle +++ b/gradle/root/jacoco.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import groovy.io.FileType; apply plugin:'jacoco' @@ -96,4 +111,4 @@ task jacocoReport(type: JacocoReport, group: 'Coverage reports') { enabled false } } -} \ No newline at end of file +} diff --git a/gradle/root/prepDev.gradle b/gradle/root/prepDev.gradle index fe46b5bca4..6daec0a34d 100644 --- a/gradle/root/prepDev.gradle +++ b/gradle/root/prepDev.gradle @@ -1,5 +1,18 @@ - - +/* ### + * 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. + */ /****************************************************************************************** * PrepDev - task to prepare a development environment for Ghidra. It needs to be run * whenever the Ghidra git repos are first cloned or after a 'clean'. It also diff --git a/gradle/root/svg.gradle b/gradle/root/svg.gradle index 5536554868..153b8c4720 100644 --- a/gradle/root/svg.gradle +++ b/gradle/root/svg.gradle @@ -1,4 +1,18 @@ - +/* ### + * 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. + */ /********************************************************************************* * SVG * diff --git a/gradle/root/test.gradle b/gradle/root/test.gradle index f2b30608aa..11d20483fd 100644 --- a/gradle/root/test.gradle +++ b/gradle/root/test.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /********************************************************************************* * test.gradle * diff --git a/gradle/root/usage.gradle b/gradle/root/usage.gradle index 1c545a97c9..8555479114 100644 --- a/gradle/root/usage.gradle +++ b/gradle/root/usage.gradle @@ -1,4 +1,18 @@ - +/* ### + * 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. + */ defaultTasks ':usage' task usage { diff --git a/gradle/support/distributionCommon.gradle b/gradle/support/distributionCommon.gradle index 795a9c67d9..d04984e7c6 100644 --- a/gradle/support/distributionCommon.gradle +++ b/gradle/support/distributionCommon.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "$rootProject.projectDir/gradle/support/ip.gradle" // all application tests depend on all the sleigh processors to be built diff --git a/gradle/support/eclipseLauncher.gradle b/gradle/support/eclipseLauncher.gradle index a996775240..d45c0f1faf 100644 --- a/gradle/support/eclipseLauncher.gradle +++ b/gradle/support/eclipseLauncher.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import org.gradle.api.*; import org.gradle.artifacts.*; import org.gradle.process.JavaExecSpec; diff --git a/gradle/support/extensionCommon.gradle b/gradle/support/extensionCommon.gradle index 953fa19ba0..686b69aa85 100644 --- a/gradle/support/extensionCommon.gradle +++ b/gradle/support/extensionCommon.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import org.apache.tools.ant.filters.* task zipExtensions (type: Zip) { @@ -121,4 +136,4 @@ plugins.withType(JavaPlugin) { into { getBaseProjectName(p) + "/lib" } } } -} \ No newline at end of file +} diff --git a/gradle/support/fetchDependencies.gradle b/gradle/support/fetchDependencies.gradle index 03f64d4c27..6b4a7912ad 100644 --- a/gradle/support/fetchDependencies.gradle +++ b/gradle/support/fetchDependencies.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ /******************************************************************************* * fetchDependencies.gradle * * * diff --git a/gradle/support/loadApplicationProperties.gradle b/gradle/support/loadApplicationProperties.gradle index 77ddd8bf43..39d52bbb5f 100644 --- a/gradle/support/loadApplicationProperties.gradle +++ b/gradle/support/loadApplicationProperties.gradle @@ -1,4 +1,18 @@ - +/* ### + * 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. + */ /***************************************************************************************** * * Reads the Ghidra/application.properties file and sets properties for the version, diff --git a/gradle/support/settingsUtil.gradle b/gradle/support/settingsUtil.gradle index a3284a1646..ada8ba7e14 100644 --- a/gradle/support/settingsUtil.gradle +++ b/gradle/support/settingsUtil.gradle @@ -1,4 +1,18 @@ - +/* ### + * 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. + */ /************************************************************************************** * Method to add a single project to this gradle build. * diff --git a/gradle/support/testUtils.gradle b/gradle/support/testUtils.gradle index ff2009dd0d..61bfb1dfa6 100644 --- a/gradle/support/testUtils.gradle +++ b/gradle/support/testUtils.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ import java.util.regex.*; import groovy.io.FileType; import java.lang.reflect.Constructor; diff --git a/settings.gradle b/settings.gradle index 75bd1c3ac3..eed164335a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,18 @@ +/* ### + * 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. + */ apply from: "gradle/support/settingsUtil.gradle" /******************************************************************************************* From 33bba9e614765cfcee4df74482fe7ffc12b99024 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 18 Mar 2021 04:50:38 -0400 Subject: [PATCH 097/140] Relax source for IP info during build --- gradle/support/ip.gradle | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gradle/support/ip.gradle b/gradle/support/ip.gradle index 1e4bbe6e05..d8fc9f89d2 100644 --- a/gradle/support/ip.gradle +++ b/gradle/support/ip.gradle @@ -204,17 +204,17 @@ def isBashSourceFile(File file) { * Gets the ip for a file in the module from its header (or certification.manifest) *********************************************************************************/ def getIp(File projectDir, File file) { + String ip = null; if (isCSourceFile(file)) { - return getIpForSourceFile(file, " * IP:"); + ip = getIpForSourceFile(file, " * IP:"); } - if (isBashSourceFile(file)) { - String ip = getIpForSourceFile(file, "# IP:"); - // allow transition from certification.manifest entry - if (ip != null) { - return ip; - } + else if (isBashSourceFile(file)) { + ip = getIpForSourceFile(file, "# IP:"); } - return getIpForNonSourceFile(projectDir, file); + if (ip == null) { + ip = getIpForNonSourceFile(projectDir, file); + } + return ip; } /********************************************************************************* From c8a4f7dcf76fb8275b4ee5dee53ccbd957a9a25f Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 18 Mar 2021 11:28:14 -0400 Subject: [PATCH 098/140] Test fixes for non-failing stack traces in log file --- .../core/datamgr/editor/EnumEditorPanel.java | 14 +++++-- .../core/function/tags/FunctionTagLoader.java | 15 ++++--- .../function/tags/FunctionTagLoaderTest.java | 42 ++++++++++++------- .../src/test/java/ghidra/test/DummyTool.java | 11 +++-- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorPanel.java index 48c12b49cc..f5a6be5794 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorPanel.java @@ -310,8 +310,10 @@ class EnumEditorPanel extends JPanel { EnumCellRenderer cellRenderer = new EnumCellRenderer(); table.setRowHeight(table.getRowHeight() + 4); table.setDefaultEditor(String.class, new EnumStringCellEditor()); - table.getColumnModel().getColumn(EnumTableModel.VALUE_COL).setCellEditor( - new EnumLongCellEditor()); + table.getColumnModel() + .getColumn(EnumTableModel.VALUE_COL) + .setCellEditor( + new EnumLongCellEditor()); table.setDefaultRenderer(String.class, cellRenderer); add(createInfoPanel(), BorderLayout.SOUTH); @@ -335,13 +337,17 @@ class EnumEditorPanel extends JPanel { } private void changed() { - String name = nameField.getText(); + String name = nameField.getText().trim(); + if (name.length() == 0) { + return; + } + if (!name.equals(editedEnumDT.getName())) { try { editedEnumDT.setName(name); } catch (InvalidNameException e) { - e.printStackTrace(); + setStatusMessage("'" + name + "' is not a valid name"); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagLoader.java index 6cc4bc68a4..2fc0bc764b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagLoader.java @@ -41,8 +41,10 @@ public class FunctionTagLoader { * * @param tagFile tag file * @return List list of function tags + * @throws IOException if there is an exception reading the file + * @throws SAXException if there is an exception parsing the file */ - protected static Set loadTags(File tagFile) { + protected static Set loadTags(File tagFile) throws SAXException, IOException { return loadTags(new ResourceFile(tagFile)); } @@ -56,16 +58,17 @@ public class FunctionTagLoader { try { return loadTags(Application.getModuleDataFile(moduleDataFilePath)); } - catch (FileNotFoundException e) { + catch (SAXException | IOException e) { Msg.error(FunctionTagLoader.class, "Error loading function tags file from " + moduleDataFilePath, e); } return new HashSet<>(); } - protected static Set loadTags(final ResourceFile tagDataFile) { - Set tags = new HashSet<>(); + protected static Set loadTags(final ResourceFile tagDataFile) + throws SAXException, IOException { + Set tags = new HashSet<>(); try { ErrorHandler errHandler = new ErrorHandler() { @Override @@ -116,10 +119,6 @@ public class FunctionTagLoader { Msg.error(FunctionTagLoader.class, "Error parsing function tags from " + tagDataFile, e); } - catch (SAXException | IOException e) { - Msg.error(FunctionTagLoader.class, "Error loading function tags from " + tagDataFile, - e); - } return tags; } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/function/tags/FunctionTagLoaderTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/function/tags/FunctionTagLoaderTest.java index 546162dd5f..7d45000009 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/function/tags/FunctionTagLoaderTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/function/tags/FunctionTagLoaderTest.java @@ -18,7 +18,6 @@ package ghidra.app.plugin.core.function.tags; import static org.junit.Assert.*; import java.io.File; -import java.io.IOException; import java.nio.file.Files; import java.util.HashSet; import java.util.Set; @@ -117,10 +116,14 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { public void testLoadTags_EmptyFile() throws Exception { // Create file without contents File xxeFile = createTempFileForTest(); - Set tags = FunctionTagLoader.loadTags(xxeFile); - Set expectedTags = new HashSet<>(); - assertEquals(tags, expectedTags); + try { + FunctionTagLoader.loadTags(xxeFile); + fail("Did not get expected exception"); + } + catch (Exception e) { + // good + } } @Test @@ -140,10 +143,13 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { File xxeFile = createTempFileForTest(); xxeFile.delete(); - Set tags = FunctionTagLoader.loadTags(xxeFile); - - Set expectedTags = new HashSet<>(); - assertEquals(tags, expectedTags); + try { + FunctionTagLoader.loadTags(xxeFile); + fail("Did not get expected exception"); + } + catch (Exception e) { + // good + } } @Test @@ -151,10 +157,14 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { // Create file with contents File xxeFile = createTempFileForTest(); Files.write(xxeFile.toPath(), FUNCTION_TAGS_MALFORMED_XML.getBytes()); - Set tags = FunctionTagLoader.loadTags(xxeFile); - Set expectedTags = new HashSet<>(); - assertEquals(tags, expectedTags); + try { + FunctionTagLoader.loadTags(xxeFile); + fail("Did not get expected exception"); + } + catch (Exception e) { + // good + } } @Test @@ -163,7 +173,7 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { * located in Base/data/functionTags.xml * @throws IOException */ - public void testLoadTags_XmlDefault() throws IOException { + public void testLoadTags_XmlDefault() throws Exception { // Create file with contents File xxeFile = createTempFileForTest(); @@ -184,7 +194,7 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { } @Test - public void testLoadTags_XmlHasBlankNameValue() throws IOException { + public void testLoadTags_XmlHasBlankNameValue() throws Exception { // Create file with contents File xxeFile = createTempFileForTest(); @@ -204,7 +214,7 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { } @Test - public void testLoadTags_XmlHasCommentValue() throws IOException { + public void testLoadTags_XmlHasCommentValue() throws Exception { // Create file with contents File xxeFile = createTempFileForTest(); @@ -225,7 +235,7 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { } @Test - public void testLoadTags_XmlNoCommentTag() throws IOException { + public void testLoadTags_XmlNoCommentTag() throws Exception { // Create file with contents File xxeFile = createTempFileForTest(); @@ -252,7 +262,7 @@ public class FunctionTagLoaderTest extends AbstractGhidraHeadedIntegrationTest { * * @throws IOException */ - public void testLoadTags_XmlNoNameTag() throws IOException { + public void testLoadTags_XmlNoNameTag() throws Exception { // Create file with contents File xxeFile = createTempFileForTest(); diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/test/DummyTool.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/test/DummyTool.java index d4608056a8..1b0931a9dc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/test/DummyTool.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/test/DummyTool.java @@ -17,8 +17,7 @@ package ghidra.test; import java.awt.Window; import java.beans.PropertyChangeListener; -import java.util.Collections; -import java.util.Set; +import java.util.*; import javax.swing.*; import javax.swing.event.ChangeListener; @@ -34,8 +33,7 @@ import ghidra.framework.model.*; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginTool; -import ghidra.framework.plugintool.util.PluginClassManager; -import ghidra.framework.plugintool.util.ServiceListener; +import ghidra.framework.plugintool.util.*; import ghidra.program.model.listing.Program; public class DummyTool extends PluginTool { @@ -451,4 +449,9 @@ public class DummyTool extends PluginTool { public JFrame getToolFrame() { return null; } + + @Override + public UndoRedoToolState getUndoRedoToolState(DomainObject domainObject) { + return new UndoRedoToolState(new ArrayList<>(), domainObject); + } } From ae69ba87d14c0006da50e206b82fddd1d1c4416a Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 18 Mar 2021 12:13:28 -0400 Subject: [PATCH 099/140] GP-706 - Speed up namespace lookup and creation --- .../ghidra_scripts/BuildGhidraJarScript.java | 14 +- .../CodeBrowserClipboardProvider.java | 23 +- .../app/util/demangler/DemangledObject.java | 57 ++-- .../ghidra/program/util/VarnodeContext.java | 38 +-- .../java/ghidra/util/GhidraJarBuilder.java | 155 +++------- .../framework/util/MultiReleaseContent.java | 26 +- .../FunctionGraphPlugin/Function_Graph.html | 16 + .../Function_Graph_Layouts.html | 7 + .../mvc/FunctionGraphOptions.java | 6 +- .../graph/layout/DNLayoutOptions.java | 18 +- .../graph/layout/DecompilerNestedLayout.java | 287 ++++++++++++------ .../main/java/ghidra/server/ServerAdmin.java | 38 ++- .../main/java/docking/DockableComponent.java | 12 +- .../framework/DockingApplicationLayout.java | 55 ++-- .../layout/AbstractVisualGraphLayout.java | 93 +++--- .../viewer/renderer/VisualGraphRenderer.java | 21 +- .../plugintool/StandAloneApplication.java | 80 +++-- .../java/ghidra/app/util/NamespaceUtils.java | 48 +-- .../database/data/DataTypeManagerDB.java | 78 +++-- .../database/symbol/GhidraClassDB.java | 17 +- .../program/database/symbol/SymbolDB.java | 22 +- .../database/symbol/SymbolManager.java | 242 ++++++++++++--- .../program/model/symbol/SymbolTable.java | 37 ++- .../SuperH4/data/languages/SuperH4.sinc | 8 +- Ghidra/RuntimeScripts/Linux/server/svrAdmin | 4 +- .../Linux/support/buildGhidraJar | 2 +- .../Windows/server/ghidraSvr.bat | 39 +-- .../Windows/server/svrAdmin.bat | 10 +- .../Windows/server/svrInstall.bat | 2 +- .../Windows/server/svrUninstall.bat | 2 +- .../Windows/support/analyzeHeadless.bat | 2 +- .../Windows/support/buildGhidraJar.bat | 6 +- .../Windows/support/createPdbXmlFiles.bat | 8 +- .../RuntimeScripts/Windows/support/launch.bat | 20 +- .../Windows/support/pythonRun.bat | 2 +- 35 files changed, 862 insertions(+), 633 deletions(-) diff --git a/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java b/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java index b6a3f8e809..675904cb82 100644 --- a/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java +++ b/Ghidra/Features/Base/ghidra_scripts/BuildGhidraJarScript.java @@ -17,10 +17,9 @@ //@category Examples import java.io.File; -import java.util.*; +import java.util.List; import generic.jar.ApplicationModule; -import generic.jar.ResourceFile; import ghidra.app.script.GhidraScript; import ghidra.framework.Application; import ghidra.util.GhidraJarBuilder; @@ -32,8 +31,7 @@ public class BuildGhidraJarScript extends GhidraScript { @Override public void run() throws Exception { - GhidraJarBuilder builder = - new GhidraJarBuilder(toFiles(Application.getApplicationRootDirectories())); + GhidraJarBuilder builder = new GhidraJarBuilder(Application.getApplicationLayout()); builder.setMainClass("ghidra.JarRun"); // default is ghidra.JarRun, only here if you want // to change it to something else. @@ -69,12 +67,4 @@ public class BuildGhidraJarScript extends GhidraScript { // uncomment the following line to create a src zip for debugging. // builder.buildSrcZip(new File(installDir, "GhidraSrc.zip"), monitor); } - - private List toFiles(Collection resourceFiles) { - List fileList = new ArrayList<>(); - for (ResourceFile resourceFile : resourceFiles) { - fileList.add(resourceFile.getFile(true)); - } - return fileList; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java index eb3e5a4c09..216a85bbd6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java @@ -24,6 +24,8 @@ import java.util.concurrent.CopyOnWriteArraySet; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.apache.commons.lang3.StringUtils; + import docking.ActionContext; import docking.ComponentProvider; import docking.dnd.GenericDataFlavor; @@ -303,12 +305,9 @@ public class CodeBrowserClipboardProvider extends ByteCopier private Transferable copyAddress() { AddressSetView addressSet = getSelectedAddresses(); - StringBuilder buffy = new StringBuilder(); AddressIterator it = addressSet.getAddresses(true); - while (it.hasNext()) { - buffy.append(it.next()).append('\n'); - } - return createStringTransferable(buffy.toString()); + String joined = StringUtils.join((Iterator

    ) it, "\n"); + return createStringTransferable(joined); } protected Transferable copyCode(TaskMonitor monitor) { @@ -377,8 +376,8 @@ public class CodeBrowserClipboardProvider extends ByteCopier private boolean pasteLabelsComments(Transferable pasteData, boolean pasteLabels, boolean pasteComments) { try { - List list = (List) pasteData.getTransferData( - CodeUnitInfoTransferable.localDataTypeFlavor); + List list = + (List) pasteData.getTransferData(CodeUnitInfoTransferable.localDataTypeFlavor); List infos = CollectionUtils.asList(list, CodeUnitInfo.class); Command cmd = new CodeUnitInfoPasteCmd(currentLocation.getAddress(), infos, pasteLabels, pasteComments); @@ -420,7 +419,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier return pasteOperandField((OperandFieldLocation) currentLocation, labelName); } - // try pasting onto something that is not a label + // try pasting onto something that is not a label return maybePasteNonLabelString(labelName); } @@ -451,12 +450,12 @@ public class CodeBrowserClipboardProvider extends ByteCopier String oldName = symbol.getName(); Namespace namespace = symbol.getParentNamespace(); Address symbolAddress = symbol.getAddress(); - RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, - namespace, SourceType.USER_DEFINED); + RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, namespace, + SourceType.USER_DEFINED); return tool.execute(cmd, currentProgram); } - // try pasting onto something that is not a label + // try pasting onto something that is not a label return maybePasteNonLabelString(labelName); } @@ -646,7 +645,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier //================================================================================================== // Unsupported Operations -//================================================================================================== +//================================================================================================== @Override public void lostOwnership(Transferable transferable) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java index b55dffb890..03b7d601bb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java @@ -441,6 +441,7 @@ public abstract class DemangledObject implements Demangled { namespace = program.getGlobalNamespace(); } + SymbolTable symbolTable = program.getSymbolTable(); for (String namespaceName : getNamespaceList(typeNamespace)) { // TODO - This is compensating for too long templates. We should probably genericize @@ -448,45 +449,43 @@ public abstract class DemangledObject implements Demangled { // same name is the same class--would that reflect reality? namespaceName = ensureNameLength(namespaceName); - SymbolTable symbolTable = program.getSymbolTable(); - - List symbols = symbolTable.getSymbols(namespaceName, namespace); - Symbol namespaceSymbol = - symbols.stream().filter(s -> (s.getSymbolType() == SymbolType.NAMESPACE || - s.getSymbolType() == SymbolType.CLASS)).findFirst().orElse(null); - if (namespaceSymbol == null) { - try { - namespace = - symbolTable.createNameSpace(namespace, namespaceName, SourceType.IMPORTED); - } - catch (DuplicateNameException e) { - Msg.error(DemangledObject.class, - "Failed to create namespace due to name conflict: " + - NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, - false)); - break; - } - catch (InvalidInputException e) { - Msg.error(DemangledObject.class, - "Failed to create namespace: " + e.getMessage()); - break; - } + try { + namespace = + symbolTable.getOrCreateNameSpace(namespace, namespaceName, SourceType.IMPORTED); } - else if (isPermittedNamespaceSymbol(namespaceSymbol, functionPermitted)) { - namespace = (Namespace) namespaceSymbol.getObject(); - } - else { + catch (DuplicateNameException e) { Msg.error(DemangledObject.class, "Failed to create namespace due to name conflict: " + + NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, + false)); + break; + } + catch (InvalidInputException e) { + Msg.error(DemangledObject.class, + "Failed to create namespace: " + e.getMessage()); + break; + } + + Symbol nsSymbol = namespace.getSymbol(); + if (!isPermittedNamespaceType(nsSymbol.getSymbolType(), functionPermitted)) { + + String allowedTypes = "SymbolType.CLASS, SymbolType.NAMESPACE"; + if (functionPermitted) { + allowedTypes += ", SymbolType.FUNCTION"; + } + + Msg.error(DemangledObject.class, + "Bad namespace type - must be one of: " + allowedTypes + NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, false)); break; } + } return namespace; } - private static boolean isPermittedNamespaceSymbol(Symbol symbol, boolean functionPermitted) { - SymbolType symbolType = symbol.getSymbolType(); + private static boolean isPermittedNamespaceType(SymbolType symbolType, + boolean functionPermitted) { if (symbolType == SymbolType.CLASS || symbolType == SymbolType.NAMESPACE) { return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java index 760bf5fd60..e0d1e22cc1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java @@ -34,8 +34,7 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.ReferenceIterator; import ghidra.util.Msg; -import ghidra.util.exception.DuplicateNameException; -import ghidra.util.exception.NotFoundException; +import ghidra.util.exception.*; public class VarnodeContext implements ProcessorContext { @@ -88,7 +87,7 @@ public class VarnodeContext implements ProcessorContext { this.program = program; // make a copy, because we could be making new spaces. - this.addrFactory = new OffsetAddressFactory(program.getAddressFactory()); + this.addrFactory = new OffsetAddressFactory(program); BAD_ADDRESS = addrFactory.getAddress(getAddressSpace("BAD_ADDRESS_SPACE"), 0); @@ -1435,8 +1434,24 @@ public class VarnodeContext implements ProcessorContext { class OffsetAddressFactory extends DefaultAddressFactory { - OffsetAddressFactory(AddressFactory baseFactory) { - super(filterSpaces(baseFactory.getAllAddressSpaces())); + OffsetAddressFactory(Program program) { + // We are only calling super with the address spaces from the language first, and then + // following up to explicitly add more spaces due to the treatment of memory address + // spaces by DefaultAddressFactory when constructed vs. when added later. + // If there is more than one memory address space (e.g., TYPE_RAM, TYPE_CODE, or + // TYPE_OTHER), then addresses are output with the space name prefix, which we do not want. + super(program.getLanguage().getAddressFactory().getAllAddressSpaces(), + program.getLanguage().getAddressFactory().getDefaultAddressSpace()); + for (AddressSpace space : program.getAddressFactory().getAllAddressSpaces()) { + if (space.isLoadedMemorySpace() && getAddressSpace(space.getName()) == null) { + try { + addAddressSpace(space); + } + catch (DuplicateNameException e) { + throw new AssertException("Duplicate name should not occur."); + } + } + } } private int getNextUniqueID() { @@ -1466,17 +1481,4 @@ class OffsetAddressFactory extends DefaultAddressFactory { return (type == AddressSpace.TYPE_SYMBOL); } - private static AddressSpace[] filterSpaces(AddressSpace[] allSpaces) { - List spaces = new ArrayList<>(); - for (AddressSpace space : allSpaces) { - int type = space.getType(); - if (type == AddressSpace.TYPE_VARIABLE || type == AddressSpace.TYPE_STACK || - type == AddressSpace.TYPE_EXTERNAL || type == AddressSpace.TYPE_JOIN) { - continue; - } - spaces.add(space); - } - return spaces.toArray(new AddressSpace[0]); - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java index 7ded06d9a2..5dd1622017 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/GhidraJarBuilder.java @@ -25,28 +25,24 @@ import java.util.zip.*; import generic.jar.*; import ghidra.GhidraApplicationLayout; import ghidra.GhidraLaunchable; -import ghidra.framework.Application; -import ghidra.framework.HeadlessGhidraApplicationConfiguration; +import ghidra.framework.*; import ghidra.framework.plugintool.dialog.ExtensionUtils; import ghidra.util.classfinder.ClassFinder; import ghidra.util.classfinder.ClassSearcher; import ghidra.util.exception.AssertException; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import ghidra.util.task.TaskMonitorAdapter; import utilities.util.FileUtilities; +import utility.application.ApplicationLayout; import utility.module.ModuleUtilities; public class GhidraJarBuilder implements GhidraLaunchable { private static final String ROOT = "_Root/"; private static final String ROOT_GHIDRA = "_Root/Ghidra/"; - private static final String LIBS_FILE_MODULE_KEY = "Module: "; // this is set in the buildGhidraJar batch/script files - private static final String GHIDRA_DIR = "Ghidra.Install.Root.Dir"; private static final String INVOCATION_NAME_PROPERTY = "GhidraJarBuilder.Name"; - private static HashMap> libsMap = new HashMap<>(); private List rootGhidraDirs = new ArrayList<>(); private List allModules; private Set includedModules = new HashSet<>(); @@ -57,19 +53,18 @@ public class GhidraJarBuilder implements GhidraLaunchable { private Pattern extensionPointSuffixPattern; private List extensionPointClasses = new ArrayList<>(); private ClassLoader classLoader; - private boolean inGradleMode = false; private Set processedJars = new HashSet<>(); public GhidraJarBuilder() { // Required for GhidraLaunchable } - public GhidraJarBuilder(List rootDirs) throws IOException { - for (File file : rootDirs) { - File rgd = file.getCanonicalFile(); + public GhidraJarBuilder(ApplicationLayout layout) throws IOException { + for (ResourceFile file : layout.getApplicationRootDirs()) { + File rgd = file.getFile(false).getCanonicalFile(); rootGhidraDirs.add(rgd); } - allModules = findAllModules(); + allModules = findAllModules(layout); Collections.sort(allModules); for (ApplicationModule module : allModules) { if (includeByDefault(module)) { @@ -203,7 +198,7 @@ public class GhidraJarBuilder implements GhidraLaunchable { for (ApplicationModule module : moduleList) { writeModuleClassesAndResources(jar, module); - if (!excludeHelp && !inGradleMode) { + if (!excludeHelp) { writeModuleHelp(jar, module); } } @@ -360,16 +355,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { private void writeModuleClassesAndResources(Jar jar, ApplicationModule module) throws CancelledException, IOException { - if (inGradleMode) { - File gradleBuildFileForModule = - new File(module.getModuleDir(), "build/libs/" + module.getName() + ".jar"); - processJarFile(jar, gradleBuildFileForModule, module); - File gradleBuildFileForGPLModule = - new File(module.getModuleDir(), "build/data/lib/" + module.getName() + ".jar"); - processJarFile(jar, gradleBuildFileForGPLModule, module); - processExternalLibs(jar, module); - return; - } // NOTE: This only works in a distribution where the 3rd party jars live in each // module's libs directory File binDir = new File(module.getModuleDir(), "bin/main"); @@ -380,18 +365,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { processLibDir(jar, module); } - private void processExternalLibs(Jar jar, ApplicationModule module) - throws CancelledException, IOException { - List list = libsMap.get(module.getName()); - if (list == null) { - return; - } - for (String libPath : list) { - File file = new File(libPath); - processJarFile(jar, file, module); - } - } - private void processLibDir(Jar jar, ApplicationModule module) throws CancelledException, IOException { File libDir = new File(module.getModuleDir(), "lib"); @@ -585,16 +558,34 @@ public class GhidraJarBuilder implements GhidraLaunchable { } return manifest; } - - private List findAllModules() { + + private List findAllModules(ApplicationLayout layout) throws IOException { List modules = new ArrayList<>(); - for (File appRoot : rootGhidraDirs) { - findModules(appRoot, appRoot, modules); - findModules(appRoot, new File(appRoot, "../GPL"), modules); - + + for (GModule module : layout.getModules().values()) { + File moduleDir = module.getModuleRoot().getFile(false).getCanonicalFile(); + File rootDir = getModuleRootDir(moduleDir); + modules.add(new ApplicationModule(rootDir, moduleDir)); } + return modules; } + + private File getModuleRootDir(File moduleDir) { + // Look in GPL directories too + List rootDirs = new ArrayList<>(rootGhidraDirs); + for (File rootDir : rootGhidraDirs) { + rootDirs.add(new File(rootDir.getParentFile(), "GPL")); + } + + // Check each root directory to see if it contains the module + for (File rootDir : rootDirs) { + if (FileUtilities.isPathContainedWithin(rootDir, moduleDir)) { + return rootDir; + } + } + throw new AssertException("Module root directory could not be determined: " + moduleDir); + } private String getPathFromRoot(String rootPath, File file) { String filePath = file.getAbsolutePath(); @@ -604,23 +595,6 @@ public class GhidraJarBuilder implements GhidraLaunchable { return filePath.substring(rootPath.length() + 1); } - private void findModules(File rootAppDir, File dir, List modules) { - File moduleManifest = new File(dir, "Module.manifest"); - if (moduleManifest.exists()) { - ApplicationModule module = new ApplicationModule(rootAppDir, dir); - modules.add(module); - return; // modules can't live in other modules; - } - File[] listFiles = dir.listFiles(); - if (listFiles != null) { - for (File file : listFiles) { - if (file.isDirectory()) { - findModules(rootAppDir, file, modules); - } - } - } - } - private void checkExtensionPointClass(String path, InputStream inputStream) { // remove .class path = path.substring(0, path.length() - 6); @@ -931,44 +905,15 @@ public class GhidraJarBuilder implements GhidraLaunchable { } } - private static void parseLibsFile(String libsFilePath) { - try { - List lines = FileUtilities.getLines(new File(libsFilePath)); - - List libPaths = new ArrayList<>(); - String currentModule = null; - for (String line : lines) { - if (line.startsWith(LIBS_FILE_MODULE_KEY)) { - if (currentModule != null) { - libsMap.put(currentModule, libPaths); - libPaths = new ArrayList<>(); - } - currentModule = line.substring(LIBS_FILE_MODULE_KEY.length()).trim(); - } - else { - libPaths.add(line.trim()); - } - } - } - catch (IOException e) { - System.err.println("Could not read lib paths file: " + libsFilePath); - System.exit(0); - } - } - private static void usage(String[] args) { for (int i = 0; i < args.length; i++) { System.err.println("arg " + i + ": " + args[i]); } String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY); - String property = System.getProperty(GHIDRA_DIR); StringBuffer buf = new StringBuffer(); buf.append("\nUsage: "); - buf.append(invocationName != null ? invocationName : "GhidraJarBuilder "); - if (property == null) { - buf.append(" [ ...] "); - } + buf.append(invocationName != null ? invocationName : "GhidraJarBuilder"); buf.append( " [-output ] [-srczip ] [-bin ] [-main ]\n"); System.err.println(buf.toString()); @@ -992,17 +937,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { usage(args); } - List ghidraDirs = new ArrayList<>(); File outputFile = null; File srczip = null; File extraBinDir = null; String mainClassArg = null; - boolean usingGradle = false; - - String property = System.getProperty(GHIDRA_DIR); - if (property != null) { - ghidraDirs.add(new File(property)); - } for (int i = 0; i < args.length; i++) { String arg = args[i]; @@ -1030,28 +968,14 @@ public class GhidraJarBuilder implements GhidraLaunchable { } mainClassArg = args[++i]; } - else if (arg.equals("-gradle")) { - if (i == args.length - 1) { - usage(args); - } - usingGradle = true; - parseLibsFile(args[++i]); - } - else if (arg.startsWith("-")) { + else { usage(args); } - else { - ghidraDirs.add(new File(arg)); - } - } - if (ghidraDirs.isEmpty()) { - usage(args); } if (outputFile == null) { outputFile = new File("ghidra.jar"); } - System.out.println("Ghidra dirs = " + ghidraDirs); System.out.println("Output file = " + outputFile); if (srczip != null) { System.out.println("Source Zip File = " + srczip); @@ -1061,13 +985,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { } try { - GhidraJarBuilder builder = new GhidraJarBuilder(ghidraDirs); + GhidraJarBuilder builder = new GhidraJarBuilder(layout); if (mainClassArg != null) { builder.setMainClass(mainClassArg); } - if (usingGradle) { - builder.setGradleMode(); - } builder.addExcludedFileExtension(".pdf"); // builder.addExcludedFileExtension(".htm"); @@ -1082,10 +1003,10 @@ public class GhidraJarBuilder implements GhidraLaunchable { System.out.println("Exclude " + module.getName()); } - builder.buildJar(outputFile, extraBinDir, TaskMonitorAdapter.DUMMY_MONITOR); + builder.buildJar(outputFile, extraBinDir, TaskMonitor.DUMMY); if (srczip != null) { - builder.buildSrcZip(srczip, TaskMonitorAdapter.DUMMY_MONITOR); + builder.buildSrcZip(srczip, TaskMonitor.DUMMY); } } catch (Exception e) { @@ -1099,8 +1020,4 @@ public class GhidraJarBuilder implements GhidraLaunchable { return new File(ghidraRootDir, "application.properties"); } - private void setGradleMode() { - inGradleMode = true; - } - } diff --git a/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java b/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java index f7ec50de6a..0e6909f086 100644 --- a/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java +++ b/Ghidra/Features/Base/src/main/java/org/apache/felix/framework/util/MultiReleaseContent.java @@ -1,7 +1,8 @@ /* ### * IP: Apache License 2.0 - * - * This is fix for a bug found in the Felix Framework: + */ +/*** + * This is fix for a bug found in the Felix Framework: * * https://issues.apache.org/jira/browse/FELIX-6297 * @@ -9,8 +10,8 @@ * * THIS FILE SHOULD BE REMOVED WHEN THE ISSUE IS ADDRESSED. * - */ -/* + *** + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -30,24 +31,15 @@ */ package org.apache.felix.framework.util; -import org.apache.felix.framework.cache.Content; -import org.osgi.framework.Version; - import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.jar.Attributes; +import java.util.*; import java.util.jar.Manifest; +import org.apache.felix.framework.cache.Content; +import org.osgi.framework.Version; + public class MultiReleaseContent implements Content { private final Content m_content; diff --git a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html index 9e5de3196f..b66dce8c8f 100644 --- a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html +++ b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph.html @@ -840,6 +840,22 @@ location when zooming from the middle-mouse. The default for this option is off, which triggers zoom to work from the center of the graph, regardless of the mouse location.

    +

    The View Settings option describes how the graph will be zoomed when it is first + loaded. The values are:

    + +
      +
    • Start Fully Zoomed Out - always start fully zoomed out so that the entire + graph can be seen.
    • + +
    • Start Fully Zoomed In/B> - always start fully zoomed in on the vertex containing + the current location.
    • + +
    • Remember User Settings - keep the zoom level where the user previously left + it.
    • +
    +
    +
    +

    There are various edge color and highlight color options available to change. The highlight colors are those to be used when the flow animations take place.

    diff --git a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html index 2f2eab68a8..6e71260598 100644 --- a/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html +++ b/Ghidra/Features/FunctionGraph/src/main/help/help/topics/FunctionGraphPlugin/Function_Graph_Layouts.html @@ -49,6 +49,13 @@ notes on how edges are routed for this layout.)

    + +
    +

    The Use Dim Return Edges option makes default code block return flow edges + lighter than conditional edges. This makes it easier for users to scan the + graph and ignore return flows. +

    +
    diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java index 51b6773a9a..ea22f1cf44 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java @@ -42,7 +42,7 @@ public class FunctionGraphOptions extends VisualGraphOptions { private static final String EDGE_COLOR_CONDITIONAL_JUMP_KEY = "Edge Color - Conditional Jump "; //@formatter:off - private static final String NAVIGATION_HISTORY_KEY = "Navigation History"; + private static final String NAVIGATION_HISTORY_KEY = "Navigation History"; private static final String NAVIGATION_HISTORY_DESCRIPTION = "Determines how the navigation history will be updated when using the Function Graph. " + "The basic options are:" + @@ -185,8 +185,8 @@ public class FunctionGraphOptions extends VisualGraphOptions { options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help, SCROLL_WHEEL_PANS_DESCRIPTION); - options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, - help, GRAPH_BACKGROUND_COLOR_DESCRPTION); + options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, help, + GRAPH_BACKGROUND_COLOR_DESCRPTION); options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR, help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION); diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java index 1467a84781..1549c2cd9a 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DNLayoutOptions.java @@ -31,7 +31,12 @@ public class DNLayoutOptions implements FGLayoutOptions { "edges should be routed around any intersecting vertex. When toggled off, edges will " + "pass through any intersecting vertices."; + private static final String DIM_RETURN_EDGES_KEY = "Use Dim Return Edges"; + private static final String DIM_RETURN_EDGES_DESCRIPTION = + "Signals to lighten the default return edges."; + private boolean useEdgeRoutingAroundVertices; + private boolean useDimmedReturnEdges = true; @Override public void registerOptions(Options options) { @@ -40,21 +45,32 @@ public class DNLayoutOptions implements FGLayoutOptions { options.registerOption(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices, help, USE_EDGE_ROUTING_AROUND_VERTICES_DESCRIPTION); + + options.registerOption(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges, help, + DIM_RETURN_EDGES_DESCRIPTION); } @Override public void loadOptions(Options options) { useEdgeRoutingAroundVertices = options.getBoolean(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices); + + useDimmedReturnEdges = options.getBoolean(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges); + } public boolean useEdgeRoutingAroundVertices() { return useEdgeRoutingAroundVertices; } + public boolean useDimmedReturnEdges() { + return useDimmedReturnEdges; + } + @Override public boolean optionChangeRequiresRelayout(String optionName) { // format: 'Nested Code Layout.Route Edges....' - return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY); + return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY) || + optionName.endsWith(DIM_RETURN_EDGES_KEY); } } diff --git a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java index 761c18f743..39c2744d80 100644 --- a/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java +++ b/Ghidra/Features/FunctionGraphDecompilerExtension/src/main/java/ghidra/app/plugin/core/functiongraph/graph/layout/DecompilerNestedLayout.java @@ -38,6 +38,7 @@ import ghidra.app.plugin.core.functiongraph.graph.jung.renderer.DNLArticulatedEd import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex; import ghidra.app.plugin.core.functiongraph.graph.vertex.GroupedFunctionGraphVertex; import ghidra.graph.VisualGraph; +import ghidra.graph.viewer.GraphViewerUtils; import ghidra.graph.viewer.layout.*; import ghidra.graph.viewer.vertex.VisualGraphVertexShapeTransformer; import ghidra.program.model.address.Address; @@ -52,19 +53,19 @@ import ghidra.util.task.TaskMonitor; /** * A layout that uses the decompiler to show code nesting based upon conditional logic. - * + * *

    Edges returning to the default code flow are painted lighter to de-emphasize them. This * could be made into an option. - * - *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. + * + *

    Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option. * Simple routing will reduce edge noise as much as possible by combining/overlapping edges that * flow towards the bottom of the function (returning code flow). Also, edges may fall behind * vertices for some functions. Complex routing allows the user to visually follow the flow * of an individual edge. Complex routing will prevent edges from overlapping and will route - * edges around vertices. Simple routing is better when the layout of the vertices is - * important to the user; complex routing is better when edges/relationships are more + * edges around vertices. Simple routing is better when the layout of the vertices is + * important to the user; complex routing is better when edges/relationships are more * important to the user. - * + * * TODO ideas: * -paint fallthrough differently for all, or just for those returning to the baseline */ @@ -113,7 +114,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override protected double getCondenseFactor() { - // our layout needs more spacing because we have custom edge routing that we want to + // our layout needs more spacing because we have custom edge routing that we want to // stand out return .3; } @@ -201,7 +202,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { continue; } - // + // // Special case: fallthrough--don't label this...not sure how to tell fallthrough. For // now assume that any column below or backwards is fallthrough. However, // do label fallthrough if it is the only edge. @@ -231,10 +232,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Map> newEdgeArticulations = new HashMap<>(); - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method below is + // bit for that effect using this offset value. The getEdgeOffset() method below is // updated for the condense factor. int edgeOffset = isCondensedLayout() ? (int) (VERTEX_TO_EDGE_ARTICULATION_PADDING * (1 - getCondenseFactor())) @@ -242,7 +243,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Vertex2dFactory vertex2dFactory = new Vertex2dFactory(transformer, vertexLayoutLocations, layoutToGridMap, edgeOffset); - // + // // Route our edges! // for (FGEdge e : edges) { @@ -262,11 +263,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { DecompilerBlock loop = block.getParentLoop(); if (loop != null) { - Set vertices = loop.getVertices(); - - Column outermostCol = getOutermostCol(layoutToGridMap, vertices); - Column loopEndColumn = layoutToGridMap.nextColumn(outermostCol); - List articulations = routeLoopEdge(start, end, loopEndColumn); + List articulations = + routeUpwardLoop(layoutToGridMap, vertex2dFactory, start, end, loop); newEdgeArticulations.put(e, articulations); continue; } @@ -275,31 +273,31 @@ public class DecompilerNestedLayout extends AbstractFGLayout { List articulations = new ArrayList<>(); // - // Basic routing: + // Basic routing: // -leave the bottom of the start vertex // -first bend at some constant offset // -move to right or left, to above the end vertex // -second bend above the end vertex at previous constant offset - // - // Edges start/end on the vertex center. If we offset them to avoid + // + // Edges start/end on the vertex center. If we offset them to avoid // overlapping, then they produce angles when only using two articulations. // Thus, we create articulations that are behind the vertices to remove // the angles. This points will not be seen. // - // + // // Complex routing: // -this mode will route edges around vertices - // + // // One goal for complex edge routing is to prevent overlapping (simple edge routing // prefers overlapping to reduce lines). To prevent overlapping we will use different - // offset x and y values, depending upon the start and end vertex row and column + // offset x and y values, depending upon the start and end vertex row and column // locations. Specifically, for a given edge direction there will be a bias: // -Edge to the right - leave from the right; arrive to the left // -Edge to the left - leave from the left; arrive to the right // -Edge straight down - go straight down // // For each of the above offsets, there will be an amplifier based upon row/column - // distance from start to end vertex. This has the effect that larger vertex + // distance from start to end vertex. This has the effect that larger vertex // distances will have a larger offset/spacing. // @@ -331,14 +329,78 @@ public class DecompilerNestedLayout extends AbstractFGLayout { return newEdgeArticulations; } + private List routeUpwardLoop(LayoutLocationMap layoutToGridMap, + Vertex2dFactory vertex2dFactory, Vertex2d start, Vertex2d end, DecompilerBlock loop) { + Set loopVertices = loop.getVertices(); + FGVertex rightmostLoopVertex = + getRightmostVertex(layoutToGridMap, vertex2dFactory, loopVertices); + + int startRow = start.rowIndex; + int endRow = end.rowIndex; + int startColumn = Math.min(start.columnIndex, end.columnIndex); + int endColumn = Math.max(start.columnIndex, end.columnIndex); + + Column rightmostLoopColumn = layoutToGridMap.col(rightmostLoopVertex); + endColumn = Math.max(endColumn, rightmostLoopColumn.index); + + // Look for any vertices that are no part of the loop, but are placed inside + // of the loop bounds. This can happen in a graph when the decompiler uses + // goto statements. Use the loop's rightmost vertex to establish the loops + // right edge and then use that to check for any stray non-loop vertices. + List interlopers = + getVerticesInBounds(vertex2dFactory, startRow, endRow, startColumn, endColumn); + + // place the right x position to the right of the rightmost vertex, not + // extending past the next column + FGVertex rightmostVertex = getRightmostVertex(interlopers); + Column rightmostColumn = layoutToGridMap.col(rightmostVertex); + Column nextColumn = layoutToGridMap.nextColumn(rightmostColumn); + Vertex2d rightmostV2d = vertex2dFactory.get(rightmostVertex); + + // the padding used for these two lines is somewhat arbitrary and may be changed + double rightSide = rightmostV2d.getRight() + GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING; + double x = Math.min(rightSide, + nextColumn.x - GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING_CONDENSED); + + List articulations = routeLoopEdge(start, end, x); + return articulations; + } + + private List getVerticesInBounds(Vertex2dFactory vertex2dFactory, int startRow, + int endRow, int startColumn, int endColumn) { + + if (startRow > endRow) { // going upwards + int temp = endRow; + endRow = startRow; + startRow = temp; + } + + List toCheck = new LinkedList<>(); + for (int row = startRow; row < endRow + 1; row++) { + + for (int col = startColumn; col < endColumn + 1; col++) { + + // assume any other vertex in our column can clip (it will not clip when + // the 'spacing' above pushes the edge away from this column, like for + // large row delta values) + Vertex2d otherVertex = vertex2dFactory.get(row, col); + if (otherVertex != null) { + toCheck.add(otherVertex); + } + } + } + + return toCheck; + } + private void routeToTheRightGoingUpwards(Vertex2d start, Vertex2d end, Vertex2dFactory vertex2dFactory, List articulations) { // - // For routing to the right and back up we will leave the start vertex from the right side + // For routing to the right and back up we will leave the start vertex from the right side // and enter the end vertex on the right side. As the vertices get further apart, we will - // space them further in towards the center. - // + // space them further in towards the center. + // int delta = start.rowIndex - end.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -347,11 +409,16 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } int distanceSpacing = delta * multiplier; - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing is when the graph will pull nodes closer together on the x axis to + // reduce whitespace and make the entire graph easier to see. In this case, update + // the offset to avoid running into the moved vertices. + + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is + // bit for that effect using this offset value. The getEdgeOffset() method is // updated for the condense factor. + int exaggerationFactor = 1; if (isCondensedLayout()) { exaggerationFactor = 2; // determined by trial-and-error; can be made into an option @@ -369,7 +436,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { y1 = Math.min(y1, startCenterY); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double startRightX = start.getRight(); double x2 = startRightX + VERTEX_BORDER_THICKNESS; // start at the end @@ -434,10 +501,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // For routing to the left we will leave the start vertex from just left of center and - // enter the end vertex on the top, towards the right. As the vertices get further apart, - // we will space them further in towards the center of the end vertex. This will keep + // enter the end vertex on the top, towards the right. As the vertices get further apart, + // we will space them further in towards the center of the end vertex. This will keep // edges with close endpoints from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER; @@ -499,7 +566,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // enter the end vertex on the left side. As the vertices get further apart, we will // space them further in towards the center. This will keep edges with close endpoints // from intersecting edges with distant endpoints. - // + // int delta = end.rowIndex - start.rowIndex; if (delta < 0) { @@ -529,7 +596,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y1 = start.getY(); articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex - // Use the spacing to move the y value towards the top of the vertex. Just like with + // Use the spacing to move the y value towards the top of the vertex. Just like with // the x value, restrict the y to the range between the edge and the center. double x2 = x1; double y2 = end.getTop() + VERTEX_BORDER_THICKNESS; @@ -556,19 +623,6 @@ public class DecompilerNestedLayout extends AbstractFGLayout { private void routeAroundColumnVertices(Vertex2d start, Vertex2d end, Vertex2dFactory vertex2dFactory, List articulations, double edgeX) { - Column column = vertex2dFactory.getColumn(edgeX); - int columnIndex = 0; - if (column != null) { - // a null column happens with a negative x value that is outside of any column - columnIndex = column.index; - } - - routeAroundColumnVertices(start, end, columnIndex, vertex2dFactory, articulations, edgeX); - } - - private void routeAroundColumnVertices(Vertex2d start, Vertex2d end, int column, - Vertex2dFactory vertex2dFactory, List articulations, double edgeX) { - if (useSimpleRouting()) { return; } @@ -582,14 +636,34 @@ public class DecompilerNestedLayout extends AbstractFGLayout { startRow = end.rowIndex; } + int startColumn = Math.min(start.columnIndex, end.columnIndex); + int endColumn = Math.max(start.columnIndex, end.columnIndex); + if (goingDown) { + endRow -= 1; + endColumn -= 1; + + if (start.columnIndex <= end.columnIndex) { + startRow += 1; + } + } + else { + // going up we swing out to the right; grab the column that is out to the right + Column rightColumn = vertex2dFactory.getColumn(edgeX); + endColumn = rightColumn.index; + } + List toCheck = new LinkedList<>(); - for (int row = startRow + 1; row < endRow; row++) { - // assume any other vertex in our column can clip (it will not clip when - // the 'spacing' above pushes the edge away from this column, like for - // large row delta values) - Vertex2d otherVertex = vertex2dFactory.get(row, column); - if (otherVertex != null) { - toCheck.add(otherVertex); + for (int row = startRow; row < endRow + 1; row++) { + + for (int col = startColumn; col < endColumn + 1; col++) { + + // assume any other vertex in our column can clip (it will not clip when + // the 'spacing' above pushes the edge away from this column, like for + // large row delta values) + Vertex2d otherVertex = vertex2dFactory.get(row, col); + if (otherVertex != null) { + toCheck.add(otherVertex); + } } } @@ -605,11 +679,16 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING; int distanceSpacing = padding + delta; // adding the delta makes overlap less likely - // Condensing Note: we have guilty knowledge that our parent class my condense the + // Condensing is when the graph will pull nodes closer together on the x axis to + // reduce whitespace and make the entire graph easier to see. In this case, update + // the offset to avoid running into the moved vertices. + + // Condensing Note: we have guilty knowledge that our parent class my condense the // vertices and edges towards the center of the graph after we calculate positions. // To prevent the edges from moving to far behind the vertices, we will compensate a - // bit for that effect using this offset value. The getEdgeOffset() method is + // bit for that effect using this offset value. The getEdgeOffset() method is // updated for the condense factor. + int vertexToEdgeOffset = otherVertex.getEdgeOffset(); int exaggerationFactor = 1; if (isCondensedLayout()) { @@ -629,20 +708,20 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // no need to check the 'y' value, as the end vertex is above/below this one if (vertexClipper.isClippingX(otherVertex, edgeX)) { - /* + /* Must route around this vertex - new points: -p1 - just above the intersection point -p2 - just past the left edge -p3 - just past the bottom of the vertex -p4 - back at the original x value - + | .___| | .-----. | | | | '-----' '---. - | + | */ // p1 - same x; y just above vertex @@ -650,19 +729,19 @@ public class DecompilerNestedLayout extends AbstractFGLayout { double y = vertexClipper.getTopOffset(otherVertex, vertexToEdgeOffset); articulations.add(new Point2D.Double(x, y)); - // Maybe merge points if they are too close together. Visually, many lines - // moving around intersecting vertices looks busy. When the intersecting + // Maybe merge points if they are too close together. Visually, many lines + // moving around intersecting vertices looks busy. When the intersecting // vertices are close together, we remove some of the articulations in order to // smooth out the edges. if (articulations.size() > 2) { - /* + /* The last articulation is the one added before this method was called, which - lies just below the intersecting vertex. The articulation before that is - the one that is the one that is sending the x value straight into the + lies just below the intersecting vertex. The articulation before that is + the one that is the one that is sending the x value straight into the intersecting vertex. Delete that point as well so that the entire edge is shifted to the outside of the intersecting vertex. This will get repeated - for each vertex that is intersecting. + for each vertex that is intersecting. */ Point2D previousArticulation = articulations.get(articulations.size() - 2); int closenessHeight = 50; @@ -696,15 +775,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout { return !getLayoutOptions().useEdgeRoutingAroundVertices(); } - private List routeLoopEdge(Vertex2d start, Vertex2d end, Column loopEndColumn) { + private List routeLoopEdge(Vertex2d start, Vertex2d end, double x) { // going backwards List articulations = new ArrayList<>(); - // loop first point - same y coord as the vertex; x is the middle of the next col - int halfWidth = loopEndColumn.getPaddedWidth(isCondensedLayout()) >> 1; - double x = loopEndColumn.x + halfWidth; // middle of the column - int startRow = start.rowIndex; int endRow = end.rowIndex; if (startRow > endRow) { // going upwards @@ -720,7 +795,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { Point2D first = new Point2D.Double(x, y1); articulations.add(first); - // loop second point - same y coord as destination; + // loop second point - same y coord as destination; // x is the col after the outermost dominated vertex Point2D endVertexPoint = end.center; @@ -733,27 +808,47 @@ public class DecompilerNestedLayout extends AbstractFGLayout { private void lighten(FGEdge e) { + if (!getLayoutOptions().useDimmedReturnEdges()) { + return; + } + // assumption: edges that move to the left in this layout are return flows that happen // after the code block has been executed. We dim those a bit so that they // produce less clutter. e.setDefaultAlpha(.25); } - private Column getOutermostCol(LayoutLocationMap layoutLocations, - Set vertices) { + private FGVertex getRightmostVertex(LayoutLocationMap layoutLocations, + Vertex2dFactory vertex2dFactory, Set vertices) { - Column outermost = null; + List points = new ArrayList<>(); for (FGVertex v : vertices) { - Column col = layoutLocations.col(v); - if (outermost == null) { - outermost = col; + Vertex2d v2d = vertex2dFactory.get(v); + points.add(v2d); + } + + FGVertex v = getRightmostVertex(points); + return v; + } + + private FGVertex getRightmostVertex(Collection points) { + + Vertex2d rightmost = null; + for (Vertex2d v2d : points) { + if (rightmost == null) { + rightmost = v2d; } - else if (col.x > outermost.x) { - outermost = col; + else { + // the rightmost is that which extends furthest to the right + double current = rightmost.getRight(); + double other = v2d.getRight(); + if (other > current) { + rightmost = v2d; + } } } - return outermost; + return rightmost.v; } @Override @@ -840,8 +935,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout { BlockCopy copy = (BlockCopy) child; StringBuilder buffy = new StringBuilder(); - buffy.append(printDepth(depth, depth + 1)).append(' ').append(ID).append( - " plain - ").append(copy.getRef()); + buffy.append(printDepth(depth, depth + 1)) + .append(' ') + .append(ID) + .append(" plain - ") + .append(copy.getRef()); debug(buffy.toString()); } @@ -958,7 +1056,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { //================================================================================================== // Inner Classes -//================================================================================================== +//================================================================================================== /** * Encapsulates knowledge of edge direction (up/down, left/right) and uses that knowledge @@ -1060,7 +1158,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { } /** - * A class that represents 2D information about the contained vertex, such as location, + * A class that represents 2D information about the contained vertex, such as location, * bounds, row and column of the layout grid. */ private class Vertex2d { @@ -1207,8 +1305,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { int row = startRow; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { row = ((DecompilerBlockGraph) block).setRows(row); } @@ -1229,8 +1326,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { String getChildrenString(int depth) { StringBuilder buffy = new StringBuilder(); int childCount = 0; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { if (block instanceof DecompilerBlockGraph) { String blockName = block.getName(); @@ -1315,8 +1411,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { @Override DecompilerBlock getBlock(FGVertex vertex) { // - // Note: we currently allow grouping in this layout. When we search for a vertex, - // we have to check each vertex inside of the given group *and* each vertex + // Note: we currently allow grouping in this layout. When we search for a vertex, + // we have to check each vertex inside of the given group *and* each vertex // inside of the vertex that belongs to this decompiler block. // if (vertex instanceof GroupedFunctionGraphVertex) { @@ -1447,9 +1543,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // The 'list' structure for children's nesting: // -all nodes are at the same level // - for (int i = 0; i < allChildren.size(); i++) { + for (DecompilerBlock block : allChildren) { int column = col; - DecompilerBlock block = allChildren.get(i); block.setCol(column); } @@ -1477,8 +1572,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // -each successive condition is another level nested // int column = col; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); column++; } @@ -1515,11 +1609,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout { // // The 'do' structure for children's nesting: - // -all blocks nested + // -all blocks nested // int column = col + 1; - for (int i = 0; i < allChildren.size(); i++) { - DecompilerBlock block = allChildren.get(i); + for (DecompilerBlock block : allChildren) { block.setCol(column); } diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index f5f3580822..5905018f95 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -52,7 +52,7 @@ public class ServerAdmin implements GhidraLaunchable { * The following properties may be set: *

     	 *   UserAdmin.invocation - identifies the name of the application used when displaying usage text.
    -	 *   UserAdmin.serverDir - identifies the server directory instead of passing on command line.
    +	 *   UserAdmin.config - identifies the config file instead of passing on command line.
     	 * 
    * @param args command line arguments */ @@ -75,22 +75,18 @@ public class ServerAdmin implements GhidraLaunchable { * The following properties may be set: *
     	 *   UserAdmin.invocation - identifies the name of the application used when displaying usage text.
    -	 *   UserAdmin.serverDir - identifies the server directory instead of passing on command line.
    +	 *   UserAdmin.config - identifies the config file instead of passing on command line.
     	 * 
    * @param args command line arguments */ public void execute(String[] args) { - File serverDir = null; - int ix = 0; - if (args.length != 0 && !args[0].startsWith("-")) { - serverDir = new File(args[ix++]); - } - else { - serverDir = getServerDirFromConfig(); - } + String configFilePath = args.length != 0 && !args[0].startsWith("-") ? args[ix++] + : System.getProperty(CONFIG_FILE_PROPERTY); + + File serverDir = getServerDirFromConfig(configFilePath); if (serverDir == null || (args.length - ix) == 0) { displayUsage(""); System.exit(-1); @@ -105,9 +101,7 @@ public class ServerAdmin implements GhidraLaunchable { System.exit(-1); } - if (propertyUsed) { - System.out.println("Using server directory: " + serverDir); - } + System.out.println("Using server directory: " + serverDir); File userFile = new File(serverDir, UserManager.USER_PASSWORD_FILE); if (!serverDir.isDirectory() || !userFile.isFile()) { @@ -423,13 +417,14 @@ public class ServerAdmin implements GhidraLaunchable { } } - private File getServerDirFromConfig() { - String p = System.getProperty(CONFIG_FILE_PROPERTY); - if (p == null) { + private File getServerDirFromConfig(String configFilePath) { + System.out.println("Using config file: " + configFilePath); + + if (configFilePath == null) { return null; } - propertyUsed = true; - File configFile = new File(p); + + File configFile = new File(configFilePath); if (!configFile.exists()) { System.out.println("Config file not found: " + configFile.getAbsolutePath()); @@ -455,8 +450,9 @@ public class ServerAdmin implements GhidraLaunchable { } } - p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); + String p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); if (p == null) { + System.out.println("Failed to find property: " + SERVER_DIR_CONFIG_PROPERTY); return null; } File dir = new File(p); @@ -482,8 +478,8 @@ public class ServerAdmin implements GhidraLaunchable { } String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY); System.err.println("Usage: " + - (invocationName != null ? invocationName : "java " + UserAdmin.class.getName()) + - (propertyUsed ? "" : " ") + " [] [] ..."); + (invocationName != null ? invocationName : "java " + ServerAdmin.class.getName()) + + (invocationName != null ? "" : " ") + " [] [] ..."); System.err.println("\nSupported commands:"); System.err.println(" -add [--p]"); System.err.println( diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java index c0963c8883..d485574655 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableComponent.java @@ -151,6 +151,10 @@ public class DockableComponent extends JPanel implements ContainerListener { } private void showContextMenu(MouseEvent e) { + if (e.isConsumed()) { + return; + } + Component component = e.getComponent(); if (component == null) { return; // not sure this can happen @@ -190,7 +194,7 @@ public class DockableComponent extends JPanel implements ContainerListener { /** * Returns the component provider attached to this dockable component; null if this object * has been disposed - * + * * @return the provider */ public ComponentProvider getComponentProvider() { @@ -255,7 +259,7 @@ public class DockableComponent extends JPanel implements ContainerListener { public synchronized void dragEnter(DropTargetDragEvent dtde) { super.dragEnter(dtde); - // On Mac, sometimes this component is not showing, + // On Mac, sometimes this component is not showing, // which causes exception in the translate method. if (!isShowing()) { dtde.rejectDrag(); @@ -278,7 +282,7 @@ public class DockableComponent extends JPanel implements ContainerListener { public synchronized void dragOver(DropTargetDragEvent dtde) { super.dragOver(dtde); - // On Mac, sometimes this component is not showing, + // On Mac, sometimes this component is not showing, // which causes exception in the translate method. if (!isShowing()) { dtde.rejectDrag(); @@ -457,7 +461,7 @@ public class DockableComponent extends JPanel implements ContainerListener { private void componentSelected(Component component) { if (!component.isFocusable()) { - // In this case, Java will not change focus for us, so we need to tell the DWM to + // In this case, Java will not change focus for us, so we need to tell the DWM to // change the active DockableComponent requestFocus(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java index 7e0975539c..21758d2c8c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java @@ -16,12 +16,12 @@ package docking.framework; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Objects; +import java.util.*; import generic.jar.ResourceFile; import ghidra.framework.ApplicationProperties; import ghidra.util.SystemUtilities; +import util.CollectionUtils; import utility.application.ApplicationLayout; import utility.application.ApplicationUtilities; import utility.module.ModuleUtilities; @@ -34,16 +34,6 @@ public class DockingApplicationLayout extends ApplicationLayout { private static final String NO_RELEASE_NAME = "NO_RELEASE"; - /** - * Constructs a new docking application layout object with the given name. - * - * @param name The name of the application. - * @throws FileNotFoundException if there was a problem getting a user directory. - */ - public DockingApplicationLayout(String name) throws FileNotFoundException { - this(name, "0.1"); - } - /** * Constructs a new docking application layout object with the given name and version. * @@ -57,24 +47,31 @@ public class DockingApplicationLayout extends ApplicationLayout { /** * Constructs a new docking application layout object with the given set of application - * properties. + * properties. The default Ghidra application root directory(s) will be used. * * @param applicationProperties The properties object that will be read system properties. * @throws FileNotFoundException if there was a problem getting a user directory. */ public DockingApplicationLayout(ApplicationProperties applicationProperties) throws FileNotFoundException { + this(getDefaultApplicationRootDirs(), applicationProperties); + } + + /** + * Constructs a new docking application layout object with the given set of application + * properties. + * + * @param applicationRootDirs list of application root directories which should be + * used to idenitfy modules and resources. The first entry will be treated as the + * installation root. + * @param applicationProperties The properties object that will be read system properties. + * @throws FileNotFoundException if there was a problem getting a user directory. + */ + public DockingApplicationLayout(Collection applicationRootDirs, + ApplicationProperties applicationProperties) throws FileNotFoundException { this.applicationProperties = Objects.requireNonNull(applicationProperties); - - // Application root directories - if (SystemUtilities.isInDevelopmentMode()) { - applicationRootDirs = ApplicationUtilities.findDefaultApplicationRootDirs(); - } - else { - applicationRootDirs = new ArrayList<>(); - applicationRootDirs.add(new ResourceFile(System.getProperty("user.dir"))); - } + this.applicationRootDirs = applicationRootDirs; // Application installation directory applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile(); @@ -97,4 +94,18 @@ public class DockingApplicationLayout extends ApplicationLayout { applicationInstallationDir); } + /** + * Get the default list of Application directories. In repo-based + * development mode this includes the root Ghidra directory within each repo. + * When not in development mode, the requirement is that the current working + * directory correspond to the installation root. The first entry will be + * the primary root in both cases. + * @return root directories + */ + public static Collection getDefaultApplicationRootDirs() { + if (SystemUtilities.isInDevelopmentMode()) { + return ApplicationUtilities.findDefaultApplicationRootDirs(); + } + return CollectionUtils.asList(new ResourceFile(System.getProperty("user.dir"))); + } } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java index 0fba3848f2..afecdf2477 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/layout/AbstractVisualGraphLayout.java @@ -44,36 +44,36 @@ import ghidra.util.task.TaskMonitor; * A base layout that marries the Visual Graph and Jung layout interfaces. This class allows * you to create new layouts while stubbing the Jung layout methods. * - *

    This class essentially takes in client-produced grid row and column indices and + *

    This class essentially takes in client-produced grid row and column indices and * produces layout locations for those values. * - *

    This an implementation the Jung {@link Layout} interface that handles most of the + *

    This an implementation the Jung {@link Layout} interface that handles most of the * layout implementation for you. Things to know: *

      *
    • You should call initialize() inside of your constructor
    • - *
    • You must implement {@link #performInitialGridLayout(VisualGraph)} - this is where + *
    • You must implement {@link #performInitialGridLayout(VisualGraph)} - this is where * you align your vertices (and optionally edge articulations) on a grid. This grid * will be translated into layout space points for you.
    • - *
    • If you wish to use articulation points in your edges, you must override - * {@link #usesEdgeArticulations()} to return true.
    • + *
    • If you wish to use articulation points in your edges, you must override + * {@link #usesEdgeArticulations()} to return true.
    • *
    - * + * *

    By default, this class will create x-position values that - * are aligned with the column's x-position. You can override + * are aligned with the column's x-position. You can override * {@link #getVertexLocation(VisualVertex, Column, Row, Rectangle)} in order to center the * vertex within its column - * {@link #getCenteredVertexLocation(VisualVertex, Column, Row, Rectangle)}. Also note though + * {@link #getCenteredVertexLocation(VisualVertex, Column, Row, Rectangle)}. Also note though * that if your layout returns true for {@link #isCondensedLayout()}, - * then the centering will be condensed and slightly off. - * + * then the centering will be condensed and slightly off. + * * @param the vertex type * @param the edge type - * + * * @see GridLocationMap * @see LayoutPositions */ //@formatter:off -public abstract class AbstractVisualGraphLayout> extends AbstractLayout implements VisualGraphLayout { @@ -106,9 +106,9 @@ public abstract class AbstractVisualGraphLayout newLayout) { @@ -260,7 +260,7 @@ public abstract class AbstractVisualGraphLayout bends = edgesToBends.get(e); if (bends == null) { - // New edge is not in the old graph. This can happen if the old graph has + // New edge is not in the old graph. This can happen if the old graph has // grouped vertices and some edges have been removed. continue; } @@ -313,14 +313,7 @@ public abstract class AbstractVisualGraphLayout vertexLayoutLocations = positionVerticesInLayoutSpace(transformer, vertices, layoutLocations); - Map> edgeLayoutArticulationLocations = - positionEdgeArticulationsInLayoutSpace(transformer, vertexLayoutLocations, edges, - layoutLocations); - - // DEGUG triggers grid lines to be printed; useful for debugging -// VisualGraphRenderer.DEBUG_ROW_COL_MAP.put((Graph) visualGraph, -// layoutLocations.copy()); - + Map> edgeLayoutArticulationLocations = new HashMap<>(); Rectangle graphBounds = getTotalGraphSize(vertexLayoutLocations, edgeLayoutArticulationLocations, transformer); double centerX = graphBounds.getCenterX(); @@ -332,6 +325,12 @@ public abstract class AbstractVisualGraphLayout> 1); int y = row.y + (row.getPaddedHeight(isCondensed) >> 1); @@ -464,8 +463,8 @@ public abstract class AbstractVisualGraphLayout transformer, double centerX, double centerY) { // - // Note: we move the articulations and vertices closer together on the x-axis. We do - // not move the y-axis, as that is already as close together as we would like at + // Note: we move the articulations and vertices closer together on the x-axis. We do + // not move the y-axis, as that is already as close together as we would like at // this point. // double condenseFactor = getCondenseFactor(); @@ -496,14 +495,14 @@ public abstract class AbstractVisualGraphLayout> 1; // half width int myHeight = vertexBounds.height >> 1; // half height double x = vertexPoint.getX(); @@ -635,20 +634,20 @@ public abstract class AbstractVisualGraphLayout the vertex type - * @param the edge type + * @param the edge type */ public class VisualGraphRenderer> extends edu.uci.ics.jung.visualization.renderers.BasicRenderer { @@ -44,7 +44,8 @@ public class VisualGraphRenderer /** * Used for displaying grid information for graph layouts */ - public static Map, LayoutLocationMap> DEBUG_ROW_COL_MAP = new HashMap<>(); + public static Map, LayoutLocationMap> DEBUG_ROW_COL_MAP = + new HashMap<>(); private Renderer.EdgeLabel edgeLabelRenderer = new BasicEdgeLabelRenderer<>(); @@ -122,11 +123,15 @@ public class VisualGraphRenderer edgeLabelRenderer.labelEdge(rc, layout, e, xform.apply(e)); } + @SuppressWarnings({ "unchecked", "rawtypes" }) // the types in the cast matter not private void paintLayoutGridCells(RenderContext renderContext, Layout layout) { // to enable this debug, search java files for commented-out uses of 'DEBUG_ROW_COL_MAP' - Graph graph = layout.getGraph(); - LayoutLocationMap locationMap = DEBUG_ROW_COL_MAP.get(graph); + Layout key = layout; + if (layout instanceof ObservableCachingLayout) { + key = ((ObservableCachingLayout) layout).getDelegate(); + } + LayoutLocationMap locationMap = DEBUG_ROW_COL_MAP.get(key); if (locationMap == null) { return; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java index 1d5e24c673..a66fb1f0d0 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/StandAloneApplication.java @@ -33,7 +33,6 @@ import ghidra.framework.model.ToolServices; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.classfinder.ClassSearcher; -import ghidra.util.exception.AssertException; import ghidra.util.exception.CancelledException; import ghidra.util.xml.GenericXMLOutputter; import ghidra.util.xml.XmlUtilities; @@ -52,7 +51,6 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat /** * Creates a new application using the given properties filename. The * filename is expected reside in the current working directory. - * *

    * The given properties file is expected to have the * {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and @@ -60,43 +58,59 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat * set. * * @param propertiesFilename the name of the properties file. + * @throws IOException error causing application initialization failure */ - public StandAloneApplication(String propertiesFilename) { - - try { - ApplicationProperties properties = ApplicationProperties.fromFile(propertiesFilename); - String name = properties.getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY); - if (name == null) { - Msg.error(this, - "The application.name property is not set in " + propertiesFilename); - } - - String version = - properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY); - if (version == null) { - Msg.error(this, - "The application.name property is not set in " + propertiesFilename); - } - - ApplicationLayout applicationLayout = new DockingApplicationLayout(properties); - init(applicationLayout); - } - catch (IOException e) { - throw new AssertException(e); - } + public StandAloneApplication(String propertiesFilename) throws IOException { + this(new DockingApplicationLayout(readApplicationProperties(propertiesFilename))); } - public StandAloneApplication(String name, String version) { + /** + * Creates a new application using the specified application name + * and version. + * @param name application name + * @param version application version + * @throws IOException error causing application initialization failure + */ + public StandAloneApplication(String name, String version) throws IOException { + this(new DockingApplicationLayout(name, version)); + } - // Setup application layout - try { - ApplicationLayout applicationLayout = new DockingApplicationLayout(name, version); - init(applicationLayout); - } - catch (IOException e) { - throw new AssertException(e); + /** + * reates a new application using the given application layout + * and associated application properties. + * @param applicationLayout application layout + */ + public StandAloneApplication(ApplicationLayout applicationLayout) { + init(applicationLayout); + } + + /** + * Read {@link ApplicationProperties} from the specified file path relative + * to the current working directory. + *

    + * The given properties file is expected to have the + * {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and + * {@link ApplicationProperties#APPLICATION_VERSION_PROPERTY} properties + * set. + * @param propertiesFilename the name of the properties file. + * @return application properties + * @throws IOException if file read error occurs + */ + public static ApplicationProperties readApplicationProperties(String propertiesFilename) + throws IOException { + ApplicationProperties properties = ApplicationProperties.fromFile(propertiesFilename); + String name = properties.getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY); + if (name == null) { + Msg.error(StandAloneApplication.class, + "The application.name property is not set in " + propertiesFilename); } + String version = properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY); + if (version == null) { + Msg.error(StandAloneApplication.class, + "The application.name property is not set in " + propertiesFilename); + } + return properties; } private void init(ApplicationLayout applicationLayout) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/NamespaceUtils.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/NamespaceUtils.java index a03b6323d4..dad12522fa 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/NamespaceUtils.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/NamespaceUtils.java @@ -534,53 +534,7 @@ public class NamespaceUtils { throws InvalidInputException { Symbol namespaceSymbol = namespace.getSymbol(); - String name = namespaceSymbol.getName(); - SourceType originalSource = namespaceSymbol.getSource(); - SymbolTable symbolTable = namespaceSymbol.getProgram().getSymbolTable(); - - // Temporarily rename old namespace (it will be removed at the end) - int count = 1; - while (true) { - String n = name + "_" + count++; - try { - namespaceSymbol.setName(n, SourceType.ANALYSIS); - break; - } - catch (DuplicateNameException e) { - // continue - } - catch (InvalidInputException e) { - throw new AssertException(e); - } - } - - // create new class namespace - GhidraClass classNamespace = null; - try { - classNamespace = - symbolTable.createClass(namespace.getParentNamespace(), name, originalSource); - } - catch (DuplicateNameException e) { - throw new AssertException(e); - } - catch (InvalidInputException e) { - // The only cause of this exception can be assumed but we need to - // avoid showing the user a temporary name - throw new InvalidInputException( - "Namespace contained within Function may not be converted to a class: " + name); - } - - // move everything from old namespace into new class namespace - try { - for (Symbol s : symbolTable.getSymbols(namespace)) { - s.setNamespace(classNamespace); - } - namespaceSymbol.delete(); - } - catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) { - throw new AssertException(e); - } - return classNamespace; + return symbolTable.convertNamespaceToClass(namespace); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index 5ae5403822..d13259b763 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -1695,34 +1695,41 @@ abstract public class DataTypeManagerDB implements DataTypeManager { @Override public void disassociate(DataType dataType) { - UniversalID oldDtID = dataType.getUniversalID(); - SourceArchive sourceArchive = dataType.getSourceArchive(); - sourceArchive = resolveSourceArchive(sourceArchive); - UniversalID id = sourceArchive == null ? DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID - : sourceArchive.getSourceArchiveID(); - if (id.equals(getUniversalID())) { - id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID; - } - if (id == DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID) { - // Already local data type so no source archive associated. - return; - } - // Set the source archive to null indicating no associated archive. - dataType.setSourceArchive(null); + lock.acquire(); + try { + UniversalID oldDtID = dataType.getUniversalID(); + SourceArchive sourceArchive = dataType.getSourceArchive(); + sourceArchive = resolveSourceArchive(sourceArchive); + UniversalID id = sourceArchive == null ? DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID + : sourceArchive.getSourceArchiveID(); + if (id.equals(getUniversalID())) { + id = DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID; + } + if (id == DataTypeManager.LOCAL_ARCHIVE_UNIVERSAL_ID) { + // Already local data type so no source archive associated. + return; + } - // Set the datatype's universal ID to a newly generated universal ID, - // since we no longer want the source archive data type's universal ID. - if (dataType instanceof DataTypeDB) { - DataTypeDB dt = (DataTypeDB) dataType; - dt.setUniversalID(UniversalIdGenerator.nextID()); + // Set the source archive to null indicating no associated archive. + dataType.setSourceArchive(null); + + // Set the datatype's universal ID to a newly generated universal ID, + // since we no longer want the source archive data type's universal ID. + if (dataType instanceof DataTypeDB) { + DataTypeDB dt = (DataTypeDB) dataType; + dt.setUniversalID(UniversalIdGenerator.nextID()); + } + + if (oldDtID != null) { + idsToDataTypeMap.removeDataType(sourceArchive, oldDtID); + } + + dataTypeChanged(dataType); } - - if (oldDtID != null) { - idsToDataTypeMap.removeDataType(sourceArchive, oldDtID); + finally { + lock.release(); } - - dataTypeChanged(dataType); } private Collection filterOutNonSourceSettableDataTypes( @@ -2694,9 +2701,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } try { creatingDataType++; - DBRecord record = functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(), - DEFAULT_DATATYPE_ID, funDef.hasVarArgs(), funDef.getGenericCallingConvention(), - sourceArchiveIdValue, universalIdValue, funDef.getLastChangeTime()); + DBRecord record = + functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(), + DEFAULT_DATATYPE_ID, funDef.hasVarArgs(), funDef.getGenericCallingConvention(), + sourceArchiveIdValue, universalIdValue, funDef.getLastChangeTime()); FunctionDefinitionDB funDefDb = new FunctionDefinitionDB(this, dtCache, functionDefAdapter, paramAdapter, record); @@ -3696,7 +3704,13 @@ abstract public class DataTypeManagerDB implements DataTypeManager { @Override public DataType getDataType(SourceArchive sourceArchive, UniversalID datatypeID) { UniversalID sourceID = sourceArchive == null ? null : sourceArchive.getSourceArchiveID(); - return idsToDataTypeMap.getDataType(sourceID, datatypeID); + lock.acquire(); + try { + return idsToDataTypeMap.getDataType(sourceID, datatypeID); + } + finally { + lock.release(); + } } @Override @@ -3829,7 +3843,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { monitor.setProgress(0); monitor.setMaximum(orderedComposites.size()); monitor.setMessage("Updating Datatype Sizes..."); - + int count = 0; for (CompositeDB c : orderedComposites) { monitor.checkCanceled(); @@ -4162,7 +4176,11 @@ abstract public class DataTypeManagerDB implements DataTypeManager { Map idMap = map.computeIfAbsent(sourceID, k -> new ConcurrentHashMap<>()); - final UniversalID sourceArchiveID = sourceID; + UniversalID sourceArchiveID = sourceID; + + // note: this call is atomic and has a lock on the 'idMap'. It may call to a method + // that requires a db lock. As such, the call to computeIfAbsent() must be + // made while holding the db lock. return idMap.computeIfAbsent(dataTypeID, k -> findDataTypeForIDs(sourceArchiveID, dataTypeID)); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/GhidraClassDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/GhidraClassDB.java index 7a93b36631..f5956b744d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/GhidraClassDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/GhidraClassDB.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -19,8 +18,7 @@ package ghidra.program.database.symbol; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.CircularDependencyException; import ghidra.program.model.listing.GhidraClass; -import ghidra.program.model.symbol.Namespace; -import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.*; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.InvalidInputException; @@ -63,6 +61,19 @@ class GhidraClassDB implements GhidraClass { return symbol.getName(); } + public void setName(String name, SourceType source, boolean checkForDuplicates) + throws DuplicateNameException, InvalidInputException { + + try { + symbol.doSetNameAndNamespace(name, symbol.getParentNamespace(), source, + checkForDuplicates); + } + catch (CircularDependencyException e) { + // can't happen since we are not changing the namespace + } + + } + /** * @see ghidra.program.model.symbol.Namespace#getID() */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDB.java index 3d4cedef45..cef6893c50 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDB.java @@ -104,8 +104,9 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol { return false; } record = rec; - address = symbolMgr.getAddressMap().decodeAddress( - rec.getLongValue(SymbolDatabaseAdapter.SYMBOL_ADDR_COL)); + address = symbolMgr.getAddressMap() + .decodeAddress( + rec.getLongValue(SymbolDatabaseAdapter.SYMBOL_ADDR_COL)); return true; } return false; @@ -522,8 +523,8 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol { return source; } - @Override - public void setNameAndNamespace(String newName, Namespace newNamespace, SourceType source) + public void doSetNameAndNamespace(String newName, Namespace newNamespace, SourceType source, + boolean checkForDuplicates) throws DuplicateNameException, InvalidInputException, CircularDependencyException { lock.acquire(); @@ -563,7 +564,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol { if (!namespaceChange && !nameChange) { return; } - symbolMgr.checkDuplicateSymbolName(address, newName, newNamespace, getSymbolType()); + + if (checkForDuplicates) { + symbolMgr.checkDuplicateSymbolName(address, newName, newNamespace, + getSymbolType()); + } } if (record != null) { @@ -617,6 +622,13 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol { } } + @Override + public void setNameAndNamespace(String newName, Namespace newNamespace, SourceType source) + throws DuplicateNameException, InvalidInputException, CircularDependencyException { + + doSetNameAndNamespace(newName, newNamespace, source, true); + } + protected List getSymbolsDynamicallyRenamedByMyRename() { return null; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java index 6dc5934ba9..f1fac019bf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java @@ -40,7 +40,6 @@ import ghidra.program.util.LanguageTranslator; import ghidra.util.*; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; -import ghidra.util.task.TaskMonitorAdapter; public class SymbolManager implements SymbolTable, ManagerDB { @@ -128,7 +127,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { * Find previously defined variable storage address * @param storage variable storage * @return previously defined variable storage address or null if not found - * @throws IOException + * @throws IOException if there is database exception */ public Address findVariableStorageAddress(VariableStorage storage) throws IOException { return variableStorageMgr.getVariableStorageAddress(storage, false); @@ -183,7 +182,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { * where all the moved external addresses will be placed. * The triggering of this upgrade relies on the addition of the VariableManager which * trigger an upgrade. - * @param monitor + * @param monitor the task monitor */ private boolean upgradeOldNamespaceAddresses(TaskMonitor monitor) throws IOException, CancelledException { @@ -239,9 +238,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Upgrade old stack and register variable symbol address to variable addresses. * Also force associated references to be updated to new variable addresses. - * @param monitor - * @throws IOException - * @throws CancelledException + * @param monitor the task monitor + * @throws IOException if there is database exception + * @throws CancelledException if the operation is cancelled */ private void processOldVariableAddresses(TaskMonitor monitor) throws IOException, CancelledException { @@ -296,8 +295,8 @@ public class SymbolManager implements SymbolTable, ManagerDB { * No more sharing the same variable address for multiple variable symbols. * Must split these up. Only reference to variable addresses should be the * symbol address - reference refer to physical/stack addresses, and symbolIDs. - * @param monitor - * @throws CancelledException + * @param monitor the task monitor + * @throws CancelledException if the operation is cancelled */ public void migrateFromOldVariableStorageManager(TaskMonitor monitor) throws CancelledException { @@ -396,9 +395,8 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Add old local symbols - * @param table - * @throws IOException - * @throws CancelledException + * @throws IOException if there is database exception + * @throws CancelledException if the operation is cancelled */ private void processOldLocalSymbols(TaskMonitor monitor) throws IOException, CancelledException { @@ -450,6 +448,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { * @param oldAddr old address value from symbol table * @param name symbol name * @param isPrimary true if symbol is primary at oldAddr + * @throws IOException if there is database exception */ public static void saveLocalSymbol(DBHandle tmpHandle, long symbolID, long oldAddr, String name, boolean isPrimary) throws IOException { @@ -480,18 +479,15 @@ public class SymbolManager implements SymbolTable, ManagerDB { return; } - List symbolList = getSymbols(name, namespace); - for (Symbol symbol : symbolList) { - if (!symbol.getSymbolType().allowsDuplicates()) { - throw new DuplicateNameException( - "A " + symbol.getSymbolType() + " symbol with name " + name + - " already exists in namespace " + symbol.getParentNamespace().getName()); - } + Symbol symbol = getFirstSymbol(name, namespace, s -> !s.getSymbolType().allowsDuplicates()); + if (symbol != null) { + throw new DuplicateNameException( + "A " + symbol.getSymbolType() + " symbol with name " + name + + " already exists in namespace " + symbol.getParentNamespace().getName()); } - } - /** + /* * Convert the specified dynamic symbol to a named symbol. Both symbol removed and symbol added * notifications are performed, although the symbol instance is changed and continues to be * valid. @@ -509,8 +505,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { Address address = symbol.getAddress(); symbolRemoved(symbol, address, symbol.getName(), oldKey, Namespace.GLOBAL_NAMESPACE_ID, null); - DBRecord record = adapter.createSymbol(newName, address, newParentID, SymbolType.LABEL, 0, - 1, null, source); + DBRecord record = + adapter.createSymbol(newName, address, newParentID, SymbolType.LABEL, 0, + 1, null, source); symbol.setRecord(record);// symbol object was morphed symbolAdded(symbol); } @@ -987,10 +984,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { return searchSymbolsByNamespaceFirst(name, namespace); } - // Try to find the symbols by searching through all the symbols with the given name and including - // only those in the specified namespace. If there are too many symbols with the same name and - // we are not in the global space, abandon this approach and instead search through all - // the symbols in the namespace and only include those with the specified name. + // Try to find the symbols by searching through all the symbols with the given name + // and including only those in the specified namespace. If there are too many symbols + // with the same name and we are not in the global space, abandon this approach and + // instead search through all the symbols in the namespace and only include those with + // the specified name. int count = 0; List list = new ArrayList<>(); SymbolIterator symbols = getSymbols(name); @@ -1009,6 +1007,42 @@ public class SymbolManager implements SymbolTable, ManagerDB { } } + // note: this could be public; adding it may be confusing due to the potential for having + // multiple symbols and not knowing when to call which method. + private Symbol getFirstSymbol(String name, Namespace namespace, Predicate test) { + if (namespace == null) { + namespace = namespaceMgr.getGlobalNamespace(); + } + + if (namespace.isExternal() && + SymbolUtilities.isReservedExternalDefaultName(name, program.getAddressFactory())) { + return findFirstSymbol(name, namespace, test); + } + + else if (namespace instanceof Function && hasDefaultVariablePrefix(name)) { + return findFirstSymbol(name, namespace, test); + } + + // Try to find the symbols by searching through all the symbols with the given name + // and including only those in the specified namespace. If there are too many symbols + // with the same name and we are not in the global space, abandon this approach and + // instead search through all the symbols in the namespace and only include those with + // the specified name. + int count = 0; + SymbolIterator symbols = getSymbols(name); + for (Symbol s : symbols) { + if (++count == MAX_DUPLICATE_COUNT && !namespace.isGlobal()) { + return findFirstSymbol(name, namespace, test); + } + if (s.getParentNamespace().equals(namespace) && + test.test(s)) { + return s; + } + } + + return null; + } + /** * Returns the list of symbols with the given name and namespace. * @@ -1143,7 +1177,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Returns the next available external symbol address - * @return + * @return the address */ public Address getNextExternalSymbolAddress() { int extID = 1; @@ -1414,6 +1448,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { if (!symbol.isDynamic()) { createLabelHistoryRecord(addr, oldName, newName, LabelHistory.RENAME); } + program.symbolChanged(symbol, ChangeManager.DOCR_SYMBOL_RENAMED, addr, symbol, oldName, newName); } @@ -1493,7 +1528,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { // fire event program.symbolChanged(symbol, ChangeManager.DOCR_SYMBOL_REMOVED, addr, symbol, name, - new Long(symbolID)); + symbolID); } void externalEntryPointRemoved(Address addr) { @@ -1543,11 +1578,6 @@ public class SymbolManager implements SymbolTable, ManagerDB { Symbol sym; - /** - * Construct iterator which returns a single symbol - * - * @param addr - */ SingleSymbolIterator(Symbol sym) { this.sym = sym; } @@ -2175,8 +2205,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { void moveLabelHistory(Address oldAddress, Address address) { try { - historyAdapter.moveAddressRange(oldAddress, address, 1, addrMap, - TaskMonitorAdapter.DUMMY_MONITOR); + historyAdapter.moveAddressRange(oldAddress, address, 1, addrMap, TaskMonitor.DUMMY); } catch (CancelledException e) { // can't happen, used dummy monitor @@ -2266,6 +2295,109 @@ public class SymbolManager implements SymbolTable, ManagerDB { return new NamespaceDB(s, namespaceMgr); } + @Override + public GhidraClass convertNamespaceToClass(Namespace namespace) { + + if (namespace instanceof GhidraClass) { + return (GhidraClass) namespace; + } + + lock.acquire(); + try { + + checkIsValidNamespaceForMyProgram(namespace); + + Symbol namespaceSymbol = namespace.getSymbol(); + String name = namespaceSymbol.getName(); + SourceType originalSource = namespaceSymbol.getSource(); + + // no duplicate check, since this class name will be set to that of the existing namespace + String tempName = name + System.nanoTime(); + SymbolDB classSymbol = + doCreateSpecialSymbol(Address.NO_ADDRESS, tempName, namespace.getParentNamespace(), + SymbolType.CLASS, -1, -1, null, originalSource, false /*check for duplicate */); + GhidraClassDB classNamespace = new GhidraClassDB(classSymbol, namespaceMgr); + + // move everything from old namespace into new class namespace + for (Symbol s : getSymbols(namespace)) { + + // no duplicate check, since these symbols all lived under the existing namespace + ((SymbolDB) s).doSetNameAndNamespace(s.getName(), classNamespace, s.getSource(), + false /*check for duplicate */); + } + + namespaceSymbol.delete(); + + // fix name now that the old namespace is deleted + classNamespace.setName(name, SourceType.ANALYSIS, false /*check for duplicate */); + + return classNamespace; + } + catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) { + throw new AssertException("Unexpected exception creating class from namespace", e); + } + finally { + lock.release(); + } + } + + private void checkIsValidNamespaceForMyProgram(Namespace namespace) { + + if (namespace == null) { + return; + } + + if (namespace == program.getGlobalNamespace()) { + return; + } + + if (!(namespace instanceof NamespaceDB)) { + throw new IllegalArgumentException( + "Namespace is not a valid parent for symbols: " + + namespace.getClass()); + } + + SymbolDB dbSymbol = (SymbolDB) namespace.getSymbol(); + if (program != dbSymbol.getProgram()) { + throw new IllegalArgumentException( + "Namespace symbol is from a different program"); + } + + // may throw a ConcurrentModificationException + dbSymbol.checkDeleted(); + } + + @Override + public Namespace getOrCreateNameSpace(Namespace parent, String name, SourceType source) + throws DuplicateNameException, InvalidInputException { + + lock.acquire(); + try { + + checkIsValidNamespaceForMyProgram(parent); + + Symbol namespaceSymbol = getFirstSymbol(name, parent, s -> { + return s.getSymbolType() == SymbolType.NAMESPACE || + s.getSymbolType() == SymbolType.CLASS; + }); + + if (namespaceSymbol != null) { + return (Namespace) namespaceSymbol.getObject(); + } + + // Note: We know there are no namespaces with the name; do we still have to check for + // duplicates? Assuming yes, as another symbol type may exist with this name. + SymbolDB s = + doCreateSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.NAMESPACE, -1, + -1, null, source, true /*check for duplicates*/); + return new NamespaceDB(s, namespaceMgr); + + } + finally { + lock.release(); + } + } + @Override public Symbol createSymbolPlaceholder(Address address, long id) { return SymbolDB.createSymbolPlaceholder(this, address, id); @@ -2293,12 +2425,24 @@ public class SymbolManager implements SymbolTable, ManagerDB { SymbolType symbolType, long data1, int data2, String data3, SourceType source) throws DuplicateNameException, InvalidInputException { + return doCreateSpecialSymbol(addr, name, parent, symbolType, data1, data2, data3, source, + true); + } + + private SymbolDB doCreateSpecialSymbol(Address addr, String name, Namespace parent, + SymbolType symbolType, long data1, int data2, String data3, SourceType source, + boolean checkForDuplicates) + throws DuplicateNameException, InvalidInputException { + lock.acquire(); try { parent = validateNamespace(parent, addr, symbolType); source = validateSource(source, name, addr, symbolType); name = validateName(name, source); - checkDuplicateSymbolName(addr, name, parent, symbolType); + + if (checkForDuplicates) { + checkDuplicateSymbolName(addr, name, parent, symbolType); + } return doCreateSymbol(name, addr, parent, symbolType, data1, data2, data3, source); } @@ -2378,7 +2522,8 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Internal method for creating funcions symbols. + * Internal method for creating function symbols + * * @param addr the address for the new symbol * @param name the name of the new symbol * @param namespace the namespace for the new symbol @@ -2489,8 +2634,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { long data1, int data2, String data3, SourceType source) { try { - DBRecord record = adapter.createSymbol(name, addr, namespace.getID(), type, data1, data2, - data3, source); + DBRecord record = + adapter.createSymbol(name, addr, namespace.getID(), type, data1, data2, + data3, source); SymbolDB newSymbol = makeSymbol(addr, record, type); symbolAdded(newSymbol); @@ -2633,19 +2779,29 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public Symbol getVariableSymbol(String name, Function function) { - return findFirstSymbol(name, function, s -> { + return getFirstSymbol(name, function, s -> { SymbolType t = s.getSymbolType(); return t == SymbolType.PARAMETER || t == SymbolType.LOCAL_VAR; }); } private Symbol getSpecificSymbol(String name, Namespace namespace, SymbolType type) { - return findFirstSymbol(name, namespace, s -> s.getSymbolType() == type); + return getFirstSymbol(name, namespace, s -> s.getSymbolType() == type); } private Symbol findFirstSymbol(String name, Namespace namespace, Predicate test) { - List symbols = getSymbols(name, namespace); - return symbols.stream().filter(test).findFirst().orElse(null); + if (namespace == null) { + namespace = namespaceMgr.getGlobalNamespace(); + } + + SymbolIterator it = getSymbols(namespace); + while (it.hasNext()) { + Symbol s = it.next(); + if (s.getName().equals(name) && test.test(s)) { + return s; + } + } + return null; } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java index ad1253bdaf..08dda6d69e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java @@ -15,8 +15,7 @@ */ package ghidra.program.model.symbol; -import java.util.Iterator; -import java.util.List; +import java.util.*; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; @@ -504,7 +503,7 @@ public interface SymbolTable { * @param name name of the namespace * @param source the source of this class namespace's symbol * @return new class namespace - * @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name + * @throws DuplicateNameException thrown if another non function or label symbol exists with the given name * @throws InvalidInputException throw if the name has invalid characters or is null * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. */ @@ -523,7 +522,7 @@ public interface SymbolTable { * @param source the source of this external library's symbol * @return the new Library namespace. * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. - * @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name + * @throws DuplicateNameException thrown if another non function or label symbol exists with the given name */ public Library createExternalLibrary(String name, SourceType source) throws DuplicateNameException, InvalidInputException; @@ -534,7 +533,7 @@ public interface SymbolTable { * @param name the name of the new namespace * @param source the source of this namespace's symbol * @return the new Namespace object. - * @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name + * @throws DuplicateNameException thrown if another non function or label symbol exists with the given name * @throws InvalidInputException if the name is invalid. * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. */ @@ -552,4 +551,32 @@ public interface SymbolTable { */ public Symbol createSymbolPlaceholder(Address address, long id); + /** + * Converts the given namespace to a class namespace + * + * @param namespace the namespace to convert + * @return the new class + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table + * @throws ConcurrentModificationException if the given parent namespace has been deleted + */ + public GhidraClass convertNamespaceToClass(Namespace namespace); + + /** + * Gets an existing namespace with the given name in the given parent. If no namespace exists, + * then one will be created. + * + * @param parent the parent namespace + * @param name the namespace name + * @param source the source type for the namespace if one is created + * @return the namespace + * @throws DuplicateNameException thrown if another non function or label symbol exists with + * the given name + * @throws InvalidInputException if the name is invalid + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table + * @throws ConcurrentModificationException if the given parent namespace has been deleted + */ + public Namespace getOrCreateNameSpace(Namespace parent, String name, SourceType source) + throws DuplicateNameException, InvalidInputException; } diff --git a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc index cfb4adc8af..724c889b7f 100644 --- a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc +++ b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc @@ -518,15 +518,15 @@ N_0t_dbr1: @^N_0^"+,"^DBR is N_0 & DBR { export N_0; } N_0t_bank1: @^N_0^"+" is N_0 { export N_0; } -FR0_t: fr0 is OP_0 & fr0 { x:4 = 0; export x; } # dummy export, just looking for the display +FR0_t: fr0 is OP_0 & fr0 { export fr0; } XMTRX_t: "xmtrx" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display -mach_t: MACH is OP_0 & MACH { x:4 = 0; export x; } # dummy export, just looking for the display +mach_t: MACH is OP_0 & MACH { export MACH; } -macl_t: MACL is OP_0 & MACL { x:4 = 0; export x; } # dummy export, just looking for the display +macl_t: MACL is OP_0 & MACL { export MACL; } -fpul_t: FPUL is OP_0 & FPUL { x:4 = 0; export x; } # dummy export, just looking for the display +fpul_t: FPUL is OP_0 & FPUL { export FPUL; } fpscr_t: "FPSCR" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display diff --git a/Ghidra/RuntimeScripts/Linux/server/svrAdmin b/Ghidra/RuntimeScripts/Linux/server/svrAdmin index 702ca83c49..deb47eec9d 100755 --- a/Ghidra/RuntimeScripts/Linux/server/svrAdmin +++ b/Ghidra/RuntimeScripts/Linux/server/svrAdmin @@ -45,8 +45,8 @@ fi OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')" if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then - VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") -DUserAdmin.config=\"${CONFIG}\"" - "${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "$@" + VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}")" + "${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "${CONFIG}" "$@" else echo "Running svrAdmin with $SUDO as ${OWNER} ..." $SUDO -u $OWNER "$0" "$@" diff --git a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar index 66b87cb0c2..c378218c75 100755 --- a/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar +++ b/Ghidra/RuntimeScripts/Linux/support/buildGhidraJar @@ -25,7 +25,7 @@ if [ ! -d "${GHIDRA_ROOT_DIR}" ]; then fi # Set required VMARGS for jar builder application -APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}") -DGhidra.Install.Root.Dir=\"${GHIDRA_ROOT_DIR}\" " +APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}")" # Launch jar builder "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" Ghidra "${MAXMEM}" "${APP_VMARGS}" ghidra.util.GhidraJarBuilder -main ghidra.JarRun "$@" diff --git a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat index 98a2bc2310..09a4979711 100644 --- a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat +++ b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat @@ -11,7 +11,7 @@ rem runtime which has been configured into the system PATH ahead of other Java rem it may be necessary to explicitly specify the path to the installation by setting JAVA_HOME rem below: -rem set JAVA_HOME= +rem set "JAVA_HOME=" setlocal enabledelayedexpansion @@ -50,7 +50,7 @@ if "%IS_ADMIN%"=="NO" ( rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" set APP_NAME=ghidraSvr set APP_LONG_NAME=Ghidra Server @@ -64,26 +64,26 @@ if exist "%_REALPATH%..\Ghidra\" goto normal rem NOTE: If adjusting JAVA command assignment - do not attempt to add parameters (e.g., -d64, -version:1.7, etc.) rem Development Environment -set GHIDRA_HOME=%_REALPATH%..\..\..\.. -set WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf -set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data -set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag -set LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main +set "GHIDRA_HOME=%_REALPATH%..\..\..\.." +set "WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf" +set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data" +set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag" +set "LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main" goto lab1 :normal -set GHIDRA_HOME=%_REALPATH%.. -set WRAPPER_CONF=%_REALPATH%server.conf -set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data -set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag -set LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar +set "GHIDRA_HOME=%_REALPATH%.." +set "WRAPPER_CONF=%_REALPATH%server.conf" +set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data" +set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag" +set "LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar" :lab1 rem set WRAPPER_HOME to unpacked yajsw location (crazy FOR syntax to set variable from command output) for /F "usebackq delims=" %%p in (`dir "%DATA_DIR%" /ad /b ^| findstr "^%WRAPPER_NAME_PREFIX%"`) do set WRAPPER_DIRNAME=%%p -set WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME% +set "WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME%" if not exist "%WRAPPER_HOME%\" ( echo. @@ -104,8 +104,7 @@ set ERROR=ERROR: JAVA_HOME is not set and no 'java' command could be found in yo goto reportError :findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA=%JAVA_HOME%\bin\java.exe +set "JAVA=%JAVA_HOME%\bin\java.exe" if exist "%JAVA%" goto lab2 set ERROR=ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -122,15 +121,7 @@ if "%JAVA_HOME%" == "" ( ) rem reestablish JAVA path based upon final JAVA_HOME -set JAVA=%JAVA_HOME%\bin\java.exe - -set OS_NAME=win32 -"%JAVA%" -version 2>&1 | findstr /I " 64-Bit " >NUL -if errorlevel 0 ( - set OS_NAME=win64 -) - -set OS_DIR=%GHIDRA_HOME%\%MODULE_DIR%\os\%OS_NAME% +set "JAVA=%JAVA_HOME%\bin\java.exe" :: set DEBUG=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=*:18888 diff --git a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat index ea7993ca45..1f8de1281e 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrAdmin.bat @@ -31,18 +31,18 @@ set MAXMEM=128M :: '% ~' dereferences the value in param 0 :: 'd' - drive :: 'p' - path (without filename) -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" :: Production Environment -set CONFIG=%SCRIPT_DIR%.\server.conf +set "CONFIG=%SCRIPT_DIR%.\server.conf" if exist "%CONFIG%" goto continue :: Development Environment -set CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf +set "CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf" :continue -set VMARGS=-DUserAdmin.invocation="%0" -DUserAdmin.config="%CONFIG%" +set VMARGS=-DUserAdmin.invocation=%~n0 -call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin %* +call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin "%CONFIG%" %* diff --git a/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat b/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat index 1314f8a174..2df9605318 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrInstall.bat @@ -3,7 +3,7 @@ setlocal rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" call "%_REALPATH%\ghidraSvr" install diff --git a/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat b/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat index 75e1905064..ac5131418b 100644 --- a/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat +++ b/Ghidra/RuntimeScripts/Windows/server/svrUninstall.bat @@ -3,7 +3,7 @@ setlocal rem Find the script directory rem %~dsp0 is location of current script under NT -set _REALPATH=%~dp0 +set "_REALPATH=%~dp0" call "%_REALPATH%\ghidraSvr" uninstall diff --git a/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat b/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat index aa4545b18b..e972b07cae 100644 --- a/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat +++ b/Ghidra/RuntimeScripts/Windows/support/analyzeHeadless.bat @@ -24,7 +24,7 @@ set VMARG_LIST=-XX:ParallelGCThreads=2 set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2 :: store current path -set filepath=%~dp0 +set "filepath=%~dp0" :: Loop through parameters (if there aren't any, just continue) and store :: in params variable. diff --git a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat index 1e618fa944..07f1c4dddc 100644 --- a/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat +++ b/Ghidra/RuntimeScripts/Windows/support/buildGhidraJar.bat @@ -8,9 +8,9 @@ setlocal set LAUNCH_MODE=fg :: Sets SCRIPT_DIR to the directory that contains this file (ends with '\') -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" -set GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra +set "GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra" if exist "%GHIDRA_ROOT_DIR%" goto continue echo This script does not support development mode use @@ -18,6 +18,6 @@ exit /B 1 :continue -set APP_VMARGS=-DGhidraJarBuilder.Name=%0 -DGhidra.Install.Root.Dir=%GHIDRA_ROOT_DIR% +set APP_VMARGS=-DGhidraJarBuilder.Name=%~n0 call "%~dp0launch.bat" %LAUNCH_MODE% Ghidra "" "%APP_VMARGS%" ghidra.util.GhidraJarBuilder -main ghidra.JarRun %* diff --git a/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat b/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat index 44826dd39e..10a7c7d8f0 100644 --- a/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat +++ b/Ghidra/RuntimeScripts/Windows/support/createPdbXmlFiles.bat @@ -11,16 +11,16 @@ setlocal REM Get parent of current folder -set SCRIPT_DIR=%~dp0 +set "SCRIPT_DIR=%~dp0" -set GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra +set "GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra" set OS_DIR=os REM Production Environment if exist "%GHIDRA_DIR%" goto continue REM Development Environment -set GHIDRA_DIR=%SCRIPT_DIR%..\..\.. +set "GHIDRA_DIR=%SCRIPT_DIR%..\..\.." set OS_DIR=build\os :continue @@ -35,7 +35,7 @@ if exist "%PROGRAMFILES(X86)%" ( set OS_TYPE=win32 ) -set PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe +set "PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe" if not exist "%PDB_EXE%" ( echo "%PDB_EXE% not found" diff --git a/Ghidra/RuntimeScripts/Windows/support/launch.bat b/Ghidra/RuntimeScripts/Windows/support/launch.bat index 9bee1566cf..5621f4e895 100644 --- a/Ghidra/RuntimeScripts/Windows/support/launch.bat +++ b/Ghidra/RuntimeScripts/Windows/support/launch.bat @@ -36,7 +36,7 @@ for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" set DOUBLE_CLI :: '% ~' dereferences the value in param 0 :: 'd' - drive :: 'p' - path (without filename) -set SUPPORT_DIR=%~dp0 +set "SUPPORT_DIR=%~dp0" :: :: Parse arguments @@ -63,20 +63,20 @@ goto showUsage :: :: Production Environment :: -set INSTALL_DIR=%SUPPORT_DIR%..\ -set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar -set LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar -set DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml +set "INSTALL_DIR=%SUPPORT_DIR%..\" +set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar" +set "LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar" +set "DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml" if exist "%INSTALL_DIR%Ghidra" goto continue2 :: :: Development Environment :: -set INSTALL_DIR=%INSTALL_DIR%..\..\..\ -set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main -set LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main -set DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml +set "INSTALL_DIR=%INSTALL_DIR%..\..\..\" +set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main" +set "LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main" +set "DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml" :continue2 @@ -108,7 +108,7 @@ if "%JAVA_HOME%" == "" ( goto exit1 ) ) -set JAVA_CMD=%JAVA_HOME%\bin\java +set "JAVA_CMD=%JAVA_HOME%\bin\java" :: Get the configurable VM arguments from the launch properties for /f "delims=*" %%i in ('java -cp "%LS_CPATH%" LaunchSupport "%INSTALL_DIR%\" -vmargs') do set VMARG_LIST=%VMARG_LIST% %%i diff --git a/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat b/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat index bc934c12a1..650e9f172b 100644 --- a/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat +++ b/Ghidra/RuntimeScripts/Windows/support/pythonRun.bat @@ -26,6 +26,6 @@ set VMARG_LIST=-XX:ParallelGCThreads=2 set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2 :: store current path -set filepath=%~dp0 +set "filepath=%~dp0" call "%filepath%launch.bat" %LAUNCH_MODE% Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %params% From c5044ae99c6c2e8ec44ab2a9f738976f919e4c5a Mon Sep 17 00:00:00 2001 From: astrelsky Date: Mon, 3 Feb 2020 11:13:02 -0500 Subject: [PATCH 100/140] Added ElfExporter and PeExporter --- .../exporter/AbstractExecutableExporter.java | 107 ++++++++++++++++++ .../ghidra/app/util/exporter/ElfExporter.java | 27 +++++ .../ghidra/app/util/exporter/PeExporter.java | 27 +++++ 3 files changed, 161 insertions(+) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ElfExporter.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/PeExporter.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java new file mode 100644 index 0000000000..490bfda798 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java @@ -0,0 +1,107 @@ +/* ### + * 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.exporter; + +import java.io.*; +import java.util.List; +import java.util.Optional; + +import ghidra.app.script.GhidraScript; +import ghidra.app.util.DomainObjectService; +import ghidra.app.util.Option; +import ghidra.framework.model.DomainObject; +import ghidra.program.database.mem.AddressSourceInfo; +import ghidra.program.database.mem.FileBytes; +import ghidra.program.model.address.*; +import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.*; +import ghidra.program.model.reloc.Relocation; +import ghidra.util.HelpLocation; +import ghidra.util.task.TaskMonitor; +import utilities.util.FileUtilities; + +abstract class AbstractExecutableExporter extends Exporter { + + protected AbstractExecutableExporter(String name, String extension, HelpLocation help) { + super(name, extension, help); + } + + @Override + public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, + TaskMonitor monitor) throws IOException, ExporterException { + + if (!(domainObj instanceof Program)) { + log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); + return false; + } + Program program = (Program) domainObj; + Memory memory = program.getMemory(); + + try (OutputStream out = new FileOutputStream(file, false)) { + FileBytes[] fileBytes = memory.getAllFileBytes() + .stream() + .filter((fb) -> fb.getFilename().equals(program.getName())) + .toArray(FileBytes[]::new); + for (FileBytes bytes : fileBytes) { + FileBytesInputStream byteStream = new FileBytesInputStream(bytes); + FileUtilities.copyStreamToStream(byteStream, out, monitor); + } + } + try (RandomAccessFile fout = new RandomAccessFile(file, "rw")) { + Iterable relocs = + () -> program.getRelocationTable().getRelocations(); + for (Relocation reloc : relocs) { + AddressSourceInfo info = memory.getAddressSourceInfo(reloc.getAddress()); + // some relocations report negative offsets + if (info.getFileOffset() >= 0) { + // seek incase we are larger than an int + fout.seek(info.getFileOffset()); + fout.write(reloc.getBytes()); + } + } + } + + return true; + } + + @Override + public List

  • Emulator. Replaced Java floating point emulation to fix multiple rounding issues. (GP-357, Issue #2414)
  • Graphing. Fixed issue with graph filters not updating satellite view when changing edge filters. (GP-557)
  • Graphing. Fixed Function Graph keybindings that did not work when docked in the main Code Browser window. (GP-586, Issue #2641)
  • -
  • GUI. Fixed NPE due to using Go To action when there was no open program in the Listing. (GP-66)
  • +
  • GUI. Fixed NullPointerException due to using Go To action when there was no open program in the Listing. (GP-66)
  • GUI. Fixed bug in Reference Code Viewer options that caused an exception. (GP-620, Issue #2672)
  • Importer. Fixed exception caused when importing previously exported XML data where the bookmark override option was turned off. (GP-667)
  • Importer:ELF. Fixed a NullPointerException caused by importing an ELF with an uninitialized .got section. (GP-360, Issue #2416)
  • @@ -43,13 +43,14 @@
  • Importer:Mach-O. Fixed an issue with DYLD Load Command data structures being created in the wrong locations. (GP-689, Issue #2624)
  • Importer:Mach-O. Fixed an exception that occurred when importing Mach-O files that define zero LC_BUILD_VERSION tool entries. (GP-702, Issue #2192)
  • PDB. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)
  • -
  • PDB. Fix PDB Universal analyzer to set the run-once flag when finished. (GP-724)
  • +
  • PDB. Fixed PDB Universal analyzer to set the run-once flag when finished. (GP-724)
  • Processors. Added missing RFE instruction in MIPS up to version R3000. (GP-33, Issue #1766)
  • Processors. ARM instruction VMUL now decodes correctly. (GP-627, Issue #2677)
  • Processors. Added missing CFINV instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)
  • Scripting. Fixed analyzeHeadless -scriptPath option that didn't work for Python and other non-Java scripts located in non-default directories. (GP-528, Issue #2561)
  • Scripting. Fixed concurrency issue with management of scripting bundle paths. (GP-576)
  • Scripting. Corrected handling for Ghidra Script files which are symlinks that were broken in Ghidra 9.2. (GP-650, Issue #2698)
  • +
  • Scripting. Fixed the analyzeHeadless -scriptPath option to correctly parse $GHIDRA_HOME and $USER_HOME. (GP-781)
  • @@ -606,14 +607,14 @@
  • Analysis. Made a fix to enable Apply button when changing tool options. (GT-2801, Issue #40)
  • Data Types. Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed. (GT-2736)
  • Decompiler. Fixed dynamic variables and equates in 16-bit x86 programs. (GT-2745, Issue #336)
  • -
  • Decompiler:Java. Fixed DEX decompilation regression issue. (Issue #350, GT-2743)
  • +
  • Decompiler:Java. Fixed DEX decompilation regression issue. (GT-2743, Issue #350)
  • Eclipse Integration. Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (GT-2721, Issues #283, #383)
  • GUI. Improved documentation on how to deal with HiDPI monitor issues in Linux. In the <ghidra_installation>/support/launch.properties file, change VMARGS=-Dsun.java2d.xrender from false to true.
  • Importer. Fixed an exception that occurred when batch importing APK files. (GT-2767, Issue #426)
  • Multi-User:Ghidra Server. Restored ability to execute svrAdmin script in development mode. (GT-2740)
  • Processors. The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (GT-2759, Issue #201)
  • Processors. The M68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (GT-2807, Issue #227)
  • -
  • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (GT-2754. Issue #407)
  • +
  • Search. Fixed NullPointerException in Decompiler Data Type Reference Finder. (GT-2754, Issue #407)
  • @@ -679,7 +680,7 @@
  • Importer:Mach-O. The Mach-O loader can now find import libraries found in Universal Binary files. (GT-2663, Issue #136)
  • Importer:PE. The PeLoader now correctly parses the GuardCFFunctionTable when table entries are more than 4 bytes each. (GT-2671, Issue #220)
  • Multi-User:Ghidra Server. Removed support for native OS authentication from Ghidra Server (removed modes -a2 and -a3) due to incompatibility with newer OS releases including Windows 10 and Windows Server 2016. Re-introduction of this will be considered for a future release. (GT-2653)
  • -
  • PDB. Corrected NPE error when processing PDB files. (GT-2673, Issues #138, #188)
  • +
  • PDB. Corrected NullPointerException when processing PDB files. (GT-2673, Issues #138, #188)
  • Processors. Added missing PowerPC VLE conditional branch instructions: e_bdnz and e_bdz. (GT-2652, Issue #103)
  • Processors. Fixed instruction semantics for several instructions and added Control Flow Enforcement, NOP variants, CMP variants, UD1, and prefixed call instructions to X86 processor specification. (GT-2660, Issues #22, #53, #158, #157)
  • Processors. The M68000 MOVE instruction now correctly sets the CF and VF flags. (GT-2661, Issue #163)
  • From 3cd3d2b68921b9d789fddcd258e067033711fc9b Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 18 Mar 2021 16:23:40 -0400 Subject: [PATCH 102/140] Fixed bug that caused the exporter dialog to sometimes close immediately --- .../plugin/core/exporter/ExporterDialog.java | 67 +++++++++++++++++-- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java index bd4f612642..56626eccaf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java @@ -20,7 +20,6 @@ import java.awt.Component; import java.io.File; import java.io.IOException; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -53,8 +52,7 @@ import ghidra.util.filechooser.ExtensionFileFilter; import ghidra.util.filechooser.GhidraFileFilter; import ghidra.util.layout.PairLayout; import ghidra.util.layout.VerticalLayout; -import ghidra.util.task.TaskLauncher; -import ghidra.util.task.TaskMonitor; +import ghidra.util.task.*; /** * Dialog for exporting a program from a Ghidra project to an external file in one of the @@ -444,10 +442,65 @@ public class ExporterDialog extends DialogComponentProvider implements AddressFa private boolean doExport() { - AtomicBoolean success = new AtomicBoolean(); - TaskLauncher.launchModal("Exporting " + domainFile.getName(), - monitor -> success.set(tryExport(monitor))); - return success.get(); + ExportTask task = new ExportTask(); + TaskLauncher.launch(task); + task.showResults(); + return task.getSuccess(); + } + + private class ExportTask extends Task { + + private boolean success; + private boolean showResults; + private Exporter exporter; + private DomainObject exportedDomainObject; + + public ExportTask() { + super("Export " + domainFile.getName(), true, true, true, false); + } + + @Override + public void run(TaskMonitor monitor) throws CancelledException { + + exporter = getSelectedExporter(); + + exporter.setExporterServiceProvider(tool); + exportedDomainObject = getDomainObject(monitor); + if (exportedDomainObject == null) { + return; + } + ProgramSelection selection = getApplicableProgramSeletion(); + File outputFile = getSelectedOutputFile(); + + try { + if (outputFile.exists() && + OptionDialog.showOptionDialog(getComponent(), "Overwrite Existing File?", + "The file " + outputFile + " already exists.\nDo you want to overwrite it?", + "Overwrite", OptionDialog.QUESTION_MESSAGE) != OptionDialog.OPTION_ONE) { + return; + } + if (options != null) { + exporter.setOptions(options); + } + success = exporter.export(outputFile, exportedDomainObject, selection, monitor); + showResults = true; + } + catch (Exception e) { + Msg.error(this, "Exception exporting", e); + SystemUtilities.runSwingLater(() -> setStatusText( + "Exception exporting: " + e.getMessage() + ". If null, see log for details.")); + } + } + + void showResults() { + if (showResults) { + displaySummaryResults(exporter, exportedDomainObject); + } + } + + boolean getSuccess() { + return success; + } } private boolean tryExport(TaskMonitor monitor) { From 92d6f6b088c1095f193409ffc19fd426a3d5004f Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 18 Mar 2021 16:48:35 -0400 Subject: [PATCH 103/140] Revert "GP-0 experiment with test failure setting" This reverts commit c905c203f0300abdd8ef12ca847ec65111b6bd17. --- gradle/javaTestProject.gradle | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/gradle/javaTestProject.gradle b/gradle/javaTestProject.gradle index ceae366dff..800cc4aed5 100644 --- a/gradle/javaTestProject.gradle +++ b/gradle/javaTestProject.gradle @@ -140,12 +140,7 @@ def initTestJVM(Task task, String rootDirName) { mkdir testOutputDir } // If false, testing will halt when an error is found. - // TODO: test.java provides test task for nightly jUnits - setting this - // here can cause sub-project builds to proceed even when tests fail. - // If test report not generated that task could be changed to always - // run even on failure (e.g., options.failOnError(false) ) - // task.ignoreFailures true - task.failFast false + task.ignoreFailures true // If false, then tests are re-run every time, even if no code has changed. task.outputs.upToDateWhen {false} From 438827ddfe2ee9a03dd5c42b65bf8682053c3e21 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 19 Mar 2021 10:36:31 -0400 Subject: [PATCH 104/140] GP-781 corrected handling of scriptPaths --- .../main/java/ghidra/app/util/headless/HeadlessAnalyzer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java index f63589fdac..5bd393cacc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java @@ -671,6 +671,9 @@ public class HeadlessAnalyzer { } private List parseScriptPaths(List scriptPaths) { + if (scriptPaths == null) { + return null; + } List parsedScriptPaths = new ArrayList<>(); for (String path : scriptPaths) { ResourceFile pathFile = Path.fromPathString(path); From 6e19466dc618a6fc916a58cd3efdb1c08b32bd36 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 19 Mar 2021 10:43:34 -0400 Subject: [PATCH 105/140] GP-786: Some improvements and docs for the PE and ELF exporters --- .../help/topics/ExporterPlugin/exporter.htm | 30 +++- .../exporter/AbstractExecutableExporter.java | 107 ------------ .../util/exporter/AbstractLoaderExporter.java | 161 ++++++++++++++++++ .../ghidra/app/util/exporter/ElfExporter.java | 18 +- .../ghidra/app/util/exporter/PeExporter.java | 14 +- 5 files changed, 216 insertions(+), 114 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractLoaderExporter.java diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm index 1509a09ba1..4a8ff89bdd 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm @@ -284,6 +284,20 @@ + +

    ELF

    + +
    +

    Writes an ELF program that was imported with the ELF loader back to its original file + layout. Any file-backed bytes that were modified by the user in the program database will + be reflected in the new file.

    + +

    Writing back a modified Memory + Map is not supported.

    + +

    Relocation bytes are always + restored to their original values, even if the user modifies them.

    +

    Ghidra Zip File (.gzf)

    @@ -320,7 +334,7 @@
    • Address Space - Specifies which address space to export as Intel Hex format - only supports one address space. This option will be intialized to the "default" + only supports one address space. This option will be initialized to the "default" address space.
    • Record Size - Specifies the size (in bytes) of each record in the output file. The default 16.
    • @@ -330,6 +344,20 @@ 2 bytes will be dropped.
    + +

    PE

    + +
    +

    Writes a PE program that was imported with the PE loader back to its original file + layout. Any file-backed bytes that were modified by the user in the program database will + be reflected in the new file.

    + +

    Writing back a modified Memory + Map is not supported.

    + +

    Relocation bytes are always + restored to their original values, even if the user modifies them.

    +

    XML

    diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java deleted file mode 100644 index 490bfda798..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java +++ /dev/null @@ -1,107 +0,0 @@ -/* ### - * 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.exporter; - -import java.io.*; -import java.util.List; -import java.util.Optional; - -import ghidra.app.script.GhidraScript; -import ghidra.app.util.DomainObjectService; -import ghidra.app.util.Option; -import ghidra.framework.model.DomainObject; -import ghidra.program.database.mem.AddressSourceInfo; -import ghidra.program.database.mem.FileBytes; -import ghidra.program.model.address.*; -import ghidra.program.model.listing.Program; -import ghidra.program.model.mem.*; -import ghidra.program.model.reloc.Relocation; -import ghidra.util.HelpLocation; -import ghidra.util.task.TaskMonitor; -import utilities.util.FileUtilities; - -abstract class AbstractExecutableExporter extends Exporter { - - protected AbstractExecutableExporter(String name, String extension, HelpLocation help) { - super(name, extension, help); - } - - @Override - public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, - TaskMonitor monitor) throws IOException, ExporterException { - - if (!(domainObj instanceof Program)) { - log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); - return false; - } - Program program = (Program) domainObj; - Memory memory = program.getMemory(); - - try (OutputStream out = new FileOutputStream(file, false)) { - FileBytes[] fileBytes = memory.getAllFileBytes() - .stream() - .filter((fb) -> fb.getFilename().equals(program.getName())) - .toArray(FileBytes[]::new); - for (FileBytes bytes : fileBytes) { - FileBytesInputStream byteStream = new FileBytesInputStream(bytes); - FileUtilities.copyStreamToStream(byteStream, out, monitor); - } - } - try (RandomAccessFile fout = new RandomAccessFile(file, "rw")) { - Iterable relocs = - () -> program.getRelocationTable().getRelocations(); - for (Relocation reloc : relocs) { - AddressSourceInfo info = memory.getAddressSourceInfo(reloc.getAddress()); - // some relocations report negative offsets - if (info.getFileOffset() >= 0) { - // seek incase we are larger than an int - fout.seek(info.getFileOffset()); - fout.write(reloc.getBytes()); - } - } - } - - return true; - } - - @Override - public List