libdw: Simplify and inline get_uleb128 and get_sleb128

This removes the IS_LIBDW distinction so LEB128 operations are now
always inlined, and the implementations are simplified, more direct.

Signed-off-by: Josh Stone <jistone@redhat.com>
This commit is contained in:
Josh Stone
2013-12-10 14:19:09 -08:00
parent c0d2a0b3a3
commit 4e2787c267
5 changed files with 56 additions and 124 deletions
+15
View File
@@ -1,3 +1,18 @@
2013-12-10 Josh Stone <jistone@redhat.com>
* memory-access.h (get_uleb128_rest_return): Removed.
(get_sleb128_rest_return): Removed.
(get_uleb128_step): Make this a self-contained block.
(get_sleb128_step): Ditto, and use a bitfield to extend signs.
(get_uleb128): Make this wholly implemented by __libdw_get_uleb128.
(get_sleb128): Make this wholly implemented by __libdw_get_sleb128.
(__libdw_get_uleb128): Simplify and inline for all callers.
(__libdw_get_sleb128): Ditto.
* dwarf_getlocation.c (store_implicit_value): Void the unused uleb128.
* memory-access.c: Delete file.
* Makefile.am (libdw_a_SOURCES): Remove it.
(DEFS): Remove the now unused -DIS_LIBDW.
2013-12-09 Josh Stone <jistone@redhat.com>
* libdw_form.c (__libdw_form_val_compute_len): Renamed function from
+1 -2
View File
@@ -28,7 +28,6 @@
## not, see <http://www.gnu.org/licenses/>.
##
include $(top_srcdir)/config/eu.am
DEFS += -DIS_LIBDW
if BUILD_STATIC
AM_CFLAGS += -fpic
endif
@@ -79,7 +78,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_getfuncs.c \
dwarf_decl_file.c dwarf_decl_line.c dwarf_decl_column.c \
dwarf_func_inline.c dwarf_getsrc_file.c \
libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \
libdw_findcu.c libdw_form.c libdw_alloc.c \
libdw_visit_scopes.c \
dwarf_entry_breakpoints.c \
dwarf_next_cfi.c \
+1 -2
View File
@@ -100,8 +100,7 @@ store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
sizeof (struct loc_block_s), 1);
const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
Dwarf_Word blength; // Ignored, equal to op->number.
get_uleb128 (blength, data);
(void) __libdw_get_uleb128 (&data); // Ignored, equal to op->number.
block->addr = op;
block->data = (unsigned char *) data;
block->length = op->number;
-50
View File
@@ -1,50 +0,0 @@
/* Out of line functions for memory-access.h macros.
Copyright (C) 2005, 2006 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 either
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at
your option) any later version
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at
your option) any later version
or both in parallel, as here.
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 copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libdwP.h"
#include "memory-access.h"
uint64_t
internal_function
__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
{
unsigned char __b;
get_uleb128_rest_return (acc, i, addrp);
}
int64_t
internal_function
__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
{
unsigned char __b;
int64_t _v = acc;
get_sleb128_rest_return (acc, i, addrp);
}
+39 -70
View File
@@ -37,90 +37,59 @@
/* Number decoding macros. See 7.6 Variable Length Data. */
#define get_uleb128_step(var, addr, nth, break) \
__b = *(addr)++; \
var |= (uintmax_t) (__b & 0x7f) << (nth * 7); \
#define len_leb128(var) ((8 * sizeof (var) + 6) / 7)
#define get_uleb128_step(var, addr, nth) \
do { \
unsigned char __b = *(addr)++; \
(var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7); \
if (likely ((__b & 0x80) == 0)) \
break
#define get_uleb128(var, addr) \
do { \
unsigned char __b; \
var = 0; \
get_uleb128_step (var, addr, 0, break); \
var = __libdw_get_uleb128 (var, 1, &(addr)); \
return (var); \
} while (0)
#define get_uleb128_rest_return(var, i, addrp) \
do { \
for (; i < 10; ++i) \
{ \
get_uleb128_step (var, *addrp, i, return var); \
} \
/* Other implementations set VALUE to UINT_MAX in this \
case. So we better do this as well. */ \
return UINT64_MAX; \
} while (0)
static inline uint64_t
__libdw_get_uleb128 (const unsigned char **addrp)
{
uint64_t acc = 0;
/* Unroll the first step to help the compiler optimize
for the common single-byte case. */
get_uleb128_step (acc, *addrp, 0);
for (unsigned int i = 1; i < len_leb128 (acc); ++i)
get_uleb128_step (acc, *addrp, i);
/* Other implementations set VALUE to UINT_MAX in this
case. So we better do this as well. */
return UINT64_MAX;
}
#define get_uleb128(var, addr) ((var) = __libdw_get_uleb128 (&(addr)))
/* The signed case is similar, but we sign-extend the result. */
#define get_sleb128_step(var, addr, nth, break) \
__b = *(addr)++; \
_v |= (uint64_t) (__b & 0x7f) << (nth * 7); \
#define get_sleb128_step(var, addr, nth) \
do { \
unsigned char __b = *(addr)++; \
if (likely ((__b & 0x80) == 0)) \
{ \
var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7); \
break; \
struct { signed int i:7; } __s = { .i = __b }; \
(var) |= (typeof (var)) __s.i << ((nth) * 7); \
return (var); \
} \
else do {} while (0)
#define get_sleb128(var, addr) \
do { \
unsigned char __b; \
int64_t _v = 0; \
get_sleb128_step (var, addr, 0, break); \
var = __libdw_get_sleb128 (_v, 1, &(addr)); \
(var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7); \
} while (0)
#define get_sleb128_rest_return(var, i, addrp) \
do { \
for (; i < 9; ++i) \
{ \
get_sleb128_step (var, *addrp, i, return var); \
} \
__b = *(*addrp)++; \
if (likely ((__b & 0x80) == 0)) \
return var | ((uint64_t) __b << 63); \
else \
/* Other implementations set VALUE to INT_MAX in this \
case. So we better do this as well. */ \
return INT64_MAX; \
} while (0)
#ifdef IS_LIBDW
extern uint64_t __libdw_get_uleb128 (uint64_t acc, unsigned int i,
const unsigned char **addrp)
internal_function attribute_hidden;
extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i,
const unsigned char **addrp)
internal_function attribute_hidden;
#else
static inline uint64_t
__attribute__ ((unused))
__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
{
unsigned char __b;
get_uleb128_rest_return (acc, i, addrp);
}
static inline int64_t
__attribute__ ((unused))
__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
__libdw_get_sleb128 (const unsigned char **addrp)
{
unsigned char __b;
int64_t _v = acc;
get_sleb128_rest_return (acc, i, addrp);
int64_t acc = 0;
/* Unrolling 0 like uleb128 didn't prove to benefit optimization. */
for (unsigned int i = 0; i < len_leb128 (acc); ++i)
get_sleb128_step (acc, *addrp, i);
/* Other implementations set VALUE to INT_MAX in this
case. So we better do this as well. */
return INT64_MAX;
}
#endif
#define get_sleb128(var, addr) ((var) = __libdw_get_sleb128 (&(addr)))
/* We use simple memory access functions in case the hardware allows it.