Fixed declarations in include/time.h file.
Deleted unused file include/stab.h and reloc utility.
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -g -ansi -Wall
|
||||
LIBS =
|
||||
|
||||
reloc: reloc.c
|
||||
$(CC) $(CFLAGS) -o reloc reloc.c
|
||||
|
||||
clean:
|
||||
-rm *core reloc reloc.o
|
||||
|
||||
shar: reloc.c makefile reloc.1 notes README
|
||||
shar reloc.c makefile reloc.1 notes README > reloc.shar
|
||||
@@ -1,71 +0,0 @@
|
||||
'\" t
|
||||
.TH RELOC 1 "3 MAy 1997"
|
||||
.SH NAME
|
||||
reloc \- examine NetBSD/sparc symbol table and relocation information
|
||||
.SH SYNOPSIS
|
||||
.B reloc
|
||||
[
|
||||
.B \-h
|
||||
.B \-x
|
||||
.B \-d
|
||||
.B \-t
|
||||
.B \-s
|
||||
.B \-c
|
||||
.B \-n
|
||||
.B \-a
|
||||
]
|
||||
.I infile
|
||||
.SH DESCRIPTION
|
||||
.B reloc
|
||||
examines NetBSD/sparc object and executable files (a.out format files)
|
||||
and prints a.out header, symbol table and relocation information in
|
||||
a human-readable form on stdout.
|
||||
.PP
|
||||
Performs a function similar to the
|
||||
.B nm
|
||||
system utility, but prints more of the information contained in an a.out
|
||||
file.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.TP 10
|
||||
.B \-h
|
||||
Print a representation of the a.out ``exec'' header.
|
||||
.TP
|
||||
.B \-x
|
||||
Print extra information derivable from, but not directly contained by
|
||||
the a.out header.
|
||||
.TP
|
||||
.B \-d
|
||||
Print a representation of the ``.data'' segment relocation information.
|
||||
.TP
|
||||
.B \-t
|
||||
Print a representation of the ``.text'' segment relocation information.
|
||||
.TP
|
||||
.B \-s
|
||||
Print a representation of the symbol table information.
|
||||
.TP
|
||||
.B \-c
|
||||
When printing relocation information, show the correspondence of the
|
||||
relocations to symbol table entries.
|
||||
.TP
|
||||
.B \-c
|
||||
When printing symbol table, don't print symbol names
|
||||
.TP
|
||||
.B \-a
|
||||
Show everything: equivalent to ``-h -d -t -s -c -x''
|
||||
.SH FILES
|
||||
.I infile
|
||||
must be specified.
|
||||
.SH BUGS
|
||||
.PP
|
||||
The output format is awkward.
|
||||
.SH "SEE ALSO"
|
||||
.PD
|
||||
a.out(5), stab(5), nm(1), nlist(3)
|
||||
.SH AUTHOR
|
||||
Bruce Ediger, bediger@csn.net
|
||||
.PP
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
without any conditions or restrictions. This software is provided ``as
|
||||
is'' without express or implied warranty.
|
||||
@@ -1,668 +0,0 @@
|
||||
/*
|
||||
* reloc - program to print out all of the a.out header, symbol table, and
|
||||
* relocation information in an a.out file. Prints out more information
|
||||
* than ``nm'', and correlates a relocation info to symbol table entries if
|
||||
* it can.
|
||||
*
|
||||
* Author: Bruce Ediger, bediger@csn.net
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* without any conditions or restrictions. This software is provided
|
||||
* ``as is'' without express or implied warranty.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
|
||||
char *read_extent(FILE *fin, int rsize, int offset, int calling_lineno);
|
||||
char *read_stringtable(FILE *fin, struct exec *exhdr, int *strtbl_sz);
|
||||
|
||||
void cleanup(FILE *fin, int count, ...);
|
||||
|
||||
void run_header(struct exec *exhdr, int extended_info);
|
||||
void run_reloc(struct exec *exhdr, int size, struct relocation_info *data_reloc, struct nlist *symtabl, char *stringtable, int strtbl_sz, int correspondence);
|
||||
void run_symtable(struct exec *exhdr, struct nlist *symbol_table, char *stringtable, int strtbl_sz, int print_symnames);
|
||||
|
||||
char *print_reloc_type(enum reloc_type type);
|
||||
char *symbol_type(struct nlist *sym);
|
||||
char *print_reloc_segment(int segnum);
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
struct stat attributes;
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
FILE *fin = NULL;
|
||||
struct exec *exhdr = NULL;
|
||||
char *fname = NULL;
|
||||
char *stringtable;
|
||||
int strtbl_sz;
|
||||
struct relocation_info *data_reloc = NULL, *text_reloc = NULL;
|
||||
struct nlist *symbol_table = NULL;
|
||||
int show_header = 0;
|
||||
int show_data_reloc = 0;
|
||||
int show_text_reloc = 0;
|
||||
int show_symbol_table = 0;
|
||||
int print_symnames = 1;
|
||||
int correspondence = 0;
|
||||
int hdr_info = 0;
|
||||
int opt;
|
||||
|
||||
while (-1 != (opt = getopt(ac, av, "hdtsacxn"))) {
|
||||
switch (opt) {
|
||||
case 'h': show_header = 1; break;
|
||||
case 'x': show_header = hdr_info = 1; break; /* show_header implied */
|
||||
case 'd': show_data_reloc = 1; break;
|
||||
case 't': show_text_reloc = 1; break;
|
||||
case 's': show_symbol_table = 1; break;
|
||||
case 'c': correspondence = 1; break;
|
||||
case 'n': print_symnames = 0; break;
|
||||
case 'a':
|
||||
show_header = show_data_reloc = show_text_reloc = show_symbol_table = correspondence = hdr_info = 1;
|
||||
break;
|
||||
default: errout:
|
||||
fprintf(stderr, "%s: show exec header, relocation and symbol table data\n", av[0]);
|
||||
fprintf(stderr, "usage: %s [-h] [-d] [-t] [-s] [-c] [-x] [-a] <filename>\n", av[0]);
|
||||
fprintf(stderr, " -h: show exec header\n"
|
||||
" -x: show info derivable from exec header \n"
|
||||
" -d: show data segment relocations\n"
|
||||
" -t: show text segment relocations\n"
|
||||
" -c: show symbols that correspond to relocations\n"
|
||||
" -s: show symbol table\n"
|
||||
" -n: when showing symbol table, don't print symbol names\n"
|
||||
" -a: show it all\n");
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == show_header && 0 == show_data_reloc && 0 == show_text_reloc &&
|
||||
0 == show_symbol_table)
|
||||
show_header = show_data_reloc = show_text_reloc = show_symbol_table = correspondence = 1;
|
||||
|
||||
if (optind < ac)
|
||||
fname = av[optind];
|
||||
|
||||
if (NULL == fname) {
|
||||
fprintf(stderr, "Need a file to examine\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (NULL == (fin = fopen(fname, "r"))) {
|
||||
fprintf(stderr, "Couldn't open \"%s\" for reading: %s\n",
|
||||
fname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stat(fname, &attributes) < 0) {
|
||||
fprintf(stderr, "Problem on stat(2) of \"%s\": %s\n",
|
||||
fname, strerror(errno));
|
||||
fclose(fin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
exhdr = (struct exec *)read_extent(fin, sizeof(*exhdr), 0, __LINE__);
|
||||
|
||||
if (NULL == exhdr) {
|
||||
cleanup(fin, 1, exhdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (show_header) {
|
||||
puts("a.out header:");
|
||||
run_header(exhdr, hdr_info);
|
||||
}
|
||||
|
||||
if (N_BADMAG(*exhdr)) {
|
||||
fprintf(stderr, "%s isn't a recognized NetBSD a.out file\n", fname);
|
||||
cleanup(fin, 1, exhdr);
|
||||
return 3;
|
||||
}
|
||||
|
||||
stringtable = read_stringtable(fin, exhdr, &strtbl_sz);
|
||||
data_reloc = (struct relocation_info *)read_extent(fin, exhdr->a_drsize, N_DRELOFF(*exhdr), __LINE__);
|
||||
text_reloc = (struct relocation_info *)read_extent(fin, exhdr->a_trsize, N_TRELOFF(*exhdr), __LINE__);
|
||||
symbol_table = (struct nlist *) read_extent(fin, exhdr->a_syms, N_SYMOFF(*exhdr), __LINE__);
|
||||
|
||||
if (show_data_reloc) {
|
||||
puts("\nData relocations:");
|
||||
run_reloc(exhdr, exhdr->a_drsize, data_reloc, symbol_table, stringtable, strtbl_sz, correspondence);
|
||||
}
|
||||
|
||||
if (show_text_reloc) {
|
||||
puts("\nText relocations:");
|
||||
run_reloc(exhdr, exhdr->a_trsize, text_reloc, symbol_table, stringtable, strtbl_sz, correspondence);
|
||||
}
|
||||
|
||||
if (show_symbol_table) {
|
||||
puts("\nSymbol table:");
|
||||
run_symtable(exhdr, symbol_table, stringtable, strtbl_sz, print_symnames);
|
||||
}
|
||||
|
||||
cleanup(fin, 5, exhdr, stringtable, data_reloc, text_reloc, symbol_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup(FILE *fin, int count, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
if (NULL != fin)
|
||||
fclose(fin);
|
||||
|
||||
va_start(ap, count);
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
char *p = va_arg(ap, char *);
|
||||
|
||||
if (NULL != p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
char *
|
||||
read_stringtable(FILE *fin, struct exec *exhdr, int *strtbl_sz)
|
||||
{
|
||||
unsigned long length;
|
||||
char *p = NULL;
|
||||
|
||||
assert(NULL != fin);
|
||||
|
||||
if (NULL == exhdr) {
|
||||
fprintf(stderr, "Trying to read string table, but got no a.out header\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fseek(fin, N_STROFF(*exhdr), SEEK_SET) < 0) {
|
||||
fprintf(stderr, "Problem seeking to string table: %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fread(&length, sizeof(length), 1, fin) != 1) {
|
||||
fprintf(stderr, "Problem reading length of string table: %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (length >= 4) {
|
||||
p = read_extent(fin, length, N_STROFF(*exhdr), __LINE__);
|
||||
*strtbl_sz = length;
|
||||
printf("\nstring table size %d\n", *strtbl_sz);
|
||||
} else {
|
||||
fprintf(stderr, "Problem, length of string table read as %d,"
|
||||
" can't be right\n, ", length);
|
||||
*strtbl_sz = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
read_extent(FILE *fin, int rsize, int offset, int calling_lineno)
|
||||
{
|
||||
char *r = NULL;
|
||||
off_t potential_eof = (off_t)rsize + (off_t)offset;
|
||||
|
||||
assert(NULL != fin);
|
||||
|
||||
if (potential_eof > attributes.st_size) {
|
||||
fprintf(stderr, "Line %d, reading extent from %d, size %d:"
|
||||
" larger than file size %qd\n", calling_lineno, offset,
|
||||
rsize, attributes.st_size);
|
||||
|
||||
} else if (fseek(fin, offset, SEEK_SET) < 0) {
|
||||
|
||||
fprintf(stderr, "Line %d, seeking to extent at %d, file size %qd: %s\n",
|
||||
calling_lineno, offset, attributes.st_size, strerror(errno));
|
||||
|
||||
} else {
|
||||
|
||||
r = malloc(rsize);
|
||||
assert(NULL != r);
|
||||
|
||||
if (fread(r, 1, rsize, fin) != rsize) {
|
||||
fprintf(stderr, "Line %d, problem reading in extent\n", calling_lineno);
|
||||
free(r);
|
||||
r = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
run_reloc(
|
||||
struct exec *exhdr,
|
||||
int size,
|
||||
struct relocation_info *reloc,
|
||||
struct nlist *symtabl,
|
||||
char *stringtable,
|
||||
int strtbl_sz,
|
||||
int correspondence
|
||||
)
|
||||
{
|
||||
int i, count;
|
||||
int max_ordinal;
|
||||
|
||||
if (NULL == exhdr || NULL == symtabl || NULL == stringtable || NULL == reloc) {
|
||||
if (NULL == exhdr) fprintf(stderr, "a.out header NULL, ");
|
||||
if (NULL == symtabl) fprintf(stderr, "symbol table NULL, ");
|
||||
if (NULL == stringtable) fprintf(stderr, "string table NULL, ");
|
||||
if (NULL == reloc) fprintf(stderr, "relocation table NULL, ");
|
||||
fprintf(stderr, " can't possibly list the relocations meaningfully\n");
|
||||
return;
|
||||
}
|
||||
|
||||
max_ordinal = exhdr->a_syms/sizeof(*symtabl);
|
||||
|
||||
count = size/sizeof(*reloc);
|
||||
|
||||
printf("%d relocations\n", count);
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
printf("r_address 0x%x, symbol ordinal %d, ", reloc[i].r_address,
|
||||
reloc[i].r_symbolnum);
|
||||
|
||||
if (reloc[i].r_extern)
|
||||
fputs("extern, ", stdout);
|
||||
else {
|
||||
printf("local, %s segment, ", print_reloc_segment(reloc[i].r_symbolnum));
|
||||
}
|
||||
|
||||
printf(
|
||||
"r_addend 0x%x (%d), type %s (0x%x)",
|
||||
reloc[i].r_addend,
|
||||
reloc[i].r_addend,
|
||||
print_reloc_type(reloc[i].r_type), reloc[i].r_type
|
||||
);
|
||||
|
||||
|
||||
if (reloc[i].r_extern && correspondence && reloc[i].r_symbolnum <= max_ordinal) {
|
||||
char *sname = "";
|
||||
/* stuff from struct nlist associated with this relocation */
|
||||
|
||||
if (symtabl[reloc[i].r_symbolnum].n_un.n_strx >= 4 &&
|
||||
symtabl[reloc[i].r_symbolnum].n_un.n_strx < strtbl_sz)
|
||||
sname = &stringtable[symtabl[reloc[i].r_symbolnum].n_un.n_strx];
|
||||
else
|
||||
fprintf(stderr,
|
||||
"relocation entry %d, symbol ordinal %d, n_strx is %d, "
|
||||
"string table size is %d\n",
|
||||
i, reloc[i].r_symbolnum, symtabl[reloc[i].r_symbolnum].n_un.n_strx,
|
||||
strtbl_sz);
|
||||
|
||||
printf("\n name \"%s\" (sym num %d), type 0x%x - %s, desc 0x%x, value 0x%x\n",
|
||||
sname,
|
||||
reloc[i].r_symbolnum,
|
||||
symtabl[reloc[i].r_symbolnum].n_type,
|
||||
symbol_type(&symtabl[reloc[i].r_symbolnum]),
|
||||
symtabl[reloc[i].r_symbolnum].n_desc,
|
||||
symtabl[reloc[i].r_symbolnum].n_value
|
||||
);
|
||||
} else
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
print_reloc_type(enum reloc_type type)
|
||||
{
|
||||
char *r = NULL;
|
||||
|
||||
if (type == RELOC_8) {
|
||||
r = "RELOC_8, 8 bit simple, ";
|
||||
} else if (type == RELOC_16) {
|
||||
r = "RELOC_16, 16 bit simple, ";
|
||||
} else if (type == RELOC_32) {
|
||||
r = "RELOC_32, 32 bit simple, ";
|
||||
} else if (type == RELOC_DISP8) {
|
||||
r = "RELOC_DISP8, 8 bit PC relative, ";
|
||||
} else if (type == RELOC_DISP16) {
|
||||
r = "RELOC_DISP16, 16 bit PC relative, ";
|
||||
} else if (type == RELOC_DISP32) {
|
||||
r = "RELOC_DISP32, 32 bit PC relative, ";
|
||||
} else if (type == RELOC_WDISP30) {
|
||||
r = "RELOC_WDISP30, 30 bit PC relative CALL, ";
|
||||
} else if (type == RELOC_WDISP22) {
|
||||
r = "RELOC_WDISP22, 22 bit PC relative BRANCH, ";
|
||||
} else if (type == RELOC_HI22) {
|
||||
r = "RELOC_HI22, ";
|
||||
} else if (type == RELOC_22) {
|
||||
r = "RELOC_22, ";
|
||||
} else if (type == RELOC_13) {
|
||||
r = "RELOC_13, ";
|
||||
} else if (type == RELOC_LO10) {
|
||||
r = "RELOC_LO10, ";
|
||||
} else if (type == RELOC_BASE13) {
|
||||
r = "RELOC_BASE13, ";
|
||||
} else if (type == RELOC_BASE22) {
|
||||
r = "RELOC_BASE22, ";
|
||||
} else if (type == RELOC_PC10) {
|
||||
r = "RELOC_PC10, 10 bit PC relative PIC, ";
|
||||
} else if (type == RELOC_PC22) {
|
||||
r = "RELOC_PC22, 22 bit PC relative PIC, ";
|
||||
} else if (type == RELOC_JMP_TBL) {
|
||||
r = "RELOC_JMP_TBL, jump table relative PIC, ";
|
||||
} else if (type == RELOC_GLOB_DAT) {
|
||||
r = "RELOC_GLOB_DAT, rtld global data, ";
|
||||
} else if (type == RELOC_JMP_SLOT) {
|
||||
r = "RELOC_JMP_SLOT, rtld jump slot, ";
|
||||
} else if (type == RELOC_RELATIVE) {
|
||||
r = "RELOC_RELATIVE, rtld relative, ";
|
||||
} else {
|
||||
r = "some unknown reloc type..., ";
|
||||
}
|
||||
|
||||
assert(NULL != r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
print_reloc_segment(int segnum)
|
||||
{
|
||||
char *r = "unknown segment";
|
||||
|
||||
switch (segnum) {
|
||||
case N_TEXT: r = "N_TEXT"; break;
|
||||
case N_DATA: r = "N_DATA"; break;
|
||||
case N_BSS: r = "N_BSS"; break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char symbol_type_buffer[512];
|
||||
|
||||
char *
|
||||
symbol_type(struct nlist *sym)
|
||||
{
|
||||
unsigned char n_type = sym->n_type;
|
||||
|
||||
symbol_type_buffer[0] = '\0';
|
||||
|
||||
/*
|
||||
N_EXT = 0x01 = 0000 0001
|
||||
N_TYPE = 0x1e = 0001 1110
|
||||
N_STAB = 0xe0 = 1110 0000 <= not just a mask. if n_type field has
|
||||
one or more of these bits set, the whole
|
||||
n_type field is signifigant.
|
||||
*/
|
||||
|
||||
if (n_type & N_EXT)
|
||||
strcat(symbol_type_buffer, "external, ");
|
||||
|
||||
if ((n_type & N_TYPE) & ~N_EXT) {
|
||||
switch ((n_type & N_TYPE) & ~N_EXT) {
|
||||
case N_UNDF : strcat(symbol_type_buffer, "undefined, "); break;
|
||||
case N_ABS : strcat(symbol_type_buffer, "absolute address, "); break;
|
||||
case N_TEXT : strcat(symbol_type_buffer, "text segment, "); break;
|
||||
case N_DATA : strcat(symbol_type_buffer, "data segment, "); break;
|
||||
case N_BSS : strcat(symbol_type_buffer, "bss segment, "); break;
|
||||
case N_INDR : strcat(symbol_type_buffer, "alias definition, "); break;
|
||||
case N_SIZE : strcat(symbol_type_buffer, "symbol's size, "); break;
|
||||
case N_COMM : strcat(symbol_type_buffer, "common reference, "); break;
|
||||
case N_FN :
|
||||
if (n_type & N_EXT)
|
||||
strcat(symbol_type_buffer, "file name, ");
|
||||
else
|
||||
strcat(symbol_type_buffer, "warning message, ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((n_type & N_STAB)) {
|
||||
switch (n_type & ~N_EXT) {
|
||||
case N_GSYM: strcat(symbol_type_buffer, "global symbol, "); break;
|
||||
case N_FNAME: strcat(symbol_type_buffer, "F77 function name, "); break;
|
||||
case N_FUN: strcat(symbol_type_buffer, "procedure name, "); break;
|
||||
case N_STSYM: strcat(symbol_type_buffer, "data segment variable, "); break;
|
||||
case N_LCSYM: strcat(symbol_type_buffer, "bss segment variable, "); break;
|
||||
case N_MAIN: strcat(symbol_type_buffer, "main function name, "); break;
|
||||
case N_PC: strcat(symbol_type_buffer, "global Pascal symbol, "); break;
|
||||
case N_RSYM: strcat(symbol_type_buffer, "register variable, "); break;
|
||||
|
||||
case N_DSLINE: case N_BSLINE: case N_SLINE:
|
||||
sprintf(
|
||||
&symbol_type_buffer[strlen(symbol_type_buffer)],
|
||||
"line %d at address 0x%x, ",
|
||||
sym->n_desc,
|
||||
sym->n_value
|
||||
);
|
||||
break;
|
||||
|
||||
case N_SSYM: strcat(symbol_type_buffer, "structure/union element, "); break;
|
||||
case N_SO: strcat(symbol_type_buffer, "main source file name, "); break;
|
||||
|
||||
case N_LSYM:
|
||||
sprintf(
|
||||
&symbol_type_buffer[strlen(symbol_type_buffer)],
|
||||
"stack variable, [%%fp + %d]",
|
||||
sym->n_value
|
||||
);
|
||||
break;
|
||||
|
||||
case N_BINCL: strcat(symbol_type_buffer, "include file beginning, "); break;
|
||||
case N_SOL: strcat(symbol_type_buffer, "included source file name, "); break;
|
||||
|
||||
case N_PSYM:
|
||||
sprintf(
|
||||
&symbol_type_buffer[strlen(symbol_type_buffer)],
|
||||
"parameter variable, [%%fp + %d]",
|
||||
sym->n_value
|
||||
);
|
||||
break;
|
||||
|
||||
case N_EINCL: strcat(symbol_type_buffer, "include file end, "); break;
|
||||
case N_ENTRY: strcat(symbol_type_buffer, "alternate entry point, "); break;
|
||||
case N_LBRAC: strcat(symbol_type_buffer, "left bracket, "); break;
|
||||
case N_EXCL: strcat(symbol_type_buffer, "deleted include file, "); break;
|
||||
case N_RBRAC: strcat(symbol_type_buffer, "right bracket, "); break;
|
||||
case N_BCOMM: strcat(symbol_type_buffer, "begin common, "); break;
|
||||
case N_ECOMM: strcat(symbol_type_buffer, "end common, "); break;
|
||||
case N_ECOML: strcat(symbol_type_buffer, "end common (local name), "); break;
|
||||
case N_LENG: strcat(symbol_type_buffer, "length of preceding entry, "); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (' ' == symbol_type_buffer[strlen(symbol_type_buffer)-1])
|
||||
symbol_type_buffer[strlen(symbol_type_buffer)-1] = '\0';
|
||||
if (',' == symbol_type_buffer[strlen(symbol_type_buffer)-1])
|
||||
symbol_type_buffer[strlen(symbol_type_buffer)-1] = '\0';
|
||||
|
||||
return symbol_type_buffer;
|
||||
}
|
||||
|
||||
void
|
||||
run_symtable(
|
||||
struct exec *exhdr,
|
||||
struct nlist *symtabl,
|
||||
char *stringtable,
|
||||
int strtbl_sz,
|
||||
int sym_names)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
if (NULL == exhdr || NULL == symtabl || NULL == stringtable) {
|
||||
if (NULL == exhdr) fprintf(stderr, "a.out header NULL, ");
|
||||
if (NULL == symtabl) fprintf(stderr, "symbol table NULL, ");
|
||||
if (NULL == stringtable) fprintf(stderr, "string table NULL, ");
|
||||
fprintf(stderr, " can't possibly list the symbol table meaningfully\n");
|
||||
return;
|
||||
}
|
||||
|
||||
count = exhdr->a_syms/sizeof(*symtabl);
|
||||
|
||||
printf("%d symbols\n", count);
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (!sym_names)
|
||||
printf("%4d name offset (%d), type 0x%x - %s, other 0x%x, desc 0x%x, value 0x%x (%d)\n",
|
||||
i,
|
||||
symtabl[i].n_un.n_strx,
|
||||
symtabl[i].n_type,
|
||||
symbol_type(&symtabl[i]),
|
||||
symtabl[i].n_other,
|
||||
symtabl[i].n_desc,
|
||||
symtabl[i].n_value,
|
||||
symtabl[i].n_value
|
||||
);
|
||||
else {
|
||||
char *sname = "";
|
||||
|
||||
if (symtabl[i].n_un.n_strx >= 0 && symtabl[i].n_un.n_strx < strtbl_sz)
|
||||
sname = &stringtable[symtabl[i].n_un.n_strx];
|
||||
|
||||
printf("%4d name \"%s\" (%d), type 0x%x - %s, other 0x%x, desc 0x%x, value 0x%x (%d)\n",
|
||||
i,
|
||||
sname,
|
||||
symtabl[i].n_un.n_strx,
|
||||
symtabl[i].n_type,
|
||||
symbol_type(&symtabl[i]),
|
||||
symtabl[i].n_other,
|
||||
symtabl[i].n_desc,
|
||||
symtabl[i].n_value,
|
||||
symtabl[i].n_value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run_header(struct exec *exhdr, int extended_info)
|
||||
{
|
||||
char *id = NULL;
|
||||
|
||||
assert(NULL != exhdr);
|
||||
|
||||
/* print raw values */
|
||||
printf(
|
||||
"\ta_midmag 0x%08x (mid %d, magic 0%o, flag 0x%x)\n"
|
||||
"\ta_text 0x%08x\n"
|
||||
"\ta_data 0x%08x\n"
|
||||
"\ta_bss 0x%08x\n"
|
||||
"\ta_syms 0x%08x\n"
|
||||
"\ta_entry 0x%08x\n"
|
||||
"\ta_trsize 0x%08x\n"
|
||||
"\ta_drsize 0x%08x\n",
|
||||
exhdr->a_midmag,
|
||||
N_GETMID(*exhdr), N_GETMAGIC(*exhdr), N_GETFLAG(*exhdr),
|
||||
exhdr->a_text,
|
||||
exhdr->a_data,
|
||||
exhdr->a_bss,
|
||||
exhdr->a_syms,
|
||||
exhdr->a_entry,
|
||||
exhdr->a_trsize,
|
||||
exhdr->a_drsize
|
||||
);
|
||||
|
||||
printf(
|
||||
"magic number %04o: %s\n", N_GETMAGIC(*exhdr),
|
||||
N_GETMAGIC(*exhdr) == OMAGIC ? "old impure format" :
|
||||
N_GETMAGIC(*exhdr) == NMAGIC ? "read-only text" :
|
||||
N_GETMAGIC(*exhdr) == ZMAGIC ? "demand load format" :
|
||||
N_GETMAGIC(*exhdr) == QMAGIC ? "deprecated format" :
|
||||
"totally funky"
|
||||
);
|
||||
|
||||
switch (N_GETMID(*exhdr)) {
|
||||
case MID_ZERO: id = "unknown - implementation dependent"; break;
|
||||
case MID_SUN010: id = "sun 68010/68020 binary"; break;
|
||||
case MID_SUN020: id = "sun 68020-only binary"; break;
|
||||
case MID_PC386: id = "386 PC binary. (so quoth BFD)"; break;
|
||||
case MID_HP200: id = "hp200 (68010) BSD binary"; break;
|
||||
case MID_I386: id = "i386 BSD binary"; break;
|
||||
case MID_M68K: id = "m68k BSD binary with 8K page sizes"; break;
|
||||
case MID_M68K4K: id = "m68k BSD binary with 4K page sizes"; break;
|
||||
case MID_NS32532: id = "ns32532"; break;
|
||||
case MID_SPARC: id = "sparc"; break;
|
||||
case MID_PMAX: id = "pmax"; break;
|
||||
case MID_VAX: id = "vax"; break;
|
||||
case MID_ALPHA: id = "Alpha BSD binary"; break;
|
||||
case MID_MIPS: id = "big-endian MIPS"; break;
|
||||
case MID_ARM6: id = "ARM6"; break;
|
||||
case MID_HP300: id = "hp300 (68020+68881) BSD binary"; break;
|
||||
case MID_HPUX: id = "hp200/300 HP-UX binary"; break;
|
||||
case MID_HPUX800: id = "hp800 HP-UX binary"; break;
|
||||
default:
|
||||
id = "don't know"; break;
|
||||
}
|
||||
|
||||
printf("type %d, %s\n", N_GETMID(*exhdr), id);
|
||||
|
||||
/* this left shift seems a bit bogus */
|
||||
|
||||
switch((N_GETFLAG(*exhdr) & EX_DPMASK)>>4) {
|
||||
case 0:
|
||||
id = "traditional executable or object file"; break;
|
||||
case 1:
|
||||
id = "object file contains PIC code"; break;
|
||||
case 2:
|
||||
id = "dynamic executable"; break;
|
||||
case 3:
|
||||
id = "position independent executable image"; break;
|
||||
default:
|
||||
id = NULL;
|
||||
}
|
||||
|
||||
if (NULL != id)
|
||||
printf("flags: 0x%x, %s\n", N_GETFLAG(*exhdr), id);
|
||||
else
|
||||
printf("flags: 0x%x\n", N_GETFLAG(*exhdr));
|
||||
|
||||
if (extended_info) {
|
||||
unsigned long txt_addr;
|
||||
unsigned long dat_addr;
|
||||
unsigned long bss_addr;
|
||||
|
||||
/* N_TXTADDR and N_DATADDR macros DON'T WORK */
|
||||
if (N_GETMAGIC(*exhdr) == ZMAGIC) {
|
||||
txt_addr = __LDPGSZ;
|
||||
dat_addr = ((txt_addr + exhdr->a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1));
|
||||
} else if (N_GETMAGIC(*exhdr) == OMAGIC) {
|
||||
txt_addr = 0;
|
||||
dat_addr = txt_addr + exhdr->a_text;
|
||||
} else {
|
||||
txt_addr = 0xdeadbeef;
|
||||
dat_addr = 0xcafebabe;
|
||||
}
|
||||
|
||||
bss_addr = dat_addr + exhdr->a_data;
|
||||
|
||||
printf(" text segment size = 0x%lx, text segment file offset = %ld\n", exhdr->a_text, N_TXTOFF(*exhdr));
|
||||
printf(" data segment size = 0x%lx, data segment file offset = %ld\n", exhdr->a_data, N_DATOFF(*exhdr));
|
||||
printf(" bss segment size = 0x%lx\n", exhdr->a_bss);
|
||||
printf(" text segment relocation size = 0x%lx, file offset = %ld, %d text relocations\n",
|
||||
exhdr->a_trsize, N_TRELOFF(*exhdr), exhdr->a_trsize/sizeof(struct relocation_info));
|
||||
printf(" data segment relocation size = 0x%lx, file offset = %ld, %d data relocations\n",
|
||||
exhdr->a_drsize, N_DRELOFF(*exhdr), exhdr->a_drsize/sizeof(struct relocation_info));
|
||||
printf(" symbol table size = 0x%lx, symbol table file offset = %ld (%d symbols)\n",
|
||||
exhdr->a_syms, N_SYMOFF(*exhdr), exhdr->a_syms/sizeof(struct nlist));
|
||||
printf(" string table file offset = 0x%lx (%d)\n", N_STROFF(*exhdr), N_STROFF(*exhdr));
|
||||
printf(" entry point = 0x%lx\n", exhdr->a_entry);
|
||||
printf(" text address = 0x%lx\n\tdata address = 0x%lx\n"
|
||||
"\tbss address = 0x%lx\n",
|
||||
txt_addr, dat_addr, bss_addr
|
||||
/* N_TXTADDR(*exhdr), N_DATADDR(*exhdr), N_BSSADDR(*exhdr) */
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user