/***************************************************************************
* Copyright ( C ) 2006 Nicolas Hadacek < hadacek @ kde . org > *
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "coff_object.h"
# include "common/common/misc.h"
# include "devices/list/device_list.h"
# include "devices/base/device_group.h"
# include "devices/pic/base/pic_register.h"
# include "coff_data.h"
# include "common/global/pfile.h"
//----------------------------------------------------------------------------
bool Coff : : getName ( const TQByteArray & data , uint & offset , uint nbChars , uint stringTableOffset ,
Log : : Base & log , TQString & name )
{
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
if ( v ! = 0 ) { // name is not in string table
offset - = 4 ;
return getString ( data , offset , nbChars , log , name ) ;
}
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
// ### do a sanity check here
name = TQString ( data . data ( ) + stringTableOffset + v ) ;
return true ;
}
const Coff : : OptHeaderFormat : : Data Coff : : OptHeaderFormat : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Old Microchip " ) } ,
{ 0 , I18N_NOOP ( " New Microchip " ) } ,
{ 0 , I18N_NOOP ( " PICC Compiler " ) } ,
{ 0 , I18N_NOOP ( " CCS Compiler " ) }
} ;
const Coff : : OptHeaderData Coff : : OPT_HEADER_DATA [ ] = {
{ 0x5678 , OptHeaderFormat : : OldMicrochip , true } ,
{ 0x0000 , OptHeaderFormat : : NewMicrochip , true } ,
{ 0x0001 , OptHeaderFormat : : NewMicrochip , true } , // PIC30 with debug
{ 0x1388 , OptHeaderFormat : : Picc , false } , // PICC
{ 0x1B78 , OptHeaderFormat : : Ccsc , false } , // CCSC
{ 0x0000 , OptHeaderFormat : : Nb_Types , false }
} ;
//----------------------------------------------------------------------------
const Coff : : AuxSymbolType : : Data Coff : : AuxSymbolType : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Direct " ) } ,
{ 0 , I18N_NOOP ( " File " ) } ,
{ 0 , I18N_NOOP ( " Indentifier " ) } ,
{ 0 , I18N_NOOP ( " Section " ) }
} ;
Coff : : AuxSymbol * Coff : : AuxSymbol : : factory ( const Object & object , AuxSymbolType type , const TQByteArray & data , uint offset , uint stringTableOffset , Log : : Base & log )
{
switch ( type . type ( ) ) {
case AuxSymbolType : : Direct : return new AuxSymbolDirect ( object , data , offset , stringTableOffset , log ) ;
case AuxSymbolType : : File : return new AuxSymbolFile ( object , data , offset , stringTableOffset , log ) ;
case AuxSymbolType : : Identifier : return new AuxSymbolIdentifier ( object , data , offset , stringTableOffset , log ) ;
case AuxSymbolType : : Section : return new AuxSymbolSection ( object , data , offset , stringTableOffset , log ) ;
case AuxSymbolType : : Nb_Types : return new AuxSymbolUnknown ( object ) ;
}
Q_ASSERT ( false ) ;
return 0 ;
}
Coff : : AuxSymbolDirect : : AuxSymbolDirect ( const Object & object , const TQByteArray & data , uint start , uint stringTableOffset , Log : : Base & log )
: AuxSymbol ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 1 , log , v ) ) return ;
_command = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_string = TQString ( data . data ( ) + stringTableOffset + v ) ;
}
Coff : : AuxSymbolFile : : AuxSymbolFile ( const Object & object , const TQByteArray & data , uint start , uint stringTableOffset , Log : : Base & log )
: AuxSymbol ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( object . format ( ) = = Format : : PIC30 ) {
if ( ! getName ( data , offset , 14 , stringTableOffset , log , _filename ) ) return ;
_line = 0 ;
} else {
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_filename = TQString ( data . data ( ) + stringTableOffset + v ) ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_line = v ;
}
}
Coff : : AuxSymbolIdentifier : : AuxSymbolIdentifier ( const Object & object , const TQByteArray & data , uint start , uint stringTableOffset , Log : : Base & log )
: AuxSymbol ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_string = TQString ( data . data ( ) + stringTableOffset + v ) ;
}
Coff : : AuxSymbolSection : : AuxSymbolSection ( const Object & object , const TQByteArray & data , uint start , uint , Log : : Base & log )
: AuxSymbol ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_length = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_nbRelocations = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_nbLineNumbers = v ;
}
//----------------------------------------------------------------------------
const Coff : : SymbolSectionType : : Data Coff : : SymbolSectionType : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Inside Section " ) } ,
{ 0 , I18N_NOOP ( " Undefined Section " ) } ,
{ 0 , I18N_NOOP ( " Absolute Value " ) } ,
{ 0 , I18N_NOOP ( " Debug Symbol " ) }
} ;
const Coff : : SymbolClass : : Data Coff : : SymbolClass : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Automatic Variable " ) , 1 } ,
{ 0 , I18N_NOOP ( " External Symbol " ) , 2 } ,
{ 0 , I18N_NOOP ( " Static Symbol " ) , 3 } ,
{ 0 , I18N_NOOP ( " Register Variable " ) , 4 } ,
{ 0 , I18N_NOOP ( " External Definition " ) , 5 } ,
{ 0 , I18N_NOOP ( " Label " ) , 6 } ,
{ 0 , I18N_NOOP ( " Undefined Label " ) , 7 } ,
{ 0 , I18N_NOOP ( " Member of Structure " ) , 8 } ,
{ 0 , I18N_NOOP ( " Function Argument " ) , 9 } ,
{ 0 , I18N_NOOP ( " Structure Tag " ) , 10 } ,
{ 0 , I18N_NOOP ( " Member of Union " ) , 11 } ,
{ 0 , I18N_NOOP ( " Union Tag " ) , 12 } ,
{ 0 , I18N_NOOP ( " Type Definition " ) , 13 } ,
{ 0 , I18N_NOOP ( " Undefined Static " ) , 14 } ,
{ 0 , I18N_NOOP ( " Enumeration Tag " ) , 15 } ,
{ 0 , I18N_NOOP ( " Member of Enumeration " ) , 16 } ,
{ 0 , I18N_NOOP ( " Register Parameter " ) , 17 } ,
{ 0 , I18N_NOOP ( " Bit Field " ) , 18 } ,
{ 0 , I18N_NOOP ( " Auto Argument " ) , 19 } ,
{ 0 , I18N_NOOP ( " Dummy Entry (end of block) " ) , 20 } ,
{ 0 , I18N_NOOP ( " Beginning or End of Block " ) , 100 } ,
{ 0 , I18N_NOOP ( " Beginning or End of Function " ) , 101 } ,
{ 0 , I18N_NOOP ( " End of Structure " ) , 102 } ,
{ 0 , I18N_NOOP ( " Filename " ) , 103 } ,
{ 0 , I18N_NOOP ( " Line Number " ) , 104 } ,
{ 0 , I18N_NOOP ( " Duplicate Tag " ) , 105 } ,
{ 0 , I18N_NOOP ( " Section " ) , 109 }
} ;
const Coff : : SymbolType : : Data Coff : : SymbolType : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Void " ) , 0x0001 } ,
{ 0 , I18N_NOOP ( " Char " ) , 0x0010 } ,
{ 0 , I18N_NOOP ( " Short " ) , 0x0011 } ,
{ 0 , I18N_NOOP ( " Int " ) , 0x0100 } ,
{ 0 , I18N_NOOP ( " Long " ) , 0x0101 } ,
{ 0 , I18N_NOOP ( " Float " ) , 0x0110 } ,
{ 0 , I18N_NOOP ( " Double " ) , 0x0111 } ,
{ 0 , I18N_NOOP ( " Structure " ) , 0x1000 } ,
{ 0 , I18N_NOOP ( " Union " ) , 0x1001 } ,
{ 0 , I18N_NOOP ( " Enumeration " ) , 0x1010 } ,
{ 0 , I18N_NOOP ( " Member Of Enumeration " ) , 0x1011 } ,
{ 0 , I18N_NOOP ( " Unsigned Char " ) , 0x1100 } ,
{ 0 , I18N_NOOP ( " Unsigned Short " ) , 0x1101 } ,
{ 0 , I18N_NOOP ( " Unsigned Int " ) , 0x1110 } ,
{ 0 , I18N_NOOP ( " Unsigned Long " ) , 0x1111 } ,
{ 0 , I18N_NOOP ( " Long Double " ) , 0x10000 }
} ;
const Coff : : SymbolDerivedType : : Data Coff : : SymbolDerivedType : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Pointer " ) , 0x010000 } ,
{ 0 , I18N_NOOP ( " Function " ) , 0x100000 } ,
{ 0 , I18N_NOOP ( " Array " ) , 0x110000 }
} ;
Coff : : Symbol : : Symbol ( const Object & object , const TQByteArray & data , uint start ,
uint stringTableOffset , const TQString & lastFilename , Log : : Base & log )
: BaseSymbol ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getName ( data , offset , 8 , stringTableOffset , log , _name ) ) return ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_value = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_section = v ;
uint nb = ( object . format ( ) = = Format : : NewMicrochip ? 4 : 2 ) ;
if ( ! getULong ( data , offset , nb , log , v ) ) return ;
_type = SymbolType : : Nb_Types ;
FOR_EACH ( SymbolType , type )
if ( ( v & 0x001111 ) = = type . data ( ) . id ) { _type = type ; break ; }
_dtype = SymbolDerivedType : : Nb_Types ;
FOR_EACH ( SymbolDerivedType , dtype )
if ( ( v & 0x110000 ) = = dtype . data ( ) . id ) { _dtype = dtype ; break ; }
if ( ! getULong ( data , offset , 1 , log , v ) ) return ;
_sclass = SymbolClass : : Nb_Types ;
FOR_EACH ( SymbolClass , sclass )
if ( v = = sclass . data ( ) . id ) { _sclass = sclass ; break ; }
if ( ! getULong ( data , offset , 1 , log , v ) ) return ;
uint nbAux = v ;
//qDebug("symbol: %s value=%s type=%i dtype=%i class=%i nbAux=%i section=%i", _name.latin1(), toHexLabel(_value, 4).latin1(), _type, _dtype, _class, nbAux, _section);
AuxSymbolType auxType = AuxSymbolType : : Nb_Types ;
if ( _name = = " .direct " ) auxType = AuxSymbolType : : Direct ;
else if ( _name = = " .ident " ) auxType = AuxSymbolType : : Identifier ;
else if ( _sclass = = SymbolClass : : Filename ) auxType = AuxSymbolType : : File ;
else if ( _sclass = = SymbolClass : : Section ) auxType = AuxSymbolType : : Section ;
if ( auxType ! = AuxSymbolType : : Nb_Types & & nbAux = = 0 ) log . log ( Log : : LineType : : Warning , i18n ( " Symbol without needed auxilliary symbol (type=%1) " ) . tqarg ( auxType . type ( ) ) ) ;
Q_ASSERT ( ( offset - start ) = = object . size ( SymbolSize ) ) ;
_aux . resize ( nbAux ) ;
for ( uint i = 0 ; i < nbAux ; i + + ) {
_aux [ i ] = AuxSymbol : : factory ( object , auxType , data , offset , stringTableOffset , log ) ;
offset + = object . size ( SymbolSize ) ;
if ( log . hasError ( ) ) return ;
}
_filename = lastFilename ;
for ( uint i = 0 ; i < uint ( _aux . count ( ) ) ; i + + )
if ( _aux [ i ] - > type ( ) = = AuxSymbolType : : File ) _filename = static_cast < AuxSymbolFile * > ( _aux [ i ] ) - > filename ( ) ;
}
Coff : : SymbolSectionType Coff : : Symbol : : sectionType ( ) const
{
switch ( _section ) {
case 0x0000 : return SymbolSectionType : : UndefinedSection ;
case 0xFFFF : return SymbolSectionType : : AbsoluteValue ;
case 0xFFFE : return SymbolSectionType : : DebugSymbol ;
}
return SymbolSectionType : : InsideSection ;
}
//----------------------------------------------------------------------------
Coff : : Relocation : : Relocation ( const Object & object , const Section & section ,
const TQByteArray & data , uint start , Log : : Base & log )
: Element ( object ) , _symbol ( 0 )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_address = v ;
if ( _address > section . size ( ) ) log . log ( Log : : LineType : : Warning , i18n ( " Relocation address beyong section size: %1/%2 " ) . tqarg ( v ) . tqarg ( section . size ( ) ) ) ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
if ( v > = object . nbSymbols ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Relocation has unknown symbol: %1 " ) . tqarg ( v ) ) ;
return ;
}
if ( object . symbol ( v ) - > isAuxSymbol ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Relocation is an auxiliary symbol: %1 " ) . tqarg ( v ) ) ;
return ;
}
_symbol = static_cast < const Symbol * > ( object . symbol ( v ) ) ;
if ( object . format ( ) ! = Format : : PIC30 ) {
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_offset = short ( v ) ;
}
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_type = v ;
//qDebug("reloc %s: address=%s offset=%i type=%i", _symbol->_name.latin1(), toHexLabel(_address, 4).latin1(), _offset, _type);
}
//----------------------------------------------------------------------------
Coff : : CodeLine : : CodeLine ( const Object & object , const Section & section ,
const TQByteArray & data , uint start , const TQString & lastFilename , Log : : Base & log )
: Element ( object ) , _section ( section ) , _symbol ( 0 )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
uint tmp = v ;
if ( object . format ( ) = = Format : : PIC30 ) {
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_line = v ;
if ( _line ! = 0 ) {
_address = tmp ;
_filename = lastFilename ;
//qDebug("code line %i: %s", _line, toHexLabel(_address, nbChars(_address)).latin1());
} else {
if ( tmp > = object . nbSymbols ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Codeline has unknown symbol: %1 " ) . tqarg ( tmp ) ) ;
return ;
}
if ( object . symbol ( tmp ) - > isAuxSymbol ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Codeline is an auxiliary symbol: %1 " ) . tqarg ( tmp ) ) ;
return ;
}
_symbol = static_cast < const Symbol * > ( object . symbol ( tmp ) ) ;
_filename = _symbol - > filename ( ) ;
//qDebug("code line %i: %s", _line, _symbol->_name.latin1());
}
} else {
if ( tmp > = object . nbSymbols ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Codeline has unknown symbol: %1 " ) . tqarg ( tmp ) ) ;
return ;
}
if ( object . symbol ( tmp ) - > isAuxSymbol ( ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Codeline is an auxiliary symbol: %1 " ) . tqarg ( tmp ) ) ;
return ;
}
_symbol = static_cast < const Symbol * > ( object . symbol ( tmp ) ) ;
_filename = _symbol - > filename ( ) ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
_line = v ;
if ( object . optHeaderFormat ( ) = = OptHeaderFormat : : Picc & & _line > = 2 ) _line - = 2 ; // #### ??
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_address = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
// flags
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
// function index
//qDebug("code line %i: %s", _line, toHexLabel(_address, nbChars(_address)).latin1());
}
// if ( _symbol && _symbol->_class!=Symbol::CFile )
// log.log(Log::LineType::Warning, i18n("Line without file symbol associated (%1:%2 %3).")
// .tqarg(_section._name).tqarg(toHexLabel(_address, nbChars(_address))).tqarg(_symbol->_class));
}
//----------------------------------------------------------------------------
const Coff : : SectionType : : Data Coff : : SectionType : : DATA [ Nb_Types ] = {
{ 0 , I18N_NOOP ( " Config " ) } ,
{ 0 , I18N_NOOP ( " Device ID " ) } ,
{ 0 , I18N_NOOP ( " User IDs " ) } ,
{ 0 , I18N_NOOP ( " Uninitialized Data " ) } ,
{ 0 , I18N_NOOP ( " Initialized Data " ) } ,
{ 0 , I18N_NOOP ( " Rom Data " ) } ,
{ 0 , I18N_NOOP ( " Code " ) }
} ;
Coff : : Section : : Section ( const Device : : Data & device , const Object & object ,
const TQByteArray & data , uint start , uint stringTableOffset , Log : : Base & log )
: Element ( object )
{
uint offset = start ;
TQ_UINT32 v ;
if ( ! getName ( data , offset , 8 , stringTableOffset , log , _name ) ) return ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_address = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
//if ( _address!=v ) log.log(Log::LineType::Warning, i18n("Virtual address (%1) does not match physical address (%2) in %3.")
// .tqarg(toHexLabel(v, 4)).tqarg(toHexLabel(_address, 4)).tqarg(_name));
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_size = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
uint dataOffset = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
uint relocationOffset = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
uint lineNumberOffset = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
uint nbRelocations = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return ;
uint nbLineNumbers = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return ;
_flags = v ;
// read data
Q_ASSERT ( device . group ( ) . name ( ) = = " pic " ) ;
const Pic : : Data & pdata = static_cast < const Pic : : Data & > ( device ) ;
//qDebug("section %s: address=%s size=%i flags=%i", _name.data(), toHexLabel(_address, 4).latin1(), _size, int(_flags));
if ( _size ! = 0 & & dataOffset ! = 0 ) {
uint inc = 1 ;
uint nbWords = _size ;
uint nbBytesWord = 1 ;
bool b = ( ( _flags & FText ) | | ( _flags & FDataRom ) ) ;
if ( b ) {
nbBytesWord = pdata . nbBytesWord ( Pic : : MemoryRangeType : : Code ) ;
nbWords / = nbBytesWord ;
inc = pdata . addressIncrement ( Pic : : MemoryRangeType : : Code ) ;
}
for ( uint i = 0 ; i < nbWords ; i + + ) {
Address address = _address + inc * i ;
if ( ! getULong ( data , dataOffset , nbBytesWord , log , v ) ) return ;
_instructions [ address ] . value = v ;
}
for ( uint i = 0 ; i < nbWords ; i + + ) {
Address address = _address + inc * i ;
BitValue op = _instructions [ address ] . value ;
if ( _flags & FText ) {
char buffer [ 512 ] ;
buffer [ 0 ] = 0 ;
BitValue op2 = ( ( i + 1 ) < nbWords ? _instructions [ address + inc ] . value : 0 ) ;
uint nbop = disassemble ( op . toUInt ( ) , op2 . toUInt ( ) , address . toUInt ( ) / inc , pdata . architecture ( ) , buffer , 512 ) ;
_instructions [ address ] . disasm = TQString ( buffer ) ;
_instructions [ address ] . opcode = toHex ( op , pdata . nbCharsWord ( Pic : : MemoryRangeType : : Code ) ) ;
if ( nbop = = 2 ) {
_instructions [ address + inc ] . opcode = toHex ( op2 , pdata . nbCharsWord ( Pic : : MemoryRangeType : : Code ) ) ;
i + + ;
}
//qDebug(" %s: %s (%s %s)", toHex(address, 4).data(), _data[address].disasm.data(), _data[address].opcode.data(), (nbop==2 ? _data[address+inc].opcode.data() : ""));
} else if ( _flags & FDataRom ) _instructions [ address ] . opcode = toHex ( op , 4 ) ;
else if ( _flags & FData ) _instructions [ address ] . opcode = toHex ( op . maskWith ( 0xFF ) , 2 ) ;
}
}
// read relocations
if ( relocationOffset ! = 0 ) {
_relocations . resize ( nbRelocations ) ;
for ( uint i = 0 ; i < nbRelocations ; i + + ) {
_relocations [ i ] = new Relocation ( object , * this , data , relocationOffset , log ) ;
relocationOffset + = object . size ( RelocationSize ) ;
if ( log . hasError ( ) ) return ;
}
}
// read line numbers
if ( lineNumberOffset ! = 0 ) {
TQString lastFilename ;
_lines . resize ( nbLineNumbers ) ;
for ( uint i = 0 ; i < nbLineNumbers ; i + + ) {
_lines [ i ] = new CodeLine ( object , * this , data , lineNumberOffset , lastFilename , log ) ;
lastFilename = _lines [ i ] - > filename ( ) ;
lineNumberOffset + = object . size ( LineNumberSize ) ;
if ( log . hasError ( ) ) return ;
}
}
}
Coff : : Section : : ~ Section ( )
{
for ( uint i = 0 ; i < uint ( _relocations . count ( ) ) ; i + + ) delete _relocations [ i ] ;
for ( uint i = 0 ; i < uint ( _lines . count ( ) ) ; i + + ) delete _lines [ i ] ;
}
Coff : : SectionType Coff : : Section : : type ( ) const
{
if ( _name = = " .config " ) return SectionType : : Config ;
if ( _name = = " .devid " ) return SectionType : : DeviceId ;
if ( _name = = " .idlocs " ) return SectionType : : UserIds ;
if ( _flags & FText ) return SectionType : : Code ;
if ( _flags & FData ) return SectionType : : InitializedData ;
if ( _flags & FBSS ) return SectionType : : UninitializedData ;
if ( _flags & FDataRom ) return SectionType : : DataRom ;
return SectionType : : Nb_Types ;
}
//----------------------------------------------------------------------------
Coff : : Object : : Object ( const Device : : Data * device , const PURL : : Url & url )
: Base ( url ) , _device ( device )
{ }
bool Coff : : Object : : parse ( Log : : Base & log )
{
// header
TQByteArray data ;
uint offset = 0 ;
if ( ! initParse ( CoffType : : Object , data , offset , log ) ) return false ;
if ( _format = = Format : : Nb_Types ) {
log . log ( Log : : LineType : : Error , i18n ( " COFF format not supported: magic number is %1. " ) . tqarg ( toHexLabel ( _magic , 4 ) ) ) ;
return false ;
}
log . log ( Log : : DebugLevel : : Extra , TQString ( " COFF format: %1 " ) . tqarg ( toHexLabel ( _magic , 4 ) ) ) ;
if ( ! parseHeader ( data , offset , log ) ) return false ;
// optionnal header
Q_ASSERT ( offset = = size ( HeaderSize ) ) ;
if ( ! getULong ( data , offset , 2 , log , _optHeaderMagic ) ) return false ;
log . log ( Log : : DebugLevel : : Extra , TQString ( " COFF optionnal header format: %1 " ) . tqarg ( toHexLabel ( _optHeaderMagic , 4 ) ) ) ;
_optHeaderFormat = OptHeaderFormat : : Nb_Types ;
uint i = 0 ;
for ( ; OPT_HEADER_DATA [ i ] . optHeaderFormat ! = OptHeaderFormat : : Nb_Types ; i + + ) if ( _optHeaderMagic = = OPT_HEADER_DATA [ i ] . magic ) break ;
_optHeaderFormat = OPT_HEADER_DATA [ i ] . optHeaderFormat ;
if ( _optHeaderFormat = = OptHeaderFormat : : Nb_Types ) {
log . log ( Log : : LineType : : Warning , i18n ( " Optional header format not supported: magic number is %1. " ) . tqarg ( toHexLabel ( _optHeaderMagic , 4 ) ) ) ;
offset + = size ( OptHeaderSize ) - 2 ;
} else if ( ! OPT_HEADER_DATA [ i ] . parsed ) {
log . log ( Log : : DebugLevel : : Normal , TQString ( " Optional header not parsed: magic number is %1. " ) . tqarg ( toHexLabel ( _optHeaderMagic , 4 ) ) ) ;
offset + = size ( OptHeaderSize ) - 2 ;
} else if ( ! parseOptionnalHeader ( data , offset , log ) ) return false ;
// parse symbol table
uint stringTableOffset = _symbolOffset + _nbSymbols * size ( SymbolSize ) ;
TQString lastFilename ;
_symbols . resize ( _nbSymbols ) ;
for ( uint i = 0 ; i < _nbSymbols ; i + + ) {
Symbol * s = new Symbol ( * this , data , _symbolOffset , stringTableOffset , lastFilename , log ) ;
if ( log . hasError ( ) ) return false ;
if ( ! s - > filename ( ) . isEmpty ( ) ) lastFilename = s - > filename ( ) ;
_symbols [ i ] = s ;
_msymbols [ s - > name ( ) ] = s ;
_symbolOffset + = size ( SymbolSize ) ;
for ( uint k = 0 ; k < uint ( s - > auxSymbols ( ) . count ( ) ) ; k + + ) {
i + + ;
_symbols [ i ] = s - > auxSymbols ( ) [ k ] ;
_symbolOffset + = size ( SymbolSize ) ;
}
}
// parse sections
Q_ASSERT ( offset = = ( size ( HeaderSize ) + size ( OptHeaderSize ) ) ) ;
_sections . resize ( _nbSections ) ;
for ( uint i = 0 ; i < _nbSections ; i + + ) {
_sections [ i ] = new Section ( * _device , * this , data , offset , stringTableOffset , log ) ;
offset + = size ( SectionHeaderSize ) ;
if ( log . hasError ( ) ) return false ;
}
// extract filenames
for ( uint i = 0 ; i < _nbSymbols ; i + + ) {
if ( _symbols [ i ] = = 0 | | _symbols [ i ] - > isAuxSymbol ( ) ) continue ;
TQString s = static_cast < const Symbol * > ( _symbols [ i ] ) - > filename ( ) ;
if ( s . isEmpty ( ) | | s = = " fake " | | _filenames . contains ( s ) ) continue ;
_filenames . append ( s ) ;
}
// extract variables
for ( uint i = 0 ; i < nbSymbols ( ) ; i + + ) {
if ( _symbols [ i ] = = 0 | | _symbols [ i ] - > isAuxSymbol ( ) ) continue ;
const Symbol * sym = static_cast < const Symbol * > ( _symbols [ i ] ) ;
if ( sym - > symbolClass ( ) ! = SymbolClass : : Static ) continue ;
if ( sym - > sectionType ( ) ! = SymbolSectionType : : InsideSection ) continue ;
TQString name = sym - > name ( ) ;
if ( name . startsWith ( " _$_ " ) | | name . startsWith ( " __ " ) | | name . startsWith ( " . " ) ) continue ; // special variables (?)
_variables [ name ] = sym - > value ( ) & 0xFFF ; // #### ??
}
return true ;
}
bool Coff : : Object : : parseHeader ( const TQByteArray & data , uint & offset , Log : : Base & log )
{
TQ_UINT32 v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return false ;
_nbSections = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
// time_t time = v;
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
_symbolOffset = v ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
_nbSymbols = v ;
if ( ! getULong ( data , offset , 2 , log , v ) ) return false ;
if ( v ! = size ( OptHeaderSize ) ) {
log . log ( Log : : LineType : : Error , i18n ( " Optionnal header size is not %1: %2 " ) . tqarg ( size ( OptHeaderSize ) ) . tqarg ( v ) ) ;
return false ;
}
if ( ! getULong ( data , offset , 2 , log , v ) ) return false ;
_flags = Flags ( v ) ;
return true ;
}
bool Coff : : Object : : parseOptionnalHeader ( const TQByteArray & data , uint & offset , Log : : Base & log )
{
TQ_UINT32 v ;
int nb = ( _format = = Format : : NewMicrochip ? 4 : 2 ) ;
if ( ! getULong ( data , offset , nb , log , v ) ) return false ; // version stamp
if ( _format = = Format : : PIC30 ) {
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // text size in bytes, padded to firmware boundary
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // initialized data "
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // uninitialized data "
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // entry point
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // offset of text
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ; // offset of data
if ( _device = = 0 ) _device = Device : : lister ( ) . data ( " 30F2010 " ) ; // for e.g.
} else {
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
// #### at least for C18 compiler, it can be compiled for generic processor: in such case
// the pic type will be 18C452 in non-extended mode and 18F4620 for extended mode...
TQString name = Coff : : findId ( v ) ;
log . log ( Log : : DebugLevel : : Normal , TQString ( " Device name: \" %1 \" " ) . tqarg ( name ) ) ;
if ( name . isEmpty ( ) ) {
log . log ( Log : : DebugLevel : : Normal , TQString ( " Unknown processor type: %1 " ) . tqarg ( toHexLabel ( v , 4 ) ) ) ;
log . log ( Log : : LineType : : Error , i18n ( " Could not determine processor (%1). " ) . tqarg ( toHexLabel ( v , 4 ) ) ) ;
return false ;
} else if ( _device = = 0 ) _device = Device : : lister ( ) . data ( name ) ;
else if ( name ! = _device - > name ( ) ) log . log ( Log : : DebugLevel : : Normal , TQString ( " Different processor name: %1 " ) . tqarg ( name ) ) ;
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
const Pic : : Data * pdata = static_cast < const Pic : : Data * > ( _device ) ;
if ( pdata ) {
uint nbBits = pdata - > nbBitsWord ( Pic : : MemoryRangeType : : Code ) / pdata - > addressIncrement ( Pic : : MemoryRangeType : : Code ) ;
if ( v ! = nbBits ) log . log ( Log : : DebugLevel : : Normal , TQString ( " Rom width is not %1: %2 " ) . tqarg ( nbBits ) . tqarg ( v ) ) ;
}
if ( ! getULong ( data , offset , 4 , log , v ) ) return false ;
if ( pdata ) {
uint nbBits = pdata - > registersData ( ) . nbBits ( ) ;
if ( v ! = nbBits ) log . log ( Log : : DebugLevel : : Normal , TQString ( " Ram width is not %1: %2 " ) . tqarg ( nbBits ) . tqarg ( v ) ) ;
}
}
return true ;
}
Coff : : Object : : ~ Object ( )
{
for ( uint i = 0 ; i < nbSymbols ( ) ; i + + ) delete _symbols [ i ] ;
for ( uint i = 0 ; i < nbSections ( ) ; i + + ) delete _sections [ i ] ;
}
TQString Coff : : Object : : variableName ( Address address ) const
{
TQMap < TQString , Address > : : const_iterator it ;
for ( it = _variables . begin ( ) ; it ! = _variables . end ( ) ; + + it )
if ( it . data ( ) = = address ) return it . key ( ) ;
return TQString ( ) ;
}
//----------------------------------------------------------------------------
TQValueVector < Pic : : RegisterNameData > Pic : : sfrList ( const Pic : : Data & data )
{
TQValueVector < Pic : : RegisterNameData > list ;
const Pic : : RegistersData & rdata = data . registersData ( ) ;
for ( uint i = 0 ; i < rdata . nbRegisters ( ) ; i + + ) {
uint address = rdata . nbBytes ( ) * i ;
Pic : : RegisterType type = rdata . type ( address ) ;
Device : : RegisterProperties rp = rdata . properties ( address ) ;
if ( ! ( rp & Device : : Readable ) ) continue ;
Register : : TypeData rtd ( address , rdata . nbChars ( ) ) ;
if ( type = = Pic : : Sfr ) list . append ( Pic : : RegisterNameData ( rdata . label ( address ) , rtd ) ) ;
}
TQMap < TQString , Pic : : CombinedData > : : const_iterator it ;
for ( it = rdata . combined . begin ( ) ; it ! = rdata . combined . end ( ) ; + + it ) {
Register : : TypeData td ( it . key ( ) , it . data ( ) . address , it . data ( ) . nbChars ) ;
list . append ( Pic : : RegisterNameData ( it . key ( ) , td ) ) ;
}
if ( data . architecture ( ) = = Pic : : Architecture : : P16X )
list . append ( Pic : : RegisterNameData ( " WREG " , Register : : TypeData ( " WREG " , rdata . nbChars ( ) ) ) ) ;
qHeapSort ( list ) ;
return list ;
}
TQValueVector < Pic : : RegisterNameData > Pic : : gprList ( const Pic : : Data & data , const Coff : : Object * coff )
{
TQValueVector < Pic : : RegisterNameData > list ;
const Pic : : RegistersData & rdata = data . registersData ( ) ;
for ( uint i = 0 ; i < rdata . nbRegisters ( ) ; i + + ) {
uint address = rdata . nbBytes ( ) * i ;
Pic : : RegisterType type = rdata . type ( address ) ;
Device : : RegisterProperties rp = rdata . properties ( address ) ;
if ( ! ( rp & Device : : Readable ) ) continue ;
if ( type = = Pic : : Gpr ) {
TQString s = toHexLabel ( address , rdata . nbCharsAddress ( ) ) ;
if ( coff ) {
TQString name = coff - > variableName ( address ) ;
if ( ! name . isEmpty ( ) ) s + = " ( " + name + " ) " ;
}
Register : : TypeData rtd ( address , rdata . nbChars ( ) ) ;
list . append ( Pic : : RegisterNameData ( s , rtd ) ) ;
}
}
return list ;
}
TQValueVector < Pic : : RegisterNameData > Pic : : variableList ( const Pic : : Data & data , const Coff : : Object & coff )
{
TQValueVector < Pic : : RegisterNameData > list ;
const Pic : : RegistersData & rdata = data . registersData ( ) ;
TQMap < TQString , Address > variables = coff . variables ( ) ;
TQMap < TQString , Address > : : const_iterator vit ;
for ( vit = variables . begin ( ) ; vit ! = variables . end ( ) ; + + vit ) {
Register : : TypeData rtd ( vit . data ( ) , rdata . nbChars ( ) ) ;
list . append ( Pic : : RegisterNameData ( vit . key ( ) + " ( " + toHexLabel ( vit . data ( ) , rdata . nbCharsAddress ( ) ) + " ) " , rtd ) ) ;
}
qHeapSort ( list ) ;
return list ;
}