summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve MacLean <Steve.MacLean@Microsoft.com>2020-05-20 22:48:41 -0400
committerSteve MacLean <Steve.MacLean@Microsoft.com>2020-05-20 22:48:41 -0400
commita52e5e7cb7948e536eca6c29bfa0d56f57576575 (patch)
tree22144db3b50b546a5ea77db7d79c12804af4920f
parent52c6488da816857de4c782bc5217defdb4c0bea3 (diff)
downloadlibunwind-a52e5e7cb7948e536eca6c29bfa0d56f57576575.tar.gz
Fix MSVC UNW_REMOTE_ONLY compilation errors
Fix errors observed while compiling libunwind for UNW_REMOTE_ONLY, library src, amd64 & aarch64 with an amd64 MSVC compile, and arm with an x86 MSVC compiler Use standard compliant variadic macros GNUC offer non-compliant variadic macros Switch to standrds compiant variadic macros Replace non-standard statement expression GNUC statement expression is non-ISO C compliant Where a simple inline function will be equivalent, use that instead Gexpr.c support compilers w/o statement expressions For this case a simple inline function would change semantics Make a close approximation with a separate set of macros for non GNUC Fix UNW_REMOTE_ONLY placement Exclude function call not required for remote only builds Fix __attribute__((packed)) On MSVC use pragma pack() Add THREAD_LOCAL macro Avoid bare use of __thread Add MSVC fetch_and_add() support Use macro ALIGNED(x) in place of __attribute__((aligned(x)) Rename local ltoa to avoid name collision The Windows x86 SDK headers define ltoa. Rename this local function to avoid a name collision. ISO C doesn't allow empty structures Add padding to allow empty arm/aarch64 structures to compile on MSVC
-rw-r--r--include/compiler.h16
-rw-r--r--include/dwarf-eh.h10
-rw-r--r--include/libunwind-aarch64.h10
-rw-r--r--include/libunwind-arm.h6
-rw-r--r--include/libunwind_i.h11
-rw-r--r--include/tdep-aarch64/libunwind_i.h10
-rw-r--r--include/tdep-arm/libunwind_i.h10
-rw-r--r--include/tdep-x86_64/libunwind_i.h10
-rw-r--r--src/aarch64/Gtrace.c4
-rw-r--r--src/arm/Gtrace.c4
-rw-r--r--src/dwarf/Gexpr.c43
-rw-r--r--src/os-linux.h4
-rw-r--r--src/x86_64/Gglobal.c2
-rw-r--r--src/x86_64/Ginit.c4
-rw-r--r--src/x86_64/Gtrace.c4
15 files changed, 124 insertions, 24 deletions
diff --git a/include/compiler.h b/include/compiler.h
index 2fa59eff..3100be09 100644
--- a/include/compiler.h
+++ b/include/compiler.h
@@ -30,6 +30,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#ifndef COMPILER_H
#define COMPILER_H
+#if defined(__STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L // C11
+# include <thread.h>
+# define THREAD_LOCAL thread_local
+#elseif defined(__GNUC__)
+# define THREAD_LOCAL __thread
+#else
+# define THREAD_LOCAL
+#endif
+
#ifdef __GNUC__
# define ALIGNED(x) __attribute__((aligned(x)))
# define CONST_ATTR __attribute__((__const__))
@@ -67,6 +76,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# define unlikely(x) (x)
#endif
+#ifdef _MSC_VER
+#include <inttypes.h>
+uint32_t fetch_and_add(uint32_t* ptr, uint32_t value);
+# define fetch_and_add1(_ptr) fetch_and_add(_ptr, 1)
+# define HAVE_FETCH_AND_ADD
+#endif
+
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
#endif /* COMPILER_H */
diff --git a/include/dwarf-eh.h b/include/dwarf-eh.h
index 96002a1b..f48e9190 100644
--- a/include/dwarf-eh.h
+++ b/include/dwarf-eh.h
@@ -107,6 +107,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define DW_EH_VERSION 1 /* The version we're implementing */
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#define __attribute__(x)
+#endif
+
struct __attribute__((packed)) dwarf_eh_frame_hdr
{
unsigned char version;
@@ -126,4 +131,9 @@ struct __attribute__((packed)) dwarf_eh_frame_hdr
binary_search_table[fde_count]; */
};
+#ifdef _MSC_VER
+#pragma pack(pop)
+#undef __attribute__
+#endif
+
#endif /* dwarf_eh_h */
diff --git a/include/libunwind-aarch64.h b/include/libunwind-aarch64.h
index 2716afcc..2463d00c 100644
--- a/include/libunwind-aarch64.h
+++ b/include/libunwind-aarch64.h
@@ -34,6 +34,11 @@ extern "C" {
#include <inttypes.h>
#include <stddef.h>
#include <ucontext.h>
+#include "compiler.h"
+
+#ifndef UNW_EMPTY_STRUCT
+# define UNW_EMPTY_STRUCT
+#endif
#define UNW_TARGET aarch64
#define UNW_TARGET_AARCH64 1
@@ -60,6 +65,7 @@ typedef long double unw_tdep_fpreg_t;
typedef struct
{
/* no aarch64-specific auxiliary proc-info */
+ UNW_EMPTY_STRUCT
}
unw_tdep_proc_info_t;
@@ -169,10 +175,10 @@ aarch64_regnum_t;
typedef struct unw_tdep_save_loc
{
/* Additional target-dependent info on a save location. */
+ UNW_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
-
/* On AArch64, we can directly use ucontext_t as the unwind context,
* however, the __reserved struct is quite large: tune it down to only
* the necessary used fields. */
@@ -184,7 +190,7 @@ struct unw_sigcontext
uint64_t sp;
uint64_t pc;
uint64_t pstate;
- uint8_t __reserved[(66 * 8)] __attribute__((__aligned__(16)));
+ uint8_t __reserved[(66 * 8)] ALIGNED(16);
};
typedef struct
diff --git a/include/libunwind-arm.h b/include/libunwind-arm.h
index 6709b7ab..ea14577b 100644
--- a/include/libunwind-arm.h
+++ b/include/libunwind-arm.h
@@ -32,6 +32,10 @@ extern "C" {
#include <inttypes.h>
#include <stddef.h>
+#ifndef UNW_EMPTY_STRUCT
+# define UNW_EMPTY_STRUCT
+#endif
+
#define UNW_TARGET arm
#define UNW_TARGET_ARM 1
@@ -247,6 +251,7 @@ arm_regnum_t;
typedef struct unw_tdep_save_loc
{
/* Additional target-dependent info on a save location. */
+ UNW_EMPTY_STRUCT
}
unw_tdep_save_loc_t;
@@ -288,6 +293,7 @@ unw_tdep_context_t;
typedef struct
{
/* no arm-specific auxiliary proc-info */
+ UNW_EMPTY_STRUCT
}
unw_tdep_proc_info_t;
diff --git a/include/libunwind_i.h b/include/libunwind_i.h
index e0f45401..3eecab72 100644
--- a/include/libunwind_i.h
+++ b/include/libunwind_i.h
@@ -275,7 +275,7 @@ extern pthread_mutex_t _U_dyn_info_list_lock;
extern long unwi_debug_level;
# include <stdio.h>
-# define Debug(level,format...) \
+# define Debug(level, /* format */ ...) \
do { \
if (unwi_debug_level >= level) \
{ \
@@ -283,13 +283,14 @@ do { \
if (_n > 16) \
_n = 16; \
fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
- fprintf (stderr, format); \
+ fprintf (stderr, /* format */ __VA_ARGS__); \
} \
} while (0)
-# define Dprintf(format...) fprintf (stderr, format)
+# define Dprintf(/* format */ ...) \
+ fprintf (stderr, /* format */ __VA_ARGS__)
#else
-# define Debug(level,format...)
-# define Dprintf(format...)
+# define Debug(level, /* format */ ...)
+# define Dprintf( /* format */ ...)
#endif
static ALWAYS_INLINE int
diff --git a/include/tdep-aarch64/libunwind_i.h b/include/tdep-aarch64/libunwind_i.h
index b91273fa..6996b98b 100644
--- a/include/tdep-aarch64/libunwind_i.h
+++ b/include/tdep-aarch64/libunwind_i.h
@@ -160,8 +160,14 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
# define DWARF_LOC_TYPE_FP (1 << 0)
# define DWARF_LOC_TYPE_REG (1 << 1)
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
-# define DWARF_IS_NULL_LOC(l) \
- ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+
+static inline int
+dwarf_is_null_loc(dwarf_loc_t l)
+{
+ return l.val == 0 && l.type == 0;
+}
+
+# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index 2602f41c..19ae4c30 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -151,8 +151,14 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
# define DWARF_LOC_TYPE_FP (1 << 0)
# define DWARF_LOC_TYPE_REG (1 << 1)
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
-# define DWARF_IS_NULL_LOC(l) \
- ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+
+static inline int
+dwarf_is_null_loc(dwarf_loc_t l)
+{
+ return l.val == 0 && l.type == 0;
+}
+
+# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) })
# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0)
# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0)
diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h
index 6b798c71..ddfd7da1 100644
--- a/include/tdep-x86_64/libunwind_i.h
+++ b/include/tdep-x86_64/libunwind_i.h
@@ -130,8 +130,14 @@ dwarf_get_uc(const struct dwarf_cursor *cursor)
#else /* !UNW_LOCAL_ONLY */
# define DWARF_NULL_LOC DWARF_LOC (0, 0)
-# define DWARF_IS_NULL_LOC(l) \
- ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
+
+static inline int
+dwarf_is_null_loc(dwarf_loc_t l)
+{
+ return l.val == 0 && l.type == 0;
+}
+
+# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l)
# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \
| DWARF_LOC_TYPE_FP))
diff --git a/src/aarch64/Gtrace.c b/src/aarch64/Gtrace.c
index c67faf0e..2f8c3f8d 100644
--- a/src/aarch64/Gtrace.c
+++ b/src/aarch64/Gtrace.c
@@ -52,8 +52,8 @@ static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
static sig_atomic_t trace_cache_once_happen;
static pthread_key_t trace_cache_key;
static struct mempool trace_cache_pool;
-static __thread unw_trace_cache_t *tls_cache;
-static __thread int tls_cache_destroyed;
+static THREAD_LOCAL unw_trace_cache_t *tls_cache;
+static THREAD_LOCAL int tls_cache_destroyed;
/* Free memory for a thread's trace cache. */
static void
diff --git a/src/arm/Gtrace.c b/src/arm/Gtrace.c
index 2f277520..7ed320cc 100644
--- a/src/arm/Gtrace.c
+++ b/src/arm/Gtrace.c
@@ -52,8 +52,8 @@ static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
static sig_atomic_t trace_cache_once_happen;
static pthread_key_t trace_cache_key;
static struct mempool trace_cache_pool;
-static __thread unw_trace_cache_t *tls_cache;
-static __thread int tls_cache_destroyed;
+static THREAD_LOCAL unw_trace_cache_t *tls_cache;
+static THREAD_LOCAL int tls_cache_destroyed;
/* Free memory for a thread's trace cache. */
static void
diff --git a/src/dwarf/Gexpr.c b/src/dwarf/Gexpr.c
index 2af45433..830fd14c 100644
--- a/src/dwarf/Gexpr.c
+++ b/src/dwarf/Gexpr.c
@@ -251,6 +251,7 @@ dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t stack_val, unw_word_t *addr,
uint32_t u32;
uint64_t u64;
int ret;
+#ifdef __GNUC__
# define pop() \
({ \
if ((tos - 1) >= MAX_EXPR_STACK_SIZE) \
@@ -280,6 +281,48 @@ do { \
} \
stack[_index]; \
})
+#else // __GNUC__
+// We don't have non-standard statement expressions
+// Use multiple statements instead
+int stackerror = 0;
+
+// pop() is either followed by a semicolon or
+// used in a push() macro
+// In either case we can sneak in an extra statement
+# define pop() \
+(((tos - 1) >= MAX_EXPR_STACK_SIZE) ? \
+ stackerror++ : stack[--tos]); \
+if (stackerror) \
+ { \
+ Debug (1, "Stack underflow\n"); \
+ return -UNW_EINVAL; \
+ }
+
+// Removed the parentheses on the asignment
+// to allow the extra stack error check
+// when x is evaluated
+# define push(x) \
+do { \
+ unw_word_t _x = x; \
+ if (tos >= MAX_EXPR_STACK_SIZE) \
+ { \
+ Debug (1, "Stack overflow\n"); \
+ return -UNW_EINVAL; \
+ } \
+ stack[tos++] = _x; \
+} while (0)
+
+// Pick is always used in a push() macro
+// In either case we can sneak in an extra statement
+# define pick(n) \
+(((tos - 1 - (n)) >= MAX_EXPR_STACK_SIZE) ? \
+ stackerror++ : stack[tos - 1 - (n)]); \
+if (stackerror) \
+ { \
+ Debug (1, "Out-of-stack pick\n"); \
+ return -UNW_EINVAL; \
+ }
+#endif // __GNUC__
as = c->as;
arg = c->as_arg;
diff --git a/src/os-linux.h b/src/os-linux.h
index 3976b38c..5a9b0b40 100644
--- a/src/os-linux.h
+++ b/src/os-linux.h
@@ -38,7 +38,7 @@ struct map_iterator
};
static inline char *
-ltoa (char *buf, long val)
+unw_ltoa (char *buf, long val)
{
char *cp = buf, tmp;
ssize_t i, len;
@@ -68,7 +68,7 @@ maps_init (struct map_iterator *mi, pid_t pid)
char path[sizeof ("/proc/0123456789/maps")], *cp;
memcpy (path, "/proc/", 6);
- cp = ltoa (path + 6, pid);
+ cp = unw_ltoa (path + 6, pid);
assert (cp + 6 < path + sizeof (path));
memcpy (cp, "/maps", 6);
diff --git a/src/x86_64/Gglobal.c b/src/x86_64/Gglobal.c
index 9a7b1957..73ba02e3 100644
--- a/src/x86_64/Gglobal.c
+++ b/src/x86_64/Gglobal.c
@@ -96,9 +96,9 @@ tdep_init (void)
dwarf_init ();
+#ifndef UNW_REMOTE_ONLY
tdep_init_mem_validate ();
-#ifndef UNW_REMOTE_ONLY
x86_64_local_addr_space_init ();
#endif
fetch_and_add1(&tdep_init_done); /* signal that we're initialized... */
diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c
index fd8d418b..81c663c1 100644
--- a/src/x86_64/Ginit.c
+++ b/src/x86_64/Ginit.c
@@ -205,8 +205,8 @@ tdep_init_mem_validate (void)
#define NLGA 4
#if defined(HAVE___THREAD) && HAVE___THREAD
// thread-local variant
-static __thread unw_word_t last_good_addr[NLGA];
-static __thread int lga_victim;
+static THREAD_LOCAL unw_word_t last_good_addr[NLGA];
+static THREAD_LOCAL int lga_victim;
static int
is_cached_valid_mem(unw_word_t addr)
diff --git a/src/x86_64/Gtrace.c b/src/x86_64/Gtrace.c
index 824527f9..7be10a00 100644
--- a/src/x86_64/Gtrace.c
+++ b/src/x86_64/Gtrace.c
@@ -50,8 +50,8 @@ static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT;
static sig_atomic_t trace_cache_once_happen;
static pthread_key_t trace_cache_key;
static struct mempool trace_cache_pool;
-static __thread unw_trace_cache_t *tls_cache;
-static __thread int tls_cache_destroyed;
+static THREAD_LOCAL unw_trace_cache_t *tls_cache;
+static THREAD_LOCAL int tls_cache_destroyed;
/* Free memory for a thread's trace cache. */
static void