|
@@ -0,0 +1,214 @@
|
|
|
+static char rcsid[] = "$Header$";
|
|
|
+/*
|
|
|
+ * show - make the contents of an ACK object file human readable.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdio.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/stat.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. */
|
|
|
+
|
|
|
+/* ARGSUSED */
|
|
|
+main(argc, argv)
|
|
|
+ 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();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+show(headp)
|
|
|
+ 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. */
|
|
|
+ extern char *myalloc();
|
|
|
+
|
|
|
+ printf("Version %d\n", headp->oh_stamp);
|
|
|
+ showflags(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 * SZ_NAME);
|
|
|
+ string = myalloc((unsigned) headp->oh_nchar);
|
|
|
+ for (np = &name[0]; np < &name[headp->oh_nname]; np++) {
|
|
|
+ rd_name(np, 1);
|
|
|
+ if (np->on_foff != 0)
|
|
|
+ np->on_mptr = string + np->on_foff - OFF_CHAR(*headp);
|
|
|
+/* Weird: ^^^^^^^^^^^^^^^^^^^ */
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * 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++) {
|
|
|
+ printf("Name %d:\n", np - name);
|
|
|
+ showname(np);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Show flags from header.
|
|
|
+ */
|
|
|
+showflags(flagword)
|
|
|
+ ushort flagword;
|
|
|
+{
|
|
|
+ if (flagword & HF_LINK) printf("unresolved references left\n");
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Show a section.
|
|
|
+ */
|
|
|
+showsect()
|
|
|
+{
|
|
|
+ struct outsect section;
|
|
|
+
|
|
|
+ rd_sect(§ion, 1);
|
|
|
+ printf("\tstartaddress in machine\t%ld\n", section.os_base);
|
|
|
+ printf("\tsection size in machine\t%ld\n", section.os_size);
|
|
|
+ printf("\tstartaddress in file\t%ld\n", section.os_foff);
|
|
|
+ printf("\tsection size in file\t%ld\n", section.os_flen);
|
|
|
+ printf("\tsection alignment\t%ld\n", section.os_lign);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Show a relocation record.
|
|
|
+ */
|
|
|
+showrelo()
|
|
|
+{
|
|
|
+ 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 RELO4:
|
|
|
+ printf("\t4 bytes\n");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ error("\tunexpected relocation length\n");
|
|
|
+ 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.
|
|
|
+ */
|
|
|
+showname(namep)
|
|
|
+ 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;
|
|
|
+ default:
|
|
|
+ printf("\tin section %ld\n", (namep->on_type & S_TYP) - S_MIN);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (namep->on_type & S_EXT) printf("\texternal\n");
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ printf("\tvalue %ld\n", namep->on_valu);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Core allocation via malloc() but fatal if no core.
|
|
|
+ */
|
|
|
+char *
|
|
|
+myalloc(u)
|
|
|
+ unsigned int u;
|
|
|
+{
|
|
|
+ register char *rcp;
|
|
|
+ extern char *malloc();
|
|
|
+
|
|
|
+ rcp = malloc(u);
|
|
|
+ if (rcp == (char *) 0) {
|
|
|
+ error("Out of core\n");
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+ return rcp;
|
|
|
+}
|
|
|
+
|
|
|
+/* VARARGS1 */
|
|
|
+error(s, a1, a2, a3, a4)
|
|
|
+ char *s;
|
|
|
+{
|
|
|
+ fflush(stdout);
|
|
|
+ fprintf(stderr, s, a1, a2, a3, a4);
|
|
|
+}
|
|
|
+
|
|
|
+rd_fatal()
|
|
|
+{
|
|
|
+ error("Error in reading the object file\n");
|
|
|
+ exit(1);
|
|
|
+}
|