[PATCH] readelf: DW_CFA_set_loc operand is an address
by Ben Gamari
Previously this was incorrectly assumed to be an ULEB128. Hilarity
ensued.
This appears to be the case in both DWARF 3, DWARF 4, and LSB 5.
Also show set_loc argument as hexadecimal
Finally, add a test for this behavior. This was derived from the
following testsuite extract from output from the Glasgow Haskell
Compiler,
.section .text
_c2JJ:
nop
_c2JP:
nop
_c2K0:
nop
_c2KN:
nop
_c2KZ:
nop
_c2L3:
nop
.La2_r2HX_info_end:
nop
a2_r2HX_info:
nop
.LMain.ffiTest_info_end:
nop
Main.ffiTest_info:
nop
.Lsat_s2Ip_info_end:
nop
sat_s2Ip_info:
nop
.section .debug_frame,"",@progbits
.Lsection_frame:
_n2PT:
.long .Ln2PT_end-.Ln2PT_start
.Ln2PT_start:
.long -1
.byte 3
.asciz "S"
.byte 1
.byte 120
.byte 16
.byte 12
.byte 6
.byte 0
.byte 144
.byte 0
.byte 8
.byte 7
.byte 20
.byte 6
.byte 0
.align 8
.Ln2PT_end:
.long .La2_r2HX_info_fde_end-.La2_r2HX_info_fde
.La2_r2HX_info_fde:
.long _n2PT
.quad a2_r2HX_info-1
.quad .La2_r2HX_info_end-a2_r2HX_info+1
.byte 1
.quad _c2JJ
.byte 14
.byte 16
.byte 1
.quad _c2JP
.byte 14
.byte 0
.byte 1
.quad _c2K0-1
.byte 14
.byte 8
.align 8
.La2_r2HX_info_fde_end:
.long .LMain.ffiTest_info_fde_end-.LMain.ffiTest_info_fde
.LMain.ffiTest_info_fde:
.long _n2PT
.quad Main.ffiTest_info-1
.quad .LMain.ffiTest_info_end-Main.ffiTest_info+1
.align 8
.LMain.ffiTest_info_fde_end:
.long .Lsat_s2Ip_info_fde_end-.Lsat_s2Ip_info_fde
.Lsat_s2Ip_info_fde:
.long _n2PT
.quad sat_s2Ip_info-1
.quad .Lsat_s2Ip_info_end-sat_s2Ip_info+1
.byte 1
.quad _c2KN
.byte 14
.byte 8
.byte 1
.quad _c2KZ
.byte 14
.byte 0
.byte 1
.quad _c2L3
.byte 14
.byte 8
.align 8
.Lsat_s2Ip_info_fde_end:
Update styule
---
libdwfl/frame_unwind.c | 40 +++++++++++++++++----
src/readelf.c | 4 +--
tests/Makefile.am | 3 +-
tests/run-readelf-test5.sh | 88 +++++++++++++++++++++++++++++++++++++++++++++
tests/testfile72 | Bin 0 -> 2640 bytes
5 files changed, 126 insertions(+), 9 deletions(-)
create mode 100755 tests/run-readelf-test5.sh
create mode 100644 tests/testfile72
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 39509b7..365da48 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -559,8 +559,24 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
bool ra_set = false;
ebl_dwarf_to_regno (ebl, &ra);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Unwinding from %lx:\n", pc);
+ char *modname = "null";
+ if (cfi->dbg) modname = elf_getident(cfi->dbg->elf, NULL);
+ fprintf(stderr, " mod = %s\n", modname ? modname : "null");
+ fprintf(stderr, " CIE offset = %lx\n", frame->fde->cie->offset);
+ if (frame->fde->cie->signal_frame)
+ fprintf(stderr, " signal frame\n");
+
for (unsigned regno = 0; regno < nregs; regno++)
{
+ char regname[10];
+ {
+ const char *prefix, *setname;
+ int bits, type;
+ ebl_register_info(ebl, regno, regname, 10, &prefix, &setname, &bits, &type);
+ }
+
Dwarf_Op reg_ops_mem[3], *reg_ops;
size_t reg_nops;
if (dwarf_frame_register (frame, regno, reg_ops_mem, ®_ops,
@@ -568,22 +584,26 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
{
__libdwfl_seterrno (DWFL_E_LIBDW);
continue;
- }
+ }
Dwarf_Addr regval;
if (reg_nops == 0)
{
if (reg_ops == reg_ops_mem)
{
/* REGNO is undefined. */
- if (regno == ra)
- unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+ if (regno == ra) {
+ fprintf(stderr, " reg %d = undefined\n", regno);
+ unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+ }
continue;
}
else if (reg_ops == NULL)
{
/* REGNO is same-value. */
- if (! state_get_reg (state, regno, ®val))
- continue;
+ if (! state_get_reg (state, regno, ®val)) {
+ fprintf(stderr, " reg %d = same = %lx\n", regno, regval);
+ continue;
+ }
}
else
{
@@ -597,7 +617,15 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
register will look as unset causing an error later, if used.
But PPC32 does not use such registers. */
continue;
- }
+ }
+
+ if (reg_nops > 0) {
+ fprintf(stderr, " reg %s = ", regname);
+ for (unsigned i = 0; i < reg_nops; i++) {
+ fprintf(stderr, "i ");
+ }
+ fprintf(stderr, " = %lx\n", regval);
+ }
/* Some architectures encode some extra info in the return address. */
if (regno == frame->fde->cie->return_address_register)
diff --git a/src/readelf.c b/src/readelf.c
index 5f6e4ed..224ed88 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4971,9 +4971,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
case DW_CFA_set_loc:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
- get_uleb128 (op1, readp, endp);
+ op1 = read_addr_unaligned_inc (ptr_size, dbg, readp);
op1 += vma_base;
- printf (" set_loc %" PRIu64 "\n", op1 * code_align);
+ printf (" set_loc %#" PRIx64 "\n", op1 * code_align);
break;
case DW_CFA_advance_loc1:
if ((uint64_t) (endp - readp) < 1)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 30cf137..8d5df71 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -88,7 +88,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-find-prologues.sh run-allregs.sh run-addrcfi.sh \
run-nm-self.sh run-readelf-self.sh \
run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
- run-readelf-test4.sh run-readelf-twofiles.sh \
+ run-readelf-test4.sh run-readelf-test5.sh \
+ run-readelf-twofiles.sh \
run-readelf-macro.sh run-readelf-loc.sh \
run-readelf-aranges.sh run-readelf-line.sh \
run-native-test.sh run-bug1-test.sh \
diff --git a/tests/run-readelf-test5.sh b/tests/run-readelf-test5.sh
new file mode 100755
index 0000000..b6ca830
--- /dev/null
+++ b/tests/run-readelf-test5.sh
@@ -0,0 +1,88 @@
+#! /bin/sh
+# Copyright (C) 2007 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
+
+testfiles testfile72
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=frames testfile72 <<\EOF
+
+DWARF section [ 4] '.debug_frame' at offset 0x50:
+
+ [ 0] CIE length=20
+ CIE_id: 18446744073709551615
+ version: 3
+ augmentation: "S"
+ code_alignment_factor: 1
+ data_alignment_factor: -8
+ return_address_register: 16
+
+ Program:
+ def_cfa r6 (rbp) at offset 0
+ offset r16 (rip) at cfa+0
+ same_value r7 (rsp)
+ val_offset 6 at offset 0
+
+ [ 18] FDE length=60 cie=[ 0]
+ CIE_pointer: 0
+ initial_location: .text+0x0000000000000006 <_c2L3+0x1>
+ address_range: 0
+
+ Program:
+ set_loc 0
+ def_cfa_offset 16
+ set_loc 0x1
+ def_cfa_offset 0
+ set_loc 0x1
+ def_cfa_offset 8
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ [ 58] FDE length=20 cie=[ 0]
+ CIE_pointer: 0
+ initial_location: .text+0x0000000000000008 <a2_r2HX_info+0x1>
+ address_range: 0
+
+ Program:
+
+ [ 70] FDE length=60 cie=[ 0]
+ CIE_pointer: 0
+ initial_location: .text+0x000000000000000a <Main.ffiTest_info+0x1>
+ address_range: 0
+
+ Program:
+ set_loc 0x3
+ def_cfa_offset 8
+ set_loc 0x4
+ def_cfa_offset 0
+ set_loc 0x5
+ def_cfa_offset 8
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+EOF
+
+exit 0
diff --git a/tests/testfile72 b/tests/testfile72
new file mode 100644
index 0000000000000000000000000000000000000000..02c3c4da544c88dc8d79d348c7801ce3ffa1a4b6
GIT binary patch
literal 2640
zcmbW3&rcIk5XWb`T8cs~!a;+H)r9DQY+;QzB_;kq5U>$Uh%qT!*+P?2NOv*yr17K|
z!@;{(kNgQ9{WJVOJm}1OGy7vGn)pcHoA-G$^L>5ucFVg*tB(tg1JWE=fOIAlpixZi
zx-siefpIv_G{RH(`Hjup0B2AcE5b39My85z&%~VW60LG2HPaoGOB_OZhqZs_E&Vm`
zeN0+_Y3v>6S9u(Ja~K%oz+T6TtmbGzw5M*St>B>hvPnS8sgO9+Xp+<p4&z!lIIM-;
z_EFsFMzuJM;s}=3UsM-2s=nvn_2$8O?@U0YIN@A&+|qPurZjmzo5|R-*xSv>$yk@M
zQ=SaG=<R+Sw7`qvz8&|(io-z+-cAq);I*O%ynfgXyq&OhwA*a=gZ(f^x}9Dgbb9Rr
z3^(pUtJM$R<ottv(Ay390MFW;;ci;*oS)0zGzW3w;-7A|$VsV_<q>0Hp%P+^app;3
zd3}<(R=CRi9Q(;|ow=^m40Ee5-T*%H(G(f$A@hrh)6@m63h><co#xg*e>aS)$#X%>
z+~`8);m)kMFl0B)*Z#^1P~V{b>741;P5+Ym)jJUQ&A$I+t7&e?TF~iv?RIAqZ@eW@
z5H}-#`OwaqJ-@LD*I1W!Xlr9Zl{wXqKC;t!#d(^%XT)FXzNGwxzhbU+x0Sz~XncnM
zK>5o_e^OlT)fdI3l3x{<dv#lJo+jr(dKG~<%KL!$M23rxoR2JBVMDmY%Xw3tOX7^<
zS$Q%p|7DstF-D56B&o9@`w}j7l=%%bh{-t%Ull`*I{p@}Q?36up6;d2Ns<lfu$|Z;
z>E&Jtm_>u`LR|olANhh*Ie8g5A&HmzJwP^0U*IC=lR^6~;KDHdZ+sC&hxDmNT7MIn
z&WQ*X8LrVJ)3on1TpOnUo%Odlmh?$m>(jc<i3mP3)c;3lU;4e$jN(ri&e0^(<T()3
zLu1(ft9+p)p7u{~SG|9FR`uOO1V35-15Gkb@0I5IH;vr)82;b@dY0+8PV3X}(lGrw
N`cl}o?2z<Y{|`Qng6#kR
literal 0
HcmV?d00001
--
2.6.2
8 years, 5 months
[PATCH] libdw: Make sure Ebl is always freed from cfi frame cache.
by Mark Wielaard
libdwfl sets the Dwfl_Module Ebl for the eh_cfi and dwarf_cfi cache to
save a bit of memory. It also calls ebl_closebackend on the ebl to free
it. The Dwarf_CFI never frees the Ebl in the cache, even when it opened
one itself. This means that if only libdw calls are used to access the
Dwarf_CFI the Ebl might be leaked.
Always destroy the Dwarf_CFI cache Ebl in __libdw_destroy_frame_cache.
And in __libdwfl_module_free clear the Dwarf_CFI Ebl if it is the
Dwfl_Module Ebl before calling dwarf_cfi_end and dwarf_end.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/frame-cache.c | 6 +++++-
libdwfl/ChangeLog | 6 ++++++
libdwfl/dwfl_module.c | 23 +++++++++++++++++++----
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 5218145..4d02449 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-19 Mark Wielaard <mjw(a)redhat.com>
+
+ * frame-cache.c (__libdw_destroy_frame_cache): Call ebl_closebackend
+ if necessary.
+
2015-10-16 Dmitry V. Levin <ldv(a)altlinux.org>
* dwarf_getsrclines.c (read_srclines): Initialize state early.
diff --git a/libdw/frame-cache.c b/libdw/frame-cache.c
index 54a1cc9..5b6afb5 100644
--- a/libdw/frame-cache.c
+++ b/libdw/frame-cache.c
@@ -1,5 +1,5 @@
/* Frame cache handling.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
# include <config.h>
#endif
+#include "../libebl/libebl.h"
#include "cfi.h"
#include <search.h>
#include <stdlib.h>
@@ -63,4 +64,7 @@ __libdw_destroy_frame_cache (Dwarf_CFI *cache)
tdestroy (cache->fde_tree, free_fde);
tdestroy (cache->cie_tree, free_cie);
tdestroy (cache->expr_tree, free_expr);
+
+ if (cache->ebl != NULL && cache->ebl != (void *) -1l)
+ ebl_closebackend (cache->ebl);
}
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..3c48b5e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-19 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_module.c (__libdwfl_module_free): Remove Dwfl_Module Ebl from
+ eh_cfi and dwarf_cfi cache if necessary before calling dwarf_end and
+ dwarf_cfi_end.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
index 76d45a8..515092f 100644
--- a/libdwfl/dwfl_module.c
+++ b/libdwfl/dwfl_module.c
@@ -1,5 +1,5 @@
/* Maintenance of module list in libdwfl.
- Copyright (C) 2005, 2006, 2007, 2008, 2014 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include "../libdw/cfi.h"
#include <search.h>
#include <unistd.h>
@@ -70,6 +71,23 @@ __libdwfl_module_free (Dwfl_Module *mod)
free (mod->cu);
}
+ /* We might have primed the Dwarf_CFI ebl cache with our own ebl
+ in __libdwfl_set_cfi. Make sure we don't free it twice. */
+ if (mod->eh_cfi != NULL)
+ {
+ if (mod->eh_cfi->ebl != NULL && mod->eh_cfi->ebl == mod->ebl)
+ mod->eh_cfi->ebl = NULL;
+ dwarf_cfi_end (mod->eh_cfi);
+ }
+
+ if (mod->dwarf_cfi != NULL)
+ {
+ if (mod->dwarf_cfi->ebl != NULL && mod->dwarf_cfi->ebl == mod->ebl)
+ mod->dwarf_cfi->ebl = NULL;
+ /* We don't need to explicitly destroy the dwarf_cfi.
+ That will be done by dwarf_end. */
+ }
+
if (mod->dw != NULL)
{
INTUSE(dwarf_end) (mod->dw);
@@ -97,9 +115,6 @@ __libdwfl_module_free (Dwfl_Module *mod)
if (mod->reloc_info != NULL)
free (mod->reloc_info);
- if (mod->eh_cfi != NULL)
- dwarf_cfi_end (mod->eh_cfi);
-
free (mod->name);
free (mod);
}
--
1.8.3.1
8 years, 5 months
ELF compressed section support in libelf
by Mark Wielaard
Hi,
Here is another update of the libelf compressed section support.
We decided to bring back [g]elf[32|64]_getchdr and make it so
that compressed Elf_Data has a new Elf_Type ELF_T_CHDR. This makes
some things a little easier/natural. In particular the xlate functions
will now do the right thing with the Chdr at the start of such section
data. Also added is support for elf_strptr to index into compressed
sections (indexes always should be against the uncompressed data).
There are still two XXXs in the code. One for incorrectly marking
the result of the Shdr update by elf_compress dirty. And one to make
sure elf_newdata does the right thing.
There is still some discussion on the final API. But it seems this is
very close to the final version. elf_compress might get a flag argument
and some arguments might turn into unsigned ints.
Comments on the implementations more than welcome. Comments on the
interface should be directed to the Generic System V Application Binary
Interface mailinglist generic-abi(a)googlegroups.com
https://groups.google.com/forum/#!forum/generic-abi
Thanks,
Mark
8 years, 5 months
[PATCH] Move nested functions in elf-from-memory.c to file scope.
by Chih-Hung Hsieh
* Move nested function 'handle_segment' to the file scope
to compile with clang.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 6 ++
libdwfl/elf-from-memory.c | 248 +++++++++++++++++++++++++++-------------------
2 files changed, 150 insertions(+), 104 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..6e89cc0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-18 Chih-Hung Hsieh <chh(a)google.com>
+
+ * elf-from-memory.c (elf_from_remote_memory): Move nested functions
+ 'handle_segment' to the file scope as 'do_check_segment' and
+ 'do_read_segment'.
+
2015-11-13 Chih-Hung Hsieh <chh(a)google.com>
* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index dd42e95..1f00ce9 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -38,6 +38,79 @@
#include <stdlib.h>
#include <string.h>
+typedef ssize_t (*ptr_read_memory_func) (void *arg, void *data,
+ GElf_Addr address,
+ size_t minread,
+ size_t maxread);
+
+struct check_read_segment_state {
+ GElf_Addr ehdr_vma;
+ GElf_Xword pagesize;
+ GElf_Off segments_end;
+ GElf_Off segments_end_mem;
+ size_t contents_size;
+ bool found_base;
+ GElf_Addr loadbase;
+ void *arg;
+ unsigned char *buffer;
+ ssize_t nread;
+ ptr_read_memory_func read_memory;
+};
+
+/* 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. */
+static inline bool
+do_check_segment (struct check_read_segment_state *state,
+ GElf_Addr vaddr, GElf_Off offset,
+ GElf_Xword filesz, GElf_Xword memsz)
+{
+ /* Sanity check the segment load aligns with the pagesize. */
+ if (((vaddr - offset) & (state->pagesize - 1)) != 0)
+ return true;
+
+ GElf_Off segment_end = ((offset + filesz + state->pagesize - 1)
+ & - state->pagesize);
+
+ if (segment_end > (GElf_Off) state->contents_size)
+ state->contents_size = segment_end;
+
+ if (!state->found_base && (offset & - state->pagesize) == 0)
+ {
+ state->loadbase = state->ehdr_vma - (vaddr & - state->pagesize);
+ state->found_base = true;
+ }
+
+ state->segments_end = offset + filesz;
+ state->segments_end_mem = offset + memsz;
+ return false;
+}
+
+#define check_segment(vaddr, offset, filesz, memsz) \
+ do_check_segment (&state, vaddr, offset, filesz, memsz)
+
+/* Reads the given segment. Returns true if reading fails,
+ false otherwise. */
+static inline bool
+do_read_segment (struct check_read_segment_state *state,
+ GElf_Addr vaddr, GElf_Off offset,
+ GElf_Xword filesz)
+{
+ GElf_Off start = offset & - state->pagesize;
+ GElf_Off end = (offset + filesz + state->pagesize - 1) & - state->pagesize;
+ if (end > (GElf_Off) state->contents_size)
+ end = state->contents_size;
+ state->nread = (*state->read_memory) (
+ state->arg, state->buffer + start,
+ (state->loadbase + vaddr) & - state->pagesize,
+ end - start, end - start);
+ return state->nread <= 0;
+}
+
+#define read_segment(vaddr, offset, filesz) \
+ do_read_segment (&state, vaddr, offset, filesz)
+
/* 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
@@ -54,15 +127,27 @@
segments. */
Elf *
-elf_from_remote_memory (GElf_Addr ehdr_vma,
- GElf_Xword pagesize,
+elf_from_remote_memory (GElf_Addr _ehdr_vma,
+ GElf_Xword _pagesize,
GElf_Addr *loadbasep,
- ssize_t (*read_memory) (void *arg, void *data,
- GElf_Addr address,
- size_t minread,
- size_t maxread),
- void *arg)
+ ptr_read_memory_func _read_memory,
+ void *_arg)
{
+ struct check_read_segment_state state =
+ {
+ .ehdr_vma = _ehdr_vma,
+ .pagesize = _pagesize,
+ .segments_end = 0,
+ .segments_end_mem = 0,
+ .contents_size = 0,
+ .found_base = false,
+ .loadbase = _ehdr_vma,
+ .arg = _arg,
+ .buffer = NULL,
+ .nread = 0,
+ .read_memory = _read_memory
+ };
+
/* We might have to reserve some memory for the phdrs. Set to NULL
here so we can always safely free it. */
void *phdrsp = NULL;
@@ -70,29 +155,29 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
/* First read in the file header and check its sanity. */
const size_t initial_bufsize = 256;
- unsigned char *buffer = malloc (initial_bufsize);
- if (unlikely (buffer == NULL))
+ state.buffer = malloc (initial_bufsize);
+ if (unlikely (state.buffer == NULL))
{
no_memory:
__libdwfl_seterrno (DWFL_E_NOMEM);
return NULL;
}
- ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
- sizeof (Elf32_Ehdr), initial_bufsize);
- if (nread <= 0)
+ state.nread = (*state.read_memory) (state.arg, state.buffer, state.ehdr_vma,
+ sizeof (Elf32_Ehdr), initial_bufsize);
+ if (state.nread <= 0)
{
read_error:
- free (buffer);
+ free (state.buffer);
free (phdrsp);
- __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
+ __libdwfl_seterrno (state.nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
return NULL;
}
- if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
+ if (memcmp (state.buffer, ELFMAG, SELFMAG) != 0)
{
bad_elf:
- free (buffer);
+ free (state.buffer);
free (phdrsp);
__libdwfl_seterrno (DWFL_E_BADELF);
return NULL;
@@ -108,7 +193,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
Elf_Data xlatefrom =
{
.d_type = ELF_T_EHDR,
- .d_buf = buffer,
+ .d_buf = state.buffer,
.d_version = EV_CURRENT,
};
Elf_Data xlateto =
@@ -124,11 +209,11 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
uint_fast16_t phentsize;
GElf_Off shdrs_end;
- switch (buffer[EI_CLASS])
+ switch (state.buffer[EI_CLASS])
{
case ELFCLASS32:
xlatefrom.d_size = sizeof (Elf32_Ehdr);
- if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+ if (elf32_xlatetom (&xlateto, &xlatefrom, state.buffer[EI_DATA]) == NULL)
{
libelf_error:
__libdwfl_seterrno (DWFL_E_LIBELF);
@@ -144,7 +229,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
case ELFCLASS64:
xlatefrom.d_size = sizeof (Elf64_Ehdr);
- if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+ if (elf64_xlatetom (&xlateto, &xlatefrom, state.buffer[EI_DATA]) == NULL)
goto libelf_error;
phoff = ehdr.e64.e_phoff;
phnum = ehdr.e64.e_phnum;
@@ -165,44 +250,46 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
xlatefrom.d_size = phnum * phentsize;
- if ((size_t) nread >= phoff + phnum * phentsize)
+ if ((size_t) state.nread >= phoff + phnum * phentsize)
/* We already have all the phdrs from the initial read. */
- xlatefrom.d_buf = buffer + phoff;
+ xlatefrom.d_buf = state.buffer + phoff;
else
{
/* Read in the program headers. */
if (initial_bufsize < phnum * phentsize)
{
- unsigned char *newbuf = realloc (buffer, phnum * phentsize);
+ unsigned char *newbuf = realloc (state.buffer, phnum * phentsize);
if (newbuf == NULL)
{
- free (buffer);
+ free (state.buffer);
free (phdrsp);
goto no_memory;
}
- buffer = newbuf;
+ state.buffer = newbuf;
}
- nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
- phnum * phentsize, phnum * phentsize);
- if (nread <= 0)
+ state.nread = (*state.read_memory) (state.arg, state.buffer,
+ state.ehdr_vma + phoff,
+ phnum * phentsize,
+ phnum * phentsize);
+ if (state.nread <= 0)
goto read_error;
- xlatefrom.d_buf = buffer;
+ xlatefrom.d_buf = state.buffer;
}
bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
if (unlikely (phnum > SIZE_MAX / phdr_size))
{
- free (buffer);
+ free (state.buffer);
goto no_memory;
}
const size_t phdrsp_bytes = phnum * phdr_size;
phdrsp = malloc (phdrsp_bytes);
if (unlikely (phdrsp == NULL))
{
- free (buffer);
+ free (state.buffer);
goto no_memory;
}
@@ -210,51 +297,19 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
xlateto.d_size = phdrsp_bytes;
/* Scan for PT_LOAD segments to find the total size of the file image. */
- size_t contents_size = 0;
- GElf_Off segments_end = 0;
- GElf_Off segments_end_mem = 0;
- GElf_Addr loadbase = ehdr_vma;
- bool found_base = false;
Elf32_Phdr (*p32)[phnum] = phdrsp;
Elf64_Phdr (*p64)[phnum] = phdrsp;
+ state.loadbase = state.ehdr_vma;
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 (check_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz, (*p32)[i].p_memsz))
goto bad_elf;
break;
@@ -264,8 +319,8 @@ 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 (check_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz, (*p64)[i].p_memsz))
goto bad_elf;
break;
@@ -278,22 +333,22 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
that are off the end of the file. However, if the extra bit in that
page includes the section headers and the memory isn't extended (which
might indicate it will have been reused otherwise), keep them. */
- if ((GElf_Off) contents_size > segments_end
- && (GElf_Off) contents_size >= shdrs_end
- && segments_end == segments_end_mem)
+ if ((GElf_Off) state.contents_size > state.segments_end
+ && (GElf_Off) state.contents_size >= shdrs_end
+ && state.segments_end == state.segments_end_mem)
{
- contents_size = segments_end;
- if ((GElf_Off) contents_size < shdrs_end)
- contents_size = shdrs_end;
+ state.contents_size = state.segments_end;
+ if ((GElf_Off) state.contents_size < shdrs_end)
+ state.contents_size = shdrs_end;
}
else
- contents_size = segments_end;
+ state.contents_size = state.segments_end;
- free (buffer);
+ free (state.buffer);
/* Now we know the size of the whole image we want read in. */
- buffer = calloc (1, contents_size);
- if (buffer == NULL)
+ state.buffer = calloc (1, state.contents_size);
+ if (state.buffer == NULL)
{
free (phdrsp);
goto no_memory;
@@ -301,31 +356,16 @@ 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 (read_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz))
goto read_error;
/* If the segments visible in memory didn't include the section
headers, then clear them from the file header. */
- if (contents_size < shdrs_end)
+ if (state.contents_size < shdrs_end)
{
ehdr.e32.e_shoff = 0;
ehdr.e32.e_shnum = 0;
@@ -337,7 +377,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
xlatefrom.d_buf = &ehdr.e32;
- xlateto.d_buf = buffer;
+ xlateto.d_buf = state.buffer;
if (elf32_xlatetof (&xlateto, &xlatefrom,
ehdr.e32.e_ident[EI_DATA]) == NULL)
goto libelf_error;
@@ -346,13 +386,13 @@ 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 (read_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz))
goto read_error;
/* If the segments visible in memory didn't include the section
headers, then clear them from the file header. */
- if (contents_size < shdrs_end)
+ if (state.contents_size < shdrs_end)
{
ehdr.e64.e_shoff = 0;
ehdr.e64.e_shnum = 0;
@@ -364,7 +404,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
xlatefrom.d_buf = &ehdr.e64;
- xlateto.d_buf = buffer;
+ xlateto.d_buf = state.buffer;
if (elf64_xlatetof (&xlateto, &xlatefrom,
ehdr.e64.e_ident[EI_DATA]) == NULL)
goto libelf_error;
@@ -380,15 +420,15 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
/* Now we have the image. Open libelf on it. */
- Elf *elf = elf_memory ((char *) buffer, contents_size);
+ Elf *elf = elf_memory ((char *) state.buffer, state.contents_size);
if (elf == NULL)
{
- free (buffer);
+ free (state.buffer);
goto libelf_error;
}
elf->flags |= ELF_F_MALLOCED;
if (loadbasep != NULL)
- *loadbasep = loadbase;
+ *loadbasep = state.loadbase;
return elf;
}
--
2.6.0.rc2.230.g3dd15c0
8 years, 5 months
[PATCH] libdw: initialize state early in read_srclines
by Dmitry V. Levin
Starting with commit f8443bd09f8a8d3d84a63e5ce206a218e57dff7a,
we might jump to "out" on error before initialization of "state".
Initialize "state" early to fix this issue.
Signed-off-by: Dmitry V. Levin <ldv(a)altlinux.org>
---
libdw/dwarf_getsrclines.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 03bdc8f..dd1b3c1 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -185,6 +185,25 @@ read_srclines (Dwarf *dbg,
struct dirlist dirstack[MAX_STACK_DIRS];
struct dirlist *dirarray = dirstack;
+ /* We are about to process the statement program. Initialize the
+ state machine registers (see 6.2.2 in the v2.1 specification). */
+ struct line_state state =
+ {
+ .linelist = NULL,
+ .nlinelist = 0,
+ .addr = 0,
+ .op_index = 0,
+ .file = 1,
+ /* We only store int but want to check for overflow (see SET above). */
+ .line = 1,
+ .column = 0,
+ .basic_block = false,
+ .prologue_end = false,
+ .epilogue_begin = false,
+ .isa = 0,
+ .discriminator = 0
+ };
+
if (unlikely (linep + 4 > lineendp))
{
invalid_data:
@@ -387,25 +406,7 @@ read_srclines (Dwarf *dbg,
goto out;
}
- /* We are about to process the statement program. Initialize the
- state machine registers (see 6.2.2 in the v2.1 specification). */
- struct line_state state =
- {
- .linelist = NULL,
- .nlinelist = 0,
- .addr = 0,
- .op_index = 0,
- .file = 1,
- /* We only store int but want to check for overflow (see SET above). */
- .line = 1,
- .column = 0,
- .is_stmt = default_is_stmt,
- .basic_block = false,
- .prologue_end = false,
- .epilogue_begin = false,
- .isa = 0,
- .discriminator = 0
- };
+ state.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). */
--
ldv
8 years, 5 months
[PATCH] Move nested functions in gzip.c to file scope.
by Chih-Hung Hsieh
* libdwfl/gzip.c should now compile with clang.
All local variables used by nested functions are
passed in an unzip_state structure.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 4 +
libdwfl/gzip.c | 269 ++++++++++++++++++++++++++++++------------------------
2 files changed, 152 insertions(+), 121 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 5cae434..926c010 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2015-10-21 Chih-Hung Hsieh <chh(a)google.com>
+
+ * gzip.c (unzip): Move nested functions to file scope.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* core-file.c (elf_begin_rand): Replace loff_t with off_t.
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c
index c81e52e..283c74a 100644
--- a/libdwfl/gzip.c
+++ b/libdwfl/gzip.c
@@ -67,6 +67,95 @@
#define READ_SIZE (1 << 20)
+struct unzip_state {
+ int fd;
+ off_t start_offset;
+ size_t mapped_size;
+ void **whole;
+ void *buffer;
+ size_t size;
+ void *input_buffer;
+ off_t input_pos;
+ gzFile zf;
+};
+
+static inline bool
+bigger_buffer (struct unzip_state *state, size_t start)
+{
+ size_t more = state->size ? state->size * 2 : start;
+ char *b = realloc (state->buffer, more);
+ while (unlikely (b == NULL) && more >= state->size + 1024)
+ b = realloc (state->buffer, more -= 1024);
+ if (unlikely (b == NULL))
+ return false;
+ state->buffer = b;
+ state->size = more;
+ return true;
+}
+
+static inline void
+smaller_buffer (struct unzip_state *state, size_t end)
+{
+ state->buffer =
+ realloc (state->buffer, end) ?: end == 0 ? NULL : state->buffer;
+ state->size = end;
+}
+
+static inline Dwfl_Error
+fail (struct unzip_state *state, Dwfl_Error failure)
+{
+ if (state->input_pos == (off_t) state->mapped_size)
+ *state->whole = state->input_buffer;
+ else
+ {
+ free (state->input_buffer);
+ *state->whole = NULL;
+ }
+ free (state->buffer);
+ return failure;
+}
+
+static inline Dwfl_Error
+zlib_fail (struct unzip_state *state, int result)
+{
+ switch (result)
+ {
+ case Z (MEM_ERROR):
+ return fail (state, DWFL_E_NOMEM);
+ case Z (ERRNO):
+ return fail (state, DWFL_E_ERRNO);
+ default:
+ return fail (state, DWFL_E_ZLIB);
+ }
+}
+
+static Dwfl_Error
+open_stream (struct unzip_state *state)
+{
+ int d = dup (state->fd);
+ if (unlikely (d < 0))
+ return DWFL_E_BADELF;
+ if (state->start_offset != 0)
+ {
+ off_t off = lseek (d, state->start_offset, SEEK_SET);
+ if (off != state->start_offset)
+ {
+ close (d);
+ return DWFL_E_BADELF;
+ }
+ }
+ state->zf = gzdopen (d, "r");
+ if (unlikely (state->zf == NULL))
+ {
+ close (d);
+ return zlib_fail (state, Z (MEM_ERROR));
+ }
+
+ /* From here on, zlib will close D. */
+
+ return DWFL_E_NOERROR;
+}
+
/* If this is not a compressed image, return DWFL_E_BADELF.
If we uncompressed it into *WHOLE, *WHOLE_SIZE, return DWFL_E_NOERROR.
Otherwise return an error for bad compressed data or I/O failure.
@@ -75,84 +164,49 @@
is not null on entry, we'll use it in lieu of repeating a read. */
Dwfl_Error internal_function
-unzip (int fd, off_t start_offset,
- void *mapped, size_t mapped_size,
- void **whole, size_t *whole_size)
+unzip (int _fd, off_t _start_offset,
+ void *mapped, size_t _mapped_size,
+ void **_whole, size_t *whole_size)
{
- void *buffer = NULL;
- size_t size = 0;
- inline bool bigger_buffer (size_t start)
- {
- size_t more = size ? size * 2 : start;
- char *b = realloc (buffer, more);
- while (unlikely (b == NULL) && more >= size + 1024)
- b = realloc (buffer, more -= 1024);
- if (unlikely (b == NULL))
- return false;
- buffer = b;
- size = more;
- return true;
- }
- inline void smaller_buffer (size_t end)
- {
- buffer = realloc (buffer, end) ?: end == 0 ? NULL : buffer;
- size = end;
- }
-
- void *input_buffer = NULL;
- off_t input_pos = 0;
-
- inline Dwfl_Error fail (Dwfl_Error failure)
- {
- if (input_pos == (off_t) mapped_size)
- *whole = input_buffer;
- else
- {
- free (input_buffer);
- *whole = NULL;
- }
- free (buffer);
- return failure;
- }
-
- inline Dwfl_Error zlib_fail (int result)
- {
- switch (result)
- {
- case Z (MEM_ERROR):
- return fail (DWFL_E_NOMEM);
- case Z (ERRNO):
- return fail (DWFL_E_ERRNO);
- default:
- return fail (DWFL_E_ZLIB);
- }
- }
+ struct unzip_state state =
+ {
+ .fd = _fd,
+ .start_offset = _start_offset,
+ .mapped_size = _mapped_size,
+ .whole = _whole,
+ .buffer = NULL,
+ .size = 0,
+ .input_buffer = NULL,
+ .input_pos = 0,
+ .zf = NULL
+ };
if (mapped == NULL)
{
- if (*whole == NULL)
+ if (*state.whole == NULL)
{
- input_buffer = malloc (READ_SIZE);
- if (unlikely (input_buffer == NULL))
+ state.input_buffer = malloc (READ_SIZE);
+ if (unlikely (state.input_buffer == NULL))
return DWFL_E_NOMEM;
- ssize_t n = pread_retry (fd, input_buffer, READ_SIZE, start_offset);
+ ssize_t n = pread_retry (state.fd, state.input_buffer, READ_SIZE, state.start_offset);
if (unlikely (n < 0))
- return zlib_fail (Z (ERRNO));
+ return zlib_fail (&state, Z (ERRNO));
- input_pos = n;
- mapped = input_buffer;
- mapped_size = n;
+ state.input_pos = n;
+ mapped = state.input_buffer;
+ state.mapped_size = n;
}
else
{
- input_buffer = *whole;
- input_pos = mapped_size = *whole_size;
+ state.input_buffer = *state.whole;
+ state.input_pos = state.mapped_size = *whole_size;
}
}
#define NOMAGIC(magic) \
- (mapped_size <= sizeof magic || memcmp (mapped, magic, sizeof magic - 1))
+ (state.mapped_size <= sizeof magic || \
+ memcmp (mapped, magic, sizeof magic - 1))
/* First, look at the header. */
if (NOMAGIC (MAGIC)
@@ -169,39 +223,39 @@ unzip (int fd, off_t start_offset,
The stupid zlib interface has nothing to grok the
gzip file headers except the slow gzFile interface. */
- z_stream z = { .next_in = mapped, .avail_in = mapped_size };
+ z_stream z = { .next_in = mapped, .avail_in = state.mapped_size };
int result = inflateInit (&z);
if (result != Z (OK))
{
inflateEnd (&z);
- return zlib_fail (result);
+ return zlib_fail (&state, result);
}
do
{
- if (z.avail_in == 0 && input_buffer != NULL)
+ if (z.avail_in == 0 && state.input_buffer != NULL)
{
- ssize_t n = pread_retry (fd, input_buffer, READ_SIZE,
- start_offset + input_pos);
+ ssize_t n = pread_retry (state.fd, state.input_buffer, READ_SIZE,
+ state.start_offset + state.input_pos);
if (unlikely (n < 0))
{
inflateEnd (&z);
- return zlib_fail (Z (ERRNO));
+ return zlib_fail (&state, Z (ERRNO));
}
- z.next_in = input_buffer;
+ z.next_in = state.input_buffer;
z.avail_in = n;
- input_pos += n;
+ state.input_pos += n;
}
if (z.avail_out == 0)
{
- ptrdiff_t pos = (void *) z.next_out - buffer;
- if (!bigger_buffer (z.avail_in))
+ ptrdiff_t pos = (void *) z.next_out - state.buffer;
+ if (!bigger_buffer (&state, z.avail_in))
{
result = Z (MEM_ERROR);
break;
}
- z.next_out = buffer + pos;
- z.avail_out = size - pos;
+ z.next_out = state.buffer + pos;
+ z.avail_out = state.size - pos;
}
}
while ((result = do_inflate (&z)) == Z (OK));
@@ -209,87 +263,60 @@ unzip (int fd, off_t start_offset,
#ifdef BZLIB
uint64_t total_out = (((uint64_t) z.total_out_hi32 << 32)
| z.total_out_lo32);
- smaller_buffer (total_out);
+ smaller_buffer (&state, total_out);
#else
- smaller_buffer (z.total_out);
+ smaller_buffer (&state, z.total_out);
#endif
inflateEnd (&z);
if (result != Z (STREAM_END))
- return zlib_fail (result);
+ return zlib_fail (&state, result);
#else /* gzip only. */
/* Let the decompression library read the file directly. */
- gzFile zf;
- Dwfl_Error open_stream (void)
- {
- int d = dup (fd);
- if (unlikely (d < 0))
- return DWFL_E_BADELF;
- if (start_offset != 0)
- {
- off_t off = lseek (d, start_offset, SEEK_SET);
- if (off != start_offset)
- {
- close (d);
- return DWFL_E_BADELF;
- }
- }
- zf = gzdopen (d, "r");
- if (unlikely (zf == NULL))
- {
- close (d);
- return zlib_fail (Z (MEM_ERROR));
- }
-
- /* From here on, zlib will close D. */
-
- return DWFL_E_NOERROR;
- }
-
- Dwfl_Error result = open_stream ();
+ Dwfl_Error result = open_stream (&state);
- if (result == DWFL_E_NOERROR && gzdirect (zf))
+ if (result == DWFL_E_NOERROR && gzdirect (state.zf))
{
- gzclose (zf);
- return fail (DWFL_E_BADELF);
+ gzclose (state.zf);
+ return fail (&state, DWFL_E_BADELF);
}
if (result != DWFL_E_NOERROR)
- return fail (result);
+ return fail (&state, result);
ptrdiff_t pos = 0;
while (1)
{
- if (!bigger_buffer (1024))
+ if (!bigger_buffer (&state, 1024))
{
- gzclose (zf);
- return zlib_fail (Z (MEM_ERROR));
+ gzclose (state.zf);
+ return zlib_fail (&state, Z (MEM_ERROR));
}
- int n = gzread (zf, buffer + pos, size - pos);
+ int n = gzread (state.zf, state.buffer + pos, state.size - pos);
if (n < 0)
{
int code;
- gzerror (zf, &code);
- gzclose (zf);
- return zlib_fail (code);
+ gzerror (state.zf, &code);
+ gzclose (state.zf);
+ return zlib_fail (&state, code);
}
if (n == 0)
break;
pos += n;
}
- gzclose (zf);
- smaller_buffer (pos);
+ gzclose (state.zf);
+ smaller_buffer (&state, pos);
#endif
- free (input_buffer);
+ free (state.input_buffer);
- *whole = buffer;
- *whole_size = size;
+ *state.whole = state.buffer;
+ *whole_size = state.size;
return DWFL_E_NOERROR;
}
--
2.6.0.rc2.230.g3dd15c0
8 years, 5 months
[PATCH] No nested functions in dwarf_get{srclines,scopevar}
by Chih-Hung Hsieh
Move nested functions in libdw/dwarf_get{scopevar,srclines}.c
to file scope to compile with clang/llvm.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdw/ChangeLog | 8 ++
libdw/dwarf_getscopevar.c | 38 ++++----
libdw/dwarf_getsrclines.c | 241 ++++++++++++++++++++++++++--------------------
3 files changed, 165 insertions(+), 122 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 39c49aa..837ccdf 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2015-10-13 Chih-Hung Hsieh <chh(a)google.com>
+
+ * dwarf_getscopevar.c (dwarf_getscopevar): Move nested
+ function 'file_matches' to file scope.
+ * dwarf_getsrclines.c (read_srclines): Move nested functions
+ 'advance_pc' and 'add_new_line' to file scope and keep many
+ local state variables within one structure.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* dwarf_begin.c (dwarf_begin): Replace stat64 and fstat64 with stat
diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c
index eb50c0a..e59dccd 100644
--- a/libdw/dwarf_getscopevar.c
+++ b/libdw/dwarf_getscopevar.c
@@ -52,6 +52,25 @@ getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
&attr_mem), value);
}
+inline static int
+file_matches (Dwarf_Files * files, size_t idx,
+ const char *lastfile, size_t match_file_len,
+ const char *match_file, bool *lastfile_matches)
+{
+ if (idx >= files->nfiles)
+ return false;
+ const char *file = files->info[idx].name;
+ if (file != lastfile)
+ {
+ size_t len = strlen (file);
+ *lastfile_matches = (len >= match_file_len
+ && !memcmp (match_file, file, match_file_len)
+ && (len == match_file_len
+ || file[len - match_file_len - 1] == '/'));
+ }
+ return *lastfile_matches;
+}
+
/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
Ignore the first SKIP_SHADOWS scopes that match the name.
If MATCH_FILE is not null, accept only declaration in that source file;
@@ -72,22 +91,6 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
bool lastfile_matches = false;
const char *lastfile = NULL;
- inline bool file_matches (Dwarf_Files *files, size_t idx)
- {
- if (idx >= files->nfiles)
- return false;
-
- const char *file = files->info[idx].name;
- if (file != lastfile)
- {
- size_t len = strlen (file);
- lastfile_matches = (len >= match_file_len
- && !memcmp (match_file, file, match_file_len)
- && (len == match_file_len
- || file[len - match_file_len - 1] == '/'));
- }
- return lastfile_matches;
- }
/* Start with the innermost scope and move out. */
for (int out = 0; out < nscopes; ++out)
@@ -130,7 +133,8 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
|| getfiles (&scopes[out], &files) != 0)
break;
- if (!file_matches (files, i))
+ if (!file_matches (files, i, lastfile, match_file_len,
+ match_file, &lastfile_matches))
break;
if (match_lineno > 0
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 389c824..a8b57e1 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -78,6 +78,73 @@ compare_lines (const void *a, const void *b)
: 0;
}
+struct line_state {
+ Dwarf_Word addr;
+ unsigned int op_index;
+ unsigned int file;
+ int64_t line;
+ unsigned int column;
+ uint_fast8_t is_stmt;
+ bool basic_block;
+ bool prologue_end;
+ bool epilogue_begin;
+ unsigned int isa;
+ unsigned int discriminator;
+ struct linelist *linelist;
+ size_t nlinelist;
+ unsigned int end_sequence;
+};
+
+static inline void
+run_advance_pc (struct line_state *state, unsigned int op_advance,
+ uint_fast8_t minimum_instr_len, uint_fast8_t max_ops_per_instr)
+{
+ state->addr += minimum_instr_len * ((state->op_index + op_advance)
+ / max_ops_per_instr);
+ state->op_index = (state->op_index + op_advance) % max_ops_per_instr;
+}
+
+static inline bool
+add_new_line (struct line_state *state, struct linelist *new_line)
+{
+ /* Set the line information. For some fields we use bitfields,
+ so we would lose information if the encoded values are too large.
+ Check just for paranoia, and call the data "invalid" if it
+ violates our assumptions on reasonable limits for the values. */
+ new_line->next = state->linelist;
+ new_line->sequence = state->nlinelist;
+ state->linelist = new_line;
+ ++(state->nlinelist);
+
+ /* Set the line information. For some fields we use bitfields,
+ so we would lose information if the encoded values are too large.
+ Check just for paranoia, and call the data "invalid" if it
+ violates our assumptions on reasonable limits for the values. */
+#define SET(field) \
+ do { \
+ new_line->line.field = state->field; \
+ if (unlikely (new_line->line.field != state->field)) \
+ return true; \
+ } while (0)
+
+ SET (addr);
+ SET (op_index);
+ SET (file);
+ SET (line);
+ SET (column);
+ SET (is_stmt);
+ SET (basic_block);
+ SET (end_sequence);
+ SET (prologue_end);
+ SET (epilogue_begin);
+ SET (isa);
+ SET (discriminator);
+
+#undef SET
+
+ return false;
+}
+
static int
read_srclines (Dwarf *dbg,
const unsigned char *linep, const unsigned char *lineendp,
@@ -86,8 +153,6 @@ read_srclines (Dwarf *dbg,
{
int res = -1;
- struct linelist *linelist = NULL;
- size_t nlinelist = 0;
size_t nfilelist = 0;
unsigned int ndirlist = 0;
@@ -323,27 +388,28 @@ read_srclines (Dwarf *dbg,
/* We are about to process the statement program. Initialize the
state machine registers (see 6.2.2 in the v2.1 specification). */
- Dwarf_Word addr = 0;
- unsigned int op_index = 0;
- unsigned int file = 1;
- /* We only store an int, but want to check for overflow (see SET below). */
- int64_t line = 1;
- unsigned int column = 0;
- uint_fast8_t is_stmt = default_is_stmt;
- bool basic_block = false;
- bool prologue_end = false;
- bool epilogue_begin = false;
- unsigned int isa = 0;
- unsigned int discriminator = 0;
+ struct line_state state =
+ {
+ .linelist = NULL,
+ .nlinelist = 0,
+ .addr = 0,
+ .op_index = 0,
+ .file = 1,
+ /* We only store an int, but want to check for overflow (see SET below). */
+ .line = 1,
+ .column = 0,
+ .is_stmt = default_is_stmt,
+ .basic_block = false,
+ .prologue_end = false,
+ .epilogue_begin = false,
+ .isa = 0,
+ .discriminator = 0
+ };
/* Apply the "operation advance" from a special opcode or
DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
- inline void advance_pc (unsigned int op_advance)
- {
- addr += minimum_instr_len * ((op_index + op_advance)
- / max_ops_per_instr);
- op_index = (op_index + op_advance) % max_ops_per_instr;
- }
+#define advance_pc(op_advance) \
+ run_advance_pc (&state, op_advance, minimum_instr_len, max_ops_per_instr)
/* Process the instructions. */
@@ -352,51 +418,16 @@ read_srclines (Dwarf *dbg,
struct linelist llstack[MAX_STACK_LINES];
#define NEW_LINE(end_seq) \
do { \
- struct linelist *ll = (nlinelist < MAX_STACK_LINES \
- ? &llstack[nlinelist] \
+ struct linelist *ll = (state.nlinelist < MAX_STACK_LINES \
+ ? &llstack[state.nlinelist] \
: malloc (sizeof (struct linelist))); \
if (unlikely (ll == NULL)) \
goto no_mem; \
- if (unlikely (add_new_line (ll, end_seq))) \
+ state.end_sequence = end_seq; \
+ if (unlikely (add_new_line (&state, ll))) \
goto invalid_data; \
} while (0)
- inline bool add_new_line (struct linelist *new_line, bool end_sequence)
- {
- new_line->next = linelist;
- new_line->sequence = nlinelist;
- linelist = new_line;
- ++nlinelist;
-
- /* Set the line information. For some fields we use bitfields,
- so we would lose information if the encoded values are too large.
- Check just for paranoia, and call the data "invalid" if it
- violates our assumptions on reasonable limits for the values. */
-#define SET(field) \
- do { \
- new_line->line.field = field; \
- if (unlikely (new_line->line.field != field)) \
- return true; \
- } while (0)
-
- SET (addr);
- SET (op_index);
- SET (file);
- SET (line);
- SET (column);
- SET (is_stmt);
- SET (basic_block);
- SET (end_sequence);
- SET (prologue_end);
- SET (epilogue_begin);
- SET (isa);
- SET (discriminator);
-
-#undef SET
-
- return false;
- }
-
while (linep < lineendp)
{
unsigned int opcode;
@@ -422,17 +453,17 @@ read_srclines (Dwarf *dbg,
+ (opcode - opcode_base) % line_range);
/* Perform the increments. */
- line += line_increment;
+ state.line += line_increment;
advance_pc ((opcode - opcode_base) / line_range);
/* Add a new line with the current state machine values. */
NEW_LINE (0);
/* Reset the flags. */
- basic_block = false;
- prologue_end = false;
- epilogue_begin = false;
- discriminator = 0;
+ state.basic_block = false;
+ state.prologue_end = false;
+ state.epilogue_begin = false;
+ state.discriminator = 0;
}
else if (opcode == 0)
{
@@ -457,28 +488,28 @@ read_srclines (Dwarf *dbg,
NEW_LINE (1);
/* Reset the registers. */
- addr = 0;
- op_index = 0;
- file = 1;
- line = 1;
- column = 0;
- is_stmt = default_is_stmt;
- basic_block = false;
- prologue_end = false;
- epilogue_begin = false;
- isa = 0;
- discriminator = 0;
+ state.addr = 0;
+ state.op_index = 0;
+ state.file = 1;
+ state.line = 1;
+ state.column = 0;
+ state.is_stmt = default_is_stmt;
+ state.basic_block = false;
+ state.prologue_end = false;
+ state.epilogue_begin = false;
+ state.isa = 0;
+ state.discriminator = 0;
break;
case DW_LNE_set_address:
/* The value is an address. The size is defined as
apporiate for the target machine. We use the
address size field from the CU header. */
- op_index = 0;
+ state.op_index = 0;
if (unlikely (lineendp - linep < (uint8_t) address_size))
goto invalid_data;
if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
- address_size, &addr))
+ address_size, &state.addr))
goto out;
break;
@@ -542,7 +573,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (linep >= lineendp))
goto invalid_data;
- get_uleb128 (discriminator, linep, lineendp);
+ get_uleb128 (state.discriminator, linep, lineendp);
break;
default:
@@ -567,10 +598,10 @@ read_srclines (Dwarf *dbg,
NEW_LINE (0);
/* Reset the flags. */
- basic_block = false;
- prologue_end = false;
- epilogue_begin = false;
- discriminator = 0;
+ state.basic_block = false;
+ state.prologue_end = false;
+ state.epilogue_begin = false;
+ state.discriminator = 0;
break;
case DW_LNS_advance_pc:
@@ -594,7 +625,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (linep >= lineendp))
goto invalid_data;
get_sleb128 (s128, linep, lineendp);
- line += s128;
+ state.line += s128;
break;
case DW_LNS_set_file:
@@ -605,7 +636,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (linep >= lineendp))
goto invalid_data;
get_uleb128 (u128, linep, lineendp);
- file = u128;
+ state.file = u128;
break;
case DW_LNS_set_column:
@@ -616,7 +647,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (linep >= lineendp))
goto invalid_data;
get_uleb128 (u128, linep, lineendp);
- column = u128;
+ state.column = u128;
break;
case DW_LNS_negate_stmt:
@@ -624,7 +655,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (standard_opcode_lengths[opcode] != 0))
goto invalid_data;
- is_stmt = 1 - is_stmt;
+ state.is_stmt = 1 - state.is_stmt;
break;
case DW_LNS_set_basic_block:
@@ -632,7 +663,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (standard_opcode_lengths[opcode] != 0))
goto invalid_data;
- basic_block = true;
+ state.basic_block = true;
break;
case DW_LNS_const_add_pc:
@@ -653,8 +684,8 @@ read_srclines (Dwarf *dbg,
|| unlikely (lineendp - linep < 2))
goto invalid_data;
- addr += read_2ubyte_unaligned_inc (dbg, linep);
- op_index = 0;
+ state.addr += read_2ubyte_unaligned_inc (dbg, linep);
+ state.op_index = 0;
break;
case DW_LNS_set_prologue_end:
@@ -662,7 +693,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (standard_opcode_lengths[opcode] != 0))
goto invalid_data;
- prologue_end = true;
+ state.prologue_end = true;
break;
case DW_LNS_set_epilogue_begin:
@@ -670,7 +701,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (standard_opcode_lengths[opcode] != 0))
goto invalid_data;
- epilogue_begin = true;
+ state.epilogue_begin = true;
break;
case DW_LNS_set_isa:
@@ -680,7 +711,7 @@ read_srclines (Dwarf *dbg,
if (unlikely (linep >= lineendp))
goto invalid_data;
- get_uleb128 (isa, linep, lineendp);
+ get_uleb128 (state.isa, linep, lineendp);
break;
}
}
@@ -728,7 +759,7 @@ read_srclines (Dwarf *dbg,
if (filesp != NULL)
*filesp = files;
- size_t buf_size = (sizeof (Dwarf_Lines) + (sizeof (Dwarf_Line) * nlinelist));
+ size_t buf_size = (sizeof (Dwarf_Lines) + (sizeof (Dwarf_Line) * state.nlinelist));
void *buf = libdw_alloc (dbg, Dwarf_Lines, buf_size, 1);
/* First use the buffer for the pointers, and sort the entries.
@@ -736,13 +767,13 @@ read_srclines (Dwarf *dbg,
copy into the buffer from the beginning so the overlap works. */
assert (sizeof (Dwarf_Line) >= sizeof (struct linelist *));
struct linelist **sortlines = (buf + buf_size
- - sizeof (struct linelist **) * nlinelist);
+ - sizeof (struct linelist **) * state.nlinelist);
/* The list is in LIFO order and usually they come in clumps with
ascending addresses. So fill from the back to probably start with
runs already in order before we sort. */
- struct linelist *lineslist = linelist;
- for (size_t i = nlinelist; i-- > 0; )
+ struct linelist *lineslist = state.linelist;
+ for (size_t i = state.nlinelist; i-- > 0; )
{
sortlines[i] = lineslist;
lineslist = lineslist->next;
@@ -750,14 +781,14 @@ read_srclines (Dwarf *dbg,
assert (lineslist == NULL);
/* Sort by ascending address. */
- qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
+ qsort (sortlines, state.nlinelist, sizeof sortlines[0], &compare_lines);
/* Now that they are sorted, put them in the final array.
The buffers overlap, so we've clobbered the early elements
of SORTLINES by the time we're reading the later ones. */
Dwarf_Lines *lines = buf;
- lines->nlines = nlinelist;
- for (size_t i = 0; i < nlinelist; ++i)
+ lines->nlines = state.nlinelist;
+ for (size_t i = 0; i < state.nlinelist; ++i)
{
lines->info[i] = sortlines[i]->line;
lines->info[i].files = files;
@@ -766,8 +797,8 @@ read_srclines (Dwarf *dbg,
/* Make sure the highest address for the CU is marked as end_sequence.
This is required by the DWARF spec, but some compilers forget and
dwfl_module_getsrc depends on it. */
- if (nlinelist > 0)
- lines->info[nlinelist - 1].end_sequence = 1;
+ if (state.nlinelist > 0)
+ lines->info[state.nlinelist - 1].end_sequence = 1;
/* Pass the line structure back to the caller. */
if (linesp != NULL)
@@ -778,11 +809,11 @@ read_srclines (Dwarf *dbg,
out:
/* Free malloced line records, if any. */
- for (size_t i = MAX_STACK_LINES; i < nlinelist; i++)
+ for (size_t i = MAX_STACK_LINES; i < state.nlinelist; i++)
{
- struct linelist *ll = linelist->next;
- free (linelist);
- linelist = ll;
+ struct linelist *ll = state.linelist->next;
+ free (state.linelist);
+ state.linelist = ll;
}
if (ndirlist >= MAX_STACK_DIRS)
free (dirarray);
--
2.6.0.rc2.230.g3dd15c0
8 years, 5 months
[PATCH] Move nested functions in dwfl_module.c and dwfl_module_getsrc_file.c.
by Chih-Hung Hsieh
* Nested functions in these two files are moved to file scope
to compile with clang. Extra parameters are added to pass
local variables.
Signed-off-by: Chih-Hung Hsieh
---
libdwfl/ChangeLog | 7 +++++++
libdwfl/dwfl_module.c | 33 +++++++++++++++++----------------
libdwfl/dwfl_module_getsrc_file.c | 31 ++++++++++++++++++-------------
3 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 5cae434..0374e5a 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,10 @@
+2015-10-21 Chih-Hung Hsieh <chh(a)google.com>
+
+ * dwfl_module.c (dwfl_report_module): Move nested function 'use' to file
+ scope.
+ * dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Move nested functions
+ 'dwarf_line_file', 'dwfl_line', and 'dwfl_line_file' to file scope.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* core-file.c (elf_begin_rand): Replace loff_t with off_t.
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
index 8efcfaa..76d45a8 100644
--- a/libdwfl/dwfl_module.c
+++ b/libdwfl/dwfl_module.c
@@ -125,6 +125,21 @@ dwfl_report_begin (Dwfl *dwfl)
}
INTDEF (dwfl_report_begin)
+static inline Dwfl_Module *
+use (Dwfl_Module *mod, Dwfl_Module **tailp, Dwfl *dwfl)
+{
+ mod->next = *tailp;
+ *tailp = mod;
+
+ if (unlikely (dwfl->lookup_module != NULL))
+ {
+ free (dwfl->lookup_module);
+ dwfl->lookup_module = NULL;
+ }
+
+ return mod;
+}
+
/* Report that a module called NAME spans addresses [START, END).
Returns the module handle, either existing or newly allocated,
or returns a null pointer for an allocation error. */
@@ -134,20 +149,6 @@ dwfl_report_module (Dwfl *dwfl, const char *name,
{
Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
- inline Dwfl_Module *use (Dwfl_Module *mod)
- {
- mod->next = *tailp;
- *tailp = mod;
-
- if (unlikely (dwfl->lookup_module != NULL))
- {
- free (dwfl->lookup_module);
- dwfl->lookup_module = NULL;
- }
-
- return mod;
- }
-
for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
{
if (m->low_addr == start && m->high_addr == end
@@ -157,7 +158,7 @@ dwfl_report_module (Dwfl *dwfl, const char *name,
after the last module already reported. */
*prevp = m->next;
m->gc = false;
- return use (m);
+ return use (m, tailp, dwfl);
}
if (! m->gc)
@@ -181,7 +182,7 @@ dwfl_report_module (Dwfl *dwfl, const char *name,
mod->high_addr = end;
mod->dwfl = dwfl;
- return use (mod);
+ return use (mod, tailp, dwfl);
}
INTDEF (dwfl_report_module)
diff --git a/libdwfl/dwfl_module_getsrc_file.c b/libdwfl/dwfl_module_getsrc_file.c
index 20aa8a5..75ba68e 100644
--- a/libdwfl/dwfl_module_getsrc_file.c
+++ b/libdwfl/dwfl_module_getsrc_file.c
@@ -30,6 +30,24 @@
#include "../libdw/libdwP.h"
+static inline const char *
+INTUSE(dwarf_line_file) (const Dwarf_Line *line)
+{
+ return line->files->info[line->file].name;
+}
+
+static inline Dwarf_Line *
+dwfl_line (const Dwfl_Line *line)
+{
+ return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
+}
+
+static inline const char *
+dwfl_line_file (const Dwfl_Line *line)
+{
+ return INTUSE(dwarf_line_file) (dwfl_line (line));
+}
+
int
dwfl_module_getsrc_file (Dwfl_Module *mod,
const char *fname, int lineno, int column,
@@ -58,19 +76,6 @@ dwfl_module_getsrc_file (Dwfl_Module *mod,
&& cu != NULL
&& (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR)
{
- inline const char *INTUSE(dwarf_line_file) (const Dwarf_Line *line)
- {
- return line->files->info[line->file].name;
- }
- inline Dwarf_Line *dwfl_line (const Dwfl_Line *line)
- {
- return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
- }
- inline const char *dwfl_line_file (const Dwfl_Line *line)
- {
- return INTUSE(dwarf_line_file) (dwfl_line (line));
- }
-
/* Search through all the line number records for a matching
file and line/column number. If any of the numbers is zero,
no match is performed. */
--
2.6.0.rc2.230.g3dd15c0
8 years, 6 months
[PATCH] Move nested functions in frame_unwind.c.
by Chih-Hung Hsieh
* Nested functions 'pop' and 'push' in libdwfl/frame_unwind.c
are moved to file scope. Used local variables are passed in
struct eval_stack.
Signed-off-by: Chih-Hung Hsieh <chh(a)google.com>
---
libdwfl/ChangeLog | 5 ++
libdwfl/frame_unwind.c | 161 +++++++++++++++++++++++++++----------------------
2 files changed, 93 insertions(+), 73 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 5cae434..96ea068 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-21 Chih-Hung Hsieh <chh(a)google.com>
+
+ * frame_unwind.c (expr_eval): Move nested function 'push' and 'pop'
+ to file scope. Pass used local variables in struct eval_stack.
+
2015-10-09 Josh Stone <jistone(a)redhat.com>
* core-file.c (elf_begin_rand): Replace loff_t with off_t.
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index bd100b8..68b3d92 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -101,6 +101,47 @@ bra_compar (const void *key_voidp, const void *elem_voidp)
return (offset > op->offset) - (offset < op->offset);
}
+struct eval_stack {
+ Dwarf_Addr *addrs;
+ size_t used;
+ size_t allocated;
+};
+
+static bool
+do_push (struct eval_stack *stack, Dwarf_Addr val)
+{
+ if (stack->used >= DWARF_EXPR_STACK_MAX)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ if (stack->used == stack->allocated)
+ {
+ stack->allocated = MAX (stack->allocated * 2, 32);
+ Dwarf_Addr *new_addrs = realloc (stack->addrs, stack->allocated * sizeof (*stack->addrs));
+ if (new_addrs == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return false;
+ }
+ stack->addrs = new_addrs;
+ }
+ stack->addrs[stack->used++] = val;
+ return true;
+}
+
+static bool
+do_pop (struct eval_stack *stack, Dwarf_Addr *val)
+{
+ if (stack->used == 0)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ *val = stack->addrs[--stack->used];
+ return true;
+}
+
/* If FRAME is NULL is are computing CFI frame base. In such case another
DW_OP_call_frame_cfa is no longer permitted. */
@@ -114,43 +155,15 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
- Dwarf_Addr *stack = NULL;
- size_t stack_used = 0, stack_allocated = 0;
+ struct eval_stack stack =
+ {
+ .addrs = NULL,
+ .used = 0,
+ .allocated = 0
+ };
- bool
- push (Dwarf_Addr val)
- {
- if (stack_used >= DWARF_EXPR_STACK_MAX)
- {
- __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
- return false;
- }
- if (stack_used == stack_allocated)
- {
- stack_allocated = MAX (stack_allocated * 2, 32);
- Dwarf_Addr *stack_new = realloc (stack, stack_allocated * sizeof (*stack));
- if (stack_new == NULL)
- {
- __libdwfl_seterrno (DWFL_E_NOMEM);
- return false;
- }
- stack = stack_new;
- }
- stack[stack_used++] = val;
- return true;
- }
-
- bool
- pop (Dwarf_Addr *val)
- {
- if (stack_used == 0)
- {
- __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
- return false;
- }
- *val = stack[--stack_used];
- return true;
- }
+#define pop(x) do_pop(&stack, x)
+#define push(x) do_push(&stack, x)
Dwarf_Addr val1, val2;
bool is_location = false;
@@ -168,14 +181,14 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_lit0 ... DW_OP_lit31:
if (! push (op->atom - DW_OP_lit0))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_addr:
if (! push (op->number + bias))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -195,7 +208,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_consts:
if (! push (op->number))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -203,67 +216,67 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1)
|| ! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_regx:
if (! state_get_reg (state, op->number, &val1) || ! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_breg0 ... DW_OP_breg31:
if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
val1 += op->number;
if (! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_bregx:
if (! state_get_reg (state, op->number, &val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
val1 += op->number2;
if (! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_dup:
if (! pop (&val1) || ! push (val1) || ! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_drop:
if (! pop (&val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_pick:
- if (stack_used <= op->number)
+ if (stack.used <= op->number)
{
- free (stack);
+ free (stack.addrs);
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
- if (! push (stack[stack_used - 1 - op->number]))
+ if (! push (stack.addrs[stack.used - 1 - op->number]))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -271,14 +284,14 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
if (! pop (&val1) || ! pop (&val2)
|| ! push (val2) || ! push (val1) || ! push (val2))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
case DW_OP_swap:
if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -288,7 +301,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
if (! pop (&val1) || ! pop (&val2) || ! pop (&val3)
|| ! push (val1) || ! push (val3) || ! push (val2))
{
- free (stack);
+ free (stack.addrs);
return false;
}
}
@@ -297,7 +310,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_deref_size:
if (process->callbacks->memory_read == NULL)
{
- free (stack);
+ free (stack.addrs);
__libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
return false;
}
@@ -305,7 +318,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
|| ! process->callbacks->memory_read (process->dwfl, val1, &val1,
process->callbacks_arg))
{
- free (stack);
+ free (stack.addrs);
return false;
}
if (op->atom == DW_OP_deref_size)
@@ -314,7 +327,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8;
if (op->number > addr_bytes)
{
- free (stack);
+ free (stack.addrs);
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
@@ -330,7 +343,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
}
if (! push (val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -338,7 +351,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case atom: \
if (! pop (&val1) || ! push (expr)) \
{ \
- free (stack); \
+ free (stack.addrs); \
return false; \
} \
break;
@@ -349,7 +362,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_plus_uconst:
if (! pop (&val1) || ! push (val1 + op->number))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -357,7 +370,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case atom: \
if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2)) \
{ \
- free (stack); \
+ free (stack.addrs); \
return false; \
} \
break;
@@ -366,7 +379,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
if (! pop (&val2) || ! pop (&val1) \
|| ! push ((int64_t) val1 op (int64_t) val2)) \
{ \
- free (stack); \
+ free (stack.addrs); \
return false; \
} \
break;
@@ -374,18 +387,18 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_div:
if (! pop (&val2) || ! pop (&val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
if (val2 == 0)
{
- free (stack);
+ free (stack.addrs);
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
if (! push ((int64_t) val1 / (int64_t) val2))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -393,18 +406,18 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_mod:
if (! pop (&val2) || ! pop (&val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
if (val2 == 0)
{
- free (stack);
+ free (stack.addrs);
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
if (! push (val1 % val2))
{
- free (stack);
+ free (stack.addrs);
return false;
}
break;
@@ -426,7 +439,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
case DW_OP_bra:
if (! pop (&val1))
{
- free (stack);
+ free (stack.addrs);
return false;
}
if (val1 == 0)
@@ -438,7 +451,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
sizeof (*ops), bra_compar);
if (found == NULL)
{
- free (stack);
+ free (stack.addrs);
/* PPC32 vDSO has such invalid operations. */
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
@@ -460,7 +473,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
|| ! push (cfa))
{
__libdwfl_seterrno (DWFL_E_LIBDW);
- free (stack);
+ free (stack.addrs);
return false;
}
is_location = true;
@@ -476,10 +489,10 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
}
if (! pop (result))
{
- free (stack);
+ free (stack.addrs);
return false;
}
- free (stack);
+ free (stack.addrs);
if (is_location)
{
if (process->callbacks->memory_read == NULL)
@@ -492,6 +505,8 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
return false;
}
return true;
+#undef push
+#undef pop
}
static void
--
2.6.0.rc2.230.g3dd15c0
8 years, 6 months