dismain.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. static char *sccsid = "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01";
  2. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  3. * *
  4. * Copyright (C) 1987 G. M. Harding, all rights reserved *
  5. * *
  6. * Permission to copy and redistribute is hereby granted, *
  7. * provided full source code, with all copyright notices, *
  8. * accompanies any redistribution. *
  9. * *
  10. * This file contains the source code for the machine- *
  11. * independent portions of a disassembler program to run *
  12. * in a Unix (System III) environment. It expects, as its *
  13. * input, a file in standard a.out format, optionally con- *
  14. * taining symbol table information. If a symbol table is *
  15. * present, it will be used in the disassembly; otherwise, *
  16. * all address references will be literal (absolute). *
  17. * *
  18. * The disassembler program was originally written for an *
  19. * Intel 8088 CPU. However, all details of the actual CPU *
  20. * architecture are hidden in three machine-specific files *
  21. * named distabs.c, dishand.c, and disfp.c (the latter *
  22. * file is specific to the 8087 numeric co-processor). The *
  23. * code in this file is generic, and should require mini- *
  24. * mal revision if a different CPU is to be targeted. If a *
  25. * different version of Unix is to be targeted, changes to *
  26. * this file may be necessary, and if a completely differ- *
  27. * ent OS is to be targeted, all bets are off. *
  28. * *
  29. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  30. #include "dis.h" /* Disassembler declarations */
  31. extern char *release; /* Contains release string */
  32. static char *IFILE = NULL; /* Points to input file name */
  33. static char *OFILE = NULL; /* Points to output file name */
  34. static char *PRG; /* Name of invoking program */
  35. static unsigned long zcount; /* Consecutive "0" byte count */
  36. int objflg = 0; /* Flag: output object bytes */
  37. int force = 0; /* Flag: override some checks */
  38. #define unix 1
  39. #define i8086 1
  40. #define ibmpc 1
  41. #if unix && i8086 && ibmpc /* Set the CPU identifier */
  42. static int cpuid = 1;
  43. #else
  44. static int cpuid = 0;
  45. #endif
  46. _PROTOTYPE(static void usage, (char *s ));
  47. _PROTOTYPE(static void fatal, (char *s, char *t ));
  48. _PROTOTYPE(static void zdump, (unsigned long beg ));
  49. _PROTOTYPE(static void prolog, (void));
  50. _PROTOTYPE(static void distext, (void));
  51. _PROTOTYPE(static void disdata, (void));
  52. _PROTOTYPE(static void disbss, (void));
  53. _PROTOTYPE(static char *invoker, (char *s));
  54. _PROTOTYPE(static int objdump, (char *c));
  55. _PROTOTYPE(static char *getlab, (int type));
  56. _PROTOTYPE(static void prolog, (void));
  57. /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */
  58. static void
  59. usage(s)
  60. register char *s;
  61. {
  62. fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s);
  63. exit(-1);
  64. }
  65. static void
  66. fatal(s,t)
  67. register char *s, *t;
  68. {
  69. fprintf(stderr,"%s: %s\n",s,t);
  70. exit(-1);
  71. }
  72. static void
  73. zdump(beg)
  74. unsigned long beg;
  75. {
  76. beg = PC - beg;
  77. if (beg > 1L)
  78. printf("\t.zerow\t%ld\n",(beg >> 1));
  79. if (beg & 1L)
  80. printf("\t.byte\t0\n");
  81. }
  82. static char *
  83. invoker(s)
  84. register char *s;
  85. {
  86. register int k;
  87. k = strlen(s);
  88. while (k--)
  89. if (s[k] == '/')
  90. {
  91. s += k;
  92. ++s;
  93. break;
  94. }
  95. return (s);
  96. }
  97. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  98. * *
  99. * This rather tricky routine supports the disdata() func- *
  100. * tion. Its job is to output the code for a sequence of *
  101. * data bytes whenever the object buffer is full, or when *
  102. * a symbolic label is to be output. However, it must also *
  103. * keep track of consecutive zero words so that lengthy *
  104. * stretches of null data can be compressed by the use of *
  105. * an appropriate assembler pseudo-op. It does this by *
  106. * setting and testing a file-wide flag which counts suc- *
  107. * cessive full buffers of null data. The function returns *
  108. * a logical TRUE value if it outputs anything, logical *
  109. * FALSE otherwise. (This enables disdata() to determine *
  110. * whether to output a new synthetic label when there is *
  111. * no symbol table.) *
  112. * *
  113. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  114. static int
  115. objdump(c)
  116. register char *c;
  117. {/* * * * * * * * * * START OF objdump() * * * * * * * * * */
  118. register int k,j;
  119. int retval = 0;
  120. if (objptr == OBJMAX)
  121. {
  122. for (k = 0; k < OBJMAX; ++k)
  123. if (objbuf[k])
  124. break;
  125. if (k == OBJMAX)
  126. {
  127. zcount += k;
  128. objptr = 0;
  129. if (c == NULL)
  130. return (retval);
  131. }
  132. }
  133. if (zcount)
  134. {
  135. printf("\t.zerow\t%ld\n",(zcount >> 1));
  136. ++retval;
  137. zcount = 0L;
  138. }
  139. if (objptr)
  140. {
  141. printf("\t.byte\t");
  142. ++retval;
  143. }
  144. else
  145. return (retval);
  146. for (k = 0; k < objptr; ++k)
  147. {
  148. printf("$%02.2x",objbuf[k]);
  149. if (k < (objptr - 1))
  150. putchar(',');
  151. }
  152. for (k = objptr; k < OBJMAX; ++k)
  153. printf(" ");
  154. printf(" | \"");
  155. for (k = 0; k < objptr; ++k)
  156. {
  157. if (objbuf[k] > ' ' && objbuf[k] <= '~' )
  158. putchar(objbuf[k]);
  159. else switch(objbuf[k])
  160. {
  161. case '\t': printf("\\t"); break;
  162. case '\n': printf("\\n"); break;
  163. case '\f': printf("\\f"); break;
  164. case '\r': printf("\\r"); break;
  165. default: putchar('.'); break;
  166. }
  167. }
  168. printf("\"\n");
  169. objptr = 0;
  170. return (retval);
  171. }/* * * * * * * * * * END OF objdump() * * * * * * * * * */
  172. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  173. * *
  174. * This routine, called at the beginning of the input *
  175. * cycle for each object byte, and before any interpreta- *
  176. * tion is attempted, searches the symbol table for any *
  177. * symbolic name with a value corresponding to the cur- *
  178. * rent PC and a type corresponding to the segment type *
  179. * (i.e., text, data, or bss) specified by the function's *
  180. * argument. If any such name is found, a pointer to it is *
  181. * returned; otherwise, a NULL pointer is returned. *
  182. * *
  183. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  184. static char *
  185. getlab(type)
  186. register int type;
  187. {/* * * * * * * * * * START OF getlab() * * * * * * * * * */
  188. register int k;
  189. static char b[48], c[32];
  190. if (symptr < 0)
  191. if ((type == N_TEXT)
  192. || ((type == N_DATA) && ( ! objptr ) && ( ! zcount )))
  193. {
  194. if (type == N_TEXT)
  195. sprintf(b,"T%05.5lx:",PC);
  196. else
  197. sprintf(b,"D%05.5lx:",PC);
  198. return (b);
  199. }
  200. else
  201. return (NULL);
  202. for (k = 0; k <= symptr; ++k)
  203. if ((symtab[k].n_value == PC)
  204. && ((symtab[k].n_sclass & N_SECT) == type))
  205. {
  206. sprintf(b,"%s:\n",getnam(k));
  207. if (objflg && (type != N_TEXT))
  208. sprintf(c,"| %05.5lx\n",PC);
  209. strcat(b,c);
  210. return (b);
  211. }
  212. return (NULL);
  213. }/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */
  214. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  215. * *
  216. * This routine performs a preliminary scan of the symbol *
  217. * table, before disassembly begins, and outputs declara- *
  218. * tions of globals and constants. *
  219. * *
  220. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  221. static void
  222. prolog()
  223. {/* * * * * * * * * * START OF prolog() * * * * * * * * * */
  224. register int j, flag;
  225. fflush(stdout);
  226. if (symptr < 0)
  227. return;
  228. for (j = flag = 0; j <= symptr; ++j)
  229. if ((symtab[j].n_sclass & N_CLASS) == C_EXT)
  230. if (((symtab[j].n_sclass & N_SECT) > N_UNDF)
  231. && ((symtab[j].n_sclass & N_SECT) < N_COMM))
  232. {
  233. char *c = getnam(j);
  234. printf("\t.globl\t%s",c);
  235. if (++flag == 1)
  236. {
  237. putchar('\t');
  238. if (strlen(c) < 8)
  239. putchar('\t');
  240. printf("| Internal global\n");
  241. }
  242. else
  243. putchar('\n');
  244. }
  245. else
  246. if (symtab[j].n_value)
  247. {
  248. char *c = getnam(j);
  249. printf("\t.comm\t%s,0x%08.8lx",c,
  250. symtab[j].n_value);
  251. if (++flag == 1)
  252. printf("\t| Internal global\n");
  253. else
  254. putchar('\n');
  255. }
  256. if (flag)
  257. putchar('\n');
  258. fflush(stdout);
  259. for (j = flag = 0; j <= relptr; ++j)
  260. if (relo[j].r_symndx < S_BSS)
  261. {
  262. char *c = getnam(relo[j].r_symndx);
  263. ++flag;
  264. printf("\t.globl\t%s",c);
  265. putchar('\t');
  266. if (strlen(c) < 8)
  267. putchar('\t');
  268. printf("| Undef: %05.5lx\n",relo[j].r_vaddr);
  269. }
  270. if (flag)
  271. putchar('\n');
  272. fflush(stdout);
  273. for (j = flag = 0; j <= symptr; ++j)
  274. if ((symtab[j].n_sclass & N_SECT) == N_ABS)
  275. {
  276. char *c = getnam(j);
  277. printf("%s=0x%08.8lx",c,symtab[j].n_value);
  278. if (++flag == 1)
  279. {
  280. printf("\t\t");
  281. if (strlen(c) < 5)
  282. putchar('\t');
  283. printf("| Literal\n");
  284. }
  285. else
  286. putchar('\n');
  287. }
  288. if (flag)
  289. putchar('\n');
  290. fflush(stdout);
  291. }/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */
  292. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  293. * *
  294. * This function is responsible for disassembly of the *
  295. * object file's text segment. *
  296. * *
  297. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  298. static void
  299. distext()
  300. {/* * * * * * * * * * START OF distext() * * * * * * * * * */
  301. char *c;
  302. register int j;
  303. register void (*f)();
  304. for (j = 0; j < (int)(HDR.a_hdrlen); ++j)
  305. getchar();
  306. printf("| %s, %s\n\n",PRG,release);
  307. printf("| @(");
  308. printf("#)\tDisassembly of %s",IFILE);
  309. if (symptr < 0)
  310. printf(" (no symbols)\n\n");
  311. else
  312. printf("\n\n");
  313. if (HDR.a_flags & A_EXEC)
  314. printf("| File is executable\n\n");
  315. if (HDR.a_flags & A_SEP)
  316. printf("| File has split I/D space\n\n");
  317. prolog();
  318. printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  319. PC,HDR.a_text);
  320. fflush(stdout);
  321. segflg = 0;
  322. for (PC = 0L; PC < HDR.a_text; ++PC)
  323. {
  324. j = getchar();
  325. if( j == EOF ) break;
  326. j &= 0xFF;
  327. if ((j == 0) && ((PC + 1L) == HDR.a_text))
  328. {
  329. ++PC;
  330. break;
  331. }
  332. if ((c = getlab(N_TEXT)) != NULL)
  333. printf("%s",c);
  334. if( j>=0 && j<256 )
  335. {
  336. f = optab[j].func;
  337. (*f)(j);
  338. }
  339. fflush(stdout);
  340. }
  341. }/* * * * * * * * * * END OF distext() * * * * * * * * * */
  342. Fetch()
  343. {
  344. int p;
  345. ++PC;
  346. if( symptr>=0 && getlab(N_TEXT) != NULL ) { --PC; return -1; }
  347. /* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */
  348. p = getchar();
  349. objbuf[objptr++] = p;
  350. return p;
  351. }
  352. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  353. * *
  354. * This function handles the object file's data segment. *
  355. * There is no good way to disassemble a data segment, be- *
  356. * cause it is impossible to tell, from the object code *
  357. * alone, what each data byte refers to. If it refers to *
  358. * an external symbol, the reference can be resolved from *
  359. * the relocation table, if there is one. However, if it *
  360. * refers to a static symbol, it cannot be distinguished *
  361. * from numeric, character, or other pointer data. In some *
  362. * cases, one might make a semi-educated guess as to the *
  363. * nature of the data, but such guesses are inherently *
  364. * haphazard, and they are bound to be wrong a good por- *
  365. * tion of the time. Consequently, the data segment is *
  366. * disassembled as a byte stream, which will satisfy no *
  367. * one but which, at least, will never mislead anyone. *
  368. * *
  369. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  370. static void
  371. disdata()
  372. {/* * * * * * * * * * START OF disdata() * * * * * * * * * */
  373. register char *c;
  374. register int j;
  375. unsigned long end;
  376. putchar('\n');
  377. if( HDR.a_data == 0 ) return;
  378. if (HDR.a_flags & A_SEP)
  379. {
  380. PC = 0L;
  381. end = HDR.a_data;
  382. }
  383. else
  384. end = HDR.a_text + HDR.a_data;
  385. printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  386. PC,HDR.a_data);
  387. segflg = 0;
  388. for (objptr = 0, zcount = 0L; PC < end; ++PC)
  389. {
  390. if ((c = getlab(N_DATA)) != NULL)
  391. {
  392. objdump(c);
  393. printf("%s",c);
  394. }
  395. if (objptr >= OBJMAX)
  396. if (objdump(NULL) && (symptr < 0))
  397. printf("D%05.5lx:",PC);
  398. j = getchar() & 0xff;
  399. objbuf[objptr++] = j;
  400. }
  401. objdump("");
  402. }/* * * * * * * * * * END OF disdata() * * * * * * * * * */
  403. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  404. * *
  405. * This function handles the object file's bss segment. *
  406. * Disassembly of the bss segment is easy, because every- *
  407. * thing in it is zero by definition. *
  408. * *
  409. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  410. static void disbss()
  411. {/* * * * * * * * * * START OF disbss() * * * * * * * * * */
  412. register int j;
  413. register char *c;
  414. unsigned long beg, end;
  415. putchar('\n');
  416. if( HDR.a_bss == 0 ) return;
  417. if (HDR.a_flags & A_SEP)
  418. end = HDR.a_data + HDR.a_bss;
  419. else
  420. end = HDR.a_text + HDR.a_data + HDR.a_bss;
  421. printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
  422. PC,HDR.a_bss);
  423. segflg = 0;
  424. for (beg = PC; PC < end; ++PC)
  425. if ((c = getlab(N_BSS)) != NULL)
  426. {
  427. if (PC > beg)
  428. {
  429. zdump(beg);
  430. beg = PC;
  431. }
  432. printf("%s",c);
  433. }
  434. if (PC > beg)
  435. zdump(beg);
  436. }/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */
  437. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  438. * *
  439. * This is the program entry point. The command line is *
  440. * searched for an input file name, which must be present. *
  441. * An optional output file name is also permitted; if none *
  442. * is found, standard output is the default. One command- *
  443. * line option is available: "-o", which causes the pro- *
  444. * gram to include object code in comments along with its *
  445. * mnemonic output. *
  446. * *
  447. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  448. void
  449. main(argc,argv)
  450. int argc; /* Command-line args from OS */
  451. register char **argv;
  452. {/* * * * * * * * * * * START OF main() * * * * * * * * * * */
  453. char a[1024];
  454. register int fd;
  455. long taboff, tabnum;
  456. long reloff, relnum;
  457. PRG = invoker(*argv);
  458. while (*++argv != NULL) /* Process command-line args */
  459. if (**argv == '-')
  460. switch (*++*argv)
  461. {
  462. case 'o' :
  463. if (*++*argv)
  464. usage(PRG);
  465. else
  466. ++objflg;
  467. break;
  468. case 'f' :
  469. force++;
  470. break;
  471. default :
  472. usage(PRG);
  473. }
  474. else
  475. if (IFILE == NULL)
  476. IFILE = *argv;
  477. else if (OFILE == NULL)
  478. OFILE = *argv;
  479. else
  480. usage(PRG);
  481. if (IFILE == NULL)
  482. usage(PRG);
  483. else
  484. if ((fd = open(IFILE,0)) < 0)
  485. {
  486. sprintf(a,"can't access input file %s",IFILE);
  487. fatal(PRG,a);
  488. }
  489. if (OFILE != NULL)
  490. if (freopen(OFILE,"w",stdout) == NULL)
  491. {
  492. sprintf(a,"can't open output file %s",OFILE);
  493. fatal(PRG,a);
  494. }
  495. if ( ! cpuid )
  496. fprintf(stderr,"%s: warning: host/cpu clash\n",PRG);
  497. read(fd, (char *) &HDR,sizeof(struct exec));
  498. if (BADMAG(HDR))
  499. {
  500. if (!force)
  501. {
  502. sprintf(a,"input file %s not in object format",IFILE);
  503. fatal(PRG,a);
  504. }
  505. memset(&HDR, '\0', sizeof(struct exec));
  506. HDR.a_text = 0x10000L;
  507. }
  508. if (HDR.a_cpu != A_I8086 && !force)
  509. {
  510. sprintf(a,"%s is not an 8086/8088 object file",IFILE);
  511. fatal(PRG,a);
  512. }
  513. if (HDR.a_hdrlen <= A_MINHDR)
  514. {
  515. HDR.a_trsize = HDR.a_drsize = 0L;
  516. HDR.a_tbase = HDR.a_dbase = 0L;
  517. /* HDR.a_lnums = HDR.a_toffs = 0L; */
  518. }
  519. reloff = HDR.a_text /* Compute reloc data offset */
  520. + HDR.a_data
  521. + (long)(HDR.a_hdrlen);
  522. relnum =
  523. (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc);
  524. taboff = reloff /* Compute name table offset */
  525. + HDR.a_trsize
  526. + HDR.a_drsize;
  527. tabnum = HDR.a_syms / sizeof(struct nlist);
  528. if (relnum > MAXSYM)
  529. fatal(PRG,"reloc table overflow");
  530. if (tabnum > MAXSYM)
  531. fatal(PRG,"symbol table overflow");
  532. if (relnum) /* Get reloc data */
  533. if (lseek(fd,reloff,0) != reloff)
  534. fatal(PRG,"lseek error");
  535. else
  536. {
  537. for (relptr = 0; relptr < relnum; ++relptr)
  538. read(fd, (char *) &relo[relptr],sizeof(struct reloc));
  539. relptr--;
  540. }
  541. if (tabnum) /* Read in symtab */
  542. if (lseek(fd,taboff,0) != taboff)
  543. fatal(PRG,"lseek error");
  544. else
  545. {
  546. for (symptr = 0; symptr < tabnum; ++symptr)
  547. read(fd, (char *) &symtab[symptr],sizeof(struct nlist));
  548. symptr--;
  549. }
  550. close(fd);
  551. if (freopen(IFILE,"r",stdin) == NULL)
  552. {
  553. sprintf(a,"can't reopen input file %s",IFILE);
  554. fatal(PRG,a);
  555. }
  556. distext();
  557. disdata();
  558. disbss();
  559. exit(0);
  560. }/* * * * * * * * * * * END OF main() * * * * * * * * * * */