mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 05:55:13 +00:00
Userland: Introduce the pmemdump utility
This utility helps to dump the physical memory space from /dev/mem. It supports both read(2) and mmap(2) on it so we could use mmap(2) for fast dumping of the memory, or read(2) when we need to read unaligned physical regions.
This commit is contained in:
parent
f7d1b8cd0c
commit
ff25958b51
Notes:
sideshowbarker
2024-07-17 21:27:25 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/ff25958b511 Pull-request: https://github.com/SerenityOS/serenity/pull/11390 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/IdanHo ✅
3 changed files with 159 additions and 0 deletions
38
Base/usr/share/man/man1/pmemdump.md
Normal file
38
Base/usr/share/man/man1/pmemdump.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
## Name
|
||||
|
||||
pmemdump - dump physical memory
|
||||
|
||||
## Synopsis
|
||||
|
||||
```**sh
|
||||
$ pmemdump [-r] <offset> <length>
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Dump a portion of the physical memory space.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
* `-r`: Dump from /dev/mem with `read(2)` instead of doing `mmap(2)` on it.
|
||||
|
||||
## Examples
|
||||
|
||||
```sh
|
||||
$ pmemdump -r 983040 65536
|
||||
$ pmemdump 983040 65536
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
The pmemdump utility opens the `/dev/mem` file, and gets a mapping by doing `mmap(2)`
|
||||
on it.
|
||||
|
||||
Using the `-r` flag might be useful sometimes, especially when reading from an unaligned
|
||||
reserved physical memory region when trying to `mmap(2)` `/dev/mem` on the specified
|
||||
offset fails.
|
||||
|
||||
## See also
|
||||
|
||||
* [`mem`(4)](../man4/mem.md)
|
|
@ -130,6 +130,7 @@ target_link_libraries(paste LibGUI)
|
|||
target_link_libraries(pgrep LibRegex)
|
||||
target_link_libraries(pls LibCrypt LibMain)
|
||||
target_link_libraries(pmap LibMain)
|
||||
target_link_libraries(pmemdump LibMain)
|
||||
target_link_libraries(pro LibMain LibProtocol)
|
||||
target_link_libraries(ps LibMain)
|
||||
target_link_libraries(pwd LibMain)
|
||||
|
|
120
Userland/Utilities/pmemdump.cpp
Normal file
120
Userland/Utilities/pmemdump.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringUtils.h>
|
||||
#include <LibCore/ArgsParser.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibMain/Main.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool try_set_offset_and_length_parameters(String const& arg_offset, String const& arg_length, u64& offset, u64& length)
|
||||
{
|
||||
// TODO: Add support for hex values
|
||||
auto possible_offset = arg_offset.to_uint<u64>();
|
||||
if (!possible_offset.has_value())
|
||||
return false;
|
||||
auto possible_length = arg_length.to_uint<u64>();
|
||||
if (!possible_length.has_value())
|
||||
return false;
|
||||
offset = possible_offset.value();
|
||||
length = possible_length.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void try_to_dump_with_memory_mapping(int fd, u64 offset, u64 length)
|
||||
{
|
||||
VERIFY(fd >= 0);
|
||||
u64 mmoffset = offset % sysconf(_SC_PAGESIZE);
|
||||
void* mmp = mmap(NULL, mmoffset + length, PROT_READ, MAP_SHARED, fd, offset - mmoffset);
|
||||
if (mmp == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t ncomplete = 0;
|
||||
while (ncomplete < length) {
|
||||
ssize_t nwritten = write(STDOUT_FILENO, static_cast<u8*>(mmp) + ncomplete, length - ncomplete);
|
||||
if (nwritten < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
ncomplete += nwritten;
|
||||
}
|
||||
if (munmap(mmp, mmoffset + length) < 0) {
|
||||
perror("munmap");
|
||||
}
|
||||
}
|
||||
|
||||
static void try_to_dump_with_read(int fd, u64 offset, u64 length)
|
||||
{
|
||||
VERIFY(fd >= 0);
|
||||
auto rs = lseek(fd, offset, SEEK_SET);
|
||||
if (rs < 0) {
|
||||
fprintf(stderr, "Couldn't seek to offset %" PRIi64 " while verifying: %s\n", offset, strerror(errno));
|
||||
return;
|
||||
}
|
||||
u8 buf[4096];
|
||||
size_t ncomplete = 0;
|
||||
while (ncomplete < length) {
|
||||
size_t length_to_be_read = min<size_t>((length - ncomplete), sizeof(buf));
|
||||
if (read(fd, buf, length_to_be_read) < 0) {
|
||||
perror("read");
|
||||
return;
|
||||
}
|
||||
ssize_t nwritten = write(STDOUT_FILENO, buf, length_to_be_read);
|
||||
if (nwritten < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
ncomplete += nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||
{
|
||||
TRY(Core::System::pledge("stdio rpath"));
|
||||
|
||||
StringView arg_offset;
|
||||
StringView arg_length;
|
||||
bool use_read_instead_of_mmap = false;
|
||||
Core::ArgsParser args;
|
||||
args.add_positional_argument(arg_offset, "Physical Address (Offset)", "offset", Core::ArgsParser::Required::Yes);
|
||||
args.add_positional_argument(arg_length, "Length of that region", "length", Core::ArgsParser::Required::Yes);
|
||||
args.add_option(use_read_instead_of_mmap, "Read /dev/mem instead of try to map it", nullptr, 'r');
|
||||
|
||||
args.parse(arguments);
|
||||
|
||||
u64 offset = 0;
|
||||
u64 length = 0;
|
||||
if (!try_set_offset_and_length_parameters(arg_offset, arg_length, offset, length)) {
|
||||
warnln("pmemdump: Invalid length or offset parameters\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
if (use_read_instead_of_mmap)
|
||||
try_to_dump_with_read(fd, offset, length);
|
||||
else
|
||||
try_to_dump_with_memory_mapping(fd, offset, length);
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue