#!/usr/bin/env python # # ORIGINAL AUTHOR, COPYRIGHT and LICENSE # # Copyright (c) 2003-2010 Chris Liechti # All Rights Reserved. # Simplified BSD License (see LICENSE.txt for full text) # # # MODIFICATIONS # # Copyright (c) 2014 Freescale Semiconductor, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # o Redistributions of source code must retain the above copyright notice, this list # of conditions and the following disclaimer. # # o 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. # # o Neither the name of Freescale Semiconductor, Inc. nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 COPYRIGHT HOLDER OR 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. """\ ELF object file reader. """ import struct # size alignment # Elf32_Addr 4 4 Unsigned program address # Elf32_Half 2 2 Unsigned medium integer # Elf32_Off 4 4 Unsigned file offset # Elf32_Sword 4 4 Signed large integer # Elf32_Word 4 4 Unsigned large integer # unsignedchar 1 1 Unsigned small integer #define EI_NIDENT 16 #~ typedef struct{ #~ unsigned char e_ident[EI_NIDENT]; #~ Elf32_Half e_type; #~ Elf32_Half e_machine; #~ Elf32_Word e_version; #~ Elf32_Addr e_entry; #~ Elf32_Off e_phoff; #~ Elf32_Off e_shoff; #~ Elf32_Word e_flags; #~ Elf32_Half e_ehsize; #~ Elf32_Half e_phentsize; #~ Elf32_Half e_phnum; #~ Elf32_Half e_shentsize; #~ Elf32_Half e_shnum; #~ Elf32_Half e_shstrndx; #~ } Elf32_Ehdr; #Section Header #~ typedef struct { #~ Elf32_Word sh_name; #~ Elf32_Word sh_type; #~ Elf32_Word sh_flags; #~ Elf32_Addr sh_addr; #~ Elf32_Off sh_offset; #~ Elf32_Word sh_size; #~ Elf32_Word sh_link; #~ Elf32_Word sh_info; #~ Elf32_Word sh_addralign; #~ Elf32_Word sh_entsize; #~ } Elf32_Shdr; #~ typedef struct { #~ Elf32_Word p_type; #~ Elf32_Off p_offset; #~ Elf32_Addr p_vaddr; #~ Elf32_Addr p_paddr; #~ Elf32_Word p_filesz; #~ Elf32_Word p_memsz; #~ Elf32_Word p_flags; #~ Elf32_Word p_align; #~ } Elf32_Phdr; # struct Elf32_Sym # { # Elf32_Word st_name; //!< Index into file's string table. # Elf32_Addr st_value; //!< Value associated with the symbol. Depends on context. # Elf32_Word st_size; //!< Size associated with symbol. 0 if the symbol has no size or an unknown size. # unsigned char st_info; //!< Specified the symbol's type and binding attributes. # unsigned char st_other; //!< Currently 0 (reserved). # Elf32_Half st_shndx; //!< Section header table index for this symbol. # }; class ELFException(Exception): pass class ELFSymbol: Elf32_Sym = "> 4) & 0x0f self.st_type = self.st_info & 0x0f def __repr__(self): return "%s(%s, st_value=0x%08x, st_size=%d, st_bind=%d, st_type=%d, st_shndx=%d)" % ( self.__class__.__name__, self.name is not None and "%r" % self.name or "st_name=%s" % self.st_name, self.st_value, self.st_size, self.st_bind, self.st_type, self.st_shndx) class ELFSection: """read and store a section""" Elf32_Shdr = "= section.sh_addr + section.sh_size) \ and (not (section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS) \ or (p.p_offset <= section.sh_offset \ and (p.p_offset + p.p_filesz >= section.sh_offset + section.sh_size)))): return section.sh_addr + p.p_paddr - p.p_vaddr return section.sh_addr def getSections(self): """get sections relevant for the application""" res = [] for section in self.sections: if section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS: res.append(section) return res def __repr__(self): """pretty print for debug...""" return "%s(self.e_type=%r, self.e_machine=%r, self.e_version=%r, sections=%r)" % ( self.__class__.__name__, self.e_type, self.e_machine, self.e_version, [section.name for section in self.sections]) if __name__ == '__main__': print "This is only a module test!" elf = ELFObject() elf.fromFile(open("test.elf")) if elf.e_type != ELFObject.ET_EXEC: raise Exception("No executable") print elf #~ print repr(elf.getSection('.text').data) #~ print [(s.name, hex(s.sh_addr)) for s in elf.getSections()] print "-"*20 for p in elf.sections: print p print "-"*20 for p in elf.getSections(): print p print "-"*20 for p in elf.getProgrammableSections(): print p