diff options
| -rw-r--r-- | ChangeLog | 4 | ||||
| -rw-r--r-- | NEWS | 1 | ||||
| -rw-r--r-- | libdw/ChangeLog | 4 | ||||
| -rw-r--r-- | libdw/libdw.map | 1 | ||||
| -rw-r--r-- | libdwfl/ChangeLog | 13 | ||||
| -rw-r--r-- | libdwfl/libdwfl.h | 4 | ||||
| -rw-r--r-- | libdwfl/libdwflP.h | 6 | ||||
| -rw-r--r-- | libdwfl/offline.c | 26 | ||||
| -rw-r--r-- | libdwfl/open.c | 30 | ||||
| -rw-r--r-- | tests/ChangeLog | 9 | ||||
| -rw-r--r-- | tests/Makefile.am | 4 | ||||
| -rw-r--r-- | tests/dwfl-report-offline-memory.c | 97 | ||||
| -rwxr-xr-x | tests/run-dwfl-report-offline-memory.sh | 26 |
13 files changed, 221 insertions, 4 deletions
@@ -1,3 +1,7 @@ +2022-09-13 Aleksei Vetrov <[email protected]> + + * NEWS (libdwfl): Add dwfl_report_offline_memory. + 2022-09-27 Taketo Kabe <[email protected]> * debuginfod/debuginfod-client.c: Correctly get timestamp when @@ -6,6 +6,7 @@ debuginfod: Add --disable-source-scan option. libdwfl: Add new function dwfl_get_debuginfod_client. Add new function dwfl_frame_reg. + Add new function dwfl_report_offline_memory. Version 0.187 diff --git a/libdw/ChangeLog b/libdw/ChangeLog index dd54afc2..9a798ff9 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,7 @@ +2022-09-13 Aleksei Vetrov <[email protected]> + + * libdw.map (ELFUTILS_0.188): Add dwfl_report_offline_memory. + 2022-08-09 Ulrich Drepper <[email protected]> * dwarf_next_cfi.c (dwarf_next_cfi): Don't skip processing the diff --git a/libdw/libdw.map b/libdw/libdw.map index 8f393438..5331ad45 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -371,4 +371,5 @@ ELFUTILS_0.188 { global: dwfl_get_debuginfod_client; dwfl_frame_reg; + dwfl_report_offline_memory; } ELFUTILS_0.186; diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 30f30b14..942f05d5 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,16 @@ +2022-09-13 Aleksei Vetrov <[email protected]> + + * libdwfl.h (dwfl_report_offline_memory): New function. + * libdwflP.h (__libdw_open_elf_memory): New internal function. + (dwfl_report_offline_memory): INTDECL. + * offline.c (dwfl_report_offline_memory): New function. + * open.c (decompress): Return DWFL_E_BADELF when fd is -1. + (libdw_open_elf): New argument use_elfp. Adding *elfp to elf if + true. + (__libdw_open_file): Pass false to libdw_open_elf. + (__libdw_open_elf_memory): New function. + (__libdw_open_elf): Pass false for libdw_open_elf. + 2022-07-28 Di Chen <[email protected]> * libdwfl.h (dwfl_frame_reg): New function. diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index edb537c2..9114f7f0 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -159,6 +159,10 @@ extern Dwfl_Module *dwfl_report_elf (Dwfl *dwfl, const char *name, extern Dwfl_Module *dwfl_report_offline (Dwfl *dwfl, const char *name, const char *file_name, int fd); +/* Similar, but report ELF from memory region. */ +extern Dwfl_Module *dwfl_report_offline_memory (Dwfl *dwfl, const char *name, + const char *file_name, + char *data, size_t size); /* Finish reporting the current set of modules to the library. If REMOVED is not null, it's called for each module that diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index a2949e74..011b5de9 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -631,6 +631,11 @@ extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok) internal_function; +/* Same as __libdw_open_file, but opens Elf handle from memory region. */ +extern Dwfl_Error __libdw_open_elf_memory (char *data, size_t size, Elf **elfp, + bool archive_ok) + internal_function; + /* Same as __libdw_open_file, but never closes the given file descriptor and ELF_K_AR is always an acceptable type. */ extern Dwfl_Error __libdw_open_elf (int fd, Elf **elfp) internal_function; @@ -760,6 +765,7 @@ INTDECL (dwfl_report_begin_add) INTDECL (dwfl_report_module) INTDECL (dwfl_report_segment) INTDECL (dwfl_report_offline) +INTDECL (dwfl_report_offline_memory) INTDECL (dwfl_report_end) INTDECL (dwfl_build_id_find_elf) INTDECL (dwfl_build_id_find_debuginfo) diff --git a/libdwfl/offline.c b/libdwfl/offline.c index 58ba4c36..499663e3 100644 --- a/libdwfl/offline.c +++ b/libdwfl/offline.c @@ -1,6 +1,7 @@ /* Recover relocatibility for addresses computed from debug information. Copyright (C) 2005-2009, 2012 Red Hat, Inc. Copyright (C) 2022 Mark J. Wielaard <[email protected]> + Copyright (C) 2022 Google LLC This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -252,6 +253,7 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd, { Dwfl_Module *mod = NULL; + /* elf_begin supports opening archives even with fd == -1 passed. */ Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive); if (unlikely (member == NULL)) /* Empty archive. */ { @@ -320,3 +322,27 @@ dwfl_report_offline (Dwfl *dwfl, const char *name, return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL); } INTDEF (dwfl_report_offline) + +Dwfl_Module * +dwfl_report_offline_memory (Dwfl *dwfl, const char *name, + const char *file_name, char *data, size_t size) +{ + if (dwfl == NULL) + return NULL; + + Elf *elf; + Dwfl_Error error = __libdw_open_elf_memory (data, size, &elf, true); + if (error != DWFL_E_NOERROR) + { + __libdwfl_seterrno (error); + return NULL; + } + /* It is ok to pass fd == -1 here, because libelf uses it as a value for + "no file opened" and supports working with files without fd, thanks to + the existence of the elf_memory function. */ + Dwfl_Module *mod = process_file (dwfl, name, file_name, -1, elf, NULL); + if (mod == NULL) + elf_end (elf); + return mod; +} +INTDEF (dwfl_report_offline_memory) diff --git a/libdwfl/open.c b/libdwfl/open.c index 77bd2bd9..da8b59a3 100644 --- a/libdwfl/open.c +++ b/libdwfl/open.c @@ -1,5 +1,6 @@ /* Decompression support for libdwfl: zlib (gzip), bzlib (bzip2) or lzma (xz). Copyright (C) 2009, 2016 Red Hat, Inc. + Copyright (C) 2022 Google LLC This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -53,6 +54,9 @@ static Dwfl_Error decompress (int fd __attribute__ ((unused)), Elf **elf) { Dwfl_Error error = DWFL_E_BADELF; + /* ELF cannot be decompressed, if there is no file descriptor. */ + if (fd == -1) + return error; void *buffer = NULL; size_t size = 0; @@ -124,11 +128,12 @@ what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *may_close_fd) static Dwfl_Error libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok, - bool never_close_fd, bool bad_elf_ok) + bool never_close_fd, bool bad_elf_ok, bool use_elfp) { bool may_close_fd = false; - Elf *elf = elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL); + Elf *elf = + use_elfp ? *elfp : elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL); Elf_Kind kind; Dwfl_Error error = what_kind (*fdp, &elf, &kind, &may_close_fd); @@ -194,11 +199,28 @@ libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok, Dwfl_Error internal_function __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok) { - return libdw_open_elf (fdp, elfp, close_on_fail, archive_ok, false, false); + return libdw_open_elf (fdp, elfp, close_on_fail, archive_ok, false, false, + false); +} + +Dwfl_Error internal_function +__libdw_open_elf_memory (char *data, size_t size, Elf **elfp, bool archive_ok) +{ + /* It is ok to use `fd == -1` here, because libelf uses it as a value for + "no file opened" and code supports working with this value, and also + `never_close_fd == false` is passed to prevent closing non-existant file. + The only caveat is in `decompress` method, which doesn't support + decompressing from memory, so reading compressed zImage using this method + won't work. */ + int fd = -1; + *elfp = elf_memory (data, size); + /* Allow using this ELF as reference for subsequent elf_begin calls. */ + (*elfp)->cmd = ELF_C_READ_MMAP_PRIVATE; + return libdw_open_elf (&fd, elfp, false, archive_ok, true, false, true); } Dwfl_Error internal_function __libdw_open_elf (int fd, Elf **elfp) { - return libdw_open_elf (&fd, elfp, false, true, true, true); + return libdw_open_elf (&fd, elfp, false, true, true, true, false); } diff --git a/tests/ChangeLog b/tests/ChangeLog index d10acfa0..6ac2c1e8 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,12 @@ +2022-09-13 Aleksei Vetrov <[email protected]> + + * Makefile.am (check_PROGRAMS): Add dwfl-report-offline-memory. + (TESTS): Add run-dwfl-report-offline-memory.sh. + (EXTRA_DIST): Likewise. + (dwfl_report_offline_memory_LDADD): New variable. + * dwfl-report-offline-memory.c: New file. + * run-dwfl-report-offline-memory.sh: Likewise. + 2022-09-13 Khem Raj <[email protected]> * Makefile.am (*_LDADD): Add libeu if needed for error. diff --git a/tests/Makefile.am b/tests/Makefile.am index 142b9c30..f680d3e1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,6 +47,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ alldts typeiter typeiter2 low_high_pc \ test-elf_cntl_gelf_getshdr dwflsyms dwfllines \ dwfl-report-elf-align dwfl-report-segment-contiguous \ + dwfl-report-offline-memory \ varlocs backtrace backtrace-child \ backtrace-data backtrace-dwarf debuglink debugaltlink \ buildid deleted deleted-lib.so aggregate_size peel_type \ @@ -149,6 +150,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-readelf-mixed-corenote.sh run-dwfllines.sh \ run-readelf-variant.sh run-readelf-fat-lto.sh \ run-dwfl-report-elf-align.sh run-addr2line-test.sh \ + run-dwfl-report-offline-memory.sh \ run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \ run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \ run-varlocs.sh run-exprlocs.sh run-varlocs-vars.sh run-funcretval.sh \ @@ -413,6 +415,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfile69.core.bz2 testfile69.so.bz2 \ testfile70.core.bz2 testfile70.exec.bz2 testfile71.bz2 \ run-dwfllines.sh run-dwfl-report-elf-align.sh \ + run-dwfl-report-offline-memory.sh \ testfile-dwfl-report-elf-align-shlib.so.bz2 \ testfilenolines.bz2 test-core-lib.so.bz2 test-core.core.bz2 \ test-core.exec.bz2 run-addr2line-test.sh \ @@ -711,6 +714,7 @@ test_elf_cntl_gelf_getshdr_LDADD = $(libelf) dwflsyms_LDADD = $(libdw) $(libelf) $(argp_LDADD) dwfllines_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD) dwfl_report_elf_align_LDADD = $(libeu) $(libdw) +dwfl_report_offline_memory_LDADD = $(libeu) $(libdw) dwfl_report_segment_contiguous_LDADD = $(libdw) $(libebl) $(libelf) varlocs_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD) backtrace_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD) diff --git a/tests/dwfl-report-offline-memory.c b/tests/dwfl-report-offline-memory.c new file mode 100644 index 00000000..837aca5e --- /dev/null +++ b/tests/dwfl-report-offline-memory.c @@ -0,0 +1,97 @@ +/* Test program for dwfl_report_offline_memory. + Copyright (C) 2022 Google LLC + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <config.h> +#include <fcntl.h> +#include <locale.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <unistd.h> +#include ELFUTILS_HEADER(dwfl) +#include "system.h" + + +static const Dwfl_Callbacks offline_callbacks = + { + .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), + .section_address = INTUSE(dwfl_offline_section_address), + }; + +static int +count_modules (Dwfl_Module *mod __attribute__ ((unused)), + void **userdata __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + Dwarf_Addr base __attribute__ ((unused)), void *arg) +{ + unsigned long long *counter = arg; + ++(*counter); + return DWARF_CB_OK; +} + +int +main (int argc, char **argv) +{ + /* We use no threads here which can interfere with handling a stream. */ + (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + if (argc != 3) + error (-1, 0, + "usage: dwfl_report_offline_memory [filename] " + "[expected number of modules]"); + + const char *fname = argv[1]; + int fd = open (fname, O_RDONLY); + if (fd < 0) + error (-1, 0, "can't open file %s: %s", fname, strerror (errno)); + size_t size = lseek (fd, 0, SEEK_END); + lseek (fd, 0, SEEK_SET); + char *data = malloc (size); + size_t bytes_read = read (fd, data, size); + assert (bytes_read == size); + close (fd); + + Dwfl *dwfl = dwfl_begin (&offline_callbacks); + assert (dwfl != NULL); + + Dwfl_Module *mod = + dwfl_report_offline_memory (dwfl, argv[1], argv[1], data, size); + assert (mod != NULL); + dwfl_report_end (dwfl, NULL, NULL); + + unsigned long long number_of_modules = 0; + ptrdiff_t offset = + dwfl_getmodules (dwfl, &count_modules, &number_of_modules, 0); + if (offset < 0) + error (1, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); + assert (offset == 0); + + char *endptr; + unsigned long long expected_number_of_modules = + strtoull (argv[2], &endptr, 0); + assert (endptr && !*endptr); + assert (number_of_modules == expected_number_of_modules); + + dwfl_end (dwfl); + free (data); + + return 0; +} diff --git a/tests/run-dwfl-report-offline-memory.sh b/tests/run-dwfl-report-offline-memory.sh new file mode 100755 index 00000000..644a45dc --- /dev/null +++ b/tests/run-dwfl-report-offline-memory.sh @@ -0,0 +1,26 @@ +#! /bin/sh +# Copyright (C) 2022 Google LLC +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. $srcdir/test-subr.sh + +testfiles testfile-dwfl-report-elf-align-shlib.so +testfiles testarchive64.a + +testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1 +testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3 + +exit 0 |
