[PATCH] Fix section corruption bug
by Thilo Schulz
Hi,
When adding data to existing sections in ELF files, libelf may corrupt
those sections, i.e. overwrite the existing data if certain conditions are
met.
If an Elf_Scn structure has seen a call to elf_rawdata(scn) before but no
call to elf_getdata(scn), scn->read_data flag is set, but not
scn->data_list_rear.
Thus, elf_newdata(scn) incorrectly detects a "new user added section" when
really it is a section with live, valid data that will be overwritten by
elf_update(), corrupting the section.
This patch fixes this incorrect behaviour.
Signed-off-by: Thilo Schulz <thilo(a)tjps.eu>
---
libelf/elf_newdata.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
index 90d1813..f90eb0a 100644
--- a/libelf/elf_newdata.c
+++ b/libelf/elf_newdata.c
@@ -64,7 +64,7 @@ elf_newdata (Elf_Scn *scn)
rwlock_wrlock (scn->elf->lock);
- if (scn->data_read && scn->data_list_rear == NULL)
+ if (scn->data_read && scn->data_list_rear == NULL && !scn->rawdata.s)
{
/* This means the section was created by the user and this is the
first data. */
--
1.7.10.4
8 years, 6 months
MIPS and -msym32
by Crestez Dan Leonard
Hello,
I've been playing around with systemtap on mips.
I used the elfutils mips patch from debian:
http://sources.debian.net/src/elfutils/0.159-4/debian/patches/mips_backen...
For systemtap I ported some old patches from cisco on top of release 2.5. Here is the link to the patches on top of 1.6:
https://sourceware.org/git/gitweb.cgi?p=systemtap.git;a=log;h=refs/heads/...
One of the issues I encountered is that by default 64-bit mips kernels are compiled with -msym32. This causes gcc to emit dwarf information with a pointer size of 4, even though the file is 64bit. In theory this can be disabled by passing KBUILD_SYM32=no to the kernel make commandline. This is a bad idea. It would disable some optimizations which have been enabled on mips for many years. I actually tried to do it locally but it broke module loading and I was unable to boot.
The generated dwarf files confuse systemtap is multiple ways.
When fetching some parameters systemtap relies on address_size from dwarf_diecu to determine max_fetch_size. This caused an error like "semantic error: single register too big for fetch/store ???: identifier '$data' at ..." for an unsigned long variable.
Here is a hack I used to get around this:
--- a/libdw/dwarf_diecu.c
+++ b/libdw/dwarf_diecu.c
@@ -47,7 +47,22 @@ dwarf_diecu (die, result, address_sizep, offset_sizep)
*result = CUDIE (die->cu);
if (address_sizep != NULL)
+ {
*address_sizep = die->cu->address_size;
+ /* Hack: */
+ if (1)
+ {
+ struct Elf *elf = die->cu->dbg->elf;
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr* ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr &&
+ ehdr->e_machine == EM_MIPS &&
+ ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+ {
+ *address_sizep = 8;
+ }
+ }
+ }
if (offset_sizep != NULL)
*offset_sizep = die->cu->offset_size;
This is obviously evil. What is worse is that -msym32 seems to break systemtap address mapping. Earlier I had to do the following hack inside systemtap.
diff --git a/tapsets.cxx b/tapsets.cxx
index 4e42403..94ee230 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1265,6 +1265,22 @@ dwarf_query::add_probe_point(const string& dw_funcname,
else
{
assert (has_kernel || has_module);
+ if (1)
+ {
+ Dwarf_Addr bias;
+ Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (dw.module, &bias))
+ ?: dwfl_module_getelf (dw.module, &bias));
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+ int elf_machine = em->e_machine;
+ if (elf_machine == EM_MIPS)
+ {
+ if (sess.verbose > 1)
+ clog << "Hack reloc=" << hex << reloc_addr
+ << " from addr=" << hex << addr;
+ reloc_addr = addr - 0xc0000400;
+ }
+ }
results.push_back (new dwarf_derived_probe(funcname, filename, line,
module, reloc_section, addr, reloc_addr,
*this, scope_die));
At the time I did the hack I was unaware of -msym32, I just wanted something to work. If I compile with KBUILD_SYM32=no it seems that the above hack might no longer be necessary (the addresses "look" right). I can't actually test the generated probes because my system won't boot with KBUILD_SYM32=no.
Apparently the gcc folks decided that this -msym32 behavior was too confusing and changed it to generate dwarf with a pointer size of 8:
https://gcc.gnu.org/ml/gcc/2009-01/msg00611.html
In the future this might not matter, but my cross-compiler is based on gcc-4.3.3. I'm posting this here because maybe somebody has a better idea about how to deal with this strange flavor of dwarf.
If this could be detected and handled inside systemtap fully then maybe you could apply the patches. Elfutils seems mostly blameless to me, it's just reading the information that GCC wrote.
Regards,
Leonard
9 years, 1 month
[PATCH] aarch64: use <sys/user.h> defined register structures
by Kyle McMartin
glibc now supplies these (compatible) structs instead of including the
kernel's <asm/ptrace.h> header, so let's use them. Annoyingly this will
cause new elfutils to FTBFS on old glibc, and vice versa, but that seems
unavoidable in the growth of a new port, and the workaround of checking
for header defines and defining one to the other seems unpleasant as
well. Therefore, bite the bullet, and let packaging systems alter their
build requires accordingly.
--- a/backends/aarch64_initreg.c
+++ b/backends/aarch64_initreg.c
@@ -51,7 +51,7 @@ aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
#else /* __aarch64__ */
/* General registers. */
- struct user_pt_regs gregs;
+ struct user_regs_struct gregs;
struct iovec iovec;
iovec.iov_base = &gregs;
iovec.iov_len = sizeof (gregs);
@@ -69,7 +69,7 @@ aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
/* ELR cannot be found. */
/* FP registers (only 64bits are used). */
- struct user_fpsimd_state fregs;
+ struct user_fpsimd_struct fregs;
iovec.iov_base = &fregs;
iovec.iov_len = sizeof (fregs);
if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
diff --git a/backends/arm_initreg.c b/backends/arm_initreg.c
index 5837383..1edf62b 100644
--- a/backends/arm_initreg.c
+++ b/backends/arm_initreg.c
@@ -67,7 +67,7 @@ arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
#elif defined __aarch64__
/* Compat mode: arm compatible code running on aarch64 */
int i;
- struct user_pt_regs gregs;
+ struct user_regs_struct gregs;
struct iovec iovec;
iovec.iov_base = &gregs;
iovec.iov_len = sizeof (gregs);
9 years, 1 month
[patch] Fix report_r_debug for prelinked libraries
by Jan Kratochvil
Hi,
jankratochvil/l_addr
eu-stack: "Callback returned failure" for seemingly OK shared libraries
https://bugzilla.redhat.com/show_bug.cgi?id=1112610#c2
attaching the fix. I find it obviously right.
It also has no testsuite regressions.
The problem was that user dumping the core file had DSOs prelinked but
downloaded DSOs from RPMs are not prelinked. l_addr is then zero but it
cannot be determined from the DSO file.
Unfortunately I do not provide a testcase. It fixes the Bug above as tested
on its core file but I cannot disclose the core file (or its parts).
And despite I did try I haven't reproduced it by a hand-made testcase.
The problem is the modules placing code got overcomplicated and IMO it could
be simplified one day. There is the former placement which works somehow and
there is the placement by patches of mine which force it here and there to the
right positions. Trying to exploit failure of the add-on code of mine always
ended up on the former code placing it right on its own.
Thanks,
Jan
9 years, 2 months
[COMMITTED] m4: Handle cross-compile situations in biarch.m4 tests.
by Mark Wielaard
Reported-by: Leonard Crestez <lcrestez(a)ixiacom.com>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
m4/ChangeLog | 5 +++++
m4/biarch.m4 | 2 +-
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/m4/ChangeLog b/m4/ChangeLog
index c950e54..163ee73 100644
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * biarch.m4 (utrace_BIARCH): Set biarch-no for cross-compile using
+ AC_RUN_IFELSE extra argument.
+
2013-12-02 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* biarch.m4 (utrace_BIARCH): Call AC_MSG_WARN if !BIARCH.
diff --git a/m4/biarch.m4 b/m4/biarch.m4
index 04c8dba..c238d8d 100644
--- a/m4/biarch.m4
+++ b/m4/biarch.m4
@@ -40,7 +40,7 @@ AC_CACHE_CHECK([whether $biarch_CC makes executables we can run],
save_CC="$CC"
CC="$biarch_CC"
AC_RUN_IFELSE([AC_LANG_PROGRAM([], [])],
- utrace_cv_cc_biarch=yes, utrace_cv_cc_biarch=no)
+ utrace_cv_cc_biarch=yes, utrace_cv_cc_biarch=no, utrace_cv_cc_biarch=no)
CC="$save_CC"])], [utrace_cv_cc_biarch=no])
AS_IF([test $utrace_cv_cc_biarch != yes], [dnl
AC_MSG_WARN([not running biarch tests, $biarch_CC does not work])])])
--
1.7.1
9 years, 2 months
[PATCH] Add ppc64le ELFv2 abi support to backends and elflint.
by Mark Wielaard
The big endian vs little endian changes are already handled by detecting
the EI_DATA data encoding. And the function descriptors are already not
used when we see there is no .opd section. This change adds new checks
for st_other bits, new relocations and recognizes DT_PPC64_OPT.
Signed-off-by: Menanteau Guy <menantea(a)linux.vnet.ibm.com>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 11 +++++++++++
backends/ppc64_init.c | 1 +
backends/ppc64_reloc.def | 15 +++++++++++++++
backends/ppc64_symbol.c | 11 ++++++++++-
src/ChangeLog | 6 ++++++
src/elflint.c | 3 ++-
6 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index c590ed6..d29a80f 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,14 @@
+2014-07-04 Menanteau Guy <menantea(a)linux.vnet.ibm.com>
+ Mark Wielaard <mjw(a)redhat.com>
+
+ * ppc64_init.c (ppc64_init): Hook check_st_other_bits.
+ * ppc64_reloc.def: TLSGD, TLSLD, TOCSAVE, ADDR16_HIGH, ADDR16_HIGHA,
+ TPREL16_HIGH, TPREL16_HIGHA, DTPREL16_HIGH, DTPREL16_HIGHA, JMP_IREL,
+ IRELATIVE, REL16, REL16_LO, REL16_HI and REL16_HA.
+ * ppc64_symbol.c (ppc64_dynamic_tag_name): Recognize DT_PPC64_OPT.
+ (ppc64_dynamic_tag_check): Likewise.
+ (ppc64_check_st_other_bits): New function.
+
2014-07-04 Mark Wielaard <mjw(a)redhat.com>
* aarch64_retval.c (aarch64_return_value_location): Handle
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
index e52231c..7ea2b23 100644
--- a/backends/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -61,6 +61,7 @@ ppc64_init (elf, machine, eh, ehlen)
HOOK (eh, machine_flag_check);
HOOK (eh, copy_reloc_p);
HOOK (eh, check_special_symbol);
+ HOOK (eh, check_st_other_bits);
HOOK (eh, bss_plt_p);
HOOK (eh, return_value_location);
HOOK (eh, register_info);
diff --git a/backends/ppc64_reloc.def b/backends/ppc64_reloc.def
index 6366f46..3a693cf 100644
--- a/backends/ppc64_reloc.def
+++ b/backends/ppc64_reloc.def
@@ -132,6 +132,21 @@ RELOC_TYPE (DTPREL16_HIGHER, REL)
RELOC_TYPE (DTPREL16_HIGHERA, REL)
RELOC_TYPE (DTPREL16_HIGHEST, REL)
RELOC_TYPE (DTPREL16_HIGHESTA, REL)
+RELOC_TYPE (TLSGD, REL)
+RELOC_TYPE (TLSLD, REL)
+RELOC_TYPE (TOCSAVE, REL)
+RELOC_TYPE (ADDR16_HIGH, REL)
+RELOC_TYPE (ADDR16_HIGHA, REL)
+RELOC_TYPE (TPREL16_HIGH, REL)
+RELOC_TYPE (TPREL16_HIGHA, REL)
+RELOC_TYPE (DTPREL16_HIGH, REL)
+RELOC_TYPE (DTPREL16_HIGHA, REL)
+RELOC_TYPE (JMP_IREL, REL)
+RELOC_TYPE (IRELATIVE, REL)
+RELOC_TYPE (REL16, REL)
+RELOC_TYPE (REL16_LO, REL)
+RELOC_TYPE (REL16_HI, REL)
+RELOC_TYPE (REL16_HA, REL)
/* Notes from Alan Modra:
diff --git a/backends/ppc64_symbol.c b/backends/ppc64_symbol.c
index 212d414..5a020d8 100644
--- a/backends/ppc64_symbol.c
+++ b/backends/ppc64_symbol.c
@@ -72,6 +72,8 @@ ppc64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
return "PPC64_OPD";
case DT_PPC64_OPDSZ:
return "PPC64_OPDSZ";
+ case DT_PPC64_OPT:
+ return "PPC64_OPT";
default:
break;
}
@@ -84,7 +86,8 @@ ppc64_dynamic_tag_check (int64_t tag)
{
return (tag == DT_PPC64_GLINK
|| tag == DT_PPC64_OPD
- || tag == DT_PPC64_OPDSZ);
+ || tag == DT_PPC64_OPDSZ
+ || tag == DT_PPC64_OPT);
}
@@ -120,3 +123,9 @@ ppc64_machine_flag_check (GElf_Word flags)
{
return flags == 0 || flags == 1 || flags == 2;
}
+
+bool
+ppc64_check_st_other_bits (unsigned char st_other)
+{
+ return (PPC64_LOCAL_ENTRY_OFFSET (st_other) != 0);
+}
diff --git a/src/ChangeLog b/src/ChangeLog
index 3023423..2d6965b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-04 Menanteau Guy <menantea(a)linux.vnet.ibm.com>
+ Mark Wielaard <mjw(a)redhat.com>
+
+ * elflint (check_symtab): Add ".TOC." to the list of possibly
+ dangling symbols because of sourceware PR13621.
+
2014-06-14 Mark Wielaard <mjw(a)redhat.com>
* elflint (check_symtab): Use ebl_func_addr_mask on st_value.
diff --git a/src/elflint.c b/src/elflint.c
index 5568c65..d6a4774 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -799,7 +799,8 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
&& strcmp (name, "__fini_array_end") != 0
&& strcmp (name, "__bss_start") != 0
&& strcmp (name, "__bss_start__") != 0
- && strcmp (name, "__TMC_END__") != 0))
+ && strcmp (name, "__TMC_END__") != 0
+ && strcmp (name, ".TOC.") != 0))
ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value out of bounds\n"),
idx, section_name (ebl, idx), cnt);
--
1.7.1
9 years, 2 months
[COMMITTED] Update elf.h from glibc.
by Mark Wielaard
Includes new bits needed for ppc64le ELFv2 abi.
https://bugzilla.redhat.com/show_bug.cgi?id=1110249
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 4 ++++
libelf/elf.h | 30 +++++++++++++++++++++++++++++-
2 files changed, 33 insertions(+), 1 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index bd009cd..4bc8f56 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,7 @@
+2014-07-07 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf.h: Update from glibc.
+
2014-04-13 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am: Remove !MUDFLAP conditions.
diff --git a/libelf/elf.h b/libelf/elf.h
index a05ea3b..40e87b2 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -1,5 +1,5 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-2013 Free Software Foundation, Inc.
+ Copyright (C) 1995-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -2252,6 +2252,17 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+#define R_PPC64_TLSGD 107 /* none (sym+add)@tlsgd */
+#define R_PPC64_TLSLD 108 /* none (sym+add)@tlsld */
+#define R_PPC64_TOCSAVE 109 /* none */
+
+/* Added when HA and HI relocs were changed to report overflows. */
+#define R_PPC64_ADDR16_HIGH 110
+#define R_PPC64_ADDR16_HIGHA 111
+#define R_PPC64_TPREL16_HIGH 112
+#define R_PPC64_TPREL16_HIGHA 113
+#define R_PPC64_DTPREL16_HIGH 114
+#define R_PPC64_DTPREL16_HIGHA 115
/* GNU extension to support local ifunc. */
#define R_PPC64_JMP_IREL 247
@@ -2261,12 +2272,29 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */
#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */
+/* e_flags bits specifying ABI.
+ 1 for original function descriptor using ABI,
+ 2 for revised ABI without function descriptors,
+ 0 for unspecified or not using any features affected by the differences. */
+#define EF_PPC64_ABI 3
+
/* PowerPC64 specific values for the Dyn d_tag field. */
#define DT_PPC64_GLINK (DT_LOPROC + 0)
#define DT_PPC64_OPD (DT_LOPROC + 1)
#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_OPT (DT_LOPROC + 3)
#define DT_PPC64_NUM 3
+/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */
+#define PPC64_OPT_TLS 1
+#define PPC64_OPT_MULTI_TOC 2
+
+/* PowerPC64 specific values for the Elf64_Sym st_other field. */
+#define STO_PPC64_LOCAL_BIT 5
+#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
+#define PPC64_LOCAL_ENTRY_OFFSET(other) \
+ (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
+
/* ARM specific declarations */
--
1.7.1
9 years, 2 months
[COMMITTED] backends: aarch64_return_value_location should handle DW_ATE_boolean.
by Mark Wielaard
Found with run-native-test.sh om debian arm64.
http://bugs.debian.org/753552
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 5 +++++
backends/aarch64_retval.c | 1 +
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index a2df83b..c590ed6 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-04 Mark Wielaard <mjw(a)redhat.com>
+
+ * aarch64_retval.c (aarch64_return_value_location): Handle
+ DW_ATE_boolean.
+
2014-06-18 Mark Wielaard <mjw(a)redhat.com>
* libebl_CPU.h (dwarf_peel_type): Remove DW_TAG_mutable_type
diff --git a/backends/aarch64_retval.c b/backends/aarch64_retval.c
index 0ed7d56..68de307 100644
--- a/backends/aarch64_retval.c
+++ b/backends/aarch64_retval.c
@@ -357,6 +357,7 @@ aarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
size of the argument is less than or equal to 8 bytes
[...] the argument is copied to the least significant
bits in x[NGRN]. */
+ case DW_ATE_boolean:
case DW_ATE_signed:
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
--
1.7.1
9 years, 2 months