func listLoadedLibraries(p process.Process) (libraries []string, harderror error, softerrors []error) { mapsFile, harderror := os.Open(common.MapsFilePathFromPid(p.Pid())) if harderror != nil { return } defer mapsFile.Close() scanner := bufio.NewScanner(mapsFile) processName, harderror, softerrors := p.Name() if harderror != nil { return } libs := make([]string, 0, 10) for scanner.Scan() { line := scanner.Text() items := common.SplitMapsFileEntry(line) if len(items) != 6 { return libs, fmt.Errorf("Unrecognised maps line: %s", line), softerrors } path := items[5] if path == processName { continue } if path == "/dev/zero" || path == "/dev/zero (deleted)" { continue } if path == "" { continue } if path[0] == '[' { continue } if inSlice(path, libs) { continue } libs = append(libs, path) } return libs, nil, nil }
func nextReadableMemoryRegion(p process.Process, address uintptr) (region MemoryRegion, harderror error, softerrors []error) { mapsFile, harderror := os.Open(common.MapsFilePathFromPid(p.Pid())) if harderror != nil { return } defer mapsFile.Close() region = MemoryRegion{} scanner := bufio.NewScanner(mapsFile) for scanner.Scan() { line := scanner.Text() items := common.SplitMapsFileEntry(line) if len(items) != 6 { return region, fmt.Errorf("Unrecognised maps line: %s", line), softerrors } start, end, err := common.ParseMapsFileMemoryLimits(items[0]) if err != nil { return region, err, softerrors } if end <= address { continue } // Skip vsyscall as it can't be read. It's a special page mapped by the kernel to accelerate some syscalls. if items[5] == "[vsyscall]" { continue } // Check if memory is unreadable if items[1][0] == '-' { // If we were already reading a region this will just finish it. We only report the softerror when we // were actually trying to read it. if region.Address != 0 { return region, nil, softerrors } softerrors = append(softerrors, fmt.Errorf("Unreadable memory %s", items[0])) continue } size := uint(end - start) // Begenning of a region if region.Address == 0 { region = MemoryRegion{Address: start, Size: size} continue } // Continuation of a region if region.Address+uintptr(region.Size) == start { region.Size += size continue } // This map is outside the current region, so we are ready return region, nil, softerrors } // No region left if err := scanner.Err(); err != nil { return NoRegionAvailable, err, softerrors } // The last map was a valid region, so it was not closed by an invalid/non-contiguous one and we have to return it if region.Address > 0 { return region, harderror, softerrors } return NoRegionAvailable, nil, softerrors }