mirror of
https://github.com/martravi/wiiqt6.git
synced 2024-11-21 21:19:15 +01:00
* add new program 'symbolizer' which has basically nothing to do with any of the rest of this stuff. but it is wii-related and using Qt, so it ends up here
git-svn-id: http://wiiqt.googlecode.com/svn/trunk@108 389f4c8b-5dfe-645f-db0e-df882bc27289
This commit is contained in:
parent
b703943847
commit
6e25705126
3
symbolizer/be.cpp
Normal file
3
symbolizer/be.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "be.h"
|
||||
|
||||
|
83
symbolizer/be.h
Normal file
83
symbolizer/be.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef BE_H
|
||||
#define BE_H
|
||||
|
||||
#include "../WiiQt/includes.h"
|
||||
|
||||
class be64
|
||||
{
|
||||
quint64 value; // in big endian;
|
||||
|
||||
public:
|
||||
explicit be64( quint64 v ): value( qFromBigEndian( v ) ) {}
|
||||
be64(): value( 0 ) {}
|
||||
|
||||
quint64 operator*()
|
||||
{
|
||||
return to_quint64();
|
||||
}
|
||||
|
||||
quint64 to_quint64() const
|
||||
{
|
||||
return qToBigEndian( value );
|
||||
}
|
||||
|
||||
be64 &operator = ( const quint64 &v )
|
||||
{
|
||||
value = qFromBigEndian( v );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class be32
|
||||
{
|
||||
quint32 value; // in big endian;
|
||||
|
||||
public:
|
||||
explicit be32( quint32 v ): value( qFromBigEndian( v ) ) {}
|
||||
be32(): value( 0 ) {}
|
||||
|
||||
quint32 operator*()
|
||||
{
|
||||
return to_quint32();
|
||||
}
|
||||
|
||||
quint32 to_quint32() const
|
||||
{
|
||||
return qToBigEndian( value );
|
||||
}
|
||||
|
||||
be32 &operator = ( const quint32 &v )
|
||||
{
|
||||
value = qFromBigEndian( v );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class be16
|
||||
{
|
||||
quint16 value; // in big endian;
|
||||
|
||||
public:
|
||||
explicit be16( quint16 v ): value( qFromBigEndian( v ) ) {}
|
||||
be16(): value( 0 ) {}
|
||||
|
||||
quint16 operator*()
|
||||
{
|
||||
return to_quint16();
|
||||
}
|
||||
|
||||
quint16 to_quint16() const
|
||||
{
|
||||
return qToBigEndian( value );
|
||||
}
|
||||
|
||||
be16 &operator = ( const quint16 &v )
|
||||
{
|
||||
value = qFromBigEndian( v );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // BE_H
|
84
symbolizer/dol.cpp
Normal file
84
symbolizer/dol.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "dol.h"
|
||||
|
||||
Dol::Dol( const QByteArray &dol ) : dh( NULL )
|
||||
{
|
||||
if( (quint32)dol.size() > sizeof( Dolheader ) )
|
||||
{
|
||||
Parse( dol );
|
||||
}
|
||||
}
|
||||
|
||||
bool Dol::Parse( const QByteArray &dol )
|
||||
{
|
||||
dh = NULL;
|
||||
text.clear();
|
||||
data.clear();
|
||||
|
||||
if( (quint32)dol.size() < sizeof( Dolheader ) )
|
||||
{
|
||||
WRN << "dol.size() < sizeof( Dolheader )";
|
||||
return false;
|
||||
}
|
||||
headerBuf = dol.left( sizeof( Dolheader ) );
|
||||
dh = reinterpret_cast< Dolheader * >( headerBuf.data() );
|
||||
if( !dh )
|
||||
{
|
||||
WRN << "!dh";
|
||||
return false;
|
||||
}
|
||||
//DBG << hex << (*(dh->entrypoint));
|
||||
|
||||
for( quint32 i = 0; i < 7; i ++ )
|
||||
{
|
||||
quint32 fileOff = (*(dh->offsetText[ i ] ) );
|
||||
quint32 len = (*(dh->sizeText[ i ] ) );
|
||||
quint32 addr = (*(dh->addressText[ i ] ) );
|
||||
if( !fileOff || !len || !addr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( fileOff + len > (quint32) dol.size() )
|
||||
{
|
||||
WRN << "text section is out of range:" << i << hex << fileOff << len;
|
||||
continue;
|
||||
}
|
||||
DolSection sec;
|
||||
sec.addr = addr;
|
||||
sec.data = dol.mid( fileOff, len );
|
||||
|
||||
text << sec;
|
||||
}
|
||||
|
||||
for( quint32 i = 0; i < 11; i ++ )
|
||||
{
|
||||
quint32 fileOff = (*(dh->offsetData[ i ] ) );
|
||||
quint32 len = (*(dh->sizeData[ i ] ) );
|
||||
quint32 addr = (*(dh->addressData[ i ] ) );
|
||||
if( !fileOff || !len || !addr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( fileOff + len > (quint32) dol.size() )
|
||||
{
|
||||
WRN << "data section is out of range:" << i << hex << fileOff << len;
|
||||
continue;
|
||||
}
|
||||
DolSection sec;
|
||||
sec.addr = addr;
|
||||
sec.data = dol.mid( fileOff, len );
|
||||
|
||||
data << sec;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Dol Dol::FakeDol( const QByteArray &mem, quint32 loadAddress )
|
||||
{
|
||||
Dol ret;
|
||||
DolSection sec;
|
||||
sec.addr = loadAddress;
|
||||
sec.data = mem;
|
||||
ret.text << sec;
|
||||
return ret;
|
||||
}
|
58
symbolizer/dol.h
Normal file
58
symbolizer/dol.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef DOL_H
|
||||
#define DOL_H
|
||||
|
||||
#include "../WiiQt/includes.h"
|
||||
#include "../WiiQt/tools.h"
|
||||
#include "be.h"
|
||||
|
||||
struct Dolheader
|
||||
{
|
||||
be32 offsetText[ 7 ]; // 0 // 0000
|
||||
be32 offsetData[ 11 ]; // 28 // 0012
|
||||
be32 addressText[ 7 ]; // 72 // 0048
|
||||
be32 addressData[ 11 ]; // 100 // 0064
|
||||
be32 sizeText[ 7 ]; // 144 // 0090
|
||||
be32 sizeData[ 11 ]; // 172 // 00ac
|
||||
be32 addressBSS; // 216 // 00d8
|
||||
be32 sizeBSS; // 220 // 00dc
|
||||
be32 entrypoint; // 224 // 00e0
|
||||
};
|
||||
|
||||
struct DolSection
|
||||
{
|
||||
quint32 addr;
|
||||
QByteArray data;
|
||||
DolSection() : addr( 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Dol
|
||||
{
|
||||
public:
|
||||
Dol( const QByteArray &dol = QByteArray() );
|
||||
|
||||
const Dolheader *Header() const { return dh; }
|
||||
|
||||
const QList< DolSection > &TextSections() const { return text; }
|
||||
const QList< DolSection > &DataSections() const { return data; }
|
||||
|
||||
bool Parse( const QByteArray &dol );
|
||||
|
||||
// create a fake dol from a memory buffer
|
||||
//! Header() will return NULL, and it will create only 1 text section with the load address and no data sections
|
||||
//! added just for convenience
|
||||
static Dol FakeDol( const QByteArray &mem, quint32 loadAddress = 0x80000000 );
|
||||
private:
|
||||
Dolheader *dh;
|
||||
QList< DolSection >text;
|
||||
QList< DolSection >data;
|
||||
|
||||
QByteArray headerBuf;
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // DOL_H
|
625
symbolizer/elfparser.cpp
Normal file
625
symbolizer/elfparser.cpp
Normal file
@ -0,0 +1,625 @@
|
||||
|
||||
#include "../WiiQt/tools.h"
|
||||
#include "elfparser.h"
|
||||
|
||||
ElfParser::ElfParser( const QString &stuff ) : error( false )
|
||||
{
|
||||
ParseText( stuff );
|
||||
}
|
||||
|
||||
bool ElfParser::ParseText( const QString &str )
|
||||
{
|
||||
QString fileName;
|
||||
QStringList fileLines;
|
||||
QMap< QString, QStringList >rawFiles;
|
||||
QMap< QString, QStringList >rawSections;
|
||||
QMap< QString, QStringList >rawSymbolTable;
|
||||
QStringList lines = str.split( '\n', QString::KeepEmptyParts );
|
||||
quint32 lineCnt = lines.size();
|
||||
for( quint32 i = 0; i < lineCnt; i++ )
|
||||
{
|
||||
const QString &line = lines.at( i );
|
||||
|
||||
|
||||
// start of a new file
|
||||
if( line.contains( ": file format" ) )
|
||||
{
|
||||
// add existing file to the list
|
||||
if( !fileName.isEmpty() && fileLines.size() )
|
||||
{
|
||||
rawFiles[ fileName ] = fileLines;
|
||||
}
|
||||
fileLines.clear();
|
||||
fileName.clear();
|
||||
fileName = line.left( line.indexOf( ": file format" ) );
|
||||
//qDebug() << "starting file" << fileName;
|
||||
|
||||
|
||||
// read symbol table
|
||||
for( ; i < lineCnt; i++ )
|
||||
{
|
||||
if( lines.at( i ).startsWith( "SYMBOL TABLE:" ) )
|
||||
{
|
||||
//qDebug() << "lines.at( i )" << lines.at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QStringList symbolListLines;
|
||||
for( ; i < lineCnt && !lines.at( i ).isEmpty(); i++ )
|
||||
{
|
||||
symbolListLines << lines.at( i );
|
||||
}
|
||||
rawSymbolTable[ fileName ] = symbolListLines;
|
||||
|
||||
|
||||
// read hex dump
|
||||
for( ; i < lineCnt; i++ )
|
||||
{
|
||||
if( lines.at( i ).startsWith( "Contents of section " ) )
|
||||
{
|
||||
//qDebug() << "lines.at( i )" << lines.at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList secList;
|
||||
for( ; i < lineCnt && !lines.at( i ).isEmpty(); i++ )
|
||||
{
|
||||
secList << lines.at( i );
|
||||
}
|
||||
//qDebug() << "section" << fileName << secList.size();
|
||||
rawSections[ fileName ] = secList;
|
||||
|
||||
for( ; i < lineCnt - 1; i++ )
|
||||
{
|
||||
if( lines.at( i + 1 ).startsWith( "Disassembly of section" ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( lines.at( i + 1 ).contains( ": file format" ) )// happens if the .o doesnt contain any rode
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( line.startsWith( "Disassembly of section" ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fileLines << line;
|
||||
}
|
||||
// add the last file in there
|
||||
if( !fileName.isEmpty() && fileLines.size() )
|
||||
{
|
||||
rawFiles[ fileName ] = fileLines;
|
||||
}
|
||||
|
||||
|
||||
QMapIterator< QString, QStringList > it( rawFiles );
|
||||
while( it.hasNext() )
|
||||
{
|
||||
it.next();
|
||||
|
||||
//qDebug() << "File:" << it.key() << it.value().size();
|
||||
File file( it.key() );
|
||||
if( !ParseFileText( it.value(), rawSections.find( it.key() ).value(), rawSymbolTable.find( it.key() ).value(), file ) )
|
||||
{
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
files << file;
|
||||
}
|
||||
|
||||
foreach( const File &f, files )
|
||||
{
|
||||
//qDebug() << f.Name();
|
||||
/*foreach( const Function &fun, f.Functions() )
|
||||
{
|
||||
//qDebug() << " " << fun.Name();
|
||||
foreach( const SymRef &ref, fun.References() )
|
||||
{
|
||||
//qDebug() << " " << hex << ref.off << ref.name;
|
||||
}
|
||||
}*/
|
||||
/*foreach( const SymAlias &alias, f.Aliases() )
|
||||
{
|
||||
qDebug() << " " << alias.name << alias.containerName;
|
||||
}*/
|
||||
}
|
||||
//exit( 0 );
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList< SymAlias > ElfParser::ParseSymbolTable( const QStringList &lines )
|
||||
{
|
||||
QList< SymAlias >ret;
|
||||
foreach( const QString &line, lines )
|
||||
{
|
||||
if( line.size() < 19 )// too small
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int tab = line.indexOf( '\t' );
|
||||
if( tab < 17 || line.size() < tab + 11 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool ok;
|
||||
SymAlias ref;
|
||||
ref.containerName = line.mid( 17, tab - 17 );
|
||||
|
||||
// filter out certain sections
|
||||
if( ref.containerName.startsWith( '*' )
|
||||
|| ref.containerName.startsWith( ".text" )
|
||||
|| ref.containerName.startsWith( ".debug" )
|
||||
|| ref.containerName.startsWith( ".comment" )
|
||||
|| ref.containerName.startsWith( ".gnu" )
|
||||
|| ref.containerName.startsWith( ".init" ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ref.offset = line.left( 8 ).toUInt( &ok, 16 );
|
||||
if( !ok )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ref.size = line.mid( tab + 1, 8 ).toUInt( &ok, 16 );
|
||||
if( !ok )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//qDebug() << line.mid( tab + 1, 8 );
|
||||
if( !ref.offset && !ref.size )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ref.name = line.mid( tab + 10 );
|
||||
//qDebug() << hex << QString( "%1" ).arg( ref.offset, 8, 16, QChar( QChar( '0' ) ) )
|
||||
// << ref.containerName
|
||||
// << QString( "%1" ).arg( ref.size, 8, 16, QChar( QChar( '0' ) ) )
|
||||
// << ref.name;
|
||||
ret << ref;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QMap< QString, QByteArray > ElfParser::ParseSectionText( const QStringList &list )
|
||||
{
|
||||
QMap< QString, QByteArray >ret;
|
||||
QMap< QString, QByteArray >ret2;
|
||||
QByteArray ba;
|
||||
QString name;
|
||||
for( quint32 i = 0; i < (quint32)list.size(); i++ )
|
||||
{
|
||||
const QString &line = list.at( i );
|
||||
if( line.startsWith( "Contents of section " ) )
|
||||
{
|
||||
if( !name.isEmpty() && ba.size() )
|
||||
{
|
||||
ret[ name ] = ba;
|
||||
}
|
||||
ba.clear();
|
||||
name = line.mid( 20 );
|
||||
name.resize( name.size() - 1 );
|
||||
//DBG << name;
|
||||
continue;
|
||||
}
|
||||
QString hexS = line.mid( 6, 35 );
|
||||
QByteArray hexA = hexS.toLatin1();
|
||||
hexA = QByteArray::fromHex( hexA );
|
||||
ba += hexA;
|
||||
}
|
||||
if( !name.isEmpty() && ba.size() )
|
||||
{
|
||||
ret[ name ] = ba;
|
||||
}
|
||||
|
||||
// remove unwanted sections
|
||||
QMapIterator< QString, QByteArray > it( ret );
|
||||
while( it.hasNext() )
|
||||
{
|
||||
it.next();
|
||||
if( !it.key().contains( ".text" )
|
||||
&& !it.key().startsWith( ".init" )
|
||||
&& !it.key().startsWith( ".ctors" )
|
||||
&& !it.key().startsWith( ".dtors" )
|
||||
&& !it.key().startsWith( ".debug" )
|
||||
&& !it.key().startsWith( ".comment" )
|
||||
&& !it.key().startsWith( "extab" ))
|
||||
{
|
||||
ret2[ it.key() ] = it.value();
|
||||
}
|
||||
}
|
||||
|
||||
// debug
|
||||
/*QMapIterator< QString, QByteArray > it2( ret2 );
|
||||
while( it2.hasNext() )
|
||||
{
|
||||
it2.next();
|
||||
qDebug() << it2.key();
|
||||
hexdump( it2.value() );
|
||||
}*/
|
||||
|
||||
return ret2;
|
||||
}
|
||||
|
||||
bool ElfParser::ParseFileText( const QStringList &strs, const QStringList §ionStrs, const QStringList &symbolStrs, ElfParser::File &file )
|
||||
{
|
||||
quint32 cnt = strs.size();
|
||||
|
||||
quint32 fOff = 0;
|
||||
quint32 fStart = 0;
|
||||
|
||||
QString name;
|
||||
QString pattern;
|
||||
QList< SymRef > refs;
|
||||
|
||||
//DBG << file.Name() << sectionStrs.size() << symbolStrs.size() << strs.size();
|
||||
QMap< QString, QByteArray >sections = ParseSectionText( sectionStrs );
|
||||
QList< SymAlias > aliases = ParseSymbolTable( symbolStrs );
|
||||
|
||||
|
||||
//DBG << file.Name() << sections.size() << aliases.size();
|
||||
|
||||
for( quint32 i = 0; i < cnt; i++ )
|
||||
{
|
||||
const QString &str = strs.at( i );
|
||||
/*if( name == "WII_Initialize" )
|
||||
{
|
||||
qDebug() << str;
|
||||
}*/
|
||||
|
||||
// start a new funciton
|
||||
if( IsFunctionStart( str, &fStart ) )
|
||||
{
|
||||
// add this function to the list
|
||||
if( !name.isEmpty() && fOff )
|
||||
{
|
||||
Function fun( name );
|
||||
fun.references = refs;
|
||||
fun.pattern = pattern;
|
||||
fun.file = &file;
|
||||
file.functions << fun;
|
||||
//qDebug() << "pattern:" << pattern;
|
||||
}
|
||||
//qDebug() << GetFunctionName( str );
|
||||
name = GetFunctionName( str );
|
||||
//DBG << name;
|
||||
if( fOff != (quint32)pattern.size() / 2 )
|
||||
{
|
||||
qDebug() << "size bad";
|
||||
exit( 0 );
|
||||
}
|
||||
fOff = 0;
|
||||
pattern.clear();
|
||||
refs.clear();
|
||||
|
||||
sections.remove( name );// remove functions from the section list
|
||||
continue;
|
||||
}
|
||||
if( name.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( IsBlank( str ) )
|
||||
{
|
||||
//qDebug() << str << "is blank";
|
||||
continue;
|
||||
}
|
||||
if( IsSymbolLine( str ) )
|
||||
{
|
||||
//qDebug() << str << "IsSymbolLine";
|
||||
continue;
|
||||
}
|
||||
QString hex;
|
||||
QString oper;
|
||||
QString symbol;
|
||||
quint32 refOff = 0xdeadbeef;
|
||||
|
||||
if( !ParseOpLine( str, hex, oper ) )
|
||||
{
|
||||
qDebug() << str << strs.at( i - 1 );
|
||||
return false;
|
||||
}
|
||||
/*if( name == "WII_Initialize" )
|
||||
{
|
||||
qDebug() << "hex" << hex;
|
||||
}*/
|
||||
|
||||
if( ( i < cnt - 1 ) && IsSymbolLine( strs.at( i + 1 ) ) )
|
||||
{
|
||||
SymRef::Type refType;
|
||||
symbol = GetNonOperRef( strs.at( i + 1 ), &refOff, &refType );
|
||||
|
||||
if( refOff < fStart )
|
||||
{
|
||||
WRN << "refOff < fStart" << str;
|
||||
return false;
|
||||
}
|
||||
SymRef ref;
|
||||
quint32 deRef;
|
||||
ref.name = DeReferenceSymbol( symbol, &deRef );
|
||||
ref.symOff = deRef;
|
||||
|
||||
switch( refType )
|
||||
{
|
||||
case SymRef::R_PPC_ADDR16_HI:
|
||||
case SymRef::R_PPC_ADDR16_LO:
|
||||
{
|
||||
hex[ 4 ] = '.';
|
||||
hex[ 5 ] = '.';
|
||||
hex[ 6 ] = '.';
|
||||
hex[ 7 ] = '.';
|
||||
}
|
||||
break;
|
||||
case SymRef::R_PPC_REL24:
|
||||
case SymRef::R_PPC_EMB_SDA21:
|
||||
{
|
||||
hex[ 1 ] = '.';
|
||||
hex[ 2 ] = '.';
|
||||
hex[ 3 ] = '.';
|
||||
hex[ 4 ] = '.';
|
||||
hex[ 5 ] = '.';
|
||||
hex[ 6 ] = '.';
|
||||
hex[ 7 ] = '.';
|
||||
}
|
||||
break;
|
||||
case SymRef::R_PPC_SDAREL16:
|
||||
{
|
||||
hex = "........";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WRN << "unhandled reference type";
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
ref.type = refType;
|
||||
ref.off = refOff - fStart;
|
||||
refs << ref;
|
||||
if( ref.off & 0xff000000 )
|
||||
{
|
||||
qDebug() << "ref.off is busted 1" << name << str;
|
||||
|
||||
qDebug() << ::hex << refOff << fStart;
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
else if( OpNeedsWildCard( oper ) )
|
||||
{
|
||||
//DBG << "bl called without symbol reference\n" << str;
|
||||
hex = "........";
|
||||
if( symbol.isEmpty() )
|
||||
{
|
||||
symbol = GetOpersymRef( str );
|
||||
}
|
||||
SymRef ref;
|
||||
ref.name = symbol;
|
||||
ref.off = (quint32)(pattern.size());
|
||||
ref.type = SymRef::R_PPC_REL24;
|
||||
refs << ref;
|
||||
|
||||
if( ref.off & 0xff000000 )
|
||||
{
|
||||
DBG << "ref.off is busted 2" << name << str;
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
pattern += hex.toUpper();
|
||||
/*if( name == "WII_Initialize" )
|
||||
{
|
||||
qDebug() << "hex" << pattern;
|
||||
}*/
|
||||
fOff += 4;
|
||||
}
|
||||
if( !name.isEmpty() )
|
||||
{
|
||||
Function fun( name );
|
||||
fun.references = refs;
|
||||
fun.pattern = pattern;
|
||||
fun.file = &file;
|
||||
file.functions << fun;
|
||||
}
|
||||
file.sections = sections;
|
||||
file.aliases = aliases;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElfParser::IsFunctionStart( const QString &str, quint32 *start )
|
||||
{
|
||||
bool ok;
|
||||
quint32 s;
|
||||
if( str.size() < 12 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( str.startsWith( ' ' ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !str.endsWith( ">:" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
s = str.left( 8 ).toUInt( &ok, 16 );
|
||||
if( !ok )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int o = str.indexOf( '<' );
|
||||
if( o < 9 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( start )
|
||||
{
|
||||
*start = s;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ElfParser::GetFunctionName( const QString &str )
|
||||
{
|
||||
QString ret = str;
|
||||
ret.remove( 0, ret.indexOf( '<' ) + 1 );
|
||||
ret.resize( ret.size() - 2 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ElfParser::IsSymbolLine( const QString & str )
|
||||
{
|
||||
if( str.startsWith( "\t\t\t" ) && str.indexOf( '\t', 3 ) > 4 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ElfParser::IsBlank( const QString & str )
|
||||
{
|
||||
QString sim = str.simplified();
|
||||
return sim.isEmpty() || sim == "...";
|
||||
}
|
||||
|
||||
bool ElfParser::ParseOpLine( const QString &str, QString &hex, QString &oper )
|
||||
{
|
||||
// 1c74: 41 82 01 54 beq-
|
||||
int tab = str.indexOf( '\t', 3 );
|
||||
if( tab < 0 || str.size() < tab + 15 || str.at( tab + 3 ) != ' ' || str.at( tab + 6 ) != ' ' || str.at( tab + 9 ) != ' ' || str.at( tab + 12 ) != ' ' )
|
||||
{
|
||||
qDebug() << str << "is not an opline";
|
||||
qDebug() << hex << oper;
|
||||
return false;
|
||||
}
|
||||
// " 0: 94 21 ff f0 stwu r1,-16(r1)"
|
||||
hex = str.mid( tab + 1, 11 );
|
||||
hex.remove( ' ' );
|
||||
|
||||
oper = str.mid( tab + 14 );
|
||||
int i = oper.indexOf( ' ' );
|
||||
if( i > 0 )
|
||||
{
|
||||
oper.resize( i );
|
||||
}
|
||||
//qDebug() << str << '\n' << hex << oper;
|
||||
//exit( 0 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElfParser::OpNeedsWildCard( const QString &str )
|
||||
{
|
||||
if( str == "bl" )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ElfParser::GetNonOperRef( const QString &str, quint32 *off, SymRef::Type *type )
|
||||
{
|
||||
int i = str.lastIndexOf( '\t' );
|
||||
if( i < 0 )
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
if( off )// get offset
|
||||
{
|
||||
bool ok;
|
||||
QString n = str.mid( 3 );
|
||||
{
|
||||
n.resize( n.indexOf( ':' ) );
|
||||
}
|
||||
*off = n.toUInt( &ok, 16 );
|
||||
if( !ok )
|
||||
{
|
||||
*off = 0xdeadbeef;
|
||||
DBG << "error converting\n" << str << '\n' << n;
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
if( type )
|
||||
{
|
||||
if( str.contains( "R_PPC_REL24" ) )
|
||||
{
|
||||
*type = SymRef::R_PPC_REL24;
|
||||
}
|
||||
else if( str.contains( "R_PPC_ADDR16_LO" ) )
|
||||
{
|
||||
*type = SymRef::R_PPC_ADDR16_LO;
|
||||
}
|
||||
else if( str.contains( "R_PPC_EMB_SDA21" ) )
|
||||
{
|
||||
*type = SymRef::R_PPC_EMB_SDA21;
|
||||
}
|
||||
else if( str.contains( "R_PPC_ADDR16_HA" ) || str.contains( "R_PPC_ADDR16_HI" ) )
|
||||
{
|
||||
*type = SymRef::R_PPC_ADDR16_HI;
|
||||
}
|
||||
else if( str.contains( "R_PPC_SDAREL16" ) )
|
||||
{
|
||||
*type = SymRef::R_PPC_SDAREL16;
|
||||
}
|
||||
else
|
||||
{
|
||||
*type = SymRef::R_PPC_WTF;
|
||||
DBG << "*type = SymRef::R_PPC_WTF" << str;
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
return str.mid( i + 1 );
|
||||
}
|
||||
|
||||
QString ElfParser::GetOpersymRef( const QString &str )
|
||||
{
|
||||
QString ret;
|
||||
int o = str.indexOf( '<' );
|
||||
if( o < 0 )
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
ret = str.mid( o + 1 );
|
||||
if( !ret.endsWith( '>' ) )
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
ret.resize( ret.size() - 1 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString ElfParser::DeReferenceSymbol( const QString &reference, quint32 *offset )
|
||||
{
|
||||
// .rodata.str1.1+0x5
|
||||
QString ret;
|
||||
if( offset )
|
||||
{
|
||||
*offset = 0;
|
||||
}
|
||||
int o = reference.indexOf( "+0x" );
|
||||
if( o < 0 )
|
||||
{
|
||||
|
||||
return reference;
|
||||
}
|
||||
ret = reference.left( o );
|
||||
bool ok;
|
||||
quint32 d = reference.mid( o + 3 ).toUInt( &ok, 16 );
|
||||
if( !ok )
|
||||
{
|
||||
return reference;
|
||||
}
|
||||
if( offset )
|
||||
{
|
||||
*offset = d;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
135
symbolizer/elfparser.h
Normal file
135
symbolizer/elfparser.h
Normal file
@ -0,0 +1,135 @@
|
||||
#ifndef ELFPARSER_H
|
||||
#define ELFPARSER_H
|
||||
|
||||
#include "../WiiQt/includes.h"
|
||||
|
||||
// class to parse the output of "objdump -xds someLib.a"
|
||||
//! specifically wii PPC libs
|
||||
|
||||
|
||||
struct SymRef
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
R_PPC_ADDR16_HI, // reference to the upper 16 bits of the variable. ie "lis"
|
||||
R_PPC_ADDR16_LO, // refers to the lower 16 bits. ie "addi"
|
||||
R_PPC_REL24, // refers by branching. ie "bl"
|
||||
R_PPC_SDAREL16, // no clue wtf this one does
|
||||
R_PPC_EMB_SDA21, // referenced by lwz/stw r13 or r2. these are converted at link time
|
||||
R_PPC_WTF // something went wrong
|
||||
};
|
||||
|
||||
quint32 off; // offset within the function where the reference occurs
|
||||
quint32 symOff; // offset from the referenced symbol. ie stringTable + 0x10
|
||||
Type type;
|
||||
QString name; // name of the symbol referenced
|
||||
SymRef() : off( 0 ), symOff( 0 ), type( R_PPC_WTF )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// ninty's compiler seems to lump a bunch of data together in 1 section and then offer names to it
|
||||
// gcc seems to give each piece of data its own section
|
||||
struct SymAlias
|
||||
{
|
||||
QString name;
|
||||
QString containerName;
|
||||
quint32 offset;
|
||||
quint32 size;
|
||||
SymAlias() : offset( 0 ), size( 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ElfParser
|
||||
{
|
||||
public:
|
||||
class File;
|
||||
class Function
|
||||
{
|
||||
public:
|
||||
Function( const QString &n = QString() ) : name( n )
|
||||
{
|
||||
}
|
||||
const QString &Name() const { return name; }
|
||||
const QString &Pattern() const { return pattern; }
|
||||
const QList< SymRef > &References() const { return references; }
|
||||
const File *PFile() const { return file; }
|
||||
private:
|
||||
friend class ElfParser;
|
||||
QString name;
|
||||
QString pattern;
|
||||
File *file;
|
||||
QList< SymRef > references;
|
||||
};
|
||||
|
||||
class File
|
||||
{
|
||||
public:
|
||||
File( const QString &n = QString() ) : name( n )
|
||||
{
|
||||
}
|
||||
const QString &Name() const { return name; }
|
||||
const QList< Function > &Functions() const { return functions; }
|
||||
|
||||
// doesnt contain the ".text" section, since that is already parsed and turned into functions
|
||||
//! this is for data and rodata and stuff
|
||||
const QMap< QString, QByteArray > &Sections() const { return sections; }
|
||||
const QList< SymAlias > &Aliases() const { return aliases; }
|
||||
private:
|
||||
friend class ElfParser;
|
||||
QString name;
|
||||
QList< Function > functions;
|
||||
QMap< QString, QByteArray >sections;
|
||||
QList< SymAlias >aliases;
|
||||
};
|
||||
|
||||
ElfParser( const QString &stuff );
|
||||
|
||||
//const QList< File >Files() const { return files; }
|
||||
bool Error() const { return error; }
|
||||
|
||||
const QList< File > Files() const { return files; }
|
||||
private:
|
||||
bool error;
|
||||
QList< File >files;
|
||||
|
||||
// takes the entire dump and separetes it into files
|
||||
bool ParseText( const QString &str );
|
||||
|
||||
// takes each file and separetes it into functions
|
||||
bool ParseFileText( const QStringList &strs, const QStringList §ionStrs, const QStringList &symbolStrs, File &file );
|
||||
|
||||
QRegExp funcStart;
|
||||
bool IsFunctionStart( const QString &str, quint32 *start = NULL );
|
||||
|
||||
// extract function name from the line that starts it
|
||||
QString GetFunctionName( const QString &str );
|
||||
|
||||
// check if operation is one that should be wildcarded
|
||||
bool OpNeedsWildCard( const QString & str );
|
||||
|
||||
// check if this is a symbol line or opcode
|
||||
bool IsSymbolLine( const QString & str );
|
||||
|
||||
bool IsBlank( const QString & str );
|
||||
|
||||
bool ParseOpLine( const QString &str, QString &hex, QString &oper );
|
||||
|
||||
// returns stuff in <***> at the end of a line
|
||||
QString GetOpersymRef( const QString &str );
|
||||
|
||||
// returns the string referenced by an extra line and the type of reference
|
||||
QString GetNonOperRef( const QString &str, quint32 *off = NULL, SymRef::Type *type = NULL );
|
||||
|
||||
// parses the hex dump text of sections
|
||||
QMap< QString, QByteArray >ParseSectionText( const QStringList &list );
|
||||
|
||||
QString DeReferenceSymbol( const QString &reference, quint32 *offset = NULL );
|
||||
|
||||
// parse symbol table
|
||||
QList< SymAlias >ParseSymbolTable( const QStringList &lines );
|
||||
|
||||
};
|
||||
|
||||
#endif // ELFPARSER_H
|
1516
symbolizer/main.cpp
Normal file
1516
symbolizer/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
symbolizer/symbolizer.pro
Normal file
28
symbolizer/symbolizer.pro
Normal file
@ -0,0 +1,28 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2011-12-12T00:35:52
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core
|
||||
|
||||
#QT -= gui
|
||||
|
||||
TARGET = symbolizer
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp\
|
||||
../WiiQt/tools.cpp \
|
||||
../WiiQt/aes.c \
|
||||
elfparser.cpp \
|
||||
dol.cpp \
|
||||
be.cpp
|
||||
|
||||
HEADERS += ../WiiQt/tools.h \
|
||||
../WiiQt/aes.h \
|
||||
elfparser.h \
|
||||
dol.h \
|
||||
be.h
|
157
symbolizer/symbolizer.pro.user
Normal file
157
symbolizer/symbolizer.pro.user
Normal file
@ -0,0 +1,157 @@
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="EditorConfiguration.AutoIndent" type="bool">true</value>
|
||||
<value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value>
|
||||
<value key="EditorConfiguration.Codec" type="QByteArray">UTF-8</value>
|
||||
<value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value>
|
||||
<value key="EditorConfiguration.IndentBraces" type="bool">false</value>
|
||||
<value key="EditorConfiguration.IndentSize" type="int">4</value>
|
||||
<value key="EditorConfiguration.MouseNavigation" type="bool">true</value>
|
||||
<value key="EditorConfiguration.PaddingMode" type="int">2</value>
|
||||
<value key="EditorConfiguration.ScrollWheelZooming" type="bool">false</value>
|
||||
<value key="EditorConfiguration.SmartBackspace" type="bool">true</value>
|
||||
<value key="EditorConfiguration.SpacesForTabs" type="bool">false</value>
|
||||
<value key="EditorConfiguration.TabKeyBehavior" type="int">0</value>
|
||||
<value key="EditorConfiguration.TabSize" type="int">4</value>
|
||||
<value key="EditorConfiguration.UseGlobal" type="bool">true</value>
|
||||
<value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value>
|
||||
<value key="EditorConfiguration.addFinalNewLine" type="bool">true</value>
|
||||
<value key="EditorConfiguration.cleanIndentation" type="bool">true</value>
|
||||
<value key="EditorConfiguration.cleanWhitespace" type="bool">true</value>
|
||||
<value key="EditorConfiguration.inEntireDocument" type="bool">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value>
|
||||
<value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
|
||||
<value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value>
|
||||
<value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
|
||||
<valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
|
||||
<value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value>
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
|
||||
<value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value>
|
||||
<value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value>
|
||||
<value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value>
|
||||
</valuemap>
|
||||
<valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">-j3</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value>
|
||||
<value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value>
|
||||
<value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
|
||||
<valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Qt in PATH Release</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
|
||||
<value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/j/c/WiiQt/93/symbolizer</value>
|
||||
<value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
|
||||
<value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value>
|
||||
<value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">false</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
|
||||
<valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deploy</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">No deployment</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value>
|
||||
<valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
|
||||
<valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/>
|
||||
<value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value>
|
||||
<value key="Analyzer.Valgrind.NumCallers" type="int">25</value>
|
||||
<valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/>
|
||||
<value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value>
|
||||
<value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value>
|
||||
<valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">symbolizer</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString">./mario.dol /home/j/c/NINTENDO_Revolution_SDK_2.1_Wii-SYNDiCATE/RVL_SDK-2_1-060821/RVL_SDK/RVL/lib/ ./testing.idc</value>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">symbolizer.pro</value>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
|
||||
<valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
|
||||
<value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
|
||||
<value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value>
|
||||
<value key="RunConfiguration.UseCppDebugger" type="bool">true</value>
|
||||
<value key="RunConfiguration.UseQmlDebugger" type="bool">false</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
|
||||
<value type="QString">{dd2f24c7-c64b-41bd-8686-5d5bbb908d16}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">9</value>
|
||||
</data>
|
||||
</qtcreator>
|
Loading…
Reference in New Issue
Block a user