2009-09-13 18:02:46 -06:00
|
|
|
/*
|
2011-06-16 15:53:39 -06:00
|
|
|
https://github.com/peterix/dfhack
|
2012-09-29 20:03:37 -06:00
|
|
|
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
|
2009-09-13 18:02:46 -06:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any
|
|
|
|
damages arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any
|
|
|
|
purpose, including commercial applications, and to alter it and
|
|
|
|
redistribute it freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must
|
|
|
|
not claim that you wrote the original software. If you use this
|
|
|
|
software in a product, an acknowledgment in the product documentation
|
|
|
|
would be appreciated but is not required.
|
|
|
|
|
|
|
|
2. Altered source versions must be plainly marked as such, and
|
|
|
|
must not be misrepresented as being the original software.
|
|
|
|
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
|
|
distribution.
|
|
|
|
*/
|
|
|
|
|
2010-05-26 04:24:45 -06:00
|
|
|
#include "Internal.h"
|
2010-05-29 21:13:59 -06:00
|
|
|
|
2011-04-10 02:19:15 -06:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <map>
|
2011-08-16 15:39:18 -06:00
|
|
|
#include <iostream>
|
2011-04-10 02:19:15 -06:00
|
|
|
using namespace std;
|
|
|
|
|
2011-12-31 04:48:42 -07:00
|
|
|
#include "VersionInfoFactory.h"
|
|
|
|
#include "VersionInfo.h"
|
|
|
|
#include "Error.h"
|
2016-07-27 18:10:03 -06:00
|
|
|
#include "Memory.h"
|
2009-11-13 20:46:56 -07:00
|
|
|
using namespace DFHack;
|
2009-09-13 18:02:46 -06:00
|
|
|
|
2011-04-10 02:19:15 -06:00
|
|
|
#include <tinyxml.h>
|
|
|
|
|
2011-11-04 02:08:29 -06:00
|
|
|
VersionInfoFactory::VersionInfoFactory()
|
2011-02-24 03:43:33 -07:00
|
|
|
{
|
|
|
|
error = false;
|
|
|
|
}
|
|
|
|
|
2010-08-20 06:10:05 -06:00
|
|
|
VersionInfoFactory::~VersionInfoFactory()
|
2011-11-04 02:08:29 -06:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
2012-03-24 05:13:51 -06:00
|
|
|
|
2012-02-08 05:17:47 -07:00
|
|
|
void VersionInfoFactory::clear()
|
2010-02-25 05:41:57 -07:00
|
|
|
{
|
2010-08-22 17:29:55 -06:00
|
|
|
// for each stored version, delete
|
2012-01-31 09:55:38 -07:00
|
|
|
for(size_t i = 0; i < versions.size();i++)
|
2010-02-25 05:41:57 -07:00
|
|
|
{
|
2010-08-22 17:29:55 -06:00
|
|
|
delete versions[i];
|
2010-02-25 05:41:57 -07:00
|
|
|
}
|
2010-08-22 17:29:55 -06:00
|
|
|
versions.clear();
|
2011-11-04 02:08:29 -06:00
|
|
|
error = false;
|
2010-02-25 05:41:57 -07:00
|
|
|
}
|
|
|
|
|
2011-02-24 03:43:33 -07:00
|
|
|
VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash)
|
|
|
|
{
|
2012-01-31 09:55:38 -07:00
|
|
|
for(size_t i = 0; i < versions.size();i++)
|
2011-02-24 03:43:33 -07:00
|
|
|
{
|
2012-02-08 05:17:47 -07:00
|
|
|
if(versions[i]->hasMD5(hash))
|
|
|
|
return versions[i];
|
2011-02-24 03:43:33 -07:00
|
|
|
}
|
2011-03-30 21:39:12 -06:00
|
|
|
return 0;
|
2011-02-24 03:43:33 -07:00
|
|
|
}
|
|
|
|
|
2016-07-03 21:32:43 -06:00
|
|
|
VersionInfo * VersionInfoFactory::getVersionInfoByPETimestamp(uintptr_t timestamp)
|
2011-02-24 03:43:33 -07:00
|
|
|
{
|
2012-01-31 09:55:38 -07:00
|
|
|
for(size_t i = 0; i < versions.size();i++)
|
2011-02-24 03:43:33 -07:00
|
|
|
{
|
2012-02-08 05:17:47 -07:00
|
|
|
if(versions[i]->hasPE(timestamp))
|
|
|
|
return versions[i];
|
2011-02-24 03:43:33 -07:00
|
|
|
}
|
2011-03-30 21:39:12 -06:00
|
|
|
return 0;
|
2011-02-24 03:43:33 -07:00
|
|
|
}
|
|
|
|
|
2010-08-22 17:29:55 -06:00
|
|
|
void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2015-07-23 21:25:01 -06:00
|
|
|
bool no_vtables = getenv("DFHACK_NO_VTABLES");
|
|
|
|
bool no_globals = getenv("DFHACK_NO_GLOBALS");
|
2009-09-13 18:02:46 -06:00
|
|
|
TiXmlElement* pMemEntry;
|
2010-08-22 17:29:55 -06:00
|
|
|
const char *cstr_name = entry->Attribute("name");
|
|
|
|
if (!cstr_name)
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlBadAttribute("name");
|
2012-02-08 05:17:47 -07:00
|
|
|
|
2012-02-11 11:24:44 -07:00
|
|
|
const char *cstr_os = entry->Attribute("os-type");
|
2010-02-28 13:44:14 -07:00
|
|
|
if (!cstr_os)
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlBadAttribute("os-type");
|
2010-08-20 06:10:05 -06:00
|
|
|
|
2009-09-13 18:02:46 -06:00
|
|
|
string os = cstr_os;
|
2010-08-22 17:29:55 -06:00
|
|
|
mem->setVersion(cstr_name);
|
2010-08-20 06:10:05 -06:00
|
|
|
|
2009-09-13 18:02:46 -06:00
|
|
|
if(os == "windows")
|
|
|
|
{
|
2012-02-08 05:17:47 -07:00
|
|
|
mem->setOS(OS_WINDOWS);
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
|
|
|
else if(os == "linux")
|
|
|
|
{
|
2012-02-08 05:17:47 -07:00
|
|
|
mem->setOS(OS_LINUX);
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2012-06-14 11:42:06 -06:00
|
|
|
else if(os == "darwin")
|
|
|
|
{
|
|
|
|
mem->setOS(OS_APPLE);
|
|
|
|
}
|
2009-09-13 18:02:46 -06:00
|
|
|
else
|
|
|
|
{
|
2012-05-28 10:06:23 -06:00
|
|
|
return; // ignore it if it's invalid
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2016-07-27 18:10:03 -06:00
|
|
|
mem->setBase(DEFAULT_BASE_ADDR); // Memory.h
|
2010-08-20 06:10:05 -06:00
|
|
|
|
2009-09-13 18:02:46 -06:00
|
|
|
// process additional entries
|
|
|
|
//cout << "Entry " << cstr_version << " " << cstr_os << endl;
|
2017-11-24 23:10:47 -07:00
|
|
|
if (!entry->FirstChildElement()) {
|
|
|
|
cerr << "Empty symbol table: " << entry->Attribute("name") << endl;
|
|
|
|
return;
|
|
|
|
}
|
2009-09-13 18:02:46 -06:00
|
|
|
pMemEntry = entry->FirstChildElement()->ToElement();
|
|
|
|
for(;pMemEntry;pMemEntry=pMemEntry->NextSiblingElement())
|
|
|
|
{
|
|
|
|
string type, name, value;
|
2010-08-22 17:29:55 -06:00
|
|
|
const char *cstr_type = pMemEntry->Value();
|
2009-09-13 18:02:46 -06:00
|
|
|
type = cstr_type;
|
2012-04-15 04:32:25 -06:00
|
|
|
bool is_vtable = (type == "vtable-address");
|
|
|
|
if(is_vtable || type == "global-address")
|
2009-11-17 19:33:17 -07:00
|
|
|
{
|
2012-02-11 11:24:44 -07:00
|
|
|
const char *cstr_key = pMemEntry->Attribute("name");
|
2012-02-08 05:17:47 -07:00
|
|
|
if(!cstr_key)
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
|
2012-02-08 05:17:47 -07:00
|
|
|
const char *cstr_value = pMemEntry->Attribute("value");
|
|
|
|
if(!cstr_value)
|
2012-02-20 00:30:33 -07:00
|
|
|
{
|
|
|
|
cerr << "Dummy symbol table entry: " << cstr_key << endl;
|
|
|
|
continue;
|
|
|
|
}
|
2015-07-23 21:25:01 -06:00
|
|
|
if ((is_vtable && no_vtables) || (!is_vtable && no_globals))
|
|
|
|
continue;
|
2016-07-27 18:21:57 -06:00
|
|
|
#ifdef DFHACK64
|
|
|
|
uintptr_t addr = strtoull(cstr_value, 0, 0);
|
|
|
|
#else
|
2016-07-03 21:32:43 -06:00
|
|
|
uintptr_t addr = strtol(cstr_value, 0, 0);
|
2016-07-27 18:21:57 -06:00
|
|
|
#endif
|
2012-04-15 04:32:25 -06:00
|
|
|
if (is_vtable)
|
|
|
|
mem->setVTable(cstr_key, addr);
|
|
|
|
else
|
|
|
|
mem->setAddress(cstr_key, addr);
|
2010-08-20 06:10:05 -06:00
|
|
|
}
|
2012-02-11 11:24:44 -07:00
|
|
|
else if (type == "md5-hash")
|
2010-06-10 09:53:25 -06:00
|
|
|
{
|
2010-08-22 17:29:55 -06:00
|
|
|
const char *cstr_value = pMemEntry->Attribute("value");
|
2015-09-22 18:01:05 -06:00
|
|
|
fprintf(stderr, "%s: MD5: %s\n", cstr_name, cstr_value);
|
2010-08-22 17:29:55 -06:00
|
|
|
if(!cstr_value)
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
|
2012-02-08 05:17:47 -07:00
|
|
|
mem->addMD5(cstr_value);
|
2009-11-09 16:18:20 -07:00
|
|
|
}
|
2012-02-11 11:24:44 -07:00
|
|
|
else if (type == "binary-timestamp")
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2010-08-22 17:29:55 -06:00
|
|
|
const char *cstr_value = pMemEntry->Attribute("value");
|
2015-09-22 18:01:05 -06:00
|
|
|
fprintf(stderr, "%s: PE: %s\n", cstr_name, cstr_value);
|
2010-08-22 17:29:55 -06:00
|
|
|
if(!cstr_value)
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
|
2012-02-08 05:17:47 -07:00
|
|
|
mem->addPE(strtol(cstr_value, 0, 16));
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
|
|
|
} // for
|
|
|
|
} // method
|
|
|
|
|
|
|
|
// load the XML file with offsets
|
2010-08-20 06:10:05 -06:00
|
|
|
bool VersionInfoFactory::loadFile(string path_to_xml)
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
|
|
|
TiXmlDocument doc( path_to_xml.c_str() );
|
2011-08-16 15:39:18 -06:00
|
|
|
std::cerr << "Loading " << path_to_xml << " ... ";
|
2010-02-28 13:44:14 -07:00
|
|
|
//bool loadOkay = doc.LoadFile();
|
|
|
|
if (!doc.LoadFile())
|
|
|
|
{
|
|
|
|
error = true;
|
2011-08-16 15:39:18 -06:00
|
|
|
cerr << "failed!\n";
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlParse(doc.ErrorDesc(), doc.ErrorId(), doc.ErrorRow(), doc.ErrorCol());
|
2010-02-28 13:44:14 -07:00
|
|
|
}
|
2011-08-16 15:39:18 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cerr << "OK\n";
|
|
|
|
}
|
2009-11-17 19:33:17 -07:00
|
|
|
TiXmlHandle hDoc(&doc);
|
2009-09-15 14:46:45 -06:00
|
|
|
TiXmlElement* pElem;
|
|
|
|
TiXmlHandle hRoot(0);
|
2010-02-28 13:44:14 -07:00
|
|
|
|
|
|
|
// block: name
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2010-02-28 13:44:14 -07:00
|
|
|
pElem=hDoc.FirstChildElement().Element();
|
|
|
|
// should always have a valid root but handle gracefully if it does
|
|
|
|
if (!pElem)
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2010-02-28 13:44:14 -07:00
|
|
|
error = true;
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlNoRoot();
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2010-02-28 13:44:14 -07:00
|
|
|
string m_name=pElem->Value();
|
2012-02-11 11:24:44 -07:00
|
|
|
if(m_name != "data-definition")
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2010-02-28 13:44:14 -07:00
|
|
|
error = true;
|
2012-03-24 05:13:51 -06:00
|
|
|
throw Error::SymbolsXmlNoRoot();
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2010-02-28 13:44:14 -07:00
|
|
|
// save this for later
|
|
|
|
hRoot=TiXmlHandle(pElem);
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2010-02-28 13:44:14 -07:00
|
|
|
// transform elements
|
2009-09-13 18:02:46 -06:00
|
|
|
{
|
2012-02-08 05:17:47 -07:00
|
|
|
clear();
|
|
|
|
// For each version
|
2012-02-11 11:24:44 -07:00
|
|
|
TiXmlElement * pMemInfo=hRoot.FirstChild( "symbol-table" ).Element();
|
|
|
|
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("symbol-table"))
|
2010-08-22 17:29:55 -06:00
|
|
|
{
|
|
|
|
const char *name = pMemInfo->Attribute("name");
|
|
|
|
if(name)
|
|
|
|
{
|
|
|
|
VersionInfo *version = new VersionInfo();
|
2012-02-08 05:17:47 -07:00
|
|
|
ParseVersion( pMemInfo , version );
|
2010-08-22 17:29:55 -06:00
|
|
|
versions.push_back(version);
|
|
|
|
}
|
2010-02-28 13:44:14 -07:00
|
|
|
}
|
2009-09-13 18:02:46 -06:00
|
|
|
}
|
2010-02-28 13:44:14 -07:00
|
|
|
error = false;
|
2012-02-11 11:24:44 -07:00
|
|
|
std::cerr << "Loaded " << versions.size() << " DF symbol tables." << std::endl;
|
2010-02-28 13:44:14 -07:00
|
|
|
return true;
|
2009-12-13 14:03:19 -07:00
|
|
|
}
|