/*
Copyright (C) 2006 - 2009 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef ANALYZER_20080630_H_
#define ANALYZER_20080630_H_

#include "DebuggerPluginInterface.h"
#include "AnalyzerInterface.h"
#include "Types.h"
#include "MemRegion.h"
#include <QSet>
#include <QMap>

class QMenu;

class Analyzer : public QObject, public AnalyzerInterface, public DebuggerPluginInterface {
	Q_OBJECT
	Q_INTERFACES(DebuggerPluginInterface)
	Q_CLASSINFO("author", "Evan Teran")
	Q_CLASSINFO("url", "http://www.codef00.com")

public:
	Analyzer();
	
public:
	virtual QMenu *menu(QWidget *parent = 0);
	
private:
	virtual void privateInit();
	virtual QWidget *optionsPage();
	
public:
	virtual void analyze(const MemRegion &region);
	virtual FunctionMap functions(const MemRegion &region) const;
	virtual AddressCatagory catagory(edb::address_t address) const;
	virtual void invalidateAnalysis(const MemRegion &region);
	virtual void invalidateAnalysis();

private:
	void bonusStackFramesHelper(Function &info) const;
	void bonusStackFrames(FunctionMap &results);
	void bonusSymbols(const MemRegion &region, FunctionMap &results);
	void bonusEntryPoint(const MemRegion &region, FunctionMap &results) const;
	void bonusMain(const MemRegion &region, FunctionMap &results) const;
	
private:
	void setFunctionTypesHelper(Function &info) const;
	void findFunctionCalls(const MemRegion &region, FunctionMap &results);
	void findCallsFromFunctions(const MemRegion &region, FunctionMap &results, QSet<edb::address_t> &walked_functions);
	void setFunctionTypes(FunctionMap &results);
	QByteArray md5Region(const MemRegion &region) const;
	int walkAllFunctions(FunctionMap &results, const MemRegion &region, QSet<edb::address_t> &walked_functions);
	void findFunctionEnd(Function &function, edb::address_t end_address, QSet<edb::address_t> &found_functions, const FunctionMap &results);
	bool findContainingFunction(edb::address_t address, Function &function) const;
	bool isInsideKnown(const MemRegion &region, edb::address_t address);
	bool isStackFrame(edb::address_t address) const;
	bool isThunk(edb::address_t address) const;
	void updateResultEntry(FunctionMap &results, edb::address_t address) const;
	edb::address_t moduleEntryPoint(const MemRegion &region) const;
	void fixOverlaps(FunctionMap &function_map);

Q_SIGNALS:
	void updateProgress(int);

public Q_SLOTS:
	void doMenu();
	
private:
	struct RegionInfo {
		FunctionMap	analysis;
		QByteArray	md5;
		bool		fuzzy;
	};
	
	QMenu						*m_Menu;
	QMap<MemRegion, RegionInfo>	m_AnalysisInfo;
};

#endif
