diff --git a/.gitattributes b/.gitattributes
index acacbe10b14a2b4a97db621a61c078cdc058200a..ff4be8ed7f6270b2e5c85bfd9d4240b39a3e88a4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -198,6 +198,7 @@ libIRDB/include/core/function.hpp -text
 libIRDB/include/core/instruction.hpp -text
 libIRDB/include/core/pqxxdb.hpp -text
 libIRDB/include/core/reloc.hpp -text
+libIRDB/include/core/type.hpp -text
 libIRDB/include/core/variantid.hpp -text
 libIRDB/include/libIRDB-cfg.hpp -text
 libIRDB/include/libIRDB-core.hpp -text
@@ -223,6 +224,7 @@ libIRDB/src/core/function.cpp -text
 libIRDB/src/core/generate_spri.cpp -text
 libIRDB/src/core/instruction.cpp -text
 libIRDB/src/core/pqxxdb.cpp -text
+libIRDB/src/core/type.cpp -text
 libIRDB/src/core/variantid.cpp -text
 libIRDB/src/syscall/Makefile.in -text
 libIRDB/src/syscall/syscall.cpp -text
@@ -259,6 +261,7 @@ libMEDSannotation/include/MEDS_AnnotationParser.hpp -text
 libMEDSannotation/include/MEDS_FPTRShadowAnnotation.hpp -text
 libMEDSannotation/include/MEDS_FRSafeAnnotation.hpp -text
 libMEDSannotation/include/MEDS_FuncAnnotation.hpp -text
+libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp -text
 libMEDSannotation/include/MEDS_InstructionCheckAnnotation.hpp -text
 libMEDSannotation/include/MEDS_ProblemFuncAnnotation.hpp -text
 libMEDSannotation/include/MEDS_Register.hpp -text
@@ -269,6 +272,7 @@ libMEDSannotation/src/FuncExitAnnotation.cpp -text
 libMEDSannotation/src/MEDS_AnnotationParser.cpp -text
 libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp -text
 libMEDSannotation/src/MEDS_FRSafeAnnotation.cpp -text
+libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp -text
 libMEDSannotation/src/MEDS_InstructionCheckAnnotation.cpp -text
 libMEDSannotation/src/MEDS_ProblemFuncAnnotation.cpp -text
 libMEDSannotation/src/MEDS_Register.cpp -text
diff --git a/libIRDB/include/core/address.hpp b/libIRDB/include/core/address.hpp
index df806d335d812bab218ec76b1de2aadce581a19b..dd267e9aa1eb2a1ad738aa87b2b3761d3e725574 100644
--- a/libIRDB/include/core/address.hpp
+++ b/libIRDB/include/core/address.hpp
@@ -46,8 +46,7 @@ class AddressID_t : public BaseObj_t
         virtual_offset_t GetVirtualOffset() { return virtual_offset; }
         void SetVirtualOffset(virtual_offset_t voff) { virtual_offset=voff; }
 
-	void WriteToDB() { assert(0); }
-        std::string WriteToDB(File_t *vid, db_id_t newid, bool p_withHeader);
+		std::string WriteToDB(File_t *vid, db_id_t newid, bool p_withHeader);
 
 	inline bool operator<(const AddressID_t& cmp) const 
 		{ return fileID < cmp.fileID || (fileID == cmp.fileID && virtual_offset < cmp.virtual_offset);} 
diff --git a/libIRDB/include/core/baseobj.hpp b/libIRDB/include/core/baseobj.hpp
index 96606299729574c0fe4d03be7f96238d9f31c322..b3d78a64cce6b34944a1d55a535ea1c90b85178c 100644
--- a/libIRDB/include/core/baseobj.hpp
+++ b/libIRDB/include/core/baseobj.hpp
@@ -39,11 +39,8 @@ class BaseObj_t
         db_id_t GetDoipID() const { return doip ? doip->GetBaseID() : NOT_IN_DATABASE; }
         void SetDoipID(doip_t *dp) { doip=dp; }
         void SetBaseID(db_id_t id) {base_id=id; }
-   
-        // A derived class must provide functionality to write to the database.
-        virtual void WriteToDB()=0;    
 
-	static const db_id_t NOT_IN_DATABASE;
+		static const db_id_t NOT_IN_DATABASE;
 
     protected:
         static DBinterface_t *dbintr;
@@ -51,6 +48,5 @@ class BaseObj_t
     private:
         doip_t* doip;
         db_id_t base_id;    // -1 means not yet in the DB.
-
 };
 
diff --git a/libIRDB/include/core/file.hpp b/libIRDB/include/core/file.hpp
index 500bd84db3c77776cb3cacde2e63649bda6b92bc..65c5ac8faa9b5de05356d7fd6d6185249a3f4277 100644
--- a/libIRDB/include/core/file.hpp
+++ b/libIRDB/include/core/file.hpp
@@ -24,7 +24,7 @@ class File_t : public BaseObj_t
     public:
         // create new item.
         File_t(db_id_t file_id, db_id_t orig_fid, std::string url, std::string hash, std::string arch, int elfoid, 
-		std::string atn, std::string ftn, std::string itn, std::string rtn, db_id_t doipid);
+		std::string atn, std::string ftn, std::string itn, std::string rtn, std::string typ, db_id_t doipid);
 
         File_t(db_id_t file_id) : BaseObj_t(NULL) { assert(0);}          // read from DB       
         void WriteToDB() { assert(0); }   // writes to DB ID is not -1.
@@ -33,6 +33,7 @@ class File_t : public BaseObj_t
         std::string GetFunctionTableName() { return function_table_name; }
         std::string GetInstructionTableName() { return instruction_table_name; }
         std::string GetRelocationsTableName() { return relocs_table_name; }
+        std::string GetTypesTableName() { return types_table_name; }
         std::string GetURL() { return url; }
 
 	void CreateTables();
@@ -45,8 +46,11 @@ class File_t : public BaseObj_t
         friend class Instruction_t;
         friend class VariantID_t;
         friend class Relocation_t;
-
-
+        friend class Type_t;
+        friend class BasicType_t;
+        friend class PointerType_t;
+        friend class AggregateType_t;
+        friend class FuncType_t;
 
     private:
 	db_id_t orig_fid;
@@ -57,5 +61,6 @@ class File_t : public BaseObj_t
         std::string function_table_name;
         std::string instruction_table_name;
         std::string relocs_table_name;
+        std::string types_table_name;
 	int elfoid;
 };
diff --git a/libIRDB/include/core/fileir.hpp b/libIRDB/include/core/fileir.hpp
index 25a07d9798f2f2b8a41dc5e0b8c007372b71046a..41da122ae61594b0857f61e975ee5fdfcb8e5c85 100644
--- a/libIRDB/include/core/fileir.hpp
+++ b/libIRDB/include/core/fileir.hpp
@@ -18,9 +18,10 @@
  *
  */
 
+#include "type.hpp"
 
 typedef std::set<Function_t*> FunctionSet_t;
-typedef std::set<AddressID_t*> AddressSet_t;;
+typedef std::set<AddressID_t*> AddressSet_t;
 
 // A variant of a problem, this
 // may be an original variant
@@ -90,13 +91,15 @@ class FileIR_t : public BaseObj_t
 	InstructionSet_t insns;
 	AddressSet_t addrs;
 	RelocationSet_t relocs;
+	TypeSet_t types;
 	VariantID_t progid;
 	File_t* fileptr;
 
 	std::map<db_id_t,AddressID_t*> ReadAddrsFromDB();
 	std::map<db_id_t,Function_t*> ReadFuncsFromDB
 	(
-		std::map<db_id_t,AddressID_t*> &addrMap
+		std::map<db_id_t,AddressID_t*> &addrMap,
+		std::map<db_id_t,Type_t*> &typeMap
 	);
 	std::map<db_id_t,Instruction_t*> ReadInsnsFromDB 
 	(	
@@ -108,7 +111,10 @@ class FileIR_t : public BaseObj_t
 		std::map<db_id_t,Instruction_t*>		&insnMap
 	);
 
+	std::map<db_id_t, Type_t*> ReadTypesFromDB(TypeSet_t& types);
+
 
+	// @TODO: need types
 
 };
 
diff --git a/libIRDB/include/core/function.hpp b/libIRDB/include/core/function.hpp
index 2877dc1bac1a46c29d080dd027a451ea61c4d267..b7feeb19565352d188455400b9eef8e5f3251123 100644
--- a/libIRDB/include/core/function.hpp
+++ b/libIRDB/include/core/function.hpp
@@ -18,6 +18,7 @@
  *
  */
 
+#include "core/type.hpp"
 
 typedef        std::set<Instruction_t*> InstructionSet_t;
 
@@ -29,7 +30,7 @@ class Function_t : public BaseObj_t
 	Function_t() : BaseObj_t(NULL) {}	// create a new function not in the db 
 
 	// create a function that's already in the DB  
-	Function_t(db_id_t id, std::string name, int size, int oa_size, bool use_fp, Instruction_t *entry);	
+	Function_t(db_id_t id, std::string name, int size, int oa_size, bool use_fp, FuncType_t *, Instruction_t *entry);	
 
 	InstructionSet_t& GetInstructions() { return my_insns; }
 
