home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume42 / elfdis / part02 / elfsyms.c < prev    next >
C/C++ Source or Header  |  1994-05-08  |  7KB  |  352 lines

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <libelf.h>
  9.  
  10. #include <dis.h>
  11.  
  12. extern char *sys_errlist[];
  13.  
  14. #ifdef __STDC__
  15. int       main(int ac, char **av);
  16. int       disassemble_file(char *FileName);
  17. int       init_elf_stuff(char *Filename, Elf **sppElf);
  18. char     *find_elf_stringtable(Elf *);
  19. int       check_elf_header(Elf *);
  20. void      usage(void);
  21.  
  22. Elf_Data *find_section_data_by_name(Elf *elf, char *sectname, char *stringtbl,
  23.     Elf32_Shdr **sectionhdr);
  24.  
  25. void      disassemble_symtab_section(Elf32_Shdr *, Elf_Data *, Elf_Data *);
  26. #endif
  27.  
  28. extern int   optind;
  29. extern char *optarg;
  30.  
  31. /*
  32.  * Elf object file format SPARC disassembler.
  33.  *
  34.  * $Log$
  35.  */
  36.  
  37. static char rcsident[] = "@(#) $Id$";
  38.  
  39. /*
  40.  * main(): manage options and command line
  41.  */
  42. int
  43. main(ac, av)
  44. int    ac;
  45. char **av;
  46. {
  47.     int iOptionFlag;
  48.     int iDisSuccess;
  49.     int iC;
  50.     
  51.     while ((iOptionFlag = getopt(ac, av, "fh")) != -1)
  52.     {
  53.         switch (iOptionFlag)
  54.         {
  55.         case 'f':
  56.             iDisSuccess = disassemble_file(optarg);
  57.             break;
  58.         case 'h':
  59.         default:
  60.             usage();
  61.             break;
  62.         }
  63.     }
  64.  
  65.     for (iC = optind; iC < ac; ++iC)
  66.     {
  67.         iDisSuccess = disassemble_file(av[iC]);
  68.     }
  69.  
  70.     return iDisSuccess;
  71. }
  72.  
  73. /*
  74.  * disassemble_file(): encapsulate flow of control for Elf stuff
  75.  * that has to be retrieved to disassemble file.  Responsible for
  76.  * Elf headers and open file descriptors.
  77.  */
  78. int
  79. disassemble_file(bpFilename)
  80. char *bpFilename;
  81. {
  82.     Elf        *spElf;
  83.     Elf_Data   *spSymtabData;
  84.     Elf_Data   *spStrtabData;
  85.     Elf32_Shdr *spSHdr;
  86.     int         iFD;
  87.     char       *bpStringTable = NULL;
  88.  
  89.     if (bpFilename == NULL)
  90.         return 0;
  91.  
  92.     if ((iFD = init_elf_stuff(bpFilename, &spElf)) < 0)
  93.         return 1;
  94.  
  95.     if (!check_elf_header(spElf))
  96.     {
  97.         (void)close(iFD);
  98.         if (spElf != NULL) elf_end(spElf);
  99.         return 1;
  100.     }
  101.  
  102.     if ((bpStringTable = find_elf_stringtable(spElf)) == NULL)
  103.     {
  104.         (void)close(iFD);
  105.         if (spElf != NULL) elf_end(spElf);
  106.         return 1;
  107.     }
  108.  
  109.     if ((spSymtabData = find_section_data_by_name(spElf, ".symtab",
  110.         bpStringTable, &spSHdr)) == NULL)
  111.     {
  112.         (void)fprintf(stderr, "No symtab section in \"%s\"\n", bpFilename);
  113.         (void)close(iFD);
  114.         if (spElf != NULL) elf_end(spElf);
  115.         return 1;
  116.     }
  117.  
  118.     if ((spStrtabData = find_section_data_by_name(spElf, ".strtab",
  119.         bpStringTable, &spSHdr)) == NULL)
  120.     {
  121.         (void)fprintf(stderr, "No strtab section in \"%s\"\n", bpFilename);
  122.         (void)close(iFD);
  123.         if (spElf != NULL) elf_end(spElf);
  124.         return 1;
  125.     }
  126.  
  127.     disassemble_symtab_section(spSHdr, spSymtabData, spStrtabData);
  128.  
  129.     if (spElf != NULL)
  130.         elf_end(spElf);
  131.  
  132.     (void)close(iFD);
  133.  
  134.     return 0;
  135. }
  136.  
  137. void
  138. usage()
  139. {
  140.     (void)fprintf(stderr, "disassemble SPARC ELF object files\n");
  141.     (void)fprintf(stderr, "elfdis <-f filename> <-h> <filename ...>\n");
  142.     exit(1);
  143. }
  144.  
  145.  
  146. /*
  147.  * Do the Elf init stuff for a file.
  148.  *
  149.  * Returns an open file descriptor (>= 0) on success, -1 on failure.
  150.  * Also fills in the "Elf" pointer passed by reference.
  151.  */
  152. int
  153. init_elf_stuff(bpFilename, sppElf)
  154. char *bpFilename;
  155. Elf **sppElf;
  156. {
  157.     int iFD;
  158.  
  159.     assert(bpFilename != NULL);
  160.     assert(sppElf != NULL);
  161.  
  162.     *sppElf = NULL;
  163.  
  164.     if (elf_version(EV_CURRENT) == EV_NONE)
  165.     {
  166.         (void)fprintf(stderr, "Elf Library out of date\n");
  167.         return -1;
  168.     }
  169.  
  170.     if ((iFD = open(bpFilename, O_RDONLY)) < 0)
  171.     {
  172.         (void)fprintf(stderr, "Problem opening \"%s\" read-only: %s\n",
  173.             bpFilename, sys_errlist[errno]);
  174.         return -1;
  175.     }
  176.  
  177.     if ((*sppElf = elf_begin(iFD, ELF_C_READ, NULL)) == NULL)
  178.     {
  179.         (void)fprintf(stderr, "Problem with elf_begin() for %s: %s\n",
  180.             bpFilename, elf_errmsg(elf_errno()));
  181.         return -1;
  182.     }
  183.  
  184.     return iFD;
  185. }
  186.  
  187. /* find string table: not same as a.out string table.  Each Elf file
  188.  * apparently has a small string table that holds the names of sections
  189.  * and segments
  190.  */
  191. char *
  192. find_elf_stringtable(spElf)
  193. Elf *spElf;
  194. {
  195.     char *bpStringTable = NULL;
  196.     Elf32_Ehdr *spEHdr;
  197.  
  198.     assert(spElf != NULL);
  199.  
  200.     if ((spEHdr = elf32_getehdr(spElf)) == NULL)
  201.     {
  202.         (void)fprintf(stderr, "Problem with elf32_getehdr(): %s\n",
  203.             elf_errmsg(elf_errno()));
  204.     } else {
  205.         Elf_Scn    *spScn;
  206.         Elf_Data   *spData;
  207.  
  208.         spScn = elf_getscn(spElf, (size_t)spEHdr->e_shstrndx);
  209.  
  210.         if (spScn == NULL)
  211.             (void)fprintf(stderr, "Couldn't find string table section: %s\n",
  212.                 elf_errmsg(elf_errno()));
  213.         else if ((spData = elf_getdata(spScn, NULL)) == NULL)
  214.             (void)fprintf(stderr, "Couldn't get string table data: %s\n",
  215.                 elf_errmsg(elf_errno()));
  216.         else
  217.             bpStringTable = (char *)spData->d_buf;
  218.  
  219.     }
  220.  
  221.     return bpStringTable;
  222. }
  223.  
  224. /*
  225.  * look at the "sections" of an elf file.  Decide which of them
  226.  * is the desired section.
  227.  */
  228. Elf_Data *
  229. find_section_data_by_name(spElf, bpSection, bpStringTable, sppSHdr)
  230. Elf         *spElf;
  231. char        *bpSection;
  232. char        *bpStringTable;
  233. Elf32_Shdr **sppSHdr;
  234. {
  235.     Elf_Data   *spData = NULL;
  236.     Elf_Scn    *spScn;
  237.  
  238.     assert(spElf != NULL);
  239.     assert(bpSection != NULL);
  240.     assert(bpStringTable != NULL);
  241.  
  242.     *sppSHdr = NULL;
  243.     spScn = NULL;
  244.     while ((spScn = elf_nextscn(spElf, spScn)))
  245.     {
  246.         Elf32_Shdr *spShdr;
  247.  
  248.         if ((spShdr = elf32_getshdr(spScn)) == NULL)
  249.         {
  250.             (void)fprintf(stderr, "Problem with elf32_getshdr(): %s\n",
  251.                 elf_errmsg(elf_errno()));
  252.             continue;
  253.         }
  254.  
  255.         if (!strcmp(&(bpStringTable[spShdr->sh_name]), bpSection))
  256.         {
  257.             spData = elf_getdata(spScn, NULL);
  258.             *sppSHdr = spShdr;
  259.             break;
  260.         }
  261.     }
  262.  
  263.     return spData;
  264. }
  265.  
  266. #ifndef IS_ELF
  267. #define IS_ELF(ehdr)    ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
  268.             (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
  269.             (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
  270.             (ehdr).e_ident[EI_MAG3] == ELFMAG3)
  271. #endif
  272.  
  273. /*
  274.  * Decide if a Elf header represents a file this program
  275.  * can disassemble (return 1) or can't (return 0).
  276.  */
  277. int
  278. check_elf_header(spElf)
  279. Elf *spElf;
  280. {
  281.     Elf32_Ehdr *spHdr;
  282.  
  283.     assert(spElf != NULL);
  284.  
  285.     if ((spHdr = elf32_getehdr(spElf)) == NULL)
  286.         return 0;
  287.  
  288.     if (!IS_ELF((*spHdr))) {
  289.         (void)fprintf(stderr, "Pointer at 0x%x is not an ELF header\n",
  290.             (unsigned int) spHdr);
  291.         (void)fprintf(stderr, "Bogus ident bytes: %x%x(%c)%x(%c)%x(%c)\n",
  292.             spHdr->e_ident[EI_MAG0],
  293.             spHdr->e_ident[EI_MAG1],
  294.             spHdr->e_ident[EI_MAG1],
  295.             spHdr->e_ident[EI_MAG2],
  296.             spHdr->e_ident[EI_MAG2],
  297.             spHdr->e_ident[EI_MAG3],
  298.             spHdr->e_ident[EI_MAG3]);
  299.  
  300.         return 0;
  301.     }
  302.  
  303.     if (spHdr->e_type != ET_REL && spHdr->e_type != ET_EXEC
  304.         && spHdr->e_type != ET_DYN)
  305.     {
  306.         (void)fprintf(stderr, "Not appropriate type of Elf file\n");
  307.         return 0;
  308.     }
  309.  
  310.     if (spHdr->e_machine != EM_SPARC)
  311.     {
  312.         (void)fprintf(stderr, "Not SPARC Elf file\n");
  313.         return 0;
  314.     }
  315.  
  316.     return 1;
  317. }
  318.  
  319. /*
  320.  * print instruction disassembly on stdout.
  321.  * manages count of lines output, program counter and pointer to buffer
  322.  * full of instructions.
  323.  */
  324. void
  325. disassemble_symtab_section(spShdr, spSymtabData, spStrtabData)
  326. Elf32_Shdr *spShdr;
  327. Elf_Data   *spSymtabData, *spStrtabData;
  328. {
  329.     Elf32_Sym *spSym;
  330.     char      *bp;
  331.  
  332.     spSym = (Elf32_Sym *)(spSymtabData->d_buf);
  333.     bp = (char *)(spStrtabData->d_buf);
  334.  
  335.     printf("Value\tsize\ttype\tbind\tother\tshndx\tname\n");
  336.     while ((unsigned long)spSym 
  337.         < (unsigned long)((char *)spSymtabData->d_buf + spSymtabData->d_size))
  338.     {
  339.         printf("0x%x \t %d \t %d \t %d \t %d \t 0x%x \t \"%s\" \n",
  340.             spSym->st_value,
  341.             spSym->st_size,
  342.             ELF32_ST_TYPE(spSym->st_info),
  343.             ELF32_ST_BIND(spSym->st_info),
  344.             spSym->st_other,
  345.             spSym->st_shndx,
  346.             &bp[spSym->st_name]
  347.         );
  348.  
  349.         ++spSym;
  350.     }
  351. }
  352.