Home | History | Annotate | Download | only in Ds5
      1 #

      2 #  Copyright (c) 2011-2013, ARM Limited. All rights reserved.

      3 #

      4 #  This program and the accompanying materials

      5 #  are licensed and made available under the terms and conditions of the BSD License

      6 #  which accompanies this distribution.  The full text of the license may be found at

      7 #  http://opensource.org/licenses/bsd-license.php

      8 #

      9 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     10 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     11 #

     12 
     13 from arm_ds.debugger_v1 import DebugException
     14 
     15 import struct
     16 import string
     17 
     18 import edk2_debugger
     19 
     20 class EfiFileSection(object):
     21     EFI_SECTION_PE32                  = 0x10
     22     EFI_SECTION_PIC                   = 0x11
     23     EFI_SECTION_TE                    = 0x12
     24 
     25     EFI_IMAGE_DEBUG_TYPE_CODEVIEW     = 0x2
     26 
     27     SIZEOF_EFI_FFS_FILE_HEADER        = 0x28
     28 
     29     def __init__(self, ec, base):
     30         self.base = base
     31         self.ec = ec
     32 
     33     def __str__(self):
     34         return "FileSection(type:0x%X, size:0x%x)" % (self.get_type(), self.get_size())
     35 
     36     def get_base(self):
     37         return self.base
     38 
     39     def get_type(self):
     40         return struct.unpack("B", self.ec.getMemoryService().read(self.base + 0x3, 1, 8))[0]
     41 
     42     def get_size(self):
     43         return (struct.unpack("<I", self.ec.getMemoryService().read(self.base, 4, 32))[0] & 0x00ffffff)
     44 
     45     def get_debug_filepath(self):
     46         type = self.get_type()
     47         if type == EfiFileSection.EFI_SECTION_TE:
     48             section = EfiSectionTE(self, ec, self.base + 0x4)
     49         elif type == EfiFileSection.EFI_SECTION_PE32:
     50             section = EfiSectionPE32(self, ec, self.base + 0x4)
     51         else:
     52             raise Exception("EfiFileSection", "No debug section")
     53         return section.get_debug_filepath()
     54 
     55 class EfiSectionTE:
     56     SIZEOF_EFI_TE_IMAGE_HEADER        = 0x28
     57     EFI_TE_IMAGE_SIGNATURE            = ('V','Z')
     58 
     59     def __init__(self, ec, base_te):
     60         self.ec = ec
     61         self.base_te = int(base_te)
     62         te_sig = struct.unpack("cc", self.ec.getMemoryService().read(self.base_te, 2, 32))
     63         if te_sig != EfiSectionTE.EFI_TE_IMAGE_SIGNATURE:
     64             raise Exception("EfiFileSectionTE","TE Signature incorrect")
     65 
     66     def get_debug_filepath(self):
     67         stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
     68         stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
     69 
     70         debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_te + 0x20)
     71         if debug_dir_entry_rva == 0:
     72             raise Exception("EfiFileSectionTE","No debug directory for image")
     73         debug_dir_entry_rva -= stripped_size
     74 
     75         debug_type = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0xC)
     76         if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
     77             raise Exception("EfiFileSectionTE","Debug type is not dwarf")
     78 
     79         debug_rva = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0x14)
     80         debug_rva -= stripped_size
     81 
     82         dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(self.base_te + debug_rva, 4, 32))
     83         if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
     84             raise Exception("EfiFileSectionTE","Dwarf debug signature not found")
     85 
     86         if dwarf_sig == 0x66727764:
     87             filename = self.base_te + debug_rva + 0xc
     88         else:
     89             filename = self.base_te + debug_rva + 0x10
     90         filename = struct.unpack("200s", self.ec.getMemoryService().read(filename, 200, 32))[0]
     91         return filename[0:string.find(filename,'\0')]
     92 
     93     def get_debug_elfbase(self):
     94         stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
     95         stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
     96 
     97         return self.base_te - stripped_size
     98 
     99 class EfiSectionPE32:
    100     def __init__(self, ec, base_pe32):
    101         self.ec = ec
    102         self.base_pe32 = base_pe32
    103 
    104     def get_debug_filepath(self):
    105         # Offset from dos hdr to PE file hdr

    106         file_header_offset = self.ec.getMemoryService().readMemory32(self.base_pe32 + 0x3C)
    107 
    108         # Offset to debug dir in PE hdrs

    109         debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + file_header_offset + 0xA8)
    110         if debug_dir_entry_rva == 0:
    111             raise Exception("EfiFileSectionPE32","No Debug Directory")
    112 
    113         debug_type = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0xC)
    114         if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
    115             raise Exception("EfiFileSectionPE32","Debug type is not dwarf")
    116 
    117 
    118         debug_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0x14)
    119 
    120         dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(str(self.base_pe32 + debug_rva), 4, 32))
    121         if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
    122             raise Exception("EfiFileSectionPE32","Dwarf debug signature not found")
    123 
    124         if dwarf_sig == 0x66727764:
    125             filename = self.base_pe32 + debug_rva + 0xc
    126         else:
    127             filename = self.base_pe32 + debug_rva + 0x10
    128         filename = struct.unpack("200s", self.ec.getMemoryService().read(str(filename), 200, 32))[0]
    129         return filename[0:string.find(filename,'\0')]
    130 
    131     def get_debug_elfbase(self):
    132         return self.base_pe32
    133 
    134 class EfiSectionPE64:
    135     def __init__(self, ec, base_pe64):
    136         self.ec = ec
    137         self.base_pe64 = base_pe64
    138 
    139     def get_debug_filepath(self):
    140         # Offset from dos hdr to PE file hdr (EFI_IMAGE_NT_HEADERS64)

    141         #file_header_offset = self.ec.getMemoryService().readMemory32(self.base_pe64 + 0x3C)

    142         file_header_offset = 0x0
    143 
    144         # Offset to debug dir in PE hdrs

    145         debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_pe64 + file_header_offset + 0x138)
    146         if debug_dir_entry_rva == 0:
    147             raise Exception("EfiFileSectionPE64","No Debug Directory")
    148 
    149         debug_type = self.ec.getMemoryService().readMemory32(self.base_pe64 + debug_dir_entry_rva + 0xC)
    150         if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
    151             raise Exception("EfiFileSectionPE64","Debug type is not dwarf")
    152 
    153 
    154         debug_rva = self.ec.getMemoryService().readMemory32(self.base_pe64 + debug_dir_entry_rva + 0x14)
    155 
    156         dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(str(self.base_pe64 + debug_rva), 4, 32))
    157         if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
    158             raise Exception("EfiFileSectionPE64","Dwarf debug signature not found")
    159 
    160         if dwarf_sig == 0x66727764:
    161             filename = self.base_pe64 + debug_rva + 0xc
    162         else:
    163             filename = self.base_pe64 + debug_rva + 0x10
    164         filename = struct.unpack("200s", self.ec.getMemoryService().read(str(filename), 200, 32))[0]
    165         return filename[0:string.find(filename,'\0')]
    166 
    167     def get_debug_elfbase(self):
    168         return self.base_pe64
    169 
    170 class FirmwareFile:
    171     EFI_FV_FILETYPE_RAW                   = 0x01
    172     EFI_FV_FILETYPE_FREEFORM              = 0x02
    173     EFI_FV_FILETYPE_SECURITY_CORE         = 0x03
    174     EFI_FV_FILETYPE_PEI_CORE              = 0x04
    175     EFI_FV_FILETYPE_DXE_CORE              = 0x05
    176     EFI_FV_FILETYPE_PEIM                  = 0x06
    177     EFI_FV_FILETYPE_DRIVER                = 0x07
    178     EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER  = 0x08
    179     EFI_FV_FILETYPE_APPLICATION           = 0x09
    180     EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B
    181     EFI_FV_FILETYPE_FFS_MIN               = 0xF0
    182 
    183     CONST_NB10_SIGNATURE = ('N','B','1','0')
    184 
    185     def __init__(self, fv, base, ec):
    186         self.fv = fv
    187         self.base = base
    188         self.ec = ec
    189 
    190     def __str__(self):
    191         return "FFS(state:0x%x, type:0x%X, size:0x%x)" % (self.get_state(), self.get_type(), self.get_size())
    192 
    193     def get_base(self):
    194         return self.base
    195 
    196     def get_size(self):
    197         size = (self.ec.getMemoryService().readMemory32(self.base + 0x14) & 0x00ffffff)
    198 
    199         # Occupied size is the size considering the alignment

    200         return size + ((0x8 - (size & 0x7)) & 0x7)
    201 
    202     def get_type(self):
    203         return self.ec.getMemoryService().readMemory8(self.base + 0x12)
    204 
    205     def get_state(self):
    206         state = self.ec.getMemoryService().readMemory8(self.base + 0x17)
    207 
    208         polarity = self.fv.get_polarity()
    209         if polarity:
    210             state = ~state
    211 
    212         highest_bit = 0x80;
    213         while (highest_bit != 0) and ((highest_bit & state) == 0):
    214             highest_bit >>= 1
    215 
    216         return highest_bit
    217 
    218     def get_next_section(self, section=None):
    219         if section == None:
    220             if self.get_type() != FirmwareFile.EFI_FV_FILETYPE_FFS_MIN:
    221                 section_base = self.get_base() + 0x18;
    222             else:
    223                 return None
    224         else:
    225             section_base = int(section.get_base() + section.get_size())
    226 
    227             # Align to next 4 byte boundary

    228             if (section_base & 0x3) != 0:
    229                 section_base = section_base + 0x4 - (section_base & 0x3)
    230 
    231         if section_base < self.get_base() + self.get_size():
    232             return EfiFileSection(self.ec, section_base)
    233         else:
    234             return None
    235 
    236 class FirmwareVolume:
    237     CONST_FV_SIGNATURE = ('_','F','V','H')
    238     EFI_FVB2_ERASE_POLARITY = 0x800
    239 
    240     DebugInfos = []
    241 
    242     def __init__(self, ec, fv_base, fv_size):
    243         self.ec = ec
    244         self.fv_base = fv_base
    245         self.fv_size = fv_size
    246 
    247         try:
    248             signature = struct.unpack("cccc", self.ec.getMemoryService().read(fv_base + 0x28, 4, 32))
    249         except DebugException:
    250             raise Exception("FirmwareVolume", "Not possible to access the defined firmware volume at [0x%X,0x%X]. Could be the used build report does not correspond to your current debugging context." % (int(fv_base),int(fv_base+fv_size)))
    251         if signature != FirmwareVolume.CONST_FV_SIGNATURE:
    252             raise Exception("FirmwareVolume", "This is not a valid firmware volume")
    253 
    254     def get_size(self):
    255         return self.ec.getMemoryService().readMemory32(self.fv_base + 0x20)
    256 
    257     def get_attributes(self):
    258         return self.ec.getMemoryService().readMemory32(self.fv_base + 0x2C)
    259 
    260     def get_polarity(self):
    261         attributes = self.get_attributes()
    262         if attributes & FirmwareVolume.EFI_FVB2_ERASE_POLARITY:
    263             return 1
    264         else:
    265             return 0
    266 
    267     def get_next_ffs(self, ffs=None):
    268         if ffs == None:
    269             # Get the offset of the first FFS file from the FV header

    270             ffs_base = self.fv_base +  self.ec.getMemoryService().readMemory16(self.fv_base + 0x30)
    271         else:
    272             # Goto the next FFS file

    273             ffs_base = int(ffs.get_base() + ffs.get_size())
    274 
    275             # Align to next 8 byte boundary

    276             if (ffs_base & 0x7) != 0:
    277                 ffs_base = ffs_base + 0x8 - (ffs_base & 0x7)
    278 
    279         if ffs_base < self.fv_base + self.get_size():
    280             return FirmwareFile(self, ffs_base, self.ec)
    281         else:
    282             return None
    283 
    284     def get_debug_info(self):
    285         self.DebugInfos = []
    286 
    287         ffs = self.get_next_ffs()
    288         while ffs != None:
    289             section = ffs.get_next_section()
    290             while section != None:
    291                 type = section.get_type()
    292                 if (type == EfiFileSection.EFI_SECTION_TE) or (type == EfiFileSection.EFI_SECTION_PE32):
    293                     self.DebugInfos.append((section.get_base(), section.get_size(), section.get_type()))
    294                 section = ffs.get_next_section(section)
    295             ffs = self.get_next_ffs(ffs)
    296 
    297     def load_symbols_at(self, addr, verbose = False):
    298         if self.DebugInfos == []:
    299             self.get_debug_info()
    300 
    301         for debug_info in self.DebugInfos:
    302             if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
    303                 if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
    304                     section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
    305                 elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
    306                     section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
    307                 else:
    308                     raise Exception('FirmwareVolume','Section Type not supported')
    309 
    310                 try:
    311                     edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
    312                 except Exception, (ErrorClass, ErrorMessage):
    313                     if verbose:
    314                         print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
    315 
    316                 return debug_info
    317 
    318     def load_all_symbols(self, verbose = False):
    319         if self.DebugInfos == []:
    320             self.get_debug_info()
    321 
    322         for debug_info in self.DebugInfos:
    323             if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
    324                 section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
    325             elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
    326                 section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
    327             else:
    328                 continue
    329 
    330             try:
    331                 edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
    332             except Exception, (ErrorClass, ErrorMessage):
    333                 if verbose:
    334                     print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
    335 
    336