df.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #
  2. # Copyright (c) 2021 Project CHIP Authors
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. """DataFrame utilities."""
  17. from typing import Dict
  18. import numpy as np # type: ignore
  19. import pandas as pd # type: ignore
  20. class DF(pd.DataFrame): # pylint: disable=too-many-ancestors
  21. """DataFrame builder with default columns and types."""
  22. def __init__(self, *args, **kwargs):
  23. super().__init__(*args, **kwargs)
  24. for c in self.required:
  25. if c not in self.columns:
  26. self[c] = pd.Series()
  27. types = {c: self.dtype[c] for c in self.columns if c in self.dtype}
  28. typed_columns = list(types.keys())
  29. self[typed_columns] = self.astype(types, copy=False)[typed_columns]
  30. self.attrs['name'] = self.name
  31. class SymbolSourceDF(DF): # pylint: disable=too-many-ancestors
  32. """Maps symbol to compilation unit"""
  33. name: str = 'symbolsource'
  34. required = frozenset(['symbol', 'address', 'cu'])
  35. dtype = {
  36. 'symbol': 'string',
  37. 'address': np.int64,
  38. 'cu': 'string',
  39. 'line': np.int64,
  40. }
  41. class SegmentDF(DF): # pylint: disable=too-many-ancestors
  42. """Segment memory map"""
  43. name: str = 'segment'
  44. required = frozenset(['type', 'vaddress', 'paddress', 'size'])
  45. dtype = {
  46. 'type': 'string',
  47. 'vaddress': np.int64,
  48. 'paddress': np.int64,
  49. 'size': np.int64,
  50. 'flags': np.int32
  51. }
  52. class SectionDF(DF): # pylint: disable=too-many-ancestors
  53. """Section memory map"""
  54. name: str = 'section'
  55. required = frozenset(['section', 'type', 'address', 'size'])
  56. dtype = {
  57. 'section': 'string',
  58. 'type': 'string',
  59. 'address': np.int64,
  60. 'size': np.int64,
  61. 'flags': np.int32,
  62. 'segment': np.int32,
  63. }
  64. class SymbolDF(DF): # pylint: disable=too-many-ancestors
  65. """Symbol table"""
  66. name: str = 'symbol'
  67. required = frozenset(['symbol', 'type', 'address', 'size'])
  68. dtype = {
  69. 'symbol': 'string',
  70. 'type': 'string',
  71. 'address': np.int64,
  72. 'size': np.int64,
  73. 'shndx': 'string'
  74. }
  75. class ExtentDF(DF): # pylint: disable=too-many-ancestors
  76. """Gaps between symbols"""
  77. name: str = 'gap'
  78. required = frozenset(['address', 'size', 'section'])
  79. dtype = {
  80. 'address': np.int64,
  81. 'size': np.int64,
  82. 'section': 'string'
  83. }
  84. class StackDF(DF): # pylint: disable=too-many-ancestors
  85. """Stack usage table"""
  86. name: str = 'stack'
  87. required = frozenset(['symbol', 'type', 'size'])
  88. dtype = {
  89. 'symbol': 'string',
  90. 'type': 'string',
  91. 'size': np.int64,
  92. 'file': 'string',
  93. 'line': np.int64,
  94. }
  95. def find_class(df: pd.DataFrame):
  96. """Find a core DF subclass for a data frame.
  97. Given a arbitrary pandas DataFrame, determine whether it is usable
  98. as one of the main memory map tables (symbol, section, segment)
  99. by checking whether the required columns are present.
  100. """
  101. if isinstance(df, DF):
  102. return type(df)
  103. for c in [SymbolDF, SectionDF, SegmentDF]:
  104. if c.required.issubset(df.columns):
  105. return c
  106. return None
  107. DFs = Dict[str, DF]