Example #1
0
    def _get_heap_config_str(self, processor_number):
        """
        @brief Returns the string representation of the heap configuration .
            In other words is the to string function for processor
            configuration.
        @param[in] self Pointer to the current object
        @param[in] processor_number
        @param[out] processor configuration string.
        """
        return_str = ""
        total_size = 0
        for heap_num in range(self.max_num_heaps):
            (available, heap_size, heap_start, heap_end) = \
                self._get_heap_config(processor_number, heap_num)

            if available:
                return_str += "%-15s : " % self.heap_names[heap_num]
                return_str += "%s at 0x%08x - 0x%08x\n" % (
                    cu.mem_size_to_string(heap_size),
                    heap_start,
                    heap_end
                )

            total_size += heap_size

        return_str += "%-15s : " % "Total size" + cu.mem_size_to_string(total_size)
        return return_str
Example #2
0
    def get_watermarks(self):
        """Displays the memory statistics.

        Shows the minimum available memory for the total, the free and the
        minimum free memories.
        """
        total_size, current_free, min_free, pools_statistic = \
            self.ret_get_watermarks()

        output_str = ""
        for pool_statistic in pools_statistic:
            output_str += (
                "pools with size %2d words, total size,   %3d blocks\n" %
                (pool_statistic[0], pool_statistic[1][0]))
            output_str += (
                "pools with size %2d words, current free, %3d blocks\n" %
                (pool_statistic[0], pool_statistic[1][1]))
            output_str += (
                "pools with size %2d words, minimum free, %3d blocks\n" %
                (pool_statistic[0], pool_statistic[1][2]))
            output_str += "\n"

        output_str += ("entire pool memory, total size,   " +
                       cu.mem_size_to_string(total_size * Arch.addr_per_word) +
                       "\n")
        output_str += (
            "entire pool memory, current free, " +
            cu.mem_size_to_string(current_free * Arch.addr_per_word) + "\n")
        output_str += ("entire pool memory, minimum free, " +
                       cu.mem_size_to_string(min_free * Arch.addr_per_word) +
                       "\n")
        # use output_raw to keep the spaces.
        self.formatter.output_raw(output_str)
Example #3
0
    def _get_free_space(self):
        """Get total size of free blocks.

            This method reads the free blocks for all heaps and returns a
            string which contains a list with the total size of those free
            blocks.
        """
        # Look up the debug information.
        self._lookup_debuginfo()
        output_str = ""
        total_size = 0
        for heap_num in range(self.max_num_heaps):
            (available, heap_size, heap_start, _, heap_free_start) = \
                self._get_heap_property(heap_num)

            if available:
                free_blocks = self._free_blocks(heap_free_start,
                                                heap_start,
                                                heap_size,
                                                memory_type=self.memory_type)
                # display the heap name
                output_str += "%-15s : " % self.heap_names[heap_num]
                free_block_size = free_blocks.total_size
                if self.pmalloc_debug_enabled:
                    # Two words are used for guard.
                    free_block_size -= 2 * Arch.addr_per_word
                output_str += cu.mem_size_to_string(free_block_size)
                total_size += free_block_size

                output_str += "\n"

        output_str += "%-15s : %s\n" % ("Total size",
                                        cu.mem_size_to_string(total_size))

        return output_str
Example #4
0
    def _get_heap_config_str(self, processor_number):
        """Get string representation of the heap configurations.

            In other words is the to string function for processor
            configuration.

        Args:
            processor_number

        Returns:
            processor configuration string.
        """
        return_str = ""
        total_size = 0
        for heap_num in range(self.max_num_heaps):
            (available, heap_size, heap_start, heap_end) = \
                self._get_heap_config(processor_number, heap_num)

            if available:
                return_str += "%-15s : " % self.heap_names[heap_num]
                return_str += "%s at 0x%08x - 0x%08x\n" % (
                    cu.mem_size_to_string(heap_size), heap_start, heap_end)

            total_size += heap_size

        return_str += "%-15s : %s" % ("Total size",
                                      cu.mem_size_to_string(total_size))

        return return_str
Example #5
0
    def overview(self):
        """
        @brief This method displays an overview of the available heaps.
        @param[in] self Pointer to the current object
        """
        output_str = self._get_overview_str(detailed=True)

        self.formatter.section_start(
            'Heap %s memory usage' % (self.memory_type.upper())
            )
        # use output_raw to keep the spaces.

        # display memory used by patches for PM Heap
        if self.memory_type.upper() == "PM":
            try:
                patch_analysis = self.interpreter.get_analysis("patches", self.chipdata.processor)
                if patch_analysis.get_patch_level() > 0:
                    patch_address_start = self.debuginfo.get_constant_strict(
                        '$PM_RAM_P0_CODE_START'
                    ).value
                    self.formatter.output_raw(
                        "\nPatch size : " +
                        cu.mem_size_to_string(patch_analysis.get_patch_size(), "o") +
                        " at address: 0x{0:0>8x}".format(patch_address_start) + "\n"
                    )
            except KeyError:
                # Patch analysis is not released to customers.
                pass

        self.formatter.output_raw(output_str)
        self.formatter.section_end()
Example #6
0
    def _get_overview_str(self, detailed=True):
        """
        @brief This method returns an overview string of the available heaps.
            This is a helper method.
        @param[in] self Pointer to the current object
        @param[in] detailed If set to True, a detailed view is provided.
        """
        total_heap, free_heap, min_free_heap = self.ret_get_watermarks()

        output_str = ""
        output_str += (
            "%s heap total size :\n" % (self.memory_type.upper())
        )
        if detailed:
            config_str = self._get_heap_config_str(self.chipdata.processor)
            # add indentation for a nicer view.
            output_str += cu.add_indentation(config_str, 2) + "\n"
        else:
            watermark_str = "%-15s : " % "from config"
            watermark_str += cu.mem_size_to_string(total_heap)
            output_str += cu.add_indentation(watermark_str, 2) + "\n"

        output_str += (
            "%s heap current free:\n" % (self.memory_type.upper())
        )
        if detailed:
            free_space_str = self._get_free_space()
            output_str += cu.add_indentation(free_space_str, 2)

        if free_heap != -1:
            watermark_str = "%-15s : " % "from watermarks"
            watermark_str += cu.mem_size_to_string(free_heap)
        else:
            watermark_str = "Watermarks not available for this heap!"
        output_str += cu.add_indentation(watermark_str, 2) + "\n"

        output_str += (
            "%s heap minimum free:\n" % (self.memory_type.upper())
        )

        if min_free_heap != -1:
            watermark_str = "%-15s : " % "from watermarks"
            watermark_str += cu.mem_size_to_string(min_free_heap)
        else:
            watermark_str = "Watermarks not available for this heap!"
        output_str += cu.add_indentation(watermark_str, 2) + "\n"
        return output_str
Example #7
0
    def get_watermarks(self):
        """
        @brief Returns the minimum available memory for the total, the free
        and the minimum free memories.
        @param[in] self Pointer to the current object
        """
        total_heap, free_heap, min_free_heap = self.ret_get_watermarks()

        output_str = ""
        output_str += ("entire heap memory, total size,   " +
                       cu.mem_size_to_string(total_heap) + "\n")
        output_str += ("entire heap memory, current free, " +
                       cu.mem_size_to_string(free_heap) + "\n")
        output_str += ("entire heap memory, minimum free, " +
                       cu.mem_size_to_string(min_free_heap) + "\n")
        # use output_raw to keep the spaces.
        self.formatter.output_raw(output_str)
    def analyse_patch_size(self):
        """Display the memory used by patches."""
        patch_address_start = self.debuginfo.get_constant_strict(
            '$PM_RAM_P0_CODE_START').value

        self.formatter.output(
            "Patch size : " +
            cu.mem_size_to_string(self.get_patch_size(), "o") +
            " at address: 0x{0:0>8x}".format(patch_address_start))
    def get_watermarks(self):
        """
        @brief Same as get_watermarks, but it will return values rather than
        print outs.
        @param[in] self Pointer to the current object
        @param[out] List with the heap usage + pools statistic.
        """
        total_heap, free_heap, min_free_heap = self.ret_get_watermarks()

        output_str = ""
        output_str += ("entire heap memory, total size,   " +
                       cu.mem_size_to_string(total_heap) + "\n")
        output_str += ("entire heap memory, current free, " +
                       cu.mem_size_to_string(free_heap) + "\n")
        output_str += ("entire heap memory, minimum free, " +
                       cu.mem_size_to_string(min_free_heap) + "\n")
        # use output_raw to keep the spaces.
        self.formatter.output_raw(output_str)
Example #10
0
    def _get_overview_str(self, detailed=True):
        """Gets Overview string of the available heaps.

        Args:
            detailed (bool, optional): If set to True, a detailed view is
                provided.
        """
        total_heap, free_heap, min_free_heap = self.ret_get_watermarks()

        output_str = ""
        output_str += ("%s heap total size :\n" % (self.memory_type.upper()))
        if detailed:
            config_str = self._get_heap_config_str(self.chipdata.processor)
            # add indentation for a nicer view.
            output_str += cu.add_indentation(config_str, 2) + "\n"
        else:
            watermark_str = "%-15s : " % "from config"
            watermark_str += cu.mem_size_to_string(total_heap)
            output_str += cu.add_indentation(watermark_str, 2) + "\n"

        output_str += ("%s heap current free:\n" % (self.memory_type.upper()))
        if detailed:
            free_space_str = self._get_free_space()
            output_str += cu.add_indentation(free_space_str, 2)

        if free_heap != -1:
            watermark_str = "%-15s : " % "from watermarks"
            watermark_str += cu.mem_size_to_string(free_heap)
        else:
            watermark_str = "Watermarks not available for this heap!"
        output_str += cu.add_indentation(watermark_str, 2) + "\n"

        output_str += ("%s heap minimum free:\n" % (self.memory_type.upper()))

        if min_free_heap != -1:
            watermark_str = "%-15s : " % "from watermarks"
            watermark_str += cu.mem_size_to_string(min_free_heap)
        else:
            watermark_str = "Watermarks not available for this heap!"
        output_str += cu.add_indentation(watermark_str, 2) + "\n"
        return output_str
Example #11
0
    def _alloc_blocks(self, heap_address, heap_size, memory_type="dm"):
        """
        @brief Reads and checks the allocated blocks.
        @param[in] self Pointer to the current object
        @param[in] heap_address The heap start address
        @param[in] heap_size The heap size.
        @param[out] Returns two lists. One for the heap
            allocations the other for debug information.
        """
        magic_val = 0xabcd01
        alloc_info = []
        debug_info = []

        (heap_data, magic_offset) = self._get_heap_and_magic_offset(
            heap_address, heap_size, memory_type
        )

        total = 0
        # here index is the index of the magic word in heap_data. Since in
        # heap_pm we are working with 32-bit words and not strictly addresses,
        # for start, index should actually be
        # -Arch.addr_per_word/Arch.arrd_per_word, which is -1
        index = -1

        # Search through the entire heap block, looking for allocated blocks
        # based on the presence of the magic word
        while True:
            try:
                index = index + heap_data[index + 1:].index(magic_val) + 1
                address = heap_address + \
                    (index - magic_offset) * Arch.addr_per_word


                (length, magic, owner_hint) = \
                    self._read_alloc_block(address, memory_type)

                if magic != magic_val:
                    raise ct.AnalysisError(
                        "Magic word not found at expected offset."
                    )

                # Check if we are still in valid region
                if (length > 0) and \
                        (address + length < heap_address + heap_size):
                    alloc_info.append(
                        "Allocated block size : " +
                        cu.mem_size_to_string(length, "o") +
                        " at address: 0x{0:0>8x}".format(address)
                    )
                    index = index + length // Arch.addr_per_word
                    total = total + length
                    if self.pmalloc_debug_enabled:
                        debug_info.append(
                            "Ptr: 0x{0:0>8x} size: ".format(address) +
                            cu.mem_size_to_string(length, "o") +
                            " allocated by: {0:s}".format(owner_hint)
                        )
            except ValueError:
                break

        alloc_info.append(
            "Total heap allocation : " + cu.mem_size_to_string(total, "ow")
        )

        return alloc_info, debug_info
Example #12
0
    def _free_blocks(self, address, heap_start, heap_size, memory_type="dm"):
        """
        @brief Checks the free blocks.
        @param[in] self Pointer to the current object
        @param[in] address Address to start with.
        @param[out] Returns a list describing the free memory allocations.
        """
        free_blocks_info = []
        address_history = []
        total_size = 0
        while address != 0:
            # Avoid infinite loop by checking if the node was already checked.
            if address not in address_history:
                address_history.append(address)
            else:
                self.formatter.error(
                    "Repeating nodes with address 0x%x. Probably memory corruption" %
                    address)
                return FreeBlocks(total_size, free_blocks_info)
            if memory_type == "dm":
                freeblock = self.chipdata.cast(address, 'mem_node')
                freeblock_size = freeblock.get_member('length').value
            elif memory_type == "pm":
                freeblock = self.chipdata.cast(address, 'mem_node_pm', False, 'PM')
                freeblock_size = freeblock.get_member(
                    'struct_mem_node'
                ).get_member('length_32').value * Arch.addr_per_word
            else:
                raise ct.FatalAnalysisError(
                    "Memory type %s not recognised." % memory_type
                )

            # verify if the address is valid
            if self.is_address_valid(address):
                # and if the list node belongs to the current analysed heap display info
                if (address >= heap_start) and \
                    (address <= (heap_start + heap_size)):
                    desc_str = (
                        "Free block size : " +
                        cu.mem_size_to_string(freeblock_size, "o") +
                        " at address: 0x{0:0>8x}".format(address)
                    )
                    free_blocks_info.append(desc_str)
                    total_size += freeblock_size
            else:
                raise ct.FatalAnalysisError(
                    " 0x%x is out of %s heap memory !" % (address, memory_type)
                )

            if memory_type == "dm":
                address = freeblock.get_member('u').get_member('next').value
            elif memory_type == "pm":
                address = freeblock.get_member('struct_mem_node').get_member(
                    'u'
                ).get_member('next').value


        free_blocks_info.append(
            "Total heap free : " + cu.mem_size_to_string(total_size, "ow")
        )
        return FreeBlocks(total_size, free_blocks_info)
Example #13
0
    def _free_blocks(self, address, heap_start, heap_size, memory_type="dm"):
        """Checks the free blocks.

        Args:
            address: Address to start with.
            heap_start
            heap_size
            memory_type (str, optional)

        Returns:
            A list describing the free memory allocations.
        """
        free_blocks_info = []
        address_history = []
        total_size = 0
        while address != 0:
            # Avoid infinite loop by checking if the node was already checked.
            if address not in address_history:
                address_history.append(address)
            else:
                self.formatter.error("Repeating nodes with address 0x%x. "
                                     "Probably memory corruption" % address)
                return FreeBlocks(total_size, free_blocks_info)
            if memory_type == "dm":
                try:
                    freeblock = self.chipdata.cast(address, 'mem_node')
                    freeblock_size = freeblock.get_member('length').value
                except InvalidDmAddressError:
                    self.formatter.error(
                        "Address 0x%x in %s cannot be access. "
                        "Heap cannot be analysed." %
                        (address, str(Arch.get_dm_region(address, False))))

                    return FreeBlocks(total_size, free_blocks_info)

            elif memory_type == "pm":
                freeblock = self.chipdata.cast(address, 'mem_node_pm', False,
                                               'PM')
                freeblock_size = freeblock.get_member(
                    'struct_mem_node').get_member(
                        'length_32').value * Arch.addr_per_word
            else:
                raise FatalAnalysisError("Memory type %s not recognised." %
                                         memory_type)

            # verify if the address is valid
            if self.is_address_valid(address):
                # If the list node belongs to the current analysed heap
                # display info
                end_of_heap = heap_start + heap_size
                if (address >= heap_start) and (address <= end_of_heap):
                    desc_str = ("Free block size : " +
                                cu.mem_size_to_string(freeblock_size, "o") +
                                " at address: 0x{0:0>8x}".format(address))
                    free_blocks_info.append(desc_str)
                    total_size += freeblock_size
            else:
                raise FatalAnalysisError(" 0x%x is out of %s heap memory !" %
                                         (address, memory_type))

            if memory_type == "dm":
                address = freeblock.get_member('u').get_member('next').value
            elif memory_type == "pm":
                address = freeblock.get_member('struct_mem_node').get_member(
                    'u').get_member('next').value

        free_blocks_info.append("Total heap free : " +
                                cu.mem_size_to_string(total_size, "ow"))
        return FreeBlocks(total_size, free_blocks_info)