@@ -42,14 +43,16 @@ class Function_t : public BaseObj_t
         void SetOutArgsRegionSize(int oa_size) {out_args_region_size=oa_size;}
 
 	void SetEntryPoint(Instruction_t *insn) {entry_point=insn;}
-	Instruction_t* GetEntryPoint() { return entry_point;}
+	Instruction_t* GetEntryPoint() const { return entry_point;}
 
-	void WriteToDB();		// we need the variant ID to write into a program.
 	std::string WriteToDB(File_t *fid, db_id_t newid);
 
-        bool GetUseFramePointer() { return use_fp; }
+        bool GetUseFramePointer() const { return use_fp; }
         void SetUseFramePointer(bool useFP) { use_fp = useFP; }
 
+		void SetType(FuncType_t *t) { function_type = t; }
+		FuncType_t* GetType() const { return function_type; }
+
 
     private:
 	Instruction_t *entry_point;
@@ -58,5 +61,6 @@ class Function_t : public BaseObj_t
         std::string name;
         int out_args_region_size;
         bool use_fp;
+		FuncType_t *function_type;
 };
 
diff --git a/libIRDB/include/core/type.hpp b/libIRDB/include/core/type.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad9bbb379a6e6649f1ccd9229b1da8ee60114330
--- /dev/null
+++ b/libIRDB/include/core/type.hpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2014 - Zephyr Software LLC
+ *
+ * This file may be used and modified for non-commercial purposes as long as
+ * all copyright, permission, and nonwarranty notices are preserved.
+ * Redistribution is prohibited without prior written consent from Zephyr
+ * Software.
+ *
+ * Please contact the authors for restrictions applying to commercial use.
+ *
+ * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Zephyr Software
+ * e-mail: jwd@zephyr-software.com
+ * URL   : http://www.zephyr-software.com/
+ *
+ */
+
+#ifndef _IRDB_TYPE_H_
+#define _IRDB_TYPE_H_
+
+// add as many types as you want here
+// MUST MATCH code in meds2pdb!!!
+typedef enum IRDB_Type {
+	T_UNKNOWN = 0,     // must be 0, leave this value alone
+	T_NUMERIC = 1, T_POINTER = 2, 
+	T_VOID = 10, T_VARIADIC = 11, T_INT = 12, T_CHAR = 13, T_FLOAT = 14, T_DOUBLE = 15, 
+	T_TYPEDEF = 21, T_SUBTYPE = 22, 
+	T_FUNC = 100, T_AGGREGATE = 101
+} IRDB_Type;
+
+class Type_t;
+
+typedef std::set<Type_t*> TypeSet_t;
+typedef std::vector<Type_t*> TypeVector_t;
+
+class Type_t : public BaseObj_t
+{
+	public:
+		Type_t() : BaseObj_t(NULL) {
+			typeID = T_UNKNOWN;
+		}	
+		Type_t(db_id_t dbid, IRDB_Type t, std::string n) : BaseObj_t(NULL) {
+			SetBaseID(dbid);
+			typeID = t;
+			name = n;
+		}	
+		virtual ~Type_t() {}
+
+		virtual std::string WriteToDB(File_t *fid, db_id_t newid) = 0;
+
+		std::string GetName() const { return name; }
+		void SetName(std::string newname) { name=newname; }
+		IRDB_Type GetTypeID() const { return typeID; }
+		void SetTypeID(IRDB_Type t) { typeID = t; }
+
+		virtual bool IsUnknownType() const { return typeID == T_UNKNOWN; }
+		virtual bool IsVariadicType() const { return typeID == T_VARIADIC; }
+		virtual bool IsAggregateType() const { return typeID == T_AGGREGATE; }
+		virtual bool IsFuncType() const { return typeID == T_FUNC; }
+		virtual bool IsBasicType() const { return false; }
+		virtual bool IsPointerType() const { return false; }
+		virtual bool IsNumericType() const { return false; }
+
+	private:
+		std::string name;
+		IRDB_Type typeID;
+};
+
+class BasicType_t : public Type_t
+{
+	public:
+		BasicType_t() : Type_t() {}	
+		BasicType_t(db_id_t id, IRDB_Type type, std::string name) : Type_t(id, type, name) {}
+		virtual ~BasicType_t() {}
+
+		virtual bool IsBasicType() const { return true; }
+		virtual bool IsNumericType() const;
+
+		std::string WriteToDB(File_t *fid, db_id_t newid);
+};
+
+class PointerType_t : public Type_t
+{
+	public:
+		PointerType_t() : Type_t() { SetTypeID(T_POINTER); referentType = NULL; }	
+		PointerType_t(db_id_t id, Type_t* ref, std::string name) : Type_t(id, T_POINTER, name) {
+			SetReferentType(ref);
+		}
+		virtual ~PointerType_t() {}
+		virtual bool IsPointerType() const { return true; }
+
+		Type_t* GetReferentType() const { return referentType; }
+		void SetReferentType(Type_t* r) { referentType = r; }
+
+		std::string WriteToDB(File_t *fid, db_id_t newid);
+
+	private:
+		Type_t* referentType; 
+};
+
+class AggregateType_t : public Type_t
+{
+	public:
+		AggregateType_t() : Type_t() { SetTypeID(T_AGGREGATE); }	
+		AggregateType_t(db_id_t id, std::string name) : Type_t(id, T_AGGREGATE, name) {}
+		virtual ~AggregateType_t() {}
+		virtual bool IsAggregateType() const { return true; }
+
+		void AddAggregatedType(Type_t *t, int pos);
+		virtual int GetNumAggregatedTypes() const { return refTypes.size(); } 
+		Type_t* GetAggregatedType(int pos) const { 
+			return (pos >= 0 && pos < refTypes.size()) ? refTypes.at(pos) : NULL;
+		}
+
+		std::string toString() {
+			return GetName();
+		}
+
+		std::string WriteToDB(File_t *fid, db_id_t newid);
+
+	private:
+		TypeVector_t refTypes;
+};
+
+class FuncType_t : public Type_t
+{
+	public:
+		FuncType_t() : Type_t() { SetTypeID(T_FUNC); _init(); }	
+		FuncType_t(db_id_t id, std::string name) : Type_t(id, T_FUNC, name) { _init(); }
+		virtual ~FuncType_t() {}
+
+		virtual bool IsFuncType() const { return true; }
+
+		std::string WriteToDB(File_t *fid, db_id_t newid);
+
+		Type_t* GetReturnType() const { return returnType; }
+		void SetReturnType(Type_t *t) { returnType = t; }
+		AggregateType_t* GetArgumentsType() const { return argsType; }
+		void SetArgumentsType(AggregateType_t *t) { argsType = t; }
+
+	private:
+		void _init() {
+			returnType = NULL;
+			argsType = NULL;
+		}
+
+	private:
+		Type_t*            returnType;
+		AggregateType_t*   argsType;
+};
+
+#endif
diff --git a/libIRDB/include/libIRDB-core.hpp b/libIRDB/include/libIRDB-core.hpp
index 2839f8343abbcf12e08009d95789234fa077210b..60ba8643cfb3f06bbdc3c2697c25b4ab4e5947fe 100644
--- a/libIRDB/include/libIRDB-core.hpp
+++ b/libIRDB/include/libIRDB-core.hpp
@@ -47,6 +47,7 @@ class Instruction_t; // forward decl for many classes
 #include <core/function.hpp>
 #include <core/variantid.hpp>
 #include <core/archdesc.hpp>
+#include <core/type.hpp>
 #include <core/fileir.hpp>
 #include <core/pqxxdb.hpp>
 
diff --git a/libIRDB/src/core/Makefile b/libIRDB/src/core/Makefile
index a22f505dc84185d7ce62f157e4cf3f996397608d..21680626fb0e068dd52219f8ebc1b5a771e9776e 100644
--- a/libIRDB/src/core/Makefile
+++ b/libIRDB/src/core/Makefile
@@ -2,7 +2,7 @@
 LIB=../../lib/libIRDB-core.a
 
 
-OBJS=baseobj.o  variantid.o pqxxdb.o dbinterface.o function.o fileir.o file.o instruction.o address.o generate_spri.o
+OBJS=baseobj.o type.o variantid.o pqxxdb.o dbinterface.o function.o fileir.o file.o instruction.o address.o generate_spri.o
 
 all: $(OBJS)
 
diff --git a/libIRDB/src/core/file.cpp b/libIRDB/src/core/file.cpp
index ab5738523adbeecdda7f62a2f5babb499c007e86..9418828b8d300cd6495ecaf5d02471b70c411b28 100644
--- a/libIRDB/src/core/file.cpp
+++ b/libIRDB/src/core/file.cpp
@@ -32,13 +32,12 @@ using namespace std;
 
 
 File_t::File_t(db_id_t myfile_id, db_id_t my_orig_fid, std::string myurl, std::string myhash, std::string myarch, int myoid, 
-		std::string atn, std::string ftn, std::string itn, std::string rtn, db_id_t mydoipid) :
+		std::string atn, std::string ftn, std::string itn, std::string rtn, std::string typ, db_id_t mydoipid) :
 	BaseObj_t(NULL), url(myurl), hash(myhash), arch(myarch), elfoid(myoid),
 	address_table_name(atn), function_table_name(ftn), instruction_table_name(itn), 
