1994-06-24 11:31:16 +00:00
|
|
|
static char rcsid[] = "$Id$";
|
1987-03-11 17:12:23 +00:00
|
|
|
/*
|
|
|
|
* show - make the contents of an ACK object file human readable.
|
|
|
|
*/
|
|
|
|
|
2006-10-16 23:20:11 +00:00
|
|
|
#include <stdlib.h>
|
1987-03-11 17:12:23 +00:00
|
|
|
#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);
|
1991-12-18 09:45:26 +00:00
|
|
|
showflags((unsigned) headp->oh_flags);
|
1987-03-11 17:12:23 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
1987-04-08 15:10:26 +00:00
|
|
|
rd_name(name, headp->oh_nname);
|
1987-03-11 17:12:23 +00:00
|
|
|
for (np = &name[0]; np < &name[headp->oh_nname]; np++) {
|
1987-04-08 15:10:26 +00:00
|
|
|
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;
|
|
|
|
}
|
1987-03-11 17:12:23 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* 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)
|
1991-12-18 09:45:26 +00:00
|
|
|
unsigned flagword;
|
1987-03-11 17:12:23 +00:00
|
|
|
{
|
|
|
|
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;
|
1991-10-31 11:04:02 +00:00
|
|
|
case S_CRS:
|
|
|
|
printf("\tcross reference\n");
|
1987-03-11 17:12:23 +00:00
|
|
|
default:
|
1987-04-08 15:10:26 +00:00
|
|
|
printf("\tin section %d\n", (namep->on_type & S_TYP) - S_MIN);
|
1987-03-11 17:12:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (namep->on_type & S_EXT) printf("\texternal\n");
|
1991-10-31 11:04:02 +00:00
|
|
|
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) {
|
1987-03-11 17:12:23 +00:00
|
|
|
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;
|
1990-08-02 15:58:10 +00:00
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("\tstab 0x%x\n", namep->on_type >> 8);
|
|
|
|
printf("\tdesc 0x%x\n", namep->on_desc);
|
1987-03-11 17:12:23 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|