/* objdump -- dump information about an object file. Copyright (C) 1988, 1991 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Id$ */ /* * objdump * * dump information about an object file. Until there is other documentation, * refer to the manual page dump(1) in the system 5 program's reference manual */ #include #include #include "getopt.h" #include "as.h" /* #define COFF_ENCAPSULATE 1 */ typedef FILHDR fileheader; typedef struct exec fileheader; #ifdef __STDC__ static char *sym_pname(SYMENT *s); static char *xmalloc(unsigned size); static char *xrealloc(char *p, unsigned size); static void doit(char *filename); static void dump_data(fileheader *execp, FILE *f){}; static void dump_header(fileheader *execp, FILE *f); static void dump_lnno(fileheader *execp, FILE *f); static void dump_nstuff(fileheader *execp){}; static void dump_reloc(fileheader *execp, FILE *f); static void dump_section_contents(fileheader *execp, FILE *f); static void dump_section_headers(fileheader *execp, FILE *f); static void dump_sym(fileheader *execp, FILE *f); static void dump_text(fileheader *execp, FILE *f){}; static void hex_dump(void *buffer, int size); #endif /* __STDC__ */ #ifndef OBJ_COFF #ifndef OBJ_BOUT static void read_symbols (execp, f) #else read_symbols (execp, f) #endif /* OBJ_BOUT */ struct exec *execp; #else static void read_section_headers(execp, f) fileheader *execp; #endif /* OBJ_COFF */ FILE *f; { #ifndef OBJ_COFF int i; struct nlist *sp; if (symtbl) return; nsyms = execp->a_syms / sizeof (struct nlist); if (nsyms == 0) #else if (section_headers || execp->f_nscns == 0) { #endif /* OBJ_COFF */ return; #ifdef OBJ_COFF } /* already read them, or don't need to */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF symtbl = (struct nlist *)xmalloc (nsyms * sizeof (struct nlist)); #else fseek(f, sizeof(*execp) + execp->f_opthdr, 0); section_headers = (struct scnhdr *) xmalloc(execp->f_nscns * sizeof(*section_headers)); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT fseek(f, N_STROFF(*execp), 0); if (fread((char *)&strsize, sizeof strsize, 1, f) != 1) { fprintf(stderr, "%s: can not read string table size\n", #else fseek (f, N_STROFF(*execp), 0); if (fread ((char *)&strsize, sizeof strsize, 1, f) != 1) { fprintf (stderr, "%s: can not read string table size\n", #endif /* OBJ_BOUT */ program_name); exit (1); } strtbl = xmalloc (strsize); #ifndef OBJ_BOUT fseek(f, N_STROFF (*execp), 0); if (fread(strtbl, 1, strsize, f) != strsize) { fprintf(stderr, "%s: error reading string table\n", #else fseek (f, N_STROFF (*execp), 0); if (fread (strtbl, 1, strsize, f) != strsize) { fprintf (stderr, "%s: error reading string table\n", #endif /* OBJ_BOUT */ program_name); exit (1); } #else if (fread(section_headers, execp->f_nscns * sizeof(*section_headers), 1, f) != 1) { perror("error reading section headers"); abort(); } /* on error */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT fseek(f, N_SYMOFF (*execp), 0); if (fread((char *)symtbl, sizeof (struct nlist), nsyms, f) != nsyms) { fprintf(stderr, "%s: error reading symbol table\n", #else fseek (f, N_SYMOFF (*execp), 0); if (fread ((char *)symtbl, sizeof (struct nlist), nsyms, f) != nsyms) { fprintf (stderr, "%s: error reading symbol table\n", #endif /* OBJ_BOUT */ program_name); exit (1); } #else return; } /* read_section_headers() */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF for (i = 0, sp = symtbl; i < nsyms; i++, sp++) { if (sp->n_un.n_strx == 0) sp->n_un.n_name = ""; else if (sp->n_un.n_strx < 0 || sp->n_un.n_strx > strsize) sp->n_un.n_name = ""; else sp->n_un.n_name = strtbl + sp->n_un.n_strx; } #ifndef OBJ_BOUT } /* read_symbols() */ #else } #endif /* OBJ_BOUT */ #else static SYMENT *symbols = NULL; static int longest_symbol_name = SYMNMLEN; #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT static void free_symbols () #else free_symbols () #endif /* OBJ_BOUT */ #else static void read_symbols(execp, f) fileheader *execp; FILE *f; #endif /* OBJ_COFF */ { #ifdef OBJ_COFF long here; int bufsiz = execp->f_nsyms * sizeof(struct syment); SYMENT *s; if (symbols || bufsiz == 0) { return; } /* already read, or don't need to */ symbols = (SYMENT *) xmalloc(bufsiz); /* read symbols */ fseek(f, execp->f_symptr, 0); if (fread(symbols, bufsiz, 1, f) != 1) { fprintf(stderr, "error reading symbol table.\n"); abort(); } /* on error */ here = ftell(f); fseek(f, 0, 2); /* find end of file */ if (here != ftell(f)) { /* find string table size */ fseek(f, here, 0); if (fread(&strsize, sizeof(strsize), 1, f) != 1) { perror("error reading string table size"); abort(); } /* on error */ /* read string table if there is one */ if (strsize > 0) { strtbl = xmalloc(strsize); fseek(f, -sizeof(strsize), 1); /* backup over size count */ if (fread(strtbl, strsize, 1, f) != 1) { perror("error reading string table"); abort(); } /* on error */ /* then connect the dots. */ for (s = symbols; s < symbols + execp->f_nsyms; ++s) { if (!s->n_zeroes) { int l; s->n_offset = (long) strtbl + s->n_offset; l = strlen((char *) s->n_offset); if (l > longest_symbol_name) { longest_symbol_name = l; } /* keep max */ } /* "long" name */ s += s->n_numaux; /* skip aux entries */ } /* walk the symbol table */ } else { fprintf(stderr, "Well, now that's weird. I have a string table whose size is zero?\n"); } /* if there is a string table */ } /* if there is a string table */ return; } /* read_symbols() */ #ifdef comment static void free_symbols() { #endif /* OBJ_COFF */ if (symtbl) free (symtbl); symtbl = NULL; if (strtbl) free (strtbl); strtbl = NULL; #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ } /* free_symbols() */ #ifndef OBJ_COFF #else } #endif /* OBJ_BOUT */ #else #endif /* comment */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT static void usage () #else usage () #endif /* OBJ_BOUT */ { #ifndef OBJ_BOUT #else static void usage() { #endif /* OBJ_COFF */ (void) fprintf(stderr, "Usage: %s\n", program_name); (void) fprintf(stderr, "\t[-ahnrt] [+all] [+header] [+nstuff]\n"); (void) fprintf(stderr, "\t[+reloc] [+symbols] [+text] [+data]\n"); (void) fprintf(stderr, "\t[+omit-symbol-numbers] [+omit-reloc-numbers]\n"); (void) fprintf(stderr, "\tfile...\n"); #ifndef OBJ_COFF #else fprintf (stderr, "\ Usage: %s [-hnrt] [+header] [+nstuff] [+reloc] [+symbols] file...\n", program_name); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ exit (1); #ifndef OBJ_COFF } #else } /* usage() */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ static int aflag = 0; static int hflag = 0; #ifdef OBJ_COFF static int lflag = 0; #endif /* OBJ_COFF */ static int nflag = 0; static int rflag = 0; #ifdef OBJ_COFF static int sflag = 0; #endif /* OBJ_COFF */ static int tflag = 0; static int Dflag = 0; static int Tflag = 0; static int omit_reloc_numbers_flag = 0; static int omit_sym_numbers_flag = 0; #ifndef OBJ_COFF #else int hflag; int nflag; int rflag; int tflag; #endif /* OBJ_BOUT */ #else static int section_headers_flag = 0; static int section_contents_flag = 0; #endif /* OBJ_COFF */ /* Size of a page. Required by N_DATADDR in a.out.gnu.h [VAX]. */ int page_size; #ifndef OBJ_COFF #ifndef OBJ_BOUT int main (argc, argv) #else int main(argc, argv) #endif /* OBJ_COFF */ int argc; #ifndef OBJ_COFF #else main (argc, argv) #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ char **argv; { int c; #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ /* extern char *optarg; */ #ifndef OBJ_COFF #else extern char *optarg; #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ extern int optind; int seenflag = 0; int ind = 0; #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ static struct option long_options[] = { #ifdef OBJ_COFF {"line-numbers", 0, &lflag, 1}, {"section-contents", 0, §ion_contents_flag, 1}, {"section-headers", 0, §ion_headers_flag, 1}, #endif /* OBJ_COFF */ {"symbols", 0, &tflag, 1}, {"reloc", 0, &rflag, 1}, {"nstuff", 0, &nflag, 1}, {"header", 0, &hflag, 1}, {"data", 0, &Dflag, 1}, {"text", 0, &Tflag, 1}, {"omit-relocation-numbers", 0, &omit_reloc_numbers_flag, 1}, {"omit-symbol-numbers", 0, &omit_sym_numbers_flag, 1}, {"all", 0, &aflag, 1}, {NULL, 0, NULL, 0}, }; #ifndef OBJ_COFF #else static struct option long_options[] = { {"symbols", 0, &tflag, 1}, {"reloc", 0, &rflag, 1}, {"nstuff", 0, &nflag, 1}, {"header", 0, &hflag, 1}, {NULL, 0, NULL, 0} }; #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF page_size = getpagesize (); #endif /* OBJ_COFF */ program_name = argv[0]; #ifndef OBJ_COFF #ifndef OBJ_BOUT while ((c = getopt_long (argc, argv, "ahnrt", long_options, &ind)) != EOF) { #else while ((c = getopt_long (argc, argv, "hnrt", long_options, &ind)) != EOF) { #endif /* OBJ_BOUT */ #else while ((c = getopt_long (argc, argv, "ahlonrt", long_options, &ind)) != EOF) { #endif /* OBJ_COFF */ seenflag = 1; #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ switch (c) { case 0 : break; /* we've been given a long option */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ case 'a': aflag = 1; break; case 'h': hflag = 1; break; #ifdef OBJ_COFF case 'o': hflag = 1; break; case 'l': lflag = 1; break; #endif /* OBJ_COFF */ case 'n': nflag = 1; break; case 'r': rflag = 1; break; #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ case 't': tflag = 1; break; #ifndef OBJ_COFF #ifdef OBJ_BOUT case 'r': rflag = 1; break; case 'n': nflag = 1; break; case 'h': hflag = 1; break; #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ default: usage (); #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ } /* switch on option */ } /* while there are options */ #ifndef OBJ_COFF #else } } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ if (seenflag == 0 || optind == argc) usage (); #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (aflag) { hflag = 1; #ifdef OBJ_COFF lflag = 1; #endif /* OBJ_COFF */ nflag = 1; rflag = 1; tflag = 1; Dflag = 1; Tflag = 1; #ifdef OBJ_COFF section_headers_flag = 1; section_contents_flag = 1; #endif /* OBJ_COFF */ } /* if all */ #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ while (optind < argc) #ifndef OBJ_COFF doit (argv[optind++]); #ifndef OBJ_BOUT #else doit(argv[optind++]); #endif /* OBJ_COFF */ return(0); } /* main() */ #ifndef OBJ_COFF #else } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT static void doit (name) #else doit (name) #endif /* OBJ_BOUT */ #else static void doit(name) #endif /* OBJ_COFF */ char *name; { FILE *f; #ifndef OBJ_COFF struct exec exec; #ifndef OBJ_BOUT #else fileheader exec; if (section_headers) { free(section_headers); section_headers = NULL; } /* free section headers */ if (symbols) { free(symbols); symbols = NULL; } /* free symbols */ #endif /* OBJ_COFF */ printf("%s:\n", name); #ifndef OBJ_COFF #else printf ("%s:\n", name); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ f = fopen (name, "r"); if (f == NULL) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ fprintf(stderr, "%s: can not open ", program_name); #ifndef OBJ_COFF #else fprintf (stderr, "%s: can not open ", program_name); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ perror (name); return; } #ifdef HEADER_SEEK HEADER_SEEK (f); #endif #ifndef OBJ_COFF #ifndef OBJ_BOUT if (fread((char *)&exec, sizeof exec, 1, f) != 1) { #else if (fread((char *)&exec, sizeof(exec), 1, f) != 1) { #endif /* OBJ_COFF */ fprintf(stderr, "%s: can not read header for %s\n", #ifndef OBJ_COFF #else if (fread ((char *)&exec, sizeof exec, 1, f) != 1) { fprintf (stderr, "%s: can not read header for %s\n", #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ program_name, name); return; } #ifdef OBJ_COFF #ifdef I960ROMAGIC #define N_BADMAG I960BADMAG #endif /* I960ROMAGIC */ #endif /* OBJ_COFF */ if (N_BADMAG (exec)) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ fprintf(stderr, "%s: %s is not a%s object file\n", program_name, name, #ifdef B_OUT " b.out" #else "n a.out" #endif /* B_OUT */ ); #ifndef OBJ_COFF #else fprintf (stderr, "%s: %s is not an object file\n", program_name, name); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ return; } #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (hflag) dump_header(&exec, f); #ifdef OBJ_COFF if (lflag) dump_lnno(&exec, f); #endif /* OBJ_COFF */ if (nflag) dump_nstuff(&exec); #ifdef OBJ_COFF if (section_headers_flag) dump_section_headers(&exec, f); if (section_contents_flag) dump_section_contents(&exec, f); if (sflag) dump_section_contents(&exec, f); #endif /* OBJ_COFF */ if (Tflag) dump_text(&exec, f); if (Dflag) dump_data(&exec, f); if (tflag) dump_sym(&exec, f); if (rflag) dump_reloc(&exec, f); #ifndef OBJ_COFF #else if (hflag) dump_header (&exec); #endif /* OBJ_COFF */ #ifndef OBJ_COFF if (nflag) dump_nstuff (&exec); #endif /* OBJ_BOUT */ #else printf("\n"); fclose(f); return; } /* doit() */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT free_symbols(); #else if (tflag) dump_sym (&exec, f); #endif /* OBJ_BOUT */ #else static void dump_lnno(execp, f) fileheader *execp; FILE *f; { int i = execp->f_nscns; struct scnhdr *section; char *buffer; int bufsiz = 0; if (i) { printf("Line numbers:\n"); read_section_headers(execp, f); read_symbols(execp, f); for (section = section_headers; i; ++section, --i) { int size = section->s_nlnno * LINESZ; LINENO *r; if (size > bufsiz) { if (bufsiz) { buffer = xrealloc(buffer, bufsiz = size); } else { buffer = xmalloc(bufsiz = size); } /* if we had allocated anything before */ } /* if bigger than our old buffer */ printf("%8.8s:", section->s_name); fseek(f, section->s_lnnoptr, 0); if (size) { int j; if (fread(buffer, size, 1, f) != 1) { printf(" (error reading lnno)\n"); continue; } /* on read error */ printf("\n"); for (r = (LINENO *) buffer, j = 0; j < section->s_nlnno; ++j, ++r) { printf("lnno = %d,", r->l_lnno); if (r->l_lnno) { printf(" paddr = 0x%lx", (unsigned long) r->l_addr.l_paddr); } else { printf(" symndx = %ld, \"%s\"", r->l_addr.l_symndx, sym_pname(symbols + r->l_addr.l_symndx)); } /* if not symbol'd */ if (r->padding[0] || r->padding[1]) { printf(" (padding = %2x %2x)", (unsigned) r->padding[0], (unsigned) r->padding[1]); } /* if padding not zero'd */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #else printf("\n"); } /* for each lnno record */ } else { printf(" (section has no line numbers.)\n"); } /* if there really is something in the section */ } /* for each section */ } else { printf("No Sections.\n"); } /* if there are sections */ free(buffer); printf("\n"); #endif /* OBJ_COFF */ return; #ifndef OBJ_COFF } /* doit() */ #else if (rflag) dump_reloc (&exec, f); #endif /* OBJ_BOUT */ #else } /* dump_lnno() */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT static void dump_header(execp, f) #else free_symbols (); #else static void dump_reloc(execp, f) fileheader *execp; FILE *f; { int i = execp->f_nscns; struct scnhdr *section; char *buffer; int bufsiz = 0; if (i) { read_section_headers(execp, f); printf("Relocations:\n"); for (section = section_headers; i; ++section, --i) { int size = section->s_nreloc * RELSZ; RELOC *r; if (size > bufsiz) { if (bufsiz) { buffer = xrealloc(buffer, bufsiz = size); } else { buffer = xmalloc(bufsiz = size); } /* if we had allocated anything before */ } /* if bigger than our old buffer */ printf("%8.8s:", section->s_name); fseek(f, section->s_relptr, 0); if (size) { int j; if (fread(buffer, size, 1, f) != 1) { printf(" (error reading reloc)\n"); continue; } /* on read error */ printf("\n"); for (r = (RELOC *) buffer, j = 0; j < section->s_nreloc; ++j, ++r) { printf("vaddr = 0x%lx, symndx = %ld, r_type = ", (unsigned long) r->r_vaddr, r->r_symndx); switch (r->r_type) { case R_RELLONG: printf(" RELLONG"); break; case R_IPRSHORT: printf("IPRSHORT"); break; case R_IPRMED: printf(" IPRMED"); break; case R_IPRLONG: printf(" IPRLONG"); break; case R_OPTCALL: printf(" OPTCALL"); break; case R_OPTCALLX: printf("OPTCALLX"); break; case R_GETSEG: printf(" GETSEG"); break; case R_GETPA: printf(" GETPA"); break; case R_TAGWORD: printf(" TAGWORD"); break; default: printf("unrecognized"); break; } /* switch on reloc type */ printf("."); if (r->pad[0] || r->pad[1]) { printf(" (padding = %2x %2x)", (unsigned) r->pad[0], (unsigned) r->pad[1]); } /* if padding isn't zero */ printf("\n"); } /* for each reloc record */ } else { printf(" (section has no relocations.)\n"); } /* if there really is something in the section */ } /* for each section */ } else { printf("No Sections.\n"); } /* if there are sections */ /* free(buffer); */ printf("\n"); return; } /* dump_reloc() */ static void dump_section_contents(execp, f) fileheader *execp; FILE *f; { int i = execp->f_nscns; struct scnhdr *section; char *buffer; int bufsiz = 0; if (i) { read_section_headers(execp, f); printf("Section Contents:\n"); for (section = section_headers; i; ++section, --i) { if (section->s_size > bufsiz) { if (bufsiz) { buffer = xrealloc(buffer, bufsiz = section->s_size); } else { buffer = xmalloc(bufsiz = section->s_size); } /* if we had allocated anything before */ } /* if bigger than our old buffer */ printf("%8.8s:", section->s_name); if (section->s_flags & STYP_BSS) { printf(" bss sections have no contents.\n"); } else { fseek(f, section->s_scnptr, 0); if (section->s_size) { if (fread(buffer, section->s_size, 1, f) != 1) { printf(" (error reading section contents)\n"); } /* on read error */ printf("\n"); hex_dump(buffer, section->s_size); printf("\n"); } else { printf(" (section has a size of zero.)\n"); } /* if there really is a section */ } /* if bss else dump */ } /* for each section */ } else { printf("No Sections.\n"); } /* if there are sections */ free(buffer); printf("\n"); return; } /* dump_section_contents() */ static void dump_section_headers(execp, f) fileheader *execp; FILE *f; { int i = execp->f_nscns; struct scnhdr *section; if (i > 0) { read_section_headers(execp, f); printf("Section Headers:\n"); for (section = section_headers; i; ++section, --i) { long flags = section->s_flags; printf("\"%8.8s\"", section->s_name); printf(" physical address: 0x%x vma: 0x%x size: 0x%x (%ld)", (unsigned) section->s_paddr, (unsigned) section->s_vaddr, (unsigned) section->s_size, section->s_size); printf(" relocs: %d linenos: %d alignment: 0x%lx (%ld)", section->s_nreloc, section->s_nlnno, section->s_align, (long) section->s_align); printf(" flags: 0x%x = ", (unsigned) section->s_flags); if (flags & STYP_REG) { printf(" REG"); flags &= ~STYP_REG; } /* STYP_REG */ if (flags & STYP_DSECT) { printf(" DSECT"); flags &= ~STYP_DSECT; } /* STYP_DSECT */ if (flags & STYP_NOLOAD) { printf(" NOLOAD"); flags &= ~STYP_NOLOAD; } /* STYP_NOLOAD */ if (flags & STYP_GROUP) { printf(" GROUP"); flags &= ~STYP_GROUP; } /* STYP_GROUP */ if (flags & STYP_PAD) { printf(" PAD"); flags &= ~STYP_PAD; } /* STYP_PAD */ if (flags & STYP_COPY) { printf(" COPY"); flags &= ~STYP_COPY; } /* STYP_COPY */ if (flags & STYP_TEXT) { printf(" TEXT"); flags &= ~STYP_TEXT; } /* STYP_TEXT */ if (flags & S_SHRSEG) { printf(" SHRSEG"); flags &= ~S_SHRSEG; } /* S_SHRSEG */ if (flags & STYP_DATA) { printf(" DATA"); flags &= ~STYP_DATA; } /* STYP_DATA */ if (flags & STYP_BSS) { printf(" BSS"); flags &= ~STYP_BSS; } /* STYP_BSS */ if (flags & S_NEWFCN) { printf(" NEWFCN"); flags &= ~S_NEWFCN; } /* S_NEWFCN */ if (flags & STYP_INFO) { printf(" INFO"); flags &= ~STYP_INFO; } /* STYP_INFO */ if (flags & STYP_OVER) { printf(" OVER"); flags &= ~STYP_OVER; } /* STYP_OVER */ if (flags & STYP_LIB) { printf(" LIB"); flags &= ~STYP_LIB; } /* STYP_LIB */ if (flags & STYP_MERGE) { printf(" MERGE"); flags &= ~STYP_MERGE; } /* STYP_MERGE */ if (flags & STYP_REVERSE_PAD) { printf(" REVERSE_PAD"); flags &= ~STYP_REVERSE_PAD; } /* STYP_REVERSE_PAD */ if (flags) { printf(" +unknown"); } /* foo */ printf("\n"); } /* for each section header */ } else { printf("No section headers.\n"); } /* if there are any sections */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF } #else printf("\n"); return; } /* dump_section_headers() */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF dump_header (execp) #endif /* OBJ_BOUT */ struct exec *execp; #ifndef OBJ_BOUT #else static void dump_header(execp, f) fileheader *execp; #endif /* OBJ_COFF */ FILE *f; #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ { #ifdef OBJ_COFF #ifdef COFF printf("magic: 0x%x (%o) ", (unsigned) execp->f_magic, (unsigned) execp->f_magic); printf("number of sections: %d number of syms: %ld ", execp->f_nscns, execp->f_nsyms); printf("time stamp: %s", ctime(&(execp->f_timdat))); printf("flags:"); if (execp->f_flags & F_RELFLG) { printf(" RELFLG"); } /* relflg */ if (execp->f_flags & F_EXEC) { printf(" EXEC"); } /* exec */ if (execp->f_flags & F_LNNO) { printf(" LNNO"); } /* lnno */ if (execp->f_flags & F_LSYMS) { printf(" LSYMS"); } /* lsyms */ if (execp->f_flags & F_AR32WR) { printf(" AR32WR"); } /* ar32wr */ assert(F_I960KB == F_I960SB); assert(F_I960KA == F_I960SA); switch (execp->f_flags & F_I960TYPE) { case F_I960CORE: printf(" I960CORE"); break; case F_I960KB: printf(" I960KB (== I960SB)"); break; case F_I960MC: printf(" I960MC"); break; case F_I960XA: printf(" I960XA"); break; case F_I960CA: printf(" I960CA"); break; case F_I960KA: printf(" I960KA (== I960SA)"); break; default: printf(" I960Unknown"); break; } /* switch on i960 type */ if (execp->f_flags & ~(F_RELFLG | F_EXEC | F_LNNO | F_LSYMS | F_AR32WR | F_I960TYPE)) { printf(" +unrecognized"); } /* unrecognized */ printf("\n\n"); if (execp->f_opthdr) { if (execp->f_opthdr == sizeof(AOUTHDR)) { AOUTHDR hdr; fseek(f, sizeof(*execp), 0); if (fread(&hdr, sizeof(AOUTHDR), 1, f) == 1) { printf("aouthdr:\n"); printf("magic: 0x%x (%o)", (unsigned) hdr.magic, (unsigned) hdr.magic); printf(" vstamp: 0x%ld\n", (long) hdr.vstamp); printf("sizes: text 0x%lx (%ld), data 0x%lx (%ld), bss 0x%lx (%ld)\n", hdr.tsize, (long) hdr.tsize, hdr.dsize, (long) hdr.dsize, hdr.bsize, (long) hdr.bsize); printf("entry point: 0x%lx, starts: text 0x%lx (%ld), data 0x%lx (%ld)\n", hdr.entry, hdr.text_start, (long) hdr.text_start, hdr.data_start, (long) hdr.data_start); printf("tag entries: %ld\n", (long) hdr.tagentries); } else { fprintf(stderr, "%s: error reading optional header", program_name); perror(NULL); } /* on error */ } else { printf("opthder != sizeof aouthdr?"); } /* size mismatch */ } else { printf("No optional header."); } /* print optional header */ #else /* COFF */ #endif /* OBJ_COFF */ int x; #if defined (__GNU_EXEC_MACROS__) && !defined (__STRUCT_EXEC_OVERRIDE__) #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("magic: 0x%x (%o)", N_MAGIC(*execp), N_MAGIC(*execp)); printf("machine type: %d", N_MACHTYPE(*execp)); printf("flags: 0x%x", N_FLAGS(*execp)); #ifndef OBJ_COFF #else printf ("magic: 0x%x (%o)", N_MAGIC(*execp), N_MAGIC(*execp)); printf ("machine type: %d", N_MACHTYPE(*execp)); printf ("flags: 0x%x", N_FLAGS(*execp)); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #else /* non-gnu struct exec. */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("magic: 0x%x (%o) ", (unsigned) execp->a_magic, (unsigned) execp->a_magic); #ifndef OBJ_COFF #else printf ("magic: 0x%x (%o) ", execp->a_magic, execp->a_magic); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #endif /* non-gnu struct exec. */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("text 0x%x ", (unsigned) execp->a_text); printf("data 0x%x ", (unsigned) execp->a_data); printf("bss 0x%x\n", (unsigned) execp->a_bss); printf("nsyms %ld", (long) (execp->a_syms / sizeof(struct nlist))); x = execp->a_syms % sizeof(struct nlist); #ifndef OBJ_COFF #else printf ("text 0x%x ", execp->a_text); printf ("data 0x%x ", execp->a_data); printf ("bss 0x%x\n", execp->a_bss); printf ("nsyms %d", execp->a_syms / sizeof (struct nlist)); x = execp->a_syms % sizeof (struct nlist); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ if (x) #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf(" (+ %d bytes)", x); printf(" entry 0x%lx ", execp->a_entry); #ifdef B_OUT printf(" talign 0x%x", (unsigned) execp->a_talign); printf(" dalign 0x%x", (unsigned) execp->a_dalign); printf(" balign 0x%x", (unsigned) execp->a_balign); printf(" unused 0x%x", (unsigned) execp->unused); #endif /* B_OUT */ printf(" trsize 0x%lx", execp->a_trsize); printf(" drsize 0x%lx", execp->a_drsize); if (N_TXTOFF(*execp) != 0 && N_TXTOFF(*execp) != sizeof(*execp)) { char *buffer; char *i; int size = N_TXTOFF(*execp) - sizeof(*execp); buffer = xmalloc(size); fseek(f, sizeof(*execp), 0); if (fread(buffer, size, 1, f) != 1) { fprintf(stderr, "%s: error reading between header and text", program_name); perror(NULL); } /* on error */ for (i = buffer; i < (buffer + size); ++i) { if (*i != '\0') { printf(" (garbage follows header)"); break; } /* non null */ } /* walk the buffer looking for garbage */ } /* check for garbage following header */ #ifdef OBJ_COFF #endif /* COFF */ #endif /* OBJ_COFF */ printf("\n"); return; } /* dump_header() */ #ifdef OBJ_COFF #ifdef comment #endif /* OBJ_COFF */ static void dump_nstuff(execp) #ifndef OBJ_COFF struct exec *execp; #else fileheader *execp; #endif /* OBJ_COFF */ { printf("N_BADMAG %d\n", N_BADMAG(*execp)); printf("N_TXTOFF 0x%x\n", N_TXTOFF(*execp)); printf("N_SYMOFF 0x%lx\n", N_SYMOFF(*execp)); printf("N_STROFF 0x%lx\n", N_STROFF(*execp)); printf("N_TXTADDR 0x%x\n", (unsigned) N_TXTADDR(*execp)); printf("N_DATADDR 0x%lx\n", N_DATADDR(*execp)); return; } /* dump_nstuff() */ #ifndef OBJ_COFF #else printf (" (+ %d bytes)", x); printf (" entry 0x%x ", execp->a_entry); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ static void dump_text(execp, f) #ifndef OBJ_COFF struct exec *execp; #else fileheader *execp; #endif /* OBJ_COFF */ FILE *f; { void *buffer; if (execp->a_text) { buffer = xmalloc(execp->a_text); fseek(f, N_TXTOFF(*execp), 0); if (fread(buffer, execp->a_text, 1, f) != 1) { fprintf(stderr, "%s: error reading text section.\n", program_name); return; } /* on error */ #ifndef OBJ_COFF #else printf (" talign 0x%x ", execp->a_talign); printf (" dalign 0x%x ", execp->a_dalign); printf (" balign 0x%x ", execp->a_balign); printf (" unused 0x%x ", execp->unused); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ hex_dump(buffer, execp->a_text); free(buffer); } else { printf("No text section.\n"); } /* if there is text */ return; } /* dump_text() */ #ifndef OBJ_COFF #else printf ("trsize 0x%x ", execp->a_trsize); printf ("drsize 0x%x\n", execp->a_drsize); } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ static void dump_data(execp, f) #ifndef OBJ_COFF #else dump_nstuff (execp) #endif /* OBJ_BOUT */ struct exec *execp; #ifndef OBJ_BOUT #else fileheader *execp; #endif /* OBJ_COFF */ FILE *f; { void *buffer; if (execp->a_data) { buffer = xmalloc(execp->a_data); fseek(f, N_TXTOFF(*execp), 0); if (fread(buffer, execp->a_data, 1, f) != 1) { fprintf(stderr, "%s: error reading data section.\n", program_name); return; } /* on error */ hex_dump(buffer, execp->a_data); free(buffer); } else { printf("No data section.\n"); } /* if there is data */ return; } /* dump_data() */ #ifdef OBJ_COFF #endif /* comment */ #endif /* OBJ_COFF */ static void hex_dump(buffer, size) void *buffer; int size; #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ FILE *f; #ifndef OBJ_COFF if ((f = popen("od -x +0x0", "w")) != NULL) { #else fflush(stdout); if ((f = popen("hexl", "w")) != NULL) { #endif /* OBJ_COFF */ if (fwrite(buffer, size, 1, f) != 1) { (void) fprintf(stderr, "%s: error writing to od(1) pipe:", program_name); perror(NULL); } /* on error */ } else { (void) fprintf(stderr, "%s: error opening pipe to od(1):", program_name); perror(NULL); } /* on successful popen */ (void) pclose(f); #ifdef OBJ_COFF fflush(stdout); #endif /* OBJ_COFF */ return; } /* hex_dump() */ #ifndef OBJ_COFF #else printf ("N_BADMAG %d\n", N_BADMAG (*execp)); printf ("N_TXTOFF 0x%x\n", N_TXTOFF (*execp)); printf ("N_SYMOFF 0x%x\n", N_SYMOFF (*execp)); printf ("N_STROFF 0x%x\n", N_STROFF (*execp)); printf ("N_TXTADDR 0x%x\n", N_TXTADDR (*execp)); printf ("N_DATADDR 0x%x\n", N_DATADDR (*execp)); } #endif /* OBJ_BOUT */ #else char *sym_class_pname(class) char class; { switch (class) { case C_EFCN: return("EFCN"); case C_NULL: return("NULL"); case C_AUTO: return("AUTO"); case C_EXT: return("EXT"); case C_STAT: return("STAT"); case C_REG: return("REG"); case C_EXTDEF: return("EXTDEF"); case C_LABEL: return("LABEL"); case C_ULABEL: return("ULABEL"); case C_MOS: return("MOS"); case C_ARG: return("ARG"); case C_STRTAG: return("STRTAG"); case C_MOU: return("MOU"); case C_UNTAG: return("UNTAG"); case C_TPDEF: return("TPDEF"); case C_USTATIC: return("USTATIC"); case C_ENTAG: return("ENTAG"); case C_MOE: return("MOE"); case C_REGPARM: return("REGPARM"); case C_FIELD: return("FIELD"); case C_BLOCK: return("BLOCK"); case C_FCN: return("FCN"); case C_EOS: return("EOS"); case C_FILE: return("FILE"); case C_LINE: return("LINE"); case C_ALIAS: return("ALIAS"); case C_HIDDEN: return("HIDDEN"); case C_SCALL: return("SCALL"); case C_LEAFEXT: return("LEAFEXT"); case C_OPTVAR: return("OPTVAR"); case C_DEFINE: return("DEFINE"); case C_PRAGMA: return("PRAGMA"); case C_SEGMENT: return("SEGMENT"); case C_LEAFSTAT:return("LEAFSTAT"); case C_AUTOARG: return("AUTOARG"); default: return("(???)"); } /* switch on class */ } /* sym_class_pname() */ char *sym_type_pname(type) unsigned long type; { switch (type) { case T_NULL: return("NULL"); case T_VOID: return("VOID"); case T_CHAR: return("CHAR"); case T_SHORT: return("SHORT"); case T_INT: return("INT"); case T_LONG: return("LONG"); case T_FLOAT: return("FLOAT"); case T_DOUBLE: return("DOUBLE"); case T_STRUCT: return("STRUCT"); case T_UNION: return("UNION"); case T_ENUM: return("ENUM"); case T_MOE: return("MOE"); case T_UCHAR: return("UCHAR"); case T_USHORT: return("USHORT"); case T_UINT: return("UINT"); case T_ULONG: return("ULONG"); case T_LNGDBL: return("LNGDBL"); default: return("(???)"); } /* switch on type */ } /* sym_type_pname() */ char *sym_section_pname(scnum, execp) short scnum; fileheader *execp; { switch (scnum) { case N_UNDEF: return("UNDEF"); case N_ABS: return("ABS"); case N_DEBUG: return("DEBUG"); case N_TV: return("NTV"); case P_TV: return("PTV"); default: assert(0 <= (scnum-1)); assert((scnum-1) < execp->f_nscns); return(section_headers[scnum-1].s_name); } /* switch on scnum */ } /* sym_section_pname() */ static char *sym_pname(s) SYMENT *s; { static char buffer[SYMNMLEN + 1]; if (s->n_zeroes) { bzero(buffer, SYMNMLEN + 1); bcopy(s->n_name, buffer, SYMNMLEN); return(buffer); } else { return((char *) s->n_offset); } /* if "short" name */ } /* sym_pname() */ /* * Notes: .file must be first, .text, .data, .bss must be last. */ static void dump_aux_fcn(aux) AUXENT *aux; { /* function symbol */ printf(" tagndx %ld,", aux->x_sym.x_tagndx); printf(" size %ld,", aux->x_sym.x_misc.x_fsize); printf(" lnnoptr 0x%lx,", (unsigned long) aux->x_sym.x_fcnary.x_fcn.x_lnnoptr); printf(" endndx %ld", aux->x_sym.x_fcnary.x_fcn.x_endndx); printf(" tvndx 0x%x,", (unsigned) aux->x_sym.x_tvndx); return; } /* dump_aux_fcn() */ static void dump_aux_tagmember(aux) AUXENT *aux; { printf(" tagndx %ld,", aux->x_sym.x_tagndx); printf(" size %d,", aux->x_sym.x_misc.x_lnsz.x_size); return; } /* dump_aux_tagmember() */ static void dump_aux_array(aux) AUXENT *aux; { int i; #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #else printf(" size %d, ", aux->x_sym.x_misc.x_lnsz.x_size); for (i = 0; i < 4; ++i) { printf("[%d]", aux->x_sym.x_fcnary.x_ary.x_dimen[i]); } /* four dimensions */ return; } /* dump_aux_array() */ #endif /* OBJ_COFF */ static void dump_sym(execp, f) #ifndef OBJ_COFF #else dump_sym (execp, f) #endif /* OBJ_BOUT */ struct exec *execp; #else fileheader *execp; #endif /* OBJ_COFF */ FILE *f; { int i; #ifndef OBJ_COFF struct nlist *sp; #else SYMENT *sp; #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT read_symbols(execp, f); #else read_symbols (execp, f); #endif /* OBJ_BOUT */ if (nsyms == 0) { #ifndef OBJ_BOUT #else read_section_headers(execp, f); if (execp->f_nsyms == 0) { #endif /* OBJ_COFF */ printf("no symbols\n"); #ifndef OBJ_COFF #else printf ("no symbols\n"); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ return; #ifndef OBJ_COFF } #else } /* if there are any */ read_symbols(execp, f); printf("Symbols:\n"); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (!omit_sym_numbers_flag) { #ifndef OBJ_COFF printf("%3s: ", "#"); #else printf("%3s:", "#"); #endif /* OBJ_COFF */ } /* printing symbol numbers */ #ifndef OBJ_COFF printf("%4s %5s %4s %8s\n", "type", "other", "desc", "val"); #else printf(" %*.*s %8.8s %3.3s %8.8s %7.7s %3.3s %s\n", SYMNMLEN, SYMNMLEN, "name", "value", "num", "sec-name", "class", "aux", "type"); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #else printf ("%3s: %4s %5s %4s %8s\n", "#", "type", "other", "desc", "val"); #endif /* OBJ_BOUT */ for (i = 0, sp = symtbl; i < nsyms; i++, sp++) { #ifndef OBJ_BOUT #else for (i = 0, sp = symbols; sp < symbols + execp->f_nsyms; ++sp, ++i) { #endif /* OBJ_COFF */ if (!omit_sym_numbers_flag) { #ifndef OBJ_COFF printf("%3d: ", i); #else printf("%3d:", i); #endif /* OBJ_COFF */ } /* printing symbol numbers */ #ifndef OBJ_COFF printf("%4x %5x %4x %8lx %s", (unsigned) (sp->n_type & 0xff), (unsigned) (sp->n_other & 0xff), (unsigned) (sp->n_desc & 0xffff), #else printf ("%3d: %4x %5x %4x %8x %s", i, sp->n_type & 0xff, sp->n_other & 0xff, sp->n_desc & 0xffff, #endif /* OBJ_BOUT */ sp->n_value, sp->n_un.n_name); #ifndef OBJ_BOUT #else printf(" %*.*s", SYMNMLEN, SYMNMLEN, (sp->n_zeroes) ? sp->n_name : ""); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #else #endif /* OBJ_BOUT */ if (sp->n_type & N_EXT) printf(" N_EXT"); if (sp->n_type & N_STAB) printf(" N_STAB"); #ifndef OBJ_BOUT #else printf(" %8lx", (unsigned long) sp->n_value); printf(" %3d", sp->n_scnum); printf(" %8.8s", sym_section_pname(sp->n_scnum, execp)); printf(" %7.7s", sym_class_pname(sp->n_sclass)); printf(" %1d", sp->n_numaux); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #else #endif /* OBJ_BOUT */ if ((sp->n_type & N_TYPE) == N_UNDF) { printf(" N_UNDF"); } else { if (sp->n_type & N_ABS) printf(" N_ABS"); if (sp->n_type & N_TEXT) printf(" N_TEXT"); if (sp->n_type & N_DATA) printf(" N_DATA"); if (sp->n_type & N_BSS) printf(" N_BSS"); if (sp->n_type & N_FN) printf(" N_FN"); } /* if not undefined */ #ifndef OBJ_BOUT #else printf(" %s", sym_type_pname(BTYPE(sp->n_type))); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifdef B_OUT #else #endif /* OBJ_BOUT */ if (sp->n_other) { printf(" ["); #ifndef OBJ_BOUT #else /* derived type */ printf("%s", (ISPTR(sp->n_type) ? "(PTR)" : (ISFCN(sp->n_type) ? "(FCN)" : (ISARY(sp->n_type) ? "(ARY)" : "")))); if (sp->n_type & ~(N_BTMASK | N_TMASK)) { printf("+"); } /* if type isn't all */ if (!sp->n_zeroes) { printf(" \"%s\"", sym_pname(sp)); } /* if "long" name */ /* FIXME do something with the flags field */ #ifdef comment if (sp->pad1[0] != 0 || sp->pad1[1] != 0) { printf(" (pad1 %2.2x%2.2x)", (unsigned) sp->pad1[0], (unsigned) sp->pad1[1]); } /* if padding not zeroed */ #endif /* comment */ if (sp->pad2[0] != 0 || sp->pad2[1] != 0) { printf(" (pad2 %2.2x%2.2x)", (unsigned) sp->pad2[0], (unsigned) sp->pad2[1]); } /* if padding not zeroed */ #define DTYPE(x) (((x) & N_TMASK) >> N_BTSHFT) if (sp->n_numaux > 0) { int auxcountshouldbe = 1; AUXENT *aux = (AUXENT *) (sp + 1); AUXENT *aux2 = (AUXENT *) (sp + 2); #endif /* OBJ_COFF */ #ifndef OBJ_COFF #else #else switch (sp->n_sclass) { case C_FILE: /* file symbol */ printf(" filename \"%s\"", aux->x_file.x_fname); break; case C_UNTAG: case C_ENTAG: case C_STRTAG: { if (DTYPE(sp->n_type) == DT_NON && (BTYPE(sp->n_type) == T_NULL || BTYPE(sp->n_type) == T_STRUCT || BTYPE(sp->n_type) == T_UNION || BTYPE(sp->n_type) == T_ENUM)) { printf(" size %d,", aux->x_sym.x_misc.x_lnsz.x_size); printf(" endndx %ld", aux->x_sym.x_fcnary.x_fcn.x_endndx); } else { printf(" (don't know why this tag has an auxent)"); abort(); } /* if I understand */ break; } /* tags */ case C_EOS: { if (BTYPE(sp->n_type) == DT_NON && BTYPE(sp->n_type) == T_NULL) { printf(" tagndx %ld,", aux->x_sym.x_tagndx); printf(" size %d,", aux->x_sym.x_misc.x_lnsz.x_size); } else { printf(" (don't know why this eos has an auxent)"); abort(); } /* if I understand */ break; } /* eos */ case C_FCN: case C_BLOCK: { if (BTYPE(sp->n_type) == DT_NON && BTYPE(sp->n_type) == T_NULL) { if (!strcmp(sp->n_name, ".bb") || !strcmp(sp->n_name, ".bf")) { printf(" lnno %d", aux->x_sym.x_misc.x_lnsz.x_lnno); printf(" endndx %ld", aux->x_sym.x_fcnary.x_fcn.x_endndx); break; } else if (!strcmp(sp->n_name, ".eb") || !strcmp(sp->n_name, ".ef")) { printf(" lnno %d", aux->x_sym.x_misc.x_lnsz.x_lnno); break; } /* beginning or ending */ } /* if I understand */ printf(" (don't know why this fcn or block has an auxent)"); abort(); break; } /* begin/end blocks */ case C_LEAFEXT: case C_LEAFSTAT: case C_SCALL: case C_EXT: { assert(BTYPE(sp->n_type) != T_MOE); if (ISFCN(sp->n_type) || BTYPE(sp->n_type) == T_NULL) { dump_aux_fcn(aux); if (sp->n_sclass == C_SCALL) { printf(" stindx %ld", aux2->x_sc.x_stindx); auxcountshouldbe = 2; } else if (sp->n_sclass == C_LEAFEXT || sp->n_sclass == C_LEAFSTAT) { printf(" balentry 0x%lx", aux2->x_bal.x_balntry); auxcountshouldbe = 2; } /* special functions */ } else if (ISARY(sp->n_type)) { dump_aux_array(aux); } else if (BTYPE(sp->n_type) == T_STRUCT) { printf(" tagndx %ld,", aux->x_sym.x_tagndx); printf(" size %d,", aux->x_sym.x_misc.x_lnsz.x_size); } else { assert(0); } /* on type */ break; } /* function */ case C_STAT: { switch (DTYPE(sp->n_type)) { case DT_NON: switch (BTYPE(sp->n_type)) { case T_NULL: /* section symbol */ printf(" length 0x%lx, relocs %d, lnnos %d", (unsigned long) aux->x_scn.x_scnlen, aux->x_scn.x_nreloc, aux->x_scn.x_nlinno); break; case T_STRUCT: case T_UNION: case T_ENUM: dump_aux_tagmember(aux); break; default: printf(" (confused)."); abort(); } /* switch on btype */ break; case DT_FCN: /* function */ if (BTYPE(sp->n_type) == T_MOE) { printf(" (confused)."); abort(); } else { dump_aux_fcn(aux); } /* if I understand */ break; case DT_ARY: assert(BTYPE(sp->n_type) != T_MOE); dump_aux_array(aux); /* intentional fall through */ case DT_PTR: assert(BTYPE(sp->n_type) == T_STRUCT || BTYPE(sp->n_type) == T_UNION || BTYPE(sp->n_type) == T_ENUM); dump_aux_tagmember(aux); break; default: printf(" (confused.)"); abort(); } /* switch on derived type */ break; } /* STAT */ case C_AUTO: case C_MOS: case C_MOU: case C_TPDEF: if (DTYPE(sp->n_type) == DT_ARY) { assert(BTYPE(sp->n_type) != T_MOE); dump_aux_array(aux); } else { dump_aux_tagmember(aux); } /* if an array */ break; #endif /* OBJ_COFF */ #ifndef OBJ_COFF #endif /* OBJ_BOUT */ if (sp->n_other == N_CALLNAME) { printf(" N_CALLNAME"); } else if (sp->n_other == N_BALNAME) { printf(" N_BALNAME"); } else if (1 <= sp->n_other && sp->n_other <= 32) { printf(" \"trap\""); } else { printf(" !!!invalid \"other\" field"); } /* what is it */ #ifndef OBJ_BOUT #else case C_FIELD: printf(" tagndx %ld,", aux->x_sym.x_tagndx); printf(" size %d,", aux->x_sym.x_misc.x_lnsz.x_size); break; default: printf(" (don't know why this symbol has aux entries.)"); abort(); break; } /* switch on class */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #else #endif /* OBJ_BOUT */ printf(" ]"); } /* is defined */ #ifndef OBJ_BOUT #endif /* B_OUT */ #else if (sp->n_numaux != auxcountshouldbe) { printf(" (expecting %d auxents here)", auxcountshouldbe); abort(); } /* on miscount */ } /* do aux entries */ i += sp->n_numaux; sp += sp->n_numaux; #endif /* OBJ_COFF */ printf("\n"); } /* for each symbol */ #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #else printf("\n"); #endif /* OBJ_COFF */ return; } /* dump_sym() */ #ifndef OBJ_COFF #else printf("\n"); } } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #else #ifdef comment #endif /* OBJ_COFF */ static void dump_reloc (execp, f) #ifndef OBJ_COFF #else dump_reloc (execp, f) #endif /* OBJ_BOUT */ struct exec *execp; #else fileheader *execp; #endif /* OBJ_COFF */ FILE *f; { #ifndef OBJ_COFF read_symbols (execp, f); #else read_symbols(execp, f); #endif /* OBJ_COFF */ if (execp->a_trsize) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("text reloc\n"); #ifndef OBJ_COFF #else printf ("text reloc\n"); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ dump_reloc1 (execp, f, N_TRELOFF (*execp), execp->a_trsize); } if (execp->a_drsize) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("data reloc\n"); #ifndef OBJ_COFF #else printf ("data reloc\n"); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ dump_reloc1 (execp, f, N_DRELOFF (*execp), execp->a_drsize); } #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ return; } /* dump_reloc() */ #ifndef OBJ_COFF #else } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ static void dump_reloc1 (execp, f, off, size) #ifndef OBJ_COFF #else dump_reloc1 (execp, f, off, size) #endif /* OBJ_BOUT */ struct exec *execp; #else fileheader *execp; #endif /* OBJ_COFF */ FILE *f; #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ int off; int size; #ifndef OBJ_COFF #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ { int nreloc; struct relocation_info reloc; int i; nreloc = size / sizeof (struct relocation_info); #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (!omit_reloc_numbers_flag) { printf("%3s: ", "#"); } /* if printing numbers */ #ifndef sparc printf("%3s ", "len"); #endif /* sparc */ printf("%8s %4s\n", "adr", "sym"); fseek(f, off, 0); #ifndef OBJ_COFF #else printf ("%3s: %3s %8s %4s\n", "#", "len", "adr", "sym"); fseek (f, off, 0); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ for (i = 0; i < nreloc; i++) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (fread((char *)&reloc, sizeof reloc, 1, f) != 1) { fprintf(stderr, "%s: error reading reloc\n", #ifndef OBJ_COFF #else if (fread ((char *)&reloc, sizeof reloc, 1, f) != 1) { fprintf (stderr, "%s: error reading reloc\n", #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ program_name); return; } #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (!omit_reloc_numbers_flag) { printf("%3d: ", i); } /* if printing numbers */ #ifndef sparc printf("%3d ", 1 << reloc.r_length); #endif /* sparc */ printf("%8lx ", (long unsigned) reloc.r_address); #ifndef B_OUT #ifndef OBJ_COFF #else printf ("%3d: %3d %8x ", i, 1 << reloc.r_length, reloc.r_address); #ifdef NOT #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ if (reloc.r_extern) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (!omit_sym_numbers_flag) { (void) printf("%4d ", reloc.r_symbolnum); } else { (void) printf(" "); } /* if printing sym numbers */ #ifndef OBJ_COFF #else printf ("%4d ", reloc.r_symbolnum); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ if (reloc.r_symbolnum < nsyms) #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("%s ", symtbl[reloc.r_symbolnum].n_un.n_name); #ifndef OBJ_COFF #else printf ("%s ", symtbl[reloc.r_symbolnum].n_un.n_name); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ } else { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf(" "); #ifndef OBJ_COFF #else printf (" "); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ switch (reloc.r_symbolnum & ~N_EXT) { #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ case N_TEXT: printf(".text "); break; case N_DATA: printf(".data "); break; case N_BSS: printf(".bss "); break; case N_ABS: printf(".abs "); break; default: printf("base %x ", (unsigned) reloc.r_symbolnum); break; #ifndef OBJ_COFF #else case N_TEXT: printf (".text "); break; case N_DATA: printf (".data "); break; case N_BSS: printf (".bss "); break; case N_ABS: printf (".abs "); break; default: printf ("base %x ", reloc.r_symbolnum); break; #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ } } #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ #endif /* not B_OUT */ #ifdef SPARC if (reloc.r_addend) printf("+0x%x ", (unsigned) reloc.r_addend); switch (reloc.r_type) { case RELOC_8: printf("R8 "); break; case RELOC_16: printf("R16 "); break; case RELOC_32: printf("R32 "); break; case RELOC_DISP8: printf("DISP8 "); break; case RELOC_DISP16: printf("DISP16 "); break; case RELOC_DISP32: printf("DISP32 "); break; case RELOC_WDISP30: printf("WDISP30 "); break; case RELOC_WDISP22: printf("WDISP22 "); break; case RELOC_HI22: printf("HI22 "); break; case RELOC_22: printf("R22 "); break; case RELOC_13: printf("R13 "); break; case RELOC_LO10: printf("LO10 "); break; case RELOC_SFA_BASE: printf("SFA_BASE "); break; case RELOC_SFA_OFF13: printf("SFA_OFF13 "); break; case RELOC_BASE10: printf("BASE10 "); break; case RELOC_BASE13: printf("BASE13 "); break; case RELOC_BASE22: printf("BASE22 "); break; case RELOC_PC10: printf("PC10 "); break; case RELOC_PC22: printf("PC22 "); break; case RELOC_JMP_TBL: printf("JMP_TBL "); break; case RELOC_SEGOFF16: printf("SEGOFF16 "); break; case RELOC_GLOB_DAT: printf("GLOB_DAT "); break; case RELOC_JMP_SLOT: printf("JMP_SLOT "); break; case RELOC_RELATIVE: printf("RELATIVE "); break; } /* switch on reloc type */ #else /* SPARC */ if (reloc.r_pcrel) printf("PCREL "); #endif /* SPARC */ #ifdef B_OUT if (reloc.r_bsr) printf("BSR "); if (reloc.r_disp) printf("DISP "); if (reloc.r_callj) printf("CALLJ "); if (reloc.nuthin) printf("NUTHIN "); #endif /* B_OUT */ #ifdef SPARC { struct reloc_info_sparc spare; bzero(&spare, sizeof(spare)); reloc.r_address = 0; reloc.r_index = 0; reloc.r_extern = 0; reloc.r_type = 0; reloc.r_addend = 0; if (bcmp(&reloc, &spare, sizeof(spare))) { printf("(garbage in spare bits) "); } /* if garbage in spare bits */ } /* sparc */ #endif /* SPARC */ #ifndef OBJ_COFF #else #endif /* NOT */ if (reloc.r_pcrel) printf ("PCREL "); if (reloc.r_bsr) printf ("BSR "); if (reloc.r_disp) printf ("DISP "); if (reloc.r_callj) printf ("CALLJ "); if (reloc.nuthin) printf ("NUTHIN "); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #if 0 #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ if (reloc.r_pad) printf("PAD %x ", reloc.r_pad); #ifndef OBJ_COFF #else if (reloc.r_pad) printf ("PAD %x ", reloc.r_pad); #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */ #endif #ifndef OBJ_COFF #ifndef OBJ_BOUT #endif /* OBJ_COFF */ printf("\n"); } /* for each reloc record */ return; } /* dump_reloc1() */ #ifndef OBJ_COFF #else printf ("\n"); } } #endif /* OBJ_BOUT */ #else #endif /* comment */ #endif /* OBJ_COFF */ /* Allocate `n' bytes of memory dynamically, with error checking. */ #ifndef OBJ_COFF char * xmalloc (n) unsigned n; { char *p; p = malloc (n); if (p == 0) { #ifndef OBJ_BOUT fprintf(stderr, "%s: virtual memory exhausted\n", program_name); #else fprintf (stderr, "%s: virtual memory exhausted\n", program_name); #endif /* OBJ_BOUT */ exit (1); } #ifndef OBJ_BOUT bzero(p, n); #endif /* OBJ_BOUT */ return p; #ifndef OBJ_BOUT #else static char *xmalloc (n) unsigned n; { char *p; p = malloc (n); if (p == NULL) { fprintf(stderr, "%s: virtual memory exhausted\n", program_name); exit (1); } bzero(p, n); return p; #endif /* OBJ_COFF */ } /* xmalloc() */ #ifdef OBJ_COFF static char *xrealloc(p, size) char *p; unsigned size; { p = realloc(p, size); if (p == NULL) { fprintf(stderr, "%s: virtual memory exhausted\n", program_name); exit (1); } /* on malloc failure */ bzero(p, size); return(p); } /* xrealloc() */ #endif /* OBJ_COFF */ /* * Local Variables: * comment-column: 0 * fill-column: 131 * End: */ /* end of objdump.c */ #ifndef OBJ_COFF #else } #endif /* OBJ_BOUT */ #endif /* OBJ_COFF */