TCF Agent: get_reg_definitions may return NULL when context proxy is used
diff --git a/agent/machine/a64/tcf/stack-crawl-a64.c b/agent/machine/a64/tcf/stack-crawl-a64.c
index 46aeea8..506d21b 100644
--- a/agent/machine/a64/tcf/stack-crawl-a64.c
+++ b/agent/machine/a64/tcf/stack-crawl-a64.c
@@ -1156,6 +1156,11 @@
     int interrupt_handler = 0;
     unsigned i;
 
+    if (defs == NULL) {
+        set_errno(ERR_OTHER, "Context has no registers");
+        return -1;
+    }
+
     stk_ctx = frame->ctx;
     stk_frame = frame;
     memset(&mem_data, 0, sizeof(mem_data));
diff --git a/agent/machine/arm/tcf/cpudefs-mdep.c b/agent/machine/arm/tcf/cpudefs-mdep.c
index 9330f21..cefe28c 100644
--- a/agent/machine/arm/tcf/cpudefs-mdep.c
+++ b/agent/machine/arm/tcf/cpudefs-mdep.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013-2019 Stanislav Yakovlev and others.
+ * Copyright (c) 2013-2020 Stanislav Yakovlev and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -258,7 +258,7 @@
                 cr |= 0x1 << 22;
                 cr |= 0xf << 5;
             }
