[PATCH] libdwfl: dwfl_standard_argp should not fail when not able to attach Dwfl.
by Mark Wielaard
As pointed out in https://bugzilla.redhat.com/show_bug.cgi?id=1107654
commit 191080 introduced a thinko that caused dwfl_standard_argp
to fail if the Dwfl couldn't be attached. Instead of generating a warning
as the comment intended, the failure would be fatal. But even warning
about dwfl_core_file_attach () or dwfl_linux_proc_attach () failing
would be a mistake. The caller/user might not be interested in such
a non-fatal issue. So just ignore if the call failed for whatever reason.
If the caller is interested in warning up front about this issue, then
dwfl_pid () should be called to check the Dwfl is attached. Things should
work just fine for anything that doesn't call any of the dwfl_state related
functions.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/argp-std.c | 13 +++++--------
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 2fd2a1a..c13e01f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-10 Mark Wielaard <mjw(a)redhat.com>
+
+ * argp-std.c (parse_opt): Ignore errors from dwfl_core_file_attach
+ or dwfl_linux_proc_attach.
+
2014-05-15 Mark Wielaard <mjw(a)redhat.com>
* linux-proc-maps.c (grovel_auxv): Close fd on error.
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 8d2bc6a..42b7e78 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -171,10 +171,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (result != 0)
return fail (dwfl, result, arg);
- result = INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
- if (result != 0)
- /* Non-fatal to not be able to attach to process. */
- failure (dwfl, result, _("cannot attach to process"));
+ /* Non-fatal to not be able to attach to process, ignore error. */
+ INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
+
opt->dwfl = dwfl;
}
else
@@ -301,10 +300,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
return fail (dwfl, result, opt->core);
}
- result = INTUSE(dwfl_core_file_attach) (dwfl, core);
- if (result < 0)
- /* Non-fatal to not be able to attach to core. */
- failure (dwfl, result, _("cannot attach to core"));
+ /* Non-fatal to not be able to attach to core, ignore error. */
+ INTUSE(dwfl_core_file_attach) (dwfl, core);
/* From now we leak FD and CORE. */
--
1.7.1
9 years, 10 months
[PATCH] libdwfl: Record dwfl_attach_state error and return it on failure.
by Mark Wielaard
When dwfl_attach_state fails functions that need the process state should
return the error that caused the attach to fail. Use this in the backtrace
test to signal any attach failure. This makes sure that architectures that
don't provide unwinder support get properly detected (and the tests SKIPs)
Also don't assert when trying to attach a non-core ELF file, but return an
error to indicate failure.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 13 ++++++++++++
libdwfl/dwfl_frame.c | 46 +++++++++++++++++++++++++++++++++---------
libdwfl/libdwflP.h | 4 ++-
libdwfl/linux-core-attach.c | 44 +++++++++++++++++++++++-----------------
libdwfl/linux-pid-attach.c | 25 +++++++++++++++++++---
tests/ChangeLog | 5 ++++
tests/backtrace.c | 5 +++-
7 files changed, 107 insertions(+), 35 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index c13e01f..ac92a21 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,16 @@
+2014-06-11 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_frame.c (__libdwfl_process_free): Reset dwfl->attacherr.
+ (dwfl_attach_state): Set dwfl->attacherr.
+ (dwfl_pid): Check and return dwfl->attacherr if set.
+ (dwfl_getthreads): Likewise.
+ (getthread): Likewise.
+ * libdwflP.h: Add DWFL_E_NO_CORE_FILE.
+ (struct Dwfl): Add attacherr field.
+ * linux-core-attach.c (dwfl_core_file_attach): Set dwfl->attacherr.
+ Don't assert if ELF file is not ET_CORE, just return error.
+ * linux-pid-attach.c (dwfl_linux_proc_attach): Set dwfl->attacherr.
+
2014-06-10 Mark Wielaard <mjw(a)redhat.com>
* argp-std.c (parse_opt): Ignore errors from dwfl_core_file_attach
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
index fd0b9ae..f6f86c0 100644
--- a/libdwfl/dwfl_frame.c
+++ b/libdwfl/dwfl_frame.c
@@ -1,5 +1,5 @@
/* Get Dwarf Frame state for target PID or core file.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -117,6 +117,7 @@ __libdwfl_process_free (Dwfl_Process *process)
if (process->ebl_close)
ebl_closebackend (process->ebl);
free (process);
+ dwfl->attacherr = DWFL_E_NOERROR;
}
/* Allocate new Dwfl_Process for DWFL. */
@@ -134,17 +135,24 @@ bool
dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
const Dwfl_Thread_Callbacks *thread_callbacks, void *arg)
{
- if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL
- || thread_callbacks->set_initial_registers == NULL)
+ if (dwfl->process != NULL)
{
- __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+ __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
return false;
}
- if (dwfl->process != NULL)
+
+ /* Reset any previous error, we are just going to try again. */
+ dwfl->attacherr = DWFL_E_NOERROR;
+ if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL
+ || thread_callbacks->set_initial_registers == NULL)
{
- __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
+ dwfl->attacherr = DWFL_E_INVALID_ARGUMENT;
+ fail:
+ dwfl->attacherr = __libdwfl_canon_error (dwfl->attacherr);
+ __libdwfl_seterrno (dwfl->attacherr);
return false;
}
+
Ebl *ebl;
bool ebl_close;
if (elf != NULL)
@@ -180,8 +188,8 @@ dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
if (ebl == NULL)
{
/* Not identified EBL from any of the modules. */
- __libdwfl_seterrno (DWFL_E_PROCESS_NO_ARCH);
- return false;
+ dwfl->attacherr = DWFL_E_PROCESS_NO_ARCH;
+ goto fail;
}
process_alloc (dwfl);
Dwfl_Process *process = dwfl->process;
@@ -189,8 +197,8 @@ dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
{
if (ebl_close)
ebl_closebackend (ebl);
- __libdwfl_seterrno (DWFL_E_NOMEM);
- return false;
+ dwfl->attacherr = DWFL_E_NOMEM;
+ goto fail;
}
process->ebl = ebl;
process->ebl_close = ebl_close;
@@ -204,6 +212,12 @@ INTDEF(dwfl_attach_state)
pid_t
dwfl_pid (Dwfl *dwfl)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
if (dwfl->process == NULL)
{
__libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
@@ -238,6 +252,12 @@ int
dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
void *arg)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
@@ -309,6 +329,12 @@ getthread (Dwfl *dwfl, pid_t tid,
int (*callback) (Dwfl_Thread *thread, void *arg),
void *arg)
{
+ if (dwfl->attacherr != DWFL_E_NOERROR)
+ {
+ __libdwfl_seterrno (dwfl->attacherr);
+ return -1;
+ }
+
Dwfl_Process *process = dwfl->process;
if (process == NULL)
{
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 9b03d8a..30c0f8a 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -91,7 +91,8 @@ typedef struct Dwfl_Process Dwfl_Process;
DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state")) \
DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \
DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
- DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))
+ DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument")) \
+ DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file"))
#define DWFL_ERROR(name, text) DWFL_E_##name,
typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -110,6 +111,7 @@ struct Dwfl
Dwfl_Module *modulelist; /* List in order used by full traversals. */
Dwfl_Process *process;
+ Dwfl_Error attacherr; /* Previous error attaching process. */
GElf_Addr offline_next_address;
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
index 1002788..7ef3f25 100644
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -1,5 +1,5 @@
/* Get Dwarf Frame state for target core file.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -309,33 +309,41 @@ static const Dwfl_Thread_Callbacks core_thread_callbacks =
int
dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
{
+ Dwfl_Error err = DWFL_E_NOERROR;
Ebl *ebl = ebl_openbackend (core);
if (ebl == NULL)
{
- __libdwfl_seterrno (DWFL_E_LIBEBL);
+ err = DWFL_E_LIBEBL;
+ fail_err:
+ if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+ dwfl->attacherr = __libdwfl_canon_error (err);
+ __libdwfl_seterrno (err);
return -1;
}
size_t nregs = ebl_frame_nregs (ebl);
if (nregs == 0)
{
- __libdwfl_seterrno (DWFL_E_NO_UNWIND);
+ err = DWFL_E_NO_UNWIND;
+ fail:
ebl_closebackend (ebl);
- return -1;
+ goto fail_err;
}
GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
if (ehdr == NULL)
{
- __libdwfl_seterrno (DWFL_E_LIBELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_LIBELF;
+ goto fail;
+ }
+ if (ehdr->e_type != ET_CORE)
+ {
+ err = DWFL_E_NO_CORE_FILE;
+ goto fail;
}
- assert (ehdr->e_type == ET_CORE);
size_t phnum;
if (elf_getphdrnum (core, &phnum) < 0)
{
- __libdwfl_seterrno (DWFL_E_LIBELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_LIBELF;
+ goto fail;
}
pid_t pid = -1;
Elf_Data *note_data = NULL;
@@ -351,8 +359,8 @@ dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
}
if (note_data == NULL)
{
- ebl_closebackend (ebl);
- return DWFL_E_LIBELF;
+ err = DWFL_E_LIBELF;
+ goto fail;
}
size_t offset = 0;
GElf_Nhdr nhdr;
@@ -394,16 +402,14 @@ dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
if (pid == -1)
{
/* No valid NT_PRPSINFO recognized in this CORE. */
- __libdwfl_seterrno (DWFL_E_BADELF);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_BADELF;
+ goto fail;
}
struct core_arg *core_arg = malloc (sizeof *core_arg);
if (core_arg == NULL)
{
- __libdwfl_seterrno (DWFL_E_NOMEM);
- ebl_closebackend (ebl);
- return -1;
+ err = DWFL_E_NOMEM;
+ goto fail;
}
core_arg->core = core;
core_arg->note_data = note_data;
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 8aee721..d60955e 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -290,13 +290,23 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
{
char buffer[36];
FILE *procfile;
+ int err = 0; /* The errno to return and set for dwfl->attcherr. */
/* Make sure to report the actual PID (thread group leader) to
dwfl_attach_state. */
snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
procfile = fopen (buffer, "r");
if (procfile == NULL)
- return errno;
+ {
+ err = errno;
+ fail:
+ if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+ {
+ errno = err;
+ dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
+ }
+ return err;
+ }
char *line = NULL;
size_t linelen = 0;
@@ -317,19 +327,26 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
fclose (procfile);
if (pid == 0)
- return ESRCH;
+ {
+ err = ESRCH;
+ goto fail;
+ }
char dirname[64];
int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
DIR *dir = opendir (dirname);
if (dir == NULL)
- return errno;
+ {
+ err = errno;
+ goto fail;
+ }
struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
if (pid_arg == NULL)
{
closedir (dir);
- return ENOMEM;
+ err = ENOMEM;
+ goto fail;
}
pid_arg->dir = dir;
pid_arg->tid_attached = 0;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index bb0ad0d..cd8a8e7 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-11 Mark Wielaard <mjw(a)redhat.com>
+
+ * backtrace.c (main): Check that Dwfl was attached by calling
+ dwfl_pid and printing the error when it is not.
+
2014-05-18 Mark Wielaard <mjw(a)redhat.com>
* testfile-backtrace-demangle.cc (cxxfunc): Make non-static.
diff --git a/tests/backtrace.c b/tests/backtrace.c
index 1a4709b..ce0bd17 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -1,5 +1,5 @@
/* Test program for unwinding of frames.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -459,6 +459,9 @@ main (int argc __attribute__ ((unused)), char **argv)
};
(void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
assert (dwfl != NULL);
+ /* We want to make sure the dwfl was properly attached. */
+ if (dwfl_pid (dwfl) < 0)
+ error (2, 0, "dwfl_pid: %s", dwfl_errmsg (-1));
dump (dwfl);
dwfl_end (dwfl);
return 0;
--
1.7.1
9 years, 10 months
[PATCH] readelf: Skip section if name is NULL in print_debug.
by Mark Wielaard
Don't crash and burn when a section doesn't have a name (possibly invalid
ELF file string table). Just try the next section instead of calling strcmp
on NULL.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 4 ++++
src/readelf.c | 4 +++-
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 5535cff..7e68036 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-27 Mark Wielaard <mjw(a)redhat.com>
+
+ * readelf.c (print_debug): Skip section if name is NULL.
+
2014-05-26 Mark Wielaard <mjw(a)redhat.com>
* readelf.c (handle_relocs_rela): Print header like handle_relocs_rel
diff --git a/src/readelf.c b/src/readelf.c
index ea14a09..6bbe436 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -7962,8 +7962,10 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
/ sizeof (debug_sections[0]));
const char *name = elf_strptr (ebl->elf, shstrndx,
shdr->sh_name);
- int n;
+ if (name == NULL)
+ continue;
+ int n;
for (n = 0; n < ndebug_sections; ++n)
if (strcmp (name, debug_sections[n].name) == 0
#if USE_ZLIB
--
1.7.1
9 years, 10 months
[PATCH] readelf: Don't print 'for section' when rela section sh_info is zero.
by Mark Wielaard
This matches how handle_relocs_rel already printed the header.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 5 +++++
src/readelf.c | 16 +++++++++++++++-
2 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 4062fc7..5535cff 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+ * readelf.c (handle_relocs_rela): Print header like handle_relocs_rel
+ does, when sh_info == 0.
+
+2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+
* unstrip.c (find_alloc_sections_prelink): Allow non-split .bss
section when sh_size of the original and undo .bss section are equal.
diff --git a/src/readelf.c b/src/readelf.c
index 45b1910..ea14a09 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -1971,7 +1971,8 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
error (EXIT_FAILURE, 0,
gettext ("cannot get section header string table index"));
- printf (ngettext ("\
+ if (shdr->sh_info != 0)
+ printf (ngettext ("\
\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
"\
\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
@@ -1982,6 +1983,19 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
shdr->sh_offset,
nentries);
+ else
+ /* The .rela.dyn section does not refer to a specific section but
+ instead of section index zero. Do not try to print a section
+ name. */
+ printf (ngettext ("\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+ "\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+ nentries),
+ (unsigned int) elf_ndxscn (scn),
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+ shdr->sh_offset,
+ nentries);
fputs_unlocked (class == ELFCLASS32
? gettext ("\
Offset Type Value Addend Name\n")
--
1.7.1
9 years, 10 months
[PATCH] unstrip: Allow prelinked, but non-split .bss section.
by Mark Wielaard
If the section sh_size of the original and undo section are equal then
match them and don't set split_bss. This is also what prelink's
undo_sections allows.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 5 +++++
src/unstrip.c | 5 +++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 4067583..4062fc7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,10 @@
2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+ * unstrip.c (find_alloc_sections_prelink): Allow non-split .bss
+ section when sh_size of the original and undo .bss section are equal.
+
+2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+
* unstrip.c (options): Add --force, -F.
(struct arg_info): Add bool force.
(parse_opt): Handle 'F', set force.
diff --git a/src/unstrip.c b/src/unstrip.c
index 4738abb..3813694 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -1125,10 +1125,11 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
&& (sec->shdr.sh_type == undo_sec->shdr.sh_type
|| (sec->shdr.sh_type == SHT_PROGBITS
&& undo_sec->shdr.sh_type == SHT_NOBITS))
- && sec->shdr.sh_size < undo_sec->shdr.sh_size
+ && sec->shdr.sh_size <= undo_sec->shdr.sh_size
&& (!strcmp (sec->name, ".bss")
|| !strcmp (sec->name, ".sbss"))
- && (split_bss = sec) > sections)))
+ && (sec->shdr.sh_size == undo_sec->shdr.sh_size
+ || (split_bss = sec) > sections))))
{
sec->outscn = undo_sec->outscn;
undo_sec = NULL;
--
1.7.1
9 years, 10 months
[PATCH] unstrip: Add --force to force combining files when ELF headers don't match.
by Mark Wielaard
Older versions of GNU binutils strip would drop some ELF header flags.
Causing the main ELF file and the separate .debug file to have mismatched
ELF header fields. Unfortunately some distros are still shipping such files.
eu-unstrip doesn't want to recombine such files. Add a more explicit
explanation which fields don't match and provide a --force, -F flag to
force combining such files anyway (producing a warning).
https://bugzilla.redhat.com/show_bug.cgi?id=698005
https://bugzilla.redhat.com/show_bug.cgi?id=806474
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 4 +++
NEWS | 5 ++++
src/ChangeLog | 15 +++++++++++++
src/unstrip.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------------
4 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 84dd193..b05f5bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+
+ * NEWS: New section 0.160. Add unstrip --force.
+
2014-05-17 Mark Wielaard <mjw(a)redhat.com>
* configure.ac: Set version to 0.159.
diff --git a/NEWS b/NEWS
index 8ac4631..4050200 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Version 0.160
+
+unstrip: New option -F, --force to combining files even if some ELF headers
+ don't seem to match.
+
Version 0.159
stack: New option -d, --debugname to lookup DWARF debuginfo name for frame.
diff --git a/src/ChangeLog b/src/ChangeLog
index 4197ccd..4067583 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
+2014-05-26 Mark Wielaard <mjw(a)redhat.com>
+
+ * unstrip.c (options): Add --force, -F.
+ (struct arg_info): Add bool force.
+ (parse_opt): Handle 'F', set force.
+ (handle_explicit_files): Add force argument, add warn function,
+ separate check ehdr field checks, use warn.
+ (handle_dwfl_module): Add force argument, pass on to
+ handle_explicit_files.
+ (handle_output_dir_module): Add force argument, pass on to
+ handle_dwfl_module.
+ (handle_implicit_modules): Pass info->force to handle_dwfl_module and
+ handle_output_dir_module.
+ (main): Pass info.force to handle_explicit_files.
+
2014-05-19 Mark Wielaard <mjw(a)redhat.com>
* elflint.c (check_reloc_shdr): Check ebl_check_reloc_target_type.
diff --git a/src/unstrip.c b/src/unstrip.c
index f6660a3..4738abb 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -1,5 +1,5 @@
/* Combine stripped files with separate symbols and debug information.
- Copyright (C) 2007-2012 Red Hat, Inc.
+ Copyright (C) 2007-2012, 2014 Red Hat, Inc.
This file is part of elfutils.
Written by Roland McGrath <roland(a)redhat.com>, 2007.
@@ -82,6 +82,9 @@ static const struct argp_option options[] =
N_("Apply relocations to section contents in ET_REL files"), 0 },
{ "list-only", 'n', NULL, 0,
N_("Only list module and file names, build IDs"), 0 },
+ { "force", 'F', NULL, 0,
+ N_("Force combining files even if some ELF headers don't seem to match"),
+ 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
@@ -97,6 +100,7 @@ struct arg_info
bool modnames;
bool match_files;
bool relocate;
+ bool force;
};
/* Handle program arguments. */
@@ -147,6 +151,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'R':
info->relocate = true;
break;
+ case 'F':
+ info->force = true;
+ break;
case ARGP_KEY_ARGS:
case ARGP_KEY_NO_ARGS:
@@ -1935,9 +1942,20 @@ open_file (const char *file, bool writable)
/* Handle a pair of files we need to open by name. */
static void
-handle_explicit_files (const char *output_file, bool create_dirs,
+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
+ sanity check for the stripped and unstripped files failed. */
+ void warn (const char *msg)
+ {
+ error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
+ force ? _("WARNING: ") : "",
+ stripped_file, unstripped_file, msg,
+ force ? "" : _(", use --force"));
+ }
+
int stripped_fd = open_file (stripped_file, false);
Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
GElf_Ehdr stripped_ehdr;
@@ -1956,12 +1974,23 @@ handle_explicit_files (const char *output_file, bool create_dirs,
ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
_("cannot create ELF descriptor: %s"));
- if (memcmp (stripped_ehdr.e_ident, unstripped_ehdr.e_ident, EI_NIDENT)
- || stripped_ehdr.e_type != unstripped_ehdr.e_type
- || stripped_ehdr.e_machine != unstripped_ehdr.e_machine
- || stripped_ehdr.e_phnum != unstripped_ehdr.e_phnum)
- error (EXIT_FAILURE, 0, _("'%s' and '%s' do not seem to match"),
- stripped_file, unstripped_file);
+ if (memcmp (stripped_ehdr.e_ident,
+ unstripped_ehdr.e_ident, EI_NIDENT) != 0)
+ warn (_("ELF header identification (e_ident) different"));
+
+ if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
+ warn (_("ELF header type (e_type) different"));
+
+ if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
+ warn (_("ELF header machine type (e_machine) different"));
+
+ if (stripped_ehdr.e_phnum != unstripped_ehdr.e_phnum)
+ {
+ /* Don't even try, not even with --force. */
+ error (EXIT_FAILURE, 0,
+ "'%s' and '%s' program header numbers (e_phnum) different.",
+ stripped_file, unstripped_file);
+ }
}
handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
@@ -1976,7 +2005,7 @@ handle_explicit_files (const char *output_file, bool create_dirs,
/* Handle a pair of files opened implicitly by libdwfl for one module. */
static void
-handle_dwfl_module (const char *output_file, bool create_dirs,
+handle_dwfl_module (const char *output_file, bool create_dirs, bool force,
Dwfl_Module *mod, bool all, bool ignore, bool relocate)
{
GElf_Addr bias;
@@ -2048,7 +2077,7 @@ handle_dwfl_module (const char *output_file, bool create_dirs,
(void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
&stripped_file, &unstripped_file);
- handle_explicit_files (output_file, create_dirs,
+ handle_explicit_files (output_file, create_dirs, force,
stripped_file, unstripped_file);
return;
}
@@ -2068,7 +2097,7 @@ handle_dwfl_module (const char *output_file, bool create_dirs,
/* Handle one module being written to the output directory. */
static void
-handle_output_dir_module (const char *output_dir, Dwfl_Module *mod,
+handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force,
bool all, bool ignore, bool modnames, bool relocate)
{
if (! modnames)
@@ -2089,7 +2118,7 @@ handle_output_dir_module (const char *output_dir, Dwfl_Module *mod,
if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0)
error (EXIT_FAILURE, 0, _("memory exhausted"));
- handle_dwfl_module (output_file, true, mod, all, ignore, relocate);
+ handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate);
}
@@ -2201,12 +2230,12 @@ handle_implicit_modules (const struct arg_info *info)
{
if (next (offset) != 0)
error (EXIT_FAILURE, 0, _("matched more than one module"));
- handle_dwfl_module (info->output_file, false, mmi.found,
+ handle_dwfl_module (info->output_file, false, info->force, mmi.found,
info->all, info->ignore, info->relocate);
}
else
do
- handle_output_dir_module (info->output_dir, mmi.found,
+ handle_output_dir_module (info->output_dir, mmi.found, info->force,
info->all, info->ignore,
info->modnames, info->relocate);
while ((offset = next (offset)) > 0);
@@ -2296,11 +2325,12 @@ or - if no debuginfo was found, or . if FILE contains the debug information.\
char *file;
if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0)
error (EXIT_FAILURE, 0, _("memory exhausted"));
- handle_explicit_files (file, true, info.args[0], info.args[1]);
+ handle_explicit_files (file, true, info.force,
+ info.args[0], info.args[1]);
free (file);
}
else
- handle_explicit_files (info.output_file, false,
+ handle_explicit_files (info.output_file, false, info.force,
info.args[0], info.args[1]);
}
else
--
1.7.1
9 years, 10 months