Category : Recently Uploaded Files
Archive   : DPMIGCC5.ZIP
Filename : SYMS.C

 
Output of file : SYMS.C contained in archive : DPMIGCC5.ZIP
/* This file is SYMS.C
**
** changed Rainer Schnitker
*/

/*
** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include
#include
#include
#include
#include
#include
#include
#include

#ifndef __GO32__
#include
#else
#include
#endif

typedef unsigned char word8;
typedef unsigned short word16;
typedef unsigned long word32;
typedef short int16;

#include "coff.h"
#include "syms.h"
#include "stab.h"

extern int ptrace_get_register(int);

int undefined_symbol = 0;

struct reg_names {
char *name;
int size;
int ofs;
};

struct reg_names regs[] =
{
{ "%eip", 4, EIP },
{ "%eflags", 4, EFL },
{ "%eax", 4, EAX },
{ "%ebx", 4, EBX },
{ "%ecx", 4, ECX },
{ "%edx", 4, EDX },
{ "%esp", 4, ESP },
{ "%ebp", 4, EBP },
{ "%esi", 4, ESI },
{ "%edi", 4, EDI },
{ "%ax", 2, EAX },
{ "%bx", 2, EBX },
{ "%cx", 2, ECX },
{ "%dx", 2, EDX },
{ "%ah", 0, EAX },
{ "%bh", 0, EBX },
{ "%ch", 0, ECX },
{ "%dh", 0, EDX },
{ "%al", 1, EAX },
{ "%bl", 1, EBX },
{ "%cl", 1, ECX },
{ "%dl", 1, EDX },
{ 0, 0, 0 }
};

typedef struct SYM_ENTRY {
word32 string_off;
word8 type;
word8 other;
word16 desc;
word32 val;
} SYM_ENTRY;

static FILHDR f_fh;
static AOUTHDR f_ah;
static SCNHDR *f_sh;
static SYMENT *f_symtab;
static SYM_ENTRY *f_aoutsyms;
static AUXENT *f_aux;
static LINENO **f_lnno;
static char *f_string_table;
static char *f_types;

/* built internally */

typedef struct {
char *filename;
word32 first_address;
word32 last_address;
LINENO *lines;
int num_lines;
} FileNode;

static FileNode *files;
static int num_files;

typedef struct SymNode {
char *name;
word32 address;
char type_c;
} SymNode;

static SymNode *syms;
static SymNode *syms_byname;
static int num_syms;

static int syms_sort_bn(const void *a, const void *b)
{
SymNode *sa = (SymNode *)a;
SymNode *sb = (SymNode *)b;
return strcmp(sa->name, sb->name);
}

static int syms_sort_bv(const void *a, const void *b)
{
SymNode *sa = (SymNode *)a;
SymNode *sb = (SymNode *)b;
return sa->address - sb->address;
}

static char *symndup(char *s, int len)
{
char c = s[len], *rv;
s[len] = 0;
rv = strdup(s);
s[len] = c;
return rv;
}

static int valid_symbol(int i)
{
char *sn;
if (f_symtab[i].e.e.e_zeroes)
sn = f_symtab[i].e.e_name;
else
sn = f_string_table + f_symtab[i].e.e.e_offset;
if (sn[0] != '_')
return 0;
if (strncmp(sn, "___gnu_compiled", 15) == 0)
return 0;
if (strcmp(sn, "__DYNAMIC") == 0)
return 0;
return 1;
}

static void * xmalloc(int size)
{
void *p;
if ((p = malloc(size)) == NULL) {
printf("malloc %d failed", size);
exit(1);
}
memset (p, 0, size);
return p;
}

static void process_coff(FILE *fd, long ofs)
{
int i, f, s, f_pending;
LINENO *l;
int l_pending;
word32 strsize;
char *name;

fseek(fd, ofs, 0);
fread(&f_fh, 1, FILHSZ, fd);
fread(&f_ah, 1, AOUTSZ, fd);

printf("COFF HEADER\n");
printf("text = %08lX\n", f_ah.tsize);
printf("data = %08lX\n", f_ah.dsize);
printf("bss = %08lX\n", f_ah.bsize);
printf("entry = %08lX\n", f_ah.entry);

f_sh = (SCNHDR *)xmalloc(f_fh.f_nscns * SCNHSZ);
f_types = (char *)xmalloc(f_fh.f_nscns);
f_lnno = (LINENO **)xmalloc(f_fh.f_nscns * sizeof(LINENO *));
fread(f_sh, f_fh.f_nscns, SCNHSZ, fd);

for (i=0; i {
if (f_sh[i].s_flags & STYP_TEXT)
f_types[i] = 'T';
if (f_sh[i].s_flags & STYP_DATA)
f_types[i] = 'D';
if (f_sh[i].s_flags & STYP_BSS)
f_types[i] = 'B';
if (f_sh[i].s_nlnno)
{
fseek(fd, ofs + f_sh[i].s_lnnoptr, 0L);
f_lnno[i] = (LINENO *)xmalloc(f_sh[i].s_nlnno * LINESZ);
fread(f_lnno[i], LINESZ, f_sh[i].s_nlnno, fd);
}
else
f_lnno[i] = 0;
}

fseek(fd, ofs + f_fh.f_symptr + f_fh.f_nsyms * SYMESZ, 0);
fread(&strsize, 1, 4, fd);
f_string_table = (char *)xmalloc(strsize);
fread(f_string_table+4, 1, strsize-4, fd);
f_string_table[0] = 0;

fseek(fd, ofs+f_fh.f_symptr, 0);
f_symtab = (SYMENT *)xmalloc(f_fh.f_nsyms * SYMESZ);
fread(f_symtab, SYMESZ, f_fh.f_nsyms, fd);
f_aux = (AUXENT *)f_symtab;

num_syms = num_files = 0;
for (i=0; i {
switch (f_symtab[i].e_sclass)
{
case C_FILE:
num_files++;
break;
case C_EXT:
case C_STAT:
if (!valid_symbol(i))
break;
num_syms++;
break;
}
i += f_symtab[i].e_numaux;
}

files = (FileNode *)xmalloc(num_files * sizeof(FileNode));

syms = (SymNode *)xmalloc(num_syms * sizeof(SymNode));

f = s = f_pending = l_pending = 0;
for (i=0; i {
switch (f_symtab[i].e_sclass)
{
case C_FILE:
if (f_aux[i+1].x_file.x_n.x_zeroes)
files[f].filename = symndup(f_aux[i+1].x_file.x_fname, 16);
else
files[f].filename = f_string_table + f_aux[i+1].x_file.x_n.x_offset;
files[f].lines = 0;
f_pending = 1;
f++;
break;
case C_EXT:
case C_STAT:

if (f_symtab[i].e.e.e_zeroes)
name = f_symtab[i].e.e_name;
else
name = f_string_table + f_symtab[i].e.e.e_offset;

if (f_pending && strcmp(name, ".text") == 0)
{
files[f-1].first_address = f_symtab[i].e_value;
files[f-1].last_address = f_symtab[i].e_value + f_aux[i+1].x_scn.x_scnlen - 1;
files[f-1].num_lines = f_aux[i+1].x_scn.x_nlinno;
f_pending = 0;
}

if (ISFCN(f_symtab[i].e_type))
{
int scn = f_symtab[i].e_scnum - 1;
l = f_lnno[scn] + ((f_aux[i+1].x_sym.x_fcnary.x_fcn.x_lnnoptr - f_sh[scn].s_lnnoptr)/LINESZ);
l_pending = 1;
l->l_addr.l_paddr = f_symtab[i].e_value;
}

if (!valid_symbol(i))
break;

syms[s].address = f_symtab[i].e_value;
if (f_symtab[i].e.e.e_zeroes)
syms[s].name = symndup(f_symtab[i].e.e_name, 8);
else
syms[s].name = f_string_table + f_symtab[i].e.e.e_offset;

switch (f_symtab[i].e_scnum)
{
case 1 ... 10:
syms[s].type_c = f_types[f_symtab[i].e_scnum-1];
break;
case N_UNDEF:
syms[s].type_c = 'U';
break;
case N_ABS:
syms[s].type_c = 'A';
break;
case N_DEBUG:
syms[s].type_c = 'D';
break;
}
if (f_symtab[i].e_sclass == C_STAT)
syms[s].type_c += 'a' - 'A';

s++;
break;
case C_FCN:
if (f_pending && files[f-1].lines == 0)
{
files[f-1].lines = l;
}
if (l_pending)
{
int lbase = f_aux[i+1].x_sym.x_misc.x_lnsz.x_lnno - 1;
int i2;
l->l_lnno = lbase;
l++;
for (i2=0; l[i2].l_lnno; i2++)
l[i2].l_lnno += lbase;
l_pending = 0;
}
break;
}
i += f_symtab[i].e_numaux;
}
}

#define _N_HDROFF(x) _n_hdroff
#define N_TXTOFF(x) ( _N_HDROFF((x)) + sizeof (GNU_AOUT))
#define N_DATOFF(x) (N_TXTOFF(x) + (x).tsize)
#define N_TRELOFF(x) (N_DATOFF(x) + (x).dsize)
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).txrel)
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).dtrel)
#define N_STROFF(x) (N_SYMOFF(x) + (x).symsize)

