1 /***********************************************************************
2  *
3  *  AVRA - Assembler for the Atmel AVR microcontroller series
4  *
5  *  Copyright (C) 1998-2020 The AVRA Authors
6  *
7  *  coff.c - Common Object File Format (COFF) support
8  *
9  *	This file was developed for the AVRA assembler in order to produce
10  *	COFF output files for use with the Atmel AVR Studio.  The Lean C
11  *	Compiler (LCC) debugging stabs output was used as input to the
12  *	assembler.  The information used to develop this file was obtained
13  *	from various sources on the Internet, most notably, the Free
14  *	Software Foundation, The "stabs" debug format, ??? Chapter 7:
15  *	Common Object File Format (COFF).
16  *
17  *	This software has absolutely no warrantee!  The money you paid for
18  *	this will be promptly refunded if not fully satisfied.
19  *
20  *	Beta release 1/20/2000 by Bob Harris
21  *
22  *	This software has not been fully tested and probably has a few
23  *	software deficiencies.
24  *  Some software support may be possible by sending a problem
25  *  description report to rth@mclean.sparta.com
26  *
27  *  Made the recommended change in write_coff_program().
28  *  Fixed an obvious typo in SkipPastDigits().  The if() statement
29  *  was terminated with a semicolon, which terminated the if(); early.
30  *  JEG 4-01-03
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <time.h>
38 
39 #include "misc.h"
40 #include "avra.h"
41 #include "args.h"
42 
43 #include "coff.h"
44 #include "device.h"
45 
46 
47 struct FundamentalType {
48 
49 	char const *pString;
50 	int Type;
51 	int Size;
52 };
53 
54 struct FundamentalType FundamentalTypes[] = {
55 	{"null", T_NULL, 0},
56 	{"void", T_VOID, 0},
57 	{"char", T_CHAR, 1},
58 	{"short", T_SHORT, 1},
59 	{"int", T_INT, 1},
60 	{"long", T_LONG, 2},
61 	{"float", T_FLOAT, 4},
62 	{"double", T_DOUBLE, 4},
63 	{"struct", T_STRUCT, 0},
64 	{"union", T_UNION, 0},
65 	{"enum",  T_ENUM, 0},
66 	{"moe", T_MOE, 0},
67 	{"unsigned char", T_UCHAR, 1},
68 	{"unsigned short", T_USHORT, 1},
69 	{"unsigned int", T_UINT, 1},
70 	{"unsigned long", T_ULONG, 2},
71 	{"long double", T_LNGDBL, 2},
72 	{"long long int", T_LONG, 2},
73 	{"long int", T_LONG, 2},
74 	{"unsigned long long", T_ULONG, 2},
75 	{"signed char", T_CHAR, 1},
76 	{0, 0}
77 };
78 
79 
80 struct coff_info *ci;
81 
82 
83 FILE *
open_coff_file(struct prog_info * pi,char * filename)84 open_coff_file(struct prog_info *pi, char *filename)
85 {
86 
87 	int ok;
88 	FILE *fp;
89 	char *p;
90 
91 
92 	ci = calloc(1, sizeof(struct coff_info));
93 	if (!ci)
94 		return (0);
95 
96 	ok = True;
97 	/* default values */
98 	ci->CurrentFileNumber = 0;
99 	ci->pRomMemory = 0;
100 	ci->pEEPRomMemory = 0;
101 	ci->MaxRomAddress = 0;
102 	ci->MaxEepromAddress = 0;
103 	ci->NeedLineNumberFixup = 0;
104 	ci->GlobalStartAddress = -1;
105 	ci->GlobalEndAddress = 0;
106 
107 	/* Linked lists start out at zero */
108 	InitializeList(&ci->ListOfSectionHeaders);
109 	InitializeList(&ci->ListOfRawData);
110 	InitializeList(&ci->ListOfRelocations);
111 	InitializeList(&ci->ListOfLineNumbers);
112 	InitializeList(&ci->ListOfSymbols);
113 	InitializeList(&ci->ListOfGlobals);
114 	InitializeList(&ci->ListOfSpecials);
115 	InitializeList(&ci->ListOfUndefined);
116 	InitializeList(&ci->ListOfStrings);
117 	InitializeList(&ci->ListOfTypes);
118 	InitializeList(&ci->ListOfSplitLines);
119 
120 	/* add two default sections to SectionHeaders */
121 	if (!AllocateListObject(&ci->ListOfSectionHeaders, sizeof(struct external_scnhdr)) ||
122 	        !AllocateListObject(&ci->ListOfSectionHeaders, sizeof(struct external_scnhdr))) {
123 
124 		fprintf(stderr, "\nOut of memory allocating section headers!");
125 		return (0);
126 	}
127 
128 	/* add to string table */
129 	p = (char *)AllocateListObject(&ci->ListOfStrings,  4);
130 	if (!p) {
131 		fprintf(stderr, "\nOut of memory allocating string table space!");
132 		return (0);
133 	}
134 
135 	/* Allocate space for binary output into ROM, and EEPROM memory buffers for COFF output */
136 	/* ASSUMES ci->device is accurate */
137 	if ((ci->pRomMemory = AllocateListObject(&ci->ListOfRawData, pi->device->flash_size * 2)) != 0) {
138 		if ((ci->pEEPRomMemory = AllocateListObject(&ci->ListOfRawData, pi->device->eeprom_size)) != 0) {
139 			ok = True; /* only true if both buffers are properly allocated */
140 			/* now fill them with 0xff's to simulate flash erasure */
141 			memset((void *)ci->pRomMemory, 0xff, pi->device->flash_size * 2);
142 			memset((void *)ci->pEEPRomMemory,    0xff,    pi->device->eeprom_size);
143 		}
144 	}
145 	if (ok != True)
146 		return (0);
147 
148 	fp = fopen(filename,"wb");
149 	if (fp == NULL) {
150 		fprintf(stderr,"Error: cannot write coff file\n");
151 		return (fp);
152 	}
153 	/* simulate void type .stabs void:t15=r1;*/
154 	stab_add_local_type("void", "15=r1;0;0;");
155 
156 	return (fp);
157 }
158 
159 void
write_coff_file(struct prog_info * pi)160 write_coff_file(struct prog_info *pi)
161 {
162 
163 	char *p;
164 	struct external_scnhdr *pSectionHdr;
165 	struct syment *pEntry;
166 	union auxent *pAux;
167 	unsigned long *plong;
168 	int NumberOfSymbols, SymbolIndex, LastFileIndex, LastFunctionIndex, LastFunctionAddress;
169 	LISTNODE *pNode;
170 	int LinesOffset, SymbolsOffset, RawOffset;
171 	struct lineno *pLine;
172 
173 	/* add two special sections */
174 	/* one for .text */
175 	if ((pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSpecials, sizeof(struct syment) * 2)) == 0) {
176 		fprintf(stderr, "\nOut of memory allocating special headers for .text!");
177 		return;
178 	}
179 	memset(pEntry->n_name, 0, 8);
180 	strcpy(pEntry->n_name, ".text");
181 	pEntry->n_value = 0;
182 	pEntry->n_scnum = 1;
183 	pEntry->n_type = 0;
184 	pEntry->n_sclass = C_STAT;
185 	pEntry->n_numaux = 1;
186 	pEntry++;
187 	pAux = (union auxent *)pEntry;
188 	pAux->x_scn.x_scnlen = ci->MaxRomAddress + 2;
189 	pAux->x_scn.x_nreloc = 0;
190 	pAux->x_scn.x_nlinno = ci->ListOfLineNumbers.TotalItems;
191 	/* one for .bss */
192 	if ((pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSpecials, sizeof(struct syment) * 2)) == 0) {
193 		fprintf(stderr, "\nOut of memory allocating special header for .bss!");
194 		return;
195 	}
196 	memset(pEntry->n_name, 0, 8);
197 	strcpy(pEntry->n_name, ".bss");
198 	if (ci->GlobalStartAddress == -1) {
199 		ci->GlobalEndAddress = ci->GlobalStartAddress = 0x60;
200 	}
201 	pEntry->n_value = ci->GlobalStartAddress;
202 	pEntry->n_scnum = 2;
203 	pEntry->n_type = 0;
204 	pEntry->n_sclass = C_STAT;
205 	pEntry->n_numaux = 1;
206 	pEntry++;
207 	pAux = (union auxent *)pEntry;
208 	pAux->x_scn.x_scnlen = 0; /* we don't store any data here */
209 	pAux->x_scn.x_nreloc = 0;
210 	pAux->x_scn.x_nlinno = 0;
211 
212 	/* one more for .data - eeprom ??? */
213 
214 	/* Calculate common offsets into the file */
215 	RawOffset = sizeof(struct external_filehdr) + ci->ListOfSectionHeaders.TotalBytes;
216 	LinesOffset = RawOffset + ci->MaxRomAddress + 2; /* ignore eeprom for now */
217 	SymbolsOffset = LinesOffset + ci->ListOfLineNumbers.TotalBytes;
218 
219 	/* Clean up loose ends in string table */
220 	if (!(plong  = (unsigned long *)FindFirstListObject(&ci->ListOfStrings))) {
221 		fprintf(stderr,"\nInternal error in string table!");
222 		return;
223 	}
224 	*plong = ci->ListOfStrings.TotalBytes; /* Size of string table */
225 
226 	/* Clean up loose ends in symbol table */
227 
228 	/*	symbol table - Filename value - index to next .file or global symbol */
229 	/* The value of that symbol equals the symbol table entry index of the next .file symbol or .global */
230 	LastFunctionAddress = ci->MaxRomAddress;
231 	NumberOfSymbols = ci->ListOfSymbols.TotalItems + ci->ListOfSpecials.TotalItems + ci->ListOfGlobals.TotalItems;
232 	SymbolIndex = LastFileIndex = NumberOfSymbols;
233 	LastFunctionIndex = 0; /* set to zero on last function */
234 	for (pEntry = (struct syment *)FindLastListObject(&ci->ListOfSymbols);
235 	        pEntry != 0;
236 	        pEntry = (struct syment *)FindNextLastListObject(&ci->ListOfSymbols)) {
237 
238 		/* Search for .file entries designated by C_FILE */
239 		if (pEntry->n_sclass == C_FILE) {
240 			pEntry->n_value = LastFileIndex;
241 			LastFileIndex = SymbolIndex; /* save current index */
242 		}
243 		/* Search for Function entries C_EXT */
244 		else if (pEntry->n_sclass == C_EXT) {
245 			pEntry++;
246 			pAux = (union auxent *)pEntry;
247 			pAux->x_sym.x_misc.x_fsize = LastFunctionAddress - pEntry->n_value; /* function updated size */
248 			pAux->x_sym.x_fcnary.x_fcn.x_lnnoptr += LinesOffset;
249 			LastFunctionAddress = pEntry->n_value;
250 			pAux->x_sym.x_fcnary.x_fcn.x_endndx = LastFunctionIndex; /* point to next function index */
251 			pAux->x_sym.x_tvndx = 0; /* ??? */
252 			LastFunctionIndex = SymbolIndex;
253 		} else if ((pEntry->n_sclass == C_FCN) || (pEntry->n_sclass == C_BLOCK)) {
254 			if (pEntry->n_name[1] == 'b') {
255 				/* .bf and .bb */
256 				pEntry++;
257 				pAux = (union auxent *)pEntry;
258 				pAux->x_sym.x_fcnary.x_fcn.x_endndx = LastFunctionIndex;
259 			}
260 		}
261 		/* else do nothing */
262 
263 		/* update current symbol index */
264 		pNode = GetCurrentNode(&ci->ListOfSymbols);
265 		SymbolIndex -= (pNode->Size / sizeof(struct syment));
266 	}
267 
268 	/* File Header */
269 	ci->FileHeader.f_magic = MAGIC_NUMBER_AVR;
270 	ci->FileHeader.f_nscns = 2;
271 	ci->FileHeader.f_timdat = pi->time;
272 	ci->FileHeader.f_symptr = SymbolsOffset;
273 	ci->FileHeader.f_nsyms = NumberOfSymbols;
274 	ci->FileHeader.f_opthdr = 0;
275 	ci->FileHeader.f_flags = 0xff; /*F_RELFLG;*/ /* No relocation information available */
276 
277 	/* write it out */
278 	if (fwrite(&ci->FileHeader, 1, sizeof(struct external_filehdr), pi->coff_file) !=  sizeof(struct external_filehdr)) {
279 		fprintf(stderr,"\nFile error writing header ...(disk full?)");
280 		return;
281 	}
282 
283 	/* Optional Information */
284 
285 	/* Section 1 Header */
286 	pSectionHdr = (struct external_scnhdr *)FindFirstListObject(&ci->ListOfSectionHeaders);
287 	if (!pSectionHdr) {
288 		fprintf(stderr, "\nInternal Coff error - cannot find section header .text!");
289 		return;
290 	}
291 	memset(&pSectionHdr->s_name[0], 0, sizeof(struct external_scnhdr));
292 	strcpy(&pSectionHdr->s_name[0], ".text");
293 	pSectionHdr->s_paddr = 0;
294 	pSectionHdr->s_vaddr = 0;
295 	pSectionHdr->s_size = ci->MaxRomAddress + 2; /* remember the last instruction */
296 	pSectionHdr->s_scnptr = RawOffset;
297 	pSectionHdr->s_relptr = 0;
298 	pSectionHdr->s_lnnoptr = LinesOffset;
299 	pSectionHdr->s_nreloc = 0;
300 	pSectionHdr->s_nlnno = ci->ListOfLineNumbers.TotalBytes/sizeof(struct lineno);
301 	pSectionHdr->s_flags = STYP_TEXT;
302 
303 	/* write it out */
304 	if (fwrite(&pSectionHdr->s_name[0], 1, sizeof(struct external_scnhdr), pi->coff_file) !=  sizeof(struct external_scnhdr)) {
305 		fprintf(stderr,"\nFile error writing section header ...(disk full?)");
306 		return;
307 	}
308 
309 	/* Section 2 Header */
310 	pSectionHdr = (struct external_scnhdr *)FindNextListObject(&ci->ListOfSectionHeaders);
311 	if (!pSectionHdr) {
312 		fprintf(stderr, "\nInternal Coff error - cannot find section header .bss!");
313 		return;
314 	}
315 	memset(&pSectionHdr->s_name[0], 0, sizeof(struct external_scnhdr));
316 	strcpy(&pSectionHdr->s_name[0], ".bss");
317 	/* later expansion */
318 	pSectionHdr->s_paddr = ci->GlobalStartAddress;
319 	pSectionHdr->s_vaddr = ci->GlobalStartAddress;
320 	pSectionHdr->s_flags = STYP_DATA; /* seems it should be STYP_BSS */
321 
322 	/* write it out */
323 	if (fwrite(&pSectionHdr->s_name[0], 1, sizeof(struct external_scnhdr), pi->coff_file) !=  sizeof(struct external_scnhdr)) {
324 		fprintf(stderr,"\nFile error writing section header ...(disk full?)");
325 		return;
326 	}
327 
328 	/* Section N Header - .data or eeprom */
329 
330 	/* Raw Data for Section 1 */
331 	if ((p = FindFirstListObject(&ci->ListOfRawData)) == 0) {
332 		fprintf(stderr,"\nInternal error - unable to find binary data!");
333 		return;
334 	}
335 
336 	/* write it out */
337 	if (fwrite(p, 1, ci->MaxRomAddress + 2, pi->coff_file) != (size_t)(ci->MaxRomAddress + 2)) {
338 		fprintf(stderr,"\nFile error writing raw .text data ...(disk full?)");
339 		return;
340 	}
341 	/* Raw data for section n */
342 
343 	/* Relocation Info for section 1 */
344 
345 	/* Relocation info for section n */
346 
347 	/* Line numbers for section 1 */
348 	for (pLine = (struct lineno *)FindFirstListObject(&ci->ListOfLineNumbers);
349 	        pLine != 0;
350 	        pLine = (struct lineno *)FindNextListObject(&ci->ListOfLineNumbers)) {
351 
352 		pNode = GetCurrentNode(&ci->ListOfLineNumbers);
353 
354 		/* write it out */
355 		if (fwrite(pLine, 1, pNode->Size, pi->coff_file) != pNode->Size) {
356 			fprintf(stderr,"\nFile error writing line numbers ...(disk full?)");
357 			return;
358 		}
359 	}
360 
361 
362 	/* Line numbers for section n */
363 
364 	/* Symbol table */
365 	for (pEntry = (struct syment *)FindFirstListObject(&ci->ListOfSymbols);
366 	        pEntry != 0;
367 	        pEntry = (struct syment *)FindNextListObject(&ci->ListOfSymbols)) {
368 
369 		pNode = GetCurrentNode(&ci->ListOfSymbols);
370 
371 		/* write it out */
372 		if (fwrite(pEntry, 1, pNode->Size, pi->coff_file) != pNode->Size) {
373 			fprintf(stderr,"\nFile error writing symbol table ...(disk full?)");
374 			return;
375 		}
376 	}
377 
378 	/* Symbol table of Globals */
379 	for (pEntry = (struct syment *)FindFirstListObject(&ci->ListOfGlobals);
380 	        pEntry != 0;
381 	        pEntry = (struct syment *)FindNextListObject(&ci->ListOfGlobals)) {
382 
383 		pNode = GetCurrentNode(&ci->ListOfGlobals);
384 
385 		/* write it out */
386 		if (fwrite(pEntry, 1, pNode->Size, pi->coff_file) != pNode->Size) {
387 			fprintf(stderr,"\nFile error writing global symbols ...(disk full?)");
388 			return;
389 		}
390 	}
391 
392 	/* Specials .text, .bss, .data */
393 
394 	for (pEntry = (struct syment *)FindFirstListObject(&ci->ListOfSpecials);
395 	        pEntry != 0;
396 	        pEntry = (struct syment *)FindNextListObject(&ci->ListOfSpecials)) {
397 
398 		pNode = GetCurrentNode(&ci->ListOfSpecials);
399 
400 		/* write it out */
401 		if (fwrite(pEntry, 1, pNode->Size, pi->coff_file) != pNode->Size) {
402 			fprintf(stderr,"\nFile error writing special symbols ...(disk full?)");
403 			return;
404 		}
405 	}
406 
407 	/* String Table */
408 	for (p = (char *)FindFirstListObject(&ci->ListOfStrings);
409 	        p != 0;
410 	        p = (char *)FindNextListObject(&ci->ListOfStrings)) {
411 
412 		pNode = GetCurrentNode(&ci->ListOfStrings);
413 
414 		/* write it out */
415 		if (fwrite(p, 1, pNode->Size, pi->coff_file) != pNode->Size) {
416 			fprintf(stderr,"\nFile error writing strings data ...(disk full?)");
417 			return;
418 		}
419 	}
420 
421 	return;
422 }
423 
424 void
write_coff_eeprom(struct prog_info * pi,int address,unsigned char data)425 write_coff_eeprom(struct prog_info *pi, int address, unsigned char data)
426 {
427 
428 	/* Coff output keeps track of binary data in memory buffers */
429 	if (ci->pEEPRomMemory) {
430 		if (address <= pi->device->eeprom_size) {
431 			*(ci->pEEPRomMemory + address) = data;
432 			if (address >= ci->MaxEepromAddress)
433 				ci->MaxEepromAddress = address;   /* keep high water mark */
434 		} else {
435 			pi->error_count++;
436 			fprintf(stderr, "Error: EEPROM address %d exceeds max range %ld", address, pi->device->eeprom_size);
437 		}
438 	}
439 }
440 
441 void
write_coff_program(struct prog_info * pi,int address,unsigned int data)442 write_coff_program(struct prog_info *pi, int address, unsigned int data)
443 {
444 
445 	unsigned char *pByte;
446 
447 	/* Coff output keeps track of binary data in memory buffers, address is in bytes not words */
448 	if (ci->pRomMemory) {
449 		/* JEG	if ( address <= pi->device->flash_size ) {  */  /* JEG 4-23-03 */
450 		if (address <= pi->device->flash_size*2) {
451 			pByte = (unsigned char *)(ci->pRomMemory + address); /* point to low byte in memory */
452 			*pByte++ = (data & 0xff);   /* low byte */
453 			*pByte = ((data >> 8) & 0xff); /* high byte */
454 
455 			if (address >= ci->MaxRomAddress)
456 				ci->MaxRomAddress = address;   /* keep high water mark */
457 		} else {
458 			pi->error_count++;
459 			/* JEG		fprintf(stderr, "Error: FLASH address %d exceeds max range %d", address, pi->device->flash_size ); */
460 			fprintf(stderr, "Error: FLASH address %d exceeds max range %ld", address, pi->device->flash_size*2);
461 		}
462 	}
463 }
464 
465 void
close_coff_file(struct prog_info * pi,FILE * fp)466 close_coff_file(struct prog_info *pi, FILE *fp)
467 {
468 
469 	/* close the output file */
470 	fclose(fp);
471 	pi->coff_file = 0;
472 
473 	/* free all the internal memory buffers used by ci */
474 
475 	FreeList(&ci->ListOfSectionHeaders);
476 	FreeList(&ci->ListOfRawData);
477 	FreeList(&ci->ListOfRelocations);
478 	FreeList(&ci->ListOfLineNumbers);
479 	FreeList(&ci->ListOfSymbols);
480 	FreeList(&ci->ListOfGlobals);
481 	FreeList(&ci->ListOfUndefined);
482 	FreeList(&ci->ListOfStrings);
483 	FreeList(&ci->ListOfTypes);
484 	FreeList(&ci->ListOfSplitLines);
485 
486 	/* now free ci */
487 	free(ci);
488 	ci = 0;
489 }
490 
491 int
parse_stabs(struct prog_info * pi,char * p)492 parse_stabs(struct prog_info *pi, char *p)
493 {
494 
495 	int ok = True;
496 	int TypeCode, n;
497 	char *pString, *p2, *p3, *p4, *p5, *pType, *pp, *pJoined;
498 
499 
500 	if (!GET_ARG_I(pi->args, ARG_COFF) || (pi->pass == PASS_1))
501 		return (True);
502 
503 	/* stabs debugging information is in the form:
504 	.stabs "symbolic info string", HexorDecimalTypecode, parm3, parm4, parm5
505 	parm1, parm2, parm3 depend on typecode
506 
507 	N_LSYM	0x80		local sym: name,,0,type,offset
508 	N_OPT	0x3c		compiler options
509 	N_SO	0x64		source file name: name,,0,0,address
510 	N_SOL	0x84		#included file name: name,,0,0,address
511 	N_FUN	0x24		procedure: name,,0,linenumber,address
512 	N_GSYM	0x20		global symbol: name,,0,type,0
513 	N_LCSYM	0x28		.lcomm symbol: name,,0,type,address
514 	N_STSYM	0x26		static symbol: name,,0,type,address
515 	N_RSYM	0x40		register sym: name,,0,type,register
516 	N_PSYM	0xa0		parameter: name,,0,type,offset
517 
518 	*/
519 
520 	/* Look for multiple commands per line */
521 
522 	/* .stabs "linktag:T19=s46next:20=*19,0,16;last:20,16,16;a:21=ar1;0;2;22=ar1;0;3;1,32,96;\\",128,0,0,0 */
523 	/* .stabs "b:23=ar1;0;4;24=ar1;0;5;2,128,240;;",128,0,0,0 */
524 
525 
526 	/* Look for continuation lines per line */
527 
528 	/* Get String information as a token */
529 	/* Parse the tokens in the stabn line buffer */
530 	pString = get_next_token(p, TERM_DOUBLEQUOTE);      /* zap first doublequote */
531 	p2 = get_next_token(pString, TERM_DOUBLEQUOTE);     /* zap last doublequote */
532 	p2 = get_next_token(p2, TERM_COMMA);                /* zap comma */
533 	p3 = get_next_token(p2, TERM_COMMA);
534 	p4 = get_next_token(p3, TERM_COMMA);
535 	p5 = get_next_token(p4, TERM_COMMA);
536 	get_next_token(p5, TERM_END);  /* zap CR LF, make ASCIIZ */
537 
538 	if (!pString || !p2 || !p3 || !p4 || !p5)
539 		return (False);
540 
541 	/* Check for split lines */
542 	n = strlen(pString);
543 	if ((pString[n - 1] == '\\') && (pString[n - 2] == '\\')) {
544 		/* We have a continuation string here */
545 		pString[n - 2] = 0;
546 		n -= 2;
547 		if (!(pp = (char *)AllocateListObject(&ci->ListOfSplitLines, n + 1))) {
548 			fprintf(stderr, "\nOut of memory allocating continuation line!");
549 			return (False);
550 		}
551 		strcpy(pp, pString);   /* loose the continuation characters */
552 		return (True);
553 	}
554 	if (ci->ListOfSplitLines.TotalItems > 0) {
555 		/* Join lines together and process */
556 		if (!(pJoined = calloc(1, n + ci->ListOfSplitLines.TotalBytes))) {
557 			fprintf(stderr, "\nOut of memory joining continuation lines!");
558 			return (False);
559 		}
560 		for (pp = (char *)FindFirstListObject(&ci->ListOfSplitLines);
561 		        pp != 0;
562 		        pp = (char *)FindNextListObject(&ci->ListOfSplitLines)) {
563 
564 			strcat(pJoined, pp);   /* connect the lines */
565 		}
566 		strcat(pJoined, pString);
567 		FreeList(&ci->ListOfSplitLines);
568 		if (!AddListObject(&ci->ListOfSplitLines, pJoined, n + ci->ListOfSplitLines.TotalBytes)) {
569 			fprintf(stderr, "\nUnable to add joined continuation line");
570 			return (False);
571 		}
572 		pString = pJoined;
573 	}
574 
575 
576 	if (*p2 == '0')
577 		TypeCode = atox(p2);    /* presume to be hex 0x */
578 	else
579 		TypeCode = atoi(p2);
580 
581 	switch (TypeCode) {
582 
583 	case N_OPT:     /* compiler options */
584 		break;      /* nothing used here */
585 
586 	case N_SO:      /* source file name: name,,0,0,address */
587 		ok = stab_add_filename(pString, p5);
588 		break;
589 
590 	case N_GSYM:    /* global symbol: name,,0,type,0 */
591 		pType = get_next_token(pString, TERM_COLON);    /* separate at colon */
592 		ok = stab_add_global(pi, pString, pType);
593 		break;
594 
595 	case N_FUN:     /* procedure: name,,0,linenumber,address */
596 		ok = stab_add_function(pi, pString, p5);
597 		break;
598 
599 	case N_LSYM:    /* local sym: name,,0,type,offset */
600 		/* pString, p2 = TypeCode, p3 = 0, p4 = 0, p5 = offset */
601 		pType = get_next_token(pString, TERM_COLON);    /* pType = symbol descriptor (character after the colon) */
602 		if (*pType == 't')
603 			ok = stab_add_local_type(pString, ++pType);
604 		else if (*pType == 'T')
605 			ok = stab_add_tag_type(pString, ++pType);
606 		else
607 			ok = stab_add_local(pi, pString, pType, p5);
608 		break;
609 
610 	case N_RSYM:    /* Symbol:[P|r]type,0,size,register */
611 		pType = get_next_token(pString, TERM_COLON);    /* separate at colon */
612 		ok = stab_add_local_register(pi, pString, pType, p5);
613 		break;
614 
615 	case N_LCSYM:   /* .lcomm symbol: name,,0,type,address */
616 		ok = True;
617 		break;  /* ignore constants */
618 
619 	case N_STSYM:   /* static symbol: name,,0,type,address */
620 		pType = get_next_token(pString, TERM_COLON);    /* separate at colon */
621 		ok = stab_add_static_symbol(pi, pString, pType, p5);
622 		break;
623 
624 	case N_PSYM:    /* parameter: name,,0,type,offset */
625 		pType = get_next_token(pString, TERM_COLON);    /* separate at colon */
626 		ok = stab_add_parameter_symbol(pi, pString, pType, p5);
627 		break;
628 
629 	case N_SOL:     /* #included file name: name,,0,0,address */
630 		ok = True;
631 		break;  /* ignore include files */
632 
633 	default:
634 		ok = False;
635 	}
636 
637 	if (ci->ListOfSplitLines.TotalItems > 0)
638 		FreeList(&ci->ListOfSplitLines);
639 
640 	return (ok);
641 }
642 
643 int
parse_stabn(struct prog_info * pi,char * p)644 parse_stabn(struct prog_info *pi, char *p)
645 {
646 
647 	int ok = True;
648 	int TypeCode, Level;
649 	char *p1, *p2, *p3, *p4, *pLabel, *pFunction;
650 
651 	/* stabn debugging information is in the form:
652 	.stabn TypeCode, 0, parm1, parm2
653 	parm1 is level
654 	parm2 is Label-Function
655 
656 	compiler currently produces the following TypeCodes:
657 	N_LBRAC	0xc0		left bracket: 0,,0,nesting level,address
658 	N_RBRAC	0xe0		right bracket: 0,,0,nesting level,address
659 	N_SLINE	0x44		src line: 0,,0,linenumber,address
660 	*/
661 
662 	if (!GET_ARG_I(pi->args, ARG_COFF) || (pi->pass == PASS_1))
663 		return (True);
664 
665 	/* Parse the tokens in the stabn line buffer */
666 	p1 = get_next_token(p, TERM_SPACE);
667 	p2 = get_next_token(p1, TERM_COMMA);
668 	p3 = get_next_token(p2, TERM_COMMA);
669 	p4 = get_next_token(p3, TERM_COMMA);
670 	get_next_token(p4, TERM_END);  /* zap CR LF, make ASCIIZ */
671 
672 	if (!p1 || !p2 || !p3 || !p4)
673 		return (False);
674 
675 	/* first convert TypeCode to binary */
676 	if (*p1 == '0')
677 		TypeCode = atox(p1);    /* presume to be hex 0x */
678 	else
679 		TypeCode = atoi(p1);
680 
681 	Level = atoi(p3);   /* line number or level */
682 	pLabel = p4;                /* Assembly label */
683 	pFunction = get_next_token(pLabel, TERM_DASH);   /* Function */
684 
685 	switch (TypeCode) {
686 	case N_SLINE:           /* src line: 0,,0,linenumber,address */
687 		ok = stab_add_lineno(pi, Level, pLabel, pFunction);
688 		break;
689 
690 	case N_LBRAC:           /* left bracket: 0,,0,nesting level,address */
691 		ok = stab_add_lbracket(pi, Level, pLabel, pFunction);
692 		break;
693 
694 	case N_RBRAC:           /* right bracket: 0,,0,nesting level,address */
695 		ok = stab_add_rbracket(pi, Level, pLabel, pFunction);
696 		break;
697 
698 	default:
699 		fprintf(stderr, "\nUnknown .stabn TypeCode = 0x%x", TypeCode);
700 		ok = False;
701 	}
702 	return (ok);
703 }
704 
705 int
stab_add_lineno(struct prog_info * pi,int LineNumber,char * pLabel,char * pFunction)706 stab_add_lineno(struct prog_info *pi, int LineNumber, char *pLabel, char *pFunction)
707 {
708 
709 	int Address;
710 	struct lineno *pln;
711 	struct syment *pEntry;
712 	union auxent *pAux;
713 
714 	/* Allocate LineNumber Table entry and fill it in */
715 	pln = (struct lineno *)AllocateListObject(&ci->ListOfLineNumbers, sizeof(struct lineno));
716 	if (!pln) {
717 		fprintf(stderr, "\nOut of memory allocating lineno table for function %s", pFunction);
718 		return (False);
719 	}
720 	/* set value field to be address of label in bytes */
721 	if (!get_symbol(pi, pLabel, &Address)) {
722 		fprintf(stderr, "\nUnable to locate label %s", pLabel);
723 		return (False);
724 	}
725 	pln->l_addr.l_paddr = Address * 2; /* need byte quanities */
726 
727 	/* Line number is relative to beginning of function, starts at 1 */
728 	if (ci->FunctionStartLine == 0) {
729 		/* This line number is that same as the function start */
730 		ci->FunctionStartLine = LineNumber;
731 	}
732 	pln->l_lnno = LineNumber - ci->FunctionStartLine + 1;
733 	ci->CurrentSourceLine = LineNumber; /* keep track of source line for .eb .ef arrays */
734 	if (ci->NeedLineNumberFixup) {
735 		/* need to go into symbol table and fix last NeedLineNumberFixup entries */
736 		for (pEntry = (struct syment *)FindLastListObject(&ci->ListOfSymbols);
737 		        (pEntry != 0) && (ci->NeedLineNumberFixup != 0);
738 		        pEntry = (struct syment *)FindNextLastListObject(&ci->ListOfSymbols)) {
739 
740 			/* Fix up line number entries */
741 			if ((pEntry->n_sclass == C_FCN) || (pEntry->n_sclass == C_BLOCK) || (pEntry->n_sclass == C_EXT)) {
742 				pEntry++;
743 				pAux = (union auxent *)pEntry;
744 				pAux->x_sym.x_misc.x_lnsz.x_lnno = LineNumber;
745 				ci->NeedLineNumberFixup--;
746 			}
747 		}
748 	}
749 
750 	return (True);
751 }
752 
753 int
stab_add_lbracket(struct prog_info * pi,int Level,char * pLabel,char * pFunction)754 stab_add_lbracket(struct prog_info *pi, int Level, char *pLabel, char *pFunction)
755 {
756 
757 	int Address;
758 	struct syment *pEntry;
759 	union auxent *pAux;
760 
761 	if (!get_symbol(pi, pLabel, &Address)) {
762 		fprintf(stderr, "\nUnable to locate label %s", pLabel);
763 		return (False);
764 	}
765 
766 	/* Now create a .bb symbol table entry and aux entry too */
767 	pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSymbols,  sizeof(struct syment) * 2);
768 	if (!pEntry) {
769 		fprintf(stderr, "\nOut of memory allocating symbol table entry for .bb %s", pLabel);
770 		return (False);
771 	}
772 	/* n_name */
773 	memset(pEntry->n_name, 0, 8);
774 	strcpy(pEntry->n_name, ".bb");
775 
776 	pEntry->n_value = Address * 2;  /* bytes not words */
777 	pEntry->n_scnum = 1;    /* .text */
778 	pEntry->n_type = 0;
779 	pEntry->n_sclass = C_BLOCK;
780 	pEntry->n_numaux = 1;
781 	pEntry++;   /* point to aux entry */
782 	pAux = (union auxent *)pEntry;
783 	pAux->x_sym.x_misc.x_lnsz.x_lnno = 0;   /* UNKNOWN - post process */
784 	pAux->x_sym.x_misc.x_lnsz.x_size = 0;   /* UNKNOWN - post process */
785 	ci->NeedLineNumberFixup++; /* once for .bb block */
786 	return (True);
787 }
788 
789 int
stab_add_rbracket(struct prog_info * pi,int Level,char * pLabel,char * pFunction)790 stab_add_rbracket(struct prog_info *pi, int Level, char *pLabel, char *pFunction)
791 {
792 
793 	int Address;
794 	struct syment *pEntry;
795 	union auxent *pAux;
796 
797 	if (!get_symbol(pi, pLabel, &Address)) {
798 		fprintf(stderr, "\nUnable to locate label %s", pLabel);
799 		return (False);
800 	}
801 
802 	/* Now create a .eb symbol table entry */
803 	pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSymbols,  sizeof(struct syment) * 2);
804 	if (!pEntry) {
805 		fprintf(stderr, "\nOut of memory allocating symbol table entry for .eb %s", pLabel);
806 		return (False);
807 	}
808 	/* n_name */
809 	memset(pEntry->n_name, 0, 8);
810 	strcpy(pEntry->n_name, ".eb");
811 	pEntry->n_sclass = C_BLOCK;
812 	pEntry->n_value = Address * 2;  /* bytes not words */
813 	pEntry->n_scnum = 1;    /* .text */
814 	pEntry->n_type = 0;
815 	pEntry->n_numaux = 1;
816 	pEntry++;   /* point to aux entry */
817 	pAux = (union auxent *)pEntry;
818 	pAux->x_sym.x_misc.x_lnsz.x_lnno = ci->CurrentSourceLine;
819 
820 	/* create an .ef if at level 0 */
821 	if (Level == 0) {
822 
823 		/* Now create a .ef symbol table entry */
824 		pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSymbols,  sizeof(struct syment) * 2);
825 		if (!pEntry) {
826 			fprintf(stderr, "\nOut of memory allocating symbol table entry for .ef %s", pLabel);
827 			return (False);
828 		}
829 		/* n_name */
830 		memset(pEntry->n_name, 0, 8);
831 		strcpy(pEntry->n_name, ".ef");
832 		pEntry->n_sclass = C_FCN;
833 		pEntry->n_value = Address * 2;  /* bytes not words */
834 		pEntry->n_scnum = 1;    /* .text */
835 		pEntry->n_type = 0;
836 		pEntry->n_numaux = 1;
837 		pEntry++;   /* point to aux entry */
838 		pAux = (union auxent *)pEntry;
839 		pAux->x_sym.x_misc.x_lnsz.x_lnno = ci->CurrentSourceLine;
840 	}
841 	return (True);
842 }
843 
844 int
stab_add_filename(char * pName,char * pLabel)845 stab_add_filename(char *pName, char *pLabel)
846 {
847 
848 	int ok, n;
849 	struct syment *pEntry;
850 	union auxent *pAux;
851 	char *p;
852 
853 	/* if( pLabel == "Ltext0" ) then beginning of .text, pName = cwd, next pName = file */
854 
855 	/* if( pLabel == "Letext" ) then end of .text , pName == NULL */
856 
857 	/* we only need the one not ending in Slash */
858 	ok = True;
859 	n = strlen(pName);
860 	if (n > 0) {
861 		if ((pName[ n - 1] == '\\') || (pName[ n - 1] == '/'))
862 			return (True); /* ignore */
863 	} else
864 		return (True);
865 
866 
867 	/* allocate entry in symbol table list */
868 	pEntry = (struct syment *)AllocateTwoListObjects(
869 	             &ci->ListOfSymbols,  sizeof(struct syment) * 2);  /* aux entry too */
870 	if (!pEntry) {
871 		fprintf(stderr, "\nOut of memory allocating symbol table entry for global %s", pName);
872 		return (False);
873 	}
874 	/* n_name */
875 	memset(pEntry->n_name, 0, 8);
876 	strcpy(pEntry->n_name, ".file");
877 	/* n_value is determined after processing done UNKNOWN - post process */
878 	/* The value of that symbol equals the symbol table entry index of the next .file symbol or .global */
879 	/* post process */
880 	pEntry->n_scnum = N_DEBUG;
881 	pEntry->n_sclass = C_FILE;
882 	pEntry->n_numaux = 1;
883 	pEntry++;   /* point to aux entry */
884 	pAux = (union auxent *)pEntry;
885 
886 	/* Add Label name to symbol table */
887 	if (n <= FILNMLEN) {
888 		/* inline filename */
889 		memset(pAux->x_file.x_fname, 0, FILNMLEN);
890 		strncpy(pAux->x_file.x_fname, pName, n);   /* might not be zero terminated */
891 	} else {
892 		pAux->x_file.x_n.x_zeroes = 0;  /* symbol name is in string table */
893 		pAux->x_file.x_n.x_offset = ci->ListOfStrings.TotalBytes;
894 
895 		/* add to string table */
896 		p = (char *)AllocateListObject(&ci->ListOfStrings,  n + 1);
897 		if (!p) {
898 			fprintf(stderr, "\nOut of memory allocating string table space!");
899 			return (False);
900 		}
901 		strcpy(p, pName);
902 	}
903 	return (ok);
904 }
905 
906 int
stab_add_function(struct prog_info * pi,char * pName,char * pLabel)907 stab_add_function(struct prog_info *pi, char *pName, char *pLabel)
908 {
909 
910 	int n, Address;
911 	unsigned short CoffType, Type;
912 	struct syment *pEntry;
913 	char *pType;
914 	struct lineno *pln;
915 	union auxent *pAux;
916 	int SymbolIndex;
917 
918 	pType = get_next_token(pName, TERM_COLON);  /* pType = symbol descriptor (character after the colon) */
919 	Type = atoi(pType + 1);     /* skip past F, predefined variable type */
920 	if ((CoffType = GetCoffType(Type)) == 0) {
921 		fprintf(stderr, "\nUnrecognized return type found for function %s = %d", pName, Type);
922 		return (False);
923 	}
924 	/* Get Current Symbol Index, Allocate Symbol Table entry and fill it in */
925 	SymbolIndex = ci->ListOfSymbols.TotalItems;
926 	pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSymbols, sizeof(struct syment) * 2);
927 	if (!pEntry) {
928 		fprintf(stderr, "\nOut of memory allocating symbol table entry for function %s", pName);
929 		return (False);
930 	}
931 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
932 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
933 	}
934 	if (!get_symbol(pi, pLabel, &Address)) {
935 		fprintf(stderr, "\nUnable to locate function %s", pName);
936 		return (False);
937 	}
938 	pEntry->n_value = Address * 2;  /* convert words to bytes */
939 	pEntry->n_scnum = 2;    /* .bss */
940 	if ((CoffType = GetCoffType(Type)) == 0) {
941 		fprintf(stderr, "\nUnrecognized type found for function %s = %d", pName, Type);
942 		return (False);
943 	}
944 	pEntry->n_type = (unsigned short)(CoffType | (DT_FCN << 4));
945 	pEntry->n_sclass = C_EXT;
946 	pEntry->n_numaux = 1;
947 	pEntry++;   /* point to aux entry */
948 	pAux = (union auxent *)pEntry;
949 	pAux->x_sym.x_tagndx = SymbolIndex + 1; /* point to the .bf entry index */
950 	pAux->x_sym.x_misc.x_fsize = 0; /* unknown till end */
951 	pAux->x_sym.x_fcnary.x_fcn.x_lnnoptr = ci->ListOfLineNumbers.TotalBytes; /* relative offset to line number entry */
952 	pAux->x_sym.x_fcnary.x_fcn.x_endndx = 0; /* index to next entry */
953 
954 	/* Now add function entry into the line number table */
955 	/* Allocate Symbol Table entry and fill it in */
956 	pln = (struct lineno *)AllocateListObject(&ci->ListOfLineNumbers, sizeof(struct lineno));
957 	if (!pln) {
958 		fprintf(stderr, "\nOut of memory allocating lineno table for function %s", pName);
959 		return (False);
960 	}
961 	pln->l_lnno = 0;
962 	pln->l_addr.l_symndx = SymbolIndex;
963 
964 	/* Initialize the FunctionStartLine from the beginning of the function */
965 	ci->FunctionStartLine = 0;
966 
967 	/* Allocate Symbol Table entry and fill it in */
968 	pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfSymbols, sizeof(struct syment) * 2);
969 	if (!pEntry) {
970 		fprintf(stderr, "\nOut of memory allocating symbol table entry .bf for function %s", pName);
971 		return (False);
972 	}
973 	memset(pEntry->n_name, 0, 8);
974 	strcpy(pEntry->n_name, ".bf");
975 	pEntry->n_value = Address * 2;  /* bytes not words */
976 	pEntry->n_scnum = 1;    /* .text */
977 	pEntry->n_type = 0;
978 	pEntry->n_sclass = C_FCN;
979 	pEntry->n_numaux = 1;
980 	pEntry++;   /* point to aux entry */
981 	pAux = (union auxent *)pEntry;
982 	pAux->x_sym.x_misc.x_lnsz.x_lnno = 0;   /* UNKNOWN - post process */
983 	pAux->x_sym.x_misc.x_lnsz.x_size = 0;   /* UNKNOWN - post process */
984 
985 	ci->NeedLineNumberFixup++; /* once for function C_EXT symbol */
986 	ci->NeedLineNumberFixup++; /* once for .bf block */
987 	return (True);
988 }
989 
990 int
stab_add_global(struct prog_info * pi,char * pName,char * pType)991 stab_add_global(struct prog_info *pi, char *pName, char *pType)
992 {
993 
994 	int n, Address, IsArray, SymbolIndex;
995 	unsigned short CoffType, Type;
996 	struct syment *pEntry;
997 	char *p;
998 	STABCOFFMAP *pMap;
999 
1000 
1001 	n = strlen(pName);      /* see if it's 8 bytes or less */
1002 	Type = atoi(pType + 1);     /* skip past G, predefined variable type */
1003 	if ((CoffType = GetCoffType(Type)) == 0) {
1004 		fprintf(stderr, "\nUnrecognized type found for global %s = %d", pName, Type);
1005 		return (False);
1006 	}
1007 	pMap = (STABCOFFMAP *)GetCurrentListObject(&ci->ListOfTypes);
1008 
1009 	SymbolIndex = ci->ListOfSymbols.TotalItems;
1010 	/* Allocate Symbol Table entry and fill it in, Auxiliary table if its an array */
1011 	if (IsTypeArray(CoffType) == True) {
1012 		IsArray = True;
1013 		pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfGlobals, sizeof(struct syment) * 2);
1014 	} else {
1015 		IsArray = False;
1016 		pEntry = (struct syment *)AllocateListObject(&ci->ListOfGlobals, sizeof(struct syment));
1017 	}
1018 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1019 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
1020 	}
1021 	/* set value field to be address of label in bytes */
1022 	/* add underscore to lookup label */
1023 	if ((p = calloc(1, n + 2)) == 0) {
1024 		fprintf(stderr,"\nOut of memory adding global %s", pName);
1025 		return (False);
1026 	}
1027 	*p = '_';
1028 	strcpy(p + 1, pName);
1029 	if (!get_symbol(pi, p, &Address)) {
1030 		fprintf(stderr, "\nUnable to locate global %s", p);
1031 		free(p);
1032 		return (False);
1033 	}
1034 	free(p);
1035 	pEntry->n_value = Address;  /* already in bytes */
1036 	if (ci->GlobalStartAddress == -1) {
1037 		ci->GlobalStartAddress = Address;
1038 	}
1039 	if (Address < ci->GlobalStartAddress)
1040 		ci->GlobalStartAddress = Address;
1041 	if (Address > ci->GlobalEndAddress)
1042 		ci->GlobalEndAddress = Address;
1043 
1044 	pEntry->n_scnum = 2;    /* .bss */
1045 	pEntry->n_type = CoffType;
1046 	pEntry->n_sclass = C_STAT;
1047 	if (IsArray == False)
1048 		pEntry->n_numaux = 0;
1049 	else {
1050 		pEntry->n_numaux = 1;
1051 		pEntry++;
1052 		AddArrayAuxInfo((union auxent *)pEntry, (unsigned short)SymbolIndex, pMap);
1053 	}
1054 	return (True);
1055 }
1056 
1057 int
stab_add_local(struct prog_info * pi,char * pName,char * pType,char * pOffset)1058 stab_add_local(struct prog_info *pi, char *pName, char *pType, char *pOffset)
1059 {
1060 
1061 	int n, Offset, IsArray;
1062 	unsigned short CoffType, Type, SymbolIndex;
1063 	struct syment *pEntry;
1064 	STABCOFFMAP *pMap;
1065 
1066 	n = strlen(pName);      /* see if it's 8 bytes or less */
1067 	Type = atoi(pType);     /* predefined variable type */
1068 	Offset = atoi(pOffset); /* offset in stack frame */
1069 	if ((CoffType = GetCoffType(Type)) == 0) {
1070 		fprintf(stderr, "\nUnrecognized type found for local %s = %d", pName, Type);
1071 		return (False);
1072 	}
1073 	pMap = (STABCOFFMAP *)GetCurrentListObject(&ci->ListOfTypes);
1074 	SymbolIndex = ci->ListOfSymbols.TotalItems;
1075 	/* Allocate Symbol Table entry and fill it in, Auxiliary table if its an array */
1076 	if (IsTypeArray(CoffType) == True) {
1077 		IsArray = True;
1078 		pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfGlobals, sizeof(struct syment) * 2);
1079 	} else {
1080 		IsArray = False;
1081 		pEntry = (struct syment *)AllocateListObject(&ci->ListOfSymbols, sizeof(struct syment));
1082 	}
1083 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1084 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
1085 	}
1086 	pEntry->n_type = CoffType;
1087 	pEntry->n_sclass = C_AUTO;
1088 	pEntry->n_scnum = N_ABS;
1089 	pEntry->n_value = Offset + 1; /* Silly avr studio is set in its ways */
1090 	if (IsArray == False)
1091 		pEntry->n_numaux = 0;
1092 	else {
1093 		pEntry->n_numaux = 1;
1094 		pEntry++;
1095 		AddArrayAuxInfo((union auxent *)pEntry, SymbolIndex, pMap);
1096 	}
1097 	return (True);
1098 }
1099 
1100 int
stab_add_parameter_symbol(struct prog_info * pi,char * pName,char * pType,char * pOffset)1101 stab_add_parameter_symbol(struct prog_info *pi, char *pName, char *pType, char *pOffset)
1102 {
1103 
1104 	int n, Offset;
1105 	unsigned short CoffType, Type;
1106 	struct syment *pEntry;
1107 
1108 	n = strlen(pName);      /* see if it's 8 bytes or less */
1109 	Type = atoi(pType);     /* predefined variable type */
1110 	Offset = atoi(pOffset); /* offset in stack frame */
1111 	if ((CoffType = GetCoffType(Type)) == 0) {
1112 		fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type);
1113 		return (False);
1114 	}
1115 	/* Allocate Symbol Table entry and fill it in */
1116 	pEntry = (struct syment *)AllocateListObject(&ci->ListOfSymbols, sizeof(struct syment));
1117 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1118 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
1119 	}
1120 	pEntry->n_type = CoffType;
1121 	pEntry->n_sclass = C_ARG;
1122 	pEntry->n_scnum = N_ABS;
1123 	pEntry->n_value = Offset;
1124 	pEntry->n_numaux = 0;
1125 	return (True);
1126 }
1127 
1128 int
stab_add_static_symbol(struct prog_info * pi,char * pName,char * pType,char * pLabel)1129 stab_add_static_symbol(struct prog_info *pi, char *pName, char *pType, char *pLabel)
1130 {
1131 
1132 	int n, Address;
1133 	unsigned short CoffType, Type;
1134 	struct syment *pEntry;
1135 
1136 	n = strlen(pName);      /* see if it's 8 bytes or less */
1137 	Type = atoi(pType + 1);     /* skip past S, predefined variable type */
1138 	if ((CoffType = GetCoffType(Type)) == 0) {
1139 		fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type);
1140 		return (False);
1141 	}
1142 	/* Allocate Symbol Table entry and fill it in */
1143 	pEntry = (struct syment *)AllocateListObject(&ci->ListOfSymbols, sizeof(struct syment));
1144 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1145 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
1146 	}
1147 	pEntry->n_type = CoffType;
1148 	pEntry->n_sclass = C_STAT;
1149 	pEntry->n_scnum = N_ABS;
1150 	if (!get_symbol(pi, pLabel, &Address)) {
1151 		fprintf(stderr, "\nUnable to locate label %s", pLabel);
1152 		return (False);
1153 	}
1154 	pEntry->n_value = Address * 2;  /* find address of variable in bytes */
1155 	pEntry->n_numaux = 0;
1156 	return (True);
1157 }
1158 
1159 int
stab_add_local_register(struct prog_info * pi,char * pName,char * pType,char * pRegister)1160 stab_add_local_register(struct prog_info *pi, char *pName, char *pType, char *pRegister)
1161 {
1162 
1163 	int n, Register, Size;
1164 	unsigned short CoffType, Type;
1165 	struct syment *pEntry;
1166 
1167 	n = strlen(pName);      /* see if it's 8 bytes or less */
1168 	Type = (unsigned short)atoi(pType + 1);     /* skip past P, predefined variable type */
1169 	Register = atoi(pRegister); /* offset in stack frame */
1170 	if ((CoffType = GetCoffType(Type)) == 0) {
1171 		fprintf(stderr, "\nUnrecognized type found for %s = %d", pName, Type);
1172 		return (False);
1173 	}
1174 	Size = GetCoffTypeSize(Type);   /* Silly requirement for avr studio */
1175 	/* Allocate Symbol Table entry and fill it in */
1176 	pEntry = (struct syment *)AllocateListObject(&ci->ListOfSymbols, sizeof(struct syment));
1177 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1178 		fprintf(stderr,"\nOut of memory adding local %s to string table", pName);
1179 		return (False);
1180 	}
1181 	pEntry->n_type = CoffType;
1182 	pEntry->n_sclass = C_REGPARM;   /* Silly avr studio only accepts this for registers */
1183 	pEntry->n_scnum = N_ABS;
1184 	pEntry->n_numaux = 0;
1185 	if (Size == 1)
1186 		pEntry->n_value = 0xffffff00 | Register; /* Silly requirement for avr studio */
1187 	else if (Size == 2)
1188 		pEntry->n_value = 0xffff0000 | ((Register + 1) << 8) | Register; /* Silly requirement for avr studio */
1189 	else if (Size == 4)
1190 		pEntry->n_value = ((Register + 3) << 24) | ((Register + 3) << 16) | ((Register + 1) << 8) | Register; /* Silly requirement for avr studio */
1191 	else {
1192 		fprintf(stderr,"\nUnknown register size (%d) and coff type (%d)", Size, CoffType);
1193 		return (False);
1194 	}
1195 	return (True);
1196 }
1197 
1198 int
stab_add_local_type(char * pName,char * pType)1199 stab_add_local_type(char *pName, char *pType)
1200 {
1201 
1202 	char *p;
1203 	unsigned short StabType;
1204 
1205 	/* .stabs "int:t1=r1;-128;127;",128,0,0,0 */
1206 	/* .stabs ":t20=ar1;0;1;21=ar1;0;1;2",128,0,0,0 */
1207 	/* pType-----^                                   */
1208 	/* Stab Type - convert to Coff type at end (after inline assignments */
1209 	if (GetStabType(pType, &StabType, &p) != True) {
1210 		fprintf(stderr,"\nInvalid tag type found in structure item -> %s", p);
1211 		return (False);
1212 	}
1213 
1214 	return (True);
1215 }
1216 
1217 int
GetStructUnionTagItem(char * p,char ** pEnd,char ** pName,unsigned short * pType,unsigned short * pBitOffset,unsigned short * pBitSize)1218 GetStructUnionTagItem(char *p, char **pEnd, char **pName, unsigned short *pType, unsigned short *pBitOffset, unsigned short *pBitSize)
1219 {
1220 
1221 	unsigned short StabType;
1222 	/* Structure or Union Tag Item consists of -> name:type,bitoffset,bitsize; */
1223 
1224 	/* name */
1225 	*pName = p;
1226 	while (*p && (*p != ':')) p++;   /* locate colon */
1227 	if (*p != ':') {
1228 		fprintf(stderr,"\nNo colon found in structure item -> %s", *pName);
1229 		return (False);
1230 	}
1231 	*p++ = 0; /* Asciiz */
1232 
1233 	/* Stab Type - convert to Coff type at end (after inline assignments */
1234 	if (GetStabType(p, &StabType, &p) != True) {
1235 		fprintf(stderr,"\nInvalid tag type found in structure item -> %s", p);
1236 		return (False);
1237 	}
1238 
1239 	/* BitSize */
1240 	if (*p != ',') {
1241 		fprintf(stderr,"\nNo Bit size found in structure item -> %s", p);
1242 		return (False);
1243 	}
1244 	*pBitOffset = (unsigned short)atoi(++p);
1245 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1246 
1247 	/* BitOffset */
1248 	if (*p != ',') {
1249 		fprintf(stderr,"\nNo Bit offset found in structure item -> %s", p);
1250 		return (False);
1251 	}
1252 	*pBitSize = (unsigned short)atoi(++p);
1253 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1254 
1255 	/* Now convert stab type to COFF */
1256 	if ((*pType = GetCoffType((unsigned short)StabType)) == 0) {
1257 		fprintf(stderr,"\nNo COFF type found for stab type %d", StabType);
1258 		return (False);
1259 	}
1260 	if (*++p == ';')   /* Now eat last semicolon(s) */
1261 		p++;
1262 	*pEnd = p;
1263 
1264 	return (True);
1265 }
1266 
1267 int
GetEnumTagItem(char * p,char ** pEnd,char ** pEnumName,int * pEnumValue)1268 GetEnumTagItem(char *p, char **pEnd, char **pEnumName, int *pEnumValue)
1269 {
1270 
1271 	/* Enum Tag Item consists of -> member1:value,member2:value2,; */
1272 	*pEnumName = p;
1273 	while (*p && (*p != ':')) p++;   /* locate colon */
1274 	if (*p != ':') {
1275 		fprintf(stderr,"\nNo colon found in enum item -> %s", *pEnumName);
1276 		return (False);
1277 	}
1278 	*p++ = 0; /* Asciiz */
1279 	*pEnumValue = atoi(p);
1280 
1281 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1282 	if (*p != ',') {
1283 		fprintf(stderr,"\nNo comma found after enum value -> %s", p);
1284 		return (False);
1285 	}
1286 	if (*++p ==';')
1287 		p++; /* eat last semicolon */
1288 	*pEnd = p;
1289 	return (True);
1290 }
1291 
1292 int
GetArrayType(char * p,char ** pEnd,STABCOFFMAP * pMap,unsigned short * DerivedBits,int ExtraLevels)1293 GetArrayType(char *p, char **pEnd, STABCOFFMAP *pMap, unsigned short *DerivedBits, int ExtraLevels)
1294 {
1295 
1296 	int MinIndex, MaxIndex, Result, Size, i;
1297 	char *pMinIndex, *pMaxIndex, *pType;
1298 	unsigned short Type;
1299 
1300 	Result = True;
1301 
1302 	pMinIndex = pMaxIndex = pType = 0;
1303 	while (*p && (*p != ';')) p++;     /* find min index */
1304 	pMinIndex = ++p;
1305 	while (*p && (*p != ';')) p++;     /* find max index */
1306 	pMaxIndex = ++p;
1307 	while (*p && (*p != ';')) p++;     /* find type index */
1308 	pType = ++p;
1309 
1310 	/* bump the pointers to the digits */
1311 	if (!isdigit(*pMinIndex))
1312 		Result = False;
1313 	if (!isdigit(*pMaxIndex))
1314 		Result = False;
1315 	if (!isdigit(*pType))
1316 		Result = False;
1317 	/* Is syntax ok ? */
1318 	if (Result != True) {
1319 		fprintf(stderr,"\nSyntax error on array parameters %s%s%s", pMinIndex, pMaxIndex, pType);
1320 		return (False);
1321 	}
1322 	MinIndex = atoi(pMinIndex);
1323 	MaxIndex = atoi(pMaxIndex);
1324 
1325 	if (GetStabType(p, &Type, &p) != True)
1326 		return (False);
1327 
1328 	if (!SetupDefinedType(Type, pMap, DerivedBits, ExtraLevels))
1329 		return (False);
1330 
1331 	/* Now update the size based on the indicies */
1332 	Size = (MaxIndex - MinIndex) + 1;
1333 	pMap->ByteSize *= Size;
1334 	pMap->Line = ci->CurrentSourceLine;
1335 	/* add the dimension information */
1336 	for (i = 5; i >= 0; i--) {
1337 		if (pMap->Dimensions[i] != 0) {
1338 			i++;
1339 			pMap->Dimensions[i] = Size;
1340 			break;
1341 		}
1342 	}
1343 
1344 	*pEnd = p;
1345 	return (True);
1346 }
1347 
1348 int
GetStabType(char * p,unsigned short * pType,char ** pEnd)1349 GetStabType(char *p, unsigned short *pType, char **pEnd)
1350 {
1351 
1352 	STABCOFFMAP *pMap;
1353 	int extra, ok;
1354 	unsigned short derivedbits[6];
1355 	unsigned short LStabType, RStabType;
1356 	char *pHigh, *pLow;
1357 
1358 
1359 	LStabType = atoi(p);
1360 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1361 
1362 	*pType = LStabType;
1363 
1364 	if (GetCoffType(LStabType) != 0) {
1365 		*pEnd = p;
1366 		return (True);
1367 	}
1368 	if (*p != '=') {
1369 		fprintf(stderr, "\nSyntax error in type assignment -> %s", p);
1370 		return (False);
1371 	}
1372 	p++;
1373 
1374 	/* Allocate space for new internal type */
1375 	if (!(pMap = (STABCOFFMAP *)AllocateListObject(&ci->ListOfTypes, sizeof(STABCOFFMAP)))) {
1376 		fprintf(stderr, "\nOut of memory allocating type info!");
1377 		return (False);
1378 	}
1379 	pMap->StabType = LStabType;
1380 
1381 	/* process items to right of equals */
1382 	for (extra = 0; extra < 6; extra++) {
1383 
1384 		if (isdigit(*p)) {
1385 			/* Finally found base type, try to terminate loop */
1386 			GetStabType(p, &RStabType, &p);
1387 			/*			RStabType = atoi( p ); */
1388 			while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1389 			if (SetupDefinedType(RStabType, pMap, &derivedbits[0], extra) != True)
1390 				return (False);
1391 			break;
1392 		} else if (*p == 'a') {
1393 			derivedbits[extra] = DT_ARY;
1394 			p++;
1395 			/* Calculate size */
1396 			/* Since type assignment will be made we need to set extra bits here */
1397 			extra++;
1398 			/* =ar1;MinIndex;MaxIndex;BaseType */
1399 			if (GetArrayType(p, &p, pMap, &derivedbits[0], extra) != True)
1400 				return (False);
1401 			break;
1402 
1403 		} else if (*p == 'f') {
1404 			derivedbits[extra] = DT_FCN;
1405 			p++;
1406 		} else if (*p == '*') {
1407 			derivedbits[extra] = DT_PTR;
1408 			p++;
1409 		} else if (*p == 'r') {
1410 			while (*p && (*p != ';')) p++;
1411 			pLow = p++;
1412 			while (*p && (*p != ';')) p++;
1413 			pHigh = p++;
1414 			ok = GetSubRangeType(LStabType, pMap, pLow, pHigh);
1415 			if (ok != True)
1416 				return (False);
1417 			while (*p && (*p != ';')) p++;    /* find end of range */
1418 			p++;
1419 			break;
1420 		} else {
1421 			fprintf(stderr, "\nUnrecognized Type modifier %c!", *p);
1422 			return (False);
1423 		}
1424 	}
1425 	*pEnd = p; /* Update return pointer */
1426 
1427 	return (True);
1428 }
1429 
1430 int
stab_add_tag_type(char * pName,char * pString)1431 stab_add_tag_type(char *pName, char *pString)
1432 {
1433 
1434 	int SymbolIndex, StabType, TotalSize, n, EnumValue;
1435 	unsigned short TagType, ItemType, BitOffset, BitSize;
1436 	char *p;
1437 	struct syment *pEntry;
1438 	union auxent *pAux;
1439 	STABCOFFMAP *pMap;
1440 
1441 	/* We arrived here due to :T defining either a structure, union or enumeration */
1442 	/* store the basic type as for internals and emit coff structures for debugging */
1443 	/* .stabs "stag:T17=s2i:1,0,8;c:2,8,8;;",128,0,0,0 */
1444 	/* .stabs "2:T18=u2a:2,0,8;b:1,0,8;c:6,0,16;;",128,0,0,0 */
1445 	/* .stabs "1:T19=eenum1:1,enum2:2,enum3:3,;",128,0,0,0 */
1446 	/* we don't care about the name */
1447 
1448 
1449 	/* check for bogus errors */
1450 	if (!pName || !pString) {
1451 		fprintf(stderr,"\nInvalid .stabs type format - no information!");
1452 		return (False);
1453 	}
1454 
1455 	p = pString;
1456 	/* Stab Type - convert to Coff type at end (after inline assignments */
1457 	if ((StabType = (unsigned short)atoi(p)) == 0) {
1458 		fprintf(stderr,"\nInvalid .stabs type format - no information! - > %s", p);
1459 		return (False);
1460 	}
1461 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1462 	if (*p != '=') {
1463 		fprintf(stderr,"\nInvalid .stabs type format - no equals - > %s", p);
1464 		return (False);
1465 	}
1466 	SymbolIndex = ci->ListOfSymbols.TotalItems;
1467 	if ((pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfGlobals, sizeof(struct syment) * 2)) == 0) {
1468 		fprintf(stderr, "\nOut of memory allocating symbol tag entries");
1469 		return (False);
1470 	}
1471 	/* Prepare Tag Header */
1472 	if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1473 		fprintf(stderr,"\nOut of memory adding local %s to string table", pString);
1474 		return (False);
1475 	}
1476 	if (!(pMap = (STABCOFFMAP *)AllocateListObject(&ci->ListOfTypes, sizeof(STABCOFFMAP)))) {
1477 		fprintf(stderr, "\nOut of memory allocating type info!");
1478 		return (False);
1479 	}
1480 	pMap->StabType = StabType;
1481 	pEntry->n_value = 0;
1482 	pEntry->n_scnum = N_DEBUG;
1483 	pEntry->n_numaux = 1;
1484 	if (*++p == 's') {
1485 		TagType = pEntry->n_type = pMap->CoffType = T_STRUCT;
1486 		pEntry->n_sclass = C_STRTAG;
1487 		TotalSize = (unsigned short)atoi(++p);
1488 	} else if (*p == 'u') {
1489 		TagType = pEntry->n_type = pMap->CoffType = T_UNION;
1490 		pEntry->n_sclass = C_UNTAG;
1491 		TotalSize = (unsigned short)atoi(++p);
1492 	} else if (*p == 'e') {
1493 		TagType = pEntry->n_type = pMap->CoffType = T_ENUM;
1494 		pEntry->n_sclass = C_ENTAG;
1495 		TotalSize = FundamentalTypes[T_INT].Size; /* use size of int for enums */
1496 	} else {
1497 		fprintf(stderr,"\nUnknown tag type -> %s", p);
1498 		return (False);
1499 	}
1500 	while (*p && (*p >= '0') && (*p <= '9')) p++;   /* locate end of digits */
1501 	pEntry++;   /* point to aux entry */
1502 	pAux = (union auxent *)pEntry;
1503 	pAux->x_sym.x_tagndx = SymbolIndex;
1504 	pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
1505 
1506 	/* update our local knowledge of tag type */
1507 	pMap->CoffType = TagType;
1508 	pMap->ByteSize = TotalSize;
1509 	pMap->Line = ci->CurrentSourceLine;
1510 
1511 	/* Process the items until the end of the line */
1512 	while (*pName) {
1513 
1514 		if ((pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfGlobals, sizeof(struct syment) * 2)) == 0) {
1515 			fprintf(stderr, "\nOut of memory allocating symbol tag member entries");
1516 			return (False);
1517 		}
1518 
1519 		if (TagType == T_STRUCT) {
1520 			if (GetStructUnionTagItem(p, &p, &pName, &ItemType, &BitOffset, &BitSize) != True) {
1521 				return (False);
1522 			}
1523 			pEntry->n_value = BitOffset/8;
1524 			pEntry->n_type = ItemType;
1525 			pEntry->n_sclass = C_MOS;
1526 		} else if (TagType == T_UNION) {
1527 			if (GetStructUnionTagItem(p, &p, &pName, &ItemType, &BitOffset, &BitSize) != True) {
1528 				return (False);
1529 			}
1530 			pEntry->n_value = BitOffset/8;
1531 			pEntry->n_type = ItemType;
1532 			pEntry->n_sclass = C_MOU;
1533 		} else { /* T_ENUM */
1534 			if (GetEnumTagItem(p, &p, &pName, &EnumValue) != True) {
1535 				return (False);
1536 			}
1537 			pEntry->n_value = EnumValue;
1538 			pEntry->n_type = TotalSize;
1539 			pEntry->n_sclass = C_MOE;
1540 		}
1541 
1542 		/* Prepare Common Tag Header items */
1543 		if ((n = AddNameToEntry(pName, pEntry)) == 0) {
1544 			fprintf(stderr,"\nOut of memory adding local %s to string table", pString);
1545 			return (False);
1546 		}
1547 		pEntry->n_scnum = N_ABS;
1548 		pEntry->n_numaux = 1;
1549 		pEntry++;   /* point to aux entry */
1550 		pAux = (union auxent *)pEntry;
1551 		pAux->x_sym.x_tagndx = SymbolIndex;
1552 		pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
1553 		pName = p;
1554 	}
1555 
1556 	/* End of Structures/Unions/Enumberations */
1557 	if ((pEntry = (struct syment *)AllocateTwoListObjects(&ci->ListOfGlobals, sizeof(struct syment) * 2)) == 0) {
1558 		fprintf(stderr, "\nOut of memory allocating special headers for structure!");
1559 		return (False);
1560 	}
1561 	strcpy(pEntry->n_name, ".eos");
1562 	pEntry->n_value = TotalSize;
1563 	pEntry->n_scnum = N_ABS;
1564 	pEntry->n_type = 0;
1565 	pEntry->n_sclass = C_EOS;
1566 	pEntry->n_numaux = 1;
1567 	pEntry++;   /* point to aux entry */
1568 	pAux = (union auxent *)pEntry;
1569 	pAux->x_sym.x_tagndx = SymbolIndex; /* point to the .bf entry index */
1570 	pAux->x_sym.x_misc.x_lnsz.x_size = TotalSize;
1571 
1572 	return (True);
1573 }
1574 
1575 int
SetupDefinedType(unsigned short Type,STABCOFFMAP * pMap,unsigned short * DerivedBits,int ExtraLevels)1576 SetupDefinedType(unsigned short Type, STABCOFFMAP *pMap, unsigned short *DerivedBits, int ExtraLevels)
1577 {
1578 
1579 	int i, Dlimit, Dstart;
1580 	unsigned short StabType;
1581 
1582 	StabType = pMap->StabType; /* save the new type we found earlier */
1583 	if (CopyStabCoffMap(Type, pMap) != True) {
1584 		fprintf(stderr, "\nCould not find defined type %d", Type);
1585 		return (False);
1586 	}
1587 	pMap->StabType = StabType; /* save the new type we found earlier */
1588 
1589 	/* Determine existing derived types for base class */
1590 	for (i = 0; i < 6; i++) {
1591 		if ((pMap->CoffType & (3 << (4 + i + i))) == 0)
1592 			break;
1593 	}
1594 	Dstart = i;
1595 	Dlimit = i + ExtraLevels;
1596 	if ((Dlimit) >= 6) {
1597 		fprintf(stderr, "\nStab Type %d has too many derived (%d) types!", pMap->StabType, Dlimit);
1598 		return (False);
1599 	}
1600 	/* Add the new derived levels */
1601 	for (; i < Dlimit; i++) {
1602 		pMap->CoffType |= ((DerivedBits[i - Dstart] & 3) << (4 + i + i));    /* add in the derived bits */
1603 	}
1604 	return (True);
1605 }
1606 
1607 int
GetArrayDefinitions(STABCOFFMAP * pMap,char * pMinIndex,char * pMaxIndex,char * pType,unsigned short * DerivedBits,int ExtraLevels)1608 GetArrayDefinitions(STABCOFFMAP *pMap, char *pMinIndex, char *pMaxIndex, char *pType, unsigned short *DerivedBits, int ExtraLevels)
1609 {
1610 
1611 	int MinIndex, MaxIndex, Result, Size, i;
1612 	unsigned short Type;
1613 
1614 	Result = True;
1615 	if ((*pMinIndex != ';') || (*pMaxIndex != ';') || (*pType != ';'))
1616 		Result = False;
1617 	/* bump the pointers to the digits */
1618 	pMinIndex++;
1619 	if (!isdigit(*pMinIndex))
1620 		Result = False;
1621 	pMaxIndex++;
1622 	if (!isdigit(*pMaxIndex))
1623 		Result = False;
1624 	pType++;
1625 	if (!isdigit(*pType))
1626 		Result = False;
1627 	/* Is syntax ok ? */
1628 	if (Result != True) {
1629 		fprintf(stderr,"\nSyntax error on array parameters %s%s%s", pMinIndex, pMaxIndex, pType);
1630 		return (False);
1631 	}
1632 	MinIndex = atoi(pMinIndex);
1633 	MaxIndex = atoi(pMaxIndex);
1634 	Type = (unsigned short)atoi(pType);
1635 	if (SetupDefinedType(Type,    pMap,    DerivedBits,    ExtraLevels)    !=    True)
1636 		return (False);
1637 	/* Now update the size based on the indicies */
1638 	Size = (MaxIndex - MinIndex) + 1;
1639 	pMap->ByteSize *= Size;
1640 	pMap->Line = ci->CurrentSourceLine;
1641 	/* add the dimension information */
1642 	for (i = 5; i >= 0; i--) {
1643 		if (pMap->Dimensions[i] != 0) {
1644 			i++;
1645 			pMap->Dimensions[i] = Size;
1646 			break;
1647 		}
1648 	}
1649 	return (True);
1650 }
1651 
1652 int
GetInternalType(char * pName,STABCOFFMAP * pMap)1653 GetInternalType(char *pName, STABCOFFMAP *pMap)
1654 {
1655 
1656 	int n, found, i;
1657 
1658 	if (!pName) {
1659 		return (False);
1660 	}
1661 
1662 	found = False;
1663 	n = strlen(pName);
1664 	/* Find out if it is a local type */
1665 	for (i = 0; FundamentalTypes[i].pString != 0; i++) {
1666 		if (!strncmp(pName, FundamentalTypes[i].pString, n)) {
1667 			/* found an internal type */
1668 			pMap->CoffType = FundamentalTypes[i].Type;
1669 			pMap->ByteSize = FundamentalTypes[i].Size;
1670 			found = True;
1671 		}
1672 	}
1673 	return (found);
1674 }
1675 
1676 int
GetSubRangeType(unsigned short Type,STABCOFFMAP * pMap,char * pLow,char * pHigh)1677 GetSubRangeType(unsigned short Type, STABCOFFMAP *pMap, char *pLow, char *pHigh)
1678 {
1679 
1680 	int Result, i;
1681 	long High, Low;
1682 	unsigned long Test;
1683 
1684 	Result = True;
1685 	if ((*pLow != ';') || (*pHigh != ';') || (Type <= 0))
1686 		Result = False;
1687 
1688 	/* Is syntax ok ? */
1689 	if (Result != True) {
1690 		fprintf(stderr,"\nSyntax error on sub range parameters!");
1691 		return (False);
1692 	}
1693 	Low = atol(++pLow);
1694 	High = atol(++pHigh);
1695 
1696 	/* Special handling of type void */
1697 	if ((Low == 0) && (High == 0)) {
1698 		/* Declare type void */
1699 		pMap->ByteSize =0;
1700 		pMap->CoffType = T_VOID;
1701 		pMap->Line = ci->CurrentSourceLine;
1702 		return (True);
1703 	}
1704 
1705 	if ((pMap->CoffType = GetCoffType(Type)) != 0) {
1706 		pMap->ByteSize = GetCoffTypeSize(Type);
1707 	} else {
1708 		/* Try to base everything off integer */
1709 		pMap->ByteSize = FundamentalTypes[T_INT].Size;
1710 	}
1711 
1712 	/* Now calculate the byte size */
1713 	if (High == 0) {
1714 		pMap->ByteSize = (unsigned short)Low; /* floating point */
1715 	} else {
1716 		if (Low == 0) {
1717 			/* Unsigned */
1718 			Test = (unsigned long)High;
1719 		} else if (Low < 0) {
1720 			/* signed */
1721 			Test = (unsigned long)High << 1;
1722 		} else {
1723 			if (Low <= High)
1724 				Test = (unsigned long)High;
1725 			else
1726 				Test = (unsigned long)Low;
1727 		}
1728 		if (pMap->ByteSize == 0) {
1729 			fprintf(stderr,"\nType Range Error 1, need previous type %d size!", pMap->CoffType);
1730 			return (False);
1731 		}
1732 		for (i = 0; i < sizeof(unsigned long); i++) {
1733 			if (!(Test & (0xff << (i * 8))))
1734 				break;
1735 		}
1736 		pMap->ByteSize = i;
1737 	}
1738 	/* Now determine the best fit based on byte size, compare against IAR Compiler */
1739 	if (pMap->ByteSize == 1) {
1740 		if (Low < 0)
1741 			pMap->CoffType = T_CHAR;
1742 		else
1743 			pMap->CoffType = T_UCHAR;
1744 	} else if (pMap->ByteSize == 2) {
1745 		if (Low < 0)
1746 			pMap->CoffType = T_INT;
1747 		else
1748 			pMap->CoffType = T_UINT;
1749 	} else if (pMap->ByteSize == 4) {
1750 		if (Low == 0)
1751 			pMap->CoffType = T_FLOAT;
1752 		if (Low < 0)
1753 			pMap->CoffType = T_LONG;
1754 		else
1755 			pMap->CoffType = T_ULONG;
1756 	} else {
1757 		fprintf(stderr,"\nGetSubRangeType failure - byte size %d", pMap->ByteSize);
1758 		return (False);
1759 	}
1760 	return (True);
1761 }
1762 
1763 int
CopyStabCoffMap(unsigned short StabType,STABCOFFMAP * pMap)1764 CopyStabCoffMap(unsigned short StabType, STABCOFFMAP *pMap)
1765 {
1766 
1767 	STABCOFFMAP *p;
1768 
1769 	for (p = FindFirstListObject(&ci->ListOfTypes); p != 0; p = FindNextListObject(&ci->ListOfTypes)) {
1770 		if (p->StabType == StabType) {
1771 			memcpy(pMap, p, sizeof(STABCOFFMAP));
1772 			return (True);
1773 		}
1774 	}
1775 	return (False);  /* Nothing found */
1776 }
1777 
1778 unsigned short
GetCoffType(unsigned short StabType)1779 GetCoffType(unsigned short StabType)
1780 {
1781 
1782 	STABCOFFMAP *p;
1783 
1784 	for (p = FindFirstListObject(&ci->ListOfTypes); p != 0; p = FindNextListObject(&ci->ListOfTypes)) {
1785 		if (p->StabType == StabType)
1786 			return (p->CoffType);
1787 	}
1788 	return (0);  /* Nothing found */
1789 }
1790 
1791 unsigned short
GetCoffTypeSize(unsigned short StabType)1792 GetCoffTypeSize(unsigned short StabType)
1793 {
1794 
1795 	STABCOFFMAP *p;
1796 
1797 	for (p = FindFirstListObject(&ci->ListOfTypes); p != 0; p = FindNextListObject(&ci->ListOfTypes)) {
1798 		if (p->StabType == StabType)
1799 			return (p->ByteSize);
1800 	}
1801 	return (0);  /* Nothing found */
1802 }
1803 
1804 
1805 int
GetDigitLength(char * p)1806 GetDigitLength(char *p)
1807 {
1808 
1809 	int i;
1810 
1811 	if (p == 0)
1812 		return (0);
1813 
1814 	for (i = 0; (*p != 0) && (*p >= '0') && (*p <= '9'); i++);
1815 
1816 	return (i);
1817 
1818 }
1819 
1820 int
GetStringDelimiters(char * pString,char ** pTokens,int MaxTokens)1821 GetStringDelimiters(char *pString, char **pTokens, int MaxTokens)
1822 {
1823 
1824 	int i;
1825 	char *p;
1826 
1827 	p = pString;
1828 
1829 	if (!p)
1830 		return (0);
1831 
1832 	for (i = 0; i < MaxTokens; i++) {
1833 		while (True) {
1834 			if ((*p == ':') || (*p == ';') || (*p == '=') || (*p == ',') || (*p == '"') || (*p == 0)) {
1835 				*(pTokens + i) = p; /* Remember this location */
1836 				p++;
1837 				if (*p == 0)
1838 					return (i);
1839 				break;
1840 			}
1841 			p++;
1842 		}
1843 	}
1844 	return (i);
1845 }
1846 
1847 int
IsTypeArray(unsigned short CoffType)1848 IsTypeArray(unsigned short CoffType)
1849 {
1850 
1851 	int Result;
1852 
1853 	Result = False;
1854 
1855 	if ((CoffType & (DT_ARY << 4)) == (DT_ARY << 4))
1856 		Result = True;
1857 	if ((CoffType & (DT_ARY << 6)) == (DT_ARY << 6))
1858 		Result = True;
1859 	if ((CoffType & (DT_ARY << 8)) == (DT_ARY << 8))
1860 		Result = True;
1861 	if ((CoffType & (DT_ARY << 10)) == (DT_ARY << 10))
1862 		Result = True;
1863 	if ((CoffType & (DT_ARY << 12)) == (DT_ARY << 12))
1864 		Result = True;
1865 	if ((CoffType & (DT_ARY << 14)) == (DT_ARY << 14))
1866 		Result = True;
1867 
1868 	return (Result);
1869 }
1870 
1871 void
AddArrayAuxInfo(union auxent * pAux,unsigned short SymbolIndex,STABCOFFMAP * pMap)1872 AddArrayAuxInfo(union auxent *pAux, unsigned short SymbolIndex, STABCOFFMAP *pMap)
1873 {
1874 
1875 	int i;
1876 
1877 	pAux->x_sym.x_tagndx = SymbolIndex; /* point to the .bf entry index */
1878 	pAux->x_sym.x_misc.x_lnsz.x_lnno =  pMap->Line;
1879 	pAux->x_sym.x_misc.x_lnsz.x_size = pMap->ByteSize;
1880 	for (i = 0; i < 4; i++)
1881 		pAux->x_sym.x_fcnary.x_ary.x_dimen[i] = pMap->Dimensions[i];
1882 }
1883 
1884 int
AddNameToEntry(char * pName,struct syment * pEntry)1885 AddNameToEntry(char *pName, struct syment *pEntry)
1886 {
1887 
1888 	int n;
1889 	char *p;
1890 
1891 	n = strlen(pName);      /* see if it's 8 bytes or less */
1892 	if (n <= 8) {
1893 		strncpy(pEntry->n_name, pName, 8);
1894 	} else {
1895 		/* point to current offset in string table */
1896 		pEntry->n_offset = ci->ListOfStrings.TotalBytes;
1897 		/* Allocate string table entry */
1898 		if ((p = (char *)AllocateListObject(&ci->ListOfStrings, n + 1)) == 0) {
1899 			return (0);
1900 		}
1901 		strcpy(p, pName);
1902 	}
1903 	return (n); /* return size of string */
1904 }
1905 
1906 char *
SkipPastDigits(char * p)1907 SkipPastDigits(char *p)
1908 {
1909 
1910 	if (!p)
1911 		return (p);
1912 	if (*p == 0)
1913 		return (p);
1914 	for (p--; (*p >= '0') && (*p <= '9') && (*p != 0); p--);
1915 	return (p);
1916 }
1917 
1918 void
InitializeList(LISTNODEHEAD * pHead)1919 InitializeList(LISTNODEHEAD *pHead)
1920 {
1921 
1922 	pHead->Node.Next = &pHead->Node;
1923 	pHead->Node.Last = &pHead->Node;
1924 	pHead->TotalBytes = 0;
1925 	pHead->TotalItems = 0;
1926 	pHead->current = &pHead->Node;
1927 	return;
1928 }
1929 
1930 void *
AllocateTwoListObjects(LISTNODEHEAD * pHead,int size)1931 AllocateTwoListObjects(LISTNODEHEAD *pHead, int size)
1932 {
1933 
1934 	void *p;
1935 
1936 	if ((p = AllocateListObject(pHead, size)))
1937 		pHead->TotalItems++;   /* already incremented once in addtolist */
1938 	return (p);
1939 }
1940 
1941 void *
AllocateListObject(LISTNODEHEAD * pHead,int size)1942 AllocateListObject(LISTNODEHEAD *pHead, int size)
1943 {
1944 
1945 	void *pObject;
1946 
1947 	LISTNODE *pNode;
1948 
1949 	if ((pObject = calloc(1, size)) != 0) {
1950 		if (!(pNode = AddListObject(pHead, pObject, size))) {
1951 			free(pObject);
1952 			pObject = 0;
1953 		}
1954 	}
1955 	return (pObject);
1956 }
1957 
1958 LISTNODE  *
AddListObject(LISTNODEHEAD * pHead,void * pObject,int size)1959 AddListObject(LISTNODEHEAD *pHead, void *pObject, int size)
1960 {
1961 
1962 	LISTNODE *pNode;
1963 
1964 	if ((pNode = calloc(1, sizeof(LISTNODE))) != 0) {
1965 		pNode->pObject = pObject;
1966 		pNode->Size = size;
1967 		pNode->FileNumber = ci->CurrentFileNumber;
1968 		AddNodeToList(pHead, pNode);
1969 	}
1970 	return (pNode);
1971 }
1972 
1973 LISTNODE *
AllocateListNode(void * pObject,int size)1974 AllocateListNode(void *pObject, int size)
1975 {
1976 
1977 	LISTNODE *pNew;
1978 
1979 	if ((pNew = calloc(1, sizeof(LISTNODE))) != 0) {
1980 		/* Then we initialize the node */
1981 		pNew->pObject = pObject;
1982 		pNew->Size = size;
1983 		pNew->FileNumber = ci->CurrentFileNumber;
1984 	}
1985 	return (pNew);
1986 }
1987 
1988 void
AddNodeToList(LISTNODEHEAD * pHead,LISTNODE * pNode)1989 AddNodeToList(LISTNODEHEAD *pHead, LISTNODE *pNode)
1990 {
1991 
1992 	LISTNODE *p;
1993 
1994 	p = &pHead->Node;
1995 
1996 	pNode->Next = p->Last->Next;
1997 	p->Last->Next = pNode;
1998 	pNode->Last = p->Last;
1999 	p->Last = pNode;
2000 
2001 	/* and update current size of data contained in the list */
2002 	pHead->TotalBytes += pNode->Size;
2003 	pHead->TotalItems++;
2004 }
2005 
2006 void
RemoveNodeFromList(LISTNODEHEAD * pHead,LISTNODE * pNode)2007 RemoveNodeFromList(LISTNODEHEAD *pHead, LISTNODE *pNode)
2008 {
2009 
2010 	pNode->Last->Next = pNode->Next;
2011 	pNode->Next->Last = pNode->Last;
2012 
2013 	pHead->TotalBytes -= pNode->Size;
2014 	pHead->TotalItems--;
2015 }
2016 
2017 void *
FindFirstListObject(LISTNODEHEAD * pHead)2018 FindFirstListObject(LISTNODEHEAD *pHead)
2019 {
2020 
2021 	if (pHead->Node.Next == &pHead->Node)
2022 		return (0); /* Nothing in list */
2023 
2024 	pHead->current = pHead->Node.Next;
2025 	return (pHead->current->pObject);
2026 }
2027 
2028 void *
FindNextListObject(LISTNODEHEAD * pHead)2029 FindNextListObject(LISTNODEHEAD *pHead)
2030 {
2031 
2032 	if (pHead->current->Next == &pHead->Node)
2033 		return (0);
2034 
2035 	pHead->current = pHead->current->Next;
2036 
2037 	return (pHead->current->pObject);
2038 }
2039 
2040 LISTNODE *
GetCurrentNode(LISTNODEHEAD * pHead)2041 GetCurrentNode(LISTNODEHEAD *pHead)
2042 {
2043 
2044 	return (pHead->current);
2045 }
2046 
2047 void *
GetCurrentListObject(LISTNODEHEAD * pHead)2048 GetCurrentListObject(LISTNODEHEAD *pHead)
2049 {
2050 
2051 	return (pHead->current->pObject);
2052 }
2053 
2054 void *
FindLastListObject(LISTNODEHEAD * pHead)2055 FindLastListObject(LISTNODEHEAD *pHead)
2056 {
2057 
2058 	if (pHead->Node.Last == &pHead->Node)
2059 		return (0); /* Nothing in list */
2060 
2061 	pHead->current = pHead->Node.Last;
2062 	return (pHead->current->pObject);
2063 }
2064 
2065 void *
FindNextLastListObject(LISTNODEHEAD * pHead)2066 FindNextLastListObject(LISTNODEHEAD *pHead)
2067 {
2068 
2069 	if (pHead->current->Last == &pHead->Node)
2070 		return (0);
2071 
2072 	pHead->current = pHead->current->Last;
2073 
2074 	return (pHead->current->pObject);
2075 }
2076 
2077 void
FreeList(LISTNODEHEAD * pHead)2078 FreeList(LISTNODEHEAD *pHead)
2079 {
2080 
2081 	LISTNODE *pNode;
2082 
2083 	for (pNode = pHead->Node.Last; pNode->Next != &pHead->Node; pNode = pHead->Node.Last) {
2084 
2085 		RemoveNodeFromList(pHead, pNode);
2086 		free(pNode->pObject);
2087 		free(pNode);
2088 	}
2089 	pHead->TotalBytes = 0;
2090 	pHead->TotalItems = 0;
2091 	pHead->current = &pHead->Node;
2092 }
2093 
2094