Skip to content

Commit

Permalink
when analyzing a coredump, always prefer maintenance info sections
Browse files Browse the repository at this point in the history
…over `info proc sections`
  • Loading branch information
hugsy committed Nov 11, 2024
1 parent 4dccd78 commit 4c63c15
Showing 1 changed file with 57 additions and 7 deletions.
64 changes: 57 additions & 7 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -3537,6 +3537,15 @@ def is_qemu_system() -> bool:
return "received: \"\"" in response


def is_target_coredump() -> bool:
global gef
if gef.session.coredump_mode is not None:
return gef.session.coredump_mode
lines = (gdb.execute("maintenance info section", to_string=True) or "").splitlines()
is_coredump_mode = any(map(lambda line: line.startswith("Core file: "), lines))
gef.session.coredump_mode = is_coredump_mode
return is_coredump_mode

def get_filepath() -> Optional[str]:
"""Return the local absolute path of the file currently debugged."""
if gef.session.remote:
Expand Down Expand Up @@ -10707,6 +10716,7 @@ def __gef_prompt__(current_prompt: Callable[[Callable], str]) -> str:
if gef.config["gef.readline_compat"] is True: return GEF_PROMPT
if gef.config["gef.disable_color"] is True: return GEF_PROMPT
prompt = gef.session.remote.mode.prompt_string() if gef.session.remote else ""
prompt += "(core) " if is_target_coredump() else ""
prompt += GEF_PROMPT_ON if is_alive() else GEF_PROMPT_OFF
return prompt

Expand Down Expand Up @@ -10817,6 +10827,12 @@ def __parse_maps(self) -> Optional[List[Section]]:
if gef.arch.maps is not None:
return list(gef.arch.maps())

# Coredumps are the only case where `maintenance info sections` collected more
# info than `info proc sections`.so use this unconditionally. See #1154

if is_target_coredump():
return list(self.parse_gdb_maintenance_info_sections())

try:
return list(self.parse_gdb_info_proc_maps())
except:
Expand All @@ -10834,8 +10850,8 @@ def __parse_maps(self) -> Optional[List[Section]]:

raise RuntimeError("Failed to get memory layout")

@classmethod
def parse_procfs_maps(cls) -> Generator[Section, None, None]:
@staticmethod
def parse_procfs_maps() -> Generator[Section, None, None]:
"""Get the memory mapping from procfs."""
procfs_mapfile = gef.session.maps
if not procfs_mapfile:
Expand Down Expand Up @@ -10866,9 +10882,9 @@ def parse_procfs_maps(cls) -> Generator[Section, None, None]:
path=pathname)
return

@classmethod
def parse_gdb_info_proc_maps(cls) -> Generator[Section, None, None]:
"""Get the memory mapping from GDB's command `maintenance info sections` (limited info)."""
@staticmethod
def parse_gdb_info_proc_maps() -> Generator[Section, None, None]:
"""Get the memory mapping from GDB's command `info proc mappings`."""
if GDB_VERSION < (11, 0):
raise AttributeError("Disregarding old format")

Expand Down Expand Up @@ -10925,8 +10941,8 @@ def parse_gdb_info_proc_maps(cls) -> Generator[Section, None, None]:
)
return

@classmethod
def parse_monitor_info_mem(cls) -> Generator[Section, None, None]:
@staticmethod
def parse_monitor_info_mem() -> Generator[Section, None, None]:
"""Get the memory mapping from GDB's command `monitor info mem`
This can raise an exception, which the memory manager takes to mean
that this method does not work to get a map.
Expand All @@ -10947,6 +10963,39 @@ def parse_monitor_info_mem(cls) -> Generator[Section, None, None]:
offset=off,
permission=perm)

@staticmethod
def parse_gdb_maintenance_info_sections() -> Generator[Section, None, None]:
"""Get the memory mapping from GDB's command `maintenance info sections` (limited info). In some cases (i.e. coredumps),
the memory info collected by `info proc sections` is insufficent."""
stream = StringIO(gdb.execute("maintenance info sections", to_string=True))

for line in stream:
if not line:
break

try:
parts = line.split()
addr_start, addr_end = [int(x, 16) for x in parts[1].split("->")]
off = int(parts[3][:-1], 16)
path = parts[4]
perm = Permission.NONE
if "DATA" in parts[5:]:
perm |= Permission.READ | Permission.WRITE
if "CODE" in parts[5:]:
perm |= Permission.READ | Permission.EXECUTE
yield Section(
page_start=addr_start,
page_end=addr_end,
offset=off,
permission=perm,
path=path,
)

except IndexError:
continue
except ValueError:
continue

@staticmethod
def parse_info_mem():
"""Get the memory mapping from GDB's command `info mem`. This can be
Expand Down Expand Up @@ -11267,6 +11316,7 @@ def __init__(self) -> None:
self.remote: Optional["GefRemoteSessionManager"] = None
self.remote_initializing: bool = False
self.qemu_mode: bool = False
self.coredump_mode: bool | None = None
self.convenience_vars_index: int = 0
self.heap_allocated_chunks: List[Tuple[int, int]] = []
self.heap_freed_chunks: List[Tuple[int, int]] = []
Expand Down

0 comments on commit 4c63c15

Please sign in to comment.