summaryrefslogtreecommitdiffstats
path: root/libdw/memory-access.h
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2017-11-24 11:18:39 +0100
committerMark Wielaard <[email protected]>2018-04-03 13:13:07 +0200
commit4a97eb02bb0bcd6562f8777596e3bbad0045d7a4 (patch)
tree373e25c5b122ecd4e98490769c29c719024234aa /libdw/memory-access.h
parent402b7f76c51d05bbba5b16827779359bd797c7b0 (diff)
libdw: Add support for reading DW_FORM_addrx[1234] in .debug_addr.
Recognize the new .debug_addr section. The CU will now hold a new address base offset in that section for that CU. dwarf_form_addr will decode DW_FORM_addrx[1234] and return addresses using that address base from the .debug_addr. A new internal function read_3ubyte_unaligned will try to read a 24-bit value depending on endianness of the underlying file. Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libdw/memory-access.h')
-rw-r--r--libdw/memory-access.h50
1 files changed, 48 insertions, 2 deletions
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
index 5f96a14a..22918cb9 100644
--- a/libdw/memory-access.h
+++ b/libdw/memory-access.h
@@ -1,7 +1,6 @@
/* Unaligned memory access functionality.
- Copyright (C) 2000-2014 Red Hat, Inc.
+ Copyright (C) 2000-2014, 2018 Red Hat, Inc.
This file is part of elfutils.
- Written by Ulrich Drepper <[email protected]>, 2001.
This file is free software; you can redistribute it and/or modify
it under the terms of either
@@ -31,6 +30,7 @@
#define _MEMORY_ACCESS_H 1
#include <byteswap.h>
+#include <endian.h>
#include <limits.h>
#include <stdint.h>
@@ -315,6 +315,52 @@ read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
t_; })
+/* 3ubyte reads are only used for DW_FORM_addrx3 and DW_FORM_strx3.
+ And are probably very rare. They are not optimized. They are
+ handled as if reading a 4byte value with the first (for big endian)
+ or last (for little endian) byte zero. */
+
+static inline int
+file_byte_order (bool other_byte_order)
+{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return other_byte_order ? __BIG_ENDIAN : __LITTLE_ENDIAN;
+#else
+ return other_byte_order ? __LITTLE_ENDIAN : __BIG_ENDIAN;
+#endif
+}
+
+static inline uint32_t
+read_3ubyte_unaligned (Dwarf *dbg, const unsigned char *p)
+{
+ union
+ {
+ uint32_t u4;
+ unsigned char c[4];
+ } d;
+ bool other_byte_order = dbg->other_byte_order;
+
+ if (file_byte_order (other_byte_order) == __BIG_ENDIAN)
+ {
+ d.c[0] = 0x00;
+ d.c[1] = p[0];
+ d.c[2] = p[1];
+ d.c[3] = p[2];
+ }
+ else
+ {
+ d.c[0] = p[0];
+ d.c[1] = p[1];
+ d.c[2] = p[2];
+ d.c[3] = 0x00;
+ }
+
+ if (other_byte_order)
+ return bswap_32 (d.u4);
+ else
+ return d.u4;
+}
+
#define read_addr_unaligned_inc(Nbytes, Dbg, Addr) \
(assert ((Nbytes) == 4 || (Nbytes) == 8), \