blob: 8d3df212a0c0a5dac2994a65eb655b80433efc63 [file] [log] [blame]
/*
* Extended Dynamic Object format dumper
*
* Copyright (C) 2004-2007 Peter Johnson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include "xdf.h"
void
print_file_header(const FILE_HEADER *filehead)
{
printf("File Header:\n");
printf("\tMagic=0x%08X\n", filehead->f_magic);
printf("\tNumber of Sections=%d\n", filehead->f_nsect);
printf("\tNumber of Symbols=%d\n", filehead->f_nsyms);
printf("\tTotal Headers Size=%d\n", filehead->f_size);
}
void
read_syment(SYMBOL_ENTRY *syment, FILE *f)
{
fread(&syment->e_sect_idx, sizeof(syment->e_sect_idx), 1, f);
fread(&syment->e_sect_off, sizeof(syment->e_sect_off), 1, f);
fread(&syment->e_name_off, sizeof(syment->e_name_off), 1, f);
fread(&syment->e_flags, sizeof(syment->e_flags), 1, f);
}
const char *
get_syment_name(const SYMBOL_ENTRY *syment, FILE *f)
{
static char symname[256];
long oldpos = ftell(f);
fseek(f, syment->e_name_off, SEEK_SET);
fread(symname, 256, 1, f);
symname[255] = '\0';
fseek(f, oldpos, SEEK_SET);
return symname;
}
const char *
get_sym_name(u32 idx, FILE *f, size_t symtab_off)
{
SYMBOL_ENTRY syment;
long oldpos = ftell(f);
fseek(f, symtab_off+idx*SYMBOL_ENTRY_SIZE, SEEK_SET);
read_syment(&syment, f);
fseek(f, oldpos, SEEK_SET);
return get_syment_name(&syment, f);
}
const char *
get_sect_name(u32 idx, FILE *f, size_t symtab_off, size_t secttab_off)
{
SECTION_HEADER secthead;
long oldpos = ftell(f);
fseek(f, secttab_off+idx*SECTION_HEADER_SIZE, SEEK_SET);
fread(&secthead.s_name_idx, sizeof(secthead.s_name_idx), 1, f);
fseek(f, oldpos, SEEK_SET);
return get_sym_name(secthead.s_name_idx, f, symtab_off);
}
void
print_symbol(const SYMBOL_ENTRY *syment, FILE *f, size_t symtab_off,
size_t secttab_off)
{
int first = 1;
printf("\tOffset=0x%08X Flags=", syment->e_sect_off);
if (syment->e_flags & XDF_SYM_EXTERN)
printf("%sEXTERN", first-->0?"":"|");
if (syment->e_flags & XDF_SYM_GLOBAL)
printf("%sGLOBAL", first-->0?"":"|");
if (syment->e_flags & XDF_SYM_EQU)
printf("%sEQU", first-->0?"":"|");
if (first>0)
printf("None");
printf(" Name=`%s' Section=", get_syment_name(syment, f));
if (syment->e_sect_idx >= 0x80000000)
printf("%d\n", syment->e_sect_idx);
else
printf("`%s' (%d)\n",
get_sect_name(syment->e_sect_idx, f, symtab_off, secttab_off),
syment->e_sect_idx);
}
void
print_reloc(const RELOCATION_ENTRY *relocent, FILE *f, size_t symtab_off)
{
const char *type = "UNK";
switch (relocent->r_type) {
case XDF_RELOC_REL:
type = "REL";
break;
case XDF_RELOC_WRT:
type = "WRT";
break;
case XDF_RELOC_RIP:
type = "RIP";
break;
case XDF_RELOC_SEG:
type = "SEG";
break;
}
printf("\t Offset=0x%08X Type=%s Size=%d Shift=%d Target=`%s' (%d)",
relocent->r_off, type, relocent->r_size, relocent->r_shift,
get_sym_name(relocent->r_targ_idx, f, symtab_off),
relocent->r_targ_idx);
if (relocent->r_type == XDF_RELOC_WRT)
printf(" Base=`%s' (%d)",
get_sym_name(relocent->r_base_idx, f, symtab_off),
relocent->r_base_idx);
printf("\n");
}
void
print_section(const SECTION_HEADER *secthead, FILE *f, size_t symtab_off)
{
int first = 1;
u32 i;
printf("Section `%s' (section name symtab %d):\n",
get_sym_name(secthead->s_name_idx, f, symtab_off),
secthead->s_name_idx);
printf("\tPhysical Address=0x%016llX\n", secthead->s_addr);
printf("\tVirtual Address=0x%016llX\n", secthead->s_vaddr);
printf("\tAlign=%d\n", secthead->s_align);
printf("\tFlags=");
if (secthead->s_flags & XDF_SECT_ABSOLUTE)
printf("%sABSOLUTE", first-->0?"":"|");
if (secthead->s_flags & XDF_SECT_FLAT)
printf("%sFLAT", first-->0?"":"|");
if (secthead->s_flags & XDF_SECT_BSS)
printf("%sBSS", first-->0?"":"|");
if (secthead->s_flags & XDF_SECT_USE_16)
printf("%sUSE16", first-->0?"":"|");
if (secthead->s_flags & XDF_SECT_USE_32)
printf("%sUSE32", first-->0?"":"|");
if (secthead->s_flags & XDF_SECT_USE_64)
printf("%sUSE64", first-->0?"":"|");
if (first>0)
printf("None");
printf("\n\tData Offset=0x%08X\n", secthead->s_data_off);
printf("\tData Size=%d\n", secthead->s_data_size);
if (!(secthead->s_flags & XDF_SECT_BSS) && secthead->s_data_size > 0) {
printf("\tSection Data:");
long oldpos = ftell(f);
fseek(f, secthead->s_data_off, SEEK_SET);
for (i=0; i<secthead->s_data_size; i++) {
if (i % 16 == 0)
printf("\n\t\t%08X:", i);
if (i % 2 == 0)
printf(" ");
printf("%02X", fgetc(f));
}
printf("\n");
fseek(f, oldpos, SEEK_SET);
}
printf("\tReloc Table Offset=0x%08X\n", secthead->s_reltab_off);
printf("\tNum Relocs=%d\n", secthead->s_num_reloc);
if (secthead->s_num_reloc > 0) {
printf("\tRelocations:\n");
long oldpos = ftell(f);
fseek(f, secthead->s_reltab_off, SEEK_SET);
for (i=0; i<secthead->s_num_reloc; i++) {
RELOCATION_ENTRY relocent;
fread(&relocent, sizeof(relocent), 1, f);
print_reloc(&relocent, f, symtab_off);
}
fseek(f, oldpos, SEEK_SET);
}
}
int
main(int argc, char **argv)
{
FILE *f;
FILE_HEADER filehead;
size_t symtab_off;
u32 i;
if (argc != 2) {
fprintf(stderr, "Usage: %s <xdf>\n", argv[0]);
return EXIT_FAILURE;
}
f = fopen(argv[1], "rb");
if (!f) {
fprintf(stderr, "Could not open `%s'\n", argv[1]);
return EXIT_FAILURE;
}
fread(&filehead.f_magic, sizeof(filehead.f_magic), 1, f);
fread(&filehead.f_nsect, sizeof(filehead.f_nsect), 1, f);
fread(&filehead.f_nsyms, sizeof(filehead.f_nsyms), 1, f);
fread(&filehead.f_size, sizeof(filehead.f_size), 1, f);
if (filehead.f_magic != XDF_MAGIC) {
fprintf(stderr, "Magic number mismatch (expected %08X, got %08X\n",
XDF_MAGIC, filehead.f_magic);
return EXIT_FAILURE;
}
print_file_header(&filehead);
symtab_off = FILE_HEADER_SIZE+filehead.f_nsect*SECTION_HEADER_SIZE;
for (i=0; i<filehead.f_nsect; i++) {
SECTION_HEADER secthead;
fread(&secthead.s_name_idx, sizeof(secthead.s_name_idx), 1, f);
fread(&secthead.s_addr, sizeof(secthead.s_addr), 1, f);
fread(&secthead.s_vaddr, sizeof(secthead.s_vaddr), 1, f);
fread(&secthead.s_align, sizeof(secthead.s_align), 1, f);
fread(&secthead.s_flags, sizeof(secthead.s_flags), 1, f);
fread(&secthead.s_data_off, sizeof(secthead.s_data_off), 1, f);
fread(&secthead.s_data_size, sizeof(secthead.s_data_size), 1, f);
fread(&secthead.s_reltab_off, sizeof(secthead.s_reltab_off), 1, f);
fread(&secthead.s_num_reloc, sizeof(secthead.s_num_reloc), 1, f);
print_section(&secthead, f, symtab_off);
}
printf("Symbol Table:\n");
for (i=0; i<filehead.f_nsyms; i++) {
SYMBOL_ENTRY syment;
read_syment(&syment, f);
print_symbol(&syment, f, symtab_off, sizeof(FILE_HEADER));
}
return EXIT_SUCCESS;
}