home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume42
/
elfdis
/
part02
/
elfsyms.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-08
|
7KB
|
352 lines
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <libelf.h>
#include <dis.h>
extern char *sys_errlist[];
#ifdef __STDC__
int main(int ac, char **av);
int disassemble_file(char *FileName);
int init_elf_stuff(char *Filename, Elf **sppElf);
char *find_elf_stringtable(Elf *);
int check_elf_header(Elf *);
void usage(void);
Elf_Data *find_section_data_by_name(Elf *elf, char *sectname, char *stringtbl,
Elf32_Shdr **sectionhdr);
void disassemble_symtab_section(Elf32_Shdr *, Elf_Data *, Elf_Data *);
#endif
extern int optind;
extern char *optarg;
/*
* Elf object file format SPARC disassembler.
*
* $Log$
*/
static char rcsident[] = "@(#) $Id$";
/*
* main(): manage options and command line
*/
int
main(ac, av)
int ac;
char **av;
{
int iOptionFlag;
int iDisSuccess;
int iC;
while ((iOptionFlag = getopt(ac, av, "fh")) != -1)
{
switch (iOptionFlag)
{
case 'f':
iDisSuccess = disassemble_file(optarg);
break;
case 'h':
default:
usage();
break;
}
}
for (iC = optind; iC < ac; ++iC)
{
iDisSuccess = disassemble_file(av[iC]);
}
return iDisSuccess;
}
/*
* disassemble_file(): encapsulate flow of control for Elf stuff
* that has to be retrieved to disassemble file. Responsible for
* Elf headers and open file descriptors.
*/
int
disassemble_file(bpFilename)
char *bpFilename;
{
Elf *spElf;
Elf_Data *spSymtabData;
Elf_Data *spStrtabData;
Elf32_Shdr *spSHdr;
int iFD;
char *bpStringTable = NULL;
if (bpFilename == NULL)
return 0;
if ((iFD = init_elf_stuff(bpFilename, &spElf)) < 0)
return 1;
if (!check_elf_header(spElf))
{
(void)close(iFD);
if (spElf != NULL) elf_end(spElf);
return 1;
}
if ((bpStringTable = find_elf_stringtable(spElf)) == NULL)
{
(void)close(iFD);
if (spElf != NULL) elf_end(spElf);
return 1;
}
if ((spSymtabData = find_section_data_by_name(spElf, ".symtab",
bpStringTable, &spSHdr)) == NULL)
{
(void)fprintf(stderr, "No symtab section in \"%s\"\n", bpFilename);
(void)close(iFD);
if (spElf != NULL) elf_end(spElf);
return 1;
}
if ((spStrtabData = find_section_data_by_name(spElf, ".strtab",
bpStringTable, &spSHdr)) == NULL)
{
(void)fprintf(stderr, "No strtab section in \"%s\"\n", bpFilename);
(void)close(iFD);
if (spElf != NULL) elf_end(spElf);
return 1;
}
disassemble_symtab_section(spSHdr, spSymtabData, spStrtabData);
if (spElf != NULL)
elf_end(spElf);
(void)close(iFD);
return 0;
}
void
usage()
{
(void)fprintf(stderr, "disassemble SPARC ELF object files\n");
(void)fprintf(stderr, "elfdis <-f filename> <-h> <filename ...>\n");
exit(1);
}
/*
* Do the Elf init stuff for a file.
*
* Returns an open file descriptor (>= 0) on success, -1 on failure.
* Also fills in the "Elf" pointer passed by reference.
*/
int
init_elf_stuff(bpFilename, sppElf)
char *bpFilename;
Elf **sppElf;
{
int iFD;
assert(bpFilename != NULL);
assert(sppElf != NULL);
*sppElf = NULL;
if (elf_version(EV_CURRENT) == EV_NONE)
{
(void)fprintf(stderr, "Elf Library out of date\n");
return -1;
}
if ((iFD = open(bpFilename, O_RDONLY)) < 0)
{
(void)fprintf(stderr, "Problem opening \"%s\" read-only: %s\n",
bpFilename, sys_errlist[errno]);
return -1;
}
if ((*sppElf = elf_begin(iFD, ELF_C_READ, NULL)) == NULL)
{
(void)fprintf(stderr, "Problem with elf_begin() for %s: %s\n",
bpFilename, elf_errmsg(elf_errno()));
return -1;
}
return iFD;
}
/* find string table: not same as a.out string table. Each Elf file
* apparently has a small string table that holds the names of sections
* and segments
*/
char *
find_elf_stringtable(spElf)
Elf *spElf;
{
char *bpStringTable = NULL;
Elf32_Ehdr *spEHdr;
assert(spElf != NULL);
if ((spEHdr = elf32_getehdr(spElf)) == NULL)
{
(void)fprintf(stderr, "Problem with elf32_getehdr(): %s\n",
elf_errmsg(elf_errno()));
} else {
Elf_Scn *spScn;
Elf_Data *spData;
spScn = elf_getscn(spElf, (size_t)spEHdr->e_shstrndx);
if (spScn == NULL)
(void)fprintf(stderr, "Couldn't find string table section: %s\n",
elf_errmsg(elf_errno()));
else if ((spData = elf_getdata(spScn, NULL)) == NULL)
(void)fprintf(stderr, "Couldn't get string table data: %s\n",
elf_errmsg(elf_errno()));
else
bpStringTable = (char *)spData->d_buf;
}
return bpStringTable;
}
/*
* look at the "sections" of an elf file. Decide which of them
* is the desired section.
*/
Elf_Data *
find_section_data_by_name(spElf, bpSection, bpStringTable, sppSHdr)
Elf *spElf;
char *bpSection;
char *bpStringTable;
Elf32_Shdr **sppSHdr;
{
Elf_Data *spData = NULL;
Elf_Scn *spScn;
assert(spElf != NULL);
assert(bpSection != NULL);
assert(bpStringTable != NULL);
*sppSHdr = NULL;
spScn = NULL;
while ((spScn = elf_nextscn(spElf, spScn)))
{
Elf32_Shdr *spShdr;
if ((spShdr = elf32_getshdr(spScn)) == NULL)
{
(void)fprintf(stderr, "Problem with elf32_getshdr(): %s\n",
elf_errmsg(elf_errno()));
continue;
}
if (!strcmp(&(bpStringTable[spShdr->sh_name]), bpSection))
{
spData = elf_getdata(spScn, NULL);
*sppSHdr = spShdr;
break;
}
}
return spData;
}
#ifndef IS_ELF
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
#endif
/*
* Decide if a Elf header represents a file this program
* can disassemble (return 1) or can't (return 0).
*/
int
check_elf_header(spElf)
Elf *spElf;
{
Elf32_Ehdr *spHdr;
assert(spElf != NULL);
if ((spHdr = elf32_getehdr(spElf)) == NULL)
return 0;
if (!IS_ELF((*spHdr))) {
(void)fprintf(stderr, "Pointer at 0x%x is not an ELF header\n",
(unsigned int) spHdr);
(void)fprintf(stderr, "Bogus ident bytes: %x%x(%c)%x(%c)%x(%c)\n",
spHdr->e_ident[EI_MAG0],
spHdr->e_ident[EI_MAG1],
spHdr->e_ident[EI_MAG1],
spHdr->e_ident[EI_MAG2],
spHdr->e_ident[EI_MAG2],
spHdr->e_ident[EI_MAG3],
spHdr->e_ident[EI_MAG3]);
return 0;
}
if (spHdr->e_type != ET_REL && spHdr->e_type != ET_EXEC
&& spHdr->e_type != ET_DYN)
{
(void)fprintf(stderr, "Not appropriate type of Elf file\n");
return 0;
}
if (spHdr->e_machine != EM_SPARC)
{
(void)fprintf(stderr, "Not SPARC Elf file\n");
return 0;
}
return 1;
}
/*
* print instruction disassembly on stdout.
* manages count of lines output, program counter and pointer to buffer
* full of instructions.
*/
void
disassemble_symtab_section(spShdr, spSymtabData, spStrtabData)
Elf32_Shdr *spShdr;
Elf_Data *spSymtabData, *spStrtabData;
{
Elf32_Sym *spSym;
char *bp;
spSym = (Elf32_Sym *)(spSymtabData->d_buf);
bp = (char *)(spStrtabData->d_buf);
printf("Value\tsize\ttype\tbind\tother\tshndx\tname\n");
while ((unsigned long)spSym
< (unsigned long)((char *)spSymtabData->d_buf + spSymtabData->d_size))
{
printf("0x%x \t %d \t %d \t %d \t %d \t 0x%x \t \"%s\" \n",
spSym->st_value,
spSym->st_size,
ELF32_ST_TYPE(spSym->st_info),
ELF32_ST_BIND(spSym->st_info),
spSym->st_other,
spSym->st_shndx,
&bp[spSym->st_name]
);
++spSym;
}
}