linux-sysprog · beginner · ~15 min

Parse a /proc/self/maps line

Robust whitespace-delimited /proc parsing.

Challenge

Pull the address range and permission string out of one line of /proc/self/maps — the memory map of a running process.

Task

Implement int parse_maps_line(const char *line, unsigned long *start, unsigned long *end, char perms[5]) that parses a single maps line.

Input

  • line: one map entry in the format start-end perms offset dev inode [path], e.g. 55b3e1e5e000-55b3e1e60000 r-xp 00000000 fd:00 12345 /usr/bin/cat. Addresses are hexadecimal; perms is 4 characters (r/-, w/-, x/-, p/s).
  • start, end: where to store the parsed start and end addresses.
  • perms: a 5-byte buffer for the 4 permission chars plus a NUL.

Output

On success, stores the start and end addresses in *start/*end, copies the 4 permission characters into perms (NUL-terminated), and returns 1. Returns 0 if the line does not parse. The offset, dev, inode, and path fields are ignored.

Example

parse_maps_line("55b3e1e5e000-55b3e1e60000 r-xp 00000000 fd:00 12345 /usr/bin/cat", &s, &e, perms)
   ->   1, s = 0x55b3e1e5e000, e = 0x55b3e1e60000, perms = "r-xp"
parse_maps_line("7ffff7ff5000-7ffff7ff7000 r--p 00000000 00:00 0", &s, &e, perms)
   ->   1, perms = "r--p"   (anonymous mapping, no path)
parse_maps_line("garbage", &s, &e, perms)
   ->   0

Edge cases

  • A line with no trailing path (anonymous mapping) still parses.
  • Unparseable input returns 0.

Rules

  • perms must be NUL-terminated (5 bytes total).

Why this matters

Reading /proc/self/maps is how every memory-analysis tool starts. The line format is the foundation; you can build a 'where is libc?' lookup in 30 lines.

Input format

One /proc/self/maps line 'start-end perms offset dev inode [path]', plus output pointers start, end and a 5-byte perms buffer.

Output format

Fills *start, *end, and the 4-char NUL-terminated perms; returns 1 on success, 0 on parse failure.

Constraints

Addresses are hex; perms is 4 chars + NUL. Use sscanf and check it matched 3 fields.

Starter code

#include <stddef.h>
int parse_maps_line(const char *line, unsigned long *start, unsigned long *end, char perms[5]) { /* TODO */ (void)line; (void)start; (void)end; (void)perms; return 0; }

Common mistakes

Reading perms as 4 chars via %4s and forgetting NUL.

Edge cases to handle

Line with no trailing path (anonymous mapping).

Complexity

O(strlen).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.