Add support for deserializing functions
authorChristoph Egger <Christoph.Egger@fau.de>
Tue, 3 Mar 2015 17:30:25 +0000 (18:30 +0100)
committerChristoph Egger <Christoph.Egger@fau.de>
Tue, 3 Mar 2015 17:30:25 +0000 (18:30 +0100)
Includes a first testcase

CMakeLists.txt
src/core/Function.cxx
src/core/Function.hxx
src/core/tests/FunctionTest.cxx [new file with mode: 0644]
testdata/core/Function/valid.xml [new file with mode: 0644]

index 765746127367f82c0a4d451989edfbc86228f485..5d1651682fabf5bea87b0556cbebdba23804a2e0 100644 (file)
@@ -89,6 +89,7 @@ TARGET_LINK_LIBRARIES(frida ${QT_LIBRARIES} ${LLVM_LDFLAGS} -lLLVM-3.5 ${LLVM_SY
 set(fridatest_SOURCES
   src/test.cxx
   src/core/tests/BasicBlockTest.cxx
+  src/core/tests/FunctionTest.cxx
   ${frida_SOURCES}
   )
 
index 1df4d1dba3b6a154c337c6d06f63bedcb3a2e6cd..781940ce71ddef42c7243ed63096f5d3155da590 100644 (file)
@@ -1,4 +1,5 @@
 #include "Function.hxx"
+#include "BasicBlock.hxx"
 #include "core/events/RenameFunctionEvent.hxx"
 #include "InformationManager.hxx"
 #include "gui/qt.hxx"
@@ -25,3 +26,30 @@ void Function::serialize(QXmlStreamWriter& stream) {
 
        stream.writeEndElement(); // "function"
 }
+
+Function* Function::deserialize(QXmlStreamReader& stream, InformationManager* manager) {
+       Q_ASSERT(stream.name() == "function");
+
+       QString name = stream.attributes().value("name").toString();
+       uint64_t entry = stream.attributes().value("entry").toULongLong(NULL, 16);
+       Function* fun = manager->newFunction(entry);
+
+       while (QXmlStreamReader::NoToken != stream.readNext()) {
+               while (QXmlStreamReader::Characters == stream.tokenType() &&
+                      stream.isWhitespace())
+                       stream.readNext();
+               if (QXmlStreamReader::EndElement == stream.tokenType())
+                       break;
+
+               if (stream.name() == "block") {
+                       BasicBlock* block = BasicBlock::deserialize(stream, manager);
+                       fun->addBasicBlock(block);
+               } else {
+                       return NULL;
+               }
+       }
+
+       manager->finishFunction(fun);
+       fun->setName(name.toStdString());
+       return fun;
+}
index d567c28c4828b4763378fd0cbed5b5adb3a42795..75b38c2cd34877fe0349b80eae21b5dc57976fbb 100644 (file)
@@ -30,6 +30,8 @@ public:
        }
 
        void serialize(QXmlStreamWriter& stream);
+       static Function* deserialize(QXmlStreamReader& stream, InformationManager* manager);
+
 private:
        Function(uint64_t start_address, InformationManager* manager);
 
diff --git a/src/core/tests/FunctionTest.cxx b/src/core/tests/FunctionTest.cxx
new file mode 100644 (file)
index 0000000..5357bb9
--- /dev/null
@@ -0,0 +1,26 @@
+#include <gtest/gtest.h>
+
+#include "gui/qt.hxx"
+#include "core/InformationManager.hxx"
+#include "core/BasicBlock.hxx"
+#include "core/Function.hxx"
+
+TEST(FunctionTest, deserializeValidInstance) {
+       QFile file("testdata/core/Function/valid.xml");
+       InformationManager manager;
+       file.open(QFile::ReadOnly | QFile::Text);
+       QXmlStreamReader reader(&file);
+
+       reader.readNextStartElement();
+       Function* fun = Function::deserialize(reader, &manager);
+
+       ASSERT_NE((void*)NULL, (void*)fun);
+       EXPECT_STREQ("main", fun->getName().c_str());
+       EXPECT_EQ(0x403e10, fun->getStartAddress());
+
+       EXPECT_STREQ("BLOCK_403e10_403e48", fun->blocks().find(0x403e10)->second->getName().c_str());
+       EXPECT_STREQ("BLOCK_403e48_403e50", fun->blocks().find(0x403e48)->second->getName().c_str());
+       EXPECT_STREQ("BLOCK_403e50_403e66", fun->blocks().find(0x403e50)->second->getName().c_str());
+       EXPECT_STREQ("BLOCK_403e66_403e75", fun->blocks().find(0x403e66)->second->getName().c_str());
+}
+
diff --git a/testdata/core/Function/valid.xml b/testdata/core/Function/valid.xml
new file mode 100644 (file)
index 0000000..a0f2bc0
--- /dev/null
@@ -0,0 +1,23 @@
+<function name="main" entry="403e10">
+       <block id="BLOCK_403e10_403e48">
+               <start>403e10</start>
+               <end>403e48</end>
+               <next>403e66</next>
+               <next>403e48</next>
+       </block>
+       <block id="BLOCK_403e48_403e50">
+               <start>403e48</start>
+               <end>403e50</end>
+               <next>403e50</next>
+       </block>
+       <block id="BLOCK_403e50_403e66">
+               <start>403e50</start>
+               <end>403e66</end>
+               <next>403e50</next>
+               <next>403e66</next>
+       </block>
+       <block id="BLOCK_403e66_403e75">
+               <start>403e66</start>
+               <end>403e75</end>
+       </block>
+</function>