-	relocs_table_name(rtn), orig_fid(my_orig_fid)
+	relocs_table_name(rtn), types_table_name(typ), orig_fid(my_orig_fid)
 {
 	SetBaseID(myfile_id);
-
 }
 
 
@@ -55,6 +54,7 @@ void File_t::CreateTables()
 		function_table_name+" "+
 		instruction_table_name+" "+
 		relocs_table_name+" "+
+		types_table_name+" "+
 		tmpfile;
 
 	system(command.c_str());
diff --git a/libIRDB/src/core/fileir.cpp b/libIRDB/src/core/fileir.cpp
index b86c7cb1e8ed60b91fb722275588fcc3ff853824..cbf346b62a79fb5b67bc5dc55483d50bb5380e24 100644
--- a/libIRDB/src/core/fileir.cpp
+++ b/libIRDB/src/core/fileir.cpp
@@ -89,6 +89,11 @@ FileIR_t::~FileIR_t()
 	{
 		delete *i;
 	}
+
+	for(std::set<Type_t*>::const_iterator i=types.begin(); i!=types.end(); ++i)
+	{
+		delete *i;
+	}
 }
   
 // DB operations
@@ -96,8 +101,9 @@ void FileIR_t::ReadFromDB()
 {
 	entry_points.clear();
 
+	std::map<db_id_t,Type_t*> typesMap = ReadTypesFromDB(types); 
 	std::map<db_id_t,AddressID_t*> 	addrMap=ReadAddrsFromDB();
-	std::map<db_id_t,Function_t*> 	funcMap=ReadFuncsFromDB(addrMap);
+	std::map<db_id_t,Function_t*> 	funcMap=ReadFuncsFromDB(addrMap, typesMap);
 	std::map<db_id_t,Instruction_t*> 	insnMap=ReadInsnsFromDB(funcMap,addrMap);
 	ReadRelocsFromDB(insnMap);
 
@@ -236,7 +242,8 @@ std::string FileIR_t::LookupAssembly(Instruction_t *instr)
 
 std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB
 	(
-        	std::map<db_id_t,AddressID_t*> &addrMap
+        	std::map<db_id_t,AddressID_t*> &addrMap,
+			std::map<db_id_t,Type_t*> &typesMap
 	)
 {
 	std::map<db_id_t,Function_t*> idMap;
@@ -254,6 +261,7 @@ std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB
 		std::string name=dbintr->GetResultColumn("name");
 		int sfsize=atoi(dbintr->GetResultColumn("stack_frame_size").c_str());
 		int oasize=atoi(dbintr->GetResultColumn("out_args_region_size").c_str());
+		db_id_t function_type_id=atoi(dbintr->GetResultColumn("type_id").c_str());
 // postgresql encoding of boolean can be 'true', '1', 'T', 'y'
                 bool useFP=false;
 		const char *useFPstr= dbintr->GetResultColumn("use_frame_pointer").c_str();
@@ -265,7 +273,10 @@ std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB
 
 		db_id_t doipid=atoi(dbintr->GetResultColumn("doip_id").c_str());
 
-		Function_t *newfunc=new Function_t(fid,name,sfsize,oasize,useFP,NULL); 
+		FuncType_t* fnType = NULL;
+		if (typesMap.count(function_type_id) > 0)
+			fnType = dynamic_cast<FuncType_t*>(typesMap[function_type_id]);
+		Function_t *newfunc=new Function_t(fid,name,sfsize,oasize,useFP,fnType, NULL); 
 		entry_points[newfunc]=entry_point_id;
 		
 //std::cout<<"Found function "<<name<<"."<<std::endl;
@@ -445,12 +456,27 @@ void FileIR_t::WriteToDB()
 	dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->function_table_name    + string(" cascade;"));
 	dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->address_table_name     + string(" cascade;"));
 	dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->relocs_table_name     + string(" cascade;"));
+	dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->types_table_name     + string(" cascade;"));
 
 	/* and now that everything has an ID, let's write to the DB */
+
+	// write out the types
+	string q=string("");
+	for(std::set<Type_t*>::const_iterator t=types.begin(); t!=types.end(); ++t)
+	{
+		q+=(*t)->WriteToDB(fileptr,j); // @TODO: wtf is j?
+		if(q.size()>1024*1024)
+		{
+			dbintr->IssueQuery(q);
+			q=string("");
+		}
+	}
+	dbintr->IssueQuery(q);
+
 	bool withHeader;
 
 	withHeader = true;
-	string q=string("");
+	q=string("");
 	for(std::set<Function_t*>::const_iterator f=funcs.begin(); f!=funcs.end(); ++f)
 	{
 		q+=(*f)->WriteToDB(fileptr,j);
@@ -536,6 +562,7 @@ void FileIR_t::WriteToDB()
 			Relocation_t* reloc=*it;
 			r+=reloc->WriteToDB(fileptr,*i);
 		}
+
 		dbintr->IssueQuery(r);
 	}
 	dbintr->IssueQuery(q);
@@ -573,6 +600,9 @@ void FileIR_t::SetBaseIDS()
 	for(std::set<Relocation_t*>::const_iterator i=relocs.begin(); i!=relocs.end(); ++i)
 		if((*i)->GetBaseID()==NOT_IN_DATABASE)
 			(*i)->SetBaseID(j++);
+	for(std::set<Type_t*>::const_iterator i=types.begin(); i!=types.end(); ++i)
+		if((*i)->GetBaseID()==NOT_IN_DATABASE)
+			(*i)->SetBaseID(j++);
 }
 
 std::string Relocation_t::WriteToDB(File_t* fid, Instruction_t* myinsn)
@@ -648,3 +678,193 @@ void FileIR_t::SetArchitecture()
 }
 
 ArchitectureDescription_t* FileIR_t::archdesc=NULL;
