Ticket #167: elf_with_sfs.diff

File elf_with_sfs.diff, 10.9 kB (added by nneonneo <nneonneo@gmail.com>, 1 year ago)

Patch (using SeekableFieldSet?) to hachoir-parser/hachoir_parser/program/elf.py

  • program/elf.py

    old new  
    55Creation date: 08 may 2006 
    66""" 
    77 
    8 from hachoir_parser import Parser 
    9 from hachoir_core.field import (FieldSet, ParserError, 
    10     UInt8, UInt16, UInt32, Enum, 
    11     String, Bytes) 
    12 from hachoir_core.text_handler import textHandler, hexadecimal 
     8from hachoir_parser import HachoirParser 
     9from hachoir_core.field import (FieldSet, ParserError, RootSeekableFieldSet, 
     10    Bit, PaddingBits, UInt8, UInt16, UInt32, Enum, 
     11    String, RawBytes, Bytes) 
     12from hachoir_core.text_handler import textHandler, hexadecimal, filesizeHandler 
    1313from hachoir_core.endian import LITTLE_ENDIAN, BIG_ENDIAN 
    1414 
    1515class ElfHeader(FieldSet): 
     
    4747        yield Bytes(self, "signature", 4, r'ELF signature ("\x7fELF")') 
    4848        yield Enum(UInt8(self, "class", "Class"), self.CLASS_NAME) 
    4949        yield Enum(UInt8(self, "endian", "Endian"), self.ENDIAN_NAME) 
    50         yield UInt8(self, "file_version", "File version") 
    51         yield String(self, "pad", 8, "Pad") 
    52         yield UInt8(self, "nb_ident", "Size of ident[]") 
     50        yield UInt8(self, "file_version", "File version (1)") 
     51        yield String(self, "pad", 9, "Pad") 
    5352        yield Enum(UInt16(self, "type", "File type"), self.TYPE_NAME) 
    5453        yield Enum(UInt16(self, "machine", "Machine type"), self.MACHINE_NAME) 
    55         yield UInt32(self, "version", "ELF format version") 
    56         yield UInt32(self, "entry", "Number of entries"
     54        yield UInt32(self, "version", "ELF format version (1)") 
     55        yield textHandler(UInt32(self, "entry", "Virtual address to entry point"), hexadecimal
    5756        yield UInt32(self, "phoff", "Program header offset") 
    5857        yield UInt32(self, "shoff", "Section header offset") 
    5958        yield UInt32(self, "flags", "Flags") 
     
    6160        yield UInt16(self, "phentsize", "Program header entry size") 
    6261        yield UInt16(self, "phnum", "Program header entry count") 
    6362        yield UInt16(self, "shentsize", "Section header entry size") 
    64         yield UInt16(self, "shnum", "Section header entre count") 
    65         yield UInt16(self, "shstrndx", "Section header strtab index") 
     63        yield UInt16(self, "shnum", "Section header entry count") 
     64        yield UInt16(self, "shstrndx", "Section header string table index") 
    6665 
    67     def isValid(self): 
     66    def validate(self): 
    6867        if self["signature"].value != "\x7FELF": 
    6968            return "Wrong ELF signature" 
    7069        if self["class"].value not in self.CLASS_NAME: 
    7170            return "Unknown class" 
    7271        if self["endian"].value not in self.ENDIAN_NAME: 
    7372            return "Unknown endian (%s)" % self["endian"].value 
    74         return "" 
     73        return True 
    7574 
     75class SectionHeader32Flags(UInt32): 
     76    def createDescription(self): 
     77        val = self.value 
     78        desc = [] 
     79        if val & 0x1: 
     80            desc.append("Writable") 
     81        else: 
     82            desc.append("Not writable") 
     83        if val & 0x2: 
     84            desc.append("In memory") 
     85        else: 
     86            desc.append("Not in memory") 
     87        if val & 0x4: 
     88            desc.append("Executable") 
     89        else: 
     90            desc.append("Not executable") 
     91        if val & 0xFFFFFFF8: 
     92            desc.append("Extra: %08X" % (val & 0xFFFFFFF8)) 
     93        return ", ".join(desc) 
     94 
    7695class SectionHeader32(FieldSet): 
    7796    static_size = 40*8 
    78     TYPE_NAME = { 
    79         8: "BSS" 
    80     } 
     97    class TypeNameClass(dict): 
     98        def __getitem__(self, key): 
     99            if dict.__contains__(self, key): 
     100                return dict.__getitem__(self, key) 
     101            if 0x70000000 <= key <= 0x7FFFFFFF: 
     102                return "Processor-specific data (0x%08X)" % key 
     103            elif 0x80000000 <= key <= 0xFFFFFFFF: 
     104                return "Application-specific data (0x%08X)" % key 
     105            else: 
     106                return str(key) 
     107        def __contains__(self, key): 
     108            return dict.__contains__(self, key) or 0x70000000 <= key <= 0xFFFFFFFF 
    81109 
     110    TYPE_NAME = TypeNameClass({ 
     111        0: "Inactive", 
     112        1: "Program bits", 
     113        2: "Symbol table", 
     114        3: "String table", 
     115        4: "Relocation entries (with explicit addends)", 
     116        5: "Symbol hash table", 
     117        6: "Dynamic linking information", 
     118        7: "Note", 
     119        8: "No bits section", 
     120        9: "Relocation entries (without explicit addends)", 
     121        10:"Reserved", 
     122        11:"Dynamic linking symbol table", 
     123        0x60000000: 'SHT_LOOS', 
     124        0x6ffffffb: 'SHT_LOSUNW', 
     125        0x6ffffffc: 'SHT_SUNW_syminfo', 
     126        0x6ffffffd: 'SHT_GNU_verdef', 
     127        0x6ffffffe: 'SHT_GNU_verneed', 
     128        0x6fffffff: 'SHT_GNU_versym', 
     129        0x6fffffff: 'SHT_HISUNW', 
     130        0x6fffffff: 'SHT_HIOS', 
     131    }) 
     132 
    82133    def createFields(self): 
    83         yield UInt32(self, "name", "Name") 
     134        yield UInt32(self, "name_offset", "Name (as an offset into the section header string table)") 
    84135        yield Enum(UInt32(self, "type", "Type"), self.TYPE_NAME) 
    85         yield UInt32(self, "flags", "Flags") 
    86         yield textHandler(UInt32(self, "VMA", "Virtual memory address"), hexadecimal) 
    87         yield textHandler(UInt32(self, "LMA", "Logical memory address (in file)"), hexadecimal) 
    88         yield textHandler(UInt32(self, "size", "Size"), hexadecimal) 
    89         yield UInt32(self, "link", "Link") 
    90         yield UInt32(self, "info", "Information") 
     136        yield SectionHeader32Flags(self, "flags") 
     137        yield textHandler(UInt32(self, "addr", "Address of section in memory"), hexadecimal) 
     138        yield UInt32(self, "offset", "Offset to section from file start") 
     139        yield UInt32(self, "size", "Size") 
     140        link_desc = "Link (not used for this section type)" 
     141        info_desc = "Info (not used for this section type)" 
     142        if self["type"].value == 5: # hash table 
     143            link_desc = "Link (section header index of the symbol table to which this hash table applies)" 
     144        elif self["type"].value == 6: # dynamic linking info 
     145            link_desc = "Link (section header index of the string table used by the entries in this section)" 
     146        elif self["type"].value in (4, 9): # relocation entries 
     147            link_desc = "Link (section header index of the associated symbol table)" 
     148            info_desc = "Info (section header index of the section to which the relocation applies)" 
     149        elif self["type"].value in (2, 11): # symbol tables 
     150            link_desc = "Link (section header index of the associated string table)" 
     151            info_desc = "Info (symbol table index of the last local symbol, plus one)" 
     152        yield UInt32(self, "link", link_desc) 
     153        yield UInt32(self, "info", info_desc) 
    91154        yield UInt32(self, "addr_align", "Address alignment") 
    92         yield UInt32(self, "entry_size", "Entry size") 
     155        yield UInt32(self, "entry_size", "Size of each entry (if this section is a table of fixed-size entries)") 
    93156 
    94157    def createDescription(self): 
     158        offset = self["/section[%s]"%self["/header/shstrndx"].value].address + (self["name_offset"].value*8) 
     159        name = "" 
     160        while 1: 
     161            c=self.stream.readBytes(offset, 1) 
     162            if c=="\0": 
     163                break 
     164            offset += 8 
     165            name += c 
     166             
    95167        return "Section header (name: %s, type: %s)" % \ 
    96             (self["name"].value, self["type"].display) 
     168            (name, self["type"].display) 
    97169 
    98170class ProgramHeader32(FieldSet): 
    99171    TYPE_NAME = { 
    100         3: "Dynamic library" 
     172        0: "Unused", 
     173        1: "Loadable segment", 
     174        2: "Dynamic linking information", 
     175        3: "Program interpreter path", 
     176        4: "Auxiliary information (note)", 
     177        5: "Reserved", 
     178        6: "Program header", 
    101179    } 
    102180    static_size = 32*8 
    103181 
    104182    def createFields(self): 
    105         yield Enum(UInt16(self, "type", "Type"), ProgramHeader32.TYPE_NAME) 
    106         yield UInt16(self, "flags", "Flags") 
    107         yield UInt32(self, "offset", "Offset") 
    108         yield textHandler(UInt32(self, "vaddr", "V. address"), hexadecimal) 
    109         yield textHandler(UInt32(self, "paddr", "P. address"), hexadecimal) 
    110         yield UInt32(self, "file_size", "File size") 
    111         yield UInt32(self, "mem_size", "Memory size") 
    112         yield UInt32(self, "align", "Alignment") 
    113         yield UInt32(self, "xxx", "???") 
     183        yield Enum(UInt32(self, "type", "Type"), self.TYPE_NAME) 
     184        yield UInt32(self, "offset", "File offset to segment") 
     185        yield textHandler(UInt32(self, "vaddr", "Virtual address of segment"), hexadecimal) 
     186        yield textHandler(UInt32(self, "paddr", "Physical address of segment"), hexadecimal) 
     187        yield filesizeHandler(UInt32(self, "file_size", "Size of file image of segment")) 
     188        yield UInt32(self, "mem_size", "Size of memory image of segment") 
     189        yield UInt32(self, "flags", "Segment-specific flags") 
     190        yield UInt32(self, "align", "Alignment requirements") 
    114191 
    115192    def createDescription(self): 
    116193        return "Program Header (%s)" % self["type"].display 
     
    131208#                chunk = self.doRead("section[]", "Section", (FormatChunk, "string[0]")) 
    132209#            chunk.description = "ELF section (in file: %s..%s)" % (ofs, ofs+size) 
    133210 
    134 class ElfFile(Parser): 
     211class ElfFile(HachoirParser, RootSeekableFieldSet): 
    135212    PARSER_TAGS = { 
    136213        "id": "elf", 
    137214        "category": "program", 
     
    147224        "description": "ELF Unix/BSD program/library" 
    148225    } 
    149226    endian = LITTLE_ENDIAN 
     227    def __init__(self, stream, **args): 
     228        RootSeekableFieldSet.__init__(self, None, "root", stream, None, stream.askSize(self)) 
     229        HachoirParser.__init__(self, stream, **args) 
    150230 
    151231    def validate(self): 
    152         err = self["header"].isValid() 
    153         if err: 
    154             return err 
    155         return True 
     232        return self["header"].validate() 
    156233 
    157234    def createFields(self): 
    158235        # Choose the right endian depending on endian specified in header 
     
    174251            #chunk.description = "Sections (use an evil hack to manage share same data on differents parts)" 
    175252            #assert self.current_size//8 == self["header/shoff"].value 
    176253        else: 
    177             raw = self.seekByte(self["header/shoff"].value, "raw[]", relative=False) 
     254            raw = self.seekByte(self["header/shoff"].value)#, "raw[]", relative=False) 
    178255            if raw: 
    179256                yield raw 
    180257 
     258        position = self["header/shoff"].value 
     259 
    181260        for index in xrange(self["header/shnum"].value): 
    182             yield SectionHeader32(self, "section_header[]") 
     261            self.seekByte(position) 
     262            header = SectionHeader32(self, "section_header[]") 
     263            yield header 
     264            position += header.size // 8 
     265            if header["type"].value != 8 and header["size"].value: 
     266                self.seekByte(header["offset"].value) 
     267                yield RawBytes(self, "section[%i]"%index, header["size"].value) 
    183268 
    184269    def createDescription(self): 
    185270        return "ELF Unix/BSD program/library: %s" % (