ack/util/amisc/ashow.c
2019-03-24 23:35:59 +08:00

257 lines
5.8 KiB
C

static char rcsid[] = "$Id$";
/*
* show - make the contents of an ACK object file human readable.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#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(&section, 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);
}