static char rcsid[] = "$Id$"; /* * show - make the contents of an ACK object file human readable. */ #include #include #include #include "object.h" #include "out.h" #define OK 0 /* Return value of gethead if Orl Korekt. */ #define BMASK 0xFF /* To extract least significant 8 bits from an int. */ /* Forward declarations */ static void show(register struct outhead *); static void showflags(unsigned int); static void showsect(void); static void showrelo(void); static void showname(struct outname *); static char *myalloc(unsigned int); static void error(char *, ...); /* ARGSUSED */ int main(int argc, char **argv) # define prog argv[0] { register char **arg = argv; struct outhead header; while (*++arg) { if (! rd_open(*arg)) { error("%s: cannot read %s\n", prog, *arg); continue; } rd_ohead(&header); if (BADMAGIC(header)) { error("%s: %s not an ACK object file\n", prog, *arg); } else { printf("%s:\n", *arg); show(&header); } rd_close(); } return EXIT_SUCCESS; } /* * Read an ACK object file from `fp' and show it in a human readable way. * NB. The header has already been read and is in the struct outhead `headp' * points to. */ static void show(register struct outhead *headp) { register int i; register struct outname *np; register struct outname *name; /* Dynamically allocated name-array. */ register char *string;/* Base of string area. */ printf("Version %d\n", headp->oh_stamp); showflags((unsigned) headp->oh_flags); /* * Show all sections. */ for (i = 0; i < headp->oh_nsect; i++) { printf("Section %d:\n", i); showsect(); } /* * Show relocation information. */ for (i = 0; i < headp->oh_nrelo; i++) { printf("Relocation record %d:\n", i); showrelo(); } /* * We get all struct outname's and the strings in core first. */ name = (struct outname *) myalloc(headp->oh_nname * sizeof(struct outname)); string = myalloc((unsigned) headp->oh_nchar); rd_name(name, headp->oh_nname); for (np = &name[0]; np < &name[headp->oh_nname]; np++) { if (np->on_foff != 0) { np->on_foff -= OFF_CHAR(*headp); if (np->on_foff >= headp->oh_nchar || np->on_foff < 0) { np->on_mptr = "????"; } else np->on_mptr = string + np->on_foff; } } /* * Transfer strings from file to core. */ rd_string(string, headp->oh_nchar); /* * Now we can show all names. */ for (np = &name[0]; np < &name[headp->oh_nname]; np++) { /* In C99 this should be "%td" but we are in ANSI C89, * so we typecast explicitly to int here. */ printf("Name %d:\n", (int)(np - name)); showname(np); } } /* * Show flags from header. */ static void showflags(unsigned int flagword) { if (flagword & HF_LINK) printf("unresolved references left\n"); } /* * Show a section. */ static void showsect(void) { struct outsect section; rd_sect(§ion, 1); printf("\tstartaddress in machine\t0x%lX\n", section.os_base); printf("\tsection size in machine\t0x%lX\n", section.os_size); printf("\tstartaddress in file\t0x%lX\n", section.os_foff); printf("\tsection size in file\t0x%lX\n", section.os_flen); printf("\tsection alignment\t%ld\n", section.os_lign); } /* * Show a relocation record. */ static void showrelo(void) { struct outrelo relrec; rd_relo(&relrec, 1); switch (relrec.or_type & RELSZ) { case RELO1: printf("\t1 byte\n"); break; case RELO2: printf("\t2 bytes\n"); break; case RELO2HI: printf("\ttop 2 bytes of result\n"); break; case RELO2HISAD: printf("\ttop 2 bytes of result, sign adjusted\n"); break; case RELO4: printf("\t4 bytes\n"); break; case RELOPPC: printf("\tPowerPC 26-bit address\n"); break; case RELOPPC_LIS: printf("\tPowerPC lis instruction\n"); break; case RELOVC4: printf("\tVideoCore IV address in 32-bit instruction\n"); break; case RELOMIPS: printf("\tMIPS b or j instruction\n"); break; default: printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); break; } if (relrec.or_type & RELPC) printf("\tpc relative\n"); if (relrec.or_type & RELBR) printf("\tbytes reversed\n"); if (relrec.or_type & RELWR) printf("\twords reversed\n"); printf("\treferencing section\t%d\n", (relrec.or_sect & BMASK) - S_MIN); printf("\treferenced symbol index\t%d\n", relrec.or_nami); printf("\treferencing address\t%ld\n", relrec.or_addr); } /* * Show the name in the struct `namep' points to. */ static void showname(struct outname *namep) { if (namep->on_mptr) printf("\t%s\n", namep->on_mptr); else printf("\tno name\n"); switch (namep->on_type & S_TYP) { case S_UND: printf("\tundefined\n"); break; case S_ABS: printf("\tabsolute\n"); break; case S_CRS: printf("\tcross reference\n"); default: printf("\tin section %d\n", (namep->on_type & S_TYP) - S_MIN); break; } if (namep->on_type & S_EXT) printf("\texternal\n"); if (namep->on_type & S_STB) { printf("\tstab 0x%x\n", namep->on_type >> 8); printf("\tdesc 0x%x\n", namep->on_desc); } else switch (namep->on_type & S_ETC) { case S_SCT: printf("\tsection name\n"); break; case S_LIN: printf("\thll source line item\n"); break; case S_FIL: printf("\thll source file item\n"); break; case S_MOD: printf("\tass src file item\n"); break; case S_COM: printf("\tcommon\n"); break; case 0: break; default: printf("\tstab 0x%x\n", namep->on_type >> 8); printf("\tdesc 0x%x\n", namep->on_desc); } printf("\tvalue 0x%lX\n", namep->on_valu); } /* * Core allocation via malloc() but fatal if no core. */ static char *myalloc(unsigned int u) { register char *rcp; rcp = malloc(u); if (rcp == (char *) NULL) { error("Out of core\n"); exit(EXIT_FAILURE); } return rcp; } static void error(char *fmt, ...) { fflush(stdout); /* Diagnostic print, no auto NL */ va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } void rd_fatal(void) { error("Error in reading the object file\n"); exit(1); }