/* This file is part of centaur.
*
* centaur is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as
* published by the Free Software Foundation.
* centaur is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with centaur. If not, see .
*/
#include
#include
static char* segmentTypeStr(Elf32_Word p_type)
{
switch(p_type) {
case PT_NULL: /* 0 */
return "NULL";
case PT_LOAD: /* 1 */
return "LOAD";
case PT_DYNAMIC: /* 2 */
return "DYNAMIC";
case PT_INTERP: /* 3 */
return "INTERP";
case PT_NOTE: /* 4 */
return "NOTE";
case PT_SHLIB: /* 5 */
return "SHLIB";
case PT_PHDR: /* 6 */
return "PHDR";
case PT_TLS: /* 7 */
return "TLS";
case PT_NUM: /* 8 */
return "NUM";
case PT_GNU_EH_FRAME: /* 0x6474e550 */
return "GNU_EH_FRAME";
case PT_GNU_STACK: /* 0x6474e551 */
return "GNU_STACK";
case PT_GNU_RELRO: /* 0x6474e552 */
return "GNU_RELRO";
}
return "-?-";
}
static char* sectionTypeStr(Elf32_Word sh_type)
{
switch(sh_type) {
case SHT_NULL: /* 0 */
return "NULL";
case SHT_PROGBITS: /* 1 */
return "PROGBITS";
case SHT_SYMTAB: /* 2 */
return "SYMTAB";
case SHT_STRTAB: /* 3 */
return "STRTAB";
case SHT_RELA: /* 4 */
return "RELA";
case SHT_HASH: /* 5 */
return "HASH";
case SHT_DYNAMIC: /* 6 */
return "DYNAMIC";
case SHT_NOTE: /* 7 */
return "NOTE";
case SHT_NOBITS: /* 8 */
return "NOBITS";
case SHT_REL: /* 9 */
return "REL";
case SHT_SHLIB: /* 10 */
return "SHLIB";
case SHT_DYNSYM: /* 11 */
return "DYNSYM";
case SHT_INIT_ARRAY: /* 14 */
return "INIT_ARRAY";
case SHT_FINI_ARRAY: /* 15 */
return "FINI_ARRAY";
case SHT_PREINIT_ARRAY: /* 16 */
return "PREINIT_ARRAY";
case SHT_GROUP: /* 17 */
return "SHT_GROUP";
case SHT_SYMTAB_SHNDX: /* 18 */
return "SYMTAB_SHNDX";
case SHT_NUM: /* 19 */
return "NUM";
case SHT_GNU_ATTRIBUTES: /* 0x6ffffff5 */
return "GNU_ATTRIBUTES";
case SHT_GNU_HASH: /* 0x6ffffff6 */
return "GNU_HASH";
case SHT_GNU_LIBLIST: /* 0x6ffffff7 */
return "GNU_LIBLIST";
case SHT_GNU_verdef: /* 0x6ffffffd */
return "GNU_verdef";
case SHT_GNU_verneed: /* 0x6ffffffe */
return "GNU_verneed";
case SHT_GNU_versym: /* 0x6fffffff */
return "GNU_versym";
}
return "-?-";
}
void elfu_mDumpPhdr(ElfuElf *me, ElfuPhdr *mp)
{
assert(me);
assert(mp);
ELFU_INFO("%12s %8x %8x %8x %8x %8x %8x %8x %8x\n",
segmentTypeStr(mp->phdr.p_type),
(unsigned)mp->phdr.p_type,
(unsigned)mp->phdr.p_offset,
(unsigned)mp->phdr.p_vaddr,
(unsigned)mp->phdr.p_paddr,
(unsigned)mp->phdr.p_filesz,
(unsigned)mp->phdr.p_memsz,
(unsigned)mp->phdr.p_flags,
(unsigned)mp->phdr.p_align);
if (!CIRCLEQ_EMPTY(&mp->childPhdrList)) {
ElfuPhdr *mpc;
ELFU_INFO(" -> Child PHDRs:\n");
CIRCLEQ_FOREACH(mpc, &mp->childPhdrList, elemChildPhdr) {
ELFU_INFO(" * %-8s @ %8x\n",
segmentTypeStr(mpc->phdr.p_type),
(unsigned)mpc->phdr.p_vaddr);
}
}
if (!CIRCLEQ_EMPTY(&mp->childScnList)) {
ElfuScn *msc;
ELFU_INFO(" -> Child sections:\n");
CIRCLEQ_FOREACH(msc, &mp->childScnList, elemChildScn) {
ELFU_INFO(" * %-17s @ %8x\n",
elfu_mScnName(me, msc),
(unsigned)msc->shdr.sh_addr);
}
}
}
void elfu_mDumpScn(ElfuElf *me, ElfuScn *ms)
{
char *namestr, *typestr, *linkstr, *infostr;
assert(me);
assert(ms);
namestr = elfu_mScnName(me, ms);
typestr = sectionTypeStr(ms->shdr.sh_type);
linkstr = ms->linkptr ? elfu_mScnName(me, ms->linkptr) : "";
infostr = ms->infoptr ? elfu_mScnName(me, ms->infoptr) : "";
ELFU_INFO("%-17s %-15s %8x %9x %8x %2x %2x %2d %-17s %-17s\n",
namestr,
typestr,
(unsigned)ms->shdr.sh_addr,
(unsigned)ms->shdr.sh_offset,
(unsigned)ms->shdr.sh_size,
(unsigned)ms->shdr.sh_entsize,
(unsigned)ms->shdr.sh_flags,
(unsigned)ms->shdr.sh_addralign,
linkstr,
infostr);
}
void elfu_mDumpEhdr(ElfuElf *me)
{
assert(me);
ELFU_INFO("ELF header:\n");
ELFU_INFO(" %d-bit ELF object\n", me->elfclass == ELFCLASS32 ? 32 : 64);
ELFU_INFO(" EHDR:\n");
ELFU_INFO(" e_type %8x\n", me->ehdr.e_type);
ELFU_INFO(" e_machine %8x\n", me->ehdr.e_machine);
ELFU_INFO(" e_version %8x\n", me->ehdr.e_version);
ELFU_INFO(" e_entry %8x\n", (unsigned)me->ehdr.e_entry);
ELFU_INFO(" e_phoff %8x\n", (unsigned)me->ehdr.e_phoff);
ELFU_INFO(" e_shoff %8x\n", (unsigned)me->ehdr.e_shoff);
ELFU_INFO(" e_flags %8x\n", me->ehdr.e_flags);
ELFU_INFO(" e_ehsize %8x\n", me->ehdr.e_ehsize);
ELFU_INFO(" e_phentsize %8x\n", me->ehdr.e_phentsize);
ELFU_INFO(" e_shentsize %8x\n", me->ehdr.e_shentsize);
ELFU_INFO(" shstrtab: %s\n", me->shstrtab ? elfu_mScnName(me, me->shstrtab) : "(none)");
}
static void* subScnDump(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
{
(void) aux1;
(void) aux2;
printf(" [%4d] ", elfu_mScnIndex(me, ms));
elfu_mDumpScn(me, ms);
return NULL;
}
void elfu_mDumpElf(ElfuElf *me)
{
ElfuPhdr *mp;
ElfuScn *ms;
size_t i;
assert(me);
elfu_mDumpEhdr(me);
ELFU_INFO("\n");
ELFU_INFO("Segments:\n");
ELFU_INFO(" # (type) p_type p_offset p_vaddr p_paddr p_filesz p_memsz p_flags p_align\n");
ELFU_INFO(" | | | | | | | | | \n");
i = 0;
CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
printf(" [%4d] ", i);
elfu_mDumpPhdr(me, mp);
i++;
}
ELFU_INFO("\n");
ELFU_INFO("Orphaned sections:\n");
CIRCLEQ_FOREACH(ms, &me->orphanScnList, elemChildScn) {
ELFU_INFO(" * %-17s @ %8x offset %8x size %8x\n",
elfu_mScnName(me, ms),
(unsigned)ms->shdr.sh_addr,
(unsigned)ms->shdr.sh_offset,
(unsigned)ms->shdr.sh_size);
}
ELFU_INFO("\n");
ELFU_INFO("Sections:\n");
ELFU_INFO(" # Name sh_type sh_addr sh_offset sh_size ES Fl Al sh_link sh_info \n");
ELFU_INFO(" | | | | | | | | | | \n");
elfu_mScnForall(me, subScnDump, &i, NULL);
ELFU_INFO("\n");
}