home *** CD-ROM | disk | FTP | other *** search
- /* > Analyse */
-
- /* Released to Public Domain by David McQuillan */
-
- /* cc -DANALYSE -> object code analyser */
- /* analyse AOF_file */
- /* cc -DRETAIN -> utility to retain only a list of globals */
- /* retain AOF_file names_file */
- /* cc -DSUPPRESS -> utility to suppress a list of globals */
- /* suppress AOF_file names_file */
- /* names_file is a space comma or newline separated list of */
- /* names which are global in the object file. */
- /* The object file is overwritten by Retain and Suppress */
-
-
- #include <setjmp.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <kernel.h>
-
-
- typedef unsigned char bool;
-
- #define FALSE 0
- #define TRUE 1
-
- typedef struct
- {
- jmp_buf js;
- } jmp_struct;
-
- static jmp_struct err_jmp;
-
-
- /* Format of a chunk file header - first few bytes of a chunk file */
-
- typedef struct chunk_file_header_entry
- {
- unsigned ChunkIDPrefix;
- unsigned ChunkIDType;
- unsigned FileOffset;
- unsigned Size;
- } chunk_file_header_entrys;
-
- typedef struct chunk_file_header
- {
- unsigned ChunkField;
- unsigned maxChunks;
- unsigned numChunks;
- struct chunk_file_header_entry entry[1];
- } chunk_file_headers;
-
- #define ChunkFileID (0xC3CBC6C5)
- #define ChunkID_LIB (0x5F42494C) /* (unsigned)('LIB_') */
- #define ChunkID_OFL (0x5F4C464F) /* (unsigned)('OFL_') */
- #define ChunkID_OBJ (0x5F4A424F) /* (unsigned)('OBJ_') */
- #define ChunkID_LIB_DIRY (0x59524944) /* (unsigned)('DIRY') */
- #define ChunkID_LIB_TIME (0x454D4954) /* (unsigned)('TIME') */
- #define ChunkID_LIB_VRSN (0x4E535256) /* (unsigned)('VRSN') */
- #define ChunkID_LIB_DATA (0x41544144) /* (unsigned)('DATA') */
- #define ChunkID_OFL_SYMT (0x544D5953) /* (unsigned)('SYMT') */
- #define ChunkID_OFL_TIME (0x454D4954) /* (unsigned)('TIME') */
- #define ChunkID_OBJ_HEAD (0x44414548) /* (unsigned)('HEAD') */
- #define ChunkID_OBJ_AREA (0x41455241) /* (unsigned)('AREA') */
- #define ChunkID_OBJ_IDFN (0x4E464449) /* (unsigned)('IDFN') */
- #define ChunkID_OBJ_SYMT (0x544D5953) /* (unsigned)('SYMT') */
- #define ChunkID_OBJ_STRT (0x54525453) /* (unsigned)('STRT') */
-
- #define ChunkFile_HdrSize(hdr_ptr) \
- (sizeof (struct chunk_file_header) + \
- ((hdr_ptr)->maxChunks - 1) * sizeof (struct chunk_file_header_entry))
-
- typedef struct lib_diry_entry
- {
- unsigned ChunkIndex;
- unsigned EntryLength;
- unsigned DataLength;
- char LibData[1];
- } lib_diry_entrys;
-
- #define Lib_DataName(ptr) (char *)((ptr)->LibData)
- #define Lib_DataTime(ptr) ((struct lib_TimeStamp *)((ptr)->LibData + \
- ( (strlen((ptr)->LibData)+4) & ~0x03 ) ) )
-
- typedef struct lib_TimeStamp
- {
- char t[8];
- } lib_TimeStamps;
-
- typedef struct ofl_symt_entry
- {
- unsigned ChunkIndex;
- unsigned EntryLength;
- unsigned DataLength;
- char Name[1];
- } ofl_symt_entrys;
-
- typedef struct obj_file_header_entry
- {
- unsigned AreaName;
- unsigned Attributes;
- unsigned AreaSize;
- unsigned numRelocations;
- unsigned unused;
- } obj_file_header_entrys;
-
- typedef struct obj_file_header
- {
- unsigned Type;
- unsigned Version;
- unsigned numAreas;
- unsigned numSymbols;
- unsigned EntryArea;
- unsigned EntryOffset;
- struct obj_file_header_entry entry[1];
- } obj_file_headers;
-
- #define ObjFileType (0xC5E2D080)
-
- typedef struct obj_symt_entry
- {
- unsigned Name;
- unsigned Attributes;
- unsigned Value;
- unsigned AreaName;
- } obj_symt_entrys;
-
-
- /*
- * interrupt
- */
-
- static void interrupt(int type)
- {
- switch (type)
- {
- case SIGINT:
- printf("\nEscape pressed\n");
- break;
- default:
- printf("\nSignal type %d\n", type);
- }
- longjmp(err_jmp.js, 1);
- }
-
-
- /*
- * Load a file into store
- * *len is initialised with extra to add.
- */
-
- static void *LoadFile(char *name, unsigned *len)
- {
- _kernel_osfile_block o_b;
- void *adr;
- int ret;
-
- ret = _kernel_osfile(5, name, &o_b);
-
- if (ret == 0)
- {
- fprintf(stderr, "File %s does not exist\n", name);
- return NULL;
- }
- else if (ret == 2)
- {
- fprintf(stderr, "File %s is a directory\n", name);
- return NULL;
- }
-
- /* Load the file */
-
- *len += o_b.start;
-
- adr = malloc(*len);
-
- o_b.load = (int) adr;
- o_b.exec = 0;
-
- _kernel_osfile(255, name, &o_b);
-
- return adr;
- }
-
-
- /*
- * Save file from store
- */
-
- static void SaveFile(char *name, void *adr, int len, int type)
- {
- _kernel_osfile_block o_b;
- int ret;
-
- /* Save the file */
-
- o_b.load = type;
- o_b.exec = 0;
- o_b.start = (int) adr;
- o_b.end = o_b.start + len;
-
- ret = _kernel_osfile(10, name, &o_b);
-
- if (ret < 0)
- {
- fprintf(stderr, "Error code %d when saving file %s\n", ret, name);
- exit(EXIT_FAILURE);
- }
-
- return;
- }
-
-
- /*
- * dump
- */
-
- static void dump(unsigned adr_start, unsigned adr_end)
- {
- char line[80];
-
- sprintf(line, "memory %X %X", adr_start, adr_end);
- #ifdef ANALYSE
- system(line);
- #endif
- }
-
- /*
- * converts the calendar time pointed to by timer to local time in the form
- * of a string. It is equivalent to asctime(sys_localtime(timer));
- */
-
- static char *lib_ctime(lib_TimeStamps * timer)
- {
- _kernel_swi_regs r;
- char t[5];
- static char p[30];
-
- t[0] = timer->t[6];
- t[1] = timer->t[7];
- t[2] = timer->t[0];
- t[3] = timer->t[1];
- t[4] = timer->t[2];
-
- r.r[0] = (int) t;
- r.r[1] = (int) p;
- r.r[2] = 30;
- r.r[3] = (int) "%w3 %m3 %dy %24:%mi:%se %ce%yr";
-
- _kernel_swi(0xC1, &r, &r);
-
- return p;
- }
-
-
- /*
- * chunk pointers
- */
-
- static chunk_file_headers *hdr_area;
- static unsigned hdr_maxc;
- static unsigned lib_diry;
- static unsigned lib_diry_size;
- static unsigned ofl_symt;
- static unsigned ofl_symt_size;
- static unsigned obj_vrsn;
- static unsigned obj_head;
- static unsigned obj_area;
- static unsigned obj_symt;
- static unsigned obj_symt_size;
- static unsigned obj_strt;
- static unsigned entry_area;
- static unsigned entry_disp;
-
-
- /*
- * Retained or Suppressed Names
- */
-
- static char *names[1000];
- static int names_cnt;
-
- static int compare_pnames(const void *ps1, const void *ps2)
- {
- return strcmp(*(char **)ps1, *(char **)ps2);
- }
-
-
- /*
- * print_file_header
- */
-
- static bool print_file_head(unsigned area, bool setup)
- {
- chunk_file_headers *hdr = (chunk_file_headers *) area;
- unsigned maxc;
- unsigned chunk;
-
- #ifdef ANALYSE
- printf("\n");
-
- printf("Chunk File check %08X\n", hdr->ChunkField);
- #endif
-
- if (hdr->ChunkField != ChunkFileID)
- {
- printf("Start not 0x%08X\n", ChunkFileID);
- return FALSE;
- }
-
- maxc = hdr->maxChunks;
-
- if (setup)
- {
- hdr_area = hdr;
- hdr_maxc = maxc;
- }
-
- #ifdef ANALYSE
- printf("Max chunks %d, Num chunks %d\n\n", maxc, hdr->numChunks);
- #endif
-
- for (chunk = 0; chunk < maxc; ++chunk)
- {
- chunk_file_header_entrys *entry = &hdr->entry[chunk];
- unsigned Prefix, Type, Offset, Size;
-
- Prefix = entry->ChunkIDPrefix;
- Type = entry->ChunkIDType;
- Offset = entry->FileOffset;
- Size = entry->Size;
-
- if (Offset != 0)
- {
- unsigned ao = area + Offset;
-
- #ifdef ANALYSE
- printf("%.8s %8X %8X\n", &entry->ChunkIDPrefix, Offset, Size);
- #endif
-
- if (!setup)
- {
- /* don't set up static ponters */
- }
- else if (Prefix == ChunkID_LIB)
- {
- if (Type == ChunkID_LIB_DIRY)
- {
- lib_diry = ao;
- lib_diry_size = Size;
- }
- }
- else if (Prefix == ChunkID_OFL)
- {
- if (Type == ChunkID_OFL_SYMT)
- {
- ofl_symt = ao;
- ofl_symt_size = Size;
- }
- }
- else if (Prefix == ChunkID_OBJ)
- {
- switch (Type)
- {
- case ChunkID_OBJ_HEAD:
- {
- obj_file_headers *obj = (obj_file_headers *) ao;
-
- entry_area = obj->EntryArea-1;
- entry_disp = obj->EntryOffset;
-
- obj_head = ao;
- }
- break;
- case ChunkID_OBJ_AREA:
- obj_area = ao;
- break;
- case ChunkID_OBJ_SYMT:
- obj_symt = ao;
- obj_symt_size = Size;
- break;
- case ChunkID_OBJ_STRT:
- obj_strt = ao;
- break;
- default:
- break;
- }
- }
- }
- }
- return TRUE;
- }
-
-
- /*
- * print_lib_diry
- */
-
- static void print_lib_diry(unsigned ao, unsigned size, int chunk)
- {
- unsigned aend = ao + size;
-
- #ifdef ANALYSE
- printf("\n");
- #endif
-
- while (ao < aend)
- {
- lib_diry_entrys *p = (lib_diry_entrys *) ao;
-
- if (p->ChunkIndex != 0 && (chunk < 0 || chunk == p->ChunkIndex))
- {
- #ifdef ANALYSE
- printf("%s %8X %s\n", lib_ctime(Lib_DataTime(p)),
- p->ChunkIndex, Lib_DataName(p));
- #endif
- }
-
- ao += p->EntryLength;
- }
- }
-
-
- /*
- * print_ofl_symt
- */
-
- static void print_ofl_symt(unsigned ao, unsigned size, int chunk)
- {
- unsigned aend = ao + size;
-
- #ifdef ANALYSE
- printf("\n");
- #endif
-
- while (ao < aend)
- {
- ofl_symt_entrys *p = (ofl_symt_entrys *) ao;
-
- if (chunk < 0 || chunk == p->ChunkIndex)
- {
- #ifdef ANALYSE
- printf("%6X %s\n", p->ChunkIndex, p->Name);
- #endif
- }
-
- ao += p->EntryLength;
- }
- }
-
-
- /*
- * print_obj_symt
- */
-
- static void print_obj_symt(unsigned ao, unsigned Size, int req_area)
- {
- obj_file_headers *obj = (obj_file_headers *) obj_head;
- unsigned numSymbols = Size / sizeof(obj_symt_entrys);
- obj_symt_entrys *symt = (obj_symt_entrys *) ao;
- unsigned symbol;
- bool any_done = FALSE;
-
- if (req_area == entry_area || req_area == -1)
- {
- #ifdef ANALYSE
- printf("\n");
- if (entry_area == -1)
- printf("No entry point\n");
- else
- printf("Entry: %8X %6X %s\n", entry_disp, entry_area,
- (char *)(obj_strt + obj->entry[entry_area].AreaName));
- #endif
- }
-
- for (symbol = 0; symbol < numSymbols; ++symbol)
- {
- obj_symt_entrys *entry = &symt[symbol];
- unsigned Attr = entry->Attributes;
- unsigned area = 0;
- char *areaz = "";
- bool do_print = (req_area < 0);
-
- if ((Attr & 4) == 0 && (Attr & 1) == 1)
- {
- int i;
- int start_i = 0;
- int end_i = obj->numAreas - 1;
-
- if (!do_print)
- end_i = start_i = req_area;
-
- for (i = start_i; i <= end_i; ++i)
- {
- if (entry->AreaName == obj->entry[i].AreaName)
- {
- area = i;
- areaz = (char *) (obj_strt + entry->AreaName);
- do_print = TRUE;
- }
- }
- }
-
- if (do_print)
- {
- if (!any_done)
- {
- #ifdef ANALYSE
- printf("\n");
- #endif
- any_done = TRUE;
- }
-
- #ifdef ANALYSE
- printf("%2X %c%c%c%c%c%c %8X %8X %6X %-16.16s %6X %s\n",
- Attr, "x.XG"[Attr & 3], ".A"[(Attr >> 2) & 1], ".c"[(Attr >> 3) & 1],
- ".W"[(Attr >> 4) & 1], ".S"[(Attr >> 5) & 1], ".C"[(Attr >> 6) & 1],
- entry->Value, entry->AreaName, area, areaz, symbol,
- (char *) (obj_strt + entry->Name));
- #endif
-
- #ifdef RETAIN
- if ((Attr & 3) == 3)
- {
- const char *entry_name = (char *) (obj_strt + entry->Name);
-
- if (bsearch(&entry_name, names, names_cnt, 4,
- &compare_pnames) == NULL)
- entry->Attributes ^= 2; /* 3 -> 1 */
- }
- #endif
-
- #ifdef SUPPRESS
- if ((Attr & 3) == 3)
- {
- const char *entry_name = (char *) (obj_strt + entry->Name);
-
- if (! bsearch(&entry_name, names, names_cnt, 4,
- &compare_pnames) == NULL)
- entry->Attributes ^= 2; /* 3 -> 1 */
- }
- #endif
- }
- ao += sizeof(obj_symt_entrys);
- }
- }
-
-
- /*
- * print_obj_area
- */
-
- static void print_obj_area(obj_file_headers * obj, unsigned ao)
- {
- obj_symt_entrys *symt = (obj_symt_entrys *) obj_symt;
- int area;
-
- #ifdef ANALYSE
- if (ao == 0)
- printf("\n");
- #endif
-
- for (area = 0; area < obj->numAreas; ++area)
- {
- obj_file_header_entrys *entry = &obj->entry[area];
- unsigned Attributes = entry->Attributes;
-
- #ifdef ANALYSE
- if (ao != 0)
- printf("\nAREA %6X\n\n", area);
-
- printf("%8X %c%c%c%c%c%c %8X %8X %8X %6X %s\n",
- Attributes,
- (Attributes & 0x0200 ? 'C' : 'D'),
- (Attributes & 0x0400 ? 'c' : '.'),
- (Attributes & 0x0800 ? 'R' : '.'),
- (Attributes & 0x1000 ? 'N' : '.'),
- (Attributes & 0x2000 ? 'R' : 'W'),
- (Attributes & 0x8000 ? 'd' : '.'),
- entry->AreaSize,
- entry->numRelocations,
- entry->unused,
- area,
- (char *) (obj_strt + entry->AreaName));
- #endif
-
- if (ao != 0)
- print_obj_symt(obj_symt, obj_symt_size, area);
-
- if (ao != 0 && (Attributes & 0x1800) == 0)
- {
- char *namez;
- int j;
-
- dump(ao, ao + entry->AreaSize);
- ao = (ao + entry->AreaSize + 3) & -4;
-
- #ifdef ANALYSE
- if (entry->numRelocations != 0)
- printf("\nRelocations\n\n");
- #endif
-
- for (j = 0; j < entry->numRelocations; ++j)
- {
- unsigned Offset = *(int *) ao;
- unsigned Action = *(int *) (ao + 4);
- unsigned Type, Additive, Reloc, Field, SID;
-
- if (Action & 0x80000000)
- {
- Type = 2;
- Field = (Action >> 24) & 3;
- Reloc = (Action >> 26) & 1;
- Additive = (Action >> 27) & 1;
- SID = Action & 0xFFFFFF;
- }
- else
- {
- Type = 1;
- Field = (Action >> 16) & 3;
- Reloc = (Action >> 18) & 1;
- Additive = (Action >> 19) & 1;
- SID = Action & 0xFFFF;
- }
-
- if (Type == 1 && Reloc == 0 && Additive == 0)
- namez = "";
- else if (Type == 2 && Additive == 0)
- {
- namez = (char *) (obj_strt + obj->entry[SID].AreaName);
- }
- else
- {
- namez = (char *) (obj_strt + symt[SID].Name);
- }
-
- #ifdef ANALYSE
- printf("%8X %8X T%1X %c%c%c %6X %s\n",
- Offset, Action,
- Type, "BH.x"[Field], "AP"[Reloc], ".S"[Additive],
- SID, namez);
- #endif
- ao += 8;
- }
- }
- }
- }
-
-
- /*
- * main
- */
-
- extern int main(int argn, char *argv[])
- {
- char *infile, *namesfile;
- unsigned area, len;
- unsigned namesarea, nameslen;
- unsigned chunk;
-
- /* Initialisation */
-
- if (setjmp(err_jmp.js))
- {
- exit(0);
- }
- signal(SIGINT, *interrupt);
-
- lib_diry = 0;
- lib_diry_size = 0;
- ofl_symt = 0;
- ofl_symt_size = 0;
- obj_vrsn = 150;
- obj_head = 0;
- obj_area = 0;
- obj_symt = 0;
- obj_symt_size = 0;
- obj_strt = 0;
-
- #ifdef ANALYSE
- if (argn < 2 || argn > 2)
- {
- printf("Syntax is *analyse objfile\n");
- exit(0);
- }
- #endif
-
- #ifdef RETAIN
- if (argn < 3 || argn > 3)
- {
- printf("Syntax is *retain objfile namesfile\n");
- exit(0);
- }
- #endif
-
- #ifdef SUPPRESS
- if (argn < 3 || argn > 3)
- {
- printf("Syntax is *suppress objfile namesfile\n");
- exit(0);
- }
- #endif
-
- infile = argv[1];
-
- len = 0;
- area = (unsigned) LoadFile(infile, &len);
- if (area == NULL)
- {
- fprintf(stderr, "File %s not loaded\n", infile);
- exit(0);
- }
-
- #if defined(RETAIN) || defined(SUPPRESS)
-
- namesfile = argv[2];
-
- nameslen = 1;
- namesarea = (unsigned) LoadFile(namesfile, &nameslen);
- if (namesarea == NULL)
- {
- fprintf(stderr, "File %s not loaded\n", namesfile);
- exit(0);
- }
- *(char *)(namesarea+nameslen-1) = 0;
-
- {
- char *name;
-
- names_cnt = 0;
- name = strtok((char *)namesarea, ", \n\t");
- while (name != NULL)
- {
- names[names_cnt++] = name;
- name = strtok(NULL, " \n\t");
- }
- }
-
- qsort(names, names_cnt, 4, compare_pnames);
-
- #endif
-
- #ifdef ANALYSE
- printf("\nFile %s\n", infile);
- #endif
-
- if (!print_file_head(area, TRUE))
- exit(0);
-
- for (chunk = 0; chunk < hdr_maxc; ++chunk)
- {
- chunk_file_header_entrys *entry = &hdr_area->entry[chunk];
- unsigned Prefix, Type, Offset, Size;
-
- Prefix = entry->ChunkIDPrefix;
- Type = entry->ChunkIDType;
- Offset = entry->FileOffset;
- Size = entry->Size;
-
- if (Offset != 0)
- {
- unsigned ao0, ao, aend;
- char *namez;
-
- #ifdef ANALYSE
- printf("\n%.8s %8X %8X\n", &entry->ChunkIDPrefix, Offset, Size);
- #endif
-
- ao = area + Offset;
- aend = ao + Size;
-
- switch (Prefix)
- {
- case ChunkID_LIB:
- switch (Type)
- {
- case ChunkID_LIB_TIME:
- #ifdef ANALYSE
- printf("\nTime %s\n", lib_ctime((lib_TimeStamps *) ao));
- #endif
- break;
- case ChunkID_LIB_VRSN:
- #ifdef ANALYSE
- printf("\nVersion %d\n", *(int *) ao);
- #endif
- break;
- case ChunkID_LIB_DIRY:
- print_lib_diry(ao, Size, -1);
- break;
- case ChunkID_LIB_DATA:
- {
- print_lib_diry(lib_diry, lib_diry_size, chunk);
-
- if (ofl_symt_size != 0)
- {
- #ifdef ANALYSE
- printf("\nEntries\n");
- #endif
- print_ofl_symt(ofl_symt, ofl_symt_size, chunk);
- }
-
- #ifdef ANALYSE
- printf("\n");
- #endif
- print_file_head(ao, FALSE);
- }
- break;
- default:
- dump(ao, aend);
- }
- break;
-
- case ChunkID_OFL:
- switch (Type)
- {
- case ChunkID_OFL_TIME:
- #ifdef ANALYSE
- printf("\nTime %s\n", lib_ctime((lib_TimeStamps *) ao));
- #endif
- break;
- case ChunkID_OFL_SYMT:
- print_ofl_symt(ao, Size, -1);
- break;
- default:
- dump(ao, aend);
- }
- break;
-
- case ChunkID_OBJ:
- switch (Type)
- {
- case ChunkID_OBJ_HEAD:
- {
- obj_file_headers *obj = (obj_file_headers *) ao;
-
- #ifdef ANALYSE
- printf("\nObject file type %08X\n", obj->Type);
- if (obj->Type != ObjFileType)
- printf(" != 0x%08X\n", ObjFileType);
- printf("Version Number %d\n", obj->Version);
- printf("Number of areas %d\n", obj->numAreas);
- printf("No. of symbols %d\n", obj->numSymbols);
- printf("Entry address info. %8X %8X\n",
- obj->EntryArea, obj->EntryOffset);
- #endif
-
- obj_vrsn = obj->Version;
- print_obj_area(obj, 0);
- }
- break;
- case ChunkID_OBJ_AREA:
- {
- obj_file_headers *obj = (obj_file_headers *) obj_head;
-
- print_obj_area(obj, ao);
- }
- break;
- case ChunkID_OBJ_IDFN:
- #ifdef ANALYSE
- printf("\n%s\n", (char *) ao);
- #endif
- break;
- case ChunkID_OBJ_SYMT:
- print_obj_symt(ao, Size, -1);
- break;
- case ChunkID_OBJ_STRT:
- printf("\n");
- ao0 = ao;
- if (obj_vrsn >= 150)
- {
- #ifdef ANALYSE
- printf("Length Strings 0x%X\n\n", *(int *) ao);
- #endif
- ao += 4;
- }
- while (ao < aend)
- {
- if (*(char *) ao == 0)
- ++ao;
- else
- {
- namez = (char *) ao;
- #ifdef ANALYSE
- printf("%8X %s\n", ao - ao0, namez);
- #endif
- ao += strlen(namez) + 1;
- }
- }
- break;
- default:
- dump(ao, aend);
- }
- break;
-
- default:
- dump(ao, aend);
- }
- }
- }
-
- #if defined(RETAIN) || defined(SUPPRESS)
-
- /* Produce output file */
-
- SaveFile(infile, (void *)area, len, 0xffd);
-
- #endif
-
- return 0;
- }
-