mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
1bed582491
8 changed files with 51 additions and 14 deletions
|
@ -109,8 +109,16 @@ public class ProgramEmulationUtils {
|
||||||
<interface name='Thread' />
|
<interface name='Thread' />
|
||||||
<interface name='Activatable' />
|
<interface name='Activatable' />
|
||||||
<interface name='Aggregate' />
|
<interface name='Aggregate' />
|
||||||
|
<attribute name='Stack' schema='Stack' />
|
||||||
<attribute name='Registers' schema='RegisterContainer' />
|
<attribute name='Registers' schema='RegisterContainer' />
|
||||||
</schema>
|
</schema>
|
||||||
|
<schema name='Stack' canonical='yes'>
|
||||||
|
<interface name='Stack' />
|
||||||
|
<element schema='Frame' />
|
||||||
|
</schema>
|
||||||
|
<schema name='Frame'>
|
||||||
|
<interface name='StackFrame' />
|
||||||
|
</schema>
|
||||||
<schema name='RegisterContainer' canonical='yes' elementResync='NEVER'
|
<schema name='RegisterContainer' canonical='yes' elementResync='NEVER'
|
||||||
attributeResync='NEVER'>
|
attributeResync='NEVER'>
|
||||||
<interface name='RegisterContainer' />
|
<interface name='RegisterContainer' />
|
||||||
|
|
|
@ -58,6 +58,11 @@ import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||||
|
import ghidra.trace.model.stack.TraceObjectStack;
|
||||||
|
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.path.PathFilter;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.trace.model.time.schedule.Scheduler;
|
import ghidra.trace.model.time.schedule.Scheduler;
|
||||||
|
@ -976,4 +981,15 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
||||||
PcodeThread<byte[]> newEmuThread = emulator.newThread(newTraceThread.getPath());
|
PcodeThread<byte[]> newEmuThread = emulator.newThread(newTraceThread.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmuSchemaHasWorkingStackFrames() throws Exception {
|
||||||
|
TraceObjectSchema rootSchema = ProgramEmulationUtils.EMU_SESSION_SCHEMA;
|
||||||
|
TraceObjectSchema threadSchema = rootSchema.getSuccessorSchema(KeyPath.parse("Threads[1]"));
|
||||||
|
KeyPath found = threadSchema.searchForCanonicalContainer(TraceObjectStackFrame.class);
|
||||||
|
assertEquals(KeyPath.parse("Stack"), found);
|
||||||
|
|
||||||
|
PathFilter stackFilter = threadSchema.searchFor(TraceObjectStack.class, false);
|
||||||
|
assertNotNull("Non-unique Stack", stackFilter.getSingletonPath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -721,7 +721,8 @@ public interface TraceObjectSchema {
|
||||||
for (Map.Entry<String, AttributeSchema> attrEnt : ent.schema.getAttributeSchemas()
|
for (Map.Entry<String, AttributeSchema> attrEnt : ent.schema.getAttributeSchemas()
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
TraceObjectSchema attrSchema = ctx.getSchema(attrEnt.getValue().getSchema());
|
TraceObjectSchema attrSchema = ctx.getSchema(attrEnt.getValue().getSchema());
|
||||||
if (TraceObjectInterface.class.isAssignableFrom(attrSchema.getType()) &&
|
if ((TraceObjectInterface.class.isAssignableFrom(attrSchema.getType()) ||
|
||||||
|
TraceObject.class.isAssignableFrom(attrSchema.getType())) &&
|
||||||
visited.add(attrSchema)) {
|
visited.add(attrSchema)) {
|
||||||
nextLevel.add(new Private.CanonicalSearchEntry(
|
nextLevel.add(new Private.CanonicalSearchEntry(
|
||||||
ent.path.key(attrEnt.getKey()),
|
ent.path.key(attrEnt.getKey()),
|
||||||
|
|
|
@ -748,7 +748,7 @@
|
||||||
</TABLE>
|
</TABLE>
|
||||||
</DIV>
|
</DIV>
|
||||||
|
|
||||||
<P>If the default Ghidra Server port (1111) is in use it need not be specified with URL.
|
<P>If the default Ghidra Server base port (13100) is in use it need not be specified with URL.
|
||||||
The <EM>hostname</EM> may specify either a Fully Qualified Domain Name (FQDN, e.g.,
|
The <EM>hostname</EM> may specify either a Fully Qualified Domain Name (FQDN, e.g.,
|
||||||
<EM>host.abc.com</EM>) or IP v4 Address (e.g., <EM>1.2.3.4</EM>).</P>
|
<EM>host.abc.com</EM>) or IP v4 Address (e.g., <EM>1.2.3.4</EM>).</P>
|
||||||
<STRONG>Local Ghidra Project</STRONG><BR>
|
<STRONG>Local Ghidra Project</STRONG><BR>
|
||||||
|
|
|
@ -105,7 +105,8 @@ def open_program(
|
||||||
analyze=True,
|
analyze=True,
|
||||||
language: str = None,
|
language: str = None,
|
||||||
compiler: str = None,
|
compiler: str = None,
|
||||||
loader: Union[str, JClass] = None
|
loader: Union[str, JClass] = None,
|
||||||
|
program_name: str = None
|
||||||
) -> ContextManager["FlatProgramAPI"]: # type: ignore
|
) -> ContextManager["FlatProgramAPI"]: # type: ignore
|
||||||
"""
|
"""
|
||||||
Opens given binary path in Ghidra and returns FlatProgramAPI object.
|
Opens given binary path in Ghidra and returns FlatProgramAPI object.
|
||||||
|
@ -122,6 +123,8 @@ def open_program(
|
||||||
(Defaults to the Language's default compiler)
|
(Defaults to the Language's default compiler)
|
||||||
:param loader: The `ghidra.app.util.opinion.Loader` class to use when importing the program.
|
:param loader: The `ghidra.app.util.opinion.Loader` class to use when importing the program.
|
||||||
This may be either a Java class or its path. (Defaults to None)
|
This may be either a Java class or its path. (Defaults to None)
|
||||||
|
:param program_name: The name to of the program to open in Ghidra.
|
||||||
|
(Defaults to None, which results in the name being derived from "binary_path")
|
||||||
:return: A Ghidra FlatProgramAPI object.
|
:return: A Ghidra FlatProgramAPI object.
|
||||||
:raises ValueError: If the provided language, compiler or loader is invalid.
|
:raises ValueError: If the provided language, compiler or loader is invalid.
|
||||||
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
||||||
|
@ -306,7 +309,9 @@ import pdb # imports Python's pdb
|
||||||
import pdb_ # imports Ghidra's pdb
|
import pdb_ # imports Ghidra's pdb
|
||||||
```
|
```
|
||||||
## Change History
|
## Change History
|
||||||
__2.0.2:__
|
__2.1.0:__
|
||||||
|
* [`pyghidra.open_program()`](#pyghidraopen_program) now accepts a `program_name` parameter, which
|
||||||
|
can be used to override the program name derived from the `binary_path` parameter.
|
||||||
* [`pyghidra.open_program()`](#pyghidraopen_program) now properly throws an exception if the project
|
* [`pyghidra.open_program()`](#pyghidraopen_program) now properly throws an exception if the project
|
||||||
exists and is locked.
|
exists and is locked.
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
__version__ = "2.0.2"
|
__version__ = "2.1.0"
|
||||||
|
|
||||||
# stub for documentation and typing
|
# stub for documentation and typing
|
||||||
# this is mostly to hide the function parameter
|
# this is mostly to hide the function parameter
|
||||||
|
|
|
@ -81,13 +81,16 @@ def _setup_project(
|
||||||
project_name: str = None,
|
project_name: str = None,
|
||||||
language: str = None,
|
language: str = None,
|
||||||
compiler: str = None,
|
compiler: str = None,
|
||||||
loader: Union[str, JClass] = None
|
loader: Union[str, JClass] = None,
|
||||||
|
program_name: str = None
|
||||||
) -> Tuple["GhidraProject", "Program"]:
|
) -> Tuple["GhidraProject", "Program"]:
|
||||||
from ghidra.base.project import GhidraProject
|
from ghidra.base.project import GhidraProject
|
||||||
from java.lang import ClassLoader # type:ignore @UnresolvedImport
|
from java.lang import ClassLoader # type:ignore @UnresolvedImport
|
||||||
from ghidra.framework.model import ProjectLocator # type:ignore @UnresolvedImport
|
from ghidra.framework.model import ProjectLocator # type:ignore @UnresolvedImport
|
||||||
if binary_path is not None:
|
if binary_path is not None:
|
||||||
binary_path = Path(binary_path)
|
binary_path = Path(binary_path)
|
||||||
|
if program_name is None and binary_path is not None:
|
||||||
|
program_name = binary_path.name
|
||||||
if project_location:
|
if project_location:
|
||||||
project_location = Path(project_location)
|
project_location = Path(project_location)
|
||||||
else:
|
else:
|
||||||
|
@ -117,9 +120,9 @@ def _setup_project(
|
||||||
else:
|
else:
|
||||||
project_location.mkdir(exist_ok=True, parents=True)
|
project_location.mkdir(exist_ok=True, parents=True)
|
||||||
project = GhidraProject.createProject(project_location, project_name, False)
|
project = GhidraProject.createProject(project_location, project_name, False)
|
||||||
if binary_path is not None:
|
if program_name is not None:
|
||||||
if project.getRootFolder().getFile(binary_path.name):
|
if project.getRootFolder().getFile(program_name):
|
||||||
program = project.openProgram("/", binary_path.name, False)
|
program = project.openProgram("/", program_name, False)
|
||||||
|
|
||||||
# NOTE: GhidraProject.importProgram behaves differently when a loader is provided
|
# NOTE: GhidraProject.importProgram behaves differently when a loader is provided
|
||||||
# loaderClass may not be null so we must use the correct method override
|
# loaderClass may not be null so we must use the correct method override
|
||||||
|
@ -146,7 +149,7 @@ def _setup_project(
|
||||||
else:
|
else:
|
||||||
message += f"The provided language ({language}) may be invalid."
|
message += f"The provided language ({language}) may be invalid."
|
||||||
raise ValueError(message)
|
raise ValueError(message)
|
||||||
project.saveAs(program, "/", program.getName(), True)
|
project.saveAs(program, "/", program_name, True)
|
||||||
|
|
||||||
return project, program
|
return project, program
|
||||||
|
|
||||||
|
@ -198,10 +201,11 @@ def open_program(
|
||||||
analyze=True,
|
analyze=True,
|
||||||
language: str = None,
|
language: str = None,
|
||||||
compiler: str = None,
|
compiler: str = None,
|
||||||
loader: Union[str, JClass] = None
|
loader: Union[str, JClass] = None,
|
||||||
|
program_name: str = None
|
||||||
) -> ContextManager["FlatProgramAPI"]: # type: ignore
|
) -> ContextManager["FlatProgramAPI"]: # type: ignore
|
||||||
"""
|
"""
|
||||||
Opens given binary path in Ghidra and returns FlatProgramAPI object.
|
Opens given binary path (or optional program name) in Ghidra and returns FlatProgramAPI object.
|
||||||
|
|
||||||
:param binary_path: Path to binary file, may be None.
|
:param binary_path: Path to binary file, may be None.
|
||||||
:param project_location: Location of Ghidra project to open/create.
|
:param project_location: Location of Ghidra project to open/create.
|
||||||
|
@ -215,6 +219,8 @@ def open_program(
|
||||||
(Defaults to the Language's default compiler)
|
(Defaults to the Language's default compiler)
|
||||||
:param loader: The `ghidra.app.util.opinion.Loader` class to use when importing the program.
|
:param loader: The `ghidra.app.util.opinion.Loader` class to use when importing the program.
|
||||||
This may be either a Java class or its path. (Defaults to None)
|
This may be either a Java class or its path. (Defaults to None)
|
||||||
|
:param program_name: The name of the program to open in Ghidra.
|
||||||
|
(Defaults to None, which results in the name being derived from "binary_path")
|
||||||
:return: A Ghidra FlatProgramAPI object.
|
:return: A Ghidra FlatProgramAPI object.
|
||||||
:raises ValueError: If the provided language, compiler or loader is invalid.
|
:raises ValueError: If the provided language, compiler or loader is invalid.
|
||||||
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
||||||
|
@ -234,7 +240,8 @@ def open_program(
|
||||||
project_name,
|
project_name,
|
||||||
language,
|
language,
|
||||||
compiler,
|
compiler,
|
||||||
loader
|
loader,
|
||||||
|
program_name
|
||||||
)
|
)
|
||||||
GhidraScriptUtil.acquireBundleHostReference()
|
GhidraScriptUtil.acquireBundleHostReference()
|
||||||
|
|
||||||
|
|
|
@ -1087,7 +1087,7 @@ public class FrontEndPlugin extends Plugin
|
||||||
Msg.showInfo(this, tool.getToolFrame(), "Cannot Find Tool",
|
Msg.showInfo(this, tool.getToolFrame(), "Cannot Find Tool",
|
||||||
"<html>File type is unrecognized: <b>" +
|
"<html>File type is unrecognized: <b>" +
|
||||||
HTMLUtilities.escapeHTML(domainFile.getName()) +
|
HTMLUtilities.escapeHTML(domainFile.getName()) +
|
||||||
"</b>.<br><br>File may have been created with a neer version of Ghidra.");
|
"</b>.<br><br>File may have been created with a newer version of Ghidra.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue