https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #12 from Di Chen <dichen at redhat dot com> --- @fche no problem, thanks for merging it :D -- You are receiving this mail because: You are on the CC list for the bug.
Hi -
> The const variable BUFFER_SIZE is used only on the zip_files
> function witch is only available with LIBARCHIVE.
Thanks, merged as obvious.
- FChE
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 Frank Ch. Eigler <fche at redhat dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |FIXED Status|NEW |RESOLVED --- Comment #11 from Frank Ch. Eigler <fche at redhat dot com> --- further malloc_trim()s may be investigated in other spots. PR31103: debuginfod: periodically call malloc_trim(0) Add malloc_trim() for releasing memory which is allocated for temporary purposes, e.g. answering queries, adding data to the database during scans. This patch just adds one call after the groom cycle, but others could be added around webapi query handling or scanning ops too. Signed-off-by: Di Chen <dichen@redhat.com> (Sorry about committing with the wrong git-author!) -- You are receiving this mail because: You are on the CC list for the bug.
The const variable BUFFER_SIZE is used only on the zip_files function witch is only available with LIBARCHIVE. | ../../elfutils-0.191/src/srcfiles.cxx:81:18: error: unused variable 'BUFFER_SIZE' [-Werror,-Wunused-const-variable] | 81 | constexpr size_t BUFFER_SIZE = 8192; | | ^~~~~~~~~~~ Signed-off-by: Jose Quaresma <jose.quaresma@foundries.io> --- src/srcfiles.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/srcfiles.cxx b/src/srcfiles.cxx index 892737cc..09d50f8d 100644 --- a/src/srcfiles.cxx +++ b/src/srcfiles.cxx @@ -78,7 +78,9 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; /* Bug report address. */ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; +#ifdef HAVE_LIBARCHIVE constexpr size_t BUFFER_SIZE = 8192; +#endif /* Definitions of arguments for argp functions. */ static const struct argp_option options[] = -- 2.44.0
Hi -
> From: Di Chen <dichen@redhat.com>
> Date: Mon, 18 Mar 2024 09:06:19 +0800
> Subject: [PATCH] debuginfod.cxx: periodically malloc_trim()
>
> Add malloc_trim() for releasing memory which is allocated for temporary
> purposes, e.g. answering queries, adding data to the database during
> scans.
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=31103
>
> Signed-off-by: Di Chen <dichen@redhat.com>
> [...]
Thanks, will merge this with a bit of configury added.
- FChE
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #10 from Di Chen <dichen at redhat dot com> --- Yes, patch submitted: https://sourceware.org/pipermail/elfutils-devel/2024q1/006916.html -- You are receiving this mail because: You are on the CC list for the bug.
[-- Attachment #1.1: Type: text/plain, Size: 1231 bytes --] From 93cfe0b3e8d51eb18c5807e4b72c17920aefb422 Mon Sep 17 00:00:00 2001 From: Di Chen <dichen@redhat.com> Date: Mon, 18 Mar 2024 09:06:19 +0800 Subject: [PATCH] debuginfod.cxx: periodically malloc_trim() Add malloc_trim() for releasing memory which is allocated for temporary purposes, e.g. answering queries, adding data to the database during scans. https://sourceware.org/bugzilla/show_bug.cgi?id=31103 Signed-off-by: Di Chen <dichen@redhat.com> --- debuginfod/debuginfod.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index 72617848..6e1b43ad 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -70,6 +70,7 @@ extern "C" { #include <fcntl.h> #include <netdb.h> #include <math.h> +#include <malloc.h> #include <float.h> @@ -4225,6 +4226,7 @@ void groom() sqlite3_db_release_memory(db); // shrink the process if possible sqlite3_db_release_memory(dbq); // ... for both connections + malloc_trim(0); // PR31103: release memory allocated for temporary purposes debuginfod_pool_groom(); // and release any debuginfod_client objects we've been holding onto #if 0 /* PR31265: don't jettison cache unnecessarily */ -- 2.41.0 [-- Attachment #2: 0001-debuginfod.cxx-periodically-malloc_trim.patch --] [-- Type: text/x-patch, Size: 1236 bytes --] From 93cfe0b3e8d51eb18c5807e4b72c17920aefb422 Mon Sep 17 00:00:00 2001 From: Di Chen <dichen@redhat.com> Date: Mon, 18 Mar 2024 09:06:19 +0800 Subject: [PATCH] debuginfod.cxx: periodically malloc_trim() Add malloc_trim() for releasing memory which is allocated for temporary purposes, e.g. answering queries, adding data to the database during scans. https://sourceware.org/bugzilla/show_bug.cgi?id=31103 Signed-off-by: Di Chen <dichen@redhat.com> --- debuginfod/debuginfod.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index 72617848..6e1b43ad 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -70,6 +70,7 @@ extern "C" { #include <fcntl.h> #include <netdb.h> #include <math.h> +#include <malloc.h> #include <float.h> @@ -4225,6 +4226,7 @@ void groom() sqlite3_db_release_memory(db); // shrink the process if possible sqlite3_db_release_memory(dbq); // ... for both connections + malloc_trim(0); // PR31103: release memory allocated for temporary purposes debuginfod_pool_groom(); // and release any debuginfod_client objects we've been holding onto #if 0 /* PR31265: don't jettison cache unnecessarily */ -- 2.41.0
Hi Martin,
On Wed, Mar 6, 2024 at 2:23 PM Martin Rodriguez Reboredo
<yakoyoku@gmail.com> wrote:
>
> diff --git a/tests/dwfl-offline-address.c b/tests/dwfl-offline-address.c
> new file mode 100644
> index 00000000..9a33b95a
> --- /dev/null
> +++ b/tests/dwfl-offline-address.c
> @@ -0,0 +1,43 @@
> +#include <config.h>
> +#include <assert.h>
> +#include <inttypes.h>
> +#include <sys/types.h>
> +#include <stdio.h>
> +#include <stdio_ext.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <locale.h>
> +#include <argp.h>
> +#include ELFUTILS_HEADER(dwfl)
> +#include <dwarf.h>
> +#include "system.h"
> +
> +#define OFFLINE_REDZONE 0x10000
> +
> +static const Dwfl_Callbacks offline_callbacks =
> + {
> + .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
> + .section_address = INTUSE(dwfl_offline_section_address),
> + };
> +
> +int
> +main (int argc, char **argv)
> +{
> + Dwfl *dwfl = dwfl_begin (&offline_callbacks);
> + assert (dwfl != NULL);
> +
> + if (dwfl_get_offline_next_address (dwfl) != OFFLINE_REDZONE)
> + {
> + dwfl_end (dwfl);
> + return 1;
> + }
> +
> + int result = 0;
> + dwfl_set_offline_next_address (dwfl, 0);
> + if (dwfl_get_offline_next_address (dwfl) != 0)
> + result = 1;
> +
> + dwfl_end (dwfl);
> +
> + return result;
> +}
This test needs to be run under a testrun command in a tests/run-*.sh script
in order to have the result recorded by 'make check'.
Also there are a few places in libdwfl/ and src/ where we manually set
dwfl->offline_next_address. We could use the setter here instead.
Aaron
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #9 from Frank Ch. Eigler <fche at redhat dot com> --- Yeah, OK, for a not-too-busy one, that sounds okay. Can you show a proposed final diff? -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #8 from Di Chen <dichen at redhat dot com> --- Got it. I have used GDB to make debuginfod stop at 1) before malloc_trim(0) $ cat /proc/$$/statm 228487 3456 2976 48 0 19049 0 2) after malloc_trim(0) $ cat /proc/$$/statm 228462 3456 2976 48 0 19024 0 debuginfod's VmSize and VmData did shrink some. $ cat /proc/$$/status Name: debuginfod ... VmSize: 913948 kB -> 913848 kB VmData: 76060 kB -> 75960 kB -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #7 from Frank Ch. Eigler <fche at redhat dot com> --- Right, the linux kernel does not share enough memory consumption data in rusage, so you need to read /proc/self/statm or such and compare its snapshots. For memory release, it's not so much the size of the database that matters, but an amount of -activity- on the database before the release attempt. It's the memory allocation for temporary purposes (answering queries, adding data to the database during scans) that we'd be hoping to release. -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #6 from Di Chen <dichen at redhat dot com> --- Thanks Frank, I have debugged with rusage, but the difference between "during" and "post" is not that obvious. I believe it's due to my small .debuginfod.sqlite. ``` (gdb) p during $2 = {ru_utime = {tv_sec = 0, tv_usec = 21790}, ru_stime = {tv_sec = 0, tv_usec = 29003}, {ru_maxrss = 103836, __ru_maxrss_word = 103836}, { ru_ixrss = 0, __ru_ixrss_word = 0}, {ru_idrss = 0, __ru_idrss_word = 0}, { ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 967, __ru_minflt_word = 967}, {ru_majflt = 0, __ru_majflt_word = 0}, { ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, {ru_oublock = 128, __ru_oublock_word = 128}, { ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, { ru_nvcsw = 1229, __ru_nvcsw_word = 1229}, {ru_nivcsw = 1, __ru_nivcsw_word = 1}} (gdb) p post $3 = {ru_utime = {tv_sec = 0, tv_usec = 21790}, ru_stime = {tv_sec = 0, tv_usec = 30393}, {ru_maxrss = 103836, __ru_maxrss_word = 103836}, { ru_ixrss = 0, __ru_ixrss_word = 0}, {ru_idrss = 0, __ru_idrss_word = 0}, { ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 967, __ru_minflt_word = 967}, {ru_majflt = 0, __ru_majflt_word = 0}, { ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, {ru_oublock = 128, __ru_oublock_word = 128}, { ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, { ru_nvcsw = 1273, __ru_nvcsw_word = 1273}, {ru_nivcsw = 1, __ru_nivcsw_word = 1}} [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): grooming database [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): database record counts: [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): file d/e 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): file s 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): archive d/e 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): archive sref 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): archive sdef 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): buildids 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): filenames 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): fileparts 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): files scanned (#) 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): files scanned (mb) 0 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): index db size (mb) 21 [Thu 14 Mar 2024 03:22:47 AM GMT] (4738/4749): groomed database in 0.0129799s ``` Do you know where I can get a big .debuginfod.sqlite, so that I can measure the performance on it? -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31480 Aaron Merey <amerey at redhat dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- See Also| |https://sourceware.org/bugz | |illa/show_bug.cgi?id=31478 -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31480 Bug ID: 31480 Summary: debuginfod_find_debuginfo returns corrupt debuginfo file when out of memory Product: elfutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: debuginfod Assignee: unassigned at sourceware dot org Reporter: amerey at redhat dot com CC: elfutils-devel at sourceware dot org Target Milestone: --- This bug has been seen when gdb ran out of memory while downloading from debuginfod. See the following PR for more information: https://sourceware.org/bugzilla/show_bug.cgi?id=31478 It may be that libdebuginfod fails to unlink a partially downloaded file when out-of-memory conditions are reached. Reproducing this bug might be tricky. We'll need to experiment with running gdb/debuginfod in a low memory environment. -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #5 from Frank Ch. Eigler <fche at redhat dot com> --- Yeah, not surprised that there are no leaks. What this malloc_trim() and the preceding sqlite3_db_release_memory() calls are supposed to do is to release memory back to the operating system. So perhaps a getrusage() call in between could be informative. i.e.: struct rusage pre,during,post; getrusage(RUSAGE_SELF, &pre); sqlite3_db_release_memory( ...); getrusage(RUSAGE_SELF, &during); malloc_trim(); getrusage(RUSAGE_SELF, &post); and then the ru_idrss value should show some decrease ... except on linux, ru_idrss is not supplied by the kernel. So instead something like the VmSize or VmData fields in /proc/self/status, ugh? -- You are receiving this mail because: You are on the CC list for the bug.
https://sourceware.org/bugzilla/show_bug.cgi?id=31103 --- Comment #4 from Di Chen <dichen at redhat dot com> --- @fche, @mjw, @amerey I don't have many clue about how to debug/measure this memory fluctuation problem. What I did: 1) use GDB to check the call graph. thread_main_groom -> groom -> sqlite3_db_release_memory(db) -> sqlite3_db_release_memory(dbq) 2) use valgrind to run a leak-check, but found nothing. $ valgrind --tool=memcheck --leak-check=full ./debuginfod/debuginfod Could you give me some suggestion? -- You are receiving this mail because: You are on the CC list for the bug.
On Mon, Mar 11, 2024 at 07:05:53AM -0700, Khem Raj wrote: > On Mon, Mar 11, 2024 at 4:23 AM Mark Wielaard <mark@klomp.org> wrote: > > > - 5: make check ( failure ) > > > Logs: > > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/stdio > > > - test-suite.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/test-suite_log > > > > That was clearly not your fault. There seems to be a space missing in > > the make -kcheck command (after the -k). I'll go look in the builder > > sources where that came from. > > Thanks Mark ! Found it, it was a silly missing ',' between strings, causing "-k" "check" to become one string, instead of two... doh. https://sourceware.org/cgit/builder/commit/?id=753c1b3e9b56949af4600b9a43424ce5004361c2 Cheers, Mark
On Mon, Mar 11, 2024 at 4:23 AM Mark Wielaard <mark@klomp.org> wrote: > > Hi Khem, > > On Mon, 2024-03-11 at 02:33 +0000, builder@sourceware.org wrote: > > A new failure has been detected on builder elfutils-snapshots-coverage while building elfutils. > > > > Full details are available at: > > https://builder.sourceware.org/buildbot/#/builders/250/builds/105 > > > > Build state: failed test (failure) > > Revision: d74f4c1d572fbeb7454a2ffa02cbc955ea24780d > > Worker: snapshots > > Build Reason: (unknown) > > Blamelist: Khem Raj <raj.khem@gmail.com> > > > > Steps: > > > > - 0: worker_preparation ( success ) > > > > - 1: git checkout ( success ) > > Logs: > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/1/logs/stdio > > > > - 2: autoreconf ( success ) > > Logs: > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/2/logs/stdio > > > > - 3: configure ( success ) > > Logs: > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/stdio > > - config.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/config_log > > > > - 4: make ( warnings ) > > Logs: > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/stdio > > - warnings (3): https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/warnings__3_ > > > > - 5: make check ( failure ) > > Logs: > > - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/stdio > > - test-suite.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/test-suite_log > > That was clearly not your fault. There seems to be a space missing in > the make -kcheck command (after the -k). I'll go look in the builder > sources where that came from. Thanks Mark ! > > Cheers, > > Mark
Hi Khem,
On Mon, 2024-03-11 at 02:33 +0000, builder@sourceware.org wrote:
> A new failure has been detected on builder elfutils-snapshots-coverage while building elfutils.
>
> Full details are available at:
> https://builder.sourceware.org/buildbot/#/builders/250/builds/105
>
> Build state: failed test (failure)
> Revision: d74f4c1d572fbeb7454a2ffa02cbc955ea24780d
> Worker: snapshots
> Build Reason: (unknown)
> Blamelist: Khem Raj <raj.khem@gmail.com>
>
> Steps:
>
> - 0: worker_preparation ( success )
>
> - 1: git checkout ( success )
> Logs:
> - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/1/logs/stdio
>
> - 2: autoreconf ( success )
> Logs:
> - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/2/logs/stdio
>
> - 3: configure ( success )
> Logs:
> - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/stdio
> - config.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/config_log
>
> - 4: make ( warnings )
> Logs:
> - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/stdio
> - warnings (3): https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/warnings__3_
>
> - 5: make check ( failure )
> Logs:
> - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/stdio
> - test-suite.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/test-suite_log
That was clearly not your fault. There seems to be a space missing in
the make -kcheck command (after the -k). I'll go look in the builder
sources where that came from.
Cheers,
Mark
Hi Mark,
Could you please review these patches, I have splited patch v2 1/5 to patch v3 1/6 and 2/6.
Thanks,
Ying
在 2024/3/5 17:51, Ying Huang 写道:
> From: Ying Huang <ying.huang@oss.cipunited.com>
>
> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com>
> ---
> backends/Makefile.am | 6 +-
> backends/mips_init.c | 52 ++++
> backends/mips_reloc.def | 93 +++++++
> backends/mips_symbol.c | 63 +++++
> libebl/eblopenbackend.c | 2 +
> libelf/libelfP.h | 3 +
> tests/libelf.h | 541 ++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 758 insertions(+), 2 deletions(-)
> create mode 100644 backends/mips_init.c
> create mode 100644 backends/mips_reloc.def
> create mode 100644 backends/mips_symbol.c
> create mode 100644 tests/libelf.h
>
> diff --git a/backends/Makefile.am b/backends/Makefile.am
> index bbb2aac7..b946fd30 100644
> --- a/backends/Makefile.am
> +++ b/backends/Makefile.am
> @@ -37,7 +37,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
> noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
>
> modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
> - m68k bpf riscv csky loongarch arc
> + m68k bpf riscv csky loongarch arc mips
>
> i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
> i386_retval.c i386_regs.c i386_auxv.c \
> @@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
>
> arc_SRCS = arc_init.c arc_symbol.c
>
> +mips_SRCS = mips_init.c mips_symbol.c
> +
> libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
> $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
> $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \
> $(ppc64_SRCS) $(s390_SRCS) \
> $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \
> - $(loongarch_SRCS) $(arc_SRCS)
> + $(loongarch_SRCS) $(arc_SRCS) $(mips_SRCS)
>
> libebl_backends_pic_a_SOURCES =
> am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os)
> diff --git a/backends/mips_init.c b/backends/mips_init.c
> new file mode 100644
> index 00000000..cedd08ca
> --- /dev/null
> +++ b/backends/mips_init.c
> @@ -0,0 +1,52 @@
> +/* Initialization of MIPS specific backend library.
> + Copyright (C) 2024 CIP United Inc.
> + This file is part of elfutils.
> +
> + This file is free software; you can redistribute it and/or modify
> + it under the terms of either
> +
> + * the GNU Lesser General Public License as published by the Free
> + Software Foundation; either version 3 of the License, or (at
> + your option) any later version
> +
> + or
> +
> + * the GNU General Public License as published by the Free
> + Software Foundation; either version 2 of the License, or (at
> + your option) any later version
> +
> + or both in parallel, as here.
> +
> + 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 copies of the GNU General Public License and
> + the GNU Lesser General Public License along with this program. If
> + not, see <http://www.gnu.org/licenses/>. */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#define BACKEND mips_
> +#define RELOC_PREFIX R_MIPS_
> +#include "libebl_CPU.h"
> +#include "libelfP.h"
> +
> +#define RELOC_TYPE_ID(type) ((type) & 0xff)
> +
> +/* This defines the common reloc hooks based on mips_reloc.def. */
> +#include "common-reloc.c"
> +
> +Ebl *
> +mips_init (Elf *elf __attribute__ ((unused)),
> + GElf_Half machine __attribute__ ((unused)),
> + Ebl *eh)
> +{
> + /* We handle it. */
> + mips_init_reloc (eh);
> + HOOK (eh, reloc_simple_type);
> + return eh;
> +}
> diff --git a/backends/mips_reloc.def b/backends/mips_reloc.def
> new file mode 100644
> index 00000000..5120980c
> --- /dev/null
> +++ b/backends/mips_reloc.def
> @@ -0,0 +1,93 @@
> +/* List the relocation types for MIPS. -*- C -*-
> + Copyright (C) 2024 CIP United Inc.
> + This file is part of elfutils.
> +
> + This file is free software; you can redistribute it and/or modify
> + it under the terms of either
> +
> + * the GNU Lesser General Public License as published by the Free
> + Software Foundation; either version 3 of the License, or (at
> + your option) any later version
> +
> + or
> +
> + * the GNU General Public License as published by the Free
> + Software Foundation; either version 2 of the License, or (at
> + your option) any later version
> +
> + or both in parallel, as here.
> +
> + 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 copies of the GNU General Public License and
> + the GNU Lesser General Public License along with this program. If
> + not, see <http://www.gnu.org/licenses/>. */
> +
> +/* NAME, REL|EXEC|DYN */
> +
> +
> +RELOC_TYPE (NONE, REL|EXEC|DYN)
> +RELOC_TYPE (16, REL|EXEC|DYN)
> +RELOC_TYPE (32, REL)
> +RELOC_TYPE (REL32, REL|EXEC|DYN)
> +RELOC_TYPE (26, REL|DYN)
> +RELOC_TYPE (HI16, REL)
> +RELOC_TYPE (LO16, REL|EXEC|DYN)
> +RELOC_TYPE (GPREL16, REL|EXEC|DYN)
> +RELOC_TYPE (LITERAL, REL|EXEC|DYN)
> +RELOC_TYPE (GOT16, REL|EXEC|DYN)
> +RELOC_TYPE (PC16, REL)
> +RELOC_TYPE (CALL16, REL)
> +RELOC_TYPE (GPREL32, REL)
> +RELOC_TYPE (SHIFT5, REL)
> +RELOC_TYPE (SHIFT6, REL)
> +RELOC_TYPE (64, REL)
> +RELOC_TYPE (GOT_DISP, REL)
> +RELOC_TYPE (GOT_PAGE, REL)
> +RELOC_TYPE (GOT_OFST, REL)
> +RELOC_TYPE (GOT_HI16, REL)
> +RELOC_TYPE (GOT_LO16, REL)
> +RELOC_TYPE (SUB, REL)
> +RELOC_TYPE (INSERT_A, REL)
> +RELOC_TYPE (INSERT_B, REL)
> +RELOC_TYPE (DELETE, REL)
> +RELOC_TYPE (HIGHER, REL)
> +RELOC_TYPE (HIGHEST, REL)
> +RELOC_TYPE (CALL_HI16, REL)
> +RELOC_TYPE (CALL_LO16, REL)
> +RELOC_TYPE (SCN_DISP, REL)
> +RELOC_TYPE (REL16, REL)
> +RELOC_TYPE (ADD_IMMEDIATE, REL)
> +RELOC_TYPE (PJUMP, REL)
> +RELOC_TYPE (RELGOT, REL)
> +RELOC_TYPE (JALR, REL)
> +RELOC_TYPE (TLS_DTPMOD32, DYN)
> +RELOC_TYPE (TLS_DTPREL32, REL)
> +RELOC_TYPE (TLS_DTPMOD64, DYN)
> +RELOC_TYPE (TLS_DTPREL64, REL)
> +RELOC_TYPE (TLS_GD, REL)
> +RELOC_TYPE (TLS_LDM, REL)
> +RELOC_TYPE (TLS_DTPREL_HI16, REL)
> +RELOC_TYPE (TLS_DTPREL_LO16, REL)
> +RELOC_TYPE (TLS_GOTTPREL, REL)
> +RELOC_TYPE (TLS_TPREL32, REL)
> +RELOC_TYPE (TLS_TPREL64, REL)
> +RELOC_TYPE (TLS_TPREL_HI16, REL)
> +RELOC_TYPE (TLS_TPREL_LO16, REL)
> +RELOC_TYPE (GLOB_DAT, REL)
> +RELOC_TYPE (PC21_S2, REL)
> +RELOC_TYPE (PC26_S2, REL)
> +RELOC_TYPE (PC18_S3, REL)
> +RELOC_TYPE (PC19_S2, REL)
> +RELOC_TYPE (PCHI16, REL)
> +RELOC_TYPE (PCLO16, REL)
> +RELOC_TYPE (COPY, REL)
> +RELOC_TYPE (JUMP_SLOT, REL)
> +RELOC_TYPE (PC32, REL)
> +RELOC_TYPE (EH, REL)
> +RELOC_TYPE (GNU_REL16_S2, REL)
> +RELOC_TYPE (GNU_VTINHERIT, REL)
> +RELOC_TYPE (GNU_VTENTRY, REL)
> diff --git a/backends/mips_symbol.c b/backends/mips_symbol.c
> new file mode 100644
> index 00000000..f2a46495
> --- /dev/null
> +++ b/backends/mips_symbol.c
> @@ -0,0 +1,63 @@
> +/* MIPS specific symbolic name handling.
> + Copyright (C) 2024 CIP United Inc.
> + This file is part of elfutils.
> +
> + This file is free software; you can redistribute it and/or modify
> + it under the terms of either
> +
> + * the GNU Lesser General Public License as published by the Free
> + Software Foundation; either version 3 of the License, or (at
> + your option) any later version
> +
> + or
> +
> + * the GNU General Public License as published by the Free
> + Software Foundation; either version 2 of the License, or (at
> + your option) any later version
> +
> + or both in parallel, as here.
> +
> + 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 copies of the GNU General Public License and
> + the GNU Lesser General Public License along with this program. If
> + not, see <http://www.gnu.org/licenses/>. */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <system.h>
> +
> +#include <elf.h>
> +#include <stddef.h>
> +#include <string.h>
> +#include <stdio.h>
> +#define BACKEND mips_
> +#include "libebl_CPU.h"
> +#include "libelfP.h"
> +
> +/* Check for the simple reloc types. */
> +Elf_Type
> +mips_reloc_simple_type (Ebl *ebl, int type,
> + int *addsub __attribute__ ((unused)))
> +{
> + int typeNew = type;
> + if(ebl->elf->class == ELFCLASS64)
> + typeNew = ELF64_MIPS_R_TYPE1(type);
> + switch (typeNew)
> + {
> + case R_MIPS_64:
> + return ELF_T_XWORD;
> + case R_MIPS_32:
> + return ELF_T_WORD;
> + case R_MIPS_16:
> + return ELF_T_HALF;
> +
> + default:
> + return ELF_T_NUM;
> + }
> +}
> diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
> index 084a1544..a5f7467a 100644
> --- a/libebl/eblopenbackend.c
> +++ b/libebl/eblopenbackend.c
> @@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl *);
> Ebl *csky_init (Elf *, GElf_Half, Ebl *);
> Ebl *loongarch_init (Elf *, GElf_Half, Ebl *);
> Ebl *arc_init (Elf *, GElf_Half, Ebl *);
> +Ebl *mips_init (Elf *, GElf_Half, Ebl *);
>
> /* This table should contain the complete list of architectures as far
> as the ELF specification is concerned. */
> @@ -154,6 +155,7 @@ static const struct
> { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB },
> { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB },
> { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB },
> + { mips_init, "elf_mips", "mips", 4, EM_MIPS, 0, 0 },
> };
> #define nmachines (sizeof (machines) / sizeof (machines[0]))
>
> diff --git a/libelf/libelfP.h b/libelf/libelfP.h
> index ed061abb..bdd2cc6a 100644
> --- a/libelf/libelfP.h
> +++ b/libelf/libelfP.h
> @@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
> #define INVALID_NDX(ndx, type, data) \
> unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
>
> +#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
> +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
> +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
> #endif /* libelfP.h */
> diff --git a/tests/libelf.h b/tests/libelf.h
> new file mode 100644
> index 00000000..d3f057b4
> --- /dev/null
> +++ b/tests/libelf.h
> @@ -0,0 +1,541 @@
> +/* Interface for libelf.
> + Copyright (C) 1998-2010, 2015 Red Hat, Inc.
> + This file is part of elfutils.
> +
> + This file is free software; you can redistribute it and/or modify
> + it under the terms of either
> +
> + * the GNU Lesser General Public License as published by the Free
> + Software Foundation; either version 3 of the License, or (at
> + your option) any later version
> +
> + or
> +
> + * the GNU General Public License as published by the Free
> + Software Foundation; either version 2 of the License, or (at
> + your option) any later version
> +
> + or both in parallel, as here.
> +
> + 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 copies of the GNU General Public License and
> + the GNU Lesser General Public License along with this program. If
> + not, see <http://www.gnu.org/licenses/>. */
> +
> +#ifndef _LIBELF_H
> +#define _LIBELF_H 1
> +
> +#include <stdint.h>
> +#include <sys/types.h>
> +
> +/* Get the ELF types. */
> +#include <elf.h>
> +
> +#ifndef SHF_COMPRESSED
> + /* Older glibc elf.h might not yet define the ELF compression types. */
> + #define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
> +
> + /* Section compression header. Used when SHF_COMPRESSED is set. */
> +
> + typedef struct
> + {
> + Elf32_Word ch_type; /* Compression format. */
> + Elf32_Word ch_size; /* Uncompressed data size. */
> + Elf32_Word ch_addralign; /* Uncompressed data alignment. */
> + } Elf32_Chdr;
> +
> + typedef struct
> + {
> + Elf64_Word ch_type; /* Compression format. */
> + Elf64_Word ch_reserved;
> + Elf64_Xword ch_size; /* Uncompressed data size. */
> + Elf64_Xword ch_addralign; /* Uncompressed data alignment. */
> + } Elf64_Chdr;
> +
> + /* Legal values for ch_type (compression algorithm). */
> + #define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */
> + #define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */
> + #define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */
> + #define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */
> + #define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */
> +#endif
> +
> +#ifndef ELFCOMPRESS_ZSTD
> + /* So ZSTD compression can be used even with an old system elf.h. */
> + #define ELFCOMPRESS_ZSTD 2 /* Zstandard algorithm. */
> +#endif
> +
> +#ifndef SHT_RELR
> + /* So RELR defines/typedefs can be used even with an old system elf.h. */
> + #define SHT_RELR 19 /* RELR relative relocations */
> +
> + /* RELR relocation table entry */
> + typedef Elf32_Word Elf32_Relr;
> + typedef Elf64_Xword Elf64_Relr;
> +
> + #define DT_RELRSZ 35 /* Total size of RELR relative relocations */
> + #define DT_RELR 36 /* Address of RELR relative relocations */
> + #define DT_RELRENT 37 /* Size of one RELR relative relocaction */
> +#endif
> +
> +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
> +# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
> +# define __deprecated_attribute__ __attribute__ ((__deprecated__))
> +# define __pure_attribute__ __attribute__ ((__pure__))
> +# define __const_attribute__ __attribute__ ((__const__))
> +#else
> +# define __nonnull_attribute__(...)
> +# define __deprecated_attribute__
> +# define __pure_attribute__
> +# define __const_attribute__
> +#endif
> +
> +#if __GNUC__ < 4
> +#define __noreturn_attribute__
> +#else
> +#define __noreturn_attribute__ __attribute__ ((noreturn))
> +#endif
> +
> +#ifdef __GNUC_STDC_INLINE__
> +# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
> +#else
> +# define __libdw_extern_inline extern __inline
> +#endif
> +
> +/* Known translation types. */
> +typedef enum
> +{
> + ELF_T_BYTE, /* unsigned char */
> + ELF_T_ADDR, /* Elf32_Addr, Elf64_Addr, ... */
> + ELF_T_DYN, /* Dynamic section record. */
> + ELF_T_EHDR, /* ELF header. */
> + ELF_T_HALF, /* Elf32_Half, Elf64_Half, ... */
> + ELF_T_OFF, /* Elf32_Off, Elf64_Off, ... */
> + ELF_T_PHDR, /* Program header. */
> + ELF_T_RELA, /* Relocation entry with addend. */
> + ELF_T_REL, /* Relocation entry. */
> + ELF_T_SHDR, /* Section header. */
> + ELF_T_SWORD, /* Elf32_Sword, Elf64_Sword, ... */
> + ELF_T_SYM, /* Symbol record. */
> + ELF_T_WORD, /* Elf32_Word, Elf64_Word, ... */
> + ELF_T_XWORD, /* Elf32_Xword, Elf64_Xword, ... */
> + ELF_T_SXWORD, /* Elf32_Sxword, Elf64_Sxword, ... */
> + ELF_T_VDEF, /* Elf32_Verdef, Elf64_Verdef, ... */
> + ELF_T_VDAUX, /* Elf32_Verdaux, Elf64_Verdaux, ... */
> + ELF_T_VNEED, /* Elf32_Verneed, Elf64_Verneed, ... */
> + ELF_T_VNAUX, /* Elf32_Vernaux, Elf64_Vernaux, ... */
> + ELF_T_NHDR, /* Elf32_Nhdr, Elf64_Nhdr, ... */
> + ELF_T_SYMINFO, /* Elf32_Syminfo, Elf64_Syminfo, ... */
> + ELF_T_MOVE, /* Elf32_Move, Elf64_Move, ... */
> + ELF_T_LIB, /* Elf32_Lib, Elf64_Lib, ... */
> + ELF_T_GNUHASH, /* GNU-style hash section. */
> + ELF_T_AUXV, /* Elf32_auxv_t, Elf64_auxv_t, ... */
> + ELF_T_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
> + ELF_T_NHDR8, /* Special GNU Properties note. Same as Nhdr,
> + except padding. */
> + ELF_T_RELR, /* Relative relocation entry. */
> + /* Keep this the last entry. */
> + ELF_T_NUM
> +} Elf_Type;
> +
> +/* Descriptor for data to be converted to or from memory format. */
> +typedef struct
> +{
> + void *d_buf; /* Pointer to the actual data. */
> + Elf_Type d_type; /* Type of this piece of data. */
> + unsigned int d_version; /* ELF version. */
> + size_t d_size; /* Size in bytes. */
> + int64_t d_off; /* Offset into section. */
> + size_t d_align; /* Alignment in section. */
> +} Elf_Data;
> +
> +
> +/* Commands for `...'. */
> +typedef enum
> +{
> + ELF_C_NULL, /* Nothing, terminate, or compute only. */
> + ELF_C_READ, /* Read .. */
> + ELF_C_RDWR, /* Read and write .. */
> + ELF_C_WRITE, /* Write .. */
> + ELF_C_CLR, /* Clear flag. */
> + ELF_C_SET, /* Set flag. */
> + ELF_C_FDDONE, /* Signal that file descriptor will not be
> + used anymore. */
> + ELF_C_FDREAD, /* Read rest of data so that file descriptor
> + is not used anymore. */
> + /* The following are extensions. */
> + ELF_C_READ_MMAP, /* Read, but mmap the file if possible. */
> + ELF_C_RDWR_MMAP, /* Read and write, with mmap. */
> + ELF_C_WRITE_MMAP, /* Write, with mmap. */
> + ELF_C_READ_MMAP_PRIVATE, /* Read, but memory is writable, results are
> + not written to the file. */
> + ELF_C_EMPTY, /* Copy basic file data but not the content. */
> + /* Keep this the last entry. */
> + ELF_C_NUM
> +} Elf_Cmd;
> +
> +
> +/* Flags for the ELF structures. */
> +enum
> +{
> + ELF_F_DIRTY = 0x1,
> +#define ELF_F_DIRTY ELF_F_DIRTY
> + ELF_F_LAYOUT = 0x4,
> +#define ELF_F_LAYOUT ELF_F_LAYOUT
> + ELF_F_PERMISSIVE = 0x8
> +#define ELF_F_PERMISSIVE ELF_F_PERMISSIVE
> +};
> +
> +/* Flags for elf_compress[_gnu]. */
> +enum
> +{
> + ELF_CHF_FORCE = 0x1
> +#define ELF_CHF_FORCE ELF_CHF_FORCE
> +};
> +
> +/* Identification values for recognized object files. */
> +typedef enum
> +{
> + ELF_K_NONE, /* Unknown. */
> + ELF_K_AR, /* Archive. */
> + ELF_K_COFF, /* Stupid old COFF. */
> + ELF_K_ELF, /* ELF file. */
> + /* Keep this the last entry. */
> + ELF_K_NUM
> +} Elf_Kind;
> +
> +
> +/* Archive member header. */
> +typedef struct
> +{
> + char *ar_name; /* Name of archive member. */
> + time_t ar_date; /* File date. */
> + uid_t ar_uid; /* User ID. */
> + gid_t ar_gid; /* Group ID. */
> + mode_t ar_mode; /* File mode. */
> + int64_t ar_size; /* File size. */
> + char *ar_rawname; /* Original name of archive member. */
> +} Elf_Arhdr;
> +
> +
> +/* Archive symbol table entry. */
> +typedef struct
> +{
> + char *as_name; /* Symbol name. */
> + size_t as_off; /* Offset for this file in the archive. */
> + unsigned long int as_hash; /* Hash value of the name. */
> +} Elf_Arsym;
> +
> +
> +/* Descriptor for the ELF file. */
> +typedef struct Elf Elf;
> +
> +/* Descriptor for ELF file section. */
> +typedef struct Elf_Scn Elf_Scn;
> +
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Return descriptor for ELF file to work according to CMD. */
> +extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
> +
> +/* Create a clone of an existing ELF descriptor. */
> + extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Create descriptor for memory region. */
> +extern Elf *elf_memory (char *__image, size_t __size);
> +
> +/* Advance archive descriptor to next element. */
> +extern Elf_Cmd elf_next (Elf *__elf);
> +
> +/* Free resources allocated for ELF. */
> +extern int elf_end (Elf *__elf);
> +
> +/* Update ELF descriptor and write file to disk. */
> +extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Determine what kind of file is associated with ELF. */
> +extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
> +
> +/* Get the base offset for an object file. */
> +extern int64_t elf_getbase (Elf *__elf);
> +
> +
> +/* Retrieve file identification data. */
> +extern char *elf_getident (Elf *__elf, size_t *__nbytes);
> +
> +/* Retrieve class-dependent object file header. */
> +extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
> +
> +/* Create ELF header if none exists. */
> +extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
> +
> +/* Get the number of program headers in the ELF file. If the file uses
> + more headers than can be represented in the e_phnum field of the ELF
> + header the information from the sh_info field in the zeroth section
> + header is used. */
> +extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
> +
> +/* Retrieve class-dependent program header table. */
> +extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
> +
> +/* Create ELF program header. */
> +extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
> +
> +
> +/* Get section at INDEX. */
> +extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
> +
> +/* Get section at OFFSET. */
> +extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
> +
> +/* Get index of section. */
> +extern size_t elf_ndxscn (Elf_Scn *__scn);
> +
> +/* Get section with next section index. */
> +extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
> +
> +/* Create a new section and append it at the end of the table. */
> +extern Elf_Scn *elf_newscn (Elf *__elf);
> +
> +/* Get the section index of the extended section index table for the
> + given symbol table. */
> +extern int elf_scnshndx (Elf_Scn *__scn);
> +
> +/* Get the number of sections in the ELF file. If the file uses more
> + sections than can be represented in the e_shnum field of the ELF
> + header the information from the sh_size field in the zeroth section
> + header is used. */
> +extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
> +/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
> + It was agreed to make the same functionality available under a different
> + name and obsolete the old name. */
> +extern int elf_getshnum (Elf *__elf, size_t *__dst)
> + __deprecated_attribute__;
> +
> +
> +/* Get the section index of the section header string table in the ELF
> + file. If the index cannot be represented in the e_shstrndx field of
> + the ELF header the information from the sh_link field in the zeroth
> + section header is used. */
> +extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
> +/* Sun messed up the implementation of 'elf_getshstrndx' in their
> + implementation. It was agreed to make the same functionality available
> + under a different name and obsolete the old name. */
> +extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
> + __deprecated_attribute__;
> +
> +
> +/* Retrieve section header of ELFCLASS32 binary. */
> +extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
> +/* Similar for ELFCLASS64. */
> +extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
> +
> +/* Returns compression header for a section if section data is
> + compressed. Returns NULL and sets elf_errno if the section isn't
> + compressed or an error occurred. */
> +extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
> +extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
> +
> +/* Compress or decompress the data of a section and adjust the section
> + header.
> +
> + elf_compress works by setting or clearing the SHF_COMPRESS flag
> + from the section Shdr and will encode or decode a Elf32_Chdr or
> + Elf64_Chdr at the start of the section data. elf_compress_gnu will
> + encode or decode any section, but is traditionally only used for
> + sections that have a name starting with ".debug" when
> + uncompressed or ".zdebug" when compressed and stores just the
> + uncompressed size. The GNU compression method is deprecated and
> + should only be used for legacy support.
> +
> + elf_compress takes a compression type that should be either zero to
> + decompress or an ELFCOMPRESS algorithm to use for compression.
> + Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
> + elf_compress_gnu will compress in the traditional GNU compression
> + format when compress is one and decompress the section data when
> + compress is zero.
> +
> + The FLAGS argument can be zero or ELF_CHF_FORCE. If FLAGS contains
> + ELF_CHF_FORCE then it will always compress the section, even if
> + that would not reduce the size of the data section (including the
> + header). Otherwise elf_compress and elf_compress_gnu will compress
> + the section only if the total data size is reduced.
> +
> + On successful compression or decompression the function returns
> + one. If (not forced) compression is requested and the data section
> + would not actually reduce in size, the section is not actually
> + compressed and zero is returned. Otherwise -1 is returned and
> + elf_errno is set.
> +
> + It is an error to request compression for a section that already
> + has SHF_COMPRESSED set, or (for elf_compress) to request
> + decompression for an section that doesn't have SHF_COMPRESSED set.
> + If a section has SHF_COMPRESSED set then calling elf_compress_gnu
> + will result in an error. The section has to be decompressed first
> + using elf_compress. Calling elf_compress on a section compressed
> + with elf_compress_gnu is fine, but probably useless.
> +
> + It is always an error to call these functions on SHT_NOBITS
> + sections or if the section has the SHF_ALLOC flag set.
> + elf_compress_gnu will not check whether the section name starts
> + with ".debug" or .zdebug". It is the responsibility of the caller
> + to make sure the deprecated GNU compression method is only called
> + on correctly named sections (and to change the name of the section
> + when using elf_compress_gnu).
> +
> + All previous returned Shdrs and Elf_Data buffers are invalidated by
> + this call and should no longer be accessed.
> +
> + Note that although this changes the header and data returned it
> + doesn't mark the section as dirty. To keep the changes when
> + calling elf_update the section has to be flagged ELF_F_DIRTY. */
> +extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
> +extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
> +
> +/* Set or clear flags for ELF file. */
> +extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
> + unsigned int __flags);
> +/* Similarly for the ELF header. */
> +extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
> + unsigned int __flags);
> +/* Similarly for the ELF program header. */
> +extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
> + unsigned int __flags);
> +/* Similarly for the given ELF section. */
> +extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
> + unsigned int __flags);
> +/* Similarly for the given ELF data. */
> +extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
> + unsigned int __flags);
> +/* Similarly for the given ELF section header. */
> +extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
> + unsigned int __flags);
> +
> +
> +/* Get data from section while translating from file representation to
> + memory representation. The Elf_Data d_type is set based on the
> + section type if known. Otherwise d_type is set to ELF_T_BYTE. If
> + the section contains compressed data then d_type is always set to
> + ELF_T_CHDR. */
> +extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
> +
> +/* Get uninterpreted section content. */
> +extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
> +
> +/* Create new data descriptor for section SCN. */
> +extern Elf_Data *elf_newdata (Elf_Scn *__scn);
> +
> +/* Get data translated from a chunk of the file contents as section data
> + would be for TYPE. The resulting Elf_Data pointer is valid until
> + elf_end (ELF) is called. */
> +extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
> + int64_t __offset, size_t __size,
> + Elf_Type __type);
> +
> +
> +/* Return pointer to string at OFFSET in section INDEX. */
> +extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
> +
> +
> +/* Return header of archive. */
> +extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
> +
> +/* Return offset in archive for current file ELF. */
> +extern int64_t elf_getaroff (Elf *__elf);
> +
> +/* Select archive element at OFFSET. */
> +extern size_t elf_rand (Elf *__elf, size_t __offset);
> +
> +/* Get symbol table of archive. */
> +extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
> +
> +
> +/* Control ELF descriptor. */
> +extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
> +
> +/* Retrieve uninterpreted file contents. */
> +extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
> +
> +
> +/* Return size of array of COUNT elements of the type denoted by TYPE
> + in the external representation. The binary class is taken from ELF.
> + The result is based on version VERSION of the ELF standard. */
> +extern size_t elf32_fsize (Elf_Type __type, size_t __count,
> + unsigned int __version)
> + __const_attribute__;
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern size_t elf64_fsize (Elf_Type __type, size_t __count,
> + unsigned int __version)
> + __const_attribute__;
> +
> +
> +/* Convert data structure from the representation in the file represented
> + by ELF to their memory representation. */
> +extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
> + unsigned int __encode);
> +/* Same for 64 bit class. */
> +extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
> + unsigned int __encode);
> +
> +/* Convert data structure from to the representation in memory
> + represented by ELF file representation. */
> +extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
> + unsigned int __encode);
> +/* Same for 64 bit class. */
> +extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
> + unsigned int __encode);
> +
> +
> +/* Return error code of last failing function call. This value is kept
> + separately for each thread. */
> +extern int elf_errno (void);
> +
> +/* Return error string for ERROR. If ERROR is zero, return error string
> + for most recent error or NULL is none occurred. If ERROR is -1 the
> + behaviour is similar to the last case except that not NULL but a legal
> + string is returned. */
> +extern const char *elf_errmsg (int __error);
> +
> +
> +/* Coordinate ELF library and application versions. */
> +extern unsigned int elf_version (unsigned int __version);
> +
> +/* Set fill bytes used to fill holes in data structures. */
> +extern void elf_fill (int __fill);
> +
> +/* Compute hash value. */
> +extern unsigned long int elf_hash (const char *__string)
> + __pure_attribute__;
> +
> +/* Compute hash value using the GNU-specific hash function. */
> +extern unsigned long int elf_gnu_hash (const char *__string)
> + __pure_attribute__;
> +
> +
> +/* Compute simple checksum from permanent parts of the ELF file. */
> +extern long int elf32_checksum (Elf *__elf);
> +/* Similar but this time the binary calls is ELFCLASS64. */
> +extern long int elf64_checksum (Elf *__elf);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* libelf.h */
A new failure has been detected on builder elfutils-snapshots-coverage while building elfutils. Full details are available at: https://builder.sourceware.org/buildbot/#/builders/250/builds/105 Build state: failed test (failure) Revision: d74f4c1d572fbeb7454a2ffa02cbc955ea24780d Worker: snapshots Build Reason: (unknown) Blamelist: Khem Raj <raj.khem@gmail.com> Steps: - 0: worker_preparation ( success ) - 1: git checkout ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/1/logs/stdio - 2: autoreconf ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/2/logs/stdio - 3: configure ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/stdio - config.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/3/logs/config_log - 4: make ( warnings ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/stdio - warnings (3): https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/4/logs/warnings__3_ - 5: make check ( failure ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/stdio - test-suite.log: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/5/logs/test-suite_log - 6: make coverage ( warnings ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/6/logs/stdio - warnings (12): https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/6/logs/warnings__12_ - 7: Wait snapshots output ready ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/7/logs/stdio - 8: create output ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/8/logs/stdio - 9: create publish file ( success ) Logs: - stdio: https://builder.sourceware.org/buildbot/#/builders/250/builds/105/steps/9/logs/stdio
Khem Raj <raj.khem@gmail.com> writes:
> Recent commit acd9525e9 has removed all references to max_fds
> therefore remove it, moreover clang18 is happier
Thanks, merged as obvious.
- FChE
Recent commit acd9525e9 has removed all references to max_fds therefore remove it, moreover clang18 is happier | ../../elfutils-0.191/debuginfod/debuginfod.cxx:1448:8: error: private field 'max_fds' is not used [-Werror,-Wunused-private-field] | 1448 | long max_fds; | | ^ | 1 error generated. Signed-off-by: Khem Raj <raj.khem@gmail.com> --- debuginfod/debuginfod.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index 560880f2..72617848 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -1445,7 +1445,6 @@ private: map<key,fdcache_entry> entries; // optimized for lookup time_t last_cleaning; - long max_fds; long max_mbs; public: -- 2.44.0
Added new functions dwfl_get_offline_next_address and dwfl_set_offline_next_address which will get plus set said field from the Dwfl struct. This is a requirement for listing functions from their addresses when using libdwfl offline, otherwise wrong symbols are going to be returned. Signed-off-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> --- This is meant to replace a patch that only had the setter [1]. Link: https://sourceware.org/pipermail/elfutils-devel/2024q1/006874.html [1] libdwfl/libdwfl.h | 6 +++++ libdwfl/offline.c | 12 ++++++++++ tests/dwfl-offline-address.c | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/dwfl-offline-address.c diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index 49ad6664..08aa61c4 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -109,6 +109,12 @@ extern int dwfl_errno (void); extern const char *dwfl_errmsg (int err); +/* Get the next offline address. */ +extern GElf_Addr dwfl_get_offline_next_address (Dwfl *dwfl); + +/* Set the next offline address. */ +extern void dwfl_set_offline_next_address (Dwfl *dwfl, GElf_Addr addr); + /* Start reporting the current set of segments and modules to the library. All existing segments are wiped. Existing modules are marked to be deleted, and will not be found via dwfl_addrmodule et al if they are not diff --git a/libdwfl/offline.c b/libdwfl/offline.c index e9ab0cc1..ca770fac 100644 --- a/libdwfl/offline.c +++ b/libdwfl/offline.c @@ -35,6 +35,18 @@ #include "libdwflP.h" #include <fcntl.h> +GElf_Addr +dwfl_get_offline_next_address (Dwfl *dwfl) +{ + return dwfl->offline_next_address; +} + +void +dwfl_set_offline_next_address (Dwfl *dwfl, GElf_Addr addr) +{ + dwfl->offline_next_address = addr; +} + /* Since dwfl_report_elf lays out the sections already, this will only be called when the section headers of the debuginfo file are being consulted instead, or for the section placed at 0. With binutils diff --git a/tests/dwfl-offline-address.c b/tests/dwfl-offline-address.c new file mode 100644 index 00000000..9a33b95a --- /dev/null +++ b/tests/dwfl-offline-address.c @@ -0,0 +1,43 @@ +#include <config.h> +#include <assert.h> +#include <inttypes.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <argp.h> +#include ELFUTILS_HEADER(dwfl) +#include <dwarf.h> +#include "system.h" + +#define OFFLINE_REDZONE 0x10000 + +static const Dwfl_Callbacks offline_callbacks = + { + .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), + .section_address = INTUSE(dwfl_offline_section_address), + }; + +int +main (int argc, char **argv) +{ + Dwfl *dwfl = dwfl_begin (&offline_callbacks); + assert (dwfl != NULL); + + if (dwfl_get_offline_next_address (dwfl) != OFFLINE_REDZONE) + { + dwfl_end (dwfl); + return 1; + } + + int result = 0; + dwfl_set_offline_next_address (dwfl, 0); + if (dwfl_get_offline_next_address (dwfl) != 0) + result = 1; + + dwfl_end (dwfl); + + return result; +} -- 2.44.0
From: Ying Huang <ying.huang@oss.cipunited.com> Signed-off-by: Ying Huang <ying.huang@oss.cipunited.com> --- backends/Makefile.am | 3 +- backends/mips_corenote.c | 85 +++++++++++++++++ backends/mips_init.c | 3 + backends/mips_regs.c | 135 +++++++++++++++++++++++++++ backends/mips_retval.c | 196 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 backends/mips_corenote.c create mode 100644 backends/mips_regs.c create mode 100644 backends/mips_retval.c diff --git a/backends/Makefile.am b/backends/Makefile.am index 5e7b7f21..7c7f3351 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -103,7 +103,8 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \ arc_SRCS = arc_init.c arc_symbol.c mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ - mips_cfi.c mips_unwind.c + mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \ + mips_corenote.c libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ diff --git a/backends/mips_corenote.c b/backends/mips_corenote.c new file mode 100644 index 00000000..aeadeb17 --- /dev/null +++ b/backends/mips_corenote.c @@ -0,0 +1,85 @@ +/* MIPS specific core note handling. + Copyright (C) 2024 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <elf.h> +#include <inttypes.h> +#include <stddef.h> +#include <stdio.h> +#include <sys/time.h> + +#define BACKEND mips_ +#include "libebl_CPU.h" + +#define BITS 64 +#ifndef BITS +# define BITS 32 +#else +# define BITS 64 +#endif + +#define PRSTATUS_REGS_SIZE (45 * (BITS / 8)) +static const Ebl_Register_Location prstatus_regs[] = + { + { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS }, + { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS }, + }; + +#define PRSTATUS_REGSET_ITEMS \ + { \ + .name = "pc", .type = ELF_T_ADDR, .format = 'x', \ + .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \ + .group = "register", \ + .pc_register = true \ + } + +#if BITS == 32 +# define ULONG uint32_t +# define ALIGN_ULONG 4 +# define TYPE_ULONG ELF_T_WORD +#define TYPE_LONG ELF_T_SWORD +#else +#define ULONG uint64_t +#define ALIGN_ULONG 8 +#define TYPE_ULONG ELF_T_XWORD +#define TYPE_LONG ELF_T_SXWORD +#endif +#define PID_T int32_t +#define UID_T uint32_t +#define GID_T uint32_t +#define ALIGN_PID_T 4 +#define ALIGN_UID_T 4 +#define ALIGN_GID_T 4 +#define TYPE_PID_T ELF_T_SWORD +#define TYPE_UID_T ELF_T_WORD +#define TYPE_GID_T ELF_T_WORD + +#include "linux-core-note.c" diff --git a/backends/mips_init.c b/backends/mips_init.c index 1a2456b1..711a934e 100644 --- a/backends/mips_init.c +++ b/backends/mips_init.c @@ -61,6 +61,9 @@ mips_init (Elf *elf __attribute__ ((unused)), HOOK (eh, set_initial_registers_tid); HOOK (eh, abi_cfi); HOOK (eh, unwind); + HOOK (eh, register_info); + HOOK (eh, return_value_location); + HOOK (eh, core_note); eh->frame_nregs = 71; return eh; } diff --git a/backends/mips_regs.c b/backends/mips_regs.c new file mode 100644 index 00000000..4a1f8c50 --- /dev/null +++ b/backends/mips_regs.c @@ -0,0 +1,135 @@ +/* Register names and numbers for mips DWARF. + Copyright (C) 2006 Red Hat, Inc. + Copyright (C) 2024 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include <string.h> + +#define BACKEND mips_ +#include "libebl_CPU.h" +#include <system.h> +ssize_t +mips_register_info (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname, + int *bits, int *type) +{ + if (name == NULL) + return 72; + + if (regno < 0 || regno > 71 || namelen < 4) + return -1; + + *prefix = "$"; + if (regno < 38) + { + *setname = "integer"; + *type = DW_ATE_signed; + *bits = 32; + } + else + { + *setname = "FPU"; + *type = DW_ATE_float; + *bits = 64; + } + + if (regno < 32) + { + if (regno < 10) + { + name[0] = regno + '0'; + namelen = 1; + } + else + { + name[0] = (regno / 10) + '0'; + name[1] = (regno % 10) + '0'; + namelen = 2; + } + if (regno == 28 || regno == 29 || regno == 31) + *type = DW_ATE_address; + } + else if (regno == 32) + { + return stpcpy (name, "lo") + 1 - name; + } + else if (regno == 33) + { + return stpcpy (name, "hi") + 1 - name; + } + else if (regno == 34) + { + return stpcpy (name, "pc") + 1 - name; + } + else if (regno == 35) + { + *type = DW_ATE_address; + return stpcpy (name, "bad") + 1 - name; + } + else if (regno == 36) + { + return stpcpy (name, "sr") + 1 - name; + } + else if (regno == 37) + { + *type = DW_ATE_address; + return stpcpy (name, "cause") + 1 - name; + } + else if (regno < 70) + { + name[0] = 'f'; + if (regno < 38 + 10) + { + name[1] = (regno - 38) + '0'; + namelen = 2; + } + else + { + name[1] = (regno - 38) / 10 + '0'; + name[2] = (regno - 38) % 10 + '0'; + namelen = 3; + } + } + else if (regno == 70) + { + return stpcpy (name, "fsr") + 1 - name; + } + else if (regno == 71) + { + return stpcpy (name, "fir") + 1 - name; + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/backends/mips_retval.c b/backends/mips_retval.c new file mode 100644 index 00000000..2b697c08 --- /dev/null +++ b/backends/mips_retval.c @@ -0,0 +1,196 @@ +/* Function return value location for Linux/mips ABI. + Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2024 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include <string.h> +#include <elf.h> +#include <stdio.h> + +#define BACKEND mips_ +#include "libebl_CPU.h" +#include "libdwP.h" +#include <stdio.h> + +/* $v0 or pair $v0, $v1 */ +static const Dwarf_Op loc_intreg_o32[] = + { + { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 }, + }; + +static const Dwarf_Op loc_intreg[] = + { + { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 }, + }; +#define nloc_intreg 1 +#define nloc_intregpair 4 + +/* $f0 (float), or pair $f0, $f1 (double). + * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */ +static const Dwarf_Op loc_fpreg_o32[] = + { + { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 }, + { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 }, + }; + +/* $f0, or pair $f0, $f2. */ +static const Dwarf_Op loc_fpreg[] = + { + { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 }, + }; +#define nloc_fpreg 1 +#define nloc_fpregpair 4 +#define nloc_fpregquad 8 + +/* The return value is a structure and is actually stored in stack space + passed in a hidden argument by the caller. But, the compiler + helpfully returns the address of that space in $v0. */ +static const Dwarf_Op loc_aggregate[] = + { + { .atom = DW_OP_breg2, .number = 0 } + }; +#define nloc_aggregate 1 + +int +mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) +{ + unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8; + if (!regsize) + return -2; + + /* Start with the function's type, and get the DW_AT_type attribute, + which is the type of the return value. */ + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); + if (attr == NULL) + /* The function has no return value, like a `void' function in C. */ + return 0; + + Dwarf_Die die_mem; + Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); + int tag = dwarf_tag (typedie); + + /* Follow typedefs and qualifiers to get to the actual type. */ + while (tag == DW_TAG_typedef + || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type + || tag == DW_TAG_restrict_type) + { + attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + + switch (tag) + { + case -1: + return -1; + + case DW_TAG_subrange_type: + if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) + { + attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + /* Fall through. */ + FALLTHROUGH; + + case DW_TAG_base_type: + case DW_TAG_enumeration_type: + CASE_POINTER: + { + Dwarf_Word size; + if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, + &attr_mem), &size) != 0) + { + if (dwarf_is_pointer (tag)) + size = regsize; + else + return -1; + } + if (tag == DW_TAG_base_type) + { + Dwarf_Word encoding; + if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, + &attr_mem), &encoding) != 0) + return -1; + +#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc)) + + if (encoding == DW_ATE_float) + { + *locp = ARCH_LOC(loc_fpreg, regsize); + if (size <= regsize) + return nloc_fpreg; + + if (size <= 2*regsize) + return nloc_fpregpair; + + if (size <= 4*regsize) + return nloc_fpregquad; + + goto aggregate; + } + } + *locp = ARCH_LOC(loc_intreg, regsize); + if (size <= regsize) + return nloc_intreg; + if (size <= 2*regsize) + return nloc_intregpair; + + /* Else fall through. Shouldn't happen though (at least with gcc) */ + } + FALLTHROUGH; + + case DW_TAG_structure_type: + case DW_TAG_class_type: + case DW_TAG_union_type: + case DW_TAG_array_type: + aggregate: + *locp = loc_aggregate; + return nloc_aggregate; + case DW_TAG_unspecified_type: + return 0; + } + + /* XXX We don't have a good way to return specific errors from ebl calls. + This value means we do not understand the type, but it is well-formed + DWARF and might be valid. */ + return -2; +} -- 2.39.2