1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/***************************************************************************
* 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_archive.h"
//----------------------------------------------------------------------------
Coff::Member::Member(const QByteArray &data, uint &offset, Log::Base &log)
{
// parse header
QString s;
if ( !getString(data, offset, 256, log, s) ) return;
int i = s.find('/');
if ( i==-1 ) {
log.log(Log::LineType::Error, i18n("Member name not terminated by '/' (\"%1\").").arg(s));
return;
}
_name = s.mid(0, i);
if ( !getString(data, offset, 12, log, s) ) return; // mtime
if ( !getString(data, offset, 10, log, s) ) return;
i = s.find('l');
if ( i==-1 ) {
log.log(Log::LineType::Error, i18n("File size not terminated by 'l' (\"%1\").").arg(s));
return;
}
bool ok;
_nbBytes = s.mid(0, i).toUInt(&ok);
if ( !ok ) {
log.log(Log::LineType::Error, i18n("Wrong format for file size \"%1\".").arg(s));
return;
}
Q_UINT32 v;
if ( !getULong(data, offset, 2, log, v) ) return;
log.log(Log::DebugLevel::Extra, i18n("Magic number: %1").arg(toHexLabel(v, 4)));
// if ( v!=0x600A ) {
// log.log(Log::LineType::Error, i18n("Wrong magic for Microchip archive (\"%1\").").arg(toHexLabel(v, 4)));
// return;
// }
offset += _nbBytes;
}
//----------------------------------------------------------------------------
Coff::Archive::Archive(const PURL::Url &url)
: Base(url)
{}
bool Coff::Archive::parse(Log::Base &log)
{
QByteArray data;
uint offset = 0, symbolEnd = 0;
Member *symbol = 0;
if ( !initParse(CoffType::Archive, data, offset, log) ) return false;
for (;;) {
if ( offset==uint(data.count()) ) break; // end of archive
uint start = offset;
Member *member = new Member(data, offset, log);
if ( log.hasError() ) return false;
if ( member->name().isEmpty() ) {
symbolEnd = offset;
symbol = member;
} else {
_members[member->name()] = member;
_offsets[start] = member;
}
}
if (symbol) {
if ( !readSymbols(data, symbolEnd - symbol->nbBytes(), log) ) return false;
delete symbol;
}
return true;
}
Coff::Archive::~Archive()
{
QMap<QString, Member *>::const_iterator it;
for (it=_members.begin(); it!=_members.end(); ++it) delete it.data();
}
bool Coff::Archive::readSymbols(const QByteArray &data, uint offset, Log::Base &log)
{
Q_UINT32 nb;
if ( !getULong(data, offset, 4, log, nb) ) return false;
QValueVector<Member *> members(nb);
for (uint i=0; i<nb; i++) {
Q_UINT32 start;
if ( !getULong(data, offset, 4, log, start) ) return false;
if ( !_offsets.contains(start) ) {
log.log(Log::LineType::Error, i18n("Unknown file member offset: %1").arg(toHexLabel(start, 8)));
return false;
}
members[i] = _offsets[start];
}
for (uint i=0; i<nb; i++) {
QString name(data.data() + offset);
offset += name.length() + 1;
_symbols[name] = members[i];
}
return true;
}
Log::KeyList Coff::Archive::information() const
{
Log::KeyList keys(i18n("Information:"));
keys.append(i18n("No. of file members:"), QString::number(members().count()));
keys.append(i18n("No. of symbols:"), QString::number(symbols().count()));
return keys;
}
Log::KeyList Coff::Archive::membersInformation() const
{
Log::KeyList keys(i18n("File Members:"));
QMap<QString, Member *>::const_iterator it;
for (it=members().begin(); it!=members().end(); ++it)
keys.append(it.key(), i18n("size: %1 bytes").arg(it.data()->nbBytes()));
return keys;
}
Log::KeyList Coff::Archive::symbolsInformation() const
{
Log::KeyList keys(i18n("Symbols:"));
QMap<QString, Member *>::const_iterator it;
for (it=symbols().begin(); it!=symbols().end(); ++it)
keys.append(it.key(), it.data()->name());
return keys;
}
|