static void process_aout(FILE *fd, long ofs)
{
GNU_AOUT header;
word32 string_table_length;
DWORD _n_hdroff;
int nsyms, i, f, s, l;

fseek(fd, ofs, 0);
fread(&header, 1, sizeof(header), fd);

if (header.entry == 0x10000)
_n_hdroff = (1024 - sizeof(GNU_AOUT));
else if (header.entry == 0x1020)
_n_hdroff = 0;
else {
printf("Not supported a.out file type\n");
return;
}

printf("GNUAOUT HEADER\n");
printf("text = %08lX\n", header.tsize);
printf("data = %08lX\n", header.dsize);
printf("bss = %08lX\n", header.bsize);
printf("entry = %08lX\n", header.entry);
printf("syms = %08lX\n", header.symsize);

fseek(fd, ofs + N_SYMOFF(header),0);
nsyms = header.symsize / sizeof(SYM_ENTRY);
f_aoutsyms = (SYM_ENTRY *)xmalloc(header.symsize);
fread(f_aoutsyms, 1, header.symsize, fd);

fread(&string_table_length, 1, 4, fd);
f_string_table = (char *)xmalloc(string_table_length);
fread(f_string_table+4, 1, string_table_length-4, fd);
f_string_table[0] = 0;

num_files = num_syms = 0;
for (i=0; i {
char *symn = f_string_table + f_aoutsyms[i].string_off;
char *cp;
switch (f_aoutsyms[i].type & ~N_EXT)
{
case N_SO:
if (symn[strlen(symn)-1] == '/')
break;
num_files++;
break;
case N_TEXT:
cp = symn + strlen(symn) - 2;
if (strncmp(symn, "___gnu", 6) == 0 ||
strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
strcmp(cp, ".o") == 0)
break;
case N_DATA:
case N_ABS:
case N_BSS:
case N_FN:
case N_SETV:
case N_SETA:
case N_SETT:
case N_SETD:
case N_SETB:
case N_INDR:
num_syms ++;
break;
}
}

syms = (SymNode *)xmalloc(num_syms * sizeof(SymNode));
memset(syms, num_syms * sizeof(SymNode), 0);
files = (FileNode *)xmalloc(num_files * sizeof(FileNode));
memset(files, num_files * sizeof(FileNode), 0);

f = s = 0;
for (i=0; i {
char c, *cp;
char *symn = f_string_table + f_aoutsyms[i].string_off;
switch (f_aoutsyms[i].type & ~N_EXT)
{
case N_SO:
if (symn[strlen(symn)-1] == '/')
break;
if (f && files[f-1].last_address == 0)
files[f-1].last_address = f_aoutsyms[i].val - 1;
files[f].filename = symn;
files[f].first_address = f_aoutsyms[i].val;
f ++;
break;
case N_SLINE:
files[f-1].num_lines++;
break;
case N_TEXT:
cp = symn + strlen(symn) - 2;
if (strncmp(symn, "___gnu", 6) == 0 ||
strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
strcmp(cp, ".o") == 0)
{
if (f && files[f-1].last_address == 0)
files[f-1].last_address = f_aoutsyms[i].val - 1;
break;
}
c = 't';
goto sym_c;
case N_DATA:
c = 'd';
goto sym_c;
case N_ABS:
c = 'a';
goto sym_c;
case N_BSS:
c = 'b';
goto sym_c;
case N_FN:
c = 'f';
goto sym_c;
case N_SETV:
c = 'v';
goto sym_c;
case N_SETA:
c = 'v';
goto sym_c;
case N_SETT:
c = 'v';
goto sym_c;
case N_SETD:
c = 'v';
goto sym_c;
case N_SETB:
c = 'v';
goto sym_c;
case N_INDR:
c = 'i';
sym_c:
syms[s].name = symn;
syms[s].address = f_aoutsyms[i].val;
syms[s].type_c = (f_aoutsyms[i].type & N_EXT) ? (c+'A'-'a') : c;
s ++;
break;
}
}

l = f = 0;
for (i=0; i {
/* char c, *cp;*/
char *symn = f_string_table + f_aoutsyms[i].string_off;
switch (f_aoutsyms[i].type & ~N_EXT)
{
case N_SO:
if (symn[strlen(symn)-1] == '/')
break;
files[f].lines = (LINENO *)xmalloc(files[f].num_lines * sizeof(LINENO));
f++;
l = 0;
break;
case N_SLINE:
files[f-1].lines[l].l_addr.l_paddr = f_aoutsyms[i].val;
files[f-1].lines[l].l_lnno = f_aoutsyms[i].desc;
l ++;
break;
}
}
}

struct exe_hdr {
unsigned short signatur;
unsigned short low;
unsigned short high;
unsigned short reloc;
unsigned short hdr_para;
};

struct emx_hdr {
char sig[18];
char next_off[4];
};

int skip_exe_hdr(FILE *fd, unsigned long *headoff)
{
struct exe_hdr exehdr;
struct emx_hdr emxhdr;
*headoff=0;

fseek(fd, 0, 0);
fread(&exehdr, sizeof(struct exe_hdr), 1, fd);

if (exehdr.signatur == 0x5a4d) {
*headoff = ((unsigned long) exehdr.hdr_para) * 16;
fseek(fd, *headoff, 0);
fread(&emxhdr, sizeof(struct emx_hdr), 1, fd);
if (memcmp(emxhdr.sig, "emx", 3) == 0)
*headoff = *(int *) emxhdr.next_off;
else { /* not a emx file */
long new_off;

fseek(fd, 0x3C, SEEK_SET);
fread(&new_off, sizeof(long), 1, fd);
if (new_off) {
char pe_sig[4];
fseek(fd, new_off, SEEK_SET);
fread(pe_sig, sizeof(pe_sig), 1, fd);
printf("file is a new executable '%c%c'", pe_sig[0], pe_sig[1]);
if (pe_sig[0]) {
*headoff = new_off + 4;
}
}
else { /* djgpp */
*headoff = (DWORD) exehdr.high * 512L;
if (exehdr.low)
*headoff += (DWORD) exehdr.low - 512L;
}
}
}
if (!fseek(fd, *headoff, 0))
return 0;
else {
*headoff = 0;
fseek(fd, 0, 0);
return -1;
}
}

static void process_file(FILE *fd, long ofs)
{
short s;
skip_exe_hdr(fd, &ofs);
fread(&s, 2, 1, fd);

switch (s)
{
case 0x014c: /* .coff */
process_coff(fd, ofs);
break;
case 0x010b: /* a.out ZMAGIC */
case 0x0107: /* a.out object */
process_aout(fd, ofs);
break;
}
}

void syms_init(char *fname)
{
FILE *fd = fopen(fname, "rb");
if (fd == 0)
{
perror(fname);
}
else
{
process_file(fd, 0);

syms_byname = (SymNode *)xmalloc(num_syms * sizeof(SymNode));
memcpy(syms_byname, syms, num_syms * sizeof(SymNode));
qsort(syms_byname, num_syms, sizeof(SymNode), syms_sort_bn);
qsort(syms, num_syms, sizeof(SymNode), syms_sort_bv);

fclose(fd);
}
}

int lookup_sym_byname(char *name, int idx, int ofs)
{
int below, above;
char ch = name[idx];
name[idx] = 0;

below = -1;
above = num_syms;
while (above - below > 1)
{
int mid = (above + below) / 2;
int c = 0;
if (ofs)
c = '_' - syms_byname[mid].name[0];
if (c == 0)
c = strcmp(name, syms_byname[mid].name+ofs);
if (c == 0)
{
name[idx] = ch;
return mid;
}
if (c < 0)
above = mid;
else
below = mid;
}
name[idx] = ch;
return -1;
}

word32 syms_name2val(char *name)
{
int idx, sign=1, i;
word32 v,pt;
char *cp;

undefined_symbol = 0;

idx = 0;
sscanf(name, "%s", name);

if (name[0] == 0)
return 0;

if (name[0] == '-')
{
sign = -1;
name++;
}
else if (name[0] == '+')
{
name++;
}
if (isdigit(name[0]))
{
if (sign == -1)
return -strtol(name, 0, 0);
return strtol(name, 0, 0);
}

cp = strpbrk(name, "+-");
if (cp)
idx = cp-name;
else
idx = strlen(name);

if (name[0] == '%') /* register */
{
for (i=0; regs[i].name; i++)
if (strncmp(name, regs[i].name, idx) == 0)
{
pt = ptrace_get_register(regs[i].ofs * 4);
switch (regs[i].size)
{
case 0: /* ah */
v = (pt>>8) & 0xFF;
break;
case 1: /* al */
v = pt & 0xFF;
break;
case 2: /* ax */
v = pt & 0xFFFF;
break;
case 4: /* eax */
v = pt;
break;
}
return v + syms_name2val(name+idx);
}
}

for (i=0; i if (name[i] == '#')
{
int f;
int lnum, l;
sscanf(name+i+1, "%d", &lnum);
for (f=0; f {
if ((strncmp(name, files[f].filename, i) == 0) && (files[f].filename[i] == 0))
{
for (l=0; l {
if (files[f].lines[l].l_lnno == lnum)
return files[f].lines[l].l_addr.l_paddr + syms_name2val(name+idx);
}
printf("undefined line number %.*s\n", idx, name);
undefined_symbol = 1;
return 0;
}
}
printf("Undefined file name %.*s\n", i, name);
undefined_symbol = 1;
return 0;
}

i = lookup_sym_byname(name, idx, 0);
if (i == -1)
i = lookup_sym_byname(name, idx, 1);
if (i != -1)
return syms_byname[i].address * sign + syms_name2val(name+idx);
printf("Undefined symbol %.*s\n", idx, name);
undefined_symbol = 1;
return 0;
}

static char noname_buf[11];

char *syms_val2name(word32 val, word32 *delta)
{
/* static char buf[1000];*/
int above, below, mid;

if (delta)
*delta = 0;

if (num_syms <= 0)
goto noname;
above = num_syms;
below = -1;
while (above-below > 1)
{
mid = (above+below)/2;
if (syms[mid].address == val)
break;
if (syms[mid].address > val)
above = mid;
else
below = mid;
}
if (syms[mid].address > val)
{
if (mid == 0)
goto noname;
mid--; /* the last below was it */
}
if (mid < 0)
goto noname;
if (strcmp(syms[mid].name, "_end") == 0)
goto noname;
if (strcmp(syms[mid].name, "__end") == 0)
goto noname;
if (strcmp(syms[mid].name, "_etext") == 0)
goto noname;
if (delta)
*delta = val - syms[mid].address;
return syms[mid].name;
noname:
sprintf(noname_buf, "%#lx", val);
return noname_buf;
}

char *syms_val2line(word32 val, int *lineret, int exact)
{
int f, l;
for (f=0; f {
if (val >= files[f].first_address && val <= files[f].last_address && files[f].lines)
{
for (l=files[f].num_lines-1; l >= 0 && files[f].lines[l].l_addr.l_paddr > val; l--);
if ((files[f].lines[l].l_addr.l_paddr != val) && exact)
return 0;
*lineret = files[f].lines[l].l_lnno;
return files[f].filename;
}
}
return 0;
}

int wild(char *pattern, char *string)
{
int nlit;
while (*pattern)
{
switch (*pattern)
{
case '*':
pattern++;
if (*pattern == 0)
return 1;
nlit=0;
while ((pattern[nlit] != 0)
&& (pattern[nlit] != '*')
&& (pattern[nlit] != '?') )
nlit++;
while (1)
{
if (strncmp(string, pattern, nlit) == 0)
break;
string++;
if (*string == 0)
return 0;
}
break;
case '?':
if (*string == 0)
return 0;
pattern++;
string++;
break;
default:
if (*pattern != *string)
return 0;
pattern++;
string++;
break;
}
}
if (*string)
return 0;
return 1;
}

void syms_listwild(char *pattern)
{
int linecnt = 0;
int lnum;
char *name;
int i, key;

for (i=0; i if (wild(pattern, syms_byname[i].name))
{
if (++linecnt > 20)
{
printf("--- More ---");
fflush(stdout);
key = getchar();
printf("\r \r");
switch (key)
{
case ' ':
linecnt = 0;
break;
case 13:
linecnt--;
break;
case 'q':
case 27:
return;
}
}
printf("0x%08lx %c %s", syms_byname[i].address, syms_byname[i].type_c, syms_byname[i].name);
name = syms_val2line(syms_byname[i].address, &lnum, 0);
if (name)
printf(", line %d of %s", lnum, name);
putchar('\n');
}
}


  3 Responses to “Category : Recently Uploaded Files
Archive   : DPMIGCC5.ZIP
Filename : SYMS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/