mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 09:13:06 +00:00
libdrgn: add read(2) and pread(2) wrappers that don't return short reads
We have a couple of loops that deal with short reads/EINTR from read(2) and pread(2), and upcoming changes would need to add more. Add some wrappers to abstract this away. drgn_read_memory_file() still needs the loop so it can fault on the exact offset that returns EIO. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
56fda2a0cf
commit
b8cdfff250
@ -269,7 +269,7 @@ TAB_SIZE = 4
|
|||||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
||||||
# a double escape (\\{ and \\})
|
# a double escape (\\{ and \\})
|
||||||
|
|
||||||
ALIASES =
|
ALIASES = manpage{2}="<a href=\"http://man7.org/linux/man-pages/man\2/\1.\2.html\">\1(\2)</a>"
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
|
@ -55,6 +55,8 @@ libdrgnimpl_la_SOURCES = $(ARCH_DEFS_PYS:_defs.py=.c) \
|
|||||||
hash_table.c \
|
hash_table.c \
|
||||||
hash_table.h \
|
hash_table.h \
|
||||||
helpers.h \
|
helpers.h \
|
||||||
|
io.c \
|
||||||
|
io.h \
|
||||||
language.c \
|
language.c \
|
||||||
language.h \
|
language.h \
|
||||||
language_c.c \
|
language_c.c \
|
||||||
|
50
libdrgn/io.c
Normal file
50
libdrgn/io.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
ssize_t read_all(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
if (count > SSIZE_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t n = 0;
|
||||||
|
while (n < count) {
|
||||||
|
ssize_t r = read(fd, (char *)buf + n, count - n);
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
return r;
|
||||||
|
} else if (r == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t pread_all(int fd, void *buf, size_t count, off_t offset)
|
||||||
|
{
|
||||||
|
if (count > SSIZE_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t n = 0;
|
||||||
|
while (n < count) {
|
||||||
|
ssize_t r = pread(fd, (char *)buf + n, count - n, offset + n);
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
return r;
|
||||||
|
} else if (r == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
27
libdrgn/io.h
Normal file
27
libdrgn/io.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Input/output helpers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRGN_IO_H
|
||||||
|
#define DRGN_IO_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around \manpage{read,2} that never returns less bytes than requested unless it
|
||||||
|
* hits end-of-file.
|
||||||
|
*/
|
||||||
|
ssize_t read_all(int fd, void *buf, size_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around \manpage{pread,2} that never returns less bytes than requested unless
|
||||||
|
* it hits end-of-file.
|
||||||
|
*/
|
||||||
|
ssize_t pread_all(int fd, void *buf, size_t count, off_t offset);
|
||||||
|
|
||||||
|
#endif /* DRGN_IO_H */
|
@ -23,6 +23,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "io.h"
|
||||||
#include "linux_kernel.h"
|
#include "linux_kernel.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
@ -630,27 +631,17 @@ kernel_module_iterator_gnu_build_id_live(struct kernel_module_iterator *it,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buf = it->build_id_buf;
|
ssize_t r = read_all(fd, it->build_id_buf, st.st_size);
|
||||||
size_t size = 0;
|
|
||||||
while (size < st.st_size) {
|
|
||||||
ssize_t r = read(fd, buf + size, st.st_size - size);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (errno == EINTR)
|
err = drgn_error_format_os("read", errno, "%s/%s", path,
|
||||||
continue;
|
|
||||||
err = drgn_error_format_os("read", errno,
|
|
||||||
"%s/%s", path,
|
|
||||||
ent->d_name);
|
ent->d_name);
|
||||||
close(fd);
|
close(fd);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (r == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size += r;
|
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
*build_id_len_ret = parse_gnu_build_id_from_note(buf, size,
|
*build_id_len_ret =
|
||||||
false,
|
parse_gnu_build_id_from_note(it->build_id_buf, r, false,
|
||||||
build_id_ret);
|
build_id_ret);
|
||||||
if (*build_id_len_ret) {
|
if (*build_id_len_ret) {
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "debug_info.h"
|
#include "debug_info.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "io.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "linux_kernel.h"
|
#include "linux_kernel.h"
|
||||||
#include "memory_reader.h"
|
#include "memory_reader.h"
|
||||||
@ -205,23 +206,11 @@ static struct drgn_error *has_kdump_signature(const char *path, int fd,
|
|||||||
bool *ret)
|
bool *ret)
|
||||||
{
|
{
|
||||||
char signature[KDUMP_SIG_LEN];
|
char signature[KDUMP_SIG_LEN];
|
||||||
size_t n = 0;
|
ssize_t r = pread_all(fd, signature, sizeof(signature), 0);
|
||||||
|
if (r < 0)
|
||||||
while (n < sizeof(signature)) {
|
|
||||||
ssize_t sret;
|
|
||||||
|
|
||||||
sret = pread(fd, signature + n, sizeof(signature) - n, n);
|
|
||||||
if (sret == -1) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
return drgn_error_create_os("pread", errno, path);
|
return drgn_error_create_os("pread", errno, path);
|
||||||
} else if (sret == 0) {
|
*ret = (r == sizeof(signature)
|
||||||
*ret = false;
|
&& memcmp(signature, KDUMP_SIGNATURE, sizeof(signature)) == 0);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
n += sret;
|
|
||||||
}
|
|
||||||
*ret = memcmp(signature, KDUMP_SIGNATURE, sizeof(signature)) == 0;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user