| 235 | |
| 236 | |
| 237 | def parse_maps_file_for_binary( |
| 238 | binary_name: Path, |
| 239 | all_maps_iter: Iterable[VirtualMap], |
| 240 | load_point_by_module: Optional[Dict[str, int]] = None, |
| 241 | ) -> MemoryMapInformation: |
| 242 | min_addr = float("inf") |
| 243 | max_addr = 0 |
| 244 | maps_by_library: Dict[str, List[VirtualMap]] = collections.defaultdict(list) |
| 245 | current_lib = "" |
| 246 | all_maps = tuple(all_maps_iter) |
| 247 | |
| 248 | if load_point_by_module is None: |
| 249 | load_point_by_module = collections.defaultdict(lambda: 2**64) |
| 250 | for memory_range in all_maps: |
| 251 | if memory_range.path is not None: |
| 252 | load_point_by_module[memory_range.path.name] = min( |
| 253 | memory_range.start, |
| 254 | load_point_by_module[memory_range.path.name], |
| 255 | ) |
| 256 | |
| 257 | for memory_range in all_maps: |
| 258 | current_lib = ( |
| 259 | memory_range.path.name if memory_range.path is not None else current_lib |
| 260 | ) |
| 261 | maps_by_library[current_lib].append(memory_range) |
| 262 | |
| 263 | if memory_range.path is None or not memory_range.path.name.startswith("[v"): |
| 264 | min_addr = min(min_addr, memory_range.start) |
| 265 | max_addr = max(max_addr, memory_range.end) |
| 266 | maps_by_library = dict(maps_by_library) |
| 267 | |
| 268 | python = libpython = bss = heap = None |
| 269 | try: |
| 270 | binary_maps = maps_by_library[binary_name.name] |
| 271 | python = _get_base_map(binary_maps) |
| 272 | except KeyError: |
| 273 | LOGGER.debug("Unable to find maps for %r in %r", binary_name, maps_by_library) |
| 274 | available_maps = { |
| 275 | str(map.path) |
| 276 | for map in all_maps |
| 277 | if map.path is not None and ".so" not in map.path.name |
| 278 | } |
| 279 | LOGGER.debug("Available executable maps: %s", ", ".join(available_maps)) |
| 280 | if available_maps: |
| 281 | maps_txt = ", ".join(available_maps) |
| 282 | msg = f"These are the available executable memory maps: {maps_txt}" |
| 283 | else: |
| 284 | msg = "There are no available executable maps with known paths." |
| 285 | raise MissingExecutableMaps( |
| 286 | f"Unable to find maps for the executable {binary_name}. " + msg |
| 287 | ) |
| 288 | LOGGER.info("python binary first map found: %r", python) |
| 289 | |
| 290 | libpython_binaries = [lib for lib in maps_by_library if "libpython" in lib] |
| 291 | if len(libpython_binaries) > 1: |
| 292 | raise PystackError( |
| 293 | f"Unexpectedly found multiple libpython in process: {libpython_binaries}" |
| 294 | ) |