Skip to content

Commit

Permalink
PyPANDA: directory overrides for PANDA constructor
Browse files Browse the repository at this point in the history
Allow caller to specify location of libpanda shared object, pc-bios files,
and directory where plugins are installed.  If these arguments are left as
their default values PyPANDA will use the previous algorithm for finding
these files.

a773
  • Loading branch information
MarkMankins authored and Andrew Fasano committed Sep 25, 2023
1 parent 05ed22c commit 9f27158
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
37 changes: 27 additions & 10 deletions panda/python/core/pandare/panda.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def __init__(self, arch="i386", mem="128M",
raw_monitor=False, # When set, don't specify a -monitor. arg Allows for use of -nographic in args with ctrl-A+C for interactive qemu prompt.
extra_args=None,
catch_exceptions=True, # Should we catch and end_analysis() when python code raises an exception?
libpanda_path=None):
libpanda_path=None,
biospath=None,
plugin_path=None):
'''
Construct a new `Panda` object. Note that multiple Panda objects cannot coexist in the same Python instance.
Args:
Expand All @@ -83,6 +85,9 @@ def __init__(self, arch="i386", mem="128M",
-nographic in args with ctrl-A+C for interactive qemu prompt. Experts only!
extra_args: extra arguments to pass to PANDA as either a string or an
array. (e.g. "-nographic" or ["-nographic", "-net", "none"])
libpanda_path: path to panda shared object to load
biospath: directory that contains "pc-bios" files
plugin_path: directory that contains panda plugins
Returns:
Panda: the created panda object
'''
Expand All @@ -99,6 +104,8 @@ def __init__(self, arch="i386", mem="128M",
self.cdrom = None
self.catch_exceptions=catch_exceptions
self.qlog = QEMU_Log_Manager(self)
self.build_dir = None
self.plugin_path = plugin_path

self.serial_unconsumed_data = b''

Expand Down Expand Up @@ -147,13 +154,10 @@ def __init__(self, arch="i386", mem="128M",
raise ValueError(f"Unsupported architecture {self.arch_name}")
self.bits, self.endianness, self.register_size = self.arch._determine_bits()

self.build_dir = find_build_dir(self.arch_name)
environ["PANDA_DIR"] = self.build_dir

if libpanda_path:
self.libpanda_path = libpanda_path
environ["PANDA_LIB"] = self.libpanda_path = libpanda_path
else:
self.libpanda_path = pjoin(self.build_dir, "{0}-softmmu/libpanda-{0}.so".format(self.arch_name))
self.libpanda_path = pjoin(self.get_build_dir(), "{0}-softmmu/libpanda-{0}.so".format(self.arch_name))
self.panda = self.libpanda_path # Necessary for realpath to work inside core-panda, may cause issues?

self.ffi = self._do_types_import()
Expand All @@ -167,7 +171,9 @@ def __init__(self, arch="i386", mem="128M",

# Setup argv for panda
self.panda_args = [self.panda]
biospath = realpath(pjoin(self.build_dir, "pc-bios")) # XXX: necessary for network drivers for arm/mips, so 'pc-bios' is a misleading name

if biospath is None:
biospath = realpath(pjoin(self.get_build_dir(), "pc-bios")) # XXX: necessary for network drivers for arm/mips, so 'pc-bios' is a misleading name
self.panda_args.append("-L")
self.panda_args.append(biospath)

Expand Down Expand Up @@ -244,6 +250,17 @@ def __init__(self, arch="i386", mem="128M",
progress ("Panda args: [" + (" ".join(self.panda_args)) + "]")
# /__init__

def get_plugin_path(self):
if self.plugin_path is None:
self.plugin_path = pjoin(*[self.get_build_dir(), self.arch_name+"-softmmu", "panda", "plugins"])
return self.plugin_path

def get_build_dir(self):
if self.build_dir is None:
self.build_dir = find_build_dir(self.arch_name)
environ["PANDA_DIR"] = self.build_dir
return self.build_dir

def _do_types_import(self):
'''
Import objects from panda_datatypes which are configured by the environment variables(?)
Expand Down Expand Up @@ -908,9 +925,9 @@ def _load_plugin_library(self, name):
libpanda_path_chr = self.ffi.new("char[]",bytes(self.libpanda_path, "UTF-8"))
self.__did_load_libpanda = self.libpanda.panda_load_libpanda(libpanda_path_chr)
if not name in self.plugins.keys():
assert(isfile(pjoin(*[self.build_dir, self.arch_name+"-softmmu", "panda/plugins/panda_{}.so".format(name)])))
library = self.ffi.dlopen(pjoin(*[self.build_dir, self.arch_name+"-softmmu", "panda/plugins/panda_{}.so".format(name)]))
self.plugins[name] = library
plugin = pjoin(*[self.get_plugin_path(), f"panda_{name}.so"])
assert(isfile(plugin))
self.plugins[name] = self.ffi.dlopen(plugin)

def queue_async(self, f, internal=False):
'''
Expand Down
36 changes: 23 additions & 13 deletions panda/src/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,23 +201,33 @@ bool _panda_load_plugin(const char *filename, const char *plugin_name, bool libr
assert(0 && "Library dir unset but library mode is enabled - Unsupported architecture?");
printf("Library dir not set");
#endif
const char *lib_dir = g_getenv("PANDA_DIR");
char *library_path;
if (lib_dir != NULL) {
library_path = g_strdup_printf("%s%s", lib_dir, LIBRARY_DIR);
}else{
fprintf(stderr, "WARNING: using hacky dlopen code that will be removed soon\n");
library_path = g_strdup_printf("../../../build/%s", LIBRARY_DIR); // XXX This is bad, need a less hardcoded path
}
const char *panda_lib = g_getenv("PANDA_LIB");
if(panda_lib != NULL) {
void *libpanda = dlopen(panda_lib, RTLD_LAZY | RTLD_NOLOAD | RTLD_GLOBAL);

if (!libpanda) {
fprintf(stderr, "Failed to load libpanda: %s from %s\n", dlerror(), panda_lib);
return false;
}
} else {
const char *lib_dir = g_getenv("PANDA_DIR");
char *library_path;
if (lib_dir != NULL) {
library_path = g_strdup_printf("%s%s", lib_dir, LIBRARY_DIR);
}else{
fprintf(stderr, "WARNING: using hacky dlopen code that will be removed soon\n");
library_path = g_strdup_printf("../../../build/%s", LIBRARY_DIR); // XXX This is bad, need a less hardcoded path
}

void *libpanda = dlopen(library_path, RTLD_LAZY | RTLD_NOLOAD | RTLD_GLOBAL);
void *libpanda = dlopen(library_path, RTLD_LAZY | RTLD_NOLOAD | RTLD_GLOBAL);

if (!libpanda) {
fprintf(stderr, "Failed to load libpanda: %s from %s\n", dlerror(), library_path);
if (!libpanda) {
fprintf(stderr, "Failed to load libpanda: %s from %s\n", dlerror(), library_path);
g_free(library_path);
return false;
}
g_free(library_path);
return false;
}
g_free(library_path);
}

void *plugin = dlopen(filename, RTLD_NOW);
Expand Down

0 comments on commit 9f27158

Please sign in to comment.