+
+std::map<db_id_t, Type_t*> FileIR_t::ReadTypesFromDB (TypeSet_t& types)
+{
+	std::map<db_id_t, Type_t*> tMap;
+
+	// 3 pass algorithm. Must be done in this exact order as:
+	//      aggregrate type depend on basic types
+	//      function type depends on both aggregate and basic types
+	//
+	// pass 1: retrieve all basic types
+	// pass 2: retrieve all aggregate types
+	// pass 3: retrieve all function types
+	//
+
+	// pass 1, get all the basic types first
+//	std::string q= "select * from " + fileptr->types_table_name + " WHERE ref_type_id = -1 AND ref_type_id2 = -1 AND pos = -1 order by type; ";
+	std::string q= "select * from " + fileptr->types_table_name + " WHERE ref_type_id = -1 order by type; ";
+
+//	cout << "pass1: query: " << q;
+
+	dbintr->IssueQuery(q);
+
+	while(!dbintr->IsDone())
+	{
+//  type_id            integer,     
+//  type               integer DEFAULT 0,    -- possible types (0: UNKNOWN)
+//  name               text DEFAULT '',      -- string representation of the type
+//  ref_type_id        integer DEFAULT -1,   -- for aggregate types and func
+//  pos                integer DEFAULT -1,   -- for aggregate types, position in aggregate
+//  ref_type_id2       integer DEFAULT -1,   -- for func types
+//  doip_id            integer DEFAULT -1    -- the DOIP
+
+		db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str());
+		IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str());
+		std::string name=dbintr->GetResultColumn("name");
+		BasicType_t *t = NULL;	
+
+//		cout << "fileir::ReadFromDB(): pass1: " << name << endl;
+		switch(type) {
+				case T_UNKNOWN:
+				case T_VOID:
+				case T_NUMERIC:
+				case T_VARIADIC:
+				case T_INT:
+				case T_CHAR:
+				case T_FLOAT:
+				case T_DOUBLE:
+					t = new BasicType_t(tid, type, name);	
+					types.insert(t);
+					tMap[tid] = t;
+					break;
+
+				case T_POINTER:
+					// do nothing for pointers
+					break;
+
+				default:
+					cerr << "ReadTypesFromDB(): ERROR: pass 1 should only see basic types or pointer"  << endl;
+					assert(0); 
+					break;						
+		}
+
+		dbintr->MoveToNextRow();
+	} // end pass1
+
+	char query[2048];
+
+	// pass2 get pointers
+	sprintf(query,"select * from %s WHERE type = %d;", fileptr->types_table_name.c_str(), T_POINTER);
+	dbintr->IssueQuery(query);
+
+	while(!dbintr->IsDone())
+	{
+		db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str());
+		IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str());
+		std::string name=dbintr->GetResultColumn("name");
+		db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str());
+		cout << "fileir::ReadFromDB(): pass2 (pointers): " << name << endl;
+		switch(type) {
+				case T_POINTER:
+					{
+						cout << "   pointer type: ref1: " << ref1 << endl;
+						Type_t *referentType = NULL;
+						if (ref1 >= 0) 
+						{
+							assert(tMap.count(ref1) > 0);
+							referentType = tMap[ref1];
+						}
+						PointerType_t *ptr = new PointerType_t(tid, referentType, name);	
+						types.insert(ptr);
+						tMap[tid] = ptr;
+					}
+					break;
+
+				default:
+					cerr << "ReadTypesFromDB(): ERROR: pass3: unhandled type id = "  << type << endl;
+					assert(0); // not yet handled
+					break;						
+
+		}
+
+		dbintr->MoveToNextRow();
+	} // end pass3
+
+	// pass3 get all aggregates
+	sprintf(query,"select * from %s WHERE type = %d order by type_id, pos;", fileptr->types_table_name.c_str(), T_AGGREGATE);
+	dbintr->IssueQuery(query);
+
+	while(!dbintr->IsDone())
+	{
+		db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str());
+		IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str());
+		std::string name=dbintr->GetResultColumn("name");
+		db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str());
+		int pos=atoi(dbintr->GetResultColumn("pos").c_str());
+		AggregateType_t *agg = NULL;	
+		cout << "fileir::ReadFromDB(): pass3 (aggregates): " << name << endl;
+		switch(type) {
+				case T_AGGREGATE:
+					{
+						if (tMap.count(tid) == 0)  // new aggregate
+						{	
+		cout << "fileir::ReadFromDB(): pass3: new aggregate type: typeid: " << tid << " name: " << name << endl;
+							agg = new AggregateType_t(tid, name);	
+							types.insert(agg);
+							tMap[tid] = agg;
+						}
+						else
+							agg = dynamic_cast<AggregateType_t*>(tMap[tid]);
+
+						assert(agg);
+						// ref1 has the id of a basic type, look it up
+						Type_t *ref = tMap.at(ref1);
+						assert(ref);
+						agg->AddAggregatedType(ref, pos);
+					}
+					break;
+
+				default:
+					cerr << "ReadTypesFromDB(): ERROR: pass2: unhandled type id = "  << type << endl;
+					assert(0); // not yet handled
+					break;						
+
+		}
+
+		dbintr->MoveToNextRow();
+	} // end pass3
+
+	// pass4 get all functions
+	sprintf(query,"select * from %s WHERE type = %d;", fileptr->types_table_name.c_str(), T_FUNC);
+	dbintr->IssueQuery(query);
+
+	while(!dbintr->IsDone())
+	{
+		db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str());
+		IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str());
+		std::string name=dbintr->GetResultColumn("name");
+		db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str());
+		db_id_t ref2=atoi(dbintr->GetResultColumn("ref_type_id2").c_str());
+		FuncType_t *fn = NULL;	
+
+		switch(type) {
+				case T_FUNC:
+					{
+					assert(tMap.count(tid) == 0);
+
+					fn = new FuncType_t(tid, name);	
+					types.insert(fn);
+					tMap[tid] = fn;
+					assert(tMap.at(ref1)); // return type
+					assert(tMap.at(ref2)); // argument type (which is an aggregate)
+					fn->SetReturnType(tMap[ref1]);
+					AggregateType_t *args = dynamic_cast<AggregateType_t*>(tMap[ref2]);
+					assert(args);
+					fn->SetArgumentsType(args);
+					}
+					break;
+
+				default:
+					cerr << "ReadTypesFromDB(): ERROR: pass4: unhandled type id = "  << type << endl;
+					assert(0); // not yet handled
+					break;						
+
+		}
+
+		dbintr->MoveToNextRow();
+	} // end pass4
+
+	return tMap;
+}
diff --git a/libIRDB/src/core/function.cpp b/libIRDB/src/core/function.cpp
index 87c17264140044b8b7d823fc14e2b8f0dc731533..44b505e5b31326bd19e37612783fae97cb0ee0ef 100644
--- a/libIRDB/src/core/function.cpp
+++ b/libIRDB/src/core/function.cpp
@@ -21,25 +21,19 @@
 #include <all.hpp>
 #include <utils.hpp>
 #include <stdlib.h>
+
 using namespace libIRDB;
 using namespace std;
 
-
-
-Function_t::Function_t(db_id_t id, std::string myname, int size, int oa_size, bool useFP, Instruction_t* entry)
+Function_t::Function_t(db_id_t id, std::string myname, int size, int oa_size, bool useFP, FuncType_t *fn_type, Instruction_t* entry)
 	: BaseObj_t(NULL), entry_point(entry)
 {
 	SetBaseID(id);
 	name=myname;
 	stack_frame_size=size;	
 	out_args_region_size=oa_size;
-        use_fp = useFP;
-}
-
-
-void Function_t::WriteToDB()
-{
-	assert(0);
+    use_fp = useFP;
+	function_type = fn_type;
 }
 
 string Function_t::WriteToDB(File_t *fid, db_id_t newid)
@@ -53,8 +47,12 @@ string Function_t::WriteToDB(File_t *fid, db_id_t newid)
 	if(GetBaseID()==NOT_IN_DATABASE)
 		SetBaseID(newid);
 
+    int function_type_id = NOT_IN_DATABASE;
+	if (GetType())
+		function_type_id = GetType()->GetBaseID();	 
+
 	string q=string("insert into ")+fid->function_table_name + 
-		string(" (function_id, entry_point_id, name, stack_frame_size, out_args_region_size, use_frame_pointer, doip_id) ")+
+		string(" (function_id, entry_point_id, name, stack_frame_size, out_args_region_size, use_frame_pointer, type_id, doip_id) ")+
 		string(" VALUES (") + 
 		string("'") + to_string(GetBaseID()) 		  + string("', ") + 
 		string("'") + to_string(entryid) 		  + string("', ") + 
@@ -62,6 +60,7 @@ string Function_t::WriteToDB(File_t *fid, db_id_t newid)
 		string("'") + to_string(stack_frame_size) 	  + string("', ") + 
 	        string("'") + to_string(out_args_region_size) 	  + string("', ") + 
 	        string("'") + to_string(use_fp) 		  + string("', ") + 
+	        string("'") + to_string(function_type_id) 		  + string("', ") + 
 		string("'") + to_string(GetDoipID()) 		  + string("') ; ") ;
 
 	return q;
diff --git a/libIRDB/src/core/type.cpp b/libIRDB/src/core/type.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7171bae6c90738d8c7adb04c39e933c2a83bb44
--- /dev/null
+++ b/libIRDB/src/core/type.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014 - Zephyr Software LLC
+ *
+ * This file may be used and modified for non-commercial purposes as long as
+ * all copyright, permission, and nonwarranty notices are preserved.
+ * Redistribution is prohibited without prior written consent from Zephyr
+ * Software.
+ *
+ * Please contact the authors for restrictions applying to commercial use.
+ *
+ * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Zephyr Software
+ * e-mail: jwd@zephyr-software.com
+ * URL   : http://www.zephyr-software.com/
+ *
+ */
+
+#include "all.hpp" 
+#include <utils.hpp>
+
+using namespace std;
+using namespace libIRDB;
+
+bool BasicType_t::IsNumericType() const
+{
+		int type = GetTypeID();
+		return type == T_NUMERIC || type == T_INT || type == T_FLOAT || type == T_DOUBLE || type == T_CHAR;
+}
+
+/*
+CREATE TABLE #TYP#
+(
+  type_id            integer,     
+  type               integer DEFAULT 0,    -- possible types (0: UNKNOWN)
+  name               text DEFAULT '',      -- string representation of the type
+  ref_type_id        integer DEFAULT -1,   -- for aggregate types
+  pos                integer DEFAULT -1,   -- for aggregate types, position in aggregate
+  ref_type_id2       integer DEFAULT -1,   -- for func types
+  doip_id            integer DEFAULT -1    -- the DOIP
+);
+*/
+
+string BasicType_t::WriteToDB(File_t *fid, db_id_t newid)
+{
+	assert(fid);
+
+//	if(GetBaseID()==NOT_IN_DATABASE)
+//		SetBaseID(newid);
+
+	string q=string("insert into ")+fid->types_table_name + 
+		string(" (type_id, type, name, ref_type_id, pos, ref_type_id2) ")+
+		string(" VALUES (") + 
+		string("'") + to_string(GetBaseID()) + string("', ") + 
+		string("'") + to_string(GetTypeID()) + string("', ") + 
+		string("'") + GetName()              + string("','-1','-1','-1') ; ") ;
+
+//    cout << "BasicType_t::WriteToDB(): " << q << endl;
+	return q;
+}
+
+string PointerType_t::WriteToDB(File_t *fid, db_id_t newid)
+{
+	assert(fid && GetReferentType());
+	string q=string("insert into ")+fid->types_table_name + 
+		string(" (type_id, type, name, ref_type_id,pos,ref_type_id2) ")+
+		string(" VALUES (") + 
+		string("'") + to_string(GetBaseID())                    + string("', ") + 
+		string("'") + to_string(GetTypeID())                    + string("', ") + 
+		string("'") + GetName()                                 + string("', ") +
+		string("'") + to_string(GetReferentType()->GetBaseID()) + 
+		string("','-1','-1') ; ") ;
+
+//    cout << "PointerType_t::WriteToDB(): " << q << endl;
+	return q;
+}
+
+string AggregateType_t::WriteToDB(File_t *fid, db_id_t newid)
+{
+	assert(fid);
+	assert(GetNumAggregatedTypes() > 0);
+
+	string q;
+
+	for (int i = 0; i < GetNumAggregatedTypes(); ++i)
+	{
+		Type_t* t = GetAggregatedType(i);
+		q+=string("insert into ")+fid->types_table_name + 
+			string(" (type_id, type, name, ref_type_id, pos,ref_type_id2) ")+
+			string(" VALUES (") + 
+			string("'") + to_string(GetBaseID())                    + string("', ") + 
+			string("'") + to_string(GetTypeID())                    + string("', ") + 
+			string("'") + GetName()                                 + string("', ") +
+			string("'") + to_string(t->GetBaseID()) + string("', ") +
+			string("'") + to_string(i) +
+			string("','-1') ; ") ;
+	}
+
+ //   cout << "AggregatedType_t::WriteToDB(): " << q << endl;
+	return q;
+}
+
+void AggregateType_t::AddAggregatedType(Type_t *t, int pos)
+{
+	refTypes.push_back(t);
+
+//	cout << "AggregatedType_t::AddAggregatedType(): new size: " << refTypes.size() << endl;
+}
+
+/*
+CREATE TABLE #TYP#
+(
+  type_id            integer,     
+  type               integer DEFAULT 0,    -- possible types (0: UNKNOWN)
+  name               text DEFAULT '',      -- string representation of the type
+  ref_type_id        integer DEFAULT -1,   -- for aggregate types
+  pos                integer DEFAULT -1,   -- for aggregate types, position in aggregate
+  ref_type_id2       integer DEFAULT -1,   -- for func types
+  doip_id            integer DEFAULT -1    -- the DOIP
+);
+*/
+string FuncType_t::WriteToDB(File_t *fid, db_id_t newid)
+{
+	assert(fid);
+	assert(GetReturnType());
+	assert(GetArgumentsType());
+	string q=string("insert into ")+fid->types_table_name + 
+		string(" (type_id, type, name, ref_type_id, ref_type_id2,pos) ")+
+		string(" VALUES (") + 
+		string("'") + to_string(GetBaseID())                    + string("', ") + 
+		string("'") + to_string(GetTypeID())                    + string("', ") + 
+		string("'") + GetName()                                 + string("', ") +
+		string("'") + to_string(GetReturnType()->GetBaseID()) + string("', ") +
+		string("'") + to_string(GetArgumentsType()->GetBaseID()) + 
+		string("','-1') ; ") ;
+
+//  cout << "FuncType_t::WriteToDB(): " << q << endl;
+	return q;
+}
+
diff --git a/libIRDB/src/core/variantid.cpp b/libIRDB/src/core/variantid.cpp
index 9de133fb3953457b9b137b661bdad163c0170572..b7d9cd640d2ad233ab032a0909650ad6b79b279b 100644
--- a/libIRDB/src/core/variantid.cpp
+++ b/libIRDB/src/core/variantid.cpp
@@ -186,6 +186,7 @@ File_t* VariantID_t::CloneFile(File_t* fptr)
 	std::string ftn="ftnfid"+to_string(newfid);
 	std::string itn="itnfid"+to_string(newfid);
 	std::string rtn="rtnfid"+to_string(newfid);
