From fa31a01a10dbbc34db8c676510cf7736de6d0128 Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Tue, 30 Jun 2020 14:26:13 -0400 Subject: [PATCH 1/2] GP-21_emteere fix for slow performance when creating functions with disjointed address sets --- .../program/database/symbol/NamespaceManager.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java index 5f734fca56..0e8b061098 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java @@ -204,13 +204,14 @@ public class NamespaceManager implements ManagerDB { * @throws OverlappingNamespaceException if the address set to test overlaps a namespace body. */ public void overlapsNamespace(AddressSetView set) throws OverlappingNamespaceException { - AddressRangeIterator iter = - namespaceMap.getAddressRanges(set.getMinAddress(), set.getMaxAddress()); - while (iter.hasNext()) { - AddressRange range = iter.next(); - if (set.intersects(range.getMinAddress(), range.getMaxAddress())) { - throw new OverlappingNamespaceException(range.getMinAddress(), - range.getMaxAddress()); + AddressRangeIterator addressRanges = set.getAddressRanges(); + for (AddressRange addressRange : addressRanges) { + AddressRangeIterator namesSpaceRanges = namespaceMap.getAddressRanges( + addressRange.getMinAddress(), addressRange.getMaxAddress()); + AddressRange existingRange = namesSpaceRanges.next(); + if (existingRange != null) { + throw new OverlappingNamespaceException(existingRange.getMinAddress(), + existingRange.getMaxAddress()); } } } From 193e9688c888ebb14c94a8bf5ab5204f06f40b2f Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Wed, 8 Jul 2020 19:30:08 -0400 Subject: [PATCH 2/2] GP-21_emteere Performance fix for overlapping namespaces, remove exception throwing as a return code --- .../database/symbol/NamespaceManagerTest.java | 16 ++++++-------- .../database/function/FunctionManagerDB.java | 8 +++---- .../OverlappingFunctionException.java | 5 ++++- .../database/symbol/NamespaceManager.java | 21 ++++++++----------- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/NamespaceManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/NamespaceManagerTest.java index 67ccc5995f..ba7826e4e0 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/NamespaceManagerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/NamespaceManagerTest.java @@ -364,30 +364,26 @@ public class NamespaceManagerTest extends AbstractGhidraHeadedIntegrationTest { set2.addRange(addr(0x20), addr(0x50)); set2.addRange(addr(0x1000), addr(0x3000)); - try { - namespaceManager.overlapsNamespace(set2); + if (namespaceManager.overlapsNamespace(set2) == null) { Assert.fail("Should overlap!"); } - catch (OverlappingNamespaceException e) { - } set2 = new AddressSet(); set2.addRange(addr(0xff), addr(0x101)); set2.addRange(addr(0x1000), addr(0x3000)); - try { - namespaceManager.overlapsNamespace(set2); + if (namespaceManager.overlapsNamespace(set2) == null) { Assert.fail("Should overlap!"); } - catch (OverlappingNamespaceException e) { - } + set2 = new AddressSet(); set.addRange(addr(0x200), addr(0x210)); set.addRange(addr(0x55), addr(0xff)); set2.addRange(addr(0x1000), addr(0x3000)); - namespaceManager.overlapsNamespace(set2); - + if (namespaceManager.overlapsNamespace(set2) != null) { + Assert.fail("Should not overlap!"); + } } @Test diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionManagerDB.java index bf113c1246..51c9e5d443 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionManagerDB.java @@ -352,11 +352,9 @@ public class FunctionManagerDB implements ManagerDB, FunctionManager { throw new IllegalArgumentException( "Function entryPoint may not be created on defined data"); } - try { - namespaceMgr.overlapsNamespace(body); - } - catch (OverlappingNamespaceException e) { - throw new OverlappingFunctionException(entryPoint, e); + + if (namespaceMgr.overlapsNamespace(body) != null) { + throw new OverlappingFunctionException(entryPoint); } if (name == null || name.length() == 0 || diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/OverlappingFunctionException.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/OverlappingFunctionException.java index 1793ece264..cfebf0c3b5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/OverlappingFunctionException.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/OverlappingFunctionException.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. @@ -25,6 +24,10 @@ public class OverlappingFunctionException extends Exception { super("Unable to create function at " + entryPoint + " due to overlap with range [" + e.getStart() + "," + e.getEnd() + "]"); } + + public OverlappingFunctionException(Address entryPoint) { + super("Unable to create function at " + entryPoint + " due to overlap with another namespace"); + } public OverlappingFunctionException(String msg) { super(msg); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java index 0e8b061098..8b484a630d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/NamespaceManager.java @@ -124,8 +124,7 @@ public class NamespaceManager implements ManagerDB { * @param namespace the namespace whose body is to be modified. * @param set the address set for the new body. */ - public void setBody(Namespace namespace, AddressSetView set) - throws OverlappingNamespaceException { + public void setBody(Namespace namespace, AddressSetView set) throws OverlappingNamespaceException { if (set.getNumAddresses() > Integer.MAX_VALUE) { throw new IllegalArgumentException( "Namespace body size must be less than 0x7fffffff byte addresses"); @@ -133,12 +132,10 @@ public class NamespaceManager implements ManagerDB { lock.acquire(); try { AddressSetView oldBody = removeBody(namespace); - try { - overlapsNamespace(set); - } - catch (OverlappingNamespaceException e) { + AddressRange range = overlapsNamespace(set); + if (range != null) { doSetBody(namespace, oldBody); - throw e; + throw new OverlappingNamespaceException(range.getMinAddress(), range.getMaxAddress()); } doSetBody(namespace, set); } @@ -200,20 +197,20 @@ public class NamespaceManager implements ManagerDB { /** * Checks if an existing namespace's address set intersects with - * the given set. If so, then it throws an OverlappingNamespaceException. - * @throws OverlappingNamespaceException if the address set to test overlaps a namespace body. + * the given set. If so, return the first overlapping range. + * @returns null if no overlaps, or an address range of the first overlap */ - public void overlapsNamespace(AddressSetView set) throws OverlappingNamespaceException { + public AddressRange overlapsNamespace(AddressSetView set) { AddressRangeIterator addressRanges = set.getAddressRanges(); for (AddressRange addressRange : addressRanges) { AddressRangeIterator namesSpaceRanges = namespaceMap.getAddressRanges( addressRange.getMinAddress(), addressRange.getMaxAddress()); AddressRange existingRange = namesSpaceRanges.next(); if (existingRange != null) { - throw new OverlappingNamespaceException(existingRange.getMinAddress(), - existingRange.getMaxAddress()); + return existingRange; } } + return null; } /**