* Re: [PATCH 14/14] segment_report_module: Inline consider_phdr() into only caller
2020-11-12 15:04 ` [PATCH 14/14] segment_report_module: Inline consider_phdr() " Timm Bäder
@ 2020-11-12 16:52 ` Navin P
2020-11-13 7:41 ` Timm Bäder
0 siblings, 1 reply; 25+ messages in thread
From: Navin P @ 2020-11-12 16:52 UTC (permalink / raw)
To: Timm Bäder; +Cc: elfutils-devel
[-- Attachment #1: Type: text/plain, Size: 8486 bytes --]
Hi,
I already have a patch that makes elfutils compile with clang. Since
you are working
this will be of use to you. I've attached the patch since it is big.
Here are some of the changes
1. All functions at file scope have static qualifier so that no
collison with other files.
2. Non global variables declared in the outer function should be
passed as pointer variable
in the new outer file scope function whenever they are assigned in
the nested function. The
argument addition in new functions are at the end.
3. With the applied patch above , gcc passes all 220 tests where
clang fails 3 tests which
is due to llvm_addrsig (change in libelf/elf.h ) and other 2 tests
are error related to
.rela.eh_frame.
clang test suite
=========
# TOTAL: 222
# PASS: 217
# SKIP: 2
# XFAIL: 0
# FAIL: 3
# XPASS: 0
# ERROR: 0
On Thu, Nov 12, 2020 at 8:36 PM Timm Bäder via Elfutils-devel
<elfutils-devel@sourceware.org> wrote:
>
> Get rid of the nested function this way
>
> Signed-off-by: Timm Bäder <tbaeder@redhat.com>
> ---
> libdwfl/dwfl_segment_report_module.c | 142 +++++++++++++--------------
> 1 file changed, 66 insertions(+), 76 deletions(-)
>
> diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
> index 0679453e..f93c60e2 100644
> --- a/libdwfl/dwfl_segment_report_module.c
> +++ b/libdwfl/dwfl_segment_report_module.c
> @@ -475,7 +475,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
> /* NOTE if the number of sections is > 0xff00 then e_shnum
> is zero and the actual number would come from the section
> zero sh_size field. We ignore this here because getting shdrs
> - is just a nice bonus (see below in consider_phdr PT_LOAD
> + is just a nice bonus (see below in the type == PT_LOAD case
> where we trim the last segment). */
> shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
> break;
> @@ -561,80 +561,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
> build_id.len = 0;
> build_id.vaddr =0;
>
> - /* Consider each of the program headers we've read from the image. */
> - inline void consider_phdr (GElf_Word type,
> - GElf_Addr vaddr, GElf_Xword memsz,
> - GElf_Off offset, GElf_Xword filesz,
> - GElf_Xword align)
> - {
> - switch (type)
> - {
> - case PT_DYNAMIC:
> - dyn_vaddr = vaddr;
> - dyn_filesz = filesz;
> - break;
> -
> - case PT_NOTE:
> - /* We calculate from the p_offset of the note segment,
> - because we don't yet know the bias for its p_vaddr. */
> - consider_notes (dwfl, memory_callback, memory_callback_arg,
> - start + offset, filesz, align,
> - buffer, buffer_available, start, segment,
> - ei_data, &build_id,
> - &xlatefrom, &xlateto,
> - ehdr.e32.e_ident[EI_DATA]);
> - break;
> -
> - case PT_LOAD:
> - align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
> -
> - GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
> - GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
> - GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
> -
> - if (file_trimmed_end < offset + filesz)
> - {
> - file_trimmed_end = offset + filesz;
> -
> - /* Trim the last segment so we don't bother with zeros
> - in the last page that are off the end of the file.
> - However, if the extra bit in that page includes the
> - section headers, keep them. */
> - if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
> - {
> - filesz += shdrs_end - file_trimmed_end;
> - file_trimmed_end = shdrs_end;
> - }
> - }
> -
> - total_filesz += filesz;
> -
> - if (file_end < filesz_offset)
> - {
> - file_end = filesz_offset;
> - if (filesz_vaddr - start == filesz_offset)
> - contiguous = file_end;
> - }
> -
> - if (!found_bias && (offset & -align) == 0
> - && likely (filesz_offset >= phoff + phnum * phentsize))
> - {
> - bias = start - vaddr;
> - found_bias = true;
> - }
> -
> - if ((vaddr & -align) < module_start)
> - {
> - module_start = vaddr & -align;
> - module_address_sync = vaddr + memsz;
> - }
> -
> - if (module_end < vaddr_end)
> - module_end = vaddr_end;
> - break;
> - }
> - }
> -
> Elf32_Phdr *p32 = phdrsp;
> Elf64_Phdr *p64 = phdrsp;
> if ((ei_class == ELFCLASS32 &&
> @@ -646,6 +572,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
> }
> else
> {
> + /* Consider each of the program headers we've read from the image. */
> for (uint_fast16_t i = 0; i < phnum; ++i)
> {
> bool is32 = (ei_class == ELFCLASS32);
> @@ -656,7 +583,70 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
> GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
> GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
>
> - consider_phdr (type, vaddr, memsz, offset, filesz, align);
> + if (type == PT_DYNAMIC)
> + {
> + dyn_vaddr = vaddr;
> + dyn_filesz = filesz;
> + }
> + else if (type == PT_NOTE)
> + {
> + /* We calculate from the p_offset of the note segment,
> + because we don't yet know the bias for its p_vaddr. */
> + consider_notes (dwfl, memory_callback, memory_callback_arg,
> + start + offset, filesz, align,
> + buffer, buffer_available, start, segment,
> + ei_data, &build_id,
> + &xlatefrom, &xlateto,
> + ehdr.e32.e_ident[EI_DATA]);
> + }
> + else if (type == PT_LOAD)
> + {
> + align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
> +
> + GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
> + GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
> + GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
> +
> + if (file_trimmed_end < offset + filesz)
> + {
> + file_trimmed_end = offset + filesz;
> +
> + /* Trim the last segment so we don't bother with zeros
> + in the last page that are off the end of the file.
> + However, if the extra bit in that page includes the
> + section headers, keep them. */
> + if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
> + {
> + filesz += shdrs_end - file_trimmed_end;
> + file_trimmed_end = shdrs_end;
> + }
> + }
> +
> + total_filesz += filesz;
> +
> + if (file_end < filesz_offset)
> + {
> + file_end = filesz_offset;
> + if (filesz_vaddr - start == filesz_offset)
> + contiguous = file_end;
> + }
> +
> + if (!found_bias && (offset & -align) == 0
> + && likely (filesz_offset >= phoff + phnum * phentsize))
> + {
> + bias = start - vaddr;
> + found_bias = true;
> + }
> +
> + if ((vaddr & -align) < module_start)
> + {
> + module_start = vaddr & -align;
> + module_address_sync = vaddr + memsz;
> + }
> +
> + if (module_end < vaddr_end)
> + module_end = vaddr_end;
> + }
> }
> }
>
> --
> 2.26.2
>
[-- Attachment #2: 0001-Make-elfutils-compile-with-clang.patch --]
[-- Type: text/x-patch, Size: 141806 bytes --]
From 934a437c9a607c25bfa5ee6e678ca9b74d7f9ff6 Mon Sep 17 00:00:00 2001
From: Navin P <navinp0304@gmail.com>
Date: Thu, 12 Nov 2020 22:12:36 +0530
Subject: [PATCH] Make elfutils compile with clang
Signed-off-by: Navin P <navinp0304@gmail.com>
---
backends/Makefile.am | 10 +-
config/eu.am | 33 +-
configure.ac | 15 +-
debuginfod/debuginfod-client.c | 4 +-
libasm/asm_newscn.c | 6 +-
libdwfl/dwfl_segment_report_module.c | 713 ++++++++++++++++-----------
libdwfl/elf-from-memory.c | 122 +++--
libdwfl/link_map.c | 171 ++++---
libelf/elf.h | 1 +
src/addr2line.c | 43 +-
src/ar.c | 31 +-
src/arlib-argp.c | 13 +-
src/elfcompress.c | 350 ++++++++-----
src/elflint.c | 56 +--
src/readelf.c | 152 +++---
src/strip.c | 333 +++++++------
src/unstrip.c | 150 +++---
tests/elfstrmerge.c | 108 ++--
tests/zstrptr.c | 44 +-
19 files changed, 1385 insertions(+), 970 deletions(-)
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 62916c9c..1e3cbffd 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -34,6 +34,8 @@ endif
AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
-I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
+
+
noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
@@ -80,12 +82,7 @@ s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
m68k_retval.c m68k_corenote.c m68k_cfi.c m68k_initreg.c
-# m68k prstatus core notes are described by a packed structure
-# which has not naturally aligned fields. Since we don't access
-# these fields directly, but take their offset to be used later
-# to extract the data through elfxx_xlatetom/memmove, this isn't
-# an issue.
-m68k_corenote_no_Wpacked_not_aligned = yes
+
bpf_SRCS = bpf_init.c bpf_regs.c bpf_symbol.c
@@ -108,3 +105,4 @@ noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
EXTRA_DIST = $(modules:=_reloc.def)
MOSTLYCLEANFILES = $(am_libebl_backends_pic_a_OBJECTS)
+
diff --git a/config/eu.am b/config/eu.am
index 6c3c444f..0ed87125 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -29,6 +29,8 @@
## not, see <http://www.gnu.org/licenses/>.
##
+
+
DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I..
@@ -64,30 +66,51 @@ endif
if HAVE_IMPLICIT_FALLTHROUGH_WARNING
# Use strict fallthrough. Only __attribute__((fallthrough)) will prevent the
# warning
-IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+ if IS_CLANG_COMPILER
+ IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough
+ else
+ IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+ endif
else
IMPLICIT_FALLTHROUGH_WARNING=
endif
+# m68k prstatus core notes are described by a packed structure
+# which has not naturally aligned fields. Since we don't access
+# these fields directly, but take their offset to be used later
+# to extract the data through elfxx_xlatetom/memmove, this isn't
+# an issue.
+#
+
+if IS_CLANG_COMPILER
+ TRAMPOLINES_WARNING=
+ NO_XOR_USED_AS_POW=-Wno-xor-used-as-pow
+ m68k_corenote_no_Wpacked_not_aligned =
+else
+ TRAMPOLINES_WARNING=-Wtrampolines
+ NO_XOR_USED_AS_POW=
+ m68k_corenote_no_Wpacked_not_aligned = yes
+endif
+
AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
- -Wold-style-definition -Wstrict-prototypes -Wtrampolines \
+ -Wold-style-definition -Wstrict-prototypes $(TRAMPOLINES_WARNING) \
$(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
$(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
$(if $($(*F)_no_Werror),,-Werror) \
$(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
$(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
$(if $($(*F)_no_Wpacked_not_aligned),-Wno-packed-not-aligned,) \
- $($(*F)_CFLAGS)
+ $($(*F)_CFLAGS) $(NO_XOR_USED_AS_POW)
AM_CXXFLAGS = -std=c++11 -Wall -Wshadow \
- -Wtrampolines \
+ $(TRAMPOLINES_WARNING) \
$(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
$(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
$(if $($(*F)_no_Werror),,-Werror) \
$(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
$(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
$(if $($(*F)_no_Wpacked_not_aligned),-Wno-packed-not-aligned,) \
- $($(*F)_CXXFLAGS)
+ $($(*F)_CXXFLAGS) $(NO_XOR_USED_AS_POW)
COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE))
diff --git a/configure.ac b/configure.ac
index c1a6954d..eed93771 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,16 @@ AM_PROG_LEX
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_CHECK_TOOL([READELF], [readelf])
AC_CHECK_TOOL([NM], [nm])
+AS_CASE([$CC],[*clang*|*clang++*],
+ [is_clang_compiler=yes],
+ [is_clang_compiler=no]
+)
+
+AM_CONDITIONAL([IS_CLANG_COMPILER],[ test x$is_clang_compiler = xyes])
+if test "$is_clang_compiler" = "no"; then
+AC_DEFINE([NOT_CLANG_COMPILER],[1],[Not a clang compiler])
+fi
+
# We use -std=gnu99 but have explicit checks for some language constructs
# and GNU extensions since some compilers claim GNU99 support, but don't
@@ -114,6 +124,7 @@ int foo (int a)
for (int i = 0; i < a; ++i) if (i % 4) break; int s = a; return s;
}
+#ifdef NOT_CLANG_COMPILER
double bar (double a, double b)
{
double square (double z) { return z * z; }
@@ -123,7 +134,9 @@ double bar (double a, double b)
void baz (int n)
{
struct S { int x[[n]]; };
-}])],
+}
+#endif
+])],
ac_cv_c99=yes, ac_cv_c99=no)
CFLAGS="$old_CFLAGS"])
AS_IF([test "x$ac_cv_c99" != xyes],
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index ce1d819b..4bbca2a2 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -819,7 +819,7 @@ debuginfod_query_server (debuginfod_client *c,
if (curl_res == 0 && dl >= 0)
pa = (dl > LONG_MAX ? LONG_MAX : (long)dl);
#else
- double dl;
+ long double dl;
curl_res = curl_easy_getinfo(target_handle,
CURLINFO_SIZE_DOWNLOAD,
&dl);
@@ -837,7 +837,7 @@ debuginfod_query_server (debuginfod_client *c,
if (curl_res == 0 && cl >= 0)
pb = (cl > LONG_MAX ? LONG_MAX : (long)cl);
#else
- double cl;
+ long double cl;
curl_res = curl_easy_getinfo(target_handle,
CURLINFO_CONTENT_LENGTH_DOWNLOAD,
&cl);
diff --git a/libasm/asm_newscn.c b/libasm/asm_newscn.c
index 7cdf484f..778a1e59 100644
--- a/libasm/asm_newscn.c
+++ b/libasm/asm_newscn.c
@@ -46,15 +46,15 @@
dirty tricks here. */
static const struct
{
- struct FillPattern pattern;
char zero;
+ struct FillPattern pattern;
} xdefault_pattern =
{
+ .zero = '\0',
.pattern =
{
.len = 1
- },
- .zero = '\0'
+ }
};
const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 430e13d5..85ac107c 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -232,60 +232,34 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id,
return false;
}
-int
-dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
- Dwfl_Memory_Callback *memory_callback,
- void *memory_callback_arg,
- Dwfl_Module_Callback *read_eagerly,
- void *read_eagerly_arg,
- const void *note_file, size_t note_file_size,
- const struct r_debug_info *r_debug_info)
-{
- size_t segment = ndx;
-
- if (segment >= dwfl->lookup_elts)
- segment = dwfl->lookup_elts - 1;
-
- while (segment > 0
- && (dwfl->lookup_segndx[segment] > ndx
- || dwfl->lookup_segndx[segment] == -1))
- --segment;
-
- while (dwfl->lookup_segndx[segment] < ndx)
- if (++segment == dwfl->lookup_elts)
- return 0;
-
- GElf_Addr start = dwfl->lookup_addr[segment];
-
- inline bool segment_read (int segndx,
+inline static bool segment_read (int segndx,
void **buffer, size_t *buffer_available,
- GElf_Addr addr, size_t minread)
+ GElf_Addr addr, size_t minread,
+ Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
{
return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
addr, minread, memory_callback_arg);
}
- inline void release_buffer (void **buffer, size_t *buffer_available)
+ inline static void release_buffer (void **buffer, size_t *buffer_available,
+ Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
{
if (*buffer != NULL)
- (void) segment_read (-1, buffer, buffer_available, 0, 0);
+ (void) segment_read (-1, buffer, buffer_available, 0, 0,dwfl,
+ memory_callback,memory_callback_arg);
}
- /* First read in the file header and check its sanity. */
-
- void *buffer = NULL;
- size_t buffer_available = INITIAL_READ;
- Elf *elf = NULL;
- int fd = -1;
-
- /* We might have to reserve some memory for the phdrs. Set to NULL
- here so we can always safely free it. */
- void *phdrsp = NULL;
-
- inline int finish (void)
+ inline static int finish (void *phdrsp,Elf *elf,
+ void **buffer,size_t *buffer_available,
+ int fd,int ndx,
+ Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
{
free (phdrsp);
- release_buffer (&buffer, &buffer_available);
+ release_buffer (buffer, buffer_available,dwfl,memory_callback,
+ memory_callback_arg);
if (elf != NULL)
elf_end (elf);
if (fd != -1)
@@ -293,51 +267,358 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
return ndx;
}
- if (segment_read (ndx, &buffer, &buffer_available,
- start, sizeof (Elf64_Ehdr))
- || memcmp (buffer, ELFMAG, SELFMAG) != 0)
- return finish ();
+ inline static bool read_portion (void **data, size_t *data_size,
+ GElf_Addr vaddr, size_t filesz,
+ size_t *buffer_available,GElf_Addr start,
+ void **buffer,size_t segment, Dwfl *dwfl,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
- inline bool read_portion (void **data, size_t *data_size,
- GElf_Addr vaddr, size_t filesz)
{
/* Check whether we will have to read the segment data, or if it
can be returned from the existing buffer. */
- if (filesz > buffer_available
- || vaddr - start > buffer_available - filesz
+ if (filesz > *buffer_available
+ || vaddr - start > *buffer_available - filesz
/* If we're in string mode, then don't consider the buffer we have
sufficient unless it contains the terminator of the string. */
- || (filesz == 0 && memchr (vaddr - start + buffer, '\0',
- buffer_available - (vaddr - start)) == NULL))
+ || (filesz == 0 && memchr (vaddr - start + *buffer, '\0',
+ *buffer_available - (vaddr - start)) == NULL))
{
*data = NULL;
*data_size = filesz;
return segment_read (addr_segndx (dwfl, segment, vaddr, false),
- data, data_size, vaddr, filesz);
+ data, data_size, vaddr, filesz,dwfl,memory_callback,
+ memory_callback_arg);
}
/* We already have this whole note segment from our initial read. */
- *data = vaddr - start + buffer;
+ *data = vaddr - start + *buffer;
*data_size = 0;
return false;
}
- inline void finish_portion (void **data, size_t *data_size)
+
+ inline static void finish_portion (void **data, size_t *data_size,
+ Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
+
{
if (*data_size != 0)
- release_buffer (data, data_size);
+ release_buffer (data, data_size,dwfl,memory_callback,memory_callback_arg);
}
+union
+ {
+ Elf32_Ehdr e32;
+ Elf64_Ehdr e64;
+ } ehdr;
+
+
+
+ /* Consider a PT_NOTE we've found in the image. */
+ inline static void consider_notes (GElf_Addr vaddr, GElf_Xword *filesz,
+ GElf_Xword align,void **build_id,
+ size_t *buffer_available,GElf_Addr start,
+ void **buffer,size_t segment,
+ Dwfl *dwfl,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg,
+ unsigned char ei_data,Elf_Data *xlatefrom,
+ Elf_Data *xlateto,size_t *build_id_len,
+ GElf_Addr *build_id_vaddr
+ )
+ {
+ /* If we have already seen a build ID, we don't care any more. */
+ if ((*build_id) != NULL || *filesz == 0)
+ return;
+
+ void *data;
+ size_t data_size;
+ if (read_portion (&data, &data_size, vaddr, *filesz,
+ buffer_available,start,buffer,segment,dwfl,
+ memory_callback,memory_callback_arg))
+ return;
+
+ /* data_size will be zero if we got everything from the initial
+ buffer, otherwise it will be the size of the new buffer that
+ could be read. */
+ if (data_size != 0)
+ *filesz = data_size;
+
+ assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
+
+ void *notes;
+ if (ei_data == MY_ELFDATA)
+ notes = data;
+ else
+ {
+ notes = malloc (*filesz);
+ if (unlikely (notes == NULL))
+ return;
+ xlatefrom->d_type = xlateto->d_type = (align == 8
+ ? ELF_T_NHDR8 : ELF_T_NHDR);
+ xlatefrom->d_buf = (void *) data;
+ xlatefrom->d_size = *filesz;
+ xlateto->d_buf = notes;
+ xlateto->d_size = *filesz;
+ if (elf32_xlatetom (xlateto, xlatefrom,
+ ehdr.e32.e_ident[EI_DATA]) == NULL)
+ goto done;
+ }
+
+ const GElf_Nhdr *nh = notes;
+ size_t len = 0;
+ while (*filesz > len + sizeof (*nh))
+ {
+ const void *note_name;
+ const void *note_desc;
+
+ len += sizeof (*nh);
+ note_name = notes + len;
+
+ len += nh->n_namesz;
+ len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+ note_desc = notes + len;
+
+ if (unlikely (*filesz < len + nh->n_descsz))
+ break;
+
+ if (nh->n_type == NT_GNU_BUILD_ID
+ && nh->n_descsz > 0
+ && nh->n_namesz == sizeof "GNU"
+ && !memcmp (note_name, "GNU", sizeof "GNU"))
+ {
+ *build_id_vaddr = note_desc - (const void *) notes + vaddr;
+ *build_id_len = nh->n_descsz;
+ *build_id = malloc (nh->n_descsz);
+ if (likely (*build_id != NULL))
+ memcpy (*build_id, note_desc, *build_id_len);
+ break;
+ }
+
+ len += nh->n_descsz;
+ len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+ nh = (void *) notes + len;
+ }
+
+ done:
+ if (notes != data)
+ free (notes);
+ finish_portion (&data, &data_size,dwfl,memory_callback,memory_callback_arg);
+ }
+
+
+/* Consider each of the program headers we've read from the image. */
+//should have inline
+ inline static void consider_phdr (GElf_Word type,
+ GElf_Addr vaddr, GElf_Xword memsz,
+ GElf_Off offset, void *ptrfilesz,size_t ptrlen,
+ GElf_Xword align, GElf_Addr *dyn_vaddr,
+ GElf_Xword *dyn_filesz,GElf_Addr start,
+ Dwfl *dwfl, GElf_Off *file_trimmed_end,
+ GElf_Off shdrs_end,GElf_Addr *module_start,
+ GElf_Addr *module_end,
+ GElf_Addr *module_address_sync,void **build_id,
+ size_t *buffer_available,void **buffer,
+ size_t segment,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg,unsigned char ei_data,
+ Elf_Data *xlatefrom,Elf_Data *xlateto,
+ size_t *build_id_len,GElf_Addr *build_id_vaddr,
+ GElf_Off *total_filesz,GElf_Off *file_end,
+ GElf_Off *contiguous , GElf_Off phoff,
+ uint_fast16_t phnum,uint_fast16_t phentsize,
+ GElf_Addr *bias,bool *found_bias
+ )
+ {
+
+ unsigned long filesz = 0;
+ memcpy(&filesz,ptrfilesz,ptrlen);
+
+ switch (type)
+ {
+ case PT_DYNAMIC:
+ *dyn_vaddr = vaddr;
+ *dyn_filesz = filesz;
+ break;
+
+ case PT_NOTE:
+
+ /* We calculate from the p_offset of the note segment,
+ because we don't yet know the bias for its p_vaddr. */
+ consider_notes (start + offset, &filesz, align, build_id,
+ buffer_available,start,
+ buffer,segment,dwfl,
+ memory_callback,memory_callback_arg,ei_data,
+ xlatefrom,xlateto,build_id_len,build_id_vaddr);
+
+ break;
+
+ case PT_LOAD:
+ align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
+
+ GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
+ GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
+ GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
+
+ if (*file_trimmed_end < offset + filesz)
+ {
+ *file_trimmed_end = offset + filesz;
+
+ /* Trim the last segment so we don't bother with zeros
+ in the last page that are off the end of the file.
+ However, if the extra bit in that page includes the
+ section headers, keep them. */
+ if (shdrs_end <= filesz_offset && shdrs_end > *file_trimmed_end)
+ {
+ filesz += shdrs_end - *file_trimmed_end;
+ *file_trimmed_end = shdrs_end;
+ }
+ }
+
+ *total_filesz += filesz;
+
+ if (*file_end < filesz_offset)
+ {
+ *file_end = filesz_offset;
+ if (filesz_vaddr - start == filesz_offset)
+ *contiguous = *file_end;
+ }
+
+ if (!*found_bias && (offset & -align) == 0
+ && likely (filesz_offset >= phoff + phnum * phentsize))
+ {
+ *bias = start - vaddr;
+ *found_bias = true;
+ }
+
+ if ((vaddr & -align) < *module_start)
+ {
+ *module_start = vaddr & -align;
+ *module_address_sync = vaddr + memsz;
+ }
+
+ if (*module_end < vaddr_end)
+ *module_end = vaddr_end;
+ break;
+ }
+
+ memcpy(ptrfilesz,&filesz,ptrlen);
+ }
+
+
+inline static bool consider_dyn (GElf_Sxword tag, GElf_Xword val,
+ bool *execlike,GElf_Addr *soname_stroff,
+ GElf_Addr *dynstr_vaddr, GElf_Xword *dynstrsz)
+ {
+ switch (tag)
+ {
+ default:
+ return false;
+
+ case DT_DEBUG:
+ *execlike = true;
+ break;
+
+ case DT_SONAME:
+ *soname_stroff = val;
+ break;
+
+ case DT_STRTAB:
+ *dynstr_vaddr = val;
+ break;
+
+ case DT_STRSZ:
+ *dynstrsz = val;
+ break;
+ }
+
+ return *soname_stroff != 0 && *dynstr_vaddr != 0 && *dynstrsz != 0;
+ }
+
+inline static void final_read (size_t offset, GElf_Addr vaddr, size_t size,
+ void *contents,Dwfl *dwfl,size_t segment,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
+ {
+ void *into = contents + offset;
+ size_t read_size = size;
+ (void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
+ &into, &read_size, vaddr, size,dwfl,
+ memory_callback,memory_callback_arg);
+
+ }
+
+
+ /* We can't use the memory image verbatim as the file image.
+ So we'll be reading into a local image of the virtual file. */
+
+ inline static void read_phdr (GElf_Word type, GElf_Addr vaddr,
+ GElf_Off offset, GElf_Xword filesz,
+ GElf_Addr bias,void *contents,Dwfl *dwfl,
+ size_t segment,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
+ {
+ if (type == PT_LOAD)
+ final_read (offset, vaddr + bias, filesz,contents,dwfl,
+ segment,memory_callback,memory_callback_arg);
+ }
+
+
+
+
+
+
+int
+dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg,
+ Dwfl_Module_Callback *read_eagerly,
+ void *read_eagerly_arg,
+ const void *note_file, size_t note_file_size,
+ const struct r_debug_info *r_debug_info)
+{
+ size_t segment = ndx;
+
+ if (segment >= dwfl->lookup_elts)
+ segment = dwfl->lookup_elts - 1;
+
+ while (segment > 0
+ && (dwfl->lookup_segndx[segment] > ndx
+ || dwfl->lookup_segndx[segment] == -1))
+ --segment;
+
+ while (dwfl->lookup_segndx[segment] < ndx)
+ if (++segment == dwfl->lookup_elts)
+ return 0;
+
+ GElf_Addr start = dwfl->lookup_addr[segment];
+
+ /* First read in the file header and check its sanity. */
+
+ void *buffer = NULL;
+ size_t buffer_available = INITIAL_READ;
+ Elf *elf = NULL;
+ int fd = -1;
+
+ /* We might have to reserve some memory for the phdrs. Set to NULL
+ here so we can always safely free it. */
+ void *phdrsp = NULL;
+
+ if (segment_read (ndx, &buffer, &buffer_available,start, sizeof (Elf64_Ehdr),
+ dwfl,memory_callback,memory_callback_arg)
+ || memcmp (buffer, ELFMAG, SELFMAG) != 0)
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
+
+
+
/* Extract the information we need from the file header. */
const unsigned char *e_ident;
unsigned char ei_class;
unsigned char ei_data;
uint16_t e_type;
- union
- {
- Elf32_Ehdr e32;
- Elf64_Ehdr e64;
- } ehdr;
GElf_Off phoff;
uint_fast16_t phnum;
uint_fast16_t phentsize;
@@ -363,13 +644,15 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
case ELFCLASS32:
xlatefrom.d_size = sizeof (Elf32_Ehdr);
if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
e_type = ehdr.e32.e_type;
phoff = ehdr.e32.e_phoff;
phnum = ehdr.e32.e_phnum;
phentsize = ehdr.e32.e_phentsize;
if (phentsize != sizeof (Elf32_Phdr))
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
/* NOTE if the number of sections is > 0xff00 then e_shnum
is zero and the actual number would come from the section
zero sh_size field. We ignore this here because getting shdrs
@@ -381,19 +664,22 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
case ELFCLASS64:
xlatefrom.d_size = sizeof (Elf64_Ehdr);
if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
e_type = ehdr.e64.e_type;
phoff = ehdr.e64.e_phoff;
phnum = ehdr.e64.e_phnum;
phentsize = ehdr.e64.e_phentsize;
if (phentsize != sizeof (Elf64_Phdr))
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
/* See the NOTE above for shdrs_end and ehdr.e32.e_shnum. */
shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
break;
default:
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
}
/* The file header tells where to find the program headers.
@@ -401,7 +687,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
Without them, we don't have a module to report. */
if (phnum == 0)
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
xlatefrom.d_size = phnum * phentsize;
@@ -409,8 +696,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
void *ph_buffer = NULL;
size_t ph_buffer_size = 0;
if (read_portion (&ph_buffer, &ph_buffer_size,
- start + phoff, xlatefrom.d_size))
- return finish ();
+ start + phoff, xlatefrom.d_size,
+ &buffer_available,start,&buffer,segment,dwfl,
+ memory_callback,memory_callback_arg))
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
/* ph_buffer_size will be zero if we got everything from the initial
buffer, otherwise it will be the size of the new buffer that
@@ -423,11 +713,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
bool class32 = ei_class == ELFCLASS32;
size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
if (unlikely (phnum > SIZE_MAX / phdr_size))
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
const size_t phdrsp_bytes = phnum * phdr_size;
phdrsp = malloc (phdrsp_bytes);
if (unlikely (phdrsp == NULL))
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
xlateto.d_buf = phdrsp;
xlateto.d_size = phdrsp_bytes;
@@ -456,155 +748,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
size_t build_id_len = 0;
GElf_Addr build_id_vaddr = 0;
- /* Consider a PT_NOTE we've found in the image. */
- inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz,
- GElf_Xword align)
- {
- /* If we have already seen a build ID, we don't care any more. */
- if (build_id != NULL || filesz == 0)
- return;
-
- void *data;
- size_t data_size;
- if (read_portion (&data, &data_size, vaddr, filesz))
- return;
-
- /* data_size will be zero if we got everything from the initial
- buffer, otherwise it will be the size of the new buffer that
- could be read. */
- if (data_size != 0)
- filesz = data_size;
-
- assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
-
- void *notes;
- if (ei_data == MY_ELFDATA)
- notes = data;
- else
- {
- notes = malloc (filesz);
- if (unlikely (notes == NULL))
- return;
- xlatefrom.d_type = xlateto.d_type = (align == 8
- ? ELF_T_NHDR8 : ELF_T_NHDR);
- xlatefrom.d_buf = (void *) data;
- xlatefrom.d_size = filesz;
- xlateto.d_buf = notes;
- xlateto.d_size = filesz;
- if (elf32_xlatetom (&xlateto, &xlatefrom,
- ehdr.e32.e_ident[EI_DATA]) == NULL)
- goto done;
- }
-
- const GElf_Nhdr *nh = notes;
- size_t len = 0;
- while (filesz > len + sizeof (*nh))
- {
- const void *note_name;
- const void *note_desc;
-
- len += sizeof (*nh);
- note_name = notes + len;
-
- len += nh->n_namesz;
- len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
- note_desc = notes + len;
-
- if (unlikely (filesz < len + nh->n_descsz))
- break;
-
- if (nh->n_type == NT_GNU_BUILD_ID
- && nh->n_descsz > 0
- && nh->n_namesz == sizeof "GNU"
- && !memcmp (note_name, "GNU", sizeof "GNU"))
- {
- build_id_vaddr = note_desc - (const void *) notes + vaddr;
- build_id_len = nh->n_descsz;
- build_id = malloc (nh->n_descsz);
- if (likely (build_id != NULL))
- memcpy (build_id, note_desc, build_id_len);
- break;
- }
-
- len += nh->n_descsz;
- len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
- nh = (void *) notes + len;
- }
-
- done:
- if (notes != data)
- free (notes);
- finish_portion (&data, &data_size);
- }
-
- /* Consider each of the program headers we've read from the image. */
- inline void consider_phdr (GElf_Word type,
- GElf_Addr vaddr, GElf_Xword memsz,
- GElf_Off offset, GElf_Xword filesz,
- GElf_Xword align)
- {
- switch (type)
- {
- case PT_DYNAMIC:
- dyn_vaddr = vaddr;
- dyn_filesz = filesz;
- break;
-
- case PT_NOTE:
- /* We calculate from the p_offset of the note segment,
- because we don't yet know the bias for its p_vaddr. */
- consider_notes (start + offset, filesz, align);
- break;
-
- case PT_LOAD:
- align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
-
- GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
- GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
- GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
-
- if (file_trimmed_end < offset + filesz)
- {
- file_trimmed_end = offset + filesz;
-
- /* Trim the last segment so we don't bother with zeros
- in the last page that are off the end of the file.
- However, if the extra bit in that page includes the
- section headers, keep them. */
- if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
- {
- filesz += shdrs_end - file_trimmed_end;
- file_trimmed_end = shdrs_end;
- }
- }
-
- total_filesz += filesz;
-
- if (file_end < filesz_offset)
- {
- file_end = filesz_offset;
- if (filesz_vaddr - start == filesz_offset)
- contiguous = file_end;
- }
-
- if (!found_bias && (offset & -align) == 0
- && likely (filesz_offset >= phoff + phnum * phentsize))
- {
- bias = start - vaddr;
- found_bias = true;
- }
-
- if ((vaddr & -align) < module_start)
- {
- module_start = vaddr & -align;
- module_address_sync = vaddr + memsz;
- }
-
- if (module_end < vaddr_end)
- module_end = vaddr_end;
- break;
- }
- }
+
Elf32_Phdr (*p32)[phnum] = phdrsp;
Elf64_Phdr (*p64)[phnum] = phdrsp;
@@ -616,8 +760,17 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
for (uint_fast16_t i = 0; i < phnum; ++i)
consider_phdr ((*p32)[i].p_type,
(*p32)[i].p_vaddr, (*p32)[i].p_memsz,
- (*p32)[i].p_offset, (*p32)[i].p_filesz,
- (*p32)[i].p_align);
+ (*p32)[i].p_offset, &((*p32)[i].p_filesz),
+ sizeof((*p32)[i].p_filesz),
+ (*p32)[i].p_align, &dyn_vaddr, &dyn_filesz,
+ start,dwfl,&file_trimmed_end,
+ shdrs_end,&module_start,&module_end,
+ &module_address_sync,&build_id,&buffer_available,
+ &buffer,segment,memory_callback,memory_callback_arg,
+ ei_data,&xlatefrom,&xlateto,&build_id_len,
+ &build_id_vaddr,&total_filesz,&file_end ,&contiguous,
+ phoff,phnum,phentsize,&bias,&found_bias);
+
}
else
{
@@ -627,18 +780,29 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
for (uint_fast16_t i = 0; i < phnum; ++i)
consider_phdr ((*p64)[i].p_type,
(*p64)[i].p_vaddr, (*p64)[i].p_memsz,
- (*p64)[i].p_offset, (*p64)[i].p_filesz,
- (*p64)[i].p_align);
+ (*p64)[i].p_offset, &((*p64)[i].p_filesz),
+ sizeof((*p64)[i].p_filesz),
+ (*p64)[i].p_align, &dyn_vaddr, &dyn_filesz,
+ start,dwfl,&file_trimmed_end,
+ shdrs_end,&module_start,&module_end,
+ &module_address_sync,&build_id,&buffer_available,
+ &buffer,segment,memory_callback,memory_callback_arg,
+ ei_data,&xlatefrom,&xlateto,&build_id_len,
+ &build_id_vaddr,&total_filesz,&file_end ,&contiguous,
+ phoff,phnum,phentsize,&bias,&found_bias);
+
}
- finish_portion (&ph_buffer, &ph_buffer_size);
+ finish_portion (&ph_buffer, &ph_buffer_size,dwfl,memory_callback,
+ memory_callback_arg);
/* We must have seen the segment covering offset 0, or else the ELF
header we read at START was not produced by these program headers. */
if (unlikely (!found_bias))
{
free (build_id);
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
}
/* Now we know enough to report a module for sure: its bounds. */
@@ -709,7 +873,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
if (skip_this_module)
{
free (build_id);
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
}
}
@@ -755,39 +920,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
GElf_Addr dynstr_vaddr = 0;
GElf_Xword dynstrsz = 0;
bool execlike = false;
- inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
- {
- switch (tag)
- {
- default:
- return false;
-
- case DT_DEBUG:
- execlike = true;
- break;
-
- case DT_SONAME:
- soname_stroff = val;
- break;
-
- case DT_STRTAB:
- dynstr_vaddr = val;
- break;
-
- case DT_STRSZ:
- dynstrsz = val;
- break;
- }
-
- return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
- }
-
const size_t dyn_entsize = (ei_class == ELFCLASS32
? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
void *dyn_data = NULL;
size_t dyn_data_size = 0;
if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
- && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
+ && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz,
+ &buffer_available,start,&buffer,segment,dwfl,memory_callback,
+ memory_callback_arg))
{
/* dyn_data_size will be zero if we got everything from the initial
buffer, otherwise it will be the size of the new buffer that
@@ -799,7 +939,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns;
Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns;
if (unlikely (dyns == NULL))
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
xlatefrom.d_buf = (void *) dyn_data;
@@ -811,19 +952,24 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
{
if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
- if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val))
+ if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val,
+ &execlike,&soname_stroff,
+ &dynstr_vaddr, &dynstrsz))
break;
}
else
{
if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
- if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val))
+ if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val,
+ &execlike,&soname_stroff,
+ &dynstr_vaddr, &dynstrsz))
break;
}
free (dyns);
}
- finish_portion (&dyn_data, &dyn_data_size);
+ finish_portion (&dyn_data, &dyn_data_size,dwfl,memory_callback,
+ memory_callback_arg);
/* We'll use the name passed in or a stupid default if not DT_SONAME. */
if (name == NULL)
@@ -856,7 +1002,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
/* Try to get the DT_SONAME string. */
if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
&& ! read_portion (&soname, &soname_size,
- dynstr_vaddr + soname_stroff, 0))
+ dynstr_vaddr + soname_stroff, 0,
+ &buffer_available,start,&buffer,segment,
+ dwfl,memory_callback,
+ memory_callback_arg))
name = soname;
}
@@ -884,12 +1033,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
/* At this point we do not need BUILD_ID or NAME any more.
They have been copied. */
free (build_id);
- finish_portion (&soname, &soname_size);
+ finish_portion (&soname, &soname_size,dwfl,memory_callback,
+ memory_callback_arg);
if (unlikely (mod == NULL))
{
ndx = -1;
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
}
/* We have reported the module. Now let the caller decide whether we
@@ -913,36 +1064,25 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
void *contents = calloc (1, file_trimmed_end);
if (unlikely (contents == NULL))
- return finish ();
-
- inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
- {
- void *into = contents + offset;
- size_t read_size = size;
- (void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
- &into, &read_size, vaddr, size);
- }
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
- if (contiguous < file_trimmed_end)
+ if (contiguous < file_trimmed_end)
{
- /* We can't use the memory image verbatim as the file image.
- So we'll be reading into a local image of the virtual file. */
-
- inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
- GElf_Off offset, GElf_Xword filesz)
- {
- if (type == PT_LOAD)
- final_read (offset, vaddr + bias, filesz);
- }
+
if (ei_class == ELFCLASS32)
for (uint_fast16_t i = 0; i < phnum; ++i)
read_phdr ((*p32)[i].p_type, (*p32)[i].p_vaddr,
- (*p32)[i].p_offset, (*p32)[i].p_filesz);
+ (*p32)[i].p_offset, (*p32)[i].p_filesz,
+ bias,contents,dwfl,segment,memory_callback,
+ memory_callback_arg);
else
for (uint_fast16_t i = 0; i < phnum; ++i)
read_phdr ((*p64)[i].p_type, (*p64)[i].p_vaddr,
- (*p64)[i].p_offset, (*p64)[i].p_filesz);
+ (*p64)[i].p_offset, (*p64)[i].p_filesz,
+ bias,contents,dwfl,segment,memory_callback,
+ memory_callback_arg);
}
else
{
@@ -953,7 +1093,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
memcpy (contents, buffer, have);
if (have < file_trimmed_end)
- final_read (have, start + have, file_trimmed_end - have);
+ final_read (have, start + have, file_trimmed_end - have,
+ contents,dwfl,segment,
+ memory_callback,memory_callback_arg);
}
elf = elf_memory (contents, file_trimmed_end);
@@ -975,5 +1117,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
mod->main_bias = bias;
}
- return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+ memory_callback,memory_callback_arg);
}
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index c54c1b99..40aea896 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -38,6 +38,63 @@
#include <stdlib.h>
#include <string.h>
+/* Sanity checks segments and calculates segment_end,
+ segments_end, segments_end_mem and loadbase (if not
+ found_base yet). Returns true if sanity checking failed,
+ false otherwise. */
+ inline static bool ehdr_memsz_handle_segment (GElf_Addr vaddr, GElf_Off offset,
+ GElf_Xword filesz, GElf_Xword memsz,
+ GElf_Xword pagesize, GElf_Addr ehdr_vma,
+ size_t *contents_size,GElf_Addr *loadbase,
+ bool *found_base,GElf_Off *segments_end,
+ GElf_Off *segments_end_mem)
+ {
+ /* Sanity check the segment load aligns with the pagesize. */
+ if (((vaddr - offset) & (pagesize - 1)) != 0)
+ return true;
+
+ GElf_Off segment_end = ((offset + filesz + pagesize - 1)
+ & -pagesize);
+
+ if (segment_end > (GElf_Off) *contents_size)
+ *contents_size = segment_end;
+
+ if (!*found_base && (offset & -pagesize) == 0)
+ {
+ *loadbase = ehdr_vma - (vaddr & -pagesize);
+ *found_base = true;
+ }
+
+ *segments_end = offset + filesz;
+ *segments_end_mem = offset + memsz;
+ return false;
+ }
+
+/* Reads the given segment. Returns true if reading fails,
+ false otherwise. */
+ inline static bool ehdr_filesz_handle_segment (GElf_Addr vaddr, GElf_Off offset,
+ GElf_Xword filesz,GElf_Xword pagesize,
+ size_t contents_size, ssize_t *nread,
+ unsigned char *buffer,GElf_Addr loadbase,
+ ssize_t (*read_memory) (void *arg, void *data,
+ GElf_Addr address,
+ size_t minread,
+ size_t maxread),
+ void *arg)
+
+ {
+ GElf_Off start = offset & -pagesize;
+ GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
+ if (end > (GElf_Off) contents_size)
+ end = contents_size;
+ *nread = (*read_memory) (arg, buffer + start,
+ (loadbase + vaddr) & -pagesize,
+ end - start, end - start);
+ return *nread <= 0;
+ }
+
+
+
/* Reconstruct an ELF file by reading the segments out of remote memory
based on the ELF file header at EHDR_VMA and the ELF program headers it
points to. If not null, *LOADBASEP is filled in with the difference
@@ -225,42 +282,16 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
Elf64_Phdr (*p64)[phnum] = phdrsp;
switch (ehdr.e32.e_ident[EI_CLASS])
{
- /* Sanity checks segments and calculates segment_end,
- segments_end, segments_end_mem and loadbase (if not
- found_base yet). Returns true if sanity checking failed,
- false otherwise. */
- inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
- GElf_Xword filesz, GElf_Xword memsz)
- {
- /* Sanity check the segment load aligns with the pagesize. */
- if (((vaddr - offset) & (pagesize - 1)) != 0)
- return true;
-
- GElf_Off segment_end = ((offset + filesz + pagesize - 1)
- & -pagesize);
-
- if (segment_end > (GElf_Off) contents_size)
- contents_size = segment_end;
-
- if (!found_base && (offset & -pagesize) == 0)
- {
- loadbase = ehdr_vma - (vaddr & -pagesize);
- found_base = true;
- }
-
- segments_end = offset + filesz;
- segments_end_mem = offset + memsz;
- return false;
- }
-
case ELFCLASS32:
if (elf32_xlatetom (&xlateto, &xlatefrom,
ehdr.e32.e_ident[EI_DATA]) == NULL)
goto libelf_error;
for (uint_fast16_t i = 0; i < phnum; ++i)
if ((*p32)[i].p_type == PT_LOAD)
- if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
- (*p32)[i].p_filesz, (*p32)[i].p_memsz))
+ if (ehdr_memsz_handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz, (*p32)[i].p_memsz,pagesize,
+ ehdr_vma,&contents_size, &loadbase,&found_base,
+ &segments_end,&segments_end_mem))
goto bad_elf;
break;
@@ -270,8 +301,10 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
goto libelf_error;
for (uint_fast16_t i = 0; i < phnum; ++i)
if ((*p64)[i].p_type == PT_LOAD)
- if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
- (*p64)[i].p_filesz, (*p64)[i].p_memsz))
+ if (ehdr_memsz_handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz, (*p64)[i].p_memsz,pagesize,
+ ehdr_vma,&contents_size, &loadbase,&found_base,
+ &segments_end,&segments_end_mem))
goto bad_elf;
break;
@@ -307,26 +340,12 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
switch (ehdr.e32.e_ident[EI_CLASS])
{
- /* Reads the given segment. Returns true if reading fails,
- false otherwise. */
- inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
- GElf_Xword filesz)
- {
- GElf_Off start = offset & -pagesize;
- GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
- if (end > (GElf_Off) contents_size)
- end = contents_size;
- nread = (*read_memory) (arg, buffer + start,
- (loadbase + vaddr) & -pagesize,
- end - start, end - start);
- return nread <= 0;
- }
-
case ELFCLASS32:
for (uint_fast16_t i = 0; i < phnum; ++i)
if ((*p32)[i].p_type == PT_LOAD)
- if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
- (*p32)[i].p_filesz))
+ if (ehdr_filesz_handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz,pagesize,contents_size,
+ &nread,buffer,loadbase,read_memory,arg))
goto read_error;
/* If the segments visible in memory didn't include the section
@@ -352,8 +371,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
case ELFCLASS64:
for (uint_fast16_t i = 0; i < phnum; ++i)
if ((*p64)[i].p_type == PT_LOAD)
- if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
- (*p64)[i].p_filesz))
+ if (ehdr_filesz_handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz,pagesize,contents_size,
+ &nread,buffer,loadbase,read_memory,arg))
goto read_error;
/* If the segments visible in memory didn't include the section
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 29307c74..d7ca42ae 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -1,3 +1,4 @@
+
/* Report modules by examining dynamic linker data structures.
Copyright (C) 2008-2016 Red Hat, Inc.
This file is part of elfutils.
@@ -224,61 +225,42 @@ addrsize (uint_fast8_t elfclass)
{
return elfclass * 4;
}
-
-/* Report a module for each struct link_map in the linked list at r_map
- in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description
- see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no
- modules get added to DWFL, caller has to add them from filled in
- R_DEBUG_INFO.
-
- For each link_map entry, if an existing module resides at its address,
- this just modifies that module's name and suggested file name. If
- no such module exists, this calls dwfl_report_elf on the l_name string.
-
- Returns the number of modules found, or -1 for errors. */
-
-static int
-report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
- Dwfl *dwfl, GElf_Addr r_debug_vaddr,
- Dwfl_Memory_Callback *memory_callback,
- void *memory_callback_arg,
- struct r_debug_info *r_debug_info)
-{
- /* Skip r_version, to aligned r_map field. */
- GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
-
- void *buffer = NULL;
- size_t buffer_available = 0;
- inline int release_buffer (int result)
+inline static int release_buffer (int result,void **buffer,size_t *buffer_available,
+ Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg)
{
if (buffer != NULL)
- (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
+ (void) (*memory_callback) (dwfl, -1, buffer, buffer_available, 0, 0,
memory_callback_arg);
return result;
}
- GElf_Addr addrs[4];
- inline bool read_addrs (GElf_Addr vaddr, size_t n)
+ inline static bool read_addrs (GElf_Addr vaddr, size_t n,uint_fast8_t elfclass,
+ void **buffer,GElf_Addr *read_vaddr,size_t *buffer_available,
+ Dwfl *dwfl,Dwfl_Memory_Callback memory_callback,
+ void *memory_callback_arg,
+ uint_fast8_t elfdata, GElf_Addr addrs[]
+ )
{
size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
/* Read a new buffer if the old one doesn't cover these words. */
- if (buffer == NULL
- || vaddr < read_vaddr
- || vaddr - read_vaddr + nb > buffer_available)
+ if (*buffer == NULL
+ || vaddr < *read_vaddr
+ || vaddr - *read_vaddr + nb > *buffer_available)
{
- release_buffer (0);
+ release_buffer (0,buffer,buffer_available,dwfl,memory_callback,memory_callback_arg);
- read_vaddr = vaddr;
+ *read_vaddr = vaddr;
int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
if (unlikely (segndx < 0)
|| unlikely (! (*memory_callback) (dwfl, segndx,
- &buffer, &buffer_available,
+ buffer, buffer_available,
vaddr, nb, memory_callback_arg)))
return true;
}
- Elf32_Addr (*a32)[n] = vaddr - read_vaddr + buffer;
+ Elf32_Addr (*a32)[n] = vaddr - *read_vaddr + *buffer;
Elf64_Addr (*a64)[n] = (void *) a32;
if (elfclass == ELFCLASS32)
@@ -303,8 +285,39 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
return false;
}
- if (unlikely (read_addrs (read_vaddr, 1)))
- return release_buffer (-1);
+
+/* Report a module for each struct link_map in the linked list at r_map
+ in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description
+ see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no
+ modules get added to DWFL, caller has to add them from filled in
+ R_DEBUG_INFO.
+
+ For each link_map entry, if an existing module resides at its address,
+ this just modifies that module's name and suggested file name. If
+ no such module exists, this calls dwfl_report_elf on the l_name string.
+
+ Returns the number of modules found, or -1 for errors. */
+
+static int
+report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
+ Dwfl *dwfl, GElf_Addr r_debug_vaddr,
+ Dwfl_Memory_Callback *memory_callback,
+ void *memory_callback_arg,
+ struct r_debug_info *r_debug_info)
+{
+ /* Skip r_version, to aligned r_map field. */
+ GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
+
+ void *buffer = NULL;
+ size_t buffer_available = 0;
+ GElf_Addr addrs[4];
+ if (unlikely (
+ read_addrs(read_vaddr,1,elfclass,&buffer,&read_vaddr,
+ &buffer_available,dwfl,memory_callback,memory_callback_arg,
+ elfdata,addrs)
+ )
+ )
+ return release_buffer (-1,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
GElf_Addr next = addrs[0];
@@ -317,9 +330,13 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
there must be a loop in the pointers due to link_map clobberation. */
size_t iterations = 0;
while (next != 0 && ++iterations < dwfl->lookup_elts)
- {
- if (read_addrs (next, 4))
- return release_buffer (-1);
+ {
+ if (
+ read_addrs(next,4,elfclass,&buffer,&read_vaddr,
+ &buffer_available,dwfl,memory_callback,memory_callback_arg,
+ elfdata,addrs)
+ )
+ return release_buffer (-1,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
/* Unused: l_addr is the difference between the address in memory
and the ELF file when the core was created. We need to
@@ -345,7 +362,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
name = l_name - read_vaddr + buffer;
else
{
- release_buffer (0);
+ release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
read_vaddr = l_name;
int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
if (likely (segndx >= 0)
@@ -372,7 +389,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
r_debug_info_module = malloc (sizeof (*r_debug_info_module)
+ strlen (name1) + 1);
if (unlikely (r_debug_info_module == NULL))
- return release_buffer (result);
+ return release_buffer (result,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
r_debug_info_module->fd = -1;
r_debug_info_module->elf = NULL;
r_debug_info_module->l_ld = l_ld;
@@ -413,7 +430,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
GElf_Addr build_id_vaddr = (build_id_elfaddr
- elf_dynamic_vaddr + l_ld);
- release_buffer (0);
+ release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
int segndx = INTUSE(dwfl_addrsegment) (dwfl,
build_id_vaddr,
NULL);
@@ -432,7 +449,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
/* File has valid build-id which does not match
the one in memory. */
valid = false;
- release_buffer (0);
+ release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
}
}
@@ -498,7 +515,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
}
}
- return release_buffer (result);
+ return release_buffer (result,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
}
\f
static GElf_Addr
@@ -688,6 +705,34 @@ find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
}
\f
+ inline static bool consider_phdr (GElf_Word type,
+ GElf_Addr vaddr, GElf_Xword filesz,
+ GElf_Addr *dyn_bias,Dwfl *dwfl,
+ GElf_Addr phdr, GElf_Addr *dyn_vaddr,
+ GElf_Xword *dyn_filesz)
+ {
+ switch (type)
+ {
+ case PT_PHDR:
+ if (*dyn_bias == (GElf_Addr) -1
+ /* Do a sanity check on the putative address. */
+ && ((vaddr & (dwfl->segment_align - 1))
+ == (phdr & (dwfl->segment_align - 1))))
+ {
+ *dyn_bias = phdr - vaddr;
+ return *dyn_vaddr != 0;
+ }
+ break;
+
+ case PT_DYNAMIC:
+ *dyn_vaddr = vaddr;
+ *dyn_filesz = filesz;
+ return *dyn_bias != (GElf_Addr) -1;
+ }
+
+ return false;
+ }
+
int
dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
Dwfl_Memory_Callback *memory_callback,
@@ -758,30 +803,6 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
GElf_Xword dyn_filesz = 0;
GElf_Addr dyn_bias = (GElf_Addr) -1;
- inline bool consider_phdr (GElf_Word type,
- GElf_Addr vaddr, GElf_Xword filesz)
- {
- switch (type)
- {
- case PT_PHDR:
- if (dyn_bias == (GElf_Addr) -1
- /* Do a sanity check on the putative address. */
- && ((vaddr & (dwfl->segment_align - 1))
- == (phdr & (dwfl->segment_align - 1))))
- {
- dyn_bias = phdr - vaddr;
- return dyn_vaddr != 0;
- }
- break;
-
- case PT_DYNAMIC:
- dyn_vaddr = vaddr;
- dyn_filesz = filesz;
- return dyn_bias != (GElf_Addr) -1;
- }
-
- return false;
- }
if (phdr != 0 && phnum != 0)
{
@@ -901,7 +922,10 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
for (size_t i = 0; i < phnum; ++i)
if (consider_phdr ((*p32)[i].p_type,
(*p32)[i].p_vaddr,
- (*p32)[i].p_filesz))
+ (*p32)[i].p_filesz,
+ &dyn_bias,dwfl,phdr,&dyn_vaddr,
+ &dyn_filesz
+ ))
break;
}
else
@@ -909,7 +933,10 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
for (size_t i = 0; i < phnum; ++i)
if (consider_phdr ((*p64)[i].p_type,
(*p64)[i].p_vaddr,
- (*p64)[i].p_filesz))
+ (*p64)[i].p_filesz,
+ &dyn_bias,dwfl,phdr,&dyn_vaddr,
+ &dyn_filesz
+ ))
break;
}
}
diff --git a/libelf/elf.h b/libelf/elf.h
index 6439c1a4..26420b45 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -444,6 +444,7 @@ typedef struct
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
#define SHT_NUM 19 /* Number of defined types. */
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
+#define SHT_LLVM_ADDRSIG 0x6FFF4C03 /* llvm address sig */
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
diff --git a/src/addr2line.c b/src/addr2line.c
index 69d8d995..038c8691 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -598,6 +598,21 @@ get_addr_width (Dwfl_Module *mod)
return width;
}
+inline static void show (int (*get) (Dwarf_Line *, bool *),
+ const char *note,Dwarf_Line *info)
+{
+bool flag;
+if ((*get) (info, &flag) == 0 && flag)
+fputs (note, stdout);
+}
+inline static void show_int (int (*get) (Dwarf_Line *, unsigned int *),
+ const char *name,Dwarf_Line *info)
+{
+unsigned int val;
+if ((*get) (info, &val) == 0 && val != 0)
+printf (" (%s %u)", name, val);
+}
+
static int
handle_address (const char *string, Dwfl *dwfl)
{
@@ -692,27 +707,13 @@ handle_address (const char *string, Dwfl *dwfl)
Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
assert (info != NULL);
- inline void show (int (*get) (Dwarf_Line *, bool *),
- const char *note)
- {
- bool flag;
- if ((*get) (info, &flag) == 0 && flag)
- fputs (note, stdout);
- }
- inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
- const char *name)
- {
- unsigned int val;
- if ((*get) (info, &val) == 0 && val != 0)
- printf (" (%s %u)", name, val);
- }
-
- show (&dwarf_linebeginstatement, " (is_stmt)");
- show (&dwarf_lineblock, " (basic_block)");
- show (&dwarf_lineprologueend, " (prologue_end)");
- show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
- show_int (&dwarf_lineisa, "isa");
- show_int (&dwarf_linediscriminator, "discriminator");
+
+ show (&dwarf_linebeginstatement, " (is_stmt)",info);
+ show (&dwarf_lineblock, " (basic_block)",info);
+ show (&dwarf_lineprologueend, " (prologue_end)",info);
+ show (&dwarf_lineepiloguebegin, " (epilogue_begin)",info);
+ show_int (&dwarf_lineisa, "isa",info);
+ show_int (&dwarf_linediscriminator, "discriminator",info);
}
putchar ('\n');
}
diff --git a/src/ar.c b/src/ar.c
index 7d33d814..2beadffb 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -436,30 +436,31 @@ copy_content (Elf *elf, int newfd, off_t off, size_t n)
return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
}
-
-static int
-do_oper_extract (int oper, const char *arfname, char **argv, int argc,
- long int instance)
-{
- bool found[argc > 0 ? argc : 1];
- memset (found, '\0', sizeof (found));
-
- size_t name_max = 0;
- inline bool should_truncate_fname (void)
+inline static bool should_truncate_fname (size_t *name_max)
{
if (errno == ENAMETOOLONG && allow_truncate_fname)
{
- if (name_max == 0)
+ if (*name_max == 0)
{
long int len = pathconf (".", _PC_NAME_MAX);
if (len > 0)
- name_max = len;
+ *name_max = len;
}
- return name_max != 0;
+ return *name_max != 0;
}
return false;
}
+
+static int
+do_oper_extract (int oper, const char *arfname, char **argv, int argc,
+ long int instance)
+{
+ bool found[argc > 0 ? argc : 1];
+ memset (found, '\0', sizeof (found));
+
+ size_t name_max = 0;
+
off_t index_off = -1;
size_t index_size = 0;
off_t cur_off = SARMAG;
@@ -615,7 +616,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
{
int printlen = INT_MAX;
- if (should_truncate_fname ())
+ if (should_truncate_fname (&name_max))
{
/* Try to truncate the name. First find out by how
much. */
@@ -704,7 +705,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
{
int printlen = INT_MAX;
- if (should_truncate_fname ())
+ if (should_truncate_fname (&name_max))
{
/* Try to truncate the name. First find out by how
much. */
diff --git a/src/arlib-argp.c b/src/arlib-argp.c
index 1bdd8d0b..8719ec10 100644
--- a/src/arlib-argp.c
+++ b/src/arlib-argp.c
@@ -56,10 +56,7 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
return 0;
}
-static char *
-help_filter (int key, const char *text, void *input __attribute__ ((unused)))
-{
- inline char *text_for_default (void)
+inline static char *text_for_default (const char *text)
{
char *new_text;
if (unlikely (asprintf (&new_text, gettext ("%s (default)"), text) < 0))
@@ -67,15 +64,19 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
return new_text;
}
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+
switch (key)
{
case 'D':
if (DEFAULT_AR_DETERMINISTIC)
- return text_for_default ();
+ return text_for_default (text);
break;
case 'U':
if (! DEFAULT_AR_DETERMINISTIC)
- return text_for_default ();
+ return text_for_default (text);
break;
}
diff --git a/src/elfcompress.c b/src/elfcompress.c
index 6ba6af41..0fa10299 100644
--- a/src/elfcompress.c
+++ b/src/elfcompress.c
@@ -242,52 +242,19 @@ compress_section (Elf_Scn *scn, size_t orig_size, const char *name,
return res;
}
-static int
-process_file (const char *fname)
-{
- if (verbose > 0)
- printf ("processing: %s\n", fname);
-
- /* The input ELF. */
- int fd = -1;
- Elf *elf = NULL;
-
- /* The output ELF. */
- char *fnew = NULL;
- int fdnew = -1;
- Elf *elfnew = NULL;
-
- /* Buffer for (one) new section name if necessary. */
- char *snamebuf = NULL;
-
- /* String table (and symbol table), if section names need adjusting. */
- Dwelf_Strtab *names = NULL;
- Dwelf_Strent **scnstrents = NULL;
- Dwelf_Strent **symstrents = NULL;
- char **scnnames = NULL;
-
- /* Section data from names. */
- void *namesbuf = NULL;
-
- /* Which sections match and need to be (un)compressed. */
- unsigned int *sections = NULL;
-
- /* How many sections are we talking about? */
- size_t shnum = 0;
-
#define WORD_BITS (8U * sizeof (unsigned int))
- void set_section (size_t ndx)
+ static void set_section (size_t ndx,unsigned int *sections)
{
sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS));
}
- bool get_section (size_t ndx)
+ static bool get_section (size_t ndx,unsigned int *sections)
{
return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
}
/* How many sections are we going to change? */
- size_t get_sections (void)
+ static size_t get_sections (size_t shnum,unsigned int *sections)
{
size_t s = 0;
for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
@@ -295,7 +262,10 @@ process_file (const char *fname)
return s;
}
- int cleanup (int res)
+ static int cleanup (int res,Elf *elf,Elf *elfnew,int fd,int fdnew,char *fnew,
+ char *snamebuf,Dwelf_Strtab *names,Dwelf_Strent **scnstrents,
+ Dwelf_Strent **symstrents,char **scnnames,size_t shnum,void *namesbuf,
+ unsigned int *sections)
{
elf_end (elf);
close (fd);
@@ -329,12 +299,46 @@ process_file (const char *fname)
return res;
}
+static int
+process_file (const char *fname)
+{
+ if (verbose > 0)
+ printf ("processing: %s\n", fname);
+
+ /* The input ELF. */
+ int fd = -1;
+ Elf *elf = NULL;
+
+ /* The output ELF. */
+ char *fnew = NULL;
+ int fdnew = -1;
+ Elf *elfnew = NULL;
+
+ /* Buffer for (one) new section name if necessary. */
+ char *snamebuf = NULL;
+
+ /* String table (and symbol table), if section names need adjusting. */
+ Dwelf_Strtab *names = NULL;
+ Dwelf_Strent **scnstrents = NULL;
+ Dwelf_Strent **symstrents = NULL;
+ char **scnnames = NULL;
+
+ /* Section data from names. */
+ void *namesbuf = NULL;
+
+ /* Which sections match and need to be (un)compressed. */
+ unsigned int *sections = NULL;
+
+ /* How many sections are we talking about? */
+ size_t shnum = 0;
+
fd = open (fname, O_RDONLY);
if (fd < 0)
{
error (0, errno, "Couldn't open %s\n", fname);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
elf = elf_begin (fd, ELF_C_READ, NULL);
@@ -342,7 +346,8 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't open ELF file %s for reading: %s",
fname, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
/* We dont' handle ar files (or anything else), we probably should. */
@@ -353,21 +358,24 @@ process_file (const char *fname)
error (0, 0, "Cannot handle ar files: %s", fname);
else
error (0, 0, "Unknown file type: %s", fname);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
struct stat st;
if (fstat (fd, &st) != 0)
{
error (0, errno, "Couldn't fstat %s", fname);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
GElf_Ehdr ehdr;
if (gelf_getehdr (elf, &ehdr) == NULL)
{
error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
/* Get the section header string table. */
@@ -376,7 +384,8 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get section header string table index in %s: %s",
fname, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
/* How many sections are we talking about? */
@@ -384,13 +393,15 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get number of sections in %s: %s",
fname, elf_errmsg (1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
if (shnum == 0)
{
error (0, 0, "ELF file %s has no sections", fname);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int));
@@ -398,8 +409,8 @@ process_file (const char *fname)
size_t phnum;
if (elf_getphdrnum (elf, &phnum) != 0)
{
- error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
/* Whether we need to adjust any section names (going to/from GNU
@@ -456,7 +467,8 @@ process_file (const char *fname)
{
error (0, 0, "Unexpected section number %zd, expected only %zd",
ndx, shnum);
- cleanup (-1);
+ cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+ symstrents,scnnames,shnum,namesbuf,sections);
}
GElf_Shdr shdr_mem;
@@ -464,14 +476,18 @@ process_file (const char *fname)
if (shdr == NULL)
{
error (0, 0, "Couldn't get shdr for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
if (sname == NULL)
{
error (0, 0, "Couldn't get name for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
if (section_name_matches (sname))
@@ -498,7 +514,7 @@ process_file (const char *fname)
else if (shdr->sh_type != SHT_NOBITS
&& (shdr->sh_flags & SHF_ALLOC) == 0)
{
- set_section (ndx);
+ set_section (ndx,sections);
/* Check if we might want to change this section name. */
if (! adjust_names
&& ((type != T_COMPRESS_GNU
@@ -532,7 +548,9 @@ process_file (const char *fname)
{
error (0, 0,
"Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
symtabndx = ndx;
}
@@ -549,12 +567,14 @@ process_file (const char *fname)
}
}
- if (foutput == NULL && get_sections () == 0)
+ if (foutput == NULL && get_sections (shnum,sections) == 0)
{
if (verbose > 0)
printf ("Nothing to do.\n");
fnew = NULL;
- return cleanup (0);
+ return cleanup (0,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
if (adjust_names)
@@ -563,7 +583,9 @@ process_file (const char *fname)
if (names == NULL)
{
error (0, 0, "Not enough memory for new strtab");
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
scnstrents = xmalloc (shnum
* sizeof (Dwelf_Strent *));
@@ -590,7 +612,9 @@ process_file (const char *fname)
/* Since we didn't create it we don't want to try to unlink it. */
free (fnew);
fnew = NULL;
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
@@ -598,21 +622,27 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't open new ELF %s for writing: %s",
fnew, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
/* Create the new ELF header and copy over all the data. */
if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
{
error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
GElf_Ehdr newehdr;
if (gelf_getehdr (elfnew, &newehdr) == NULL)
{
error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
@@ -625,7 +655,9 @@ process_file (const char *fname)
if (gelf_update_ehdr (elfnew, &newehdr) == 0)
{
error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
/* Copy over the phdrs as is. */
@@ -634,7 +666,9 @@ process_file (const char *fname)
if (gelf_newphdr (elfnew, phnum) == 0)
{
error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
for (size_t cnt = 0; cnt < phnum; ++cnt)
@@ -644,13 +678,17 @@ process_file (const char *fname)
if (phdr == NULL)
{
error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
{
error (0, 0, "Couldn't create phdr %zd: %s", cnt,
elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
}
}
@@ -687,14 +725,16 @@ process_file (const char *fname)
/* (de)compress if section matched. */
char *sname = NULL;
char *newname = NULL;
- if (get_section (ndx))
+ if (get_section (ndx,sections))
{
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr == NULL)
{
error (0, 0, "Couldn't get shdr for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
uint64_t size = shdr->sh_size;
@@ -702,7 +742,9 @@ process_file (const char *fname)
if (sname == NULL)
{
error (0, 0, "Couldn't get name for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
/* strdup sname, the shdrstrndx section itself might be
@@ -724,7 +766,9 @@ process_file (const char *fname)
{
if (compress_section (scn, size, sname, NULL, ndx,
false, false, verbose > 0) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
else if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
{
@@ -733,7 +777,9 @@ process_file (const char *fname)
newname = snamebuf;
if (compress_section (scn, size, sname, newname, ndx,
true, false, verbose > 0) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+ scnstrents,symstrents,scnnames,shnum,namesbuf,
+ sections);
}
else if (verbose > 0)
printf ("[%zd] %s already decompressed\n", ndx, sname);
@@ -748,7 +794,9 @@ process_file (const char *fname)
Don't report even when verbose. */
if (compress_section (scn, size, sname, NULL, ndx,
false, false, false) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
snamebuf[0] = '.';
@@ -779,7 +827,9 @@ process_file (const char *fname)
ndx, true, true,
verbose > 0);
if (res < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
if (res == 0)
newname = NULL;
@@ -805,7 +855,9 @@ process_file (const char *fname)
Don't report even when verbose. */
if (compress_section (scn, size, sname, NULL, ndx,
true, false, false) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
snamebuf[0] = '.';
strcpy (&snamebuf[1], &sname[2]);
@@ -833,7 +885,9 @@ process_file (const char *fname)
}
else if (compress_section (scn, size, sname, newname, ndx,
false, true, verbose > 0) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
else if (verbose > 0)
printf ("[%zd] %s already compressed\n", ndx, sname);
@@ -847,7 +901,9 @@ process_file (const char *fname)
if (newscn == NULL)
{
error (0, 0, "Couldn't create new section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
GElf_Shdr shdr_mem;
@@ -855,13 +911,17 @@ process_file (const char *fname)
if (shdr == NULL)
{
error (0, 0, "Couldn't get shdr for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
if (gelf_update_shdr (newscn, shdr) == 0)
{
error (0, 0, "Couldn't update section header %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Except for the section header string table all data can be
@@ -874,14 +934,18 @@ process_file (const char *fname)
if (data == NULL)
{
error (0, 0, "Couldn't get data from section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
Elf_Data *newdata = elf_newdata (newscn);
if (newdata == NULL)
{
error (0, 0, "Couldn't create new data for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
*newdata = *data;
@@ -899,7 +963,9 @@ process_file (const char *fname)
if (name == NULL)
{
error (0, 0, "Couldn't get name for section [%zd]", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
@@ -908,7 +974,9 @@ process_file (const char *fname)
if ((scnstrents[ndx] = dwelf_strtab_add (names, name)) == NULL)
{
error (0, 0, "No memory to add section name string table");
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* If the symtab shares strings then add those too. */
@@ -925,7 +993,9 @@ process_file (const char *fname)
/* Don't report the (internal) uncompression. */
if (compress_section (newscn, size, sname, NULL, ndx,
false, false, false) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
symtab_size = size;
symtab_compressed = T_COMPRESS_ZLIB;
@@ -935,7 +1005,9 @@ process_file (const char *fname)
/* Don't report the (internal) uncompression. */
if (compress_section (newscn, size, sname, NULL, ndx,
true, false, false) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
symtab_size = size;
symtab_compressed = T_COMPRESS_GNU;
@@ -947,7 +1019,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get symtab data for section [%zd] %s",
ndx, name);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
size_t syms = symd->d_size / elsize;
@@ -959,7 +1033,9 @@ process_file (const char *fname)
if (sym == NULL)
{
error (0, 0, "Couldn't get symbol %zd", i);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
if (sym->st_name != 0)
{
@@ -971,13 +1047,17 @@ process_file (const char *fname)
if (symname == NULL)
{
error (0, 0, "Couldn't get symbol %zd name", i);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
symstrents[i] = dwelf_strtab_add (names, symname);
if (symstrents[i] == NULL)
{
error (0, 0, "No memory to add to symbol name");
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
}
@@ -996,19 +1076,25 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get new section header string table [%zd]",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
Elf_Data *data = elf_newdata (scn);
if (data == NULL)
{
error (0, 0, "Couldn't create new section header string table data");
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
if (dwelf_strtab_finalize (names, data) == NULL)
{
error (0, 0, "Not enough memory to create string table");
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
namesbuf = data->d_buf;
@@ -1018,7 +1104,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get shdr for new section strings %zd",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Note that we also might have to compress and possibly set
@@ -1038,7 +1126,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't update new section strings [%zd]",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* We might have to compress the data if the user asked us to,
@@ -1054,7 +1144,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get section header string table [%zd]",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
shdr = gelf_getshdr (oldscn, &shdr_mem);
@@ -1062,7 +1154,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get shdr for old section strings [%zd]",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
@@ -1070,7 +1164,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get name for old section strings [%zd]",
shdrstrndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
shstrtab_size = shdr->sh_size;
@@ -1087,7 +1183,9 @@ process_file (const char *fname)
shstrtab_newname, shdrstrndx,
shstrtab_compressed == T_COMPRESS_GNU,
true, verbose > 0) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
@@ -1096,7 +1194,9 @@ process_file (const char *fname)
if (gelf_getehdr (elfnew, &newehdr) == NULL)
{
error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Set this after the sections have been created, otherwise section
@@ -1104,7 +1204,9 @@ process_file (const char *fname)
if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
{
error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Fixup pass. Adjust string table references, symbol table and
@@ -1121,7 +1223,9 @@ process_file (const char *fname)
if (shdr == NULL)
{
error (0, 0, "Couldn't get shdr for section %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Keep the offset of allocated sections so they are at the
@@ -1143,7 +1247,9 @@ process_file (const char *fname)
if (gelf_update_shdr (scn, shdr) == 0)
{
error (0, 0, "Couldn't update section header %zd", ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
if (adjust_names && ndx == symtabndx)
@@ -1156,7 +1262,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get new symtab data section [%zd]",
ndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
size_t syms = symd->d_size / elsize;
@@ -1167,7 +1275,9 @@ process_file (const char *fname)
if (sym == NULL)
{
error (0, 0, "2 Couldn't get symbol %zd", i);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
if (sym->st_name != 0)
@@ -1177,7 +1287,9 @@ process_file (const char *fname)
if (gelf_update_sym (symd, i, sym) == 0)
{
error (0, 0, "Couldn't update symbol %zd", i);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
}
@@ -1195,7 +1307,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get symbol table [%zd]",
symtabndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
shdr = gelf_getshdr (oldscn, &shdr_mem);
@@ -1203,7 +1317,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get old symbol table shdr [%zd]",
symtabndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
@@ -1211,7 +1327,9 @@ process_file (const char *fname)
{
error (0, 0, "Couldn't get old symbol table name [%zd]",
symtabndx);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
symtab_size = shdr->sh_size;
@@ -1229,7 +1347,9 @@ process_file (const char *fname)
symtab_newname, symtabndx,
symtab_compressed == T_COMPRESS_GNU,
true, verbose > 0) < 0)
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
}
@@ -1243,7 +1363,9 @@ process_file (const char *fname)
if (gelf_getehdr (elfnew, &newehdr) == NULL)
{
error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* Position the shdrs after the last (unallocated) section. */
@@ -1258,7 +1380,9 @@ process_file (const char *fname)
if (gelf_update_ehdr (elfnew, &newehdr) == 0)
{
error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
}
@@ -1268,7 +1392,9 @@ process_file (const char *fname)
if (elf_update (elfnew, ELF_C_WRITE) < 0)
{
error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
elf_end (elfnew);
@@ -1290,14 +1416,18 @@ process_file (const char *fname)
if (rename (fnew, fname) != 0)
{
error (0, errno, "Couldn't rename %s to %s", fnew, fname);
- return cleanup (-1);
+ return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
/* We are finally done with the new file, don't unlink it now. */
free (fnew);
fnew = NULL;
- return cleanup (0);
+ return cleanup (0,elf,elfnew,fd,fdnew,fnew,snamebuf,
+ names,scnstrents,symstrents,scnnames,
+ shnum,namesbuf, sections);
}
int
diff --git a/src/elflint.c b/src/elflint.c
index ef3e3732..05626084 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3421,6 +3421,16 @@ section [%2d] '%s': unknown parent version '%s'\n"),
}
}
+ inline static size_t pos (const unsigned char *p,Elf_Data *data)
+ {
+ return p - (const unsigned char *) data->d_buf;
+ }
+
+inline static size_t left (Elf_Data *data,const unsigned char *p)
+ {
+ return (const unsigned char *) data->d_buf + data->d_size - p;
+ }
+
static void
check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
{
@@ -3438,12 +3448,6 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
idx, section_name (ebl, idx));
return;
}
-
- inline size_t pos (const unsigned char *p)
- {
- return p - (const unsigned char *) data->d_buf;
- }
-
const unsigned char *p = data->d_buf;
if (*p++ != 'A')
{
@@ -3452,12 +3456,7 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
}
- inline size_t left (void)
- {
- return (const unsigned char *) data->d_buf + data->d_size - p;
- }
-
- while (left () >= 4)
+ while (left (data,p) >= 4)
{
uint32_t len;
memcpy (&len, p, sizeof len);
@@ -3465,16 +3464,16 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
if (len == 0)
ERROR (gettext ("\
section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
- idx, section_name (ebl, idx), pos (p));
+ idx, section_name (ebl, idx), pos (p,data));
if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
CONVERT (len);
- if (len > left ())
+ if (len > left (data,p))
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
- idx, section_name (ebl, idx), pos (p));
+ idx, section_name (ebl, idx), pos (p,data));
break;
}
@@ -3486,7 +3485,7 @@ section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
- idx, section_name (ebl, idx), pos (p));
+ idx, section_name (ebl, idx), pos (p,data));
break;
}
++q;
@@ -3503,7 +3502,7 @@ section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
- idx, section_name (ebl, idx), pos (chunk));
+ idx, section_name (ebl, idx), pos (chunk,data));
break;
}
@@ -3512,7 +3511,7 @@ section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: truncated attribute section\n"),
- idx, section_name (ebl, idx), pos (q));
+ idx, section_name (ebl, idx), pos (q,data));
break;
}
@@ -3521,7 +3520,7 @@ section [%2d] '%s': offset %zu: truncated attribute section\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
- idx, section_name (ebl, idx), pos (q));
+ idx, section_name (ebl, idx), pos (q,data));
q += sizeof subsection_len;
continue;
@@ -3536,7 +3535,7 @@ section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
- idx, section_name (ebl, idx), pos (q));
+ idx, section_name (ebl, idx), pos (q,data));
break;
}
@@ -3547,7 +3546,7 @@ section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
if (subsection_tag != 1) /* Tag_File */
ERROR (gettext ("\
section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
- idx, section_name (ebl, idx), pos (chunk), subsection_tag);
+ idx, section_name (ebl, idx), pos (chunk,data), subsection_tag);
else
{
chunk += sizeof subsection_len;
@@ -3565,7 +3564,7 @@ section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
- idx, section_name (ebl, idx), pos (chunk));
+ idx, section_name (ebl, idx), pos (chunk,data));
break;
}
}
@@ -3576,7 +3575,7 @@ section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
- idx, section_name (ebl, idx), pos (chunk));
+ idx, section_name (ebl, idx), pos (chunk,data));
break;
}
++r;
@@ -3589,11 +3588,11 @@ section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
&tag_name, &value_name))
ERROR (gettext ("\
section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
- idx, section_name (ebl, idx), pos (chunk), tag);
+ idx, section_name (ebl, idx), pos (chunk,data), tag);
else if ((tag & 1) == 0 && value_name == NULL)
ERROR (gettext ("\
section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
- idx, section_name (ebl, idx), pos (chunk),
+ idx, section_name (ebl, idx), pos (chunk,data),
tag_name, value);
chunk = r;
@@ -3603,13 +3602,13 @@ section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
else
ERROR (gettext ("\
section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
- idx, section_name (ebl, idx), pos (p), name);
+ idx, section_name (ebl, idx), pos (p,data), name);
}
- if (left () != 0)
+ if (left (data,p) != 0)
ERROR (gettext ("\
section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
- idx, section_name (ebl, idx), pos (p));
+ idx, section_name (ebl, idx), pos (p,data));
}
static bool has_loadable_segment;
@@ -3905,6 +3904,7 @@ section [%2zu] '%s': size not multiple of entry size\n"),
&& shdr->sh_type != SHT_GNU_ATTRIBUTES
&& shdr->sh_type != SHT_GNU_LIBLIST
&& shdr->sh_type != SHT_CHECKSUM
+ && shdr->sh_type != SHT_LLVM_ADDRSIG
&& shdr->sh_type != SHT_GNU_verdef
&& shdr->sh_type != SHT_GNU_verneed
&& shdr->sh_type != SHT_GNU_versym
diff --git a/src/readelf.c b/src/readelf.c
index f6d13afa..2bfe43bd 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -381,13 +381,7 @@ main (int argc, char *argv[])
return error_message_count != 0;
}
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg,
- struct argp_state *state __attribute__ ((unused)))
-{
- void add_dump_section (const char *name, bool implicit)
+static void add_dump_section (const char *name, bool implicit,int key)
{
struct section_argument *a = xmalloc (sizeof *a);
a->arg = name;
@@ -399,7 +393,14 @@ parse_opt (int key, char *arg,
*tailp = &a->next;
}
- switch (key)
+
+
+/* Handle program arguments. */
+static error_t
+parse_opt (int key, char *arg,
+ struct argp_state *state __attribute__ ((unused)))
+{
+ switch (key)
{
case 'a':
print_file_header = true;
@@ -414,9 +415,9 @@ parse_opt (int key, char *arg,
print_arch = true;
print_notes = true;
implicit_debug_sections |= section_exception;
- add_dump_section (".strtab", true);
- add_dump_section (".dynstr", true);
- add_dump_section (".comment", true);
+ add_dump_section (".strtab", true,key);
+ add_dump_section (".dynstr", true,key);
+ add_dump_section (".comment", true,key);
any_control_option = true;
break;
case 'A':
@@ -562,7 +563,7 @@ parse_opt (int key, char *arg,
}
FALLTHROUGH;
case 'x':
- add_dump_section (arg, false);
+ add_dump_section (arg, false,key);
any_control_option = true;
break;
case 'N':
@@ -3567,6 +3568,11 @@ print_liblist (Ebl *ebl)
}
}
+inline static size_t elf_left (Elf_Data *data,const unsigned char *p)
+ {
+ return (const unsigned char *) data->d_buf + data->d_size - p;
+ }
+
static void
print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
{
@@ -3611,13 +3617,9 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
fputs_unlocked (gettext (" Owner Size\n"), stdout);
- inline size_t left (void)
- {
- return (const unsigned char *) data->d_buf + data->d_size - p;
- }
-
+
/* Loop over the sections. */
- while (left () >= 4)
+ while (elf_left (data,p) >= 4)
{
/* Section length. */
uint32_t len;
@@ -3626,7 +3628,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
CONVERT (len);
- if (unlikely (len > left ()))
+ if (unlikely (len > elf_left (data,p)))
break;
/* Section vendor name. */
@@ -6200,6 +6202,12 @@ read_encoded (unsigned int encoding, const unsigned char *readp,
return readp;
}
+static const char *regname (unsigned int regno,Ebl *ebl,char *regnamebuf)
+ {
+ register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
+ return regnamebuf;
+ }
+
static void
print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
@@ -6210,12 +6218,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg)
{
char regnamebuf[REGNAMESZ];
- const char *regname (unsigned int regno)
- {
- register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
- return regnamebuf;
- }
-
+
puts ("\n Program:");
Dwarf_Word pc = vma_base;
while (readp < endp)
@@ -6271,26 +6274,26 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
get_uleb128 (op2, readp, endp);
printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
"\n",
- op1, regname (op1), op2 * data_align);
+ op1, regname (op1,ebl,regnamebuf), op2 * data_align);
break;
case DW_CFA_restore_extended:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
get_uleb128 (op1, readp, endp);
printf (" restore_extended r%" PRIu64 " (%s)\n",
- op1, regname (op1));
+ op1, regname (op1,ebl,regnamebuf));
break;
case DW_CFA_undefined:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
get_uleb128 (op1, readp, endp);
- printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
+ printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1,ebl,regnamebuf));
break;
case DW_CFA_same_value:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
get_uleb128 (op1, readp, endp);
- printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
+ printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1,ebl,regnamebuf));
break;
case DW_CFA_register:
if ((uint64_t) (endp - readp) < 1)
@@ -6300,7 +6303,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_uleb128 (op2, readp, endp);
printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
- op1, regname (op1), op2, regname (op2));
+ op1, regname (op1,ebl,regnamebuf), op2, regname (op2,ebl,regnamebuf));
break;
case DW_CFA_remember_state:
puts (" remember_state");
@@ -6316,14 +6319,14 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_uleb128 (op2, readp, endp);
printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
- op1, regname (op1), op2);
+ op1, regname (op1,ebl,regnamebuf), op2);
break;
case DW_CFA_def_cfa_register:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
get_uleb128 (op1, readp, endp);
printf (" def_cfa_register r%" PRIu64 " (%s)\n",
- op1, regname (op1));
+ op1, regname (op1,ebl,regnamebuf));
break;
case DW_CFA_def_cfa_offset:
if ((uint64_t) (endp - readp) < 1)
@@ -6354,7 +6357,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
printf (" expression r%" PRIu64 " (%s) \n",
- op1, regname (op1));
+ op1, regname (op1,ebl,regnamebuf));
if ((uint64_t) (endp - readp) < op2)
goto invalid;
print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
@@ -6370,7 +6373,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
get_sleb128 (sop2, readp, endp);
printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
PRId64 "\n",
- op1, regname (op1), sop2 * data_align);
+ op1, regname (op1,ebl,regnamebuf), sop2 * data_align);
break;
case DW_CFA_def_cfa_sf:
if ((uint64_t) (endp - readp) < 1)
@@ -6380,7 +6383,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_sleb128 (sop2, readp, endp);
printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
- op1, regname (op1), sop2 * data_align);
+ op1, regname (op1,ebl,regnamebuf), sop2 * data_align);
break;
case DW_CFA_def_cfa_offset_sf:
if ((uint64_t) (endp - readp) < 1)
@@ -6416,7 +6419,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */
printf (" val_expression r%" PRIu64 " (%s)\n",
- op1, regname (op1));
+ op1, regname (op1,ebl,regnamebuf));
if ((uint64_t) (endp - readp) < op2)
goto invalid;
print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
@@ -6456,11 +6459,11 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
goto invalid;
get_uleb128 (offset, readp, endp);
printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
- opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
+ opcode & 0x3f, regname (opcode & 0x3f,ebl,regnamebuf), offset * data_align);
}
else
printf (" restore r%u (%s)\n",
- opcode & 0x3f, regname (opcode & 0x3f));
+ opcode & 0x3f, regname (opcode & 0x3f,ebl,regnamebuf));
}
}
@@ -8343,6 +8346,22 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
return readp;
}
+/* Apply the "operation advance" from a special opcode
+ or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
+ static inline void advance_pc (unsigned int op_advance,
+ unsigned int *op_addr_advance,
+ uint_fast8_t minimum_instr_len,unsigned int *op_index ,
+ uint_fast8_t max_ops_per_instr, Dwarf_Word *address,
+ bool *show_op_index
+ )
+ {
+ *op_addr_advance = minimum_instr_len * ((*op_index + op_advance)
+ / max_ops_per_instr);
+ *address += *op_addr_advance;
+ *show_op_index = (*op_index > 0 ||
+ (*op_index + op_advance) % max_ops_per_instr > 0);
+ *op_index = (*op_index + op_advance) % max_ops_per_instr;
+ }
static void
print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
@@ -8731,20 +8750,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
size_t line = 1;
uint_fast8_t is_stmt = default_is_stmt;
- /* Apply the "operation advance" from a special opcode
- or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
unsigned int op_addr_advance;
bool show_op_index;
- inline void advance_pc (unsigned int op_advance)
- {
- op_addr_advance = minimum_instr_len * ((op_index + op_advance)
- / max_ops_per_instr);
- address += op_addr_advance;
- show_op_index = (op_index > 0 ||
- (op_index + op_advance) % max_ops_per_instr > 0);
- op_index = (op_index + op_advance) % max_ops_per_instr;
- }
-
+
if (max_ops_per_instr == 0)
{
error (0, 0,
@@ -8777,10 +8785,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
*/
int line_increment = (line_base
+ (opcode - opcode_base) % line_range);
-
- /* Perform the increments. */
+ /* Perform the increments. */
line += line_increment;
- advance_pc ((opcode - opcode_base) / line_range);
+ advance_pc ((opcode - opcode_base) / line_range,&op_addr_advance,minimum_instr_len,&op_index,max_ops_per_instr,&address,&show_op_index);
printf (gettext (" special opcode %u: address+%u = "),
opcode, op_addr_advance);
@@ -8898,7 +8905,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (lineendp - linep < 1)
goto invalid_unit;
get_uleb128 (u128, linep, lineendp);
- advance_pc (u128);
+ advance_pc (u128,&op_addr_advance,minimum_instr_len,
+ &op_index,max_ops_per_instr,&address,
+ &show_op_index
+ );
{
printf (gettext (" advance address by %u to "),
op_addr_advance);
@@ -8958,8 +8968,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (unlikely (line_range == 0))
goto invalid_unit;
-
- advance_pc ((255 - opcode_base) / line_range);
+ advance_pc ((255 - opcode_base) / line_range,
+ &op_addr_advance,minimum_instr_len,&op_index,
+ max_ops_per_instr,&address,
+ &show_op_index);
{
printf (gettext (" advance address by constant %u to "),
op_addr_advance);
@@ -12067,7 +12079,18 @@ compare_register_sets (const void *a, const void *b)
const struct register_info *const *p2 = b;
return compare_sets_by_info (*p1, *p2);
}
-
+ /* Collect the unique sets and sort them. */
+ inline static bool same_set (const struct register_info *a,
+ const struct register_info *b,
+ const struct register_info *regs,
+ ssize_t maxnreg
+ )
+ {
+ return (a < ®s[maxnreg] && a->regloc != NULL
+ && b < ®s[maxnreg] && b->regloc != NULL
+ && a->bits == b->bits
+ && (a->set == b->set || !strcmp (a->set, b->set)));
+ }
static unsigned int
handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
const Ebl_Register_Location *reglocs, size_t nregloc)
@@ -12105,20 +12128,13 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
}
qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
- /* Collect the unique sets and sort them. */
- inline bool same_set (const struct register_info *a,
- const struct register_info *b)
- {
- return (a < ®s[maxnreg] && a->regloc != NULL
- && b < ®s[maxnreg] && b->regloc != NULL
- && a->bits == b->bits
- && (a->set == b->set || !strcmp (a->set, b->set)));
- }
+
struct register_info *sets[maxreg + 1];
sets[0] = ®s[0];
size_t nsets = 1;
for (int i = 1; i <= maxreg; ++i)
- if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
+ if (regs[i].regloc != NULL &&
+ !same_set (®s[i], ®s[i - 1],regs, maxnreg))
sets[nsets++] = ®s[i];
qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
@@ -12129,7 +12145,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
/* Find the longest name of a register in this set. */
size_t maxname = 0;
const struct register_info *end;
- for (end = sets[i]; same_set (sets[i], end); ++end)
+ for (end = sets[i]; same_set (sets[i], end,regs,maxnreg); ++end)
{
size_t len = strlen (end->name);
if (len > maxname)
diff --git a/src/strip.c b/src/strip.c
index 48792a70..33e47dc0 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -442,85 +442,14 @@ update_shdrstrndx (Elf *elf, size_t shdrstrndx)
return 0;
}
-/* Remove any relocations between debug sections in ET_REL
- for the debug file when requested. These relocations are always
- zero based between the unallocated sections. */
-static void
-remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
- const char *fname, size_t shstrndx)
-{
- Elf_Scn *scn = NULL;
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- /* We need the actual section and header from the elf
- not just the cached original in shdr_info because we
- might want to change the size. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
- {
- /* Make sure that this relocation section points to a
- section to relocate with contents, that isn't
- allocated and that is a debug section. */
- Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
- GElf_Shdr tshdr_mem;
- GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
- if (tshdr->sh_type == SHT_NOBITS
- || tshdr->sh_size == 0
- || (tshdr->sh_flags & SHF_ALLOC) != 0)
- continue;
-
- const char *tname = elf_strptr (elf, shstrndx,
- tshdr->sh_name);
- if (! tname || ! ebl_debugscn_p (ebl, tname))
- continue;
-
- /* OK, lets relocate all trivial cross debug section
- relocations. */
- Elf_Data *reldata = elf_getdata (scn, NULL);
- if (reldata == NULL || reldata->d_buf == NULL)
- INTERNAL_ERROR (fname);
-
- /* Make sure we adjust the uncompressed debug data
- (and recompress if necessary at the end). */
- GElf_Chdr tchdr;
- int tcompress_type = 0;
- bool is_gnu_compressed = false;
- if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
- {
- is_gnu_compressed = true;
- if (elf_compress_gnu (tscn, 0, 0) != 1)
- INTERNAL_ERROR (fname);
- }
- else
- {
- if (gelf_getchdr (tscn, &tchdr) != NULL)
- {
- tcompress_type = tchdr.ch_type;
- if (elf_compress (tscn, 0, 0) != 1)
- INTERNAL_ERROR (fname);
- }
- }
-
- Elf_Data *tdata = elf_getdata (tscn, NULL);
- if (tdata == NULL || tdata->d_buf == NULL
- || tdata->d_type != ELF_T_BYTE)
- INTERNAL_ERROR (fname);
-
- /* Pick up the symbol table and shndx table to
- resolve relocation symbol indexes. */
- Elf64_Word symt = shdr->sh_link;
- Elf_Data *symdata, *xndxdata;
- Elf_Scn * symscn = elf_getscn (elf, symt);
- symdata = elf_getdata (symscn, NULL);
- xndxdata = get_xndxdata (elf, symscn);
- if (symdata == NULL)
- INTERNAL_ERROR (fname);
/* Apply one relocation. Returns true when trivial
relocation actually done. */
- bool relocate (GElf_Addr offset, const GElf_Sxword addend,
- bool is_rela, int rtype, int symndx)
+ static bool relocate (GElf_Addr offset, const GElf_Sxword addend,
+ bool is_rela, int rtype, int symndx,
+ Ebl *ebl,Elf_Data *symdata,Elf_Data *xndxdata,
+ Elf *elf,Elf_Data *tdata,GElf_Ehdr *ehdr,
+ const char *fname)
{
/* R_*_NONE relocs can always just be removed. */
if (rtype == 0)
@@ -658,6 +587,82 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
return false;
}
+/* Remove any relocations between debug sections in ET_REL
+ for the debug file when requested. These relocations are always
+ zero based between the unallocated sections. */
+static void
+remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
+ const char *fname, size_t shstrndx)
+{
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ /* We need the actual section and header from the elf
+ not just the cached original in shdr_info because we
+ might want to change the size. */
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+ {
+ /* Make sure that this relocation section points to a
+ section to relocate with contents, that isn't
+ allocated and that is a debug section. */
+ Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
+ GElf_Shdr tshdr_mem;
+ GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+ if (tshdr->sh_type == SHT_NOBITS
+ || tshdr->sh_size == 0
+ || (tshdr->sh_flags & SHF_ALLOC) != 0)
+ continue;
+
+ const char *tname = elf_strptr (elf, shstrndx,
+ tshdr->sh_name);
+ if (! tname || ! ebl_debugscn_p (ebl, tname))
+ continue;
+
+ /* OK, lets relocate all trivial cross debug section
+ relocations. */
+ Elf_Data *reldata = elf_getdata (scn, NULL);
+ if (reldata == NULL || reldata->d_buf == NULL)
+ INTERNAL_ERROR (fname);
+
+ /* Make sure we adjust the uncompressed debug data
+ (and recompress if necessary at the end). */
+ GElf_Chdr tchdr;
+ int tcompress_type = 0;
+ bool is_gnu_compressed = false;
+ if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
+ {
+ is_gnu_compressed = true;
+ if (elf_compress_gnu (tscn, 0, 0) != 1)
+ INTERNAL_ERROR (fname);
+ }
+ else
+ {
+ if (gelf_getchdr (tscn, &tchdr) != NULL)
+ {
+ tcompress_type = tchdr.ch_type;
+ if (elf_compress (tscn, 0, 0) != 1)
+ INTERNAL_ERROR (fname);
+ }
+ }
+
+ Elf_Data *tdata = elf_getdata (tscn, NULL);
+ if (tdata == NULL || tdata->d_buf == NULL
+ || tdata->d_type != ELF_T_BYTE)
+ INTERNAL_ERROR (fname);
+
+ /* Pick up the symbol table and shndx table to
+ resolve relocation symbol indexes. */
+ Elf64_Word symt = shdr->sh_link;
+ Elf_Data *symdata, *xndxdata;
+ Elf_Scn * symscn = elf_getscn (elf, symt);
+ symdata = elf_getdata (symscn, NULL);
+ xndxdata = get_xndxdata (elf, symscn);
+ if (symdata == NULL)
+ INTERNAL_ERROR (fname);
+
+
if (shdr->sh_entsize == 0)
INTERNAL_ERROR (fname);
@@ -670,7 +675,8 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
if (! relocate (r->r_offset, 0, false,
GELF_R_TYPE (r->r_info),
- GELF_R_SYM (r->r_info)))
+ GELF_R_SYM (r->r_info),ebl,symdata,xndxdata,
+ elf,tdata,ehdr,fname))
{
if (relidx != next)
gelf_update_rel (reldata, next, r);
@@ -684,7 +690,8 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
if (! relocate (r->r_offset, r->r_addend, true,
GELF_R_TYPE (r->r_info),
- GELF_R_SYM (r->r_info)))
+ GELF_R_SYM (r->r_info),ebl,symdata,xndxdata,
+ elf,tdata,ehdr,fname))
{
if (relidx != next)
gelf_update_rela (reldata, next, r);
@@ -917,6 +924,82 @@ handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
return 0;
}
+struct shdr_info
+ {
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ Elf_Data *debug_data;
+ const char *name;
+ Elf32_Word idx; /* Index in new file. */
+ Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
+ Elf32_Word symtab_idx;
+ Elf32_Word version_idx;
+ Elf32_Word group_idx;
+ Elf32_Word group_cnt;
+ Elf_Scn *newscn;
+ Dwelf_Strent *se;
+ Elf32_Word *newsymidx;
+ } *shdr_info = NULL;
+
+ /* This section is being preserved in the debug file.
+ Sections it refers to must be preserved there too.
+
+ In this pass we mark sections to be preserved in both
+ files by setting the .debug_data pointer to the original
+ file's .data pointer. Below, we'll copy the section
+ contents. */
+
+ inline static void check_preserved (size_t i,size_t shnum,
+ bool *changes,
+ const char *fname,size_t cnt)
+ {
+ if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
+ && shdr_info[i].debug_data == NULL)
+ {
+ if (shdr_info[i].data == NULL)
+ shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
+ if (shdr_info[i].data == NULL)
+ INTERNAL_ERROR (fname);
+
+ shdr_info[i].debug_data = shdr_info[i].data;
+ *changes |= i < cnt;
+ }
+ }
+
+ /* Update section headers when the data size has changed.
+ We also update the SHT_NOBITS section in the debug
+ file so that the section headers match in sh_size. */
+ inline static void update_section_size (const Elf_Data *newdata,Elf_Scn *scn,
+ Elf *debugelf, const char *fname,size_t cnt)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ shdr->sh_size = newdata->d_size;
+ (void) gelf_update_shdr (scn, shdr);
+ if (debugelf != NULL)
+ {
+ /* libelf will use d_size to set sh_size. */
+ Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
+ cnt), NULL);
+ if (debugdata == NULL)
+ INTERNAL_ERROR (fname);
+ debugdata->d_size = newdata->d_size;
+ }
+ }
+
+inline static bool no_symtab_updates (const Elf32_Word symtabidx,size_t cnt)
+ {
+ /* If the symbol table hasn't changed, do not do anything. */
+ if (shdr_info[symtabidx].newsymidx == NULL)
+ return true;
+
+ /* If the symbol table is not discarded, but additionally
+ duplicated in the separate debug file and this section
+ is discarded, don't adjust anything. */
+ return (shdr_info[cnt].idx == 0
+ && shdr_info[symtabidx].debug_data != NULL);
+ }
/* Maximum size of array allocated on stack. */
#define MAX_STACK_ALLOC (400 * 1024)
@@ -936,23 +1019,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
GElf_Off lastsec_offset = 0;
Elf64_Xword lastsec_size = 0;
size_t shstrndx;
- struct shdr_info
- {
- Elf_Scn *scn;
- GElf_Shdr shdr;
- Elf_Data *data;
- Elf_Data *debug_data;
- const char *name;
- Elf32_Word idx; /* Index in new file. */
- Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
- Elf32_Word symtab_idx;
- Elf32_Word version_idx;
- Elf32_Word group_idx;
- Elf32_Word group_cnt;
- Elf_Scn *newscn;
- Dwelf_Strent *se;
- Elf32_Word *newsymidx;
- } *shdr_info = NULL;
Elf_Scn *scn;
size_t cnt;
size_t idx;
@@ -1528,32 +1594,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
if (debug_fname != NULL
&& (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
{
- /* This section is being preserved in the debug file.
- Sections it refers to must be preserved there too.
-
- In this pass we mark sections to be preserved in both
- files by setting the .debug_data pointer to the original
- file's .data pointer. Below, we'll copy the section
- contents. */
-
- inline void check_preserved (size_t i)
- {
- if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
- && shdr_info[i].debug_data == NULL)
- {
- if (shdr_info[i].data == NULL)
- shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
- if (shdr_info[i].data == NULL)
- INTERNAL_ERROR (fname);
-
- shdr_info[i].debug_data = shdr_info[i].data;
- changes |= i < cnt;
- }
- }
-
- check_preserved (shdr_info[cnt].shdr.sh_link);
+ check_preserved (shdr_info[cnt].shdr.sh_link,shnum,
+ &changes,fname,cnt);
if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
- check_preserved (shdr_info[cnt].shdr.sh_info);
+ check_preserved (shdr_info[cnt].shdr.sh_info,shnum,
+ &changes,fname,cnt);
}
}
}
@@ -2124,25 +2169,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* Find all relocation sections which use this symbol table. */
for (cnt = 1; cnt <= shdridx; ++cnt)
{
- /* Update section headers when the data size has changed.
- We also update the SHT_NOBITS section in the debug
- file so that the section headers match in sh_size. */
- inline void update_section_size (const Elf_Data *newdata)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_size = newdata->d_size;
- (void) gelf_update_shdr (scn, shdr);
- if (debugelf != NULL)
- {
- /* libelf will use d_size to set sh_size. */
- Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
- cnt), NULL);
- if (debugdata == NULL)
- INTERNAL_ERROR (fname);
- debugdata->d_size = newdata->d_size;
- }
- }
+
if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
/* Ignore sections which are discarded. When we are saving a
@@ -2155,22 +2182,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
switch (shdr_info[cnt].shdr.sh_type)
{
- inline bool no_symtab_updates (void)
- {
- /* If the symbol table hasn't changed, do not do anything. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- return true;
-
- /* If the symbol table is not discarded, but additionally
- duplicated in the separate debug file and this section
- is discarded, don't adjust anything. */
- return (shdr_info[cnt].idx == 0
- && shdr_info[symtabidx].debug_data != NULL);
- }
-
+
case SHT_REL:
case SHT_RELA:
- if (no_symtab_updates ())
+ if (no_symtab_updates (symtabidx,cnt))
break;
Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
@@ -2227,7 +2242,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
break;
case SHT_HASH:
- if (no_symtab_updates ())
+ if (no_symtab_updates (symtabidx,cnt))
break;
/* We have to recompute the hash table. */
@@ -2273,7 +2288,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
* sizeof (Elf32_Word));
elf_assert (n_size <= hashd->d_size);
hashd->d_size = n_size;
- update_section_size (hashd);
+ update_section_size (hashd,scn,debugelf,fname,cnt);
/* Clear the arrays. */
memset (bucket, '\0',
@@ -2335,7 +2350,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
* sizeof (Elf64_Xword));
elf_assert (n_size <= hashd->d_size);
hashd->d_size = n_size;
- update_section_size (hashd);
+ update_section_size (hashd,scn,debugelf,fname,cnt);
/* Clear the arrays. */
memset (bucket, '\0',
@@ -2371,7 +2386,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
case SHT_GNU_versym:
/* If the symbol table changed we have to adjust the entries. */
- if (no_symtab_updates ())
+ if (no_symtab_updates (symtabidx,cnt))
break;
elf_assert (shdr_info[cnt].idx > 0);
@@ -2409,11 +2424,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/ gelf_fsize (elf, symd->d_type, 1,
EV_CURRENT),
EV_CURRENT);
- update_section_size (verd);
+ update_section_size (verd,scn,debugelf,fname,cnt);
break;
case SHT_GROUP:
- if (no_symtab_updates ())
+ if (no_symtab_updates (symtabidx,cnt))
break;
/* Yes, the symbol table changed.
diff --git a/src/unstrip.c b/src/unstrip.c
index 231b941d..f3b280f3 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -436,14 +436,7 @@ update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
update_shdr (outscn, newshdr);
}
-/* Update relocation sections using the symbol table. */
-static void
-adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
- size_t map[], size_t map_size, const GElf_Shdr *symshdr)
-{
- Elf_Data *data = elf_getdata (outscn, NULL);
-
- inline void adjust_reloc (GElf_Xword *info)
+inline static void adjust_reloc (GElf_Xword *info,size_t map_size,size_t map[])
{
size_t ndx = GELF_R_SYM (*info);
if (ndx != STN_UNDEF)
@@ -454,7 +447,15 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
}
}
- switch (shdr->sh_type)
+
+/* Update relocation sections using the symbol table. */
+static void
+adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
+ size_t map[], size_t map_size, const GElf_Shdr *symshdr)
+{
+ Elf_Data *data = elf_getdata (outscn, NULL);
+
+ switch (shdr->sh_type)
{
case SHT_REL:
if (shdr->sh_entsize == 0)
@@ -464,7 +465,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
{
GElf_Rel rel_mem;
GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
- adjust_reloc (&rel->r_info);
+ adjust_reloc (&rel->r_info,map_size,map);
ELF_CHECK (gelf_update_rel (data, i, rel),
_("cannot update relocation: %s"));
}
@@ -478,7 +479,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
{
GElf_Rela rela_mem;
GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
- adjust_reloc (&rela->r_info);
+ adjust_reloc (&rela->r_info,map_size,map);
ELF_CHECK (gelf_update_rela (data, i, rela),
_("cannot update relocation: %s"));
}
@@ -1066,6 +1067,16 @@ get_group_sig (Elf *elf, GElf_Shdr *shdr)
return sig;
}
+ inline static void check_match (bool match, Elf_Scn *scn, const char *name,bool *fail)
+ {
+ if (!match)
+ {
+ *fail = true;
+ error (0, 0, _("cannot find matching section for [%zu] '%s'"),
+ elf_ndxscn (scn), name);
+ }
+ }
+
/* Fix things up when prelink has moved some allocated sections around
and the debuginfo file's section headers no longer match up.
@@ -1202,16 +1213,6 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
}
bool fail = false;
- inline void check_match (bool match, Elf_Scn *scn, const char *name)
- {
- if (!match)
- {
- fail = true;
- error (0, 0, _("cannot find matching section for [%zu] '%s'"),
- elf_ndxscn (scn), name);
- }
- }
-
Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (debug, scn)) != NULL)
{
@@ -1242,7 +1243,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
if (sections[i].outscn == scn)
shdr = NULL;
- check_match (shdr == NULL, scn, name);
+ check_match (shdr == NULL, scn, name,&fail);
}
if (fail)
@@ -1298,7 +1299,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
}
}
- check_match (undo_sec == NULL, scn, name);
+ check_match (undo_sec == NULL, scn, name,&fail);
}
free (undo_sections);
@@ -1377,6 +1378,33 @@ new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
return strtab_data;
}
+/* Locate a matching unallocated section in SECTIONS. */
+ inline static struct section *find_unalloc_section (const GElf_Shdr *shdr,
+ const char *name,
+ const char *sig,
+ size_t nalloc,
+ size_t stripped_shnum,
+ struct section *sections
+ )
+ {
+ size_t l = nalloc, u = stripped_shnum - 1;
+ while (l < u)
+ {
+ size_t i = (l + u) / 2;
+ struct section *sec = §ions[i];
+ int cmp = compare_unalloc_sections (shdr, &sec->shdr,
+ name, sec->name,
+ sig, sec->sig);
+ if (cmp < 0)
+ u = i;
+ else if (cmp > 0)
+ l = i + 1;
+ else
+ return sec;
+ }
+ return NULL;
+ }
+
/* Fill in any SHT_NOBITS sections in UNSTRIPPED by
copying their contents and sh_type from STRIPPED. */
@@ -1450,30 +1478,7 @@ more sections in stripped file than debug file -- arguments reversed?"));
stripped_symtab = §ions[nalloc];
}
- /* Locate a matching unallocated section in SECTIONS. */
- inline struct section *find_unalloc_section (const GElf_Shdr *shdr,
- const char *name,
- const char *sig)
- {
- size_t l = nalloc, u = stripped_shnum - 1;
- while (l < u)
- {
- size_t i = (l + u) / 2;
- struct section *sec = §ions[i];
- int cmp = compare_unalloc_sections (shdr, &sec->shdr,
- name, sec->name,
- sig, sec->sig);
- if (cmp < 0)
- u = i;
- else if (cmp > 0)
- l = i + 1;
- else
- return sec;
- }
- return NULL;
- }
-
- Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
+ Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
unstripped_shstrndx), NULL);
ELF_CHECK (shstrtab != NULL,
_("cannot read section header string table: %s"));
@@ -1533,10 +1538,11 @@ more sections in stripped file than debug file -- arguments reversed?"));
}
}
else
- {
+ {
/* Look for the section that matches. */
sec = find_unalloc_section (shdr, name,
- get_group_sig (unstripped, shdr));
+ get_group_sig (unstripped, shdr),nalloc,
+ stripped_shnum,sections);
if (sec == NULL)
{
/* An additional unallocated section is fine if not SHT_NOBITS.
@@ -2227,22 +2233,22 @@ open_file (const char *file, bool writable)
error (EXIT_FAILURE, errno, _("cannot open '%s'"), file);
return fd;
}
-
-/* Handle a pair of files we need to open by name. */
-static void
-handle_explicit_files (const char *output_file, bool create_dirs, bool force,
- const char *stripped_file, const char *unstripped_file)
-{
-
- /* Warn, and exit if not forced to continue, if some ELF header
+/* Warn, and exit if not forced to continue, if some ELF header
sanity check for the stripped and unstripped files failed. */
- void warn (const char *msg)
+ static void warn (const char *msg,bool force,const char *stripped_file,const char *unstripped_file)
{
error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
force ? _("WARNING: ") : "",
stripped_file, unstripped_file, msg,
force ? "" : _(", use --force"));
}
+/* Handle a pair of files we need to open by name. */
+static void
+handle_explicit_files (const char *output_file, bool create_dirs, bool force,
+ const char *stripped_file, const char *unstripped_file)
+{
+
+
int stripped_fd = open_file (stripped_file, false);
Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
@@ -2264,16 +2270,19 @@ handle_explicit_files (const char *output_file, bool create_dirs, bool force,
if (memcmp (stripped_ehdr.e_ident,
unstripped_ehdr.e_ident, EI_NIDENT) != 0)
- warn (_("ELF header identification (e_ident) different"));
+ warn (_("ELF header identification (e_ident) different"),force,stripped_file,unstripped_file);
if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
- warn (_("ELF header type (e_type) different"));
+ warn (_("ELF header type (e_type) different"),force,stripped_file,unstripped_file);
+
+;
if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
- warn (_("ELF header machine type (e_machine) different"));
+ warn (_("ELF header machine type (e_machine) different"),force,stripped_file,unstripped_file);
if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
- warn (_("stripped program header (e_phnum) smaller than unstripped"));
+ warn (_("stripped program header (e_phnum) smaller than unstripped"),force,stripped_file,unstripped_file);
+
}
handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
@@ -2491,26 +2500,27 @@ match_module (Dwfl_Module *mod,
return DWARF_CB_OK;
}
+inline static ptrdiff_t next (ptrdiff_t offset,const struct arg_info *info,struct match_module_info *mmi)
+ {
+ return dwfl_getmodules (info->dwfl, &match_module, mmi, offset);
+ }
+
/* Handle files opened implicitly via libdwfl. */
static void
handle_implicit_modules (const struct arg_info *info)
{
struct match_module_info mmi = { info->args, NULL, info->match_files };
- inline ptrdiff_t next (ptrdiff_t offset)
- {
- return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
- }
- ptrdiff_t offset = next (0);
+ ptrdiff_t offset = next (0,info,&mmi);
if (offset == 0)
error (EXIT_FAILURE, 0, _("no matching modules found"));
if (info->list)
do
list_module (mmi.found);
- while ((offset = next (offset)) > 0);
+ while ((offset = next (offset,info,&mmi)) > 0);
else if (info->output_dir == NULL)
{
- if (next (offset) != 0)
+ if (next (offset,info,&mmi) != 0)
error (EXIT_FAILURE, 0, _("matched more than one module"));
handle_dwfl_module (info->output_file, false, info->force, mmi.found,
info->all, info->ignore, info->relocate);
@@ -2520,7 +2530,7 @@ handle_implicit_modules (const struct arg_info *info)
handle_output_dir_module (info->output_dir, mmi.found, info->force,
info->all, info->ignore,
info->modnames, info->relocate);
- while ((offset = next (offset)) > 0);
+ while ((offset = next (offset,info,&mmi)) > 0);
}
\f
int
diff --git a/tests/elfstrmerge.c b/tests/elfstrmerge.c
index ba0d68df..f5277c38 100644
--- a/tests/elfstrmerge.c
+++ b/tests/elfstrmerge.c
@@ -147,6 +147,50 @@ fail_elf_idx (const char *msg, const char *fname, size_t idx)
abort();
}
+/* section index mapping and sanity checking. */
+ static size_t newsecndx (size_t secndx, const char *what, size_t widx,
+ const char *member, size_t midx,size_t shdrstrndx,
+ size_t shdrnum,
+ const char *fname)
+ {
+ if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
+ {
+ /* Don't use fail... too specialized messages. Call release
+ outselves and then error. Ignores midx if widx is
+ zero. */
+ release ();
+ if (widx == 0)
+ error (1, 0, "%s: bad section index %zd in %s for %s",
+ fname, secndx, what, member);
+ else if (midx == 0)
+ error (1, 0, "%s: bad section index %zd in %s %zd for %s",
+ fname, secndx, what, widx, member);
+ else
+ error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
+ fname, secndx, what, widx, member, midx);
+ }
+
+ return secndx < shdrstrndx ? secndx : secndx - 1;
+ }
+
+
+ /* Some sections need a new data buffer because they need to
+ manipulate the original data. Allocate and check here, so we
+ have a list of all data buffers we might need to release when
+ done. */
+ static void new_data_buf (Elf_Data *d,const char *fname,size_t ndx,
+ size_t shdrstrndx, size_t shdrnum)
+ {
+ size_t s = d->d_size;
+ if (s == 0)
+ fail_idx ("Expected data in section", fname, ndx);
+ void *b = malloc (d->d_size);
+ if (b == NULL)
+ fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
+ newscnbufs[newsecndx (ndx, "section", ndx, "d_buf", 0,
+ shdrstrndx, shdrnum,fname )] = d->d_buf = b;
+ }
+
int
main (int argc, char **argv)
{
@@ -325,30 +369,6 @@ main (int argc, char **argv)
if (newstrtabdata.d_size >= shdrstrshdr->sh_size + strtabshdr->sh_size)
fail ("Impossible, merged string table is larger", fname);
- /* section index mapping and sanity checking. */
- size_t newsecndx (size_t secndx, const char *what, size_t widx,
- const char *member, size_t midx)
- {
- if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
- {
- /* Don't use fail... too specialized messages. Call release
- outselves and then error. Ignores midx if widx is
- zero. */
- release ();
- if (widx == 0)
- error (1, 0, "%s: bad section index %zd in %s for %s",
- fname, secndx, what, member);
- else if (midx == 0)
- error (1, 0, "%s: bad section index %zd in %s %zd for %s",
- fname, secndx, what, widx, member);
- else
- error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
- fname, secndx, what, widx, member, midx);
- }
-
- return secndx < shdrstrndx ? secndx : secndx - 1;
- }
-
struct stat st;
if (fstat (fd, &st) != 0)
fail_errno("Couldn't fstat", fname);
@@ -392,7 +412,9 @@ main (int argc, char **argv)
newehdr.e_flags = ehdr.e_flags;
/* The new file uses the new strtab as shstrtab. */
- size_t newstrtabndx = newsecndx (strtabndx, "ehdr", 0, "e_shstrndx", 0);
+
+ size_t newstrtabndx = newsecndx (strtabndx, "ehdr", 0, "e_shstrndx", 0,shdrstrndx,
+ shdrnum,fname);
if (newstrtabndx < SHN_LORESERVE)
newehdr.e_shstrndx = newstrtabndx;
else
@@ -459,30 +481,19 @@ main (int argc, char **argv)
newshdr.sh_flags = shdr->sh_flags;
newshdr.sh_addr = shdr->sh_addr;
newshdr.sh_size = shdr->sh_size;
+
if (shdr->sh_link != 0)
- newshdr.sh_link = newsecndx (shdr->sh_link, "shdr", ndx, "sh_link", 0);
+ newshdr.sh_link = newsecndx (shdr->sh_link, "shdr", ndx, "sh_link", 0,
+ shdrstrndx,shdrnum,fname);
else
newshdr.sh_link = 0;
if (SH_INFO_LINK_P (shdr) && shdr->sh_info != 0)
- newshdr.sh_info = newsecndx (shdr->sh_info, "shdr", ndx, "sh_info", 0);
+ newshdr.sh_info = newsecndx (shdr->sh_info, "shdr", ndx, "sh_info", 0,
+ shdrstrndx,shdrnum,fname);
else
newshdr.sh_info = shdr->sh_info;
newshdr.sh_entsize = shdr->sh_entsize;
- /* Some sections need a new data buffer because they need to
- manipulate the original data. Allocate and check here, so we
- have a list of all data buffers we might need to release when
- done. */
- void new_data_buf (Elf_Data *d)
- {
- size_t s = d->d_size;
- if (s == 0)
- fail_idx ("Expected data in section", fname, ndx);
- void *b = malloc (d->d_size);
- if (b == NULL)
- fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
- newscnbufs[newsecndx (ndx, "section", ndx, "d_buf", 0)] = d->d_buf = b;
- }
Elf_Data *newdata = elf_newdata (newscn);
if (newdata == NULL)
@@ -510,7 +521,7 @@ main (int argc, char **argv)
const bool update_name = shdr->sh_link == strtabndx;
if (update_name && ndx != symtabndx)
fail ("Only one symbol table using strtab expected", fname);
- new_data_buf (newdata);
+ new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
size_t syms = (data->d_size
/ gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
for (size_t i = 0; i < syms; i++)
@@ -527,7 +538,8 @@ main (int argc, char **argv)
else if (sym.st_shndx != SHN_UNDEF
&& sym.st_shndx < SHN_LORESERVE)
sym.st_shndx = newsecndx (sym.st_shndx, "section", ndx,
- "symbol", i);
+ "symbol", i,
+ shdrstrndx, shdrnum,fname );
if (update_name && sym.st_name != 0)
sym.st_name = dwelf_strent_off (symstrents[i]);
@@ -541,7 +553,7 @@ main (int argc, char **argv)
case SHT_GROUP:
{
- new_data_buf (newdata);
+ new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
/* A section group contains Elf32_Words. The first
word is a falg value, the rest of the words are
indexes of the sections belonging to the group. */
@@ -553,13 +565,14 @@ main (int argc, char **argv)
newgroup[0] = group[0];
for (size_t i = 1; i < words; i++)
newgroup[i] = newsecndx (group[i], "section", ndx,
- "group", i);
+ "group", i,
+ shdrstrndx, shdrnum,fname );
}
break;
case SHT_SYMTAB_SHNDX:
{
- new_data_buf (newdata);
+ new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
/* A SHNDX just contains an array of section indexes
for the corresponding symbol table. The entry is
SHN_UNDEF unless the corresponding symbol is
@@ -572,7 +585,8 @@ main (int argc, char **argv)
newshndx[i] = SHN_UNDEF;
else
newshndx[i] = newsecndx (shndx[i], "section", ndx,
- "shndx", i);
+ "shndx", i,
+ shdrstrndx, shdrnum,fname );
}
break;
diff --git a/tests/zstrptr.c b/tests/zstrptr.c
index 6d8e19f7..173c9426 100644
--- a/tests/zstrptr.c
+++ b/tests/zstrptr.c
@@ -30,6 +30,26 @@
#include ELFUTILS_HEADER(elf)
#include <gelf.h>
+static void print_strings (Elf_Scn *scn,size_t ndx,Elf *elf)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+ printf ("Strings in section %zd (%s):\n", ndx,
+ ((shdr->sh_flags & SHF_COMPRESSED) != 0
+ ? "compressed" : "uncompressed"));
+
+ size_t off = 0;
+ const char *str = elf_strptr (elf, ndx, off);
+ while (str != NULL)
+ {
+ printf ("[%zx] '%s'\n", off, str);
+ off += strlen (str) + 1;
+ str = elf_strptr (elf, ndx, off);
+ }
+ }
+
+
int
main (int argc, char *argv[])
{
@@ -79,38 +99,20 @@ main (int argc, char *argv[])
exit (1);
}
- void print_strings (void)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- printf ("Strings in section %zd (%s):\n", ndx,
- ((shdr->sh_flags & SHF_COMPRESSED) != 0
- ? "compressed" : "uncompressed"));
-
- size_t off = 0;
- const char *str = elf_strptr (elf, ndx, off);
- while (str != NULL)
- {
- printf ("[%zx] '%s'\n", off, str);
- off += strlen (str) + 1;
- str = elf_strptr (elf, ndx, off);
- }
- }
-
+
if (elf_compress (scn, ELFCOMPRESS_ZLIB, 0) < 0)
{
printf ("Couldn't compress section %zd: %s\n", ndx, elf_errmsg (-1));
exit (1);
}
- print_strings ();
+ print_strings (scn,ndx,elf);
if (elf_compress (scn, 0, 0) < 0)
{
printf ("Couldn't decompress section %zd: %s\n", ndx, elf_errmsg (-1));
exit (1);
}
- print_strings ();
+ print_strings (scn,ndx,elf);
if (elf_end (elf) != 0)
{
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread