Skip to content

Commit

Permalink
memparse: add search functionnality to memparse
Browse files Browse the repository at this point in the history
This commit adds `--search`, `--search-regex` and `--context` flags
to `memparse`, enabling pattern search in a process's memory pages.

Signed-off-by: Kouame Behouba Manasse <[email protected]>
  • Loading branch information
behouba committed Sep 15, 2024
1 parent 7545506 commit eb668d3
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 22 deletions.
93 changes: 93 additions & 0 deletions cmd/memparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ func MemParse() *cobra.Command {
"Specify the output file to be written to",
)

flags.StringVarP(
searchPattern,
"search",
"s",
"",
"Search for a string pattern in memory pages",
)

flags.StringVarP(
searchRegexPattern,
"search-regex",
"r",
"",
"Search for a regex pattern in memory pages",
)

flags.IntVarP(
searchContext,
"context",
"c",
0,
"Print the specified number of bytes surrounding each match",
)

return cmd
}

Expand Down Expand Up @@ -79,6 +103,10 @@ func memparse(cmd *cobra.Command, args []string) error {
}
defer internal.CleanupTasks(tasks)

if *searchPattern != "" || *searchRegexPattern != "" {
return printMemorySearchResultForPID(tasks[0])
}

if *pID != 0 {
return printProcessMemoryPages(tasks[0])
}
Expand Down Expand Up @@ -273,3 +301,68 @@ func generateHexAndAscii(data []byte) (string, string) {

return hex, ascii
}

// Searches for a pattern in the memory of a given PID and prints the results.
func printMemorySearchResultForPID(task internal.Task) error {
c := crit.New(nil, nil, filepath.Join(task.OutputDir, metadata.CheckpointDirectory), false, false)
psTree, err := c.ExplorePs()
if err != nil {
return fmt.Errorf("failed to get process tree: %w", err)
}

// Check if PID exist within the checkpoint
ps := psTree.FindPs(*pID)
if ps == nil {
return fmt.Errorf("no process with PID %d (use `inspect --ps-tree` to view all PIDs)", *pID)
}

memReader, err := crit.NewMemoryReader(
filepath.Join(task.OutputDir, metadata.CheckpointDirectory),
*pID, pageSize,
)
if err != nil {
return fmt.Errorf("failed to create memory reader: %w", err)
}

if err := internal.UntarFiles(
task.CheckpointFilePath, task.OutputDir,
[]string{filepath.Join(metadata.CheckpointDirectory, fmt.Sprintf("pages-%d.img", memReader.GetPagesID()))},
); err != nil {
return fmt.Errorf("failed to extract pages file: %w", err)
}

pattern := *searchPattern
escapeRegExpCharacters := true
if pattern == "" {
pattern = *searchRegexPattern
escapeRegExpCharacters = false
}

results, err := memReader.SearchPattern(pattern, escapeRegExpCharacters, *searchContext, 0)
if err != nil {
return fmt.Errorf("failed to search pattern in memory: %w", err)
}

if len(results) == 0 {
fmt.Printf("No matches for pattern \"%s\" in the memory of PID %d\n", pattern, *pID)
return nil
}

table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Address", "Match", "Instance"})
table.SetAutoMergeCells(false)
table.SetRowLine(true)

for i, result := range results {
table.Append([]string{
fmt.Sprintf(
"%016x", result.Vaddr),
result.Match,
fmt.Sprintf("%d", i+1),
})
}

table.Render()

return nil
}
25 changes: 14 additions & 11 deletions cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package cmd
import "github.com/checkpoint-restore/checkpointctl/internal"

var (
format *string = &internal.Format
stats *bool = &internal.Stats
mounts *bool = &internal.Mounts
outputFilePath *string = &internal.OutputFilePath
pID *uint32 = &internal.PID
psTree *bool = &internal.PsTree
psTreeCmd *bool = &internal.PsTreeCmd
psTreeEnv *bool = &internal.PsTreeEnv
files *bool = &internal.Files
sockets *bool = &internal.Sockets
showAll *bool = &internal.ShowAll
format *string = &internal.Format
stats *bool = &internal.Stats
mounts *bool = &internal.Mounts
outputFilePath *string = &internal.OutputFilePath
pID *uint32 = &internal.PID
psTree *bool = &internal.PsTree
psTreeCmd *bool = &internal.PsTreeCmd
psTreeEnv *bool = &internal.PsTreeEnv
files *bool = &internal.Files
sockets *bool = &internal.Sockets
showAll *bool = &internal.ShowAll
searchPattern *string = &internal.SearchPattern
searchRegexPattern *string = &internal.SearchRegexPattern
searchContext *int = &internal.SearchContext
)
25 changes: 14 additions & 11 deletions internal/options.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package internal

var (
Format string
Stats bool
Mounts bool
OutputFilePath string
PID uint32
PsTree bool
PsTreeCmd bool
PsTreeEnv bool
Files bool
Sockets bool
ShowAll bool
Format string
Stats bool
Mounts bool
OutputFilePath string
PID uint32
PsTree bool
PsTreeCmd bool
PsTreeEnv bool
Files bool
Sockets bool
ShowAll bool
SearchPattern string
SearchRegexPattern string
SearchContext int
)

0 comments on commit eb668d3

Please sign in to comment.