rsp2elff.cxx
8.67 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <symconst.h>
#include "rsp2elf.h"
source * fileList, * fileLast;
extern int hasLineInfo, includeConstants, labelCount;
extern ifstream lineFile;
extern char srcBuf[];
extern symbol * symTable;
extern unsigned long codeBase;
extern int textSectionSize;
extern int simplified;
char * lastFile = "";
int fileCount, procCount;
unsigned long codeBase = 0x1000; /* impossibly high address */
void DumpFileTable( void )
{
source * sfp = fileList;
range * rng;
line * lin;
while ( sfp )
{
sfp->print();
rng = sfp->firstRange();
while ( rng )
{
rng->print();
rng = rng->next;
}
lin = sfp->GetLines();
if ( lin )
{
cout << " LINES ";
while ( lin )
{
lin->print();
lin = lin->next;
}
cout << endl;
}
sfp->PrintProcs();
sfp->PrintSymbols();
sfp = sfp->next;
}
}
/************************************************************************
Function: GetFileOfAddr
Args: unsigned long addr - the address to look up
Type: int - returns number of file containing addr
Purpose: This function looks up an address by walking the list of files
and their associated address ranges. When the address is found
the index of the file is returned.
************************************************************************/
int GetFileOfAddr( unsigned long addr )
{
source * sfp;
int fileNumber = 0;
if ( !fileList )
return -1;
sfp = fileList;
while ( sfp )
{
if ( sfp->containsAddr( addr ) )
return fileNumber;
sfp = sfp->next;
++fileNumber;
}
return -1; /* couldn't find it */
}
/************************************************************************
Function: SymBaseOfFile
Args: int fileno - The number of the file, as returned by GetFileOfAddr()
Type: int - returns the index of the first symbol for that file
Purpose: This function looks up the base symbol for the specified file
(by position in the file list). It is needed so we can subtract
off the base symbol and specify a relative symbol number for a
symbol.
************************************************************************/
int SymBaseOfFile( int fileno )
{
source * sfp = fileList;
if ( fileno < 0 )
return 0;
while ( fileno-- )
{
sfp = sfp->next;
if ( !sfp )
return 0;
}
return sfp->FirstSymIs();
}
/************************************************************************
Function: AddSymToFile
Args: symbol * sym - the symbol to be added
Type: void
Purpose: This function adds a symbol to a file. If it is in the range
of a proc, then it is added to the proc itself; otherwise,
it is added to the orphan symbol list for the file itself
************************************************************************/
void AddSymToFile( symbol * sym )
{
source * sfp = fileList;
int fileNumber = sym->GetFile();
proc * pro;
if ( fileNumber < 0 )
{
--labelCount; // Not a label in any valid code range, ignore it
return;
}
while ( fileNumber-- )
sfp = sfp->next;
pro = sfp->GetProcs();
while ( pro )
{
if ( pro->contains( sym->GetValue() ) )
{
// add it to this proc
pro->AddSymbol( sym );
return;
}
pro = pro->next;
}
// add it to the orphan list instead
sfp->AddSymbol( sym );
}
/************************************************************************
Function: AddSyntheticProc
Args: none
Type: void
Purpose: This function adds a proc entry for the synthetic proc to
the first file on the file list.
************************************************************************/
void AddSyntheticProc( void )
{
proc * synth = new proc;
line * nullLine = new line( 0 );
synth->callMe( symTable->NameIs() );
synth->newlow( codeBase, 0 );
synth->newhigh( codeBase + textSectionSize - 1, nullLine );
synth->AsgLineIndex( -1 );
synth->next = fileList->GetProcs();
++procCount;
fileList->JamProc( synth );
}
/************************************************************************
Function: CleanupInfo
Args: none
Type: void
Purpose: This function walks the file list and adds the number of labels
for all the procs in the file to the total count of labels for
the file. This simplifies building debug info, since we will
know how many symbols are needed for each file without having
to traverse the list again. It also looks for files that have
no user-specified procs. For these, it synthesizes a proc so that
line numbers can be used.
************************************************************************/
void CleanupInfo( void )
{
source * sfp = fileList;
while ( sfp )
{
proc * pro;
pro = sfp->GetProcs();
if ( !pro && !simplified )
{
cout << "File " << sfp->filename() <<
" has no procs - making one" << endl;
sfp->MakeProcForFile();
++procCount;
pro = sfp->GetProcs();
}
while ( pro )
{
symbol * sym;
sym = pro->GetLabels();
while ( sym )
{
sfp->OneMoreLabel();
sym = sym->pnext;
}
pro = pro->next;
}
sfp = sfp->next;
}
}
/************************************************************************
Function: BuildFileTable
Args: none
Type: void
Purpose: This function reads the line file (.sym) and builds a linked list
of the source files used to build this executable. For each
source file, there is a list of the address ranges contained in
the file with one record for each contiguous block of addresses.
In general, including a .s file forces another record because
instructions will have been generated. This is not a rule, of
course; the program simply looks for an address that did not
match the last one + 4. The resulting file table also tracks
source lines for each file.
Note that the .sym file contains other directives besides .lines.
These are also processed here. .sname and .vname records are
added to the symbol table as constants only if the user has
requested that constants are to be included. .unname records are
ignored. The proc records (entry and end) are used to build the
proclist for this file.
************************************************************************/
void BuildFileTable( void )
{
char *s, *addr, *file, *name;
int sourceLine;
source * sfile;
line * l;
unsigned long IMEMloc;
int procPending = 0, isInsideProc = 0;;
class proc * newProc;
if ( !hasLineInfo )
return;
lineFile.seekg( 0 ); /* just in case... */
while ( lineFile.getline( srcBuf, 1024 ) != NULL )
{
/* parse line, see if it's the same file as last time */
s = strtok( srcBuf, " \t\n" );
if ( strcmp( s, "line" ) )
{
if ( !strcmp( s, "sname" ) || /* scalar reg name */
!strcmp( s, "vname" ) ) /* vector reg name */
{
if ( !includeConstants )
continue;
name = strtok( NULL, " \t\n" ); /* get name */
sourceLine = atoi( strtok( NULL, " \t\n" ) ); /* regnum */
if ( (s = (char *) malloc( strlen( name ) + 1 )) == NULL )
nospace();
strcpy( s, name );
NewSymbol( s, sourceLine, stConstant );
}
else if ( !strcmp( s, "entry" ) )
{
name = strtok( NULL, " \t\n" ); /* get name */
if ( !name )
{
cerr << "Bad entry directive" << endl;
continue;
}
newProc = new proc;
newProc->callMe( name );
procPending = 1;
isInsideProc = 1;
++procCount;
}
else if ( !strcmp( s, "end" ) )
{
name = strtok( NULL, " \t\n" ); /* get name */
isInsideProc = 0;
newProc->newhigh( IMEMloc + IMEM_START + 3, l );
}
else if ( strcmp( s, "unname" ) ) /* ignore it */
cerr << "Unknown directive type " << s
<< endl;
continue;
}
/* Got a line directive */
addr = strtok( NULL, " \t\n" );
IMEMloc = strtoul( addr, (char **) NULL, 16 ) & 0xfff;
if ( IMEMloc < codeBase )
codeBase = IMEMloc;
file = strtok( NULL, " \t\n" );
sourceLine = atoi( strtok( NULL, " \t\n" ) );
if ( strcmp( lastFile, file ) ) /* name change */
{
sfile = fileList;
while ( sfile )
{
if ( !strcmp( sfile->filename(), file ) )
break;
sfile = sfile->next;
}
if ( !sfile ) /* not in list, add it */
{
sfile = new source;
if ( !fileList )
fileList = fileLast = sfile;
else
{
fileLast->next = sfile;
fileLast = sfile;
}
sfile->callMe( file );
++fileCount;
}
}
lastFile = sfile->filename();
if ( procPending ) /* take care of it now */
{
NewSymbol( newProc->nameIs(), IMEMloc + IMEM_START,
stProc );
newProc->newlow( IMEMloc + IMEM_START, sourceLine );
sfile->AddProc( newProc );
}
sfile->newRange( IMEMloc + IMEM_START, sourceLine );
/*
We are now pointing to the right file list.
See if this is more of the same region or a
new one.
*/
l = new line( sourceLine );
if ( isInsideProc )
newProc->AddLine( l );
else // orphan
sfile->AddLine( l );
procPending = 0;
}
}