run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
run-find-prologues.sh run-allregs.sh run-addrcfi.sh \
run-nm-self.sh run-readelf-self.sh \
+ run-varlocs-self.sh run-exprlocs-self.sh \
run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
run-readelf-test4.sh run-readelf-twofiles.sh \
run-readelf-macro.sh run-readelf-loc.sh \
run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
run-nm-self.sh run-readelf-self.sh run-addrcfi.sh \
+ run-varlocs-self.sh run-exprlocs-self.sh \
run-find-prologues.sh run-allregs.sh run-native-test.sh \
run-addrname-test.sh run-dwfl-bug-offline-rel.sh \
run-dwfl-addr-sect.sh run-early-offscn.sh \
--- /dev/null
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Just makes sure exprlocs doesn't crash, triggers self-check/asserts
+# or leaks memory under valgrind.
+testrun_on_self_quiet ${abs_top_builddir}/tests/varlocs --exprlocs -e
--- /dev/null
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Make sure varlocs doesn't crash, doesn't trigger self-check/asserts
+# or leaks running under valgrind.
+testrun_on_self_quiet ${abs_top_builddir}/tests/varlocs -e
// Needed for DW_OP_call_frame_cfa.
static Dwarf *dw;
Dwarf_CFI *cfi_debug;
+Dwarf_Addr cfi_debug_bias;
Dwarf_CFI *cfi_eh;
Dwarf_Addr cfi_eh_bias;
+bool is_ET_REL;
+
// Whether the current function has a DW_AT_frame_base defined.
// Needed for DW_OP_fbreg.
bool has_frame_base;
error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
Dwarf_Frame *frame;
- if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) != 0
- && dwarf_cfi_addrframe (cfi_debug, addr, &frame) != 0)
+ if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) == 0
+ || dwarf_cfi_addrframe (cfi_debug, addr + cfi_debug_bias,
+ &frame) == 0)
+ {
+ Dwarf_Op *cfa_ops;
+ size_t cfa_nops;
+ if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
+ addr, dwarf_errmsg (-1));
+ if (cfa_nops < 1)
+ error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
+ print_expr_block (NULL, cfa_ops, cfa_nops, 0);
+ free (frame);
+ }
+ else if (is_ET_REL)
+ {
+ /* XXX In ET_REL files there might be an .eh_frame with relocations
+ we don't handle (e.g. X86_64_PC32). Maybe we should? */
+ printf ("{...}\n");
+ }
+ else
error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
addr, dwarf_errmsg (-1));
-
- Dwarf_Op *cfa_ops;
- size_t cfa_nops;
- if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
- error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
- addr, dwarf_errmsg (-1));
- if (cfa_nops < 1)
- error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
- print_expr_block (NULL, cfa_ops, cfa_nops, 0);
- free (frame);
break;
case DW_OP_push_object_address:
on address. */
Dwarf_Addr die_entrypc;
if (dwarf_entrypc (die, &die_entrypc) != 0 || die_entrypc == 0)
- die_entrypc = outer_entrypc;
+ {
+ /* Try to get the lowest address of the first range covered. */
+ Dwarf_Addr base, start, end;
+ if (dwarf_ranges (die, 0, &base, &start, &end) <= 0 || start == 0)
+ die_entrypc = outer_entrypc;
+ else
+ die_entrypc = start;
+ }
arg.entrypc = die_entrypc;
/* Whether this or the any outer DIE has a frame base. Used as
Dwarf_Die *cu = NULL;
Dwarf_Addr dwbias;
+ bool found_cu = false;
while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
{
/* Only walk actual compile units (not partial units) that
if (dwarf_tag (cu) == DW_TAG_compile_unit
&& (exprlocs || dwarf_lowpc (cu, &cubase) == 0))
{
+ found_cu = true;
+
Dwfl_Module *mod = dwfl_cumodule (cu);
Dwarf_Addr modbias;
dw = dwfl_module_getdwarf (mod, &modbias);
Elf *elf = dwfl_module_getelf (mod, &elfbias);
// CFI. We need both since sometimes neither is complete.
- cfi_debug = dwarf_getcfi (dw); // No bias needed, same file.
- cfi_eh = dwarf_getcfi_elf (elf);
- cfi_eh_bias = dwbias - elfbias;
+ cfi_debug = dwfl_module_dwarf_cfi (mod, &cfi_debug_bias);
+ cfi_eh = dwfl_module_eh_cfi (mod, &cfi_eh_bias);
+
+ assert (cfi_debug == 0); // No bias needed, same file.
+
+ // We are a bit forgiving for object files. There might be
+ // relocations we don't handle that are needed in some
+ // places...
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ is_ET_REL = ehdr->e_type == ET_REL;
// Get the actual CU DIE and walk all all DIEs (or just the
// functions) inside it.
}
}
+ if (! found_cu)
+ error (EXIT_FAILURE, 0, "No DWARF CU found?");
+
dwfl_end (dwfl);
return 0;
}