+	std::string typ="typfid"+to_string(newfid);
 
 	q ="update file_info set address_table_name='";
 	q+=atn;
@@ -195,6 +196,8 @@ File_t* VariantID_t::CloneFile(File_t* fptr)
 	q+=itn;
 	q+="', relocs_table_name='";
 	q+=rtn;
+	q+="', types_table_name='";
+	q+=typ;
 	q+="' where file_id='";
 	q+=to_string(newfid);
 	q+="' ; ";
@@ -202,7 +205,7 @@ File_t* VariantID_t::CloneFile(File_t* fptr)
         dbintr->IssueQuery(q);
 
 	File_t* newfile=new File_t(newfid, fptr->orig_fid, fptr->url, fptr->hash, fptr->arch, fptr->elfoid, 
-					atn, ftn, itn, rtn, fptr->GetDoipID());
+					atn, ftn, itn, rtn, typ, fptr->GetDoipID());
 
 	newfile->CreateTables();
 
@@ -227,6 +230,10 @@ File_t* VariantID_t::CloneFile(File_t* fptr)
         q+=" ; ";
         dbintr->IssueQuery(q);
 
+        q="drop table ";
+        q+=typ;
+        q+=" ; ";
+        dbintr->IssueQuery(q);
 
         // next issue SQL to clone each table
         q="select * into ";
@@ -257,6 +264,13 @@ File_t* VariantID_t::CloneFile(File_t* fptr)
         q+=" ;";
         dbintr->IssueQuery(q);
 
+        q="select * into ";
+        q+=typ;
+        q+=" from ";
+        q+=fptr->types_table_name;
+        q+=" ;";
+        dbintr->IssueQuery(q);
+
 	// update the variant dependency table to represent the deep clone 
 
 	// update the variant dependency table to represent the deep clone 
@@ -339,7 +353,7 @@ void VariantID_t::ReadFilesFromDB()
 {
 
 	std::string q= "select  file_info.orig_file_id, file_info.address_table_name, file_info.instruction_table_name, "
-		" file_info.function_table_name, file_info.relocs_table_name, file_info.file_id, file_info.url, file_info.hash,"
+		" file_info.function_table_name, file_info.relocs_table_name, file_info.types_table_name, file_info.file_id, file_info.url, file_info.hash,"
 		" file_info.arch, file_info.type, file_info.elfoid, file_info.doip_id "
 		" from file_info,variant_dependency "
 		" where variant_dependency.variant_id = '" + to_string(GetBaseID()) + "' AND "
@@ -362,13 +376,14 @@ void VariantID_t::ReadFilesFromDB()
         	std::string ftn=(BaseObj_t::dbintr->GetResultColumn("function_table_name"));
         	std::string itn=(BaseObj_t::dbintr->GetResultColumn("instruction_table_name"));
         	std::string rtn=(BaseObj_t::dbintr->GetResultColumn("relocs_table_name"));
+        	std::string typ=(BaseObj_t::dbintr->GetResultColumn("types_table_name"));
 
 
 
-		File_t *newfile=new File_t(file_id,orig_fid,url,hash,type,oid,atn,ftn,itn,rtn,doipid);
-
-//std::cout<<"Found file "<<file_id<<"."<<std::endl;
+		File_t *newfile=new File_t(file_id,orig_fid,url,hash,type,oid,atn,ftn,itn,rtn,typ,doipid);
 
+std::cout<<"Found file "<<file_id<<"."<<std::endl;
+std::cout<<"  atn: " << atn << " ftn: " << ftn << " rtn: " << rtn << " typ: " << typ << std::endl;
 
 		files.insert(newfile);
 
diff --git a/libMEDSannotation/include/MEDS_AnnotationBase.hpp b/libMEDSannotation/include/MEDS_AnnotationBase.hpp
index 60a6832156c2aa4f69f0a652d83b4cd050e49911..c60c0bc94e976b3f62861557abf387d2132e1c0c 100644
--- a/libMEDSannotation/include/MEDS_AnnotationBase.hpp
+++ b/libMEDSannotation/include/MEDS_AnnotationBase.hpp
@@ -55,6 +55,7 @@ class MEDS_AnnotationBase
 		virtual void init() { m_isValid = false; m_size = 0; }
 
 		virtual bool isFuncAnnotation() const { return false; } // false by default 
+		virtual bool isFuncPrototypeAnnotation() const { return false; } // false by default 
 
 	protected:
 		bool m_isValid;
diff --git a/libMEDSannotation/include/MEDS_AnnotationParser.hpp b/libMEDSannotation/include/MEDS_AnnotationParser.hpp
index 2eca52662791ee563d7864333899beeaf7c167cc..15b054224f6871a36fbb13a74661bfd318e59fb8 100644
--- a/libMEDSannotation/include/MEDS_AnnotationParser.hpp
+++ b/libMEDSannotation/include/MEDS_AnnotationParser.hpp
@@ -45,10 +45,12 @@ class MEDS_AnnotationParser
 		void parseFile(const std::string &);	 /* pass filename */
 		MEDS_Annotations_t &         getAnnotations() { return m_annotations; }
 		MEDS_FuncAnnotations_t & getFuncAnnotations() { return m_func_annotations; }
+		MEDS_Annotations_t & getFuncPrototypeAnnotations() { return m_func_prototype_annotations; }
 
 	private:
 		MEDS_Annotations_t m_annotations;
 		MEDS_FuncAnnotations_t m_func_annotations;
+		MEDS_Annotations_t m_func_prototype_annotations;
 };
 
 }
