dos_compilers/Manx Aztec C86 v42b/ARC/DBGMAP.C
2024-07-02 07:07:59 -07:00

669 lines
16 KiB
C

/********************************************
dbgmap - conversion utily for
Aztec C
This utility converts an Aztec C
symbol table file (.DBG) into a
RDSD compatible symbol file (.MAP).
Paul McClintock April 21, 1987
Last Edit April 21, 1987
(c) Lines Unlimited April 1987
*******************************************/
/******************************************
The following definition of the Aztec .DBG
file is the results of a phone coversation with
Tom Ferwick of Aztec. The .DBG file is a
complex binary symbol file containing substancially
more data then the Microsoft .MAP file is able
to contain.
The .DBG file format is based on 64 byte records.
Each record type has a unique structure.
HEADER RECORD :
type_def dw 13678 ; 0356Eh
num_struct dw ; number of structure records
start_struct dw ; starting record # for struct
num_strings dw ; total # of strings
total_string_lnth dw ; total string table length
start_string dw ; starting record for strings
num_src_line_rec dw ; number of src line records
num_block_rec dw ; number of block records
num_sym_rec dw ; number of symbol records
; offsets into symbol data
s_abs_symbol dw ; 1st aboslute symbol
s_code_symbol dw ; 1st code symbol
s_data_symbol dw ; 1st data symbol
SYMBOL RECORD :
type_def dw 15431 ; 03C47h
name_idx dw ; name string subscript
type_idx dw ; type string subscript
struct_idx dw ; index into struct table
add_offset dw ;
add_segment dw ; also used as a flag word
-2 = Auto variable BP.[add_offset]
-3 = Register variable
add_offset == 5 for SI
add_offset == 6 for DI
-4 = argument BP.[add_offset]
-5 = argument, Register variable
-6 = TYPE DEF name
Type Strings Modifers
* = 16 Bit Pointer
# = 32 Bit Pointer
[size = size of array
( = Near Function
{ = Far Function
Base Type Characters
c = char
C = unsigned char
i = int
I = unsigned int
l = long
L = unsigned int
f = float
D = double
V = void
: = struct
SOURCE LINE RECORD :
type_def dw 12345 ; 3039h
add_offset dw ; starting address offset
add_segment dw ; starting address segment
file_name dw ; file name string subscript
line_number dw ; starting source line number
object_displacement db ; obj code displacement / line
Special flag bit
0FFH == end of obj offsets array
00h to 07Fh == 8 bit object code displacement
080h to 0FEh == 15 bit object code displacement
SYMBOL SCOPE DEF RECORD :
type_def dw 15432 ; 03C48h (BLOCK)
Unknown record format
STRUCT DEF RECORD :
; no type_def
;
name_idx dw ; name string subscript
type_idx dw ; type string subscript
struct_idx dw ; index into struct table
add_segment dw ; also used as a flag word
*******************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
/* .DBG Header record */
struct HEADER
{
unsigned int type_def, /* 13678 */
num_struct, /* nuber of struct records */
start_struct, /* starting record for struct */
num_strings, /* total num of strings */
tot_str_lnth, /* total strings length */
start_string, /* starting record for string */
num_src_rec, /* total src records */
num_block_rec, /* total block records */
num_sym_rec, /* total symbol records */
s_abs_sym, /* starting abs symbol */
s_code_sym, /* starting code symbol */
s_data_sym; /* starting data symbol */
unsigned int fill[20]; /* total size of 64 bytes */
};
/* Public Symbols */
struct SYMBOL
{
unsigned int name_idx, /* symbol name index */
type_idx, /* symbol type index */
struct_idx, /* index into struct table */
add_offset, /* address offset value */
add_segment; /* address segment value */
};
struct SYM_RECORD
{
unsigned int type_def; /* 15431 */
struct SYMBOL sym_data[6];
unsigned int fill[1]; /* total size of 64 bytes */
};
/* Internal Format */
struct SYM_DATA
{
struct SYM_DATA *next; /* linked list */
unsigned int name_idx, /* symbol name index */
type_idx, /* symbol type index */
add_offset, /* address offset value */
add_segment, /* address segment value */
struct_idx; /* index into struct table */
};
#define RECORDSIZE 64
#define LINEENTRY (RECORDSIZE - 5*sizeof(short))
/* Source Line numbers */
struct SRC_RECORD
{
unsigned short type_def, /* 12345 */
add_offset, /* address offset value */
add_segment, /* address segment value */
file_idx, /* function's src file index */
line_num; /* starting line number */
unsigned char obj_displ[LINEENTRY]; /* object code displacement */
};
/* internal format */
struct SRC_DATA
{
struct SRC_DATA *next; /* linked list */
unsigned int file_idx, /* src file index */
line_num, /* specified line number */
add_offset,
add_segment;
};
/* Global DATA */
struct HEADER dbg_header;
struct SYM_DATA *sym_list = NULL; /* header for linked list */
int sym_count = 0; /* number of entries */
unsigned short max_symbol ; /* max valid symbol index */
struct SRC_DATA *src_list = NULL; /* header for linked list */
int src_count = 0; /* number of entries */
char **str_idx, *str_buff; /* string buffer pointers */
char *dbg_file, *map_file; /* file paths */
char *filename() ;
main (argc, argv)
int argc; /* number of paramiters */
char **argv; /* array of paramiters */
{
int count ; /* loop counter */
unsigned int *buff ; /* input buffer */
int dbg ; /* input file handle */
int error ; /* file operations return value */
FILE *map ; /* output map file */
printf("\nAztec .DBG to Microsoft compatible .MAP symbol file converter");
printf("\n(c) Lines Unlimited 8-24-87 \n");
if (argc != 2)
{
printf("\n\nusage: dbgmap filename");
exit(1);
}
++argv; /* skip command name */
dbg_file = filename( *argv, ".dbg");
map_file = filename( *argv, ".map");
dbg = open( dbg_file, O_RDONLY | O_BINARY);
if (dbg == -1)
err_abort(dbg_file); /* abort on error */
/* Read header record */
error = read( dbg, &dbg_header, sizeof(struct HEADER) );
if (error == -1)
err_abort(dbg_file); /* abort on read error */
buff = (int *) malloc(64); /* block buffer */
if (buff == NULL)
err_abort("buff - out of memory ");
max_symbol = 0xffff ; /* initialize */
/* build data structures from the .DBG file */
for (count = dbg_header.start_struct - 1 ; count ; --count)
{
error = read( dbg, buff, 64);
if (error == -1)
err_abort( dbg_file);
switch (*buff) /* type_def */
{
case 15431 : /* SYMBOL RECORD */
save_symbols( buff);
break;
case 12345 : /* SOURCE LINE RECORD */
save_src_line( buff);
break;
}
}
free(buff);
read_strings( dbg); /* read in strings */
/* Time to generate the .MAP file */
map = fopen ( map_file, "w");
if (map == NULL)
err_abort ( map_file);
print_symbols ( map);
print_src_data ( map);
if ( fclose ( map) )
err_abort( map_file);
exit (0);
}
save_symbols ( buff)
struct SYM_RECORD *buff;
{
int count;
struct SYMBOL *c_symbol;
struct SYM_DATA *tmp;
c_symbol = buff->sym_data;
for (count = 0 ; count < 6 ; ++count, ++c_symbol)
{
if ( c_symbol->name_idx < dbg_header.num_strings )
{
tmp = (struct SYM_DATA *) malloc(sizeof(struct SYM_DATA) );
if (tmp == NULL)
err_abort( "save_symbols - out of memory ");
tmp->name_idx = c_symbol->name_idx;
tmp->type_idx = c_symbol->type_idx;
tmp->add_offset = c_symbol->add_offset;
tmp->add_segment = c_symbol->add_segment;
tmp->struct_idx = c_symbol->struct_idx;
if ((tmp->type_idx < max_symbol) && (tmp->type_idx != 0 ) )
max_symbol = tmp->type_idx ; /* type strings follow global
symbols strings */
/* add to linked list in memory */
tmp->next = sym_list;
sym_list = tmp; /* update linked list */
++sym_count;
}
}
}
print_symbols( map)
FILE *map; /* output file descriptor */
{
struct SYM_DATA **idx, **tmp, *cur;
int count, tot_sym ;
int sym_by_name(), sym_by_value();
tmp = idx = (struct SYM_DATA **)
malloc( sizeof(struct SYM_DATA) * (sym_count + 1) ) ;
if (idx == NULL)
err_abort("print_symbols - out of memory ");
/* generate index for quick sort */
for ( tot_sym = 0 , cur = sym_list; cur != NULL ; cur = cur->next )
{
if ( ( cur->add_segment < (unsigned) -6 ) &&
(cur->name_idx < max_symbol ) )
{
*tmp++ = cur ;
++tot_sym ;
}
}
*tmp = NULL ;
fprintf ( map, "\n\n Address Publics by Name\n");
qsort ( idx, tot_sym, sizeof(struct SYM_DATA *), sym_by_name );
for ( tmp = idx; *tmp ; ++tmp)
{
fprintf( map, "\n %04X:%04X %s", (*tmp)->add_segment,
(*tmp)->add_offset, str_idx[ (*tmp)->name_idx] );
}
fprintf ( map, "\n\n Address Publics by Value\n");
qsort ( idx, tot_sym, sizeof(struct SYM_DATA *), sym_by_value );
for ( tmp = idx; (*tmp) ; ++tmp)
{
fprintf( map, "\n %04x:%04x %s", (*tmp)->add_segment,
(*tmp)->add_offset, str_idx[ (*tmp)->name_idx] );
}
free(idx); /* return to free memory */
}
sym_by_name(a, b)
struct SYM_DATA **a, **b;
{
return ( strcmp( str_idx[ (*a)->name_idx], str_idx[ (*b)->name_idx]) );
}
sym_by_value ( a, b)
struct SYM_DATA **a, **b;
{
long a_add, b_add, add_to_long() ;
int ret_value;
a_add = add_to_long( (*a)->add_segment, (*a)->add_offset);
b_add = add_to_long( (*b)->add_segment, (*b)->add_offset);
(a_add == b_add) ? ( ret_value = 0) :
((a_add < b_add) ? (ret_value = -1) : (ret_value = 1) ) ;
return (ret_value);
}
long add_to_long ( segment, offset)
unsigned int segment, offset;
{
long ret_value ;
ret_value = (long) segment << 4 ;
ret_value += (long) offset ;
return (ret_value);
}
save_src_line ( src)
struct SRC_RECORD *src;
{
unsigned char *obj_offset;
int cnt ;
store_src ( src); /* save start of function */
/* Process the source lines for this function */
/* each offset byte represents a source line */
for ( obj_offset = src->obj_displ , cnt = 0 ; cnt < LINEENTRY ;
++obj_offset, ++src->line_num, ++cnt )
{
if ( *obj_offset)
{
if (*obj_offset == 0xff)
break ; /* end of table */
store_src ( src);
if ( *obj_offset < 0x80 )
src->add_offset += *obj_offset ; /* additional offset */
else
{
/* 15 bit object code offset */
*obj_offset &= 0x7f ; /* mask off flag bit */
src->add_offset += ( *obj_offset++ << 8) ;/* high 7 bits */
src->add_offset += *obj_offset ; /* low 8 bits */
}
}
}
}
store_src ( src)
struct SRC_RECORD *src;
{
struct SRC_DATA *tmp;
tmp = (struct SRC_DATA *) malloc( sizeof(struct SRC_DATA)) ;
if (tmp == NULL)
err_abort( "store_src - out of memory ");
/* copy to memory storage */
tmp->add_offset = src->add_offset ;
tmp->add_segment = src->add_segment ;
tmp->line_num = src->line_num ;
tmp->file_idx = src->file_idx ;
if (tmp->file_idx < max_symbol)
max_symbol = tmp->file_idx; /* global symbols proceed
file names in the string
table */
/* add to linked list */
tmp->next = src_list ;
src_list = tmp ;
++src_count ;
}
print_src_data( map)
FILE *map;
{
struct SRC_DATA **tmp, **idx, *cur;
int src_data_cmp();
char *src_file, *obj_file;
int count ;
/* generate source line data index */
tmp = idx = (struct SRC_DATA **)
malloc( sizeof(struct SRC_DATA *) * (src_count + 1) ) ;
if (idx == NULL)
err_abort("print_src_data - out of memory ");
for ( cur = src_list ; cur != NULL ; cur = cur->next)
{
*tmp++ = cur ;
*tmp = NULL ;
}
qsort( idx, src_count, sizeof(struct SRC_DATA *), src_data_cmp);
for ( tmp = idx; *tmp != NULL ; )
{
src_file = str_idx[ (*tmp)->file_idx ] ;
obj_file = filename( src_file, ".obj");
fprintf( map,"\n\nLine numbers for %s(%s)\n\n",
obj_file, src_file);
free( obj_file); /* release free memory */
/* print line data for this source module */
for ( count = 1 ; (*tmp != NULL) &&
(strcmp( src_file, str_idx[ (*tmp)->file_idx]) == 0 ) ;
++tmp )
{
if (( *(tmp + 1) == NULL) ||
( (*tmp)->add_segment != (*(tmp + 1))->add_segment) ||
( (*tmp)->add_offset != (*(tmp + 1))->add_offset) )
{
fprintf (map, "%6d %04X:%04X%s", (*tmp)->line_num,
(*tmp)->add_segment, (*tmp)->add_offset,
(count % 4) ? "" : "\n" );
++count;
}
}
}
fprintf (map, "\n\n");
free(idx);
}
src_data_cmp ( a, b)
struct SRC_DATA **a, **b;
{
int ret_value;
ret_value = strcmp( str_idx[ (*a)->file_idx], str_idx[ (*b)->file_idx] );
if ( ret_value == 0)
( (*a)->line_num < (*b)->line_num) ?
( ret_value = -1) : (ret_value = 1) ;
return (ret_value);
}
char *filename( path, ext)
char *path, *ext;
{
char *f_path, *bf;
f_path = malloc( strlen(path) + 5); /* get buffer space */
if (f_path == NULL)
err_abort("filename - out of memory ");
strcpy( f_path, path);
if ((bf = strchr( f_path, '.')) != NULL )
*bf = '\0'; /* truncate extension */
strcat( f_path, ext); /* add the extension */
return( f_path);
}
read_strings( dbg)
int dbg ; /* input file handle */
{
char **idx_ptr; /* string index pointer */
char *s_ptr;
int count ;
long position ; /* return value for lseek() */
int error ; /* return value for file operations */
/* Read in strings (symbol names ) */
position = lseek( dbg, (long) dbg_header.start_string * 64, SEEK_SET);
if (position == -1L)
err_abort( dbg_file);
s_ptr = str_buff = malloc( dbg_header.tot_str_lnth); /* get string buffer */
if (str_buff == NULL)
err_abort ("read_strings - out of memory ");
error = read( dbg, str_buff, dbg_header.tot_str_lnth);
if (error == -1)
err_abort (dbg_file);
/* string index buffer */
idx_ptr = str_idx =
(char **) malloc( sizeof(char *) * (dbg_header.num_strings + 2) );
if (str_idx == NULL)
err_abort ("read_strings - out of memory ");
*idx_ptr++ = NULL; /* string indexes are base 1 */
for( count = dbg_header.num_strings ; count ; --count)
{
*idx_ptr++ = s_ptr ; /* current string starting address */
s_ptr += strlen( s_ptr) + 1 ; /* advance to the next string */
}
*idx_ptr = NULL;
}
err_abort(msg)
char *msg;
{
perror(msg); /* display error message */
exit (1); /* abort */
}
/* */