base: Expose the ObjectFile class to python.

This will make it possible to inspect a binary and determine, for
example, what architecture or operating system it was compiled for.

Change-Id: Ib40f1e1c02448dc5bf084bb0dd98d3767f463fef
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/33899
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc
index 12e5606..6fdf228 100644
--- a/src/base/loader/object_file.cc
+++ b/src/base/loader/object_file.cc
@@ -38,6 +38,60 @@
 
 ObjectFile::ObjectFile(ImageFileDataPtr ifd) : ImageFile(ifd) {}
 
+const char *
+archToString(Arch arch)
+{
+    switch (arch) {
+      case UnknownArch:
+        return "unknown";
+      case SPARC64:
+        return "sparc64";
+      case SPARC32:
+        return "sparc32";
+      case Mips:
+        return "mips";
+      case X86_64:
+        return "x86_64";
+      case I386:
+        return "i386";
+      case Arm64:
+        return "arm64";
+      case Arm:
+        return "arm";
+      case Thumb:
+        return "thumb";
+      case Power:
+        return "power";
+      case Riscv64:
+        return "riscv64";
+      case Riscv32:
+        return "riscv32";
+      default:
+        panic("Unrecognized arch %d.", arch);
+    }
+}
+
+const char *
+opSysToString(OpSys op_sys)
+{
+    switch (op_sys) {
+      case UnknownOpSys:
+        return "unknown";
+      case Tru64:
+        return "tru64";
+      case Linux:
+        return "linux";
+      case Solaris:
+        return "solaris";
+      case LinuxArmOABI:
+        return "linux_arm_OABI";
+      case FreeBSD:
+        return "freebsd";
+      default:
+        panic("Unrecognized operating system %d.", op_sys);
+    }
+}
+
 namespace
 {
 
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 9ff9997..0bfd918 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -56,6 +56,8 @@
     Riscv32
 };
 
+const char *archToString(Arch arch);
+
 enum OpSys {
     UnknownOpSys,
     Tru64,
@@ -65,6 +67,8 @@
     FreeBSD
 };
 
+const char *opSysToString(OpSys op_sys);
+
 class SymbolTable;
 
 class ObjectFile : public ImageFile
diff --git a/src/python/SConscript b/src/python/SConscript
index cf52ee1..50f467e 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -69,4 +69,5 @@
 Source('pybind11/core.cc', add_tags='python')
 Source('pybind11/debug.cc', add_tags='python')
 Source('pybind11/event.cc', add_tags='python')
+Source('pybind11/object_file.cc', add_tags='python')
 Source('pybind11/stats.cc', add_tags='python')
diff --git a/src/python/pybind11/object_file.cc b/src/python/pybind11/object_file.cc
new file mode 100644
index 0000000..2ad5598
--- /dev/null
+++ b/src/python/pybind11/object_file.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/loader/object_file.hh"
+#include "python/pybind11/pybind.hh"
+#include "sim/init.hh"
+
+namespace py = pybind11;
+
+namespace
+{
+
+void
+objectfile_pybind(py::module &m_internal)
+{
+    py::module m = m_internal.def_submodule("object_file");
+
+    py::class_<Loader::ObjectFile>(m, "ObjectFile")
+        .def("get_arch", [](const Loader::ObjectFile &obj) {
+                return Loader::archToString(obj.getArch());
+                }, py::return_value_policy::reference)
+        .def("get_op_sys", [](const Loader::ObjectFile &obj) {
+                return Loader::opSysToString(obj.getOpSys());
+                }, py::return_value_policy::reference)
+        .def("entry_point", &Loader::ObjectFile::entryPoint)
+        .def("get_interpreter", &Loader::ObjectFile::getInterpreter);
+
+    m.def("create", [](const std::string &fname) {
+            return Loader::createObjectFile(fname); });
+}
+EmbeddedPyBind embed_("object_file", &objectfile_pybind);
+
+} // anonymous namespace