diff --git a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
index 781042aeac5a27e9884df5030ae85f3c568e9f91..c2c246ff7319c20cdc34baebc0bae764b50759dc 100644
--- a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
+++ b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp
@@ -30,6 +30,9 @@
 namespace MEDS_Annotation 
 {
 
+// These strings must match those emitted by MEDS in the information annotation file exactly
+#define MEDS_ANNOT_FUNC        "FUNC"
+
 using namespace std;
 using namespace MEDS_Annotation;
 
@@ -42,7 +45,7 @@ class MEDS_FuncAnnotation : public MEDS_AnnotationBase
 		MEDS_FuncAnnotation() {}
 		virtual ~MEDS_FuncAnnotation(){}
 
-                virtual bool isFuncAnnotation() const { return true; } 
+		virtual bool isFuncAnnotation() const { return true; } 
 
 		virtual string getFuncName() const { return m_func_name; }
 		virtual void setFuncName(const string &p_func_name) { m_func_name=p_func_name; }
diff --git a/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp b/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..75055f29aaab46e2ea1ed9dc6257b61a8cef2f24
--- /dev/null
+++ b/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 - Zephyr Software LLC
+ *
+ * This file may be used and modified for non-commercial purposes as long as
+ * all copyright, permission, and nonwarranty notices are preserved.
+ * Redistribution is prohibited without prior written consent from Zephyr
+ * Software.
+ *
+ * Please contact the authors for restrictions applying to commercial use.
+ *
+ * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Zephyr Software
+ * e-mail: jwd@zephyr-software.com
+ * URL   : http://www.zephyr-software.com/
+ *
+ */
+
+#ifndef _MEDS_FUNCPROTOTYPEANNOTATION_H_
+#define _MEDS_FUNCPROTOTYPEANNOTATION_H_
+
+#include <string>
+#include <vector>
+#include "VirtualOffset.hpp"
+#include "MEDS_Register.hpp"
+#include "MEDS_FuncAnnotation.hpp"
+
+
+namespace MEDS_Annotation 
+{
+
+using namespace std;
+using namespace MEDS_Annotation;
+
+//
+// Must match STARS type system
+//    UNINIT = 0,      // Operand type not yet analyzed; type lattice top
+//    NUMERIC = 1,     // Definitely holds non-pointer value (char, int, etc.)
+//    CODEPTR = 2,     // Definitely holds a code address; mmStrata considers this NUMERIC
+//    POINTER = 4,     // Definitely holds a data address
+//    STACKPTR = 8,    // Definitely holds a stack data address (refinement of POINTER)
+//    GLOBALPTR = 16,   // Definitely holds a global static data address (refinement of POINTER)
+//    HEAPPTR = 32,     // Definitely holds a heap data address (refinement of POINTER)
+//    PTROFFSET = 64,   // Offset from a pointer, e.g. a difference between two pointers
+//    NEGATEDPTR = 65,  // Temporary ptr arithmetic leaves NUMERIC-POINTER; should get +POINTER later to make PTROFFSET
+//    UNKNOWN = 96,     // Might hold an address, might not (Bad!); type lattice bottom
+//
+typedef enum {
+	MEDS_TYPE_UNINIT = 0,
+	MEDS_TYPE_NUMERIC = 1, 
+	MEDS_TYPE_CODEPTR = 2,
+	MEDS_TYPE_POINTER = 4, 
+	MEDS_TYPE_STACKPTR = 8, 
+	MEDS_TYPE_GLOBALPTR = 16,
+	MEDS_TYPE_HEAPPTR = 32, 
+	MEDS_TYPE_PTROFFSET = 64,
+	MEDS_TYPE_NEGATEDPTR = 65,
+	MEDS_TYPE_UNKNOWN = 96     
+} MEDS_ArgType;
+
+// wrapper class around MEDS typing system
+class MEDS_Arg {
+	public:
+		MEDS_Arg() { m_type = MEDS_TYPE_UNKNOWN; m_reg = Register::UNKNOWN; }
+		MEDS_Arg(int p_type, Register::RegisterName p_reg = Register::UNKNOWN) { m_type = (MEDS_ArgType) p_type; m_reg = p_reg; }
+		virtual ~MEDS_Arg() {}
+		bool isNumericType() { return m_type == MEDS_TYPE_NUMERIC; }
+		bool isPointerType() { 
+			return m_type == MEDS_TYPE_CODEPTR || m_type == MEDS_TYPE_POINTER || 
+				m_type == MEDS_TYPE_STACKPTR || m_type == MEDS_TYPE_GLOBALPTR || 
+				m_type == MEDS_TYPE_HEAPPTR;
+		}
+		bool isUnknownType() { return !(isNumericType() || isPointerType()); }
+
+	private:
+		MEDS_ArgType m_type;
+		Register::RegisterName m_reg;
+};
+
+//
+// Class to handle one function prototype annotations
+//
+class MEDS_FuncPrototypeAnnotation : public MEDS_FuncAnnotation
+{
+	public:
+		MEDS_FuncPrototypeAnnotation() { init(); };
+		MEDS_FuncPrototypeAnnotation(const string &p_rawLine);
+		virtual ~MEDS_FuncPrototypeAnnotation(){}
+		virtual bool isFuncPrototypeAnnotation() const { return true; }
+
+		virtual const string toString() const { return "func proto: " + m_rawInputLine; }
+
+		int getNumArgs() const { return m_arguments ? m_arguments->size() : 0; }
+		std::vector<MEDS_Arg>* getArgs() { return m_arguments; }
+		void addArg(MEDS_Arg p_arg) { 
+			if (!m_arguments) m_arguments = new std::vector<MEDS_Arg>;
+			m_arguments->push_back(p_arg);
+		}
+		void setReturnArg(MEDS_Arg p_arg) { 
+			if (!m_returnArg) m_returnArg = new MEDS_Arg;
+			*m_returnArg = p_arg; 
+		}
+		MEDS_Arg* getReturnArg() const { return m_returnArg; }
+
+	private:
+		void init();
+		void parse();
+
+	private:
+		string m_rawInputLine;
+
+		std::vector<MEDS_Arg> *m_arguments;
+		MEDS_Arg *m_returnArg;
+};
+
+}
+
+#endif
diff --git a/libMEDSannotation/src/MEDS_AnnotationParser.cpp b/libMEDSannotation/src/MEDS_AnnotationParser.cpp
index 8973cca67e6a7e8a434311882a6f7dfa81e8a77a..cf795d07d824f8aa82c05f43d9fc796570fcf4ef 100644
--- a/libMEDSannotation/src/MEDS_AnnotationParser.cpp
+++ b/libMEDSannotation/src/MEDS_AnnotationParser.cpp
@@ -24,6 +24,7 @@
 #include "MEDS_AnnotationParser.hpp"
 #include "MEDS_InstructionCheckAnnotation.hpp"
 #include "FuncExitAnnotation.hpp"
+#include "MEDS_FuncPrototypeAnnotation.hpp"
 #include "MEDS_SafeFuncAnnotation.hpp"
 #include "MEDS_ProblemFuncAnnotation.hpp"
 #include "MEDS_FRSafeAnnotation.hpp"
@@ -55,36 +56,48 @@ void MEDS_AnnotationParser::parseFile(istream &p_inputStream)
 
 	while (!p_inputStream.eof())
 	{
-	    	getline(p_inputStream, line);
+		getline(p_inputStream, line);
 		if (line.empty()) continue;
 
-cerr << "MEDS_AnnotationParser: line: " << line << endl;
+//cerr << "MEDS_AnnotationParser: line: " << line << endl;
 
 #define 	ADD_AND_CONTINUE_IF_VALID(type) \
 		{ \
 			type * annot=new type(line); \
 			if (annot->isValid()) \
 			{ \
-				if(annot->isFuncAnnotation()) \
+				if(annot->isFuncPrototypeAnnotation()) \
+				{ \
+					MEDS_FuncPrototypeAnnotation* fpannot=dynamic_cast<MEDS_FuncPrototypeAnnotation*>(annot); \
+					assert(fpannot); \
+					m_func_prototype_annotations.insert(MEDS_Annotations_Pair_t(annot->getVirtualOffset(), annot)); \
+					cout << "Insert func prototype annot: " << line << endl; \
+				} \
+				else if(annot->isFuncAnnotation()) \
 				{ \
 					MEDS_FuncAnnotation* fannot=dynamic_cast<MEDS_FuncAnnotation*>(annot); \
 					assert(fannot); \
 					string nam=fannot->getFuncName(); \
 					m_func_annotations.insert(MEDS_Annotations_FuncPair_t(nam, annot)); \
+					cout << "Insert func annot: " << line << endl; \
 				} \
 				else \
 				{ \
 					VirtualOffset vo = annot->getVirtualOffset(); \
 					m_annotations.insert(MEDS_Annotations_Pair_t(vo, annot)); \
+					cout << "Insert instruction annot: " << hex << vo.getOffset() << dec << " | " << line << endl; \
 				} \
 				continue; \
 			} \
 			else \
+			{ \
 				delete annot; \
+			} \
 		}
 
 		ADD_AND_CONTINUE_IF_VALID(MEDS_FPTRShadowAnnotation);
 		ADD_AND_CONTINUE_IF_VALID(MEDS_InstructionCheckAnnotation);
+		ADD_AND_CONTINUE_IF_VALID(MEDS_FuncPrototypeAnnotation);
 		ADD_AND_CONTINUE_IF_VALID(MEDS_SafeFuncAnnotation);
 		ADD_AND_CONTINUE_IF_VALID(MEDS_ProblemFuncAnnotation);
 		ADD_AND_CONTINUE_IF_VALID(MEDS_FRSafeAnnotation);
diff --git a/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp b/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp
index ef45af9f6fbc55d7bb87104691f39ae0395578c0..cc09d08991e3636142f8359d7487703d7e7998fd 100644
--- a/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp
+++ b/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp
@@ -68,8 +68,6 @@ MEDS_FPTRShadowAnnotation::MEDS_FPTRShadowAnnotation(const string &p_rawLine) :
 
 void MEDS_FPTRShadowAnnotation::parse()
 {
-	cerr << "MEDS_FPTRShadowAnnotation::parse(): enter" << endl;
-
 	if (m_rawInputLine.find(" INSTR ")==string::npos)
 		return;
 
diff --git a/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp b/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f4d939e7e8c6cd9b40f5bb867e7186e0e04125c7
--- /dev/null
+++ b/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2014, 2015 - Zephyr Software LLC
+ *
+ * This file may be used and modified for non-commercial purposes as long as
+ * all copyright, permission, and nonwarranty notices are preserved.
+ * Redistribution is prohibited without prior written consent from Zephyr
+ * Software.
+ *
+ * Please contact the authors for restrictions applying to commercial use.
+ *
+ * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author: Zephyr Software
+ * e-mail: jwd@zephyr-software.com
+ * URL   : http://www.zephyr-software.com/
+ *
+ */
+
+#include <stdlib.h>
+
+#include <iostream>
+#include <cstdio>
+#include <string>
+#include <string.h>
+
+#include "MEDS_Register.hpp"
+#include "MEDS_FuncPrototypeAnnotation.hpp"
+
+using namespace std;
+using namespace MEDS_Annotation;
+
+MEDS_FuncPrototypeAnnotation::MEDS_FuncPrototypeAnnotation(const string &p_rawLine)
+{
+	init();
+	m_rawInputLine=p_rawLine;
+	parse();
+}
+
+void MEDS_FuncPrototypeAnnotation::init()
+{
+	MEDS_AnnotationBase::init();
+	m_returnArg = NULL; 
+	m_arguments = NULL;
+}
+
+
+/*
+4046e0     71 FUNC INARGS    4  ARG0 1 ARG1 0 ARG2 0 ARG3 0
+404740    697 FUNC RETURNTYPE RAX 1
+*/
+void MEDS_FuncPrototypeAnnotation::parse()
+{
+	bool about_inargs = false;
+	bool about_return = false;
+
+	if (m_rawInputLine.find("FUNC ")==string::npos)
+		return;
+
+	if (m_rawInputLine.find("INARGS")!=string::npos)
+	{
+		about_inargs = true;
+	}
+
+	if (m_rawInputLine.find("RETURNTYPE")!=string::npos)
+	{
+		about_return = true;
+	}
+
+	if (!about_inargs && !about_return)
+		return;
+
+	// get offset
+	VirtualOffset vo(m_rawInputLine);
+	m_virtualOffset = vo;
+
+	if (about_inargs)
+	{
+// 4046e0     71 FUNC INARGS    4  ARG0 1 ARG1 0 ARG2 0 ARG3 0
+		int numargs = 0;
+		char buf[1024];
+		strcpy(buf, m_rawInputLine.c_str());
+		sscanf(buf, "%*x %*d %*s %*s %d %*s", &numargs);
+		for (int i = 0; i < numargs; ++i)
+		{
+			char arg[24];
+			sprintf(arg, "ARG%d", i);			
+			char *zarg = strstr(buf, arg);
+			if (zarg)
+			{
+				char tmp[1024];
+				int meds_type;
+				sscanf(tmp,"%*s %d %*s", &meds_type);
+				MEDS_Arg marg(meds_type);
+				addArg(marg);
+			}
+			else
+			{
+				setInvalid();
+				return;
+			}
+		}
+	}
+	else if (about_return)
+	{
+		// 404740    697 FUNC RETURNTYPE RAX 1
+		char regbuf[1024];
+		int meds_retType;
+		sscanf(m_rawInputLine.c_str(), "%*x %*d %*s %*s %s %d", regbuf, &meds_retType);
+		Register::RegisterName reg = Register::getRegister(regbuf);
+		MEDS_Arg marg(meds_retType, reg);
+		setReturnArg(marg);
+		cout << "   adding return argument: " << Register::toString(reg) << " type: " << meds_retType << endl;
+	}
+	else
+	{
+		assert(0);
+		return;
+	}			
+
+	setValid();
+}
+
diff --git a/libMEDSannotation/src/Makefile b/libMEDSannotation/src/Makefile
index ef6cfce3eba7fe102ee97e35ea95ae7f6c571126..4144a820560c3646549ab94223064ab8651939d3 100644
--- a/libMEDSannotation/src/Makefile
+++ b/libMEDSannotation/src/Makefile
@@ -1,7 +1,7 @@
 
 LIB=../lib/libMEDSannotation.a
 
-OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o MEDS_FRSafeAnnotation.o FuncExitAnnotation.o MEDS_FPTRShadowAnnotation.o
+OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o MEDS_FRSafeAnnotation.o FuncExitAnnotation.o MEDS_FPTRShadowAnnotation.o MEDS_FuncPrototypeAnnotation.o
 
 all: $(OBJS)
 
diff --git a/libMEDSannotation/src/VirtualOffset.cpp b/libMEDSannotation/src/VirtualOffset.cpp
index 917ba7fbc0bcfe50b0f0595a5a6c38b56479f6f1..fe1b616af57f126e851b733adb48f9804b4f9796 100644
--- a/libMEDSannotation/src/VirtualOffset.cpp
+++ b/libMEDSannotation/src/VirtualOffset.cpp
@@ -19,31 +19,34 @@
  */
 
 #include <cstdio>
+#include <iostream>
 
 #include "VirtualOffset.hpp"
 
+using namespace std;
 
 VirtualOffset::VirtualOffset()
 {
 	m_offset = 0;
+	m_libraryName = std::string(DEFAULT_LIBRARY_NAME);
 }
 
 VirtualOffset::VirtualOffset(const std::string &p_offset, const std::string &p_libraryName)
 {
-	sscanf(p_offset.c_str(), "%x", &m_offset);
+	sscanf(p_offset.c_str(), "%llx", &m_offset);
 	m_libraryName = p_libraryName;
 }
 
-
 VirtualOffset::VirtualOffset(const std::string &p_offset)
 {
-	sscanf(p_offset.c_str(), "%x", &m_offset);
+	sscanf(p_offset.c_str(), "%llx", &m_offset);
 	m_libraryName = std::string(DEFAULT_LIBRARY_NAME);
 }
 
 VirtualOffset::VirtualOffset(const int p_offset)
 {
 	m_offset = p_offset;
+	m_libraryName = std::string(DEFAULT_LIBRARY_NAME);
 }
 
 ApplicationAddress VirtualOffset::getOffset() const
@@ -56,8 +59,6 @@ std::string VirtualOffset::getLibraryName() const
 	return m_libraryName;
 }
 
-// /usr/include/c++/4.4/bits/stl_function.h:230: error: passing ‘const VirtualOffset’ as ‘this’ argument of ‘bool VirtualOffset::operator<(VirtualOffset)’ discards qualifiers
-
 bool VirtualOffset::operator < (const VirtualOffset &p_other) const
 {
 	if (&p_other == this) return false;
@@ -69,7 +70,9 @@ bool VirtualOffset::operator == (const VirtualOffset &p_other) const
 	if (&p_other == this) 
 		return true;
 	else
+	{
 		return (m_offset == p_other.getOffset() && m_libraryName == p_other.getLibraryName());
+	}
 }
 
 VirtualOffset& VirtualOffset::operator = (const VirtualOffset &p_other) 
diff --git a/libtransform/src/integertransform64.cpp b/libtransform/src/integertransform64.cpp
index a1a886f1550e962fc5d5ee2b84a6063b9e88dae4..634dae20458e56d0d6644847eb502cfe95c1f69f 100644
--- a/libtransform/src/integertransform64.cpp
+++ b/libtransform/src/integertransform64.cpp
@@ -127,6 +127,7 @@ int IntegerTransform64::execute()
 
 				if (getAnnotations()->count(vo) == 0)
 					continue;
+
 				std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret;
 				ret = getAnnotations()->equal_range(vo);
 				MEDS_InstructionCheckAnnotation annotation; 
diff --git a/tools/meds2pdb/Makefile b/tools/meds2pdb/Makefile
index 96eef39a6aa8901aefb5f38c095379f677f1da26..ee69c2a96fe009e1cba13e6e3da86f5faaaa744c 100644
--- a/tools/meds2pdb/Makefile
+++ b/tools/meds2pdb/Makefile
@@ -1,7 +1,7 @@
 CC=g++
 CFLAGS= -g
-INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include
-LIBS=-L../../lib -lxform -lBeaEngine_s_d -lpq -lpqxx
+INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include -I../../libMEDSannotation/include -I../../libIRDB/include
+LIBS=-L../../lib -lxform -lBeaEngine_s_d -lpq -lpqxx -lIRDB-core -lMEDSannotation
 
 .SUFFIXES: .o .c .cpp
 
diff --git a/tools/meds2pdb/meds2pdb.cpp b/tools/meds2pdb/meds2pdb.cpp
index e353f556b6b7242e50202b0a5ab3c0f87f270869..abb6cd9744b0fa95db4bb5591b950aa247978e09 100644
--- a/tools/meds2pdb/meds2pdb.cpp
+++ b/tools/meds2pdb/meds2pdb.cpp
@@ -25,15 +25,21 @@
 #include "rewriter.h"
 #include <pqxx/pqxx>
 #include <stdlib.h>
+#include "MEDS_AnnotationParser.hpp"
+#include "MEDS_FuncPrototypeAnnotation.hpp"
+#include "libIRDB-core.hpp"
 
 using namespace std;
 using namespace pqxx;
+using namespace libIRDB;
+using namespace MEDS_Annotation;
 
 #include <sstream>
 
 string functionTable;
 string addressTable;
 string instructionTable;
+string typesTable;
 
 static const int STRIDE = 50;
 
@@ -50,7 +56,6 @@ int next_address_id=0;
 
 map<app_iaddr_t,int> address_to_instructionid_map;
 
-
 // extract the file id from the md5 hash and the program name
 int get_file_id(char *progName, char *md5hash)
 {
@@ -272,35 +277,181 @@ void update_functions(int fileID, const vector<wahoo::Function*> &functions  )
   txn.commit(); // must commit o/w everything will be rolled back
 }
 
+/*
+	typedef enum IRDB_Type {
+		T_UNKNOWN = 0, T_NUMERIC = 1, T_POINTER = 2, 
+		T_INT = 10, T_CHAR = 11, T_FLOAT = 12, T_DOUBLE = 13,
+		T_VARIADIC = 20, T_TYPEDEF = 21, T_SUBTYPE = 22, 
+		T_FUNC = 100, T_AGGREGATE = 101
+	} IRDB_Type;
 
+// MUST MATCH typedef in type.hpp in libIRDB-core!!!
+*/
+
+static int getNewTypeId()
+{
+	// start at 5000 so we don't clash with predefined type ids
+	static int next_type_id=5000; 
+	return next_type_id++;
+}
+
+void populate_predefined_types()
+{
+	connection conn;
+	work txn(conn);
+	string q = "SET client_encoding='LATIN1';";
+	q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('0', '0','unknown','-1','-1');";
+	q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('1', '1','numeric','-1','-1');";
+	q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('2', '2','pointer','0','-1');";
+	txn.exec(q);
+	txn.commit(); 
+}
+
+void update_function_prototype(vector<wahoo::Function*> functions, char* annotFile)
+{
+	populate_predefined_types();
+
+	connection conn;
+	work txn(conn);
+	txn.exec("SET client_encoding='LATIN1';");
+
+	ifstream annotationif(annotFile, ifstream::in);
+	assert(annotationif.is_open());
+
+	MEDS_AnnotationParser annotationParser(annotationif);
+	MEDS_Annotations_t annotations = annotationParser.getFuncPrototypeAnnotations();
+
+	for (int i = 0; i < functions.size(); i += STRIDE)
+	{  
+		string q = "";
+		for (int j = i; j < i + STRIDE; ++j)
+		{
+			if (j >= functions.size()) break;
+			wahoo::Function *f = functions[j];
+      		int function_id = f->getFunctionID();
+			app_iaddr_t functionAddress = f->getAddress();
+			VirtualOffset vo(functionAddress);
+
+			MEDS_FuncPrototypeAnnotation* fn_prototype_annot = NULL; 
+			MEDS_FuncPrototypeAnnotation* fn_returntotype_annot = NULL; 
+			
+			std::vector<MEDS_Arg> *args = NULL;
+			MEDS_Arg *returnArg = NULL;
+
+			if (annotations.count(vo) > 0)
+			{
+				std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret; 
+				ret = annotations.equal_range(vo);
+				MEDS_FuncPrototypeAnnotation* p_annotation; 
+				for ( MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it)
+				{    
+					MEDS_AnnotationBase *base_type=(it->second);
+					p_annotation = dynamic_cast<MEDS_FuncPrototypeAnnotation*>(base_type);
+					if(p_annotation == NULL || !p_annotation->isValid()) 
+						continue;
+
+					if (p_annotation->getArgs())
+						args = p_annotation->getArgs();
+
+					if (p_annotation->getReturnArg())
+						returnArg = p_annotation->getReturnArg();
+				}    
+			}
+
+			// we should have 2 valid annotations per function
+			// one for the args, one for the return type
+			if (args)
+			{
+				// (1) define new aggregate type
+				// (2) define new return type
+				// (3) define new function type (combo (1) + (2))
+				int aggregate_type_id = getNewTypeId();
+				int func_type_id = getNewTypeId();
+				int basic_type_id = T_UNKNOWN;
+
+				for (int i = 0; i < args->size(); ++i)
+				{
+					if ((*args)[i].isNumericType())
+						basic_type_id = T_NUMERIC;
+					else if ((*args)[i].isPointerType())
+						basic_type_id = T_POINTER;
+
+					q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, pos) VALUES (";
+					q += txn.quote(my_to_string(aggregate_type_id)) + ",";
+					q += txn.quote(my_to_string(T_AGGREGATE)) + ",";
+					q += txn.quote(string(f->getName()) + "_arg" + my_to_string(i)) + ",";
+					q += txn.quote(my_to_string(basic_type_id)) + ",";
+					q += txn.quote(my_to_string(i)) + ");";
+				}
+
+				int return_type_id = T_UNKNOWN;
+				if (returnArg) 
+				{
+					if (returnArg->isNumericType())
+						return_type_id = T_NUMERIC;
+					else if (returnArg->isPointerType())
+						return_type_id = T_POINTER;
+					else
+						return_type_id = T_UNKNOWN;
+				}
+
+				// new function type id (ok to have duplicate prototypes)
+				// ref_type_id is the return type id
+				// ref_type_id2 is the type id for the aggregated type 
+				//     that describes the function arguments
+				q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) VALUES (";
+
+				q += txn.quote(my_to_string(func_type_id)) + ",";
+				q += txn.quote(my_to_string(T_FUNC)) + ",";
+				q += txn.quote(string(f->getName()) + "_func") + ",";
+				q += txn.quote(my_to_string(return_type_id)) + ",";
+				q += txn.quote(my_to_string(aggregate_type_id)) + ");";
+
+				// update the type id in the function table
+				q += "UPDATE " + functionTable;
+				q += " SET type_id = " + txn.quote(my_to_string(func_type_id));
+				q += " where function_id = " + txn.quote(my_to_string(function_id)) + "; ";
+			} // update function prototype
+		} // strided
+
+		if (q.size() > 0)
+			txn.exec(q);
+	} // outer loop
+
+ 	txn.commit(); // must commit o/w everything will be rolled back
+}
 
 int main(int argc, char **argv)
 {
-  	if (argc != 8)
+  	if (argc != 10)
   	{
-    		cerr << "usage: " << argv[0] << " <annotations file> <file id> <func tab name> <insn tab name> <addr tab name> <elf file> <STARSxref file>" << endl;
+    		cerr << "usage: " << argv[0] << " <annotations file> <info annotation file> <file id> <func tab name> <insn tab name> <addr tab name> <types tab name> <elf file> <STARSxref file>" << endl;
     		return 1;
   	}
 
   	char *annotFile = argv[1];
-  	char *fid=argv[2];
-  	char *myFunctionTable=argv[3];
-  	char *myInstructionTable=argv[4];
-  	char *myAddressTable=argv[5];
-  	char *elfFile=argv[6];
-  	char *starsXrefFile=argv[7];
+  	char *infoAnnotFile = argv[2];
+  	char *fid=argv[3];
+  	char *myFunctionTable=argv[4];
+  	char *myInstructionTable=argv[5];
+  	char *myAddressTable=argv[6];
+  	char *myTypesTable=argv[7];
+  	char *elfFile=argv[8];
+  	char *starsXrefFile=argv[9];
 
 	cout<<"Annotation file: "<< annotFile<<endl;
+	cout<<"Info annotation file: "<< infoAnnotFile<<endl;
 	cout<<"File ID: "<< fid<<endl;
 	cout<<"FTN:: "<< myFunctionTable<<endl;
 	cout<<"ITN: "<< myInstructionTable<<endl;
 	cout<<"ATN: "<< myAddressTable<<endl;
+	cout<<"TYP: "<< myTypesTable<<endl;
 
 	// set global vars for importing.
 	functionTable=myFunctionTable;
 	addressTable=myAddressTable;
 	instructionTable=myInstructionTable;
-
+	typesTable=myTypesTable;
 
   	Rewriter *rewriter = new Rewriter(elfFile, annotFile, starsXrefFile);
 
@@ -321,6 +472,7 @@ int main(int argc, char **argv)
   	insert_instructions(fileID, instructions, functions);
   	update_functions(fileID, functions);
 
-
+	// add function prototype information to the IRDB
+	update_function_prototype(functions, infoAnnotFile);
 	exit(0);
 }
diff --git a/tools/transforms/integertransformdriver.cpp b/tools/transforms/integertransformdriver.cpp
index b798974bcfe10227293fc240871774e8f40dc290..9df2a38f8ea5584ce2e5d0dae2c06848bafba8f9 100644
--- a/tools/transforms/integertransformdriver.cpp
+++ b/tools/transforms/integertransformdriver.cpp
@@ -180,6 +180,8 @@ int main(int argc, char **argv)
 
 			MEDS_Annotations_t annotations = annotationParser.getAnnotations();
 
+			cout << "integer transform driver: found " << annotations.size() << " annotaitons" << endl;
+
 			// do the transformation
 
 			libTransform::IntegerTransform *intxform = NULL;