-            cr |= 0x7u;
+            cr |= 0x7;
             if (ptrace(PTRACE_SETHBPREGS, pid, 1, &vr) < 0) return -1;
         }
         else if (cb != NULL) {
diff --git a/agent/machine/arm/tcf/stack-crawl-arm.c b/agent/machine/arm/tcf/stack-crawl-arm.c
index 35f6264..83ecfc4 100644
--- a/agent/machine/arm/tcf/stack-crawl-arm.c
+++ b/agent/machine/arm/tcf/stack-crawl-arm.c
@@ -2475,6 +2475,11 @@
     for (i = 0; i < MEM_CACHE_SIZE; i++) mem_cache[i].size = 0;
 #endif
 
+    if (defs == NULL) {
+        set_errno(ERR_OTHER, "Context has no registers");
+        return -1;
+    }
+
     stk_ctx = frame->ctx;
     stk_frame = frame;
     memset(&reg_data, 0, sizeof(reg_data));
diff --git a/agent/machine/microblaze/tcf/stack-crawl-microblaze.c b/agent/machine/microblaze/tcf/stack-crawl-microblaze.c
index e3fa571..aa15622 100644
--- a/agent/machine/microblaze/tcf/stack-crawl-microblaze.c
+++ b/agent/machine/microblaze/tcf/stack-crawl-microblaze.c
@@ -1103,6 +1103,7 @@
 }
 
 int crawl_stack_frame_microblaze(StackFrame * frame, StackFrame * down) {
+    RegisterDefinition * defs = get_reg_definitions(frame->ctx);
     RegisterDefinition * def = NULL;
     uint64_t pc = 0;
 
@@ -1111,6 +1112,11 @@
     for (i = 0; i < MEM_CACHE_SIZE; i++) mem_cache[i].size = 0;
 #endif
 
+    if (defs == NULL) {
+        set_errno(ERR_OTHER, "Context has no registers");
+        return -1;
+    }
+
     reg_size = 4;
     stk_ctx = frame->ctx;
     memset(&reg_data, 0, sizeof(reg_data));
@@ -1118,7 +1124,7 @@
     branch_pos = 0;
     branch_cnt = 0;
 
-    for (def = get_reg_definitions(stk_ctx); def->name; def++) {
+    for (def = defs; def->name; def++) {
         if (def->dwarf_id == 0) reg_size = def->size;
         if (def->dwarf_id < 0 || def->dwarf_id >= REG_DATA_SIZE) continue;
         if (read_reg_value(frame, def, &reg_data[def->dwarf_id].v) < 0) continue;
@@ -1129,7 +1135,7 @@
 
     if (trace_instructions() < 0) return -1;
 
-    for (def = get_reg_definitions(stk_ctx); def->name; def++) {
+    for (def = defs; def->name; def++) {
         if (def->dwarf_id < 0 || def->dwarf_id >= REG_DATA_SIZE) continue;
         if (chk_loaded(def->dwarf_id) < 0) continue;
         if (!reg_data[def->dwarf_id].o) continue;
diff --git a/agent/machine/riscv/tcf/stack-crawl-riscv.c b/agent/machine/riscv/tcf/stack-crawl-riscv.c
index 026888a..6b3ec82 100644
--- a/agent/machine/riscv/tcf/stack-crawl-riscv.c
+++ b/agent/machine/riscv/tcf/stack-crawl-riscv.c
@@ -1380,6 +1380,11 @@
     RegisterDefinition * def = NULL;
     unsigned i;
 
+    if (defs == NULL) {
+        set_errno(ERR_OTHER, "Context has no registers");
+        return -1;
+    }
+
     stk_ctx = frame->ctx;
     stk_frame = frame;
     memset(&mem_data, 0, sizeof(mem_data));
diff --git a/agent/system/GNU/Linux/tcf/context-linux.c b/agent/system/GNU/Linux/tcf/context-linux.c
index e42511c..51692b1 100644
--- a/agent/system/GNU/Linux/tcf/context-linux.c
+++ b/agent/system/GNU/Linux/tcf/context-linux.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -397,12 +397,14 @@
 
     if (error) {
         RegisterDefinition * def = get_reg_definitions(ctx);
-        while (def->name != NULL && (def->offset > i || def->offset + def->size <= i)) def++;
-        if (error != ESRCH || !EXT(ctx->parent)->sigkill_posted) {
-            trace(LOG_ALWAYS, "error: writing register %s failed: ctx %#" PRIxPTR ", id %s, error %d %s",
-                def->name ? def->name : "?", (uintptr_t)ctx, ctx->id, error, errno_to_str(error));
+        if (def != NULL) {
+            while (def->name != NULL && (def->offset > i || def->offset + def->size <= i)) def++;
+            if (error != ESRCH || !EXT(ctx->parent)->sigkill_posted) {
+                trace(LOG_ALWAYS, "error: writing register %s failed: ctx %#" PRIxPTR ", id %s, error %d %s",
+                    def->name ? def->name : "?", (uintptr_t)ctx, ctx->id, error, errno_to_str(error));
+            }
+            if (def->name) error = set_fmt_errno(error, "Cannot write register %s", def->name);
         }
-        if (def->name) error = set_fmt_errno(error, "Cannot write register %s", def->name);
         errno = error;
         return -1;
     }
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index 0615739..8db5a72 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -242,6 +242,7 @@
 
 int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) {
     const char * ctx_id = NULL;
+    RegisterDefinition * defs = NULL;
     unsigned reg_num = 0;
 
     *ctx = NULL;
@@ -258,7 +259,12 @@
         errno = ERR_ALREADY_EXITED;
         return -1;
     }
-    *reg_def = get_reg_definitions(*ctx) + reg_num;
+    defs = get_reg_definitions(*ctx);
+    if (defs == NULL) {
+        set_errno(ERR_OTHER, "Context has no registers");
+        return -1;
+    }
+    *reg_def = defs + reg_num;
     return 0;
 }
 
diff --git a/agent/tcf/main/gdb-rsp.c b/agent/tcf/main/gdb-rsp.c
index 49c8b97..92442f1 100644
--- a/agent/tcf/main/gdb-rsp.c
+++ b/agent/tcf/main/gdb-rsp.c
@@ -328,6 +328,7 @@
 
     if (r->id >= 0) {
         RegisterDefinition * def = get_reg_definitions(t->ctx);
+        if (def == NULL) return NULL;
         while (def->name != NULL) {
             if (def->dwarf_id == r->id) return def;
             def++;
diff --git a/agent/tcf/services/funccall.c b/agent/tcf/services/funccall.c
index dca820a..a5b3f9a 100644
--- a/agent/tcf/services/funccall.c
+++ b/agent/tcf/services/funccall.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Wind River Systems, Inc. and others.
+ * Copyright (c) 2012-2020 Wind River Systems, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -227,18 +227,20 @@
 
 static void save_registers(void) {
     unsigned cnt = 0;
-    RegisterDefinition * r;
     RegisterDefinition * regs = get_reg_definitions(info->ctx);
-    for (r = regs; r->name != NULL; r++) {
-        if (r->dwarf_id < 0) continue;
-        if (r->size == 0) continue;
-        cnt++;
-    }
-    info->saveregs = (RegisterDefinition **)tmp_alloc(sizeof(RegisterDefinition *) * cnt);
-    for (r = regs; r->name != NULL; r++) {
-        if (r->dwarf_id < 0) continue;
-        if (r->size == 0) continue;
-        info->saveregs[info->saveregs_cnt++] = r;
+    if (regs != NULL) {
+        RegisterDefinition * r;
+        for (r = regs; r->name != NULL; r++) {
+            if (r->dwarf_id < 0) continue;
+            if (r->size == 0) continue;
+            cnt++;
+        }
+        info->saveregs = (RegisterDefinition **)tmp_alloc(sizeof(RegisterDefinition *) * cnt);
+        for (r = regs; r->name != NULL; r++) {
+            if (r->dwarf_id < 0) continue;
+            if (r->size == 0) continue;
+            info->saveregs[info->saveregs_cnt++] = r;
+        }
     }
     assert(info->saveregs_cnt == cnt);
 }
diff --git a/agent/tcf/services/stacktrace.c b/agent/tcf/services/stacktrace.c
index ef4622c..687898f 100644
--- a/agent/tcf/services/stacktrace.c
+++ b/agent/tcf/services/stacktrace.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007-2017 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -153,7 +153,7 @@
                     StackFrame * prev = stk->frames + stk->frame_cnt - 1;
                     down->ctx = ctx;
                     down->fp = frame->fp;
-                    while (def->name != NULL) {
+                    while (def && def->name) {
                         if (def->dwarf_id >= 0) {
 #if ENABLE_StackRegisterLocations
                             cmd.args.reg = def;
@@ -269,7 +269,7 @@
             uint64_t v;
             RegisterDefinition * def;
             trace(LOG_STACK, "Frame %d", stack->frame_cnt - 1);
-            for (def = get_reg_definitions(ctx); def && def->name != NULL; def++) {
+            for (def = get_reg_definitions(ctx); def && def->name; def++) {
                 if (def->no_read || def->read_once || def->bits || !def->size) continue;
                 if (read_reg_value(frame, def, &v) != 0) continue;
                 trace(LOG_STACK, "  %-8s %16" PRIx64, def->name, v);
@@ -308,7 +308,7 @@
             uint8_t * buf0 = (uint8_t *)tmp_alloc(buf_size);
             uint8_t * buf1 = (uint8_t *)tmp_alloc(buf_size);
             RegisterDefinition * def;
-            for (def = get_reg_definitions(ctx); def->name != NULL; def++) {
+            for (def = get_reg_definitions(ctx); def && def->name; def++) {
                 int f0, f1;
                 if (buf_size < def->size) {
                     buf_size = def->size;