Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/agent/tcf
diff options
context:
space:
mode:
Diffstat (limited to 'agent/tcf')
-rw-r--r--agent/tcf/config.h2
-rw-r--r--agent/tcf/framework/channel_tcp.c3
-rw-r--r--agent/tcf/framework/context.c12
-rw-r--r--agent/tcf/framework/cpudefs-ext.h4
-rw-r--r--agent/tcf/framework/cpudefs.c103
-rw-r--r--agent/tcf/framework/cpudefs.h34
-rw-r--r--agent/tcf/framework/errors.c35
-rw-r--r--agent/tcf/framework/events.c2
-rw-r--r--agent/tcf/framework/inputbuf.c9
-rw-r--r--agent/tcf/framework/json.c5
-rw-r--r--agent/tcf/framework/mdep-inet.h4
-rw-r--r--agent/tcf/framework/mdep.c158
-rw-r--r--agent/tcf/framework/mdep.h23
-rw-r--r--agent/tcf/framework/myalloc.c47
-rw-r--r--agent/tcf/framework/tcf.h4
-rw-r--r--agent/tcf/framework/trace.c2
-rw-r--r--agent/tcf/framework/trace.h1
-rw-r--r--agent/tcf/framework/waitpid.c12
-rw-r--r--agent/tcf/framework/waitpid.h6
-rw-r--r--agent/tcf/http/http-tcf.c6
-rw-r--r--agent/tcf/http/http-tcf.h3
-rw-r--r--agent/tcf/http/http.c25
-rw-r--r--agent/tcf/http/http.h3
-rw-r--r--agent/tcf/main/gdb-rsp.c104
-rw-r--r--agent/tcf/main/logfilter.c8
-rw-r--r--agent/tcf/main/main.c2
-rw-r--r--agent/tcf/main/main_lua.c6
-rw-r--r--agent/tcf/main/tcf-agent.spec2
-rw-r--r--agent/tcf/services/breakpoints.c192
-rw-r--r--agent/tcf/services/breakpoints.h12
-rw-r--r--agent/tcf/services/disassembly.c2
-rw-r--r--agent/tcf/services/dprintf.c4
-rw-r--r--agent/tcf/services/dwarf.h135
-rw-r--r--agent/tcf/services/dwarfcache.c599
-rw-r--r--agent/tcf/services/dwarfcache.h79
-rw-r--r--agent/tcf/services/dwarfecomp.c191
-rw-r--r--agent/tcf/services/dwarfexpr.c214
-rw-r--r--agent/tcf/services/dwarfframe.c40
-rw-r--r--agent/tcf/services/dwarfio.c612
-rw-r--r--agent/tcf/services/dwarfio.h27
-rw-r--r--agent/tcf/services/elf-symbols.h4
-rw-r--r--agent/tcf/services/expressions.c120
-rw-r--r--agent/tcf/services/filesystem.c2
-rw-r--r--agent/tcf/services/linenumbers_elf.c26
-rw-r--r--agent/tcf/services/pathmap.c64
-rw-r--r--agent/tcf/services/pathmap.h7
-rw-r--r--agent/tcf/services/processes.c8
-rw-r--r--agent/tcf/services/registers.c7
-rw-r--r--agent/tcf/services/runctrl.c121
-rw-r--r--agent/tcf/services/stacktrace-ext.h15
-rw-r--r--agent/tcf/services/stacktrace.c96
-rw-r--r--agent/tcf/services/symbols.c35
-rw-r--r--agent/tcf/services/symbols.h15
-rw-r--r--agent/tcf/services/symbols_elf.c448
-rw-r--r--agent/tcf/services/symbols_proxy.c69
-rw-r--r--agent/tcf/services/sysmon.c2
-rw-r--r--agent/tcf/services/tcf_elf.c63
-rw-r--r--agent/tcf/services/tcf_elf.h14
-rw-r--r--agent/tcf/services/vm.c291
59 files changed, 3084 insertions, 1055 deletions
diff --git a/agent/tcf/config.h b/agent/tcf/config.h
index 2353d2ec..640f028a 100644
--- a/agent/tcf/config.h
+++ b/agent/tcf/config.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 20018 Xilinx, Inc. and others.
+ * Copyright (c) 2018-2020 Xilinx, 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.
diff --git a/agent/tcf/framework/channel_tcp.c b/agent/tcf/framework/channel_tcp.c
index 70d30abe..02807a2d 100644
--- a/agent/tcf/framework/channel_tcp.c
+++ b/agent/tcf/framework/channel_tcp.c
@@ -39,7 +39,7 @@
# include <openssl/rand.h>
# include <openssl/err.h>
# if defined(_WIN32) || defined(__CYGWIN__)
-# include <ShlObj.h>
+# include <shlobj.h>
# endif
#else
typedef void SSL;
@@ -1545,6 +1545,7 @@ void channel_tcp_connect(PeerServer * ps, ChannelConnectCallBack callback, void
info->sock = -1;
for (res = reslist; res != NULL; res = res->ai_next) {
info->addr_len = res->ai_addrlen;
+ if (info->addr_buf != NULL) loc_free(info->addr_buf);
info->addr_buf = (struct sockaddr *)loc_alloc(res->ai_addrlen);
memcpy(info->addr_buf, res->ai_addr, res->ai_addrlen);
info->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
diff --git a/agent/tcf/framework/context.c b/agent/tcf/framework/context.c
index 2472fffe..64baf7cd 100644
--- a/agent/tcf/framework/context.c
+++ b/agent/tcf/framework/context.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2016 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -52,7 +52,7 @@ const char * REASON_ERROR = "Error";
char * pid2id(pid_t pid, pid_t parent) {
static char s[64];
char * p = s + sizeof(s);
- unsigned long n = (long)pid;
+ uint64_t n = pid;
*(--p) = 0;
do {
*(--p) = (char)(n % 10 + '0');
@@ -60,7 +60,7 @@ char * pid2id(pid_t pid, pid_t parent) {
}
while (n != 0);
if (parent != 0) {
- n = (long)parent;
+ n = parent;
*(--p) = '.';
do {
*(--p) = (char)(n % 10 + '0');
@@ -74,7 +74,7 @@ char * pid2id(pid_t pid, pid_t parent) {
pid_t id2pid(const char * id, pid_t * parent) {
/* TODO: (pid_t)0 is valid value in Windows, should use (pid_t)-1 to indicate an error */
- pid_t pid = 0;
+ uint64_t pid = 0;
if (parent != NULL) *parent = 0;
if (id == NULL) return 0;
if (*id++ != 'P') return 0;
@@ -82,7 +82,7 @@ pid_t id2pid(const char * id, pid_t * parent) {
pid = pid * 10 + (*id++ - '0');
}
if (*id == '.') {
- if (parent != NULL) *parent = pid;
+ if (parent != NULL) *parent = (pid_t)pid;
id++;
pid = 0;
while (*id >= '0' && *id <= '9') {
@@ -90,7 +90,7 @@ pid_t id2pid(const char * id, pid_t * parent) {
}
}
if (*id != 0) return 0;
- return pid;
+ return (pid_t)pid;
}
void add_context_event_listener(ContextEventListener * listener, void * client_data) {
diff --git a/agent/tcf/framework/cpudefs-ext.h b/agent/tcf/framework/cpudefs-ext.h
index b63a4214..20bc46ff 100644
--- a/agent/tcf/framework/cpudefs-ext.h
+++ b/agent/tcf/framework/cpudefs-ext.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -114,7 +114,7 @@ int read_reg_bytes(StackFrame * frame, RegisterDefinition * reg_def, unsigned of
uint8_t * m_addr = (uint8_t *)&((SysRegisterData *)frame->regs)->mask + reg_def->offset;
for (i = 0; i < size; i++) {
if (m_addr[offs + i] != 0xff) {
- set_fmt_errno(ERR_OTHER, "Value of register %s is unknown in the selected frame", reg_def->name);
+ set_fmt_errno(ERR_OTHER, "Value of register %s is unknown in frame %d", reg_def->name, frame->frame);
return -1;
}
}
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index 8db5a72f..fec3cacb 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -33,6 +33,15 @@
#include <tcf/framework/cpudefs-ext.h>
+typedef struct ContextExtensionRegisters {
+ unsigned reg_seq;
+ unsigned reg_cnt;
+} ContextExtensionRegisters;
+
+static unsigned reg_defs_seq = 1;
+static size_t context_extension_offset = 0;
+#define EXT(ctx) ((ContextExtensionRegisters *)((char *)(ctx) + context_extension_offset))
+
void create_reg_children_refs(RegisterDefinition * defs) {
#if ENABLE_RegisterChildrenRefs
RegisterDefinition * r = NULL;
@@ -196,10 +205,27 @@ const char * frame2id(Context * ctx, int frame) {
return tmp_printf("FP%d.%s", frame, ctx->id);
}
+static void update_reg_cnt(Context * ctx, RegisterDefinition * defs) {
+ ContextExtensionRegisters * ext = EXT(ctx);
+ assert(reg_defs_seq != 0);
+ if (ext->reg_seq != reg_defs_seq) {
+ ext->reg_cnt = 0;
+ if (defs != NULL) {
+ while (defs->name != NULL) {
+ ext->reg_cnt++;
+ defs++;
+ }
+ }
+ ext->reg_seq = reg_defs_seq;
+ }
+}
+
const char * register2id(Context * ctx, int frame, RegisterDefinition * reg) {
RegisterDefinition * defs = get_reg_definitions(ctx);
+ update_reg_cnt(ctx, defs);
assert(defs != NULL);
assert(reg >= defs);
+ assert(reg < defs + EXT(ctx)->reg_cnt);
if (frame < 0) return tmp_printf("R%d.%s", (int)(reg - defs), ctx->id);
return tmp_printf("R%d@%d.%s", (int)(reg - defs), frame, ctx->id);
}
@@ -209,7 +235,7 @@ int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * re
*frame = STACK_TOP_FRAME;
*reg_num = 0;
if (*id++ != 'R') {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
while (*id != '.' && *id != '@') {
@@ -217,7 +243,7 @@ int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * re
*reg_num = *reg_num * 10 + (*id++ - '0');
}
else {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
}
@@ -229,7 +255,7 @@ int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * re
n = n * 10 + (*id++ - '0');
}
else {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
}
@@ -248,7 +274,10 @@ int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition
*ctx = NULL;
*reg_def = NULL;
- if (id2reg_num(id, &ctx_id, frame, &reg_num) < 0) return -1;
+ if (id2reg_num(id, &ctx_id, frame, &reg_num) < 0) {
+ if (errno == ERR_OTHER) set_errno(errno, "Malformed register ID");
+ return -1;
+ }
*ctx = id2ctx(ctx_id);
if (*ctx == NULL) {
@@ -264,10 +293,20 @@ int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition
set_errno(ERR_OTHER, "Context has no registers");
return -1;
}
+ update_reg_cnt(*ctx, defs);
+ if (reg_num >= EXT(*ctx)->reg_cnt) {
+ set_errno(ERR_OTHER, "Invalid register ID");
+ return -1;
+ }
*reg_def = defs + reg_num;
return 0;
}
+void invalidate_register_ids(void) {
+ do reg_defs_seq++;
+ while (reg_defs_seq == 0);
+}
+
static void location_expression_error(void) {
str_exception(ERR_OTHER, "Invalid location expression");
}
@@ -526,7 +565,8 @@ LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame
}
else {
stk_pos--;
- piece->addr = (ContextAddress)stk[stk_pos];
+ piece->addr = (ContextAddress)stk[stk_pos] + piece->bit_offs / 8;
+ piece->bit_offs %= 8;
}
}
break;
@@ -550,7 +590,7 @@ LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame
#define bit_mask(n) (1u << (big_endian ? 7 - (n) % 8 : (n) % 8))
-void read_location_pieces(Context * ctx, StackFrame * frame,
+void read_location_pieces_local(Context * ctx, StackFrame * frame, void * loc_buf, size_t loc_size,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void ** value, size_t * size) {
/* Note: 'big_endian' should match endianness of LocationPiece.value in 'pieces' */
@@ -562,7 +602,22 @@ void read_location_pieces(Context * ctx, StackFrame * frame,
unsigned i = 0;
while (i < pieces_cnt) {
LocationPiece * piece = pieces + i++;
- bf_bits += piece->bit_size ? piece->bit_size : piece->size * 8;
+ if (piece->optimized_away) {
+ str_exception(ERR_OTHER, "Cannot get symbol value: optimized away");
+ }
+ else if (piece->implicit_pointer) {
+ if (piece->implicit_pointer == 1 &&
+ piece->reg == NULL && piece->value == NULL &&
+ piece->bit_offs == 0 && piece->bit_size == 0) {
+ bf_bits += context_word_size(ctx) * 8;
+ }
+ else {
+ str_exception(ERR_OTHER, "Cannot get symbol value: implicit pointer");
+ }
+ }
+ else {
+ bf_bits += piece->bit_size ? piece->bit_size : piece->size * 8;
+ }
}
bf_size = (size_t)((bf_bits + 7) / 8);
bf = (uint8_t *)tmp_alloc_zero(bf_size);
@@ -573,15 +628,16 @@ void read_location_pieces(Context * ctx, StackFrame * frame,
unsigned piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
uint8_t * pbf = NULL;
uint8_t * rbf = NULL;
- if (piece->optimized_away) {
- set_errno(ERR_OTHER, "Cannot get symbol value: optimized away");
- exception(errno);
- }
if (piece->implicit_pointer) {
- set_errno(ERR_OTHER, "Cannot get symbol value: implicit pointer");
- exception(errno);
+ piece_size = context_word_size(ctx);
+ piece_bits = piece_size * 8;
+ pbf = (uint8_t *)tmp_alloc(piece_size);
+ rbf = (uint8_t *)&piece->addr;
+ if (sizeof(piece->addr) > piece_size && big_endian_host()) rbf += sizeof(piece->addr) - piece_size;
+ memcpy(pbf, rbf, piece_size);
+ if (!big_endian_host() != !big_endian) swap_bytes(pbf, piece_size);
}
- if (piece->reg) {
+ else if (piece->reg) {
if (piece->reg->size < piece_size) {
rbf = pbf = (uint8_t *)tmp_alloc_zero(piece_size);
if (big_endian) rbf += piece_size - piece->reg->size;
@@ -602,7 +658,15 @@ void read_location_pieces(Context * ctx, StackFrame * frame,
}
else {
pbf = (uint8_t *)tmp_alloc(piece_size);
- if (context_read_mem(ctx, piece->addr, pbf, piece_size) < 0) exception(errno);
+ if (loc_buf == NULL) {
+ if (context_read_mem(ctx, piece->addr, pbf, piece_size) < 0) exception(errno);
+ }
+ else {
+ if (piece->addr + piece_size > loc_size) {
+ str_exception(ERR_OTHER, "Cannot get symbol value: invalid location expression");
+ }
+ memcpy(pbf, (uint8_t *)loc_buf + piece->addr, piece_size);
+ }
}
for (i = piece->bit_offs; i < piece->bit_offs + piece_bits; i++) {
if (pbf[i / 8] & bit_mask(i)) bf[bf_offs / 8] |= bit_mask(bf_offs);
@@ -614,6 +678,12 @@ void read_location_pieces(Context * ctx, StackFrame * frame,
*size = bf_size;
}
+void read_location_pieces(Context * ctx, StackFrame * frame,
+ LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
+ void ** value, size_t * size) {
+ read_location_pieces_local(ctx, frame, NULL, 0, pieces, pieces_cnt, big_endian, value, size);
+}
+
void write_location_pieces(Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void * value, size_t size) {
@@ -739,6 +809,7 @@ void ini_cpu_disassembler(Context * cpu) {
}
void ini_cpudefs(void) {
+ context_extension_offset = context_extension(sizeof(ContextExtensionRegisters));
#if defined(ENABLE_ini_cpudefs_mdep) && ENABLE_ini_cpudefs_mdep
ini_cpudefs_mdep();
#endif
diff --git a/agent/tcf/framework/cpudefs.h b/agent/tcf/framework/cpudefs.h
index a11a1342..35edc913 100644
--- a/agent/tcf/framework/cpudefs.h
+++ b/agent/tcf/framework/cpudefs.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -66,16 +66,16 @@ struct RegisterDefinition {
size_t size; /* register size in bytes */
int16_t dwarf_id; /* ID of the register in DWARF sections, or -1 */
int16_t eh_frame_id; /* ID of the register in .eh_frame section, or -1 */
- uint8_t big_endian; /* 0 - little endian, 1 - big endian */
- uint8_t fp_value; /* true if the register value is a floating-point value */
- uint8_t no_read; /* true if context value can not be read */
- uint8_t no_write; /* true if context value can not be written */
- uint8_t read_once; /* true if reading the context (register) destroys its current value */
- uint8_t write_once; /* true if register value can not be overwritten - every write counts */
- uint8_t side_effects; /* true if writing the context can change values of other registers */
- uint8_t volatile_value;/* true if the register value can change even when target is stopped */
- uint8_t left_to_right; /* true if the lowest numbered bit should be shown to user as the left-most bit */
- int first_bit; /* bit numbering base (0 or 1) to use when showing bits to user */
+ unsigned big_endian : 1; /* 0 - little endian, 1 - big endian */
+ unsigned fp_value : 1; /* true if the register value is a floating-point value */
+ unsigned no_read : 1; /* true if context value can not be read */
+ unsigned no_write : 1; /* true if context value can not be written */
+ unsigned read_once : 1; /* true if reading the context (register) destroys its current value */
+ unsigned write_once : 1; /* true if register value can not be overwritten - every write counts */
+ unsigned side_effects : 1; /* true if writing the context can change values of other registers */
+ unsigned volatile_value : 1; /* true if the register value can change even when target is stopped */
+ unsigned left_to_right : 1; /* true if the lowest numbered bit should be shown to user as the left-most bit */
+ unsigned first_bit : 1; /* bit numbering base (0 or 1) to use when showing bits to user */
int * bits; /* if context is a bit field, contains the field bit numbers in the parent register definition, -1 marks end of the list */
RegisterDefinition * parent; /* parent register definition, NULL for top level definitions */
NamedRegisterValue ** values; /* predefined names (mnemonics) for some of register values */
@@ -282,7 +282,7 @@ extern int write_reg_location(StackFrame * frame, RegisterDefinition * reg_def,
#endif
/* Get instruction pointer (PC) value.
-* Deprecated: use get_PC() */
+ * Deprecated: use get_PC() */
extern ContextAddress get_regs_PC(Context * ctx);
/* Set instruction pointer (PC) value.
@@ -308,6 +308,10 @@ extern const char * register2id(Context * ctx, int frame, RegisterDefinition * r
extern int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * reg_num);
extern int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def);
+/* Invalidate register IDs.
+ * This function is called by the RunControl service when register definitions change. */
+extern void invalidate_register_ids(void);
+
/* Get breakpoint instruction code and size.
* Return NULL if the context does not support software breakpoints. */
extern uint8_t * get_break_instruction(Context * ctx, size_t * size);
@@ -336,6 +340,12 @@ extern void read_location_pieces(
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
void ** value, size_t * size);
+extern void read_location_pieces_local(
+ Context * ctx, StackFrame * frame,
+ void * loc_buf, size_t loc_size,
+ LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
+ void ** value, size_t * size);
+
extern void write_location_pieces(
Context * ctx, StackFrame * frame,
LocationPiece * pieces, unsigned pieces_cnt, int big_endian,
diff --git a/agent/tcf/framework/errors.c b/agent/tcf/framework/errors.c
index 641346cd..753599db 100644
--- a/agent/tcf/framework/errors.c
+++ b/agent/tcf/framework/errors.c
@@ -67,7 +67,7 @@ typedef struct ErrorMessage {
} ErrorMessage;
static ErrorMessage msgs[MESSAGE_CNT];
-static int msgs_pos = 0;
+static unsigned msgs_pos = 0;
static char * msg_buf = NULL;
static size_t msg_buf_max = 0;
@@ -162,7 +162,7 @@ int set_nt_status_errno(DWORD status) {
int error = 0;
assert(is_dispatch_thread());
if (status != 0) {
- HMODULE module = LoadLibrary("NTDLL.DLL");
+ HMODULE module = LoadLibrarySystem32("NTDLL.DLL");
char * msg = system_strerror(status, module);
error = set_errno(ERR_OTHER, msg);
FreeLibrary(module);
@@ -392,34 +392,35 @@ const char * errno_to_str(int err) {
int set_errno(int no, const char * msg) {
errno = no;
- if (no != 0 && msg != NULL) {
+ if (no != 0 && msg != NULL && *msg != 0) {
ErrorMessage * m = alloc_msg(SRC_MESSAGE);
/* alloc_msg() assigns new value to 'errno',
* need to be sure it does not change until this function exits.
*/
int err = errno;
- m->error = get_error_code(no);
if (no == ERR_OTHER) {
m->text = loc_strdup(msg);
+ m->error = ERR_OTHER;
+ }
+ else if (no == err) {
+ /* Overflow of error message buffer */
+ m->text = loc_strdup2(msg, "...");
+ m->error = ERR_OTHER;
}
else {
size_t msg_len = strlen(msg);
- if (msg_len == 0) {
- m->text = loc_strdup(errno_to_str(no));
+ const char * str = errno_to_str(no);
+ if (msg[msg_len - 1] == '.' || msg[msg_len - 1] == '\n') {
+ size_t len = msg_len + strlen(str) + 2;
+ m->text = (char *)loc_alloc(len);
+ snprintf(m->text, len, "%s %s", msg, str);
}
else {
- const char * str = errno_to_str(no);
- if (msg[msg_len - 1] == '.' || msg[msg_len - 1] == '\n') {
- size_t len = msg_len + strlen(str) + 2;
- m->text = (char *)loc_alloc(len);
- snprintf(m->text, len, "%s %s", msg, str);
- }
- else {
- size_t len = msg_len + strlen(str) + 3;
- m->text = (char *)loc_alloc(len);
- snprintf(m->text, len, "%s. %s", msg, str);
- }
+ size_t len = msg_len + strlen(str) + 3;
+ m->text = (char *)loc_alloc(len);
+ snprintf(m->text, len, "%s. %s", msg, str);
}
+ m->error = get_error_code(no);
}
errno = err;
}
diff --git a/agent/tcf/framework/events.c b/agent/tcf/framework/events.c
index 3a35fde7..12f0b5c4 100644
--- a/agent/tcf/framework/events.c
+++ b/agent/tcf/framework/events.c
@@ -227,7 +227,7 @@ void post_event_with_delay(EventCallBack * handler, void * arg, unsigned long de
}
check_error(pthread_mutex_unlock(&event_lock));
- trace(LOG_EVENTCORE, "post_event: event %#" PRIxPTR ", handler %#" PRIxPTR ", arg %#" PRIxPTR ", runtime %02u%02u.%03u",
+ trace(LOG_EVENTCORE, "post_event: event %#" PRIxPTR ", handler %#" PRIxPTR ", arg %#" PRIxPTR ", runtime %02u:%02u.%03u",
(uintptr_t)ev, (uintptr_t)ev->handler, (uintptr_t)ev->arg,
(unsigned)(ev->runtime.tv_sec / 60 % 60),
(unsigned)(ev->runtime.tv_sec % 60),
diff --git a/agent/tcf/framework/inputbuf.c b/agent/tcf/framework/inputbuf.c
index 2ba5efb3..3901e993 100644
--- a/agent/tcf/framework/inputbuf.c
+++ b/agent/tcf/framework/inputbuf.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -49,6 +49,7 @@ static void ibuf_eof(InputBuf * ibuf) {
}
static size_t ibuf_free_size(InputBuf * ibuf) {
+ assert(ibuf->stream->cur <= ibuf->stream->end);
if (ibuf->eof) return 0;
if (ibuf->stream->cur == ibuf->buf + ibuf->buf_size) {
assert(ibuf->stream->cur == ibuf->stream->end);
@@ -67,7 +68,7 @@ void ibuf_trigger_read(InputBuf * ibuf) {
size_t size = ibuf_free_size(ibuf);
if (size > 0) {
assert(ibuf->inp + size <= ibuf->buf + ibuf->buf_size);
- assert(ibuf->inp + size <= ibuf->stream->cur || ibuf->inp >= ibuf->stream->end);
+ assert(ibuf->inp + size < ibuf->stream->cur || ibuf->inp >= ibuf->stream->end);
ibuf->post_read(ibuf, ibuf->inp, size);
}
}
@@ -87,7 +88,8 @@ int ibuf_get_more(InputBuf * ibuf, int peeking) {
if (out == ibuf->inp) {
/* No data available */
assert(ibuf->long_msg || ibuf->eof);
- inp->cur = out;
+ /* Note: async read may be running, don't change ibuf->inp */
+ inp->cur = inp->end = out;
if (ibuf->eof) return MARKER_EOS;
assert(ibuf->message_count == 1);
ibuf_trigger_read(ibuf);
@@ -173,7 +175,6 @@ int ibuf_get_more(InputBuf * ibuf, int peeking) {
while (out != max && *out != ESC) out++;
inp->end = out;
if (!peeking) inp->cur++;
- assert(inp->cur <= inp->end);
ibuf_trigger_read(ibuf);
return ch;
}
diff --git a/agent/tcf/framework/json.c b/agent/tcf/framework/json.c
index 04e6f6c0..c0d35531 100644
--- a/agent/tcf/framework/json.c
+++ b/agent/tcf/framework/json.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -59,7 +59,7 @@
#define ENCODING_BASE64 1
#define read_no_whitespace(ch, inp) do { int _c_ = read_stream(inp); \
- while (_c_ > 0 && isspace(_c_)) _c_ = read_stream(inp); (ch) = _c_; } while (0)
+ while (_c_ > 0 && isspace(_c_)) { _c_ = read_stream(inp); } (ch) = _c_; } while (0)
#define skip_whitespace(inp) do { int _c_ = peek_stream(inp); \
while (_c_ > 0 && isspace(_c_)) { read_stream(inp); _c_ = peek_stream(inp); } } while (0)
@@ -1114,6 +1114,7 @@ int read_error_object(InputStream * inp) {
err->time_stamp = json_read_uint64(inp);
}
else if (strcmp(name, "Format") == 0) {
+ if (err->format != NULL) loc_free(err->format);
err->format = json_read_alloc_string(inp);
}
else if (strcmp(name, "Params") == 0) {
diff --git a/agent/tcf/framework/mdep-inet.h b/agent/tcf/framework/mdep-inet.h
index 32f4b849..e7688544 100644
--- a/agent/tcf/framework/mdep-inet.h
+++ b/agent/tcf/framework/mdep-inet.h
@@ -30,7 +30,7 @@
#include <cygwin/version.h>
-#if CYGWIN_VERSION_CYGWIN_CONV < 157
+#if defined(CYGWIN_VERSION_CYGWIN_CONV) && CYGWIN_VERSION_CYGWIN_CONV < 157
extern void __stdcall freeaddrinfo(struct addrinfo *);
extern int __stdcall getaddrinfo(const char *, const char *,
@@ -45,7 +45,7 @@ extern const char * loc_gai_strerror(int ecode);
/* inet_ntop()/inet_pton() are not available in MinGW */
/* inet_ntop()/inet_pton() are not available in Windows before Windows Vista */
-#if defined(__MINGW32__) || (defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600)
+#if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) || (defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600)
extern const char * inet_ntop(int af, const void * src, char * dst, socklen_t size);
extern int inet_pton(int af, const char * src, void * dst);
#endif
diff --git a/agent/tcf/framework/mdep.c b/agent/tcf/framework/mdep.c
index 24343c79..148c9b8e 100644
--- a/agent/tcf/framework/mdep.c
+++ b/agent/tcf/framework/mdep.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -264,7 +264,7 @@ int wsa_closesocket(int socket) {
/* inet_ntop()/inet_pton() are not available in MinGW */
/* inet_ntop()/inet_pton() are not available in Windows before Windows Vista */
-#if defined(__MINGW32__) || (defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600)
+#if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) || (defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600)
const char * inet_ntop(int af, const void * src, char * dst, socklen_t size) {
char * str = NULL;
if (af != AF_INET) {
@@ -319,20 +319,41 @@ int clock_gettime(clockid_t clock_id, struct timespec * tp) {
return 0;
}
if (clock_id == CLOCK_MONOTONIC) {
- typedef ULONGLONG (FAR WINAPI * ProcType)(void);
- static ProcType proc = NULL;
+ typedef ULONGLONG (FAR WINAPI * ProcTickType)(void);
+ typedef BOOL (FAR WINAPI * ProcPerfType)(LARGE_INTEGER *);
+ typedef BOOL (FAR WINAPI * ProcFreqType)(LARGE_INTEGER *);
+ static ProcTickType proc_tick = NULL;
+ static ProcPerfType proc_perf = NULL;
+ static LONGLONG perf_freq = 0; /* Hz */
static int chk_done = 0;
ULONGLONG time_ms = 0;
/* GetTickCount() is valid only first 49 days */
- /* GetTickCount64 not available before Windows Vista */
+ /* GetTickCount64() not available before Windows Vista */
+ /* QueryPerformanceCounter() not available before Windows 2000 */
+ /* GetTickCount64() appears delayed 200ms relative to QueryPerformanceCounter() */
if (!chk_done) {
- HMODULE kernel_dll = LoadLibraryA("Kernel32.dll");
+ HMODULE kernel_dll = LoadLibrarySystem32("Kernel32.dll");
if (kernel_dll != NULL) {
- proc = (ProcType)GetProcAddress(kernel_dll, "GetTickCount64");
+ LARGE_INTEGER li;
+ ProcFreqType proc_freq = (ProcFreqType)GetProcAddress(kernel_dll, "QueryPerformanceFrequency");
+ if (proc_freq != NULL && proc_freq(&li)) {
+ proc_perf = (ProcPerfType)GetProcAddress(kernel_dll, "QueryPerformanceCounter");
+ perf_freq = li.QuadPart;
+ }
+ proc_tick = (ProcTickType)GetProcAddress(kernel_dll, "GetTickCount64");
}
chk_done = 1;
}
- time_ms = proc != NULL ? proc() : (ULONGLONG)GetTickCount();
+ if (proc_perf != NULL) {
+ LARGE_INTEGER li;
+ if (proc_perf(&li)) {
+ tp->tv_sec = (time_t)(li.QuadPart / perf_freq);
+ tp->tv_nsec = (long)(li.QuadPart % perf_freq * 1000000000 / perf_freq);
+ assert(tp->tv_nsec < 1000000000);
+ return 0;
+ }
+ }
+ time_ms = proc_tick != NULL ? proc_tick() : (ULONGLONG)GetTickCount();
tp->tv_sec = (time_t)(time_ms / 1000);
tp->tv_nsec = (long)(time_ms % 1000) * 1000000;
return 0;
@@ -662,6 +683,12 @@ void swap_bytes(void * buf, size_t size) {
#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _MSC_VER
+# pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union (in winternl.h) */
+# include <winternl.h>
+#else
+# include <ntdef.h>
+#endif
#if USE_locale
# include <locale.h>
#endif
@@ -692,8 +719,9 @@ const char * get_os_name(void) {
if (info.wProductType == VER_NT_WORKSTATION) return "Windows 7";
return "Windows Server 2008 R2";
case 2:
- if (info.wProductType == VER_NT_WORKSTATION) return "Windows 8";
- return "Windows Server 2012";
+ /* Starting with Windows 8.1, GetVersionEx returns same version number,
+ * which is retrieved from the application manifest, or 6.2 by default. */
+ return "Windows";
}
}
snprintf(str, sizeof(str), "Windows %d.%d", (int)info.dwMajorVersion, (int)info.dwMinorVersion);
@@ -733,11 +761,69 @@ const char * get_user_name(void) {
return a_buf;
}
+#ifndef BCRYPT_RNG_ALGORITHM
+# define BCRYPT_RNG_ALGORITHM L"RNG"
+#endif
+#ifndef PROV_RSA_FULL
+# define PROV_RSA_FULL 1
+#endif
+
+static PVOID crypt_handle = NULL;
+typedef NTSTATUS(FAR WINAPI * BCryptRNGProcType)(PVOID, PUCHAR, ULONG, ULONG);
+typedef BOOL(FAR WINAPI * WinCryptRNGProcType)(PVOID, DWORD, BYTE *);
+static BCryptRNGProcType bcrypt_rng_proc = NULL;
+static WinCryptRNGProcType wincrypt_rng_proc = NULL;
+
+uint32_t rand32(void) {
+ uint32_t buf = 0;
+ if (bcrypt_rng_proc) {
+ if (bcrypt_rng_proc(crypt_handle, (PUCHAR)&buf, sizeof(buf), 0) < 0) {
+ fprintf(stderr, "Couldn't access BCRYPT.\n");
+ exit(1);
+ }
+ return buf;
+ }
+ if (wincrypt_rng_proc) {
+ if (wincrypt_rng_proc(crypt_handle, sizeof(buf), (BYTE *)&buf) < 0) {
+ fprintf(stderr, "Couldn't access WINCRYPT.\n");
+ exit(1);
+ }
+ return buf;
+ }
+ fprintf(stderr, "Couldn't access random number generator.\n");
+ exit(1);
+}
+
void ini_mdep(void) {
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err;
+ if (crypt_handle == NULL) {
+ HMODULE bcrypt_dll = LoadLibrarySystem32("Bcrypt.dll");
+ if (bcrypt_dll != NULL) {
+ typedef NTSTATUS(FAR WINAPI * ProcType)(PVOID *, LPCWSTR, LPCWSTR, ULONG);
+ ProcType proc = (ProcType)GetProcAddress(bcrypt_dll, "BCryptOpenAlgorithmProvider");
+ bcrypt_rng_proc = (BCryptRNGProcType)GetProcAddress(bcrypt_dll, "BCryptGenRandom");
+ if (proc == NULL || bcrypt_rng_proc == NULL || proc(&crypt_handle, BCRYPT_RNG_ALGORITHM, NULL, 0) < 0) {
+ fprintf(stderr, "Couldn't access BCRYPT.\n");
+ exit(1);
+ }
+ }
+ }
+ if (crypt_handle == NULL) {
+ HMODULE advapi_dll = LoadLibrarySystem32("Advapi32.dll");
+ if (advapi_dll != NULL) {
+ typedef BOOL(FAR WINAPI * ProcType)(PVOID *, LPCWSTR, LPCWSTR, DWORD, DWORD);
+ ProcType proc = (ProcType)GetProcAddress(advapi_dll, "CryptAcquireContextA");
+ wincrypt_rng_proc = (WinCryptRNGProcType)GetProcAddress(advapi_dll, "CryptGenRandom");
+ if (proc == NULL || wincrypt_rng_proc == NULL || !proc(&crypt_handle, NULL, NULL, PROV_RSA_FULL, 0)) {
+ fprintf(stderr, "Couldn't call CryptAcquireContext.\n");
+ exit(1);
+ }
+ }
+ }
+
#if USE_locale
setlocale(LC_ALL, "");
#endif
@@ -813,7 +899,15 @@ const char * get_user_name(void) {
return NULL;
}
+uint32_t rand32(void) {
+ /* TODO: should we use randBytes() on vxWorks? */
+ return rand();
+}
+
void ini_mdep(void) {
+ struct timespec time_now;
+ if (clock_gettime(CLOCK_REALTIME, &time_now)) check_error(errno);
+ srand((unsigned)time_now.tv_sec ^ (unsigned)time_now.tv_nsec);
pthread_attr_init(&pthread_create_attr);
#ifndef USE_DEFAULT_THREAD_STACK_SIZE
pthread_attr_setstacksize(&pthread_create_attr, 0x8000);
@@ -848,7 +942,15 @@ const char * get_user_name(void) {
return NULL;
}
+uint32_t rand32(void) {
+ /* TODO: should we use random() on Symbian? */
+ return rand();
+}
+
void ini_mdep(void) {
+ struct timespec time_now;
+ if (clock_gettime(CLOCK_REALTIME, &time_now)) check_error(errno);
+ srand((unsigned)time_now.tv_sec ^ (unsigned)time_now.tv_nsec);
pthread_attr_init(&pthread_create_attr);
}
@@ -977,6 +1079,24 @@ int tkill(pid_t pid, int signal) {
#endif
}
+uint32_t rand32(void) {
+ static int ini = 0;
+ static int crypt_handle = -1;
+ uint32_t buf = 0;
+ if (!ini) {
+ crypt_handle = open("/dev/urandom", O_RDONLY);
+ if (crypt_handle < 0) {
+ struct timespec time_now;
+ if (clock_gettime(CLOCK_REALTIME, &time_now)) check_error(errno);
+ srandom((unsigned)time_now.tv_sec ^ (unsigned)time_now.tv_nsec);
+ }
+ ini = 1;
+ }
+ if (crypt_handle < 0) return random();
+ if (read(crypt_handle, &buf, sizeof(buf)) < 0) check_error(errno);
+ return buf;
+}
+
void ini_mdep(void) {
#if USE_locale
setlocale(LC_ALL, "");
@@ -1314,12 +1434,6 @@ const char * loc_gai_strerror(int ecode) {
#if defined(_WIN32) || defined(__CYGWIN__)
# include <tlhelp32.h>
-# ifdef _MSC_VER
-# pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union (in winternl.h) */
-# include <winternl.h>
-# else
-# include <ntdef.h>
-# endif
# ifndef STATUS_INFO_LENGTH_MISMATCH
# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
# endif
@@ -1876,15 +1990,12 @@ const char * create_uuid(void) {
#else
const char * create_uuid(void) {
- static char buf[40];
struct timespec time_now;
memset(&time_now, 0, sizeof(time_now));
if (clock_gettime(CLOCK_REALTIME, &time_now)) check_error(errno);
- if (buf[0] == 0) srand((unsigned)time_now.tv_sec ^ (unsigned)time_now.tv_nsec);
- snprintf(buf, sizeof(buf), "%08x-%04x-4%03x-8%03x-%04x%04x%04x",
+ return tmp_printf("%08x-%04x-4%03x-8%03x-%04x%04x%04x",
(int)time_now.tv_sec & 0xffffffff, (int)(time_now.tv_nsec >> 13) & 0xffff,
- rand() & 0xfff, rand() & 0xfff, rand() & 0xffff, rand() & 0xffff, rand() & 0xffff);
- return buf;
+ rand32() & 0xfff, rand32() & 0xfff, rand32() & 0xffff, rand32() & 0xffff, rand32() & 0xffff);
}
#endif
@@ -1902,7 +2013,7 @@ int tcf_set_thread_name(const char * name) {
HANDLE thread;
if (!init_done) {
- HMODULE kernel_dll = LoadLibraryA("Kernel32.dll");
+ HMODULE kernel_dll = LoadLibrarySystem32("Kernel32.dll");
if (kernel_dll != NULL) {
set_td = (ProcType)GetProcAddress(kernel_dll, "SetThreadDescription");
if (set_td == NULL) {
@@ -1929,7 +2040,8 @@ int tcf_set_thread_name(const char * name) {
loc_free(w_name);
return error;
-#elif defined(_GNU_SOURCE)
+#elif defined(_GNU_SOURCE) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
+ /* pthread_setname_np was added in glibc 2.12 */
return pthread_setname_np(pthread_self(), name);
#else
return 0;
diff --git a/agent/tcf/framework/mdep.h b/agent/tcf/framework/mdep.h
index f71751bb..f9da3f2f 100644
--- a/agent/tcf/framework/mdep.h
+++ b/agent/tcf/framework/mdep.h
@@ -161,14 +161,20 @@ typedef unsigned long pid_t;
#endif
#endif
-#define CLOCK_REALTIME 1
-#define CLOCK_MONOTONIC 2
+#ifndef CLOCK_REALTIME
+# define CLOCK_REALTIME 1
+#endif
+#ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC 2
+#endif
typedef int clockid_t;
extern int clock_gettime(clockid_t clock_id, struct timespec * tp);
extern void usleep(unsigned useconds);
#define off_t __int64
-#define lseek _lseeki64
+#ifndef lseek
+# define lseek _lseeki64
+#endif
extern int truncate(const char * path, off_t size);
extern int ftruncate(int f, off_t size);
@@ -186,6 +192,12 @@ extern ssize_t pwrite(int fd, const void * buf, size_t size, off_t offset);
#endif /* __CYGWIN__ */
+#if defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
+# define LoadLibrarySystem32(name) LoadLibraryExA(name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32)
+#else
+# define LoadLibrarySystem32(name) LoadLibraryA(name)
+#endif
+
#elif defined(_WRS_KERNEL)
/* VxWork kernel module */
@@ -414,7 +426,7 @@ extern size_t strlcat(char * dst, const char * src, size_t size);
/* Swap bytes in a buffer - change value endianness */
extern void swap_bytes(void * buf, size_t size);
-#if defined(__GNUC__)
+#if defined(__GNUC__) && __GNUC__ >= 5
# define SWAP(x) do { \
switch(sizeof(x)) { \
case 8: x = __builtin_bswap64(x); break; \
@@ -445,6 +457,9 @@ extern const char * get_user_home(void);
/* Get user name as known to the system */
extern const char * get_user_name(void);
+/* Return 32-bit random number */
+extern uint32_t rand32(void);
+
/* Create new UUID - Universally Unique IDentifier */
extern const char * create_uuid(void);
diff --git a/agent/tcf/framework/myalloc.c b/agent/tcf/framework/myalloc.c
index 61f5ac84..3b4478b1 100644
--- a/agent/tcf/framework/myalloc.c
+++ b/agent/tcf/framework/myalloc.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -48,6 +48,8 @@ static LINK tmp_alloc_list = TCF_LIST_INIT(tmp_alloc_list);
static size_t tmp_alloc_size = 0;
static int tmp_gc_posted = 0;
+static char tmp_str_buf[0x10 * MEM_USAGE_FACTOR];
+
static void gc_event(void * args) {
tmp_gc_posted = 0;
tmp_gc();
@@ -61,6 +63,14 @@ void tmp_gc(void) {
else if (tmp_pool_avr > POOL_SIZE / 0x10) {
tmp_pool_avr -= POOL_SIZE / 0x10000;
}
+#endif
+ while (!list_is_empty(&tmp_alloc_list)) {
+ LINK * l = tmp_alloc_list.next;
+ list_remove(l);
+ loc_free(l);
+ }
+ tmp_alloc_size = 0;
+#if ENABLE_FastMemAlloc
if (tmp_pool_max < tmp_pool_avr && tmp_pool_max < POOL_SIZE) {
if (tmp_pool_max < POOL_SIZE / 0x10) tmp_pool_max = POOL_SIZE / 0x10;
while (tmp_pool_max < tmp_pool_avr) tmp_pool_max *= 2;
@@ -73,12 +83,6 @@ void tmp_gc(void) {
}
tmp_pool_pos = sizeof(LINK);
#endif
- while (!list_is_empty(&tmp_alloc_list)) {
- LINK * l = tmp_alloc_list.next;
- list_remove(l);
- loc_free(l);
- }
- tmp_alloc_size = 0;
}
void * tmp_alloc(size_t size) {
@@ -180,15 +184,25 @@ char * tmp_printf(const char * fmt, ...) {
return buf;
}
+static int vsnprintf_apc(char * buf, size_t len, const char * fmt, va_list ap) {
+ int n;
+ /* Some implementations of vsnprintf destructively modifies the passed va_list */
+ /* We need to use va_list multiple times, so make a copy */
+ va_list apc;
+ va_copy(apc, ap);
+ n = vsnprintf(buf, len, fmt, apc);
+ va_end(apc);
+ return n;
+}
+
char * tmp_vprintf(const char * fmt, va_list ap) {
- char arr[0x100];
void * mem = NULL;
- char * buf = arr;
- size_t len = sizeof(arr);
+ char * buf = tmp_str_buf;
+ size_t len = sizeof(tmp_str_buf);
int n;
while (1) {
- n = vsnprintf(buf, len, fmt, ap);
+ n = vsnprintf_apc(buf, len, fmt, ap);
if (n < 0) {
if (len > 0x1000) break;
len *= 2;
@@ -200,7 +214,7 @@ char * tmp_vprintf(const char * fmt, va_list ap) {
mem = tmp_realloc(mem, len);
buf = (char *)mem;
}
- if (buf == arr) buf = tmp_strdup(arr);
+ if (buf == tmp_str_buf) buf = tmp_strdup(tmp_str_buf);
return buf;
}
@@ -285,14 +299,13 @@ char * loc_printf(const char * fmt, ...) {
}
char * loc_vprintf(const char * fmt, va_list ap) {
- char arr[0x100];
void * mem = NULL;
- char * buf = arr;
- size_t len = sizeof(arr);
+ char * buf = tmp_str_buf;
+ size_t len = sizeof(tmp_str_buf);
int n;
while (1) {
- n = vsnprintf(buf, len, fmt, ap);
+ n = vsnprintf_apc(buf, len, fmt, ap);
if (n < 0) {
if (len > 0x1000) break;
len *= 2;
@@ -304,6 +317,6 @@ char * loc_vprintf(const char * fmt, va_list ap) {
mem = loc_realloc(mem, len);
buf = (char *)mem;
}
- if (buf == arr) buf = loc_strdup(arr);
+ if (buf == tmp_str_buf) buf = loc_strdup(tmp_str_buf);
return buf;
}
diff --git a/agent/tcf/framework/tcf.h b/agent/tcf/framework/tcf.h
index 61c58dd8..26d3fd50 100644
--- a/agent/tcf/framework/tcf.h
+++ b/agent/tcf/framework/tcf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 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.
@@ -17,7 +17,7 @@
#define D_tcf
#define _TCF_VERSION_MAJOR 1
-#define _TCF_VERSION_MINOR 7
+#define _TCF_VERSION_MINOR 8
#define _TCF_VERSION (_TCF_VERSION_MAJOR * 100 + _TCF_VERSION_MINOR)
#endif
diff --git a/agent/tcf/framework/trace.c b/agent/tcf/framework/trace.c
index bb1aa70e..be3ddbe6 100644
--- a/agent/tcf/framework/trace.c
+++ b/agent/tcf/framework/trace.c
@@ -56,7 +56,6 @@ struct trace_mode trace_mode_table[MAX_TRACE_MODES + 1] = {
{ LOG_PROXY, "proxy", "proxy state" },
{ LOG_TCFLOG, "tcflog", "proxy traffic" },
{ LOG_ELF, "elf", "ELF reader" },
- { LOG_LUA, "lua", "LUA interpreter" },
{ LOG_STACK, "stack", "stack trace service" },
{ LOG_PLUGIN, "plugin", "plugins" },
{ LOG_SHUTDOWN, "shutdown", "shutdown of subsystems" },
@@ -182,6 +181,7 @@ int add_trace_mode(int mode, const char * name, const char * description) {
void open_log_file(const char * log_name) {
#if ENABLE_Trace
+ use_syslog = 0;
if (log_name == NULL) {
log_file = NULL;
}
diff --git a/agent/tcf/framework/trace.h b/agent/tcf/framework/trace.h
index 1b3ca5df..8ada41d8 100644
--- a/agent/tcf/framework/trace.h
+++ b/agent/tcf/framework/trace.h
@@ -37,7 +37,6 @@
#define LOG_PROXY 0x200
#define LOG_TCFLOG 0x400
#define LOG_ELF 0x800
-#define LOG_LUA 0x1000
#define LOG_STACK 0x2000
#define LOG_PLUGIN 0x4000
#define LOG_SHUTDOWN 0x8000
diff --git a/agent/tcf/framework/waitpid.c b/agent/tcf/framework/waitpid.c
index b7bd0708..3fe0a945 100644
--- a/agent/tcf/framework/waitpid.c
+++ b/agent/tcf/framework/waitpid.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2009-2022 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.
@@ -105,7 +105,7 @@ static void init(void) {
semaphore = CreateSemaphore(NULL, 1, 1, NULL);
}
-void add_waitpid_process(int pid) {
+void add_waitpid_process(pid_t pid) {
HANDLE prs = NULL;
WaitPIDThread * thread = threads;
assert(listener_cnt > 0);
@@ -133,7 +133,7 @@ void detach_waitpid_process(void) {
#include <taskHookLib.h>
typedef struct EventInfo {
- UINT32 pid;
+ pid_t pid;
SEM_ID signal;
} EventInfo;
@@ -153,7 +153,7 @@ static void task_delete_hook(WIND_TCB * tcb) {
EventInfo info;
VX_COUNTING_SEMAPHORE(signal_mem);
info.signal = semCInitialize(signal_mem, SEM_Q_FIFO, 0);
- info.pid = (UINT32)tcb;
+ info.pid = tcb;
post_event(task_delete_event, &info);
semTake(info.signal, WAIT_FOREVER);
semTerminate(info.signal);
@@ -165,7 +165,7 @@ static void init(void) {
taskDeleteHookAdd((FUNCPTR)task_delete_hook);
}
-void add_waitpid_process(int pid) {
+void add_waitpid_process(pid_t pid) {
}
void detach_waitpid_process(void) {
@@ -236,7 +236,7 @@ static void waitpid_done(void * arg) {
}
}
-void add_waitpid_process(int pid) {
+void add_waitpid_process(pid_t pid) {
AsyncReqInfo * req = (AsyncReqInfo *)loc_alloc_zero(sizeof(AsyncReqInfo));
assert(listener_cnt > 0);
trace(LOG_WAITPID, "waitpid: add pid %d", pid);
diff --git a/agent/tcf/framework/waitpid.h b/agent/tcf/framework/waitpid.h
index c82ed6a7..5627c01e 100644
--- a/agent/tcf/framework/waitpid.h
+++ b/agent/tcf/framework/waitpid.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2011 Wind River Systems, Inc. and others.
+ * Copyright (c) 2009-2022 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.
@@ -24,11 +24,11 @@
#if (ENABLE_DebugContext && !ENABLE_ContextProxy) || SERVICE_Processes || SERVICE_Terminals
-typedef void WaitPIDListener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args);
+typedef void WaitPIDListener(pid_t pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args);
extern void add_waitpid_listener(WaitPIDListener * listener, void * args);
-extern void add_waitpid_process(int pid);
+extern void add_waitpid_process(pid_t pid);
extern void detach_waitpid_process(void);
diff --git a/agent/tcf/http/http-tcf.c b/agent/tcf/http/http-tcf.c
index 34504ba3..21f6b962 100644
--- a/agent/tcf/http/http-tcf.c
+++ b/agent/tcf/http/http-tcf.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018-2019 Xilinx, Inc. and others.
+ * Copyright (c) 2018-2022 Xilinx, 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.
@@ -711,7 +711,7 @@ static int get_page(const char * uri) {
return 0;
}
-void http_connection_closed(OutputStream * out) {
+static void http_connection_closed(OutputStream * out) {
LINK * l;
for (l = link_clients.next; l != &link_clients; l = l->next) {
ClientData * cd = all2client(l);
@@ -730,7 +730,7 @@ void http_connection_closed(OutputStream * out) {
}
ChannelServer * ini_http_tcf(int sock, PeerServer * ps) {
- static HttpListener l = { get_page };
+ static HttpListener l = { get_page, http_connection_closed };
assert(list_is_empty(&server.servlink));
add_http_listener(&l);
server_sock = sock;
diff --git a/agent/tcf/http/http-tcf.h b/agent/tcf/http/http-tcf.h
index d15abe34..fbc751bb 100644
--- a/agent/tcf/http/http-tcf.h
+++ b/agent/tcf/http/http-tcf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018 Xilinx, Inc. and others.
+ * Copyright (c) 2018-2022 Xilinx, 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.
@@ -24,7 +24,6 @@
#include <tcf/framework/channel.h>
-extern void http_connection_closed(OutputStream * out);
extern ChannelServer * ini_http_tcf(int sock, PeerServer * ps);
#endif /* D_http_tcf */
diff --git a/agent/tcf/http/http.c b/agent/tcf/http/http.c
index 37dfbc8c..66b5a90d 100644
--- a/agent/tcf/http/http.c
+++ b/agent/tcf/http/http.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018-2019 Xilinx, Inc. and others.
+ * Copyright (c) 2018-2022 Xilinx, 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.
@@ -26,7 +26,7 @@
#include <stdarg.h>
#include <assert.h>
#if defined(_WIN32) || defined(__CYGWIN__)
-# include <ShlObj.h>
+# include <shlobj.h>
#endif
#include <tcf/framework/trace.h>
#include <tcf/framework/errors.h>
@@ -144,9 +144,12 @@ static void clear_connection_state(HttpConnection * con) {
}
static void close_connection(HttpConnection * con) {
+ unsigned i;
assert(!con->read_posted);
assert(!con->write_posted);
- http_connection_closed(&con->out.out);
+ for (i = 0; i < listener_cnt; i++) {
+ if (listener_arr[i]->closed) listener_arr[i]->closed(&con->out.out);
+ }
clear_connection_state(con);
closesocket(con->sock);
list_remove(&con->link_all);
@@ -295,11 +298,21 @@ static void http_send_done(void * x) {
}
static void send_reply(HttpConnection * con) {
- unsigned i;
current_con = con;
create_byte_array_output_stream(&con->out);
- for (i = listener_cnt; i > 0; i--) {
- if (listener_arr[i - 1]->get_page(con->http_uri)) break;
+ if (con->http_method == NULL || con->http_uri == NULL) {
+ http_response_status(400, "BAD REQUEST");
+ http_printf("Bad request: syntax error\n");
+ }
+ else if (strcmp(con->http_method, "GET") != 0) {
+ http_response_status(400, "BAD REQUEST");
+ http_printf("Bad request method: %s\n", con->http_method);
+ }
+ else {
+ unsigned i;
+ for (i = listener_cnt; i > 0; i--) {
+ if (listener_arr[i - 1]->get_page && listener_arr[i - 1]->get_page(con->http_uri)) break;
+ }
}
if (con->suspended) {
current_con = NULL;
diff --git a/agent/tcf/http/http.h b/agent/tcf/http/http.h
index 6dd04e31..64166a91 100644
--- a/agent/tcf/http/http.h
+++ b/agent/tcf/http/http.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018-2019 Xilinx, Inc. and others.
+ * Copyright (c) 2018-2022 Xilinx, 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.
@@ -49,6 +49,7 @@ extern void http_close(void);
typedef struct HttpListener {
int (*get_page)(const char * uri);
+ void (*closed)(OutputStream * out);
} HttpListener;
extern void add_http_listener(HttpListener * l);
diff --git a/agent/tcf/main/gdb-rsp.c b/agent/tcf/main/gdb-rsp.c
index 5335deb2..9c4fcad6 100644
--- a/agent/tcf/main/gdb-rsp.c
+++ b/agent/tcf/main/gdb-rsp.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016-2020 Xilinx, Inc. and others.
+ * Copyright (c) 2016-2022 Xilinx, 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.
@@ -60,7 +60,7 @@
# define DEBUG_RSP 0
#endif
-#define ID_ANY ~0u
+#define ID_ALL ~0u
typedef struct GdbServer {
LINK link_a2s;
@@ -78,7 +78,7 @@ typedef struct GdbClient {
uint8_t * buf;
AsyncReqInfo req;
GdbServer * server;
- ClientConnection client;
+ ClientConnection connection;
int closed;
/* Command packet */
@@ -161,7 +161,7 @@ typedef struct MonitorCommand {
#define link_p2t(x) ((GdbThread *)((char *)(x) - offsetof(GdbThread, link_p2t)))
#define link_p2b(x) ((GdbBreakpoint *)((char *)(x) - offsetof(GdbBreakpoint, link_p2b)))
-#define client2gdb(c) ((GdbClient *)((char *)(c) - offsetof(GdbClient, client)))
+#define client2gdb(c) ((GdbClient *)((char *)(c) - offsetof(GdbClient, connection)))
static int ini_done = 0;
static LINK link_a2s;
@@ -321,9 +321,18 @@ static unsigned reg_name_hash(const char * name) {
return h;
}
-static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
+static RegisterDefinition * find_register_by_name(GdbThread * t, const char * name) {
RegisterDefinition ** map = t->regs_nm_map;
- unsigned n = 0;
+ unsigned n = reg_name_hash(name) & t->regs_nm_map_index_mask;
+ while (map[n] != NULL) {
+ if (strcmp(map[n]->name, name) == 0) return map[n];
+ n = (n + 1) & t->regs_nm_map_index_mask;
+ }
+ return NULL;
+}
+
+static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
+ RegisterDefinition * res = NULL;
if (r->id >= 0) {
RegisterDefinition * def = get_reg_definitions(t->ctx);
@@ -334,9 +343,10 @@ static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
}
return NULL;
}
- if (map == NULL) {
+ if (t->regs_nm_map == NULL) {
unsigned map_len = 0;
unsigned map_len_p2 = 1;
+ RegisterDefinition ** map = NULL;
RegisterDefinition * def = get_reg_definitions(t->ctx);
if (def == NULL) return NULL;
while (def->name != NULL) {
@@ -356,12 +366,31 @@ static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
}
t->regs_nm_map = map;
}
- n = reg_name_hash(r->name) & t->regs_nm_map_index_mask;
- while (map[n] != NULL) {
- if (strcmp(map[n]->name, r->name) == 0) return map[n];
- n = (n + 1) & t->regs_nm_map_index_mask;
+ res = find_register_by_name(t, r->name);
+ if (res == NULL) {
+ const char * regs = get_regs(t->process->client);
+ /* Try alternative register names */
+ if (regs == cpu_regs_gdb_i386 || regs == cpu_regs_gdb_x86_64) {
+ static const char * alt_names[] = {
+ "fctrl", "control", "fpcr", "cwd", NULL,
+ "fstat", "status", "fpsr", "swd", NULL,
+ "ftag", "tag", "fptag", "twd", NULL,
+ "fiseg", "fcs", NULL,
+ "fioff", "fip", NULL,
+ "foseg", "fos", NULL,
+ "fooff", "foo", NULL,
+ NULL
+ };
+ unsigned i = 0;
+ for (; alt_names[i] != NULL && res == NULL; i++) {
+ int b = strcmp(alt_names[i++], r->name) == 0;
+ for (; alt_names[i] != NULL && res == NULL; i++) {
+ if (b) res = find_register_by_name(t, alt_names[i]);
+ }
+ }
+ }
}
- return NULL;
+ return res;
}
static int open_server(const char * port) {
@@ -534,11 +563,11 @@ static void close_client(GdbClient * c) {
c->closed = 1;
unlock_threads(c);
closesocket(c->req.u.sio.sock);
- notify_client_disconnected(&c->client);
+ notify_client_disconnected(&c->connection);
}
}
-static void dispose_client(ClientConnection * cc) {
+static void dispose_connection(ClientConnection * cc) {
GdbClient * c = client2gdb(cc);
GdbServer * s = c->server;
@@ -817,28 +846,41 @@ static void get_cmd_ptid(GdbClient * c, char ** pp, unsigned * res_pid, unsigned
s++;
}
tid = get_cmd_uint(c, &s);
+ /*
+ ID is a positive number with target-specific interpretation formatted as a big-endian hex string,
+ or literal '-1' to indicate all processes or threads (respectively),
+ or '0' to indicate an arbitrary process (keep current selection if any)
+ */
if (neg_pid) {
- pid = ID_ANY;
+ pid = ID_ALL;
}
else if (pid == 0) {
- LINK * l;
- pid = 0;
- for (l = c->link_c2p.next; l != &c->link_c2p; l = l->next) {
- GdbProcess * p = link_c2p(l);
- if (p->attached) {
- pid = p->pid;
- break;
+ if (find_process_pid(c, *res_pid)) {
+ pid = *res_pid;
+ }
+ else {
+ LINK * l;
+ for (l = c->link_c2p.next; l != &c->link_c2p; l = l->next) {
+ GdbProcess * p = link_c2p(l);
+ if (p->attached) {
+ pid = p->pid;
+ break;
+ }
}
}
}
- if (neg_tid || pid == ID_ANY) {
- tid = ID_ANY;
+ if (neg_tid || pid == ID_ALL) {
+ tid = ID_ALL;
}
else if (tid == 0) {
- GdbProcess * p = find_process_pid(c, pid);
- tid = 0;
- if (p != NULL && !list_is_empty(&p->link_p2t)) {
- tid = link_p2t(p->link_p2t.next)->tid;
+ if (find_thread(c, pid, *res_tid)) {
+ tid = *res_tid;
+ }
+ else {
+ GdbProcess * p = find_process_pid(c, pid);
+ if (p != NULL && !list_is_empty(&p->link_p2t)) {
+ tid = link_p2t(p->link_p2t.next)->tid;
+ }
}
}
*pp = s;
@@ -1409,7 +1451,7 @@ static int handle_v_command(GdbClient * c) {
s++;
get_cmd_ptid(c, &s, &c->cur_g_pid, &c->cur_g_tid);
}
- if (c->cur_g_tid == ID_ANY) {
+ if (c->cur_g_tid == ID_ALL) {
GdbProcess * p = find_process_pid(c, c->cur_g_pid);
switch (mode) {
case 'c':
@@ -1774,7 +1816,7 @@ static void accept_done(void * args) {
c->req.u.sio.flags = 0;
list_init(&c->link_c2p);
list_add_last(&c->link_s2c, &s->link_s2c);
- c->client.dispose = dispose_client;
+ c->connection.dispose = dispose_connection;
for (l = context_root.next; l != &context_root; l = l->next) {
Context * ctx = ctxl2ctxp(l);
@@ -1787,7 +1829,7 @@ static void accept_done(void * args) {
}
}
- notify_client_connected(&c->client);
+ notify_client_connected(&c->connection);
async_req_post(&s->req);
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt)) < 0) {
diff --git a/agent/tcf/main/logfilter.c b/agent/tcf/main/logfilter.c
index 2ad42a8c..01123c9d 100644
--- a/agent/tcf/main/logfilter.c
+++ b/agent/tcf/main/logfilter.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 Wind River Systems, Inc. and others.
+ * Copyright (c) 2014-2022 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.
@@ -201,10 +201,10 @@ int filter_is_log_filtered(Channel * src, Channel * dst, int argc,
/* Need to store the token and propagate truncation size
* for reply.
*/
- TokenFilter * tf = (TokenFilter *)loc_alloc_zero(
- sizeof(TokenFilter) + strlen(argv[1]));
+ const size_t len = strlen(argv[1]);
+ TokenFilter * tf = (TokenFilter *)loc_alloc_zero(sizeof(TokenFilter) + len);
tf->chan = src;
- strcpy(tf->token, argv[1]);
+ memcpy(tf->token, argv[1], len);
list_add_last(&tf->all, &token_filters);
if (mf->flags & FILTER_LIMIT_REPLY) {
tf->limit = mf->limit;
diff --git a/agent/tcf/main/main.c b/agent/tcf/main/main.c
index bbcfd73f..d9aedc76 100644
--- a/agent/tcf/main/main.c
+++ b/agent/tcf/main/main.c
@@ -476,7 +476,7 @@ int main(int argc, char ** argv) {
for (i = 0; i < url_cnt; i++) {
if (ini_server(url_arr[i], proto, bcg) < 0) {
- fprintf(stderr, "Cannot create listening port: %s\n", errno_to_str(errno));
+ fprintf(stderr, "Cannot create listening port %s: %s\n", url_arr[i], errno_to_str(errno));
exit(1);
}
}
diff --git a/agent/tcf/main/main_lua.c b/agent/tcf/main/main_lua.c
index 95ff7aa0..55545093 100644
--- a/agent/tcf/main/main_lua.c
+++ b/agent/tcf/main/main_lua.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.
@@ -51,7 +51,8 @@ extern "C" {
#include <tcf/main/framework.h>
static const char * progname;
-static lua_State *luastate;
+static lua_State * luastate;
+static int LOG_LUA = 0;
struct luaref {
int ref;
@@ -1418,6 +1419,7 @@ int main(int argc, char ** argv) {
#else
+ LOG_LUA = add_trace_mode(0, "lua", "LUA interpreter");
progname = argv[0];
/* Parse arguments */
diff --git a/agent/tcf/main/tcf-agent.spec b/agent/tcf/main/tcf-agent.spec
index 5166b4d2..e8396bf3 100644
--- a/agent/tcf/main/tcf-agent.spec
+++ b/agent/tcf/main/tcf-agent.spec
@@ -1,5 +1,5 @@
%define name tcf-agent
-%define version 1.7.0
+%define version 1.8.0
%define release 1.%(bin/get-os-tag)
%define make_options CONF=Release PATH_Plugins=/etc/tcf/plugins
diff --git a/agent/tcf/services/breakpoints.c b/agent/tcf/services/breakpoints.c
index a4ba8738..61a07131 100644
--- a/agent/tcf/services/breakpoints.c
+++ b/agent/tcf/services/breakpoints.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 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.
@@ -54,6 +54,8 @@
# define ENABLE_SkipPrologueWhenPlanting 0
#endif
+#define MAX_WP_SIZE 0x10000
+
typedef struct BreakpointRef BreakpointRef;
typedef struct InstructionRef InstructionRef;
typedef struct BreakInstruction BreakInstruction;
@@ -156,6 +158,10 @@ struct BreakInstruction {
size_t bp_size; /* Size of breakpoint instruction */
Context * ph_ctx;
ContextAddress ph_addr;
+ unsigned bit_offs;
+ unsigned bit_size;
+ void * bit_value;
+ void * bit_next;
};
struct EvaluationArgs {
@@ -170,6 +176,7 @@ struct ConditionEvaluationRequest {
BreakInstruction * bi;
int condition_ok;
int triggered;
+ int canceled;
};
struct LocationEvaluationRequest {
@@ -282,11 +289,13 @@ static unsigned id2bp_hash(const char * id) {
}
static unsigned get_bp_access_types(BreakpointInfo * bp, int virtual_addr) {
+ /* Return breakpoint instruction access types for given breakpoint */
char * type = bp->type;
unsigned access_types = bp->access_mode;
if (access_types == 0 && (bp->file != NULL || bp->location != NULL)) access_types |= CTX_BP_ACCESS_INSTRUCTION;
if (virtual_addr && type != NULL && strcmp(type, "Software") == 0) access_types |= CTX_BP_ACCESS_SOFTWARE;
if (virtual_addr) access_types |= CTX_BP_ACCESS_VIRTUAL;
+ access_types &= ~CTX_BP_ACCESS_CHANGE; /* Handled by the service */
return access_types;
}
@@ -520,6 +529,8 @@ static void free_instruction(BreakInstruction * bi) {
release_error_report(bi->planting_error);
release_error_report(bi->condition_error);
loc_free(bi->bp_encoding);
+ loc_free(bi->bit_value);
+ loc_free(bi->bit_next);
loc_free(bi->refs);
loc_free(bi);
}
@@ -554,6 +565,8 @@ static void flush_instructions(void) {
list_init(&lst);
+ assert(list_is_empty(&evaluations_active));
+
/* Validate references */
l = instructions.next;
while (l != &instructions) {
@@ -597,6 +610,7 @@ static void flush_instructions(void) {
/* Hardware resource might be available now, try to re-plant */
list_add_last(&bi->link_lst, &lst);
}
+ if (bi->bit_value != NULL) memcpy(bi->bit_value, bi->bit_next, bi->cb.length);
}
/* Unplant breakpoints */
@@ -1063,6 +1077,7 @@ static void line_offs_check(CodeArea * area, void * x) {
#endif
static void verify_line_offset(BreakInstruction * bi, InstructionRef * ref) {
+#if ENABLE_LineNumbers
ref->line_offs_error = 0;
if (bi->virtual_addr && (bi->cb.access_types & CTX_BP_ACCESS_INSTRUCTION) != 0) {
LineOffsCheckArgs args;
@@ -1081,6 +1096,7 @@ static void verify_line_offset(BreakInstruction * bi, InstructionRef * ref) {
}
}
}
+#endif
}
static void get_bp_opcodes(void) {
@@ -1243,8 +1259,8 @@ static BreakInstruction * address_expression_error(Context * ctx, BreakpointInfo
return link_breakpoint_instruction(bp, ctx, 0, 0, NULL, 0, 0, rp);
}
-static void plant_breakpoint(Context * ctx, BreakpointInfo * bp, ContextAddress addr, ContextAddress size) {
- link_breakpoint_instruction(bp, ctx, addr, size, ctx, 1, addr, NULL);
+static BreakInstruction * plant_breakpoint(Context * ctx, BreakpointInfo * bp, ContextAddress addr, ContextAddress size) {
+ return link_breakpoint_instruction(bp, ctx, addr, size, ctx, 1, addr, NULL);
}
static BreakInstruction ** plant_at_canonical_address(BreakInstruction * v_bi) {
@@ -1293,7 +1309,8 @@ static ConditionEvaluationRequest * add_condition_evaluation_request(
assert(ctx->stopped_by_bp || ctx->stopped_by_cb);
for (i = 0; i < req->bp_cnt; i++) {
- if (req->bp_arr[i].ctx == ctx && req->bp_arr[i].bp == bp && req->bp_arr[i].bi == bi) return NULL;
+ c = req->bp_arr + i;
+ if (c->ctx == ctx && c->bp == bp && c->bi == bi && !c->canceled) return NULL;
}
if (req->bp_max <= req->bp_cnt) {
@@ -1306,6 +1323,7 @@ static ConditionEvaluationRequest * add_condition_evaluation_request(
c->bi = bi;
c->condition_ok = 0;
c->triggered = 0;
+ c->canceled = 0;
return c;
}
@@ -1633,14 +1651,31 @@ static int skip_function_prologue(Context * ctx, Symbol * sym, ContextAddress *
static void plant_at_address_expression(Context * ctx, ContextAddress ip, BreakpointInfo * bp) {
ContextAddress addr = 0;
ContextAddress size = 1;
+ unsigned bit_offs = 0;
+ unsigned bit_size = 0;
+ void * bit_value = NULL;
+ int read_bit_value = 0;
int error = 0;
#if ENABLE_Expressions
Value v;
- memset (&v, 0, sizeof (Value));
+ memset(&v, 0, sizeof(Value));
- if (evaluate_expression(ctx, STACK_NO_FRAME, ip, bp->location, 1, &v) < 0) error = errno;
- if (!error && value_to_address(&v, &addr) < 0) error = errno;
+ if (evaluate_expression(ctx, STACK_NO_FRAME, ip, bp->location, 0, &v) < 0) {
+ error = errno;
+ }
+ else if ((bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) != 0 &&
+ v.sym_list == NULL && v.loc != NULL && v.loc->pieces_cnt == 1 &&
+ v.loc->pieces->implicit_pointer == 1 && v.loc->pieces->optimized_away == 0 &&
+ v.loc->pieces->reg == NULL && v.loc->pieces->value == NULL) {
+ /* Special case: bitfield watchpoint */
+ addr = v.loc->pieces->addr;
+ bit_offs = v.loc->pieces->bit_offs;
+ bit_size = v.loc->pieces->bit_size;
+ }
+ else if (value_to_address(&v, &addr) < 0) {
+ error = errno;
+ }
#if ENABLE_Symbols
if (!error && v.sym != NULL) {
SymbolProperties props;
@@ -1658,6 +1693,18 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp
if (bp->access_size > 0) {
size = bp->access_size;
}
+ else if (bit_size > 0) {
+ unsigned i;
+ for (i = 0; i <= 24; i++) {
+ size = (ContextAddress)1 << i;
+ if ((addr & ~(size - 1)) + size >= addr + (bit_offs + bit_size + 7) / 8) break;
+ }
+ bit_offs += (unsigned)(addr & (size - 1)) * 8;
+ addr &= ~(size - 1);
+ if ((bp->access_mode & CTX_BP_ACCESS_DATA_READ) == 0) {
+ read_bit_value = 1;
+ }
+ }
else if (bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) {
size = context_word_size(ctx);
#if ENABLE_Symbols
@@ -1673,11 +1720,39 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp
}
#endif
}
+ if ((bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) != 0 && (bp->access_mode & CTX_BP_ACCESS_CHANGE) != 0) {
+ read_bit_value = 1;
+ }
+ if (!error && size == 0) error = set_errno(ERR_OTHER, "Invalid breakpoint size: 0");
+ if (!error && read_bit_value) {
+ if (size > MAX_WP_SIZE) {
+ error = set_fmt_errno(ERR_BUFFER_OVERFLOW, "Too large watchpoint size: > 0x%x", MAX_WP_SIZE);
+ }
+ else {
+ bit_value = tmp_alloc_zero(size);
+ if (!error && context_read_mem(ctx, addr, bit_value, size) < 0) error = errno;
+ }
+ }
if (error) {
address_expression_error(ctx, bp, error);
}
else {
- plant_breakpoint(ctx, bp, addr, size);
+ BreakInstruction * bi = plant_breakpoint(ctx, bp, addr, size);
+ assert(bi->cb.length == size);
+ bi->bit_offs = bit_offs;
+ bi->bit_size = bit_size;
+ if (bi->bit_value == NULL && bit_value != NULL) {
+ bi->bit_value = loc_alloc(size);
+ bi->bit_next = loc_alloc(size);
+ memcpy(bi->bit_value, bit_value, size);
+ memcpy(bi->bit_next, bit_value, size);
+ }
+ else if (bi->bit_value != NULL && bit_value == NULL) {
+ loc_free(bi->bit_value);
+ loc_free(bi->bit_next);
+ bi->bit_value = NULL;
+ bi->bit_next = NULL;
+ }
#if ENABLE_Symbols
/* If the expression returns multiple symbols, plant multiple breakpoints */
if (v.sym_list != NULL) {
@@ -1837,6 +1912,7 @@ static void evaluate_condition(void * x) {
BreakpointInfo * bp = ce->bp;
BreakInstruction * bi = ce->bi;
ErrorReport * condition_error = NULL;
+ int condition_ok = 0;
assert(req != NULL);
assert(req->bp_cnt > 0);
@@ -1844,35 +1920,55 @@ static void evaluate_condition(void * x) {
assert(cache_enter_cnt > 0);
assert(args->bp == ce->bp);
- if (!is_disabled(bp)) {
+ if (!ce->canceled && !is_disabled(bp)) {
+ int error = 0;
Context * ctx = ce->ctx;
assert(ctx->stopped);
assert(ctx->stopped_by_bp || ctx->stopped_by_cb);
- if (check_context_ids_condition(bp, ctx)) {
- if (bp->condition != NULL) {
+ if (check_context_ids_condition(bp, ctx)) condition_ok = 1;
+ if (condition_ok && bp->condition != NULL) {
#if ENABLE_Expressions
- Value v;
- int b = 0;
- if (evaluate_expression(ctx, STACK_TOP_FRAME, 0, bp->condition, 1, &v) < 0 ||
- (v.size > 0 && value_to_boolean(&v, &b) < 0)) {
- int error = errno;
- Channel * c = cache_channel();
- if (c == NULL || !is_channel_closed(c)) {
- condition_error = get_error_report(error);
- ce->condition_ok = 1;
- }
- }
- else if (b) {
- ce->condition_ok = 1;
- }
+ Value v;
+ if (evaluate_expression(ctx, STACK_TOP_FRAME, 0, bp->condition, 1, &v) < 0 ||
+ (v.size > 0 && value_to_boolean(&v, &condition_ok) < 0)) {
+ error = errno;
+ }
#endif
+ }
+ if (condition_ok && bi->bit_value != NULL) {
+ unsigned size = (unsigned)bi->cb.length;
+ if (context_read_mem(ctx, bi->cb.address, bi->bit_next, size) < 0) {
+ error = errno;
}
else {
- ce->condition_ok = 1;
+ int changed = 0;
+ if (bi->bit_size == 0) {
+ changed = memcmp(bi->bit_value, bi->bit_next, size) != 0;
+ }
+ else {
+ unsigned i;
+ for (i = bi->bit_offs; i < bi->bit_offs + bi->bit_size; i++) {
+ uint8_t v0 = ((uint8_t *)bi->bit_value)[i / 8];
+ uint8_t v1 = ((uint8_t *)bi->bit_next)[i / 8];
+ if ((v0 & (1 << (i % 8))) != (v1 & (1 << (i % 8)))) {
+ changed = 1;
+ break;
+ }
+ }
+ }
+ if (!changed) condition_ok = 0;
+ }
+ }
+ if (error) {
+ Channel * c = cache_channel();
+ if (c == NULL || !is_channel_closed(c)) {
+ condition_error = get_error_report(error);
+ condition_ok = 1;
}
}
}
+ if (condition_ok) ce->condition_ok = 1;
if (cache_miss_count() > 0 || compare_error_reports(bi->condition_error, condition_error)) {
release_error_report(condition_error);
}
@@ -1903,7 +1999,7 @@ static void evaluate_bp_location(void * x) {
bp_location_error = errno;
}
else if (bp_line_cnt == 0) {
- bp_location_error = set_errno(ERR_OTHER, "Unresolved source line information");
+ bp_location_error = set_errno(ERR_OTHER, "No debug information for this source line, check your compiler options");
}
else if (bp_stmt_cnt == 0) {
unsigned i;
@@ -2003,11 +2099,7 @@ static void replant_breakpoints_cache_client(void * args) {
assert(cache_enter_cnt >= 0);
if (cache_enter_cnt == 0) {
done_all_evaluations();
-
- assert(list_is_empty(&evaluations_active));
- if (list_is_empty(&evaluations_posted)) {
- flush_instructions();
- }
+ flush_instructions();
if (!list_is_empty(&evaluations_posted)) {
post_event(event_replant_breakpoints, (void *)++generation_posted);
@@ -2025,6 +2117,7 @@ static void replant_breakpoints_cache_client(void * args) {
static void event_replant_breakpoints(void * arg) {
LINK * q;
+ assert(!is_safe_event());
assert(!list_is_empty(&evaluations_posted));
if ((uintptr_t)arg != generation_posted) return;
if (cache_enter_cnt > 0) return;
@@ -2037,6 +2130,7 @@ static void event_replant_breakpoints(void * arg) {
req->loc_active = req->loc_posted;
memset(&req->loc_posted, 0, sizeof(LocationEvaluationRequest));
assert(list_is_empty(&req->link_active));
+ post_safe_event(req->ctx, NULL, NULL);
list_add_last(&req->link_active, &evaluations_active);
list_remove(&req->link_posted);
cache_enter_cnt++;
@@ -2991,11 +3085,11 @@ void evaluate_breakpoint(Context * ctx) {
if (need_to_post) continue;
assert(bi->valid);
if (is_disabled(bp)) continue;
+ if (!check_context_ids_condition(bp, ctx)) continue;
if (bp->condition != NULL || bp->stop_group != NULL || bp->temporary) {
need_to_post = 1;
continue;
}
- if (!check_context_ids_condition(bp, ctx)) continue;
c->condition_ok = 1;
}
}
@@ -3014,11 +3108,11 @@ void evaluate_breakpoint(Context * ctx) {
if (need_to_post) continue;
assert(bi->valid);
if (is_disabled(bp)) continue;
- if (bp->condition != NULL || bp->stop_group != NULL || bp->temporary) {
+ if (!check_context_ids_condition(bp, ctx)) continue;
+ if (bp->condition != NULL || bp->stop_group != NULL || bp->temporary || bi->bit_value) {
need_to_post = 1;
continue;
}
- if (!check_context_ids_condition(bp, ctx)) continue;
c->condition_ok = 1;
}
}
@@ -3217,6 +3311,32 @@ static void event_context_created(Context * ctx, void * args) {
list_init(&EXT(ctx)->link_hit_count);
}
+static void event_context_started(Context * ctx, void * args) {
+ LINK * l;
+ unsigned i;
+
+ /* Need to cancel condition evaluation request
+ * if the context was resumed */
+
+ l = evaluations_active.next;
+ while (l != &evaluations_active) {
+ EvaluationRequest * req = link_active2erl(l);
+ for (i = 0; i < req->bp_cnt; i++) {
+ if (req->bp_arr[i].ctx == ctx) req->bp_arr[i].canceled = 1;
+ }
+ l = l->next;
+ }
+
+ l = evaluations_posted.next;
+ while (l != &evaluations_posted) {
+ EvaluationRequest * req = link_posted2erl(l);
+ for (i = 0; i < req->bp_cnt; i++) {
+ if (req->bp_arr[i].ctx == ctx) req->bp_arr[i].canceled = 1;
+ }
+ l = l->next;
+ }
+}
+
static void event_context_changed(Context * ctx, void * args) {
if (ctx->mem_access && context_get_group(ctx, CONTEXT_GROUP_PROCESS) == ctx) {
/* If the context is a memory space, we need to update
@@ -3326,7 +3446,7 @@ void ini_breakpoints_service(Protocol * proto, TCFBroadcastGroup * bcg) {
event_context_created,
event_context_exited,
NULL,
- NULL,
+ event_context_started,
event_context_changed,
event_context_disposed
};
diff --git a/agent/tcf/services/breakpoints.h b/agent/tcf/services/breakpoints.h
index b50d8c9d..70fbfd4e 100644
--- a/agent/tcf/services/breakpoints.h
+++ b/agent/tcf/services/breakpoints.h
@@ -169,10 +169,18 @@ extern int is_skipping_breakpoint(Context * ctx);
/* Return 1 if break instruction is planted at given address in the context memory */
extern int is_breakpoint_address(Context * ctx, ContextAddress address);
-/* Clone all planted breakpoints when a process forks */
+/*
+ * Notify fork(): clone planted software breakpoints when a process forks.
+ * The process clone inherits memory contents of the original process,
+ * so software breakpoints are also cloned and the Breakpoints service needs to update the list of planted breakpoints.
+ */
extern void clone_breakpoints_on_process_fork(Context * parent, Context * child);
-/* Invalidate all planted breakpoints when a process calls exec() */
+/*
+ * Notify exec(): invalidate planted software breakpoints when a process calls exec().
+ * exec() replaces memory contents of the original process with something else,
+ * so software breakpoints are destroyed and the Breakpoints service needs to remove them from the list of planted breakpoints.
+ */
extern void invalidate_breakpoints_on_process_exec(Context * prs);
/*
diff --git a/agent/tcf/services/disassembly.c b/agent/tcf/services/disassembly.c
index 903632c3..a9ee66c1 100644
--- a/agent/tcf/services/disassembly.c
+++ b/agent/tcf/services/disassembly.c
@@ -426,7 +426,7 @@ static void disassemble_cache_client(void * x) {
else {
mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
}
- /* Continue after unredable range */
+ /* Continue after unreadable range */
error = 0;
}
}
diff --git a/agent/tcf/services/dprintf.c b/agent/tcf/services/dprintf.c
index 9f3e105e..2d7c6575 100644
--- a/agent/tcf/services/dprintf.c
+++ b/agent/tcf/services/dprintf.c
@@ -370,6 +370,7 @@ static void channel_close_listener(Channel * c) {
}
static void function_callback(int mode, Value * v, Value * args, unsigned args_cnt) {
+ uint8_t b = 0;
if (args_cnt == 0) {
str_exception(ERR_INV_EXPRESSION, "$printf mush have at least one argument");
}
@@ -379,7 +380,8 @@ static void function_callback(int mode, Value * v, Value * args, unsigned args_c
if (mode == EXPRESSION_MODE_NORMAL) {
dprintf_expression_ctx(v->ctx, (char *)args[0].value, args + 1, args_cnt - 1);
}
- set_value(v, NULL, 0, 0);
+ set_value(v, &b, 1, 0);
+ v->type_class = TYPE_CLASS_CARDINAL;
}
static int identifier_callback(Context * ctx, int frame, char * name, Value * v) {
diff --git a/agent/tcf/services/dwarf.h b/agent/tcf/services/dwarf.h
index 0e29c61a..6ab31286 100644
--- a/agent/tcf/services/dwarf.h
+++ b/agent/tcf/services/dwarf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 1996-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 1996-2022 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.
@@ -89,8 +89,13 @@
#define TAG_wrs_throw_breakpoint 0x4081
#define TAG_wrs_catch_breakpoint 0x4082
#define TAG_wrs_extern_subroutine 0x4083
+/* GNU extension https://gcc.gnu.org/wiki/TemplateParmsDwarf */
+#define TAG_GNU_template_parameter_pack 0x4107
+#define TAG_GNU_formal_parameter_pack 0x4108
+/**/
#define TAG_GNU_call_site 0x4109
#define TAG_GNU_call_site_parameter 0x410a
+/**/
#define TAG_hi_user 0xffff
#define CHILDREN_no 0x00
@@ -121,7 +126,25 @@
#define FORM_SEC_OFFSET 0x0017 /* v4 */
#define FORM_EXPRLOC 0x0018 /* v4 */
#define FORM_FLAG_PRESENT 0x0019 /* v4 */
+#define FORM_STRX 0x001a /* v5 */
+#define FORM_ADDRX 0x001b /* v5 */
+#define FORM_REF_SUP4 0x001c /* v5 */
+#define FORM_STRP_SUP 0x001d /* v5 */
+#define FORM_DATA16 0x001e /* v5 */
+#define FORM_LINE_STRP 0x001f /* v5 */
#define FORM_REF_SIG8 0x0020 /* v4 */
+#define FORM_IMPLICIT_CONST 0x0021 /* v5 */
+#define FORM_LOCLISTX 0x0022 /* v5 */
+#define FORM_RNGLISTX 0x0023 /* v5 */
+#define FORM_REF_SUP8 0x0024 /* v5 */
+#define FORM_STRX1 0x0025 /* v5 */
+#define FORM_STRX2 0x0026 /* v5 */
+#define FORM_STRX3 0x0027 /* v5 */
+#define FORM_STRX4 0x0028 /* v5 */
+#define FORM_ADDRX1 0x0029 /* v5 */
+#define FORM_ADDRX2 0x002a /* v5 */
+#define FORM_ADDRX3 0x002b /* v5 */
+#define FORM_ADDRX4 0x002c /* v5 */
/*
* GNU "dwz -m" extension.
@@ -231,6 +254,35 @@
#define AT_const_expr 0x006c /* v4 */
#define AT_enum_class 0x006d /* v4 */
#define AT_linkage_name 0x006e /* v4 */
+#define AT_string_length_bit_size 0x006f /* v5 */
+#define AT_string_length_byte_size 0x0070 /* v5 */
+#define AT_rank 0x0071 /* v5 */
+#define AT_str_offsets_base 0x0072 /* v5 */
+#define AT_addr_base 0x0073 /* v5 */
+#define AT_rnglists_base 0x0074 /* v5 */
+#define AT_dwo_name 0x0076 /* v5 */
+#define AT_reference 0x0077 /* v5 */
+#define AT_rvalue_reference 0x0078 /* v5 */
+#define AT_macros 0x0079 /* v5 */
+#define AT_call_all_calls 0x007a /* v5 */
+#define AT_call_all_source_calls 0x007b /* v5 */
+#define AT_call_all_tail_calls 0x007c /* v5 */
+#define AT_call_return_pc 0x007d /* v5 */
+#define AT_call_value 0x007e /* v5 */
+#define AT_call_origin 0x007f /* v5 */
+#define AT_call_parameter 0x0080 /* v5 */
+#define AT_call_pc 0x0081 /* v5 */
+#define AT_call_tail_call 0x0082 /* v5 */
+#define AT_call_target 0x0083 /* v5 */
+#define AT_call_target_clobbered 0x0084 /* v5 */
+#define AT_call_data_location 0x0085 /* v5 */
+#define AT_call_data_value 0x0086 /* v5 */
+#define AT_noreturn 0x0087 /* v5 */
+#define AT_alignment 0x0088 /* v5 */
+#define AT_export_symbols 0x0089 /* v5 */
+#define AT_deleted 0x008a /* v5 */
+#define AT_defaulted 0x008b /* v5 */
+#define AT_loclists_base 0x008c /* v5 */
#define AT_lo_user_v1 0x0200
#define AT_hi_user_v1 0x03ff
#define AT_push_mask 0x0220
@@ -243,12 +295,15 @@
#define AT_wrs_options 0x2001
#define AT_MIPS_linkage_name 0x2007
#define AT_GNU_call_site_value 0x2111
+#define AT_GNU_locviews 0x2137
/* GNAT descriptive type extension.
* See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type */
#define AT_GNAT_use_descriptive_type 0x2301
#define AT_GNAT_descriptive_type 0x2302
#define AT_hi_user_v2 0x3fff
+/* Pseudo-attribute, used to indicate first pass over comp unit info */
+#define AT_read_base_offsets 0xffff
#define OP_reg 0x01 /* v1 */
#define OP_basereg 0x02 /* v1 */
@@ -409,7 +464,16 @@
#define OP_bit_piece 0x9d
#define OP_implicit_value 0x9e /* v4 */
#define OP_stack_value 0x9f /* v4 */
-#define OP_implicit_pointer 0xa0
+#define OP_implicit_pointer 0xa0 /* v4 */
+#define OP_addrx 0xa1 /* v5 */
+#define OP_constx 0xa2 /* v5 */
+#define OP_entry_value 0xa3 /* v5 */
+#define OP_const_type 0xa4 /* v5 */
+#define OP_regval_type 0xa5 /* v5 */
+#define OP_deref_type 0xa6 /* v5 */
+#define OP_xderef_type 0xa7 /* v5 */
+#define OP_convert 0xa8 /* v5 */
+#define OP_reinterpret 0xa9 /* v5 */
#define OP_lo_user 0xe0
#define OP_hi_user 0xff
/* GCC extensions */
@@ -503,7 +567,29 @@
#define LANG_C99 0x0000000c /* v3 */
#define LANG_ADA95 0x0000000d /* v3 */
#define LANG_FORTRAN95 0x0000000e /* v3 */
-#define LANG_PLI 0x0000000f
+#define LANG_PLI 0x0000000f /* v3 */
+#define LANG_ObjC 0x00000010 /* v3 */
+#define LANG_ObjC_plus_plus 0x00000011 /* v3 */
+#define LANG_UPC 0x00000012 /* v3 */
+#define LANG_D 0x00000013 /* v3 */
+#define LANG_Python 0x00000014 /* v4 */
+#define LANG_OpenCL 0x00000015 /* v5 */
+#define LANG_Go 0x00000016 /* v5 */
+#define LANG_Modula3 0x00000017 /* v5 */
+#define LANG_Haskell 0x00000018 /* v5 */
+#define LANG_C_plus_plus_03 0x00000019 /* v5 */
+#define LANG_C_plus_plus_11 0x0000001a /* v5 */
+#define LANG_OCaml 0x0000001b /* v5 */
+#define LANG_Rust 0x0000001c /* v5 */
+#define LANG_C11 0x0000001d /* v5 */
+#define LANG_Swift 0x0000001e /* v5 */
+#define LANG_Julia 0x0000001f /* v5 */
+#define LANG_Dylan 0x00000020 /* v5 */
+#define LANG_C_plus_plus_14 0x00000021 /* v5 */
+#define LANG_Fortran03 0x00000022 /* v5 */
+#define LANG_Fortran08 0x00000023 /* v5 */
+#define LANG_RenderScript 0x00000024 /* v5 */
+#define LANG_BLISS 0x00000025 /* v5 */
#define LANG_lo_user 0x00008000
#define LANG_hi_user 0x0000ffff
@@ -647,3 +733,46 @@
#define DW_END_little 0x02
#define DW_END_lo_user 0x40
#define DW_END_hi_user 0xff
+
+/* New in DWARF Version 5 */
+#define DW_UT_compile 0x01
+#define DW_UT_type 0x02
+#define DW_UT_partial 0x03
+#define DW_UT_skeleton 0x04
+#define DW_UT_split_compile 0x05
+#define DW_UT_split_type 0x06
+#define DW_UT_lo_user 0x80
+#define DW_UT_hi_user 0xff
+
+/* Line number header entry format name Value */
+/* New in DWARF Version 5 */
+#define DW_LNCT_path 0x1
+#define DW_LNCT_directory_index 0x2
+#define DW_LNCT_timestamp 0x3
+#define DW_LNCT_size 0x4
+#define DW_LNCT_MD5 0x5
+#define DW_LNCT_lo_user 0x2000
+#define DW_LNCT_hi_user 0x3fff
+
+/* Location list entry encoding values */
+/* New in DWARF Version 5 */
+#define DW_LLE_end_of_list 0x00
+#define DW_LLE_base_addressx 0x01
+#define DW_LLE_startx_endx 0x02
+#define DW_LLE_startx_length 0x03
+#define DW_LLE_offset_pair 0x04
+#define DW_LLE_default_location 0x05
+#define DW_LLE_base_address 0x06
+#define DW_LLE_start_end 0x07
+#define DW_LLE_start_length 0x08
+
+/* Range list entry encoding values */
+/* New in DWARF Version 5 */
+#define DW_RLE_end_of_list 0x00
+#define DW_RLE_base_addressx 0x01
+#define DW_RLE_startx_endx 0x02
+#define DW_RLE_startx_length 0x03
+#define DW_RLE_offset_pair 0x04
+#define DW_RLE_base_address 0x05
+#define DW_RLE_start_end 0x06
+#define DW_RLE_start_length 0x07
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c
index 3e2db14b..d3e2cb5f 100644
--- a/agent/tcf/services/dwarfcache.c
+++ b/agent/tcf/services/dwarfcache.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 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.
@@ -253,7 +253,7 @@ static ObjectInfo * find_alt_object_info(ContextAddress ID) {
for (i = 0; i < File->dwz_file->section_cnt; i++) {
ELF_Section * section = File->dwz_file->sections + i;
if (section->name != NULL && strcmp(section->name, ".debug_info") == 0) {
- if (Info != NULL) str_exception(ERR_INV_DWARF, "More then one .debug_info section in DWZ file");
+ if (Info != NULL) str_exception(ERR_INV_DWARF, "More than one .debug_info section in DWZ file");
Info = find_loaded_object(section, ID);
}
}
@@ -530,10 +530,32 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
high_pc_offs = 0;
if (Tag == TAG_compile_unit || Tag == TAG_partial_unit || Tag == TAG_type_unit) {
CompUnit * Unit = add_comp_unit((ContextAddress)(sDebugSection->addr + dio_gEntryPos));
+ ELF_Section * Section = dio_GetSection();
+ U8_T Pos = dio_GetPos();
assert(sParentObject == NULL);
Info = Unit->mObject;
assert(Info->mTag == 0);
sCompUnit = Unit;
+ if (sUnitDesc.mRngListsSection != NULL) {
+ /* Read header of Range List Table */
+ if (sUnitDesc.mRngListsOffs < 8) str_exception(ERR_INV_DWARF, "Invalid AT_rnglists_base");
+ dio_EnterSection(&sUnitDesc, sUnitDesc.mRngListsSection, sUnitDesc.mRngListsOffs - 8);
+ if (dio_ReadU2() != 5) str_exception(ERR_INV_DWARF, "Invalid version of .debug_rnglists section");
+ if (dio_ReadU1() != sUnitDesc.mAddressSize) str_exception(ERR_INV_DWARF, "Invalid header of .debug_rnglists section");
+ if (dio_ReadU1() != 0) str_exception(ERR_INV_DWARF, "Invalid header of .debug_rnglists section");
+ sUnitDesc.mRngListsOffsetEntryCount = dio_ReadU4();
+ dio_EnterSection(&sUnitDesc, Section, Pos);
+ }
+ if (sUnitDesc.mLocListsSection != NULL) {
+ /* Read header of Loc List Table */
+ if (sUnitDesc.mLocListsOffs < 8) str_exception(ERR_INV_DWARF, "Invalid AT_loclists_base");
+ dio_EnterSection(&sUnitDesc, sUnitDesc.mLocListsSection, sUnitDesc.mLocListsOffs - 8);
+ if (dio_ReadU2() != 5) str_exception(ERR_INV_DWARF, "Invalid version of .debug_loclists section");
+ if (dio_ReadU1() != sUnitDesc.mAddressSize) str_exception(ERR_INV_DWARF, "Invalid header of .debug_loclists section");
+ if (dio_ReadU1() != 0) str_exception(ERR_INV_DWARF, "Invalid header of .debug_loclists section");
+ sUnitDesc.mLocListsOffsetEntryCount = dio_ReadU4();
+ dio_EnterSection(&sUnitDesc, Section, Pos);
+ }
}
else {
Info = add_object_info((ContextAddress)(sDebugSection->addr + dio_gEntryPos));
@@ -599,7 +621,11 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
case LANG_C:
case LANG_C89:
case LANG_C99:
+ case LANG_C11:
case LANG_C_PLUS_PLUS:
+ case LANG_C_plus_plus_03:
+ case LANG_C_plus_plus_11:
+ case LANG_C_plus_plus_14:
Info->mType->mName = "void";
break;
}
@@ -618,7 +644,11 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
case LANG_C:
case LANG_C89:
case LANG_C99:
+ case LANG_C11:
case LANG_C_PLUS_PLUS:
+ case LANG_C_plus_plus_03:
+ case LANG_C_plus_plus_11:
+ case LANG_C_plus_plus_14:
Info->mType->mName = "char";
break;
}
@@ -762,12 +792,14 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
if (dio_gFormData) Info->mFlags |= DOIF_optional;
break;
case AT_low_pc:
+ if (Tag == TAG_base_type || Tag == TAG_fund_type || Tag == TAG_index_range) break;
dio_ChkAddr(Form);
Info->u.mCode.mLowPC = (ContextAddress)dio_gFormData;
if (dio_gFormSection) Info->u.mCode.mSection = dio_gFormSection;
Info->mFlags |= DOIF_low_pc;
break;
case AT_high_pc:
+ if (Tag == TAG_base_type || Tag == TAG_fund_type || Tag == TAG_index_range) break;
if (Info->mFlags & DOIF_ranges) break;
if (Form != FORM_ADDR) {
dio_ChkData(Form);
@@ -779,7 +811,10 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
Info->u.mCode.mHighPC.mAddr = (ContextAddress)dio_gFormData;
break;
case AT_ranges:
- dio_ChkData(Form);
+ if (Tag == TAG_base_type || Tag == TAG_fund_type || Tag == TAG_index_range) break;
+ if (Form != FORM_RNGLISTX) {
+ dio_ChkData(Form);
+ }
Info->u.mCode.mHighPC.mRanges = dio_gFormData;
Info->mFlags |= DOIF_ranges;
break;
@@ -787,6 +822,10 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
dio_ChkFlag(Form);
if (dio_gFormData) Info->mFlags |= DOIF_external;
break;
+ case AT_inline:
+ dio_ChkData(Form);
+ if (dio_gFormData & 1) Info->mFlags |= DOIF_inlined;
+ break;
case AT_artificial:
dio_ChkFlag(Form);
if (dio_gFormData) Info->mFlags |= DOIF_artificial;
@@ -832,19 +871,38 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
break;
case AT_location:
Info->mFlags |= DOIF_location;
- if (Form == FORM_DATA4 || Form == FORM_DATA8 || Form == FORM_SEC_OFFSET || Tag == TAG_formal_parameter) {
+ if (Tag == TAG_formal_parameter) {
+ Info->mFlags |= DOIF_need_frame;
+ }
+ switch (Form) {
+ case FORM_DATA1:
+ case FORM_DATA2:
+ case FORM_DATA4:
+ case FORM_DATA8:
+ case FORM_DATA16:
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX:
Info->mFlags |= DOIF_need_frame;
+ break;
}
break;
case AT_data_location:
- if (sCompUnit->mDesc.mVersion <= 1) {
+ if (sUnitDesc.mVersion <= 1) {
/* AT_mangled */
Info->mFlags |= DOIF_mangled_name;
break;
}
Info->mFlags |= DOIF_data_location;
- if (Form == FORM_DATA4 || Form == FORM_DATA8 || Form == FORM_SEC_OFFSET) {
+ switch (Form) {
+ case FORM_DATA1:
+ case FORM_DATA2:
+ case FORM_DATA4:
+ case FORM_DATA8:
+ case FORM_DATA16:
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX:
Info->mFlags |= DOIF_need_frame;
+ break;
}
break;
case AT_string_length:
@@ -857,10 +915,18 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
case AT_vtable_elem_location:
case AT_upper_bound:
case AT_lower_bound:
- /* Note: FORM_DATA4, FORM_DATA8 and FORM_SEC_OFFSET are location lists.
+ /* Note: FORM_DATAn and FORM_SEC_OFFSET are location lists.
* Location list needs PC, so we set DOIF_need_frame because of that */
- if (Form == FORM_DATA4 || Form == FORM_DATA8 || Form == FORM_SEC_OFFSET) {
+ switch (Form) {
+ case FORM_DATA1:
+ case FORM_DATA2:
+ case FORM_DATA4:
+ case FORM_DATA8:
+ case FORM_DATA16:
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX:
Info->mFlags |= DOIF_need_frame;
+ break;
}
break;
case AT_const_value:
@@ -876,32 +942,7 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
Unit->mDir = (char *)dio_gFormDataAddr;
break;
case AT_stmt_list:
- if (Form == FORM_ADDR || Form == FORM_SEC_OFFSET) {
- Unit->mLineInfoOffs = dio_gFormData;
- if (dio_gFormSection != NULL) {
- Unit->mLineInfoOffs -= dio_gFormSection->addr;
- Unit->mLineInfoSection = dio_gFormSection;
- }
- else {
- unsigned idx;
- ELF_File * file = Unit->mFile;
- for (idx = 1; idx < file->section_cnt; idx++) {
- ELF_Section * sec = file->sections + idx;
- if (sec->size == 0) continue;
- if (sec->name == NULL) continue;
- if (sec->type == SHT_NOBITS) continue;
- if (Unit->mLineInfoOffs >= sec->addr && Unit->mLineInfoOffs < sec->addr + sec->size &&
- strcmp(sec->name, sUnitDesc.mVersion <= 1 ? ".line" : ".debug_line") == 0) {
- Unit->mLineInfoOffs -= sec->addr;
- Unit->mLineInfoSection = sec;
- break;
- }
- }
- }
- break;
- }
- dio_ChkData(Form);
- Unit->mLineInfoOffs = dio_gFormData;
+ dio_ReadSectionPointer(Form, &Unit->mLineInfoSection, &Unit->mLineInfoOffs, sUnitDesc.mVersion <= 1 ? sCache->mDebugLineV1 : sCache->mDebugLineV2);
break;
case AT_base_types:
Unit->mBaseTypes = add_comp_unit((ContextAddress)dio_gFormData);
@@ -961,8 +1002,10 @@ static void read_object_refs(ELF_Section * Section) {
while (pos < sObjRefsCnt) {
ObjectReference ref = sObjRefs[pos++];
if (ref.obj != NULL) {
- assert(ref.org->mTag != 0);
- if (ref.org->mFlags & DOIF_load_mark) {
+ if (ref.org->mTag == 0) {
+ ref.obj->mFlags |= DOIF_inv_reference;
+ }
+ else if (ref.org->mFlags & DOIF_load_mark) {
fwd = 1;
}
else {
@@ -1036,41 +1079,198 @@ static void add_addr_range(ELF_Section * sec, CompUnit * unit, ContextAddress ad
range->mUnit = unit;
}
-static void add_object_addr_ranges(ObjectInfo * info) {
- CompUnit * unit = info->mCompUnit;
- ContextAddress base = info->u.mCode.mLowPC;
- assert(info->mFlags & DOIF_low_pc);
- if (info->mFlags & DOIF_ranges) {
- if (sCache->mDebugRanges != NULL) {
- dio_EnterSection(&unit->mDesc, sCache->mDebugRanges, info->u.mCode.mHighPC.mRanges);
+U8_T read_dwarf_addr_section(CompUnit * Unit, U4_T idx, ELF_Section ** Section) {
+ U8_T addr = 0;
+ U8_T pos = dio_GetPos();
+ ELF_Section * sec = dio_GetSection();
+ U8_T offs = idx * Unit->mDesc.mAddressSize + Unit->mDesc.mAddrInfoOffs;
+ if (Unit->mDesc.mAddrInfoSection == NULL) str_exception(ERR_INV_DWARF, "Missing AT_addr_base");
+ dio_EnterSection(&Unit->mDesc, Unit->mDesc.mAddrInfoSection, offs);
+ addr = dio_ReadAddress(Section);
+ dio_EnterSection(&Unit->mDesc, sec, pos);
+ return addr;
+}
+
+void start_dwarf_addr_ranges(ObjectInfo * Obj, ObjectAddressRange * Range) {
+ memset(Range, 0, sizeof(ObjectAddressRange));
+ Range->mObject = Obj;
+ Range->mUnit = Obj->mCompUnit;
+ Range->mVersion = Range->mUnit->mDesc.mVersion;
+ if (Obj->mFlags & DOIF_ranges) {
+ DWARFCache * Cache = get_dwarf_cache(Range->mUnit->mFile);
+ Range->mBaseAddr = Range->mUnit->mObject->u.mCode.mLowPC;
+ if (Range->mVersion <= 4) {
+ if (Cache->mDebugRanges != NULL) {
+ dio_EnterSection(&Range->mUnit->mDesc, Cache->mDebugRanges, Obj->u.mCode.mHighPC.mRanges);
+ Range->mRngSection = Cache->mDebugRanges;
+ }
+ }
+ else if (Cache->mDebugRngLists) {
+ dio_EnterSection(&Range->mUnit->mDesc, Cache->mDebugRngLists, Obj->u.mCode.mHighPC.mRanges);
+ Range->mRngSection = Cache->mDebugRngLists;
+ }
+ Range->mDone = Range->mRngSection == NULL;
+ }
+}
+
+int read_dwarf_addr_range(ObjectAddressRange * Range) {
+ if (Range->mDone) return 0;
+ if (Range->mObject->mFlags & DOIF_ranges) {
+ if (Range->mVersion <= 4) {
+ U8_T set_base = Range->mUnit->mDesc.mAddressSize < 8 ? ((U8_T)1 << Range->mUnit->mDesc.mAddressSize * 8) - 1 : ~(U8_T)0;
for (;;) {
- U8_T AddrMax = ~(U8_T)0;
ELF_Section * sec_x = NULL;
ELF_Section * sec_y = NULL;
U8_T x = dio_ReadAddress(&sec_x);
U8_T y = dio_ReadAddress(&sec_y);
if (x == 0 && y == 0) break;
- if (unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << unit->mDesc.mAddressSize * 8) - 1;
- if (x == AddrMax) {
- base = (ContextAddress)y;
+ if (x == set_base) {
+ Range->mBaseAddr = (ContextAddress)y;
+ Range->mBaseSection = sec_y;
+ continue;
}
- else if (y > x) {
- ELF_Section * sec = info->u.mCode.mSection;
- if (sec == NULL) sec = unit->mTextSection;
- x = base + x;
- y = base + y;
- if (sec_x != NULL) sec = sec_x;
- else if (sec_y != NULL) sec = sec_y;
- add_addr_range(sec, unit, (ContextAddress)x, (ContextAddress)(y - x));
+ if (y > x) {
+ ELF_Section * sec = sec_x;
+ if (sec == NULL) sec = sec_y;
+ if (sec == NULL) sec = Range->mBaseSection;
+ if (sec == NULL) sec = Range->mObject->u.mCode.mSection;
+ if (sec == NULL) sec = Range->mUnit->mTextSection;
+ x = Range->mBaseAddr + x;
+ y = Range->mBaseAddr + y;
+ Range->mSection = sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)(y - x);
+ return 1;
}
}
- dio_ExitSection();
}
+ else {
+ for (;;) {
+ U1_T type = dio_ReadU1();
+ if (type == DW_RLE_end_of_list) break;
+ switch (type) {
+ case DW_RLE_base_addressx:
+ Range->mBaseAddr = read_dwarf_addr_section(Range->mUnit, dio_ReadULEB128(), &Range->mBaseSection);
+ break;
+ case DW_RLE_startx_endx:
+ {
+ ELF_Section * x_sec = NULL;
+ ELF_Section * y_sec = NULL;
+ U8_T x = read_dwarf_addr_section(Range->mUnit, dio_ReadULEB128(), &x_sec);
+ U8_T y = read_dwarf_addr_section(Range->mUnit, dio_ReadULEB128(), &y_sec);
+ if (y > x) {
+ if (x_sec == NULL) x_sec = y_sec;
+ if (x_sec == NULL) x_sec = Range->mObject->u.mCode.mSection;
+ if (x_sec == NULL) x_sec = Range->mUnit->mTextSection;
+ Range->mSection = x_sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)(y - x);
+ return 1;
+ }
+ break;
+ }
+ case DW_RLE_startx_length:
+ {
+ ELF_Section * x_sec = NULL;
+ U8_T x = read_dwarf_addr_section(Range->mUnit, dio_ReadULEB128(), &x_sec);
+ U8_T y = dio_ReadU8LEB128();
+ if (y > 0) {
+ if (x_sec == NULL) x_sec = Range->mObject->u.mCode.mSection;
+ if (x_sec == NULL) x_sec = Range->mUnit->mTextSection;
+ Range->mSection = x_sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)y;
+ return 1;
+ }
+ break;
+ }
+ case DW_RLE_offset_pair:
+ {
+ ELF_Section * x_sec = Range->mBaseSection;
+ U8_T x = Range->mBaseAddr + dio_ReadU8LEB128();
+ U8_T y = Range->mBaseAddr + dio_ReadU8LEB128();
+ if (y > x) {
+ if (x_sec == NULL) x_sec = Range->mObject->u.mCode.mSection;
+ if (x_sec == NULL) x_sec = Range->mUnit->mTextSection;
+ Range->mSection = x_sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)(y - x);
+ return 1;
+ }
+ break;
+ }
+ case DW_RLE_base_address:
+ Range->mBaseAddr = dio_ReadAddress(&Range->mBaseSection);
+ break;
+ case DW_RLE_start_end:
+ {
+ ELF_Section * x_sec = NULL;
+ ELF_Section * y_sec = NULL;
+ U8_T x = dio_ReadAddress(&x_sec);
+ U8_T y = dio_ReadAddress(&y_sec);
+ if (y > x) {
+ if (x_sec == NULL) x_sec = y_sec;
+ if (x_sec == NULL) x_sec = Range->mObject->u.mCode.mSection;
+ if (x_sec == NULL) x_sec = Range->mUnit->mTextSection;
+ Range->mSection = x_sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)(y - x);
+ return 1;
+ }
+ break;
+ }
+ case DW_RLE_start_length:
+ {
+ ELF_Section * x_sec = NULL;
+ U8_T x = dio_ReadAddress(&x_sec);
+ U8_T y = dio_ReadU8LEB128();
+ if (y > 0) {
+ if (x_sec == NULL) x_sec = Range->mObject->u.mCode.mSection;
+ if (x_sec == NULL) x_sec = Range->mUnit->mTextSection;
+ Range->mSection = x_sec;
+ Range->mAddr = (ContextAddress)x;
+ Range->mSize = (ContextAddress)y;
+ return 1;
+ }
+ break;
+ }
+ default:
+ str_exception(ERR_OTHER, "Invalid .debug_rnglists section");
+ break;
+ }
+ }
+ }
+ dio_ExitSection();
+ Range->mDone = 1;
+ return 0;
}
- else if (info->u.mCode.mHighPC.mAddr > base) {
- ELF_Section * sec = info->u.mCode.mSection;
- if (sec == NULL) sec = unit->mTextSection;
- add_addr_range(sec, unit, base, info->u.mCode.mHighPC.mAddr - base);
+ if ((Range->mObject->mFlags & DOIF_low_pc) && Range->mObject->u.mCode.mHighPC.mAddr > Range->mObject->u.mCode.mLowPC) {
+ ELF_Section * sec = Range->mObject->u.mCode.mSection;
+ if (sec == NULL) sec = Range->mUnit->mTextSection;
+ Range->mSection = sec;
+ Range->mAddr = Range->mObject->u.mCode.mLowPC;
+ Range->mSize = Range->mObject->u.mCode.mHighPC.mAddr - Range->mObject->u.mCode.mLowPC;
+ Range->mDone = 1;
+ return 1;
+ }
+ if ((Range->mObject->mFlags & DOIF_low_pc) && Range->mObject->mTag == TAG_GNU_call_site) {
+ ELF_Section * sec = Range->mObject->u.mCode.mSection;
+ if (sec == NULL) sec = Range->mUnit->mTextSection;
+ Range->mSection = sec;
+ Range->mAddr = Range->mObject->u.mCode.mLowPC;
+ Range->mSize = 1;
+ Range->mDone = 1;
+ return 1;
+ }
+ Range->mDone = 1;
+ return 0;
+}
+
+static void add_object_addr_ranges(ObjectInfo * info) {
+ ObjectAddressRange range;
+ start_dwarf_addr_ranges(info, &range);
+ while (read_dwarf_addr_range(&range)) {
+ add_addr_range(range.mSection, range.mUnit, range.mAddr, range.mSize);
}
}
@@ -1147,7 +1347,7 @@ static void load_addr_ranges(ELF_Section * debug_info) {
for (idx = 1; idx < file->section_cnt; idx++) {
ObjectInfo * info = sCache->mObjectHashTable[idx].mCompUnits;
while (info != NULL) {
- if (info->mFlags & DOIF_low_pc) add_object_addr_ranges(info);
+ if (info->mFlags & (DOIF_low_pc | DOIF_ranges)) add_object_addr_ranges(info);
if ((info->mFlags & DOIF_aranges) == 0 && (info->mFlags & DOIF_ranges) == 0 && info->u.mCode.mHighPC.mAddr == 0) {
/* Unit does not have PC ranges data. As a workaround, add line info ranges */
@@ -1169,13 +1369,13 @@ static void load_addr_ranges(ELF_Section * debug_info) {
}
}
- {
+ if (!(info->mFlags & DOIF_low_pc) || (info->mFlags & DOIF_ranges)) {
/* Workaround for GCC bug - certain ranges are missing in both ".debug_aranges" and the unit info.
* Add address ranges of the underlying scopes. */
ObjectInfo * obj = info->mChildren;
assert(info->mFlags & DOIF_children_loaded);
while (obj != NULL) {
- if (obj->mFlags & DOIF_low_pc) add_object_addr_ranges(obj);
+ if (obj->mFlags & (DOIF_low_pc | DOIF_ranges)) add_object_addr_ranges(obj);
obj = obj->mSibling;
}
}
@@ -1450,6 +1650,36 @@ static void load_debug_sections(void) {
if (strcmp(sec->name, ".debug_types") == 0) {
debug_types_size += sec->size;
}
+ else if (strcmp(sec->name, ".line") == 0) {
+ sCache->mDebugLineV1 = sec;
+ }
+ else if (strcmp(sec->name, ".debug_line") == 0) {
+ sCache->mDebugLineV2 = sec;
+ }
+ else if (strcmp(sec->name, ".debug_loc") == 0) {
+ sCache->mDebugLoc = sec;
+ }
+ else if (strcmp(sec->name, ".debug_loclists") == 0) {
+ sCache->mDebugLocLists = sec;
+ }
+ else if (strcmp(sec->name, ".debug_rnglists") == 0) {
+ sCache->mDebugRngLists = sec;
+ }
+ else if (strcmp(sec->name, ".debug_ranges") == 0) {
+ sCache->mDebugRanges = sec;
+ }
+ else if (strcmp(sec->name, ".debug_frame") == 0) {
+ FrameInfoIndex * idx = (FrameInfoIndex *)loc_alloc_zero(sizeof(FrameInfoIndex));
+ idx->mSection = sec;
+ idx->mNext = frame_info_d;
+ frame_info_d = idx;
+ }
+ else if (strcmp(sec->name, ".eh_frame") == 0) {
+ FrameInfoIndex * idx = (FrameInfoIndex *)loc_alloc_zero(sizeof(FrameInfoIndex));
+ idx->mSection = sec;
+ idx->mNext = frame_info_e;
+ frame_info_e = idx;
+ }
}
if (debug_types_size > 0) {
@@ -1490,37 +1720,6 @@ static void load_debug_sections(void) {
}
}
- for (idx = 1; idx < file->section_cnt; idx++) {
- ELF_Section * sec = file->sections + idx;
- if (sec->size == 0) continue;
- if (sec->name == NULL) continue;
- if (sec->type == SHT_NOBITS) continue;
- if (strcmp(sec->name, ".line") == 0) {
- sCache->mDebugLineV1 = sec;
- }
- else if (strcmp(sec->name, ".debug_line") == 0) {
- sCache->mDebugLineV2 = sec;
- }
- else if (strcmp(sec->name, ".debug_loc") == 0) {
- sCache->mDebugLoc = sec;
- }
- else if (strcmp(sec->name, ".debug_ranges") == 0) {
- sCache->mDebugRanges = sec;
- }
- else if (strcmp(sec->name, ".debug_frame") == 0) {
- FrameInfoIndex * idx = (FrameInfoIndex *)loc_alloc_zero(sizeof(FrameInfoIndex));
- idx->mSection = sec;
- idx->mNext = frame_info_d;
- frame_info_d = idx;
- }
- else if (strcmp(sec->name, ".eh_frame") == 0) {
- FrameInfoIndex * idx = (FrameInfoIndex *)loc_alloc_zero(sizeof(FrameInfoIndex));
- idx->mSection = sec;
- idx->mNext = frame_info_e;
- frame_info_e = idx;
- }
- }
-
while (frame_info_e != NULL) {
FrameInfoIndex * idx = frame_info_e;
frame_info_e = idx->mNext;
@@ -1814,13 +2013,14 @@ void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T
case FORM_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
+ case FORM_DATA16 :
case FORM_FLAG :
case FORM_BLOCK1 :
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
case FORM_STRP :
- case FORM_SEC_OFFSET:
+ case FORM_LINE_STRP :
case FORM_EXPRLOC :
case FORM_REF_SIG8 :
case FORM_STRING :
@@ -1830,6 +2030,7 @@ void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T
break;
case FORM_SDATA :
case FORM_UDATA :
+ case FORM_IMPLICIT_CONST:
Value->mValue = gop_gFormData;
break;
case FORM_ADDR :
@@ -1837,6 +2038,10 @@ void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T
Value->mValue = elf_map_to_run_time_address(Ctx, Obj->mCompUnit->mFile, gop_gFormSection, (ContextAddress)gop_gFormData);
if (errno) str_exception(errno, "Cannot get object run-time address");
break;
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX :
+ Value->mValue = gop_gFormData;
+ break;
default:
if (Attr == AT_data_member_location && Obj->mTag == TAG_member && Obj->mParent->mTag == TAG_union_type) {
Value->mForm = FORM_UDATA;
@@ -1904,7 +2109,9 @@ void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T
break;
}
}
- exception(ERR_SYM_NOT_FOUND);
+ str_fmt_exception(ERR_SYM_NOT_FOUND,
+ "Cannot read symbol attribute 0x%02x at 0x%" PRIx64,
+ (unsigned)Attr, (U8_T)Obj->mID);
}
sCache = NULL;
@@ -1931,6 +2138,7 @@ void read_and_evaluate_dwarf_object_property_with_args(
case FORM_DATA8 :
case FORM_SDATA :
case FORM_UDATA :
+ case FORM_IMPLICIT_CONST:
if (ArgsCnt == 0) exception(ERR_INV_CONT_OBJ);
Value->mValue = Args[0] + get_numeric_property_value(Value);
Value->mForm = FORM_UDATA;
@@ -1941,19 +2149,25 @@ void read_and_evaluate_dwarf_object_property_with_args(
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX :
dwarf_evaluate_expression(Value, Args, ArgsCnt);
break;
}
}
else if (Attr == AT_location || Attr == AT_string_length || Attr == AT_frame_base || Attr == AT_use_location) {
switch (Value->mForm) {
+ case FORM_DATA1 :
+ case FORM_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
+ case FORM_DATA16 :
case FORM_BLOCK1 :
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX :
dwarf_evaluate_expression(Value, Args, ArgsCnt);
break;
}
@@ -1964,6 +2178,8 @@ void read_and_evaluate_dwarf_object_property_with_args(
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX :
dwarf_evaluate_expression(Value, Args, ArgsCnt);
break;
}
@@ -2052,7 +2268,6 @@ DWARFCache * get_dwarf_cache(ELF_File * file) {
sCache->mObjectArrayPos = OBJECT_ARRAY_SIZE;
sCache->mObjectHashTable = (ObjectHashTable *)loc_alloc_zero(sizeof(ObjectHashTable) * file->section_cnt);
if (set_trap(&trap)) {
- dio_LoadAbbrevTable(file);
load_debug_sections();
clear_trap(&trap);
}
@@ -2074,6 +2289,7 @@ static void add_dir(CompUnit * unit, char * name) {
}
static void add_file(FileInfo * file) {
+ unsigned i;
CompUnit * unit = file->mCompUnit;
file->mNameHash = calc_file_name_hash(file->mName);
if (unit->mFilesCnt >= unit->mFilesMax) {
@@ -2081,6 +2297,16 @@ static void add_file(FileInfo * file) {
unit->mFiles = (FileInfo *)loc_realloc(unit->mFiles, sizeof(FileInfo) * unit->mFilesMax);
}
if (file->mDir == NULL) file->mDir = unit->mDir;
+ /* Workaround: check for duplicate entries */
+ file->mDup = ~(unsigned)0;
+ for (i = 0; i < unit->mFilesCnt; i++) {
+ if (unit->mFiles[i].mNameHash == file->mNameHash &&
+ unit->mFiles[i].mDir != NULL && file->mDir != NULL && strcmp(unit->mFiles[i].mDir, file->mDir) == 0 &&
+ unit->mFiles[i].mName != NULL && file->mName != NULL && strcmp(unit->mFiles[i].mName, file->mName) == 0) {
+ file->mDup = i;
+ break;
+ }
+ }
unit->mFiles[unit->mFilesCnt++] = *file;
}
@@ -2089,6 +2315,10 @@ static void add_state(CompUnit * unit, LineNumbersState * state) {
/* Workaround: Diab compiler generates invalid file indices for an empty compilation unit */
return;
}
+ if (unit->mFiles[state->mFile].mDup < unit->mFilesCnt) {
+ /* Workaround: dublicate file IDs break line numbers service */
+ state->mFile = unit->mFiles[state->mFile].mDup;
+ }
if (unit->mFiles[state->mFile].mAreaCnt++ == 0) {
/* Workaround: compilers don't produce mapping for first lines in a source file.
* Such mapping is needed, for example, for re-positioning of source line breakpoints.
@@ -2165,21 +2395,30 @@ static int state_text_pos_comparator(const void * x1, const void * x2) {
}
static void compute_reverse_lookup_indices(DWARFCache * Cache, CompUnit * Unit) {
- U4_T i;
+ U4_T i, j;
qsort(Unit->mStates, Unit->mStatesCnt, sizeof(LineNumbersState), state_address_comparator);
Unit->mStatesIndex = (LineNumbersState **)loc_alloc(sizeof(LineNumbersState *) * Unit->mStatesCnt);
- for (i = 0; i < Unit->mStatesCnt; i++) {
- LineNumbersState * s1 = Unit->mStates + i;
- while (i + 1 < Unit->mStatesCnt) {
- LineNumbersState * s2 = s1 + 1;
- if (s1->mFile != s2->mFile ||
- s1->mLine != s2->mLine || s1->mColumn != s2->mColumn ||
+ for (i = 0, j = 0; i < Unit->mStatesCnt;) {
+ LineNumbersState * s1 = Unit->mStates + i++;
+ while (i < Unit->mStatesCnt) {
+ LineNumbersState * s2 = Unit->mStates + i;
+ if (s1->mLine != s2->mLine || s1->mColumn != s2->mColumn || s1->mFile != s2->mFile ||
s1->mFlags != s2->mFlags || s1->mISA != s2->mISA ||
s1->mOpIndex != s2->mOpIndex || s1->mDiscriminator != s2->mDiscriminator) break;
- memmove(s2, s2 + 1, sizeof(LineNumbersState) * (Unit->mStatesCnt - i - 2));
- Unit->mStatesCnt--;
+ /* Workaround for GCC bug: skip redundant entries in line info */
+ i++;
}
- Unit->mStatesIndex[i] = s1;
+ Unit->mStatesIndex[j++] = s1;
+ }
+ assert(j <= Unit->mStatesCnt);
+ if (j < Unit->mStatesCnt) {
+ Unit->mStatesCnt = j;
+ for (i = 0; i < j && Unit->mStates + i == Unit->mStatesIndex[i]; i++) {}
+ for (; i < j; i++) {
+ Unit->mStates[i] = *Unit->mStatesIndex[i];
+ Unit->mStatesIndex[i] = Unit->mStates + i;
+ }
+ Unit->mStatesIndex = (LineNumbersState **)loc_realloc(Unit->mStatesIndex, sizeof(LineNumbersState *) * Unit->mStatesCnt);
}
qsort(Unit->mStatesIndex, Unit->mStatesCnt, sizeof(LineNumbersState *), state_text_pos_comparator);
for (i = 0; i < Unit->mStatesCnt; i++) Unit->mStatesIndex[i]->mStatesIndexPos = i;
@@ -2214,6 +2453,13 @@ static void load_line_numbers_v1(CompUnit * Unit, U4_T unit_size) {
ELF_Section * sec = NULL;
ContextAddress addr = 0;
U4_T line = 0;
+ FileInfo file;
+
+ memset(&file, 0, sizeof(file));
+ file.mCompUnit = Unit;
+ file.mDir = Unit->mDir;
+ file.mName = Unit->mObject->mName;
+ add_file(&file);
memset(&state, 0, sizeof(state));
addr = (ContextAddress)dio_ReadAddress(&sec);
@@ -2234,6 +2480,8 @@ static void load_line_numbers_v1(CompUnit * Unit, U4_T unit_size) {
static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) {
U2_T version = 0;
+ U1_T address_size = dwarf64 ? 8 : 4;
+ U1_T segment_selector_size = 0;
U8_T header_pos = 0;
U1_T opcode_base = 0;
U1_T opcode_size[256];
@@ -2246,7 +2494,22 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) {
LineNumbersState state;
version = dio_ReadU2();
- if (version < 2 || version > 4) str_exception(ERR_INV_DWARF, "Invalid line number info version");
+ if (version < 2 || version > 5) str_exception(ERR_INV_DWARF, "Invalid line number info version");
+ if (version >= 5) {
+ address_size = dio_ReadU1();
+ segment_selector_size = dio_ReadU1();
+ }
+ if (version < 5) {
+ /* Prior to DWARF Version 5, the current compilation file name was not represented in
+ the file_names field. In DWARF Version 5, the current compilation file name is
+ explicitly present and has index 0 */
+ FileInfo file;
+ memset(&file, 0, sizeof(file));
+ file.mCompUnit = Unit;
+ file.mDir = Unit->mDir;
+ file.mName = Unit->mObject->mName;
+ add_file(&file);
+ }
header_size = dwarf64 ? dio_ReadU8() : (U8_T)dio_ReadU4();
header_pos = dio_GetPos();
min_instruction_length = dio_ReadU1();
@@ -2258,26 +2521,102 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) {
memset(opcode_size, 0, sizeof(opcode_size));
dio_Read(opcode_size + 1, opcode_base - 1);
+ if (segment_selector_size > 0) str_exception(ERR_INV_DWARF, "Segment selectors not supported");
+ if (address_size > 8) str_exception(ERR_INV_DWARF, "Address size > 8 not supported");
+
/* Read directory names */
- for (;;) {
- char * name = dio_ReadString();
- if (name == NULL) break;
- add_dir(Unit, name);
+ if (version <= 4) {
+ add_dir(Unit, NULL);
+ for (;;) {
+ char * name = dio_ReadString();
+ if (name == NULL) break;
+ add_dir(Unit, name);
+ }
+ }
+ else {
+ U1_T directory_entry_format_count = dio_ReadU1();
+ typedef struct {
+ U4_T type;
+ U4_T form;
+ } DirectoryEntryFormat;
+ DirectoryEntryFormat * format = (DirectoryEntryFormat *)tmp_alloc_zero(sizeof(DirectoryEntryFormat) * directory_entry_format_count);
+ U8_T directories_count = 0;
+ unsigned i, j;
+ for (i = 0; i < directory_entry_format_count; i++) {
+ format[i].type = dio_ReadULEB128();
+ format[i].form = dio_ReadULEB128();
+ }
+ directories_count = dio_ReadULEB128();
+ for (j = 0; j < directories_count; j++) {
+ for (i = 0; i < directory_entry_format_count; i++) {
+ dio_ReadAttribute(0, format[i].form);
+ switch (format[i].type) {
+ case DW_LNCT_path:
+ add_dir(Unit, (char *)dio_gFormDataAddr);
+ break;
+ }
+ }
+ }
}
/* Read source files info */
- for (;;) {
- U4_T dir = 0;
- FileInfo file;
- memset(&file, 0, sizeof(file));
- file.mName = dio_ReadString();
- if (file.mName == NULL) break;
- dir = dio_ReadULEB128();
- if (dir > 0 && dir <= Unit->mDirsCnt) file.mDir = Unit->mDirs[dir - 1];
- file.mCompUnit = Unit;
- file.mModTime = dio_ReadULEB128();
- file.mSize = dio_ReadULEB128();
- add_file(&file);
+ if (version <= 4) {
+ for (;;) {
+ U4_T dir = 0;
+ FileInfo file;
+ memset(&file, 0, sizeof(file));
+ file.mName = dio_ReadString();
+ if (file.mName == NULL) break;
+ dir = dio_ReadULEB128();
+ if (dir < Unit->mDirsCnt) file.mDir = Unit->mDirs[dir];
+ file.mModTime = dio_ReadULEB128();
+ file.mSize = dio_ReadU8LEB128();
+ file.mCompUnit = Unit;
+ add_file(&file);
+ }
+ }
+ else {
+ U1_T file_name_entry_format_count = dio_ReadU1();
+ typedef struct {
+ U4_T type;
+ U4_T form;
+ } FileNameEntryFormat;
+ FileNameEntryFormat * format = (FileNameEntryFormat *)tmp_alloc_zero(sizeof(FileNameEntryFormat) * file_name_entry_format_count);
+ U8_T file_names_count = 0;
+ unsigned i, j;
+ for (i = 0; i < file_name_entry_format_count; i++) {
+ format[i].type = dio_ReadULEB128();
+ format[i].form = dio_ReadULEB128();
+ }
+ file_names_count = dio_ReadULEB128();
+ for (j = 0; j < file_names_count; j++) {
+ FileInfo file;
+ memset(&file, 0, sizeof(file));
+ for (i = 0; i < file_name_entry_format_count; i++) {
+ dio_ReadAttribute(0, format[i].form);
+ switch (format[i].type) {
+ case DW_LNCT_path:
+ file.mName = (char *)dio_gFormDataAddr;
+ break;
+ case DW_LNCT_directory_index:
+ if (dio_gFormData >= Unit->mDirsCnt) break;
+ file.mDir = Unit->mDirs[dio_gFormData];
+ break;
+ case DW_LNCT_timestamp:
+ file.mModTime = (U4_T)dio_gFormData;
+ break;
+ case DW_LNCT_size:
+ file.mSize = dio_gFormData;
+ break;
+ case DW_LNCT_MD5:
+ if (dio_gFormDataSize < sizeof(file.mMD5)) break;
+ memcpy(file.mMD5, dio_gFormDataAddr, sizeof(file.mMD5));
+ break;
+ }
+ }
+ file.mCompUnit = Unit;
+ if (file.mName != NULL) add_file(&file);
+ }
}
if (header_pos + header_size != dio_GetPos()) {
@@ -2317,10 +2656,10 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) {
memset(&file, 0, sizeof(file));
file.mName = dio_ReadString();
dir = dio_ReadULEB128();
- if (dir > 0 && dir <= Unit->mDirsCnt) file.mDir = Unit->mDirs[dir - 1];
+ if (dir < Unit->mDirsCnt) file.mDir = Unit->mDirs[dir];
file.mCompUnit = Unit;
file.mModTime = dio_ReadULEB128();
- file.mSize = dio_ReadULEB128();
+ file.mSize = dio_ReadU8LEB128();
add_file(&file);
break;
}
@@ -2397,19 +2736,11 @@ void load_line_numbers(CompUnit * Unit) {
Trap trap;
DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
ELF_Section * LineInfoSection = Unit->mLineInfoSection;
- if (LineInfoSection == NULL) LineInfoSection = Unit->mDesc.mVersion <= 1 ? Cache->mDebugLineV1 : Cache->mDebugLineV2;
if (LineInfoSection == NULL) return;
if (Unit->mLineInfoLoaded) return;
- if (elf_load(LineInfoSection)) exception(errno);
dio_EnterSection(&Unit->mDesc, LineInfoSection, Unit->mLineInfoOffs);
if (set_trap(&trap)) {
U8_T unit_size = 0;
- FileInfo file;
- memset(&file, 0, sizeof(file));
- file.mCompUnit = Unit;
- file.mDir = Unit->mDir;
- file.mName = Unit->mObject->mName;
- add_file(&file);
/* Read header */
unit_size = dio_ReadU4();
if (Unit->mDesc.mVersion <= 1) {
diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h
index 41d7c6c1..ffabf212 100644
--- a/agent/tcf/services/dwarfcache.h
+++ b/agent/tcf/services/dwarfcache.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006-2023 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.
@@ -50,17 +50,20 @@ typedef struct UnitAddressRange UnitAddressRange;
typedef struct FrameInfoRange FrameInfoRange;
typedef struct FrameInfoIndex FrameInfoIndex;
typedef struct ObjectHashTable ObjectHashTable;
+typedef struct ObjectAddressRange ObjectAddressRange;
typedef struct DWARFCache DWARFCache;
struct FileInfo {
const char * mName;
const char * mDir;
U4_T mModTime;
- U4_T mSize;
+ U8_T mSize;
+ U1_T mMD5[16];
unsigned mNameHash;
FileInfo * mNextInHash;
CompUnit * mCompUnit;
unsigned mAreaCnt;
+ unsigned mDup;
};
#define TAG_fund_type 0x2000
@@ -68,30 +71,32 @@ struct FileInfo {
#define TAG_mod_pointer 0x2002
#define TAG_mod_reference 0x2003
-#define DOIF_declaration 0x000001
-#define DOIF_external 0x000002
-#define DOIF_artificial 0x000004
-#define DOIF_specification 0x000008
-#define DOIF_abstract_origin 0x000010
-#define DOIF_extension 0x000020
-#define DOIF_private 0x000040
-#define DOIF_protected 0x000080
-#define DOIF_public 0x000100
-#define DOIF_children_loaded 0x000200
-#define DOIF_ranges 0x000400
-#define DOIF_aranges 0x000800
-#define DOIF_find_mark 0x001000
-#define DOIF_load_mark 0x002000
-#define DOIF_pub_mark 0x004000
-#define DOIF_low_pc 0x008000
-#define DOIF_need_frame 0x010000
-#define DOIF_mips_linkage_name 0x020000
-#define DOIF_linkage_name 0x040000
-#define DOIF_mangled_name 0x080000
-#define DOIF_optional 0x100000
-#define DOIF_location 0x200000
-#define DOIF_data_location 0x400000
-#define DOIF_const_value 0x800000
+#define DOIF_declaration 0x0000001
+#define DOIF_external 0x0000002
+#define DOIF_artificial 0x0000004
+#define DOIF_specification 0x0000008
+#define DOIF_abstract_origin 0x0000010
+#define DOIF_extension 0x0000020
+#define DOIF_private 0x0000040
+#define DOIF_protected 0x0000080
+#define DOIF_public 0x0000100
+#define DOIF_children_loaded 0x0000200
+#define DOIF_ranges 0x0000400
+#define DOIF_aranges 0x0000800
+#define DOIF_find_mark 0x0002000
+#define DOIF_load_mark 0x0004000
+#define DOIF_pub_mark 0x0008000
+#define DOIF_low_pc 0x0010000
+#define DOIF_need_frame 0x0020000
+#define DOIF_mips_linkage_name 0x0040000
+#define DOIF_linkage_name 0x0080000
+#define DOIF_mangled_name 0x0100000
+#define DOIF_optional 0x0200000
+#define DOIF_location 0x0400000
+#define DOIF_data_location 0x0800000
+#define DOIF_const_value 0x1000000
+#define DOIF_inv_reference 0x2000000
+#define DOIF_inlined 0x4000000
struct ObjectInfo {
@@ -252,6 +257,19 @@ struct ObjectHashTable {
unsigned mCompUnitsIndexSize;
};
+struct ObjectAddressRange {
+ ObjectInfo * mObject;
+ CompUnit * mUnit;
+ ELF_Section * mRngSection;
+ ELF_Section * mBaseSection;
+ ContextAddress mBaseAddr;
+ unsigned mVersion;
+ ELF_Section * mSection;
+ ContextAddress mAddr; /* Link-time start address of the range */
+ ContextAddress mSize; /* Size of the range */
+ int mDone;
+};
+
#define DWARF_CACHE_MAGIC 0x34625490
struct DWARFCache {
@@ -261,6 +279,8 @@ struct DWARFCache {
ELF_Section * mDebugLineV1;
ELF_Section * mDebugLineV2;
ELF_Section * mDebugLoc;
+ ELF_Section * mDebugLocLists;
+ ELF_Section * mDebugRngLists;
ELF_Section * mDebugRanges;
ObjectHashTable * mObjectHashTable; /* per ELF section */
struct ObjectArray * mObjectList;
@@ -307,6 +327,13 @@ extern ObjectInfo * find_object(ELF_Section * sec, ContextAddress ID);
extern UnitAddressRange * find_comp_unit_addr_range(DWARFCache * cache, ELF_Section * section,
ContextAddress addr_min, ContextAddress addr_max);
+/* Read an address from .debug_addr section */
+extern U8_T read_dwarf_addr_section(CompUnit * Unit, U4_T idx, ELF_Section ** Section);
+
+/* Read address ranges */
+extern void start_dwarf_addr_ranges(ObjectInfo * Obj, ObjectAddressRange * Range);
+extern int read_dwarf_addr_range(ObjectAddressRange * Range);
+
/*
* Read a property of a DWARF object, perform ELF relocations if any.
* FORM_ADDR values are mapped to run-time address space.
diff --git a/agent/tcf/services/dwarfecomp.c b/agent/tcf/services/dwarfecomp.c
index 8b29497e..c7540274 100644
--- a/agent/tcf/services/dwarfecomp.c
+++ b/agent/tcf/services/dwarfecomp.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2011-2022 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.
@@ -61,6 +61,8 @@ static ObjectInfo ** call_site_buf = NULL;
static unsigned call_site_cnt = 0;
static unsigned call_site_max = 0;
+static const char * name_synopsys = "CHESS, Synopsys Inc";
+
static void add(unsigned n) {
if (buf_pos >= buf_max) {
buf_max *= 2;
@@ -170,40 +172,53 @@ static int get_num_prop(ObjectInfo * obj, U2_T at, U8_T * res) {
return 1;
}
-static void op_addr(void) {
+static ContextAddress get_relocated_addr(ELF_Section * src_section, U8_T pos, ELF_Section ** dst_section, int * rt) {
+ DIO_UnitDescriptor * desc = &expr->object->mCompUnit->mDesc;
ContextAddress addr = 0;
- ELF_Section * section = NULL;
- U8_T pos = 0;
- int rt = 0;
-
- expr_pos++;
- pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
- dio_EnterSection(&expr->object->mCompUnit->mDesc, expr->section, pos);
- switch (expr->object->mCompUnit->mDesc.mAddressSize) {
+ dio_EnterSection(desc, src_section, pos);
+ switch (desc->mAddressSize) {
case 2: {
U2_T x = dio_ReadU2();
- drl_relocate_in_context(expr_ctx, expr->section, pos, &x, sizeof(x), &section, &rt);
+ drl_relocate_in_context(expr_ctx, src_section, pos, &x, sizeof(x), dst_section, rt);
addr = x;
break;
}
case 4: {
U4_T x = dio_ReadU4();
- drl_relocate_in_context(expr_ctx, expr->section, pos, &x, sizeof(x), &section, &rt);
+ drl_relocate_in_context(expr_ctx, src_section, pos, &x, sizeof(x), dst_section, rt);
addr = x;
break;
}
case 8: {
U8_T x = dio_ReadU8();
- drl_relocate_in_context(expr_ctx, expr->section, pos, &x, sizeof(x), &section, &rt);
+ drl_relocate_in_context(expr_ctx, src_section, pos, &x, sizeof(x), dst_section, rt);
addr = x;
break;
}
default:
str_exception(ERR_INV_DWARF, "Invalid data size");
- return;
+ break;
}
- expr_pos += (size_t)(dio_GetPos() - pos);
dio_ExitSection();
+ return addr;
+}
+
+static void op_addr(void) {
+ ContextAddress addr = 0;
+ DIO_UnitDescriptor * desc = &expr->object->mCompUnit->mDesc;
+ ELF_Section * section = NULL;
+ U8_T pos = 0;
+ int rt = 0;
+
+ expr_pos++;
+ pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
+ addr = get_relocated_addr(expr->section, pos, &section, &rt);
+ expr_pos += (size_t)desc->mAddressSize;
+ if (expr_pos < expr->expr_size && expr->expr_addr[expr_pos] == OP_addr && expr->object->mCompUnit->mProducer &&
+ !strncmp(expr->object->mCompUnit->mProducer, name_synopsys, strlen(name_synopsys))) {
+ /* Workaround: Synopsys compiler for Xilinx AIE generates multiple OP_addr where 1 is expected */
+ return;
+ }
if (expr_pos < expr->expr_size && expr->expr_addr[expr_pos] == OP_GNU_push_tls_address) {
/* Bug in some versions of GCC: OP_addr used instead of OP_const, use link-time value */
}
@@ -215,6 +230,55 @@ static void op_addr(void) {
add_uleb128(addr);
}
+static void op_addrx(void) {
+ ContextAddress addr = 0;
+ DIO_UnitDescriptor * desc = &expr->object->mCompUnit->mDesc;
+ ELF_Section * section = NULL;
+ U8_T pos = 0;
+ U4_T idx = 0;
+ int rt = 0;
+
+ expr_pos++;
+ pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
+ dio_EnterSection(desc, expr->section, pos);
+ idx = dio_ReadULEB128();
+ expr_pos += (size_t)(dio_GetPos() - pos);
+ dio_ExitSection();
+ if (desc->mAddrInfoSection == NULL) str_exception(ERR_INV_DWARF, "Missing AT_addr_base");
+ addr = get_relocated_addr(desc->mAddrInfoSection, desc->mAddrInfoOffs + idx * desc->mAddressSize, &section, &rt);
+ if (!rt) {
+ addr = elf_map_to_run_time_address(expr_ctx, expr->object->mCompUnit->mFile, section, addr);
+ if (errno) str_exception(errno, "Cannot get object run-time address");
+ }
+ add(OP_constu);
+ add_uleb128(addr);
+}
+
+static void op_constx(void) {
+ ContextAddress addr = 0;
+ DIO_UnitDescriptor * desc = &expr->object->mCompUnit->mDesc;
+ U8_T pos = 0;
+ U4_T idx = 0;
+
+ expr_pos++;
+ pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
+ dio_EnterSection(desc, expr->section, pos);
+ idx = dio_ReadULEB128();
+ expr_pos += (size_t)(dio_GetPos() - pos);
+ dio_ExitSection();
+ if (desc->mAddrInfoSection == NULL) str_exception(ERR_INV_DWARF, "Missing AT_addr_base");
+ dio_EnterSection(desc, desc->mAddrInfoSection, desc->mAddrInfoOffs + idx * desc->mAddressSize);
+ switch (desc->mAddressSize) {
+ case 2: addr = dio_ReadU2(); break;
+ case 4: addr = dio_ReadU4(); break;
+ case 8: addr = dio_ReadU8(); break;
+ default: str_exception(ERR_INV_DWARF, "Invalid data size"); break;
+ }
+ dio_ExitSection();
+ add(OP_constu);
+ add_uleb128(addr);
+}
+
static ObjectInfo * get_parent_function(ObjectInfo * info) {
while (info != NULL) {
switch (info->mTag) {
@@ -238,58 +302,22 @@ static int check_section(CompUnit * unit, ELF_Section * sec_obj, ELF_Section * s
}
int dwarf_check_in_range(ObjectInfo * obj, ELF_Section * sec, U8_T addr) {
- if (obj->mFlags & DOIF_ranges) {
- Trap trap;
- if (set_trap(&trap)) {
- CompUnit * unit = obj->mCompUnit;
- DWARFCache * cache = get_dwarf_cache(unit->mFile);
- ELF_Section * debug_ranges = cache->mDebugRanges;
- if (debug_ranges != NULL) {
- ContextAddress base = unit->mObject->u.mCode.mLowPC;
- int res = 0;
-
-#if 0
- U8_T entry_pc = 0;
- if (obj->mTag == TAG_inlined_subroutine &&
- get_num_prop(obj, AT_entry_pc, &entry_pc))
- base = (ContextAddress)entry_pc;
-#endif
-
- dio_EnterSection(&unit->mDesc, debug_ranges, obj->u.mCode.mHighPC.mRanges);
- for (;;) {
- U8_T AddrMax = ~(U8_T)0;
- ELF_Section * x_sec = NULL;
- ELF_Section * y_sec = NULL;
- U8_T x = dio_ReadAddress(&x_sec);
- U8_T y = dio_ReadAddress(&y_sec);
- if (x == 0 && y == 0) break;
- if (unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << unit->mDesc.mAddressSize * 8) - 1;
- if (x == AddrMax) {
- base = (ContextAddress)y;
- }
- else if (check_section(unit, x_sec, sec) && check_section(unit, y_sec, sec)) {
- x = base + x;
- y = base + y;
- if (x <= addr && addr < y) {
- res = 1;
- break;
- }
- }
- }
+ Trap trap;
+ int res = 0;
+ ObjectAddressRange range;
+ if (set_trap(&trap)) {
+ start_dwarf_addr_ranges(obj, &range);
+ while (read_dwarf_addr_range(&range)) {
+ if (check_section(range.mUnit, range.mSection, sec) &&
+ range.mAddr <= addr && (range.mAddr + range.mSize == 0 || addr < range.mAddr + range.mSize)) {
dio_ExitSection();
- clear_trap(&trap);
- return res;
+ res = 1;
+ break;
}
- clear_trap(&trap);
}
- return 0;
- }
-
- if (obj->u.mCode.mHighPC.mAddr > obj->u.mCode.mLowPC && check_section(obj->mCompUnit, obj->u.mCode.mSection, sec)) {
- return addr >= obj->u.mCode.mLowPC && addr < obj->u.mCode.mHighPC.mAddr;
+ clear_trap(&trap);
}
-
- return 0;
+ return res;
}
static ObjectInfo * get_function_by_addr(ObjectInfo * parent, ELF_Section * sec, U8_T addr) {
@@ -516,7 +544,7 @@ static void op_fbreg(void) {
dwarf_get_expression_list(&fp, &info);
add_expression_list(info, 1, offs);
}
- else if (trap.error != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(trap.error) != ERR_SYM_NOT_FOUND) {
str_exception(trap.error, "OP_fbreg: cannot read AT_frame_base");
}
else {
@@ -588,6 +616,7 @@ static void op_implicit_pointer(void) {
switch (pv.mForm) {
case FORM_SDATA:
case FORM_UDATA:
+ case FORM_IMPLICIT_CONST:
pv.mAddr = buf.arr;
if (unit->mFile->elf64) {
pv.mSize = 8;
@@ -662,7 +691,7 @@ static void op_call(void) {
expr_pos += (size_t)(dio_GetPos() - dio_pos);
dio_ExitSection();
- ref_obj = find_object(expr->object->mCompUnit->mDesc.mSection, ref_id);
+ ref_obj = find_object(desc->mSection, ref_id);
if (ref_obj == NULL) str_exception(ERR_INV_DWARF, "Invalid reference in OP_call");
read_dwarf_object_property(expr_ctx, STACK_NO_FRAME, ref_obj, AT_location, &pv);
dwarf_get_expression_list(&pv, &info);
@@ -688,7 +717,7 @@ static void op_gnu_variable_value(void) {
expr_pos += (size_t)(dio_GetPos() - dio_pos);
dio_ExitSection();
- ref_obj = find_object(expr->object->mCompUnit->mDesc.mSection, ref_id);
+ ref_obj = find_object(desc->mSection, ref_id);
if (ref_obj == NULL) str_exception(ERR_INV_DWARF, "Invalid reference in OP_GNU_variable_value");
elf_object2symbol(NULL, ref_obj, &sym);
id = symbol2id(sym);
@@ -775,7 +804,7 @@ static void op_parameter_ref(void) {
PropertyValue pv;
expr_pos++;
- add(OP_GNU_entry_value);
+ add(OP_entry_value);
size_pos = buf_pos;
add(0);
add(0);
@@ -792,7 +821,7 @@ static void op_parameter_ref(void) {
ObjectInfo * site = call_site_buf[n];
ObjectInfo * args = get_dwarf_children(site);
while (args != NULL) {
- if (args->mTag == TAG_GNU_call_site_parameter && args->mFlags & DOIF_abstract_origin) {
+ if (args->mTag == TAG_GNU_call_site_parameter && (args->mFlags & DOIF_abstract_origin) != 0) {
read_and_evaluate_dwarf_object_property(expr_ctx, STACK_NO_FRAME, args, AT_abstract_origin, &pv);
if (get_numeric_property_value(&pv) == ref_id) {
Trap trap;
@@ -882,7 +911,6 @@ static void add_expression(DWARFExpressionInfo * info) {
DWARFExpressionInfo * org_expr = expr;
size_t org_expr_pos = expr_pos;
JumpInfo * org_jumps = jumps;
- const char * name_synopsys = "CHESS, Synopsys Inc";
expr = info;
expr_pos = 0;
@@ -895,6 +923,9 @@ static void add_expression(DWARFExpressionInfo * info) {
size_t op_dst_pos = buf_pos;
U1_T op = info->expr_addr[expr_pos];
switch (op) {
+ case OP_nop:
+ expr_pos++;
+ break;
case OP_const1u:
case OP_const1s:
case OP_pick:
@@ -907,7 +938,6 @@ static void add_expression(DWARFExpressionInfo * info) {
copy(1 + info->object->mCompUnit->mDesc.mAddressSize);
break;
case OP_basereg:
- check_frame();
copy(1 + info->object->mCompUnit->mDesc.mAddressSize);
break;
case OP_const2u:
@@ -954,7 +984,6 @@ static void add_expression(DWARFExpressionInfo * info) {
case OP_breg29:
case OP_breg30:
case OP_breg31:
- check_frame();
add(op);
expr_pos++;
copy_leb128();
@@ -991,7 +1020,6 @@ static void add_expression(DWARFExpressionInfo * info) {
}
break;
case OP_bregx:
- check_frame();
add(op);
expr_pos++;
copy_leb128();
@@ -1023,6 +1051,12 @@ static void add_expression(DWARFExpressionInfo * info) {
case OP_addr:
op_addr();
break;
+ case OP_addrx:
+ op_addrx();
+ break;
+ case OP_constx:
+ op_constx();
+ break;
case OP_implicit_pointer:
case OP_GNU_implicit_pointer:
op_implicit_pointer();
@@ -1036,6 +1070,7 @@ static void add_expression(DWARFExpressionInfo * info) {
case OP_call_ref:
op_call();
break;
+ case OP_entry_value:
case OP_GNU_entry_value:
check_frame();
op_entry_value();
@@ -1044,6 +1079,7 @@ static void add_expression(DWARFExpressionInfo * info) {
check_frame();
op_parameter_ref();
break;
+ case OP_const_type:
case OP_GNU_const_type:
expr_pos++;
{
@@ -1090,6 +1126,7 @@ static void add_expression(DWARFExpressionInfo * info) {
copy(size);
}
break;
+ case OP_regval_type:
case OP_GNU_regval_type:
expr_pos++;
{
@@ -1122,6 +1159,8 @@ static void add_expression(DWARFExpressionInfo * info) {
}
}
break;
+ case OP_deref_type:
+ case OP_xderef_type:
case OP_GNU_deref_type:
expr_pos++;
{
@@ -1138,18 +1177,19 @@ static void add_expression(DWARFExpressionInfo * info) {
case ATE_unsigned_fixed:
case ATE_UTF:
ok = 1;
- add(OP_deref_size);
+ add(op == OP_xderef_type ? OP_xderef_size : OP_deref_size);
add(size);
break;
}
if (!ok) {
- add(OP_GNU_deref_type);
+ add(op == OP_xderef_type ? OP_xderef_type : OP_GNU_deref_type);
add_uleb128(size);
add_uleb128(fund_type);
add_uleb128(byte_size);
}
}
break;
+ case OP_convert:
case OP_GNU_convert:
expr_pos++;
{
@@ -1184,7 +1224,8 @@ static void add_expression(DWARFExpressionInfo * info) {
break;
case OP_GNU_variable_value:
/* case OP_address_class: */
- if (!strncmp(expr->object->mCompUnit->mProducer, name_synopsys, strlen(name_synopsys))) {
+ if (expr->object->mCompUnit->mProducer &&
+ !strncmp(expr->object->mCompUnit->mProducer, name_synopsys, strlen(name_synopsys))) {
/* Synopsys compiler for Xilinx AIE core uses 0xFD as a location expression
* operation, which takes integer argument from top-of-stack of the location
* expression stack and uses it as the address class for the location being
diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c
index 5085faef..010f0a50 100644
--- a/agent/tcf/services/dwarfexpr.c
+++ b/agent/tcf/services/dwarfexpr.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2016 Wind River Systems, Inc. and others.
+ * Copyright (c) 2008-2023 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.
@@ -32,67 +32,184 @@
#include <tcf/services/elf-symbols.h>
#include <tcf/services/vm.h>
+static DWARFExpressionInfo * Last = NULL;
+
+static void add_entry(PropertyValue * Value, DWARFExpressionInfo ** List, U8_T RT_Addr, U8_T RT_Size, size_t Size) {
+ DWARFExpressionInfo * Info = (DWARFExpressionInfo *)tmp_alloc_zero(sizeof(DWARFExpressionInfo));
+ Info->object = Value->mObject;
+ Info->code_addr = RT_Addr;
+ Info->code_size = RT_Size;
+ Info->section = dio_GetSection();
+ Info->expr_addr = dio_GetDataPtr();
+ Info->expr_size = Size;
+ Info->attr = Value->mAttr;
+ Info->form = Value->mForm;
+ if (Last == NULL) *List = Info;
+ else Last->next = Info;
+ Last = Info;
+}
+
void dwarf_get_expression_list(PropertyValue * Value, DWARFExpressionInfo ** List) {
CompUnit * Unit = Value->mObject->mCompUnit;
+ DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
+ U8_T Offset = 0;
+ int LocSec = 0;
- if (Value->mAddr == NULL || Value->mSize == 0) str_exception(ERR_INV_DWARF, "Invalid format of location expression");
-
- if (Value->mForm == FORM_DATA4 || Value->mForm == FORM_DATA8 || Value->mForm == FORM_SEC_OFFSET) {
- U8_T Base = 0;
- U8_T Offset = 0;
- U8_T AddrMax = ~(U8_T)0;
- DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
- DWARFExpressionInfo * Last = NULL;
+ Last = NULL;
+ assert(Cache->magic == DWARF_CACHE_MAGIC);
- assert(Cache->magic == DWARF_CACHE_MAGIC);
- if (Cache->mDebugLoc == NULL) str_exception(ERR_INV_DWARF, "Missing .debug_loc section");
+ if (Value->mForm == FORM_DATA1 || Value->mForm == FORM_DATA2 || Value->mForm == FORM_DATA4 || Value->mForm == FORM_DATA8) {
+ if (Value->mAddr == NULL || Value->mSize == 0) str_exception(ERR_INV_DWARF, "Invalid format of location expression");
dio_EnterSection(&Unit->mDesc, Unit->mDesc.mSection, Value->mAddr - (U1_T *)Unit->mDesc.mSection->data);
Offset = dio_ReadAddressX(NULL, Value->mSize);
dio_ExitSection();
+ LocSec = 1;
+ }
+ else if (Value->mForm == FORM_SEC_OFFSET || Value->mForm == FORM_LOCLISTX) {
+ Offset = Value->mValue;
+ LocSec = 1;
+ }
+
+ if (LocSec) {
+ U8_T Base = 0;
+ U8_T AddrMax = ~(U8_T)0;
+
Base = Unit->mObject->u.mCode.mLowPC;
- if (Unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << Unit->mDesc.mAddressSize * 8) - 1;
- dio_EnterSection(&Unit->mDesc, Cache->mDebugLoc, Offset);
- for (;;) {
- ELF_Section * S0 = NULL;
- ELF_Section * S1 = NULL;
- U8_T Addr0 = dio_ReadAddress(&S0);
- U8_T Addr1 = dio_ReadAddress(&S1);
- if (Addr0 == AddrMax) {
- Base = Addr1;
- }
- else if (Addr0 == 0 && Addr1 == 0) {
- break;
- }
- else if (Addr0 > Addr1) {
- str_exception(ERR_INV_DWARF, "Invalid .debug_loc section");
+ if (Unit->mDesc.mVersion <= 4) {
+ if (Unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << Unit->mDesc.mAddressSize * 8) - 1;
+ if (Cache->mDebugLoc == NULL) str_exception(ERR_INV_DWARF, "Missing .debug_loc section");
+ dio_EnterSection(&Unit->mDesc, Cache->mDebugLoc, Offset);
+ for (;;) {
+ ELF_Section * S0 = NULL;
+ ELF_Section * S1 = NULL;
+ U8_T Addr0 = dio_ReadAddress(&S0);
+ U8_T Addr1 = dio_ReadAddress(&S1);
+ if (Addr0 == AddrMax) {
+ Base = Addr1;
+ }
+ else if (Addr0 == 0 && Addr1 == 0) {
+ break;
+ }
+ else if (Addr0 > Addr1) {
+ str_exception(ERR_INV_DWARF, "Invalid .debug_loc section");
+ }
+ else {
+ U2_T Size = dio_ReadU2();
+ U8_T RT_Addr = 0;
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Base + Addr0);
+ if (!errno) add_entry(Value, List, RT_Addr, Addr1 - Addr0, Size);
+ dio_Skip(Size);
+ }
}
- else {
- U2_T Size = dio_ReadU2();
- U8_T RT_Addr0 = 0;
- if (S0 == NULL) S0 = Unit->mTextSection;
- RT_Addr0 = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Base + Addr0);
- if (!errno) {
- DWARFExpressionInfo * Info = (DWARFExpressionInfo *)tmp_alloc_zero(sizeof(DWARFExpressionInfo));
- Info->object = Value->mObject;
- Info->code_addr = RT_Addr0;
- Info->code_size = Addr1 - Addr0;
- Info->section = Cache->mDebugLoc;
- Info->expr_addr = dio_GetDataPtr();
- Info->expr_size = Size;
- Info->attr = Value->mAttr;
- Info->form = Value->mForm;
- if (Last == NULL) *List = Info;
- else Last->next = Info;
- Last = Info;
+ dio_ExitSection();
+ if (Last == NULL) str_exception(ERR_OTHER, "Object is not available at this location in the code");
+ }
+ else {
+ ELF_Section * BaseSection = NULL;
+ if (Cache->mDebugLocLists == NULL) str_exception(ERR_INV_DWARF, "Missing .debug_loclists section");
+ dio_EnterSection(&Unit->mDesc, Cache->mDebugLocLists, Offset);
+ for (;;) {
+ U1_T type = dio_ReadU1();
+ if (type == DW_LLE_end_of_list) break;
+ switch (type) {
+ case DW_LLE_base_addressx:
+ Base = read_dwarf_addr_section(Unit, dio_ReadULEB128(), &BaseSection);
+ break;
+ case DW_LLE_startx_endx:
+ {
+ ELF_Section * S0 = NULL;
+ ELF_Section * S1 = NULL;
+ U8_T Addr0 = read_dwarf_addr_section(Unit, dio_ReadULEB128(), &S0);
+ U8_T Addr1 = read_dwarf_addr_section(Unit, dio_ReadULEB128(), &S1);
+ U4_T Size = dio_ReadULEB128();
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ if (Addr1 > Addr0) {
+ U8_T RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Addr0);
+ if (!errno) add_entry(Value, List, RT_Addr, Addr1 - Addr0, Size);
+ }
+ dio_Skip(Size);
+ }
+ break;
+ case DW_LLE_startx_length:
+ {
+ ELF_Section * S0 = NULL;
+ U8_T Addr0 = read_dwarf_addr_section(Unit, dio_ReadULEB128(), &S0);
+ U8_T CSize = dio_ReadU8LEB128();
+ U4_T Size = dio_ReadULEB128();
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ if (CSize != 0) {
+ U8_T RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Addr0);
+ if (!errno) add_entry(Value, List, RT_Addr, CSize, Size);
+ }
+ dio_Skip(Size);
+ }
+ break;
+ case DW_LLE_offset_pair:
+ {
+ ELF_Section * S0 = BaseSection;
+ U8_T Offs0 = dio_ReadU8LEB128();
+ U8_T Offs1 = dio_ReadU8LEB128();
+ U4_T Size = dio_ReadULEB128();
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ if (Offs1 > Offs0) {
+ U8_T RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Base + Offs0);
+ if (!errno) add_entry(Value, List, RT_Addr, Offs1 - Offs0, Size);
+ }
+ dio_Skip(Size);
+ }
+ break;
+ case DW_LLE_default_location:
+ {
+ U4_T Size = dio_ReadULEB128();
+ add_entry(Value, List, 0, 0, Size);
+ dio_Skip(Size);
+ }
+ break;
+ case DW_LLE_base_address:
+ Base = dio_ReadAddress(&BaseSection);
+ break;
+ case DW_LLE_start_end:
+ {
+ ELF_Section * S0 = NULL;
+ ELF_Section * S1 = NULL;
+ U8_T Addr0 = dio_ReadAddress(&S0);
+ U8_T Addr1 = dio_ReadAddress(&S1);
+ U4_T Size = dio_ReadULEB128();
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ if (Addr1 > Addr0) {
+ U8_T RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Addr0);
+ if (!errno) add_entry(Value, List, RT_Addr, Addr1 - Addr0, Size);
+ }
+ dio_Skip(Size);
+ }
+ break;
+ case DW_LLE_start_length:
+ {
+ ELF_Section * S0 = NULL;
+ U8_T Addr0 = dio_ReadAddress(&S0);
+ U8_T CSize = dio_ReadU8LEB128();
+ U4_T Size = dio_ReadULEB128();
+ if (S0 == NULL) S0 = Unit->mTextSection;
+ if (CSize != 0) {
+ U8_T RT_Addr = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Addr0);
+ if (!errno) add_entry(Value, List, RT_Addr, CSize, Size);
+ }
+ dio_Skip(Size);
+ }
+ break;
+ default:
+ str_exception(ERR_OTHER, "Invalid .debug_loclists section");
+ break;
}
- dio_Skip(Size);
}
+ dio_ExitSection();
+ if (Last == NULL) str_exception(ERR_OTHER, "Object is not available at this location in the code");
}
- dio_ExitSection();
- if (Last == NULL) str_exception(ERR_OTHER, "Object is not available at this location in the code");
}
else {
DWARFExpressionInfo * Info = (DWARFExpressionInfo *)tmp_alloc_zero(sizeof(DWARFExpressionInfo));
+ if (Value->mAddr == NULL || Value->mSize == 0) str_exception(ERR_INV_DWARF, "Invalid format of location expression");
Info->object = Value->mObject;
Info->section = Unit->mDesc.mSection;
Info->expr_addr = Value->mAddr;
@@ -139,9 +256,6 @@ static void evaluate_expression(void * x) {
State->stk[State->stk_pos++] = args[1];
State->stk[State->stk_pos++] = args[0];
}
- if (Value->mPieces != NULL || Value->mAddr == NULL || Value->mSize == 0) {
- str_exception(ERR_INV_DWARF, "Invalid DWARF expression reference");
- }
dwarf_get_expression_list(Value, &Info);
dwarf_transform_expression(Value->mContext, Value->mFrame, Info);
State->code = Info->expr_addr;
diff --git a/agent/tcf/services/dwarfframe.c b/agent/tcf/services/dwarfframe.c
index a97ac06b..2ddb2897 100644
--- a/agent/tcf/services/dwarfframe.c
+++ b/agent/tcf/services/dwarfframe.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 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.
@@ -170,7 +170,7 @@ static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) {
}
break;
case EM_PPC:
- min_reg_cnt = 64;
+ min_reg_cnt = 109;
if (n == 1) {
regs->regs[n].rule = RULE_VAL_OFFSET;
}
@@ -183,7 +183,7 @@ static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) {
}
break;
case EM_PPC64:
- min_reg_cnt = 64;
+ min_reg_cnt = 66;
if (n == 1) {
regs->regs[n].rule = RULE_VAL_OFFSET;
}
@@ -297,6 +297,22 @@ static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) {
regs->regs[n].offset = 1; /* RA */
}
break;
+ case EM_ARC_V2:
+ min_reg_cnt = 32;
+ if (n >= 16 && n <= 25) { /* Callee-saved registers */
+ regs->regs[n].rule = RULE_SAME_VALUE;
+ }
+ else if (n == 27) { /* Frame pointer */
+ regs->regs[n].rule = RULE_SAME_VALUE;
+ }
+ else if (n == 28) { /* Stack pointer */
+ regs->regs[n].rule = RULE_VAL_OFFSET;
+ }
+ else if (n == rules.return_address_register) {
+ regs->regs[n].rule = RULE_REGISTER;
+ regs->regs[n].offset = 31; /* BLINK */
+ }
+ break;
}
}
return regs->regs + reg;
@@ -908,7 +924,7 @@ static void generate_commands(void) {
reg = get_reg(&frame_regs, rules.return_address_register);
if (reg->rule != 0) {
- reg_def = get_reg_by_id(rules.ctx, rules.return_address_register, &rules.reg_id_scope);
+ reg_def = get_reg_by_id(rules.ctx, reg->offset, &rules.reg_id_scope);
generate_register_commands(reg, get_PC_definition(rules.ctx), reg_def);
}
for (i = 0; i < frame_regs.regs_cnt; i++) {
@@ -1055,9 +1071,9 @@ static void read_frame_cie(U8_T fde_pos, U8_T pos) {
" in FDE at %#" PRIx64, pos, fde_pos);
}
dio_SetPos(pos);
- cie_length = dio_ReadU4();
+ cie_length = dio_ReadAddressX(NULL, 4);
if (cie_length == ~(U4_T)0) {
- cie_length = dio_ReadU8();
+ cie_length = dio_ReadAddressX(NULL, 8);
cie_dwarf64 = 1;
}
cie_end = dio_GetPos() + cie_length;
@@ -1140,15 +1156,15 @@ static void read_frame_fde(U8_T IP, U8_T fde_pos) {
int fde_flag = 0;
dio_EnterSection(NULL, rules.section, fde_pos);
- fde_length = dio_ReadU4();
+ fde_length = dio_ReadAddressX(NULL, 4);
assert(fde_length > 0);
if (fde_length == ~(U4_T)0) {
- fde_length = dio_ReadU8();
+ fde_length = dio_ReadAddressX(NULL, 8);
fde_dwarf64 = 1;
}
ref_pos = dio_GetPos();
fde_end = ref_pos + fde_length;
- cie_ref = fde_dwarf64 ? dio_ReadU8() : dio_ReadU4();
+ cie_ref = dio_ReadAddressX(NULL, fde_dwarf64 ? 8 : 4);
if (rules.eh_frame) fde_flag = cie_ref != 0;
else if (fde_dwarf64) fde_flag = cie_ref != ~(U8_T)0;
else fde_flag = cie_ref != ~(U4_T)0;
@@ -1226,10 +1242,10 @@ static void create_search_index(DWARFCache * cache, FrameInfoIndex * index) {
int fde_flag = 0;
fde_pos = dio_GetPos();
- fde_length = dio_ReadU4();
+ fde_length = dio_ReadAddressX(NULL, 4);
if (fde_length == 0) continue;
if (fde_length == ~(U4_T)0) {
- fde_length = dio_ReadU8();
+ fde_length = dio_ReadAddressX(NULL, 8);
fde_dwarf64 = 1;
}
ref_pos = dio_GetPos();
@@ -1247,7 +1263,7 @@ static void create_search_index(DWARFCache * cache, FrameInfoIndex * index) {
" in FDE at %#" PRIx64, fde_length, fde_pos);
}
}
- cie_ref = fde_dwarf64 ? dio_ReadU8() : dio_ReadU4();
+ cie_ref = dio_ReadAddressX(NULL, fde_dwarf64 ? 8 : 4);
if (rules.eh_frame) fde_flag = cie_ref != 0;
else if (fde_dwarf64) fde_flag = cie_ref != ~(U8_T)0;
else fde_flag = cie_ref != ~(U4_T)0;
diff --git a/agent/tcf/services/dwarfio.c b/agent/tcf/services/dwarfio.c
index c097d964..4795b558 100644
--- a/agent/tcf/services/dwarfio.c
+++ b/agent/tcf/services/dwarfio.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006-2023 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.
@@ -31,13 +31,19 @@
#include <tcf/services/dwarfreloc.h>
#include <tcf/services/dwarf.h>
-#define ABBREV_TABLE_SIZE (4 * MEM_USAGE_FACTOR - 1)
+struct DIO_AbbreviationAttr {
+ U2_T mAttr;
+ U2_T mForm;
+ I8_T mValue;
+};
+
+typedef struct DIO_AbbreviationAttr DIO_AbbreviationAttr;
struct DIO_Abbreviation {
U2_T mTag;
U1_T mChildren;
U4_T mAttrLen;
- U2_T mAttrs[2];
+ DIO_AbbreviationAttr mAttrs[1];
};
typedef struct DIO_Abbreviation DIO_Abbreviation;
@@ -55,8 +61,11 @@ struct DIO_Cache {
U1_T * mStringTable;
U8_T mStringTableAddr;
U4_T mStringTableSize;
- DIO_AbbrevSet ** mAbbrevTable;
- U8_T mAbbrevSectionAddr;
+ U1_T * mLineStringTable;
+ U8_T mLineStringTableAddr;
+ U4_T mLineStringTableSize;
+ DIO_AbbrevSet * mAbbrevList;
+ ELF_Section * mAbbrevSection;
};
typedef struct DIO_Cache DIO_Cache;
@@ -72,30 +81,25 @@ static ELF_Section * sSection;
static int sBigEndian;
static int sAddressSize;
static int sRefAddressSize;
+static int sSectionRefSize;
static U1_T * sData;
static U8_T sDataPos;
static U8_T sDataLen;
static DIO_UnitDescriptor * sUnit;
static void dio_CloseELF(ELF_File * File) {
- U4_T n, m;
DIO_Cache * Cache = (DIO_Cache *)File->dwarf_io_cache;
if (Cache == NULL) return;
- if (Cache->mAbbrevTable != NULL) {
- for (n = 0; n < ABBREV_TABLE_SIZE; n++) {
- DIO_AbbrevSet * Set = Cache->mAbbrevTable[n];
- while (Set != NULL) {
- DIO_AbbrevSet * Next = Set->mNext;
- for (m = 0; m < Set->mSize; m++) {
- loc_free(Set->mTable[m]);
- }
- loc_free(Set->mTable);
- loc_free(Set);
- Set = Next;
- }
+ while (Cache->mAbbrevList != NULL) {
+ U4_T m;
+ DIO_AbbrevSet * Set = Cache->mAbbrevList;
+ Cache->mAbbrevList = Set->mNext;
+ for (m = 0; m < Set->mSize; m++) {
+ loc_free(Set->mTable[m]);
}
- loc_free(Cache->mAbbrevTable);
+ loc_free(Set->mTable);
+ loc_free(Set);
}
loc_free(Cache);
File->dwarf_io_cache = NULL;
@@ -130,14 +134,17 @@ void dio_EnterSection(DIO_UnitDescriptor * Unit, ELF_Section * Section, U8_T Off
sAddressSize = Unit->mAddressSize;
if (Unit->mVersion < 3) sRefAddressSize = Unit->mAddressSize;
else sRefAddressSize = Unit->m64bit ? 8 : 4;
+ sSectionRefSize = Unit->m64bit ? 8 : 4;
}
else if (Section->file->elf64) {
sAddressSize = 8;
sRefAddressSize = 8;
+ sSectionRefSize = 8;
}
else {
sAddressSize = 4;
sRefAddressSize = 4;
+ sSectionRefSize = 4;
}
sUnit = Unit;
dio_gEntryPos = 0;
@@ -161,6 +168,10 @@ U1_T * dio_GetDataPtr(void) {
return sData + sDataPos;
}
+ELF_Section * dio_GetSection(void) {
+ return sSection;
+}
+
void dio_Skip(I8_T Bytes) {
if (sDataPos + Bytes > sDataLen) exception(ERR_EOF);
sDataPos += Bytes;
@@ -196,6 +207,15 @@ U2_T dio_ReadU2(void) {
return sBigEndian ? (x0 << 8) | x1 : x0 | (x1 << 8);
}
+U4_T dio_ReadU3(void) {
+ U4_T x0, x1, x2;
+ if (sDataPos + 3 > sDataLen) exception(ERR_EOF);
+ x0 = sData[sDataPos++];
+ x1 = sData[sDataPos++];
+ x2 = sData[sDataPos++];
+ return sBigEndian ? (x0 << 16) | (x1 << 8) | x2 : x0 | (x1 << 8) | (x2 << 16);
+}
+
U4_T dio_ReadU4(void) {
#if defined(__BYTE_ORDER__)
U4_T x;
@@ -283,27 +303,40 @@ I8_T dio_ReadS8LEB128(void) {
}
U8_T dio_ReadAddressX(ELF_Section ** s, int size) {
- U8_T pos = sDataPos;
- switch (size) {
- case 2: {
- U2_T x = dio_ReadU2();
- drl_relocate(sSection, pos, &x, sizeof(x), s);
- return x;
- }
- case 4: {
- U4_T x = dio_ReadU4();
- drl_relocate(sSection, pos, &x, sizeof(x), s);
- return x;
- }
- case 8: {
- U8_T x = dio_ReadU8();
- drl_relocate(sSection, pos, &x, sizeof(x), s);
- return x;
+ if (sSection->relocate != NULL) {
+ U8_T pos = sDataPos;
+ switch (size) {
+ case 1: {
+ U1_T x = dio_ReadU1();
+ drl_relocate(sSection, pos, &x, sizeof(x), s);
+ return x;
+ }
+ case 2: {
+ U2_T x = dio_ReadU2();
+ drl_relocate(sSection, pos, &x, sizeof(x), s);
+ return x;
+ }
+ case 4: {
+ U4_T x = dio_ReadU4();
+ drl_relocate(sSection, pos, &x, sizeof(x), s);
+ return x;
+ }
+ case 8: {
+ U8_T x = dio_ReadU8();
+ drl_relocate(sSection, pos, &x, sizeof(x), s);
+ return x;
+ }
+ }
}
- default:
- str_exception(ERR_INV_DWARF, "Invalid data size");
- return 0;
+ if (s != NULL) *s = NULL;
+ switch (size) {
+ case 1: return dio_ReadU1();
+ case 2: return dio_ReadU2();
+ case 4: return dio_ReadU4();
+ case 8: return dio_ReadU8();
+ default: str_exception(ERR_INV_DWARF, "Invalid data size");
}
+ return 0;
}
U8_T dio_ReadAddress(ELF_Section ** s) {
@@ -318,26 +351,57 @@ char * dio_ReadString(void) {
return Res;
}
-static U1_T * dio_LoadStringTable(ELF_File * File, U8_T * StringTableAddr, U4_T * StringTableSize) {
- DIO_Cache * Cache = dio_GetCache(File);
+void dio_ReadSectionPointer(U2_T Form, ELF_Section ** Section, U8_T * Offs, ELF_Section * DefSection) {
+ if (Form == FORM_ADDR || Form == FORM_SEC_OFFSET) {
+ *Offs = dio_gFormData;
+ *Section = dio_gFormSection;
+ }
+ else {
+ dio_ChkData(Form);
+ *Offs = dio_gFormData;
+ *Section = NULL;
+ }
+ if (*Section == NULL) {
+ *Section = DefSection;
+ }
+ if (*Section != NULL) {
+ *Offs -= (*Section)->addr;
+ }
+}
- if (Cache->mStringTable == NULL) {
- U4_T ID;
- ELF_Section * Section = NULL;
+static void dio_FindSection(ELF_File * File, const char * Name, ELF_Section ** Res) {
+ ELF_Section * Section = NULL;
+ U4_T ID;
- for (ID = 1; ID < File->section_cnt; ID++) {
- if (strcmp(File->sections[ID].name, ".debug_str") == 0) {
- if (Section != NULL) {
- str_exception(ERR_INV_DWARF, "More then one .debug_str section in a file");
- }
- Section = File->sections + ID;
- assert(Section->file == File);
+ for (ID = 1; ID < File->section_cnt; ID++) {
+ if (strcmp(File->sections[ID].name, Name) == 0) {
+ if (Section != NULL) {
+ str_exception(ERR_INV_DWARF, "More than one .debug_str section in a file");
}
+ Section = File->sections + ID;
+ assert(Section->file == File);
}
+ }
- if (Section == NULL) {
- str_exception(ERR_INV_DWARF, "Section .debug_str not found");
- }
+ if (Section == NULL) {
+ str_fmt_exception(ERR_INV_DWARF, "Section %s not found", Name);
+ }
+
+ *Res = Section;
+}
+
+static U1_T * dio_LoadStringTable(ELF_File * File, ELF_Section * Section, U8_T * StringTableAddr, U4_T * StringTableSize) {
+ DIO_Cache * Cache = dio_GetCache(File);
+
+ if (Section != NULL) {
+ if (elf_load(Section) < 0) str_fmt_exception(errno, "Cannot read %s section", Section->name);
+ *StringTableAddr = Section->addr;
+ *StringTableSize = Section->size;
+ return (U1_T *)Section->data;
+ }
+
+ if (Cache->mStringTable == NULL) {
+ dio_FindSection(File, ".debug_str", &Section);
if (elf_load(Section) < 0) {
str_exception(errno, "Cannot read .debug_str section");
@@ -353,9 +417,38 @@ static U1_T * dio_LoadStringTable(ELF_File * File, U8_T * StringTableAddr, U4_T
return Cache->mStringTable;
}
-static U1_T * dio_LoadAltStringTable(ELF_File * File, U8_T * StringTableAddr, U4_T * StringTableSize) {
+static U1_T * dio_LoadLineStringTable(ELF_File * File, ELF_Section * Section, U8_T * StringTableAddr, U4_T * StringTableSize) {
+ DIO_Cache * Cache = dio_GetCache(File);
+
+ if (Section != NULL) {
+ if (elf_load(Section) < 0) str_fmt_exception(errno, "Cannot read %s section", Section->name);
+ *StringTableAddr = Section->addr;
+ *StringTableSize = Section->size;
+ return (U1_T *)Section->data;
+ }
+
+ if (Cache->mLineStringTable == NULL) {
+ ELF_Section * Section = NULL;
+
+ dio_FindSection(File, ".debug_line_str", &Section);
+
+ if (elf_load(Section) < 0) {
+ str_exception(errno, "Cannot read .debug_line_str section");
+ }
+
+ Cache->mLineStringTableAddr = Section->addr;
+ Cache->mLineStringTableSize = (size_t)Section->size;
+ Cache->mLineStringTable = (U1_T *)Section->data;
+ }
+
+ *StringTableAddr = Cache->mLineStringTableAddr;
+ *StringTableSize = Cache->mLineStringTableSize;
+ return Cache->mLineStringTable;
+}
+
+static U1_T * dio_LoadAltStringTable(ELF_File * File, ELF_Section * Section, U8_T * StringTableAddr, U4_T * StringTableSize) {
if (File->dwz_file == NULL) str_exception(errno, "Cannot open DWZ file");
- return dio_LoadStringTable(File->dwz_file, StringTableAddr, StringTableSize);
+ return dio_LoadStringTable(File->dwz_file, Section, StringTableAddr, StringTableSize);
}
static void dio_ReadFormAddr(void) {
@@ -376,15 +469,19 @@ static void dio_ReadFormData(U1_T Size, U8_T Data) {
dio_gFormDataSize = Size;
}
+static void dio_ReadFormDataNoAddr(U1_T Size, U8_T Data) {
+ dio_gFormData = Data;
+ dio_gFormDataSize = Size;
+}
+
static void dio_ReadFormRef(void) {
dio_gFormData = dio_ReadU4();
dio_gFormDataSize = 4;
}
static void dio_ReadFormAltRef(void) {
- int size = sUnit->m64bit ? 8 : 4;
- dio_gFormData = dio_ReadAddressX(&dio_gFormSection, size);
- dio_gFormDataSize = size;
+ dio_gFormData = dio_ReadAddressX(&dio_gFormSection, sSectionRefSize);
+ dio_gFormDataSize = sSectionRefSize;
dio_gFormData += sSection->addr;
}
@@ -417,8 +514,9 @@ static void dio_ReadFormString(void) {
static void dio_ReadFormStringRef(void) {
U8_T StringTableAddr = 0;
U4_T StringTableSize = 0;
- U1_T * StringTable = dio_LoadStringTable(sSection->file, &StringTableAddr, &StringTableSize);
- U8_T Offset = dio_ReadAddressX(&dio_gFormSection, sUnit->m64bit ? 8 : 4) - StringTableAddr;
+ U8_T Offset = dio_ReadAddressX(&dio_gFormSection, sSectionRefSize);
+ U1_T * StringTable = dio_LoadStringTable(sSection->file, dio_gFormSection, &StringTableAddr, &StringTableSize);
+ Offset -= StringTableAddr;
dio_gFormDataAddr = StringTable + Offset;
dio_gFormDataSize = 1;
for (;;) {
@@ -430,11 +528,53 @@ static void dio_ReadFormStringRef(void) {
}
}
+static void dio_ReadFormLineStringRef(void) {
+ U8_T StringTableAddr = 0;
+ U4_T StringTableSize = 0;
+ U8_T Offset = dio_ReadAddressX(&dio_gFormSection, sSectionRefSize);
+ U1_T * StringTable = dio_LoadLineStringTable(sSection->file, dio_gFormSection, &StringTableAddr, &StringTableSize);
+ Offset -= StringTableAddr;
+ dio_gFormDataAddr = StringTable + Offset;
+ dio_gFormDataSize = 1;
+ for (;;) {
+ if (Offset >= StringTableSize) {
+ str_exception(ERR_INV_DWARF, "Invalid FORM_LINE_STRP attribute");
+ }
+ if (StringTable[Offset++] == 0) break;
+ dio_gFormDataSize++;
+ }
+}
+
+static void dio_ReadFormStringIndex(U4_T index) {
+ U8_T Offset = 0;
+ U8_T Pos = sDataPos;
+ ELF_Section * Section = sSection;
+ U8_T StringTableAddr = 0;
+ U4_T StringTableSize = 0;
+ U1_T * StringTable = NULL;
+ if (sUnit->mStrOffsetsSection == NULL) str_exception(ERR_INV_DWARF, "Invalid FORM_STRX attribute");
+ dio_EnterSection(sUnit, sUnit->mStrOffsetsSection, sUnit->mStrOffsetsOffs + index * sSectionRefSize);
+ Offset = dio_ReadAddressX(&dio_gFormSection, sSectionRefSize);
+ StringTable = dio_LoadStringTable(sSection->file, dio_gFormSection, &StringTableAddr, &StringTableSize);
+ Offset -= StringTableAddr;
+ dio_EnterSection(sUnit, Section, Pos);
+ dio_gFormDataAddr = StringTable + Offset;
+ dio_gFormDataSize = 1;
+ for (;;) {
+ if (Offset >= StringTableSize) {
+ str_exception(ERR_INV_DWARF, "Invalid FORM_STRX attribute");
+ }
+ if (StringTable[Offset++] == 0) break;
+ dio_gFormDataSize++;
+ }
+}
+
static void dio_ReadFormAltStringRef(void) {
U8_T StringTableAddr = 0;
U4_T StringTableSize = 0;
- U1_T * StringTable = dio_LoadAltStringTable(sSection->file, &StringTableAddr, &StringTableSize);
- U8_T Offset = dio_ReadAddressX(&dio_gFormSection, sUnit->m64bit ? 8 : 4) - StringTableAddr;
+ U8_T Offset = dio_ReadAddressX(&dio_gFormSection, sSectionRefSize);
+ U1_T * StringTable = dio_LoadAltStringTable(sSection->file, dio_gFormSection, &StringTableAddr, &StringTableSize);
+ Offset -= StringTableAddr;
dio_gFormDataAddr = StringTable + Offset;
dio_gFormDataSize = 1;
for (;;) {
@@ -446,25 +586,50 @@ static void dio_ReadFormAltStringRef(void) {
}
}
+static void dio_ReadFormAddressIndex(U4_T index) {
+ U8_T Pos = sDataPos;
+ ELF_Section * Section = sSection;
+ if (sUnit->mAddrInfoSection == NULL) str_exception(ERR_INV_DWARF, "Invalid FORM_ADDRX attribute");
+ dio_EnterSection(sUnit, sUnit->mAddrInfoSection, sUnit->mAddrInfoOffs + index * sAddressSize);
+ dio_ReadFormAddr();
+ dio_EnterSection(sUnit, Section, Pos);
+}
+
+static void dio_ReadFormLocIndex(U4_T index) {
+ U8_T Pos = sDataPos;
+ ELF_Section * Section = sSection;
+ if (sUnit->mLocListsSection == NULL) str_exception(ERR_INV_DWARF, "Invalid FORM_LOCLISTX attribute");
+ if (index >= sUnit->mLocListsOffsetEntryCount) str_exception(ERR_INV_DWARF, "Invalid FORM_LOCLISTX attribute");
+ dio_EnterSection(sUnit, sUnit->mLocListsSection, sUnit->mLocListsOffs + index * sSectionRefSize);
+ dio_gFormData = (sSectionRefSize > 4 ? dio_ReadU8() : dio_ReadU4()) + sUnit->mLocListsOffs;
+ dio_gFormDataSize = sSectionRefSize;
+ dio_EnterSection(sUnit, Section, Pos);
+}
+
+static void dio_ReadFormRngIndex(U4_T index) {
+ U8_T Pos = sDataPos;
+ ELF_Section * Section = sSection;
+ if (sUnit->mRngListsSection == NULL) str_exception(ERR_INV_DWARF, "Invalid FORM_RNGLISTX attribute");
+ if (index >= sUnit->mRngListsOffsetEntryCount) str_exception(ERR_INV_DWARF, "Invalid FORM_RNGLISTX attribute");
+ dio_EnterSection(sUnit, sUnit->mRngListsSection, sUnit->mRngListsOffs + index * sSectionRefSize);
+ dio_gFormData = (sSectionRefSize > 4 ? dio_ReadU8() : dio_ReadU4()) + sUnit->mRngListsOffs;
+ dio_gFormDataSize = sSectionRefSize;
+ dio_EnterSection(sUnit, Section, Pos);
+}
+
void dio_ReadAttribute(U2_T Attr, U2_T Form) {
dio_gFormSection = NULL;
dio_gFormDataAddr = NULL;
dio_gFormDataSize = 0;
dio_gFormData = 0;
- if (sSection->relocate &&
- (Attr == AT_stmt_list || Attr == AT_ranges ||
- (Attr == AT_high_pc && Form != FORM_ADDR))) {
- U4_T Size = 0;
+ if (sSection->relocate && (Attr == AT_stmt_list || Attr == AT_ranges || Attr == AT_high_pc)) {
+ /* Legacy special case: relocatable FORM_DATAn */
switch (Form) {
- case FORM_DATA2 : Size = 2; break;
- case FORM_DATA4 : Size = 4; break;
- case FORM_DATA8 : Size = 8; break;
- case FORM_SEC_OFFSET: Size = sUnit->m64bit ? 8 : 4; break;
- default: str_exception(ERR_INV_DWARF, "FORM_DATA or FORM_SEC_OFFSET was expected");
+ case FORM_DATA1 : dio_ReadFormData(1, dio_ReadAddressX(&dio_gFormSection, 1)); return;
+ case FORM_DATA2 : dio_ReadFormData(2, dio_ReadAddressX(&dio_gFormSection, 2)); return;
+ case FORM_DATA4 : dio_ReadFormData(4, dio_ReadAddressX(&dio_gFormSection, 4)); return;
+ case FORM_DATA8 : dio_ReadFormData(8, dio_ReadAddressX(&dio_gFormSection, 8)); return;
}
- dio_gFormData = dio_ReadAddressX(&dio_gFormSection, Size);
- dio_gFormDataSize = Size;
- return;
}
switch (Form) {
case FORM_ADDR : dio_ReadFormAddr(); break;
@@ -478,8 +643,9 @@ void dio_ReadAttribute(U2_T Attr, U2_T Form) {
case FORM_DATA2 : dio_ReadFormData(2, dio_ReadU2()); break;
case FORM_DATA4 : dio_ReadFormData(4, dio_ReadU4()); break;
case FORM_DATA8 : dio_ReadFormData(8, dio_ReadU8()); break;
- case FORM_SDATA : dio_ReadFormData(8, dio_ReadS8LEB128()); dio_gFormDataAddr = NULL; break;
- case FORM_UDATA : dio_ReadFormData(8, dio_ReadU8LEB128()); dio_gFormDataAddr = NULL; break;
+ case FORM_DATA16 : dio_ReadFormBlock(16); break;
+ case FORM_SDATA : dio_ReadFormDataNoAddr(8, dio_ReadS8LEB128()); break;
+ case FORM_UDATA : dio_ReadFormDataNoAddr(8, dio_ReadU8LEB128()); break;
case FORM_FLAG : dio_ReadFormData(1, dio_ReadU1()); break;
case FORM_FLAG_PRESENT : dio_ReadFormData(0, 1); break;
case FORM_STRING : dio_ReadFormString(); break;
@@ -491,11 +657,22 @@ void dio_ReadAttribute(U2_T Attr, U2_T Form) {
case FORM_REF4 : dio_ReadFormRelRef(Attr, dio_ReadU4()); break;
case FORM_REF8 : dio_ReadFormRelRef(Attr, dio_ReadU8()); break;
case FORM_REF_UDATA : dio_ReadFormRelRef(Attr, dio_ReadULEB128()); break;
- case FORM_SEC_OFFSET: if (sUnit->m64bit) dio_ReadFormData(8, dio_ReadAddressX(&dio_gFormSection,8));
- else dio_ReadFormData(4, dio_ReadAddressX(&dio_gFormSection,4));
- break;
+ case FORM_SEC_OFFSET : dio_ReadFormData(sSectionRefSize, dio_ReadAddressX(&dio_gFormSection, sSectionRefSize)); break;
case FORM_EXPRLOC : dio_ReadFormBlock(dio_ReadULEB128()); break;
case FORM_REF_SIG8 : dio_ReadFormData(8, dio_ReadU8()); break;
+ case FORM_LINE_STRP : dio_ReadFormLineStringRef(); break;
+ case FORM_STRX : dio_ReadFormStringIndex(dio_ReadULEB128()); break;
+ case FORM_STRX1 : dio_ReadFormStringIndex(dio_ReadU1()); break;
+ case FORM_STRX2 : dio_ReadFormStringIndex(dio_ReadU2()); break;
+ case FORM_STRX3 : dio_ReadFormStringIndex(dio_ReadU3()); break;
+ case FORM_STRX4 : dio_ReadFormStringIndex(dio_ReadU4()); break;
+ case FORM_ADDRX : dio_ReadFormAddressIndex(dio_ReadULEB128()); break;
+ case FORM_ADDRX1 : dio_ReadFormAddressIndex(dio_ReadU1()); break;
+ case FORM_ADDRX2 : dio_ReadFormAddressIndex(dio_ReadU2()); break;
+ case FORM_ADDRX3 : dio_ReadFormAddressIndex(dio_ReadU3()); break;
+ case FORM_ADDRX4 : dio_ReadFormAddressIndex(dio_ReadU4()); break;
+ case FORM_LOCLISTX : dio_ReadFormLocIndex(dio_ReadULEB128()); break;
+ case FORM_RNGLISTX : dio_ReadFormRngIndex(dio_ReadULEB128()); break;
default: str_fmt_exception(ERR_INV_DWARF, "Invalid FORM code 0x%04x", Form);
}
}
@@ -531,6 +708,7 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
for (;;) {
U2_T Attr = 0;
U2_T Form = 0;
+ I8_T Value = 0;
if (Init) {
Form = DWARF_ENTRY_NO_CHILDREN;
if (Abbr != NULL && Abbr->mChildren) Form = DWARF_ENTRY_HAS_CHILDREN;
@@ -538,9 +716,11 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
}
else if (Abbr != NULL) {
if (AttrPos < Abbr->mAttrLen) {
- Attr = Abbr->mAttrs[AttrPos++];
- Form = Abbr->mAttrs[AttrPos++];
+ Attr = Abbr->mAttrs[AttrPos].mAttr;
+ Form = Abbr->mAttrs[AttrPos].mForm;
+ Value = Abbr->mAttrs[AttrPos].mValue;
if (Form == FORM_INDIRECT) Form = (U2_T)dio_ReadULEB128();
+ AttrPos++;
}
}
else if (sDataPos <= dio_gEntryPos + EntrySize - 2) {
@@ -567,10 +747,22 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
case AT_extension:
break;
default:
+ if (TargetAttr == AT_read_base_offsets) {
+ int ok = 0;
+ switch (Attr) {
+ case AT_addr_base:
+ case AT_str_offsets_base:
+ case AT_rnglists_base:
+ case AT_loclists_base:
+ ok = 1;
+ break;
+ }
+ if (ok) break;
+ }
switch (Form) {
case FORM_ADDR : sDataPos += sAddressSize; continue;
case FORM_REF : sDataPos += 4; continue;
- case FORM_GNU_REF_ALT : sDataPos += (sUnit->m64bit ? 8 : 4); continue;
+ case FORM_GNU_REF_ALT : sDataPos += sSectionRefSize; continue;
case FORM_BLOCK1 : sDataPos += dio_ReadU1F(); continue;
case FORM_BLOCK2 : sDataPos += dio_ReadU2(); continue;
case FORM_BLOCK4 : sDataPos += dio_ReadU4(); continue;
@@ -579,26 +771,51 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
case FORM_DATA2 : sDataPos += 2; continue;
case FORM_DATA4 : sDataPos += 4; continue;
case FORM_DATA8 : sDataPos += 8; continue;
+ case FORM_DATA16 : sDataPos += 16; continue;
case FORM_SDATA : dio_ReadS8LEB128(); continue;
case FORM_UDATA : dio_ReadU8LEB128(); continue;
case FORM_FLAG : sDataPos++; continue;
case FORM_FLAG_PRESENT : continue;
case FORM_STRING : dio_ReadFormString(); continue;
- case FORM_STRP : sDataPos += (sUnit->m64bit ? 8 : 4); continue;
- case FORM_GNU_STRP_ALT : sDataPos += (sUnit->m64bit ? 8 : 4); continue;
+ case FORM_STRP : sDataPos += sSectionRefSize; continue;
+ case FORM_LINE_STRP : sDataPos += sSectionRefSize; continue;
+ case FORM_GNU_STRP_ALT : sDataPos += sSectionRefSize; continue;
case FORM_REF_ADDR : sDataPos += sRefAddressSize; continue;
case FORM_REF1 : sDataPos++; continue;
case FORM_REF2 : sDataPos += 2; continue;
case FORM_REF4 : sDataPos += 4; continue;
case FORM_REF8 : sDataPos += 8; continue;
case FORM_REF_UDATA : dio_ReadULEB128(); continue;
- case FORM_SEC_OFFSET : sDataPos += (sUnit->m64bit ? 8 : 4); continue;
+ case FORM_SEC_OFFSET : sDataPos += sSectionRefSize; continue;
case FORM_EXPRLOC : sDataPos += dio_ReadULEB128(); continue;
case FORM_REF_SIG8 : sDataPos += 8; continue;
+ case FORM_IMPLICIT_CONST: continue;
+ case FORM_STRX : dio_ReadULEB128(); continue;
+ case FORM_STRX1 : sDataPos++; continue;
+ case FORM_STRX2 : sDataPos += 2; continue;
+ case FORM_STRX3 : sDataPos += 3; continue;
+ case FORM_STRX4 : sDataPos += 4; continue;
+ case FORM_ADDRX : dio_ReadULEB128(); continue;
+ case FORM_ADDRX1 : sDataPos++; continue;
+ case FORM_ADDRX2 : sDataPos += 2; continue;
+ case FORM_ADDRX3 : sDataPos += 3; continue;
+ case FORM_ADDRX4 : sDataPos += 4; continue;
+ case FORM_LOCLISTX : dio_ReadULEB128(); continue;
+ case FORM_RNGLISTX : dio_ReadULEB128(); continue;
}
}
}
- if (Attr != 0 && Form != 0) dio_ReadAttribute(Attr, Form);
+ if (Attr != 0 && Form != 0) {
+ if (Form == FORM_IMPLICIT_CONST) {
+ dio_gFormSection = NULL;
+ dio_gFormDataAddr = NULL;
+ dio_gFormDataSize = 0;
+ dio_gFormData = Value;
+ }
+ else {
+ dio_ReadAttribute(Attr, Form);
+ }
+ }
if (Tag == TAG_compile_unit || Tag == TAG_partial_unit || Tag == TAG_type_unit) {
if (Attr == AT_sibling && sUnit->mUnitSize == 0) {
dio_ChkRef(Form);
@@ -617,76 +834,20 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
return 1;
}
-static void dio_FindAbbrevTable(void);
-
-void dio_ReadUnit(DIO_UnitDescriptor * Unit, DIO_EntryCallBack CallBack) {
- memset(Unit, 0, sizeof(DIO_UnitDescriptor));
- sUnit = Unit;
- sUnit->mSection = sSection;
- sUnit->mUnitOffs = sDataPos;
- sUnit->m64bit = 0;
- if (strcmp(sSection->name, ".debug") != 0) {
- ELF_Section * Sect = NULL;
- DIO_Cache * Cache = dio_GetCache(sSection->file);
- sUnit->mUnitSize = dio_ReadU4();
- if (sUnit->mUnitSize == 0xffffffffu) {
- sUnit->m64bit = 1;
- sUnit->mUnitSize = dio_ReadU8();
- sUnit->mUnitSize += 12;
- }
- else {
- sUnit->mUnitSize += 4;
- }
- sUnit->mVersion = dio_ReadU2();
- sUnit->mAbbrevTableOffs = dio_ReadAddressX(&Sect, sUnit->m64bit ? 8 : 4);
- sUnit->mAbbrevTableOffs -= Cache->mAbbrevSectionAddr;
- sUnit->mAddressSize = dio_ReadU1();
- if (strcmp(sSection->name, ".debug_types") == 0) {
- sUnit->mTypeSignature = dio_ReadU8();
- sUnit->mTypeOffset = sUnit->m64bit ? dio_ReadU8() : dio_ReadU4();
- }
- dio_FindAbbrevTable();
- }
- else {
- sUnit->mVersion = 1;
- sUnit->mAddressSize = 4;
- }
- sAddressSize = sUnit->mAddressSize;
- if (sUnit->mVersion < 3) sRefAddressSize = sUnit->mAddressSize;
- else sRefAddressSize = sUnit->m64bit ? 8 : 4;
- while (sUnit->mUnitSize == 0 || sDataPos < sUnit->mUnitOffs + sUnit->mUnitSize) {
- dio_ReadEntry(CallBack, 0);
- }
- sUnit = NULL;
-}
-
-#define dio_AbbrevTableHash(Offset) (((unsigned)(Offset)) / 16 % ABBREV_TABLE_SIZE)
-
-void dio_LoadAbbrevTable(ELF_File * File) {
- U8_T TableOffset = 0;
- ELF_Section * Section = NULL;
- static U2_T * AttrBuf = NULL;
+static void dio_LoadAbbrevTable(DIO_UnitDescriptor * Unit) {
+ ELF_File * File = Unit->mSection->file;
+ DIO_Cache * Cache = dio_GetCache(File);
+ static DIO_AbbreviationAttr * AttrBuf = NULL;
static U4_T AttrBufSize = 0;
static DIO_Abbreviation ** AbbrevBuf = NULL;
static U4_T AbbrevBufSize = 0;
U4_T AbbrevBufPos = 0;
- DIO_Cache * Cache = dio_GetCache(File);
- unsigned i;
- if (Cache->mAbbrevTable != NULL) return;
- Cache->mAbbrevTable = (DIO_AbbrevSet **)loc_alloc_zero(sizeof(DIO_AbbrevSet *) * ABBREV_TABLE_SIZE);
-
- for (i = 1; i < File->section_cnt; i++) {
- if (strcmp(File->sections[i].name, ".debug_abbrev") == 0) {
- if (Section != NULL) {
- str_exception(ERR_INV_DWARF, "More then one .debug_abbrev section in a file");
- }
- Section = File->sections + i;
- }
+ if (Cache->mAbbrevSection == NULL) {
+ dio_FindSection(File, ".debug_abbrev", &Cache->mAbbrevSection);
}
- if (Section == NULL) return;
- Cache->mAbbrevSectionAddr = Section->addr;
- dio_EnterSection(NULL, Section, 0);
+
+ dio_EnterSection(Unit, Cache->mAbbrevSection, Unit->mAbbrevTableAddr - Cache->mAbbrevSection->addr);
for (;;) {
U4_T AttrPos = 0;
U2_T Tag = 0;
@@ -694,19 +855,17 @@ void dio_LoadAbbrevTable(ELF_File * File) {
U4_T ID = dio_ReadULEB128();
if (ID == 0) {
/* End of compilation unit */
- U4_T Hash = dio_AbbrevTableHash(TableOffset);
DIO_AbbrevSet * AbbrevSet = (DIO_AbbrevSet *)loc_alloc_zero(sizeof(DIO_AbbrevSet));
- AbbrevSet->mOffset = TableOffset;
+ AbbrevSet->mOffset = Unit->mAbbrevTableAddr - Cache->mAbbrevSection->addr;
AbbrevSet->mTable = (DIO_Abbreviation **)loc_alloc(sizeof(DIO_Abbreviation *) * AbbrevBufPos);
AbbrevSet->mSize = AbbrevBufPos;
- AbbrevSet->mNext = Cache->mAbbrevTable[Hash];
- Cache->mAbbrevTable[Hash] = AbbrevSet;
+ AbbrevSet->mNext = Cache->mAbbrevList;
+ Cache->mAbbrevList = AbbrevSet;
memcpy(AbbrevSet->mTable, AbbrevBuf, sizeof(DIO_Abbreviation *) * AbbrevBufPos);
memset(AbbrevBuf, 0, sizeof(DIO_Abbreviation *) * AbbrevBufPos);
- AbbrevBufPos = 0;
- if (sDataPos >= Section->size) break;
- TableOffset = sDataPos;
- continue;
+ Unit->mAbbrevTable = AbbrevSet->mTable;
+ Unit->mAbbrevTableSize = AbbrevSet->mSize;
+ break;
}
if (ID >= 0x1000000) str_exception(ERR_INV_DWARF, "Invalid abbreviation table");
if (ID >= AbbrevBufPos) {
@@ -733,43 +892,116 @@ void dio_LoadAbbrevTable(ELF_File * File) {
if (Attr == 0 && Form == 0) {
DIO_Abbreviation * Abbr;
if (AbbrevBuf[ID] != NULL) str_exception(ERR_INV_DWARF, "Invalid abbreviation table");
- Abbr = (DIO_Abbreviation *)loc_alloc_zero(sizeof(DIO_Abbreviation) - sizeof(U2_T) * 2 + sizeof(U2_T) * AttrPos);
+ Abbr = (DIO_Abbreviation *)loc_alloc_zero(sizeof(DIO_Abbreviation) - sizeof(DIO_AbbreviationAttr) + sizeof(DIO_AbbreviationAttr) * AttrPos);
Abbr->mTag = Tag;
Abbr->mChildren = Children;
Abbr->mAttrLen = AttrPos;
- memcpy(Abbr->mAttrs, AttrBuf, sizeof(U2_T) * AttrPos);
+ memcpy(Abbr->mAttrs, AttrBuf, sizeof(DIO_AbbreviationAttr) * AttrPos);
AbbrevBuf[ID] = Abbr;
break;
}
- if (AttrBufSize < AttrPos + 2) {
+ if (AttrBufSize <= AttrPos) {
AttrBufSize = AttrPos + 256;
- AttrBuf = (U2_T *)loc_realloc(AttrBuf, sizeof(U2_T) * AttrBufSize);
+ AttrBuf = (DIO_AbbreviationAttr *)loc_realloc(AttrBuf, sizeof(DIO_AbbreviationAttr) * AttrBufSize);
}
- AttrBuf[AttrPos++] = (U2_T)Attr;
- AttrBuf[AttrPos++] = (U2_T)Form;
+ AttrBuf[AttrPos].mAttr = (U2_T)Attr;
+ AttrBuf[AttrPos].mForm = (U2_T)Form;
+ AttrBuf[AttrPos].mValue = Form == FORM_IMPLICIT_CONST ? dio_ReadS8LEB128() : 0;
+ AttrPos++;
}
}
- assert(AbbrevBufPos == 0);
dio_ExitSection();
}
-static void dio_FindAbbrevTable(void) {
- DIO_Cache * Cache = dio_GetCache(sSection->file);
- if (Cache->mAbbrevTable != NULL) {
- U4_T Hash = dio_AbbrevTableHash(sUnit->mAbbrevTableOffs);
- DIO_AbbrevSet * AbbrevSet = Cache->mAbbrevTable[Hash];
- while (AbbrevSet != NULL) {
- if (AbbrevSet->mOffset == sUnit->mAbbrevTableOffs) {
- sUnit->mAbbrevTable = AbbrevSet->mTable;
- sUnit->mAbbrevTableSize = AbbrevSet->mSize;
- return;
+static void dio_ReadUnitBaseOffsets(U2_T Tag, U2_T Attr, U2_T Form) {
+ ELF_Section * Section = NULL;
+ ELF_File * File = sSection->file;
+
+ switch (Attr) {
+ case AT_addr_base:
+ dio_FindSection(File, ".debug_addr", &Section);
+ dio_ReadSectionPointer(Form, &sUnit->mAddrInfoSection, &sUnit->mAddrInfoOffs, Section);
+ break;
+ case AT_str_offsets_base:
+ dio_FindSection(File, ".debug_str_offsets", &Section);
+ dio_ReadSectionPointer(Form, &sUnit->mStrOffsetsSection, &sUnit->mStrOffsetsOffs, Section);
+ break;
+ case AT_rnglists_base:
+ dio_FindSection(File, ".debug_rnglists", &Section);
+ dio_ReadSectionPointer(Form, &sUnit->mRngListsSection, &sUnit->mRngListsOffs, Section);
+ break;
+ case AT_loclists_base:
+ dio_FindSection(File, ".debug_loclists", &Section);
+ dio_ReadSectionPointer(Form, &sUnit->mLocListsSection, &sUnit->mLocListsOffs, Section);
+ break;
+ }
+}
+
+void dio_ReadUnit(DIO_UnitDescriptor * Unit, DIO_EntryCallBack CallBack) {
+ memset(Unit, 0, sizeof(DIO_UnitDescriptor));
+ sUnit = Unit;
+ sUnit->mSection = sSection;
+ sUnit->mUnitOffs = sDataPos;
+ sUnit->m64bit = 0;
+ if (strcmp(sSection->name, ".debug") == 0) {
+ sUnit->mVersion = 1;
+ sUnit->mAddressSize = 4;
+ }
+ else {
+ ELF_Section * Sect = NULL;
+ U8_T DataPos = 0;
+ sUnit->mUnitSize = dio_ReadAddressX(&Sect, 4);
+ if (sUnit->mUnitSize == 0xffffffff) {
+ sUnit->m64bit = 1;
+ sUnit->mUnitSize = dio_ReadU8();
+ sUnit->mUnitSize += 12;
+ }
+ else {
+ sUnit->mUnitSize += 4;
+ }
+ sUnit->mVersion = dio_ReadU2();
+ if (sUnit->mVersion < 5) {
+ sUnit->mAbbrevTableAddr = dio_ReadAddressX(&Sect, sUnit->m64bit ? 8 : 4);
+ sUnit->mAddressSize = dio_ReadU1();
+ if (strcmp(sSection->name, ".debug_types") == 0) {
+ sUnit->mTypeSignature = dio_ReadU8();
+ sUnit->mTypeOffset = sUnit->m64bit ? dio_ReadU8() : dio_ReadU4();
+ }
+ }
+ else {
+ sUnit->mUnitType = dio_ReadU1();
+ sUnit->mAddressSize = dio_ReadU1();
+ sUnit->mAbbrevTableAddr = dio_ReadAddressX(&Sect, sUnit->m64bit ? 8 : 4);
+ switch (sUnit->mUnitType) {
+ case DW_UT_skeleton:
+ case DW_UT_split_compile:
+ sUnit->mCompUnitID = dio_ReadU8();
+ break;
+ case DW_UT_type:
+ case DW_UT_split_type:
+ sUnit->mTypeSignature = dio_ReadU8();
+ sUnit->mTypeOffset = sUnit->m64bit ? dio_ReadU8() : dio_ReadU4();
+ break;
}
- AbbrevSet = AbbrevSet->mNext;
}
+ DataPos = sDataPos;
+ dio_ExitSection();
+ dio_LoadAbbrevTable(Unit);
+ dio_EnterSection(Unit, Unit->mSection, DataPos);
}
- sUnit->mAbbrevTable = NULL;
- sUnit->mAbbrevTableSize = 0;
- str_exception(ERR_INV_DWARF, "Invalid abbreviation table offset");
+ sAddressSize = sUnit->mAddressSize;
+ if (sUnit->mVersion < 3) sRefAddressSize = sUnit->mAddressSize;
+ else sRefAddressSize = sUnit->m64bit ? 8 : 4;
+ sSectionRefSize = sUnit->m64bit ? 8 : 4;
+ if (sUnit->mVersion >= 5) {
+ U8_T DataPos = sDataPos;
+ dio_ReadEntry(dio_ReadUnitBaseOffsets, AT_read_base_offsets);
+ sDataPos = DataPos;
+ }
+ while (sUnit->mUnitSize == 0 || sDataPos < sUnit->mUnitOffs + sUnit->mUnitSize) {
+ dio_ReadEntry(CallBack, 0);
+ }
+ sUnit = NULL;
}
void dio_ChkFlag(U2_T Form) {
@@ -799,6 +1031,11 @@ void dio_ChkRef(U2_T Form) {
void dio_ChkAddr(U2_T Form) {
switch (Form) {
case FORM_ADDR :
+ case FORM_ADDRX :
+ case FORM_ADDRX1 :
+ case FORM_ADDRX2 :
+ case FORM_ADDRX3 :
+ case FORM_ADDRX4 :
return;
}
str_exception(ERR_INV_DWARF, "FORM_ADDR expected");
@@ -813,6 +1050,7 @@ void dio_ChkData(U2_T Form) {
case FORM_SDATA :
case FORM_UDATA :
case FORM_SEC_OFFSET:
+ case FORM_IMPLICIT_CONST:
return;
}
str_exception(ERR_INV_DWARF, "FORM_DATA expected");
@@ -828,6 +1066,7 @@ void dio_ChkBlock(U2_T Form, U1_T ** Buf, size_t * Size) {
case FORM_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
+ case FORM_DATA16 :
case FORM_EXPRLOC :
case FORM_SEC_OFFSET:
assert(dio_gFormDataAddr >= sSection->data);
@@ -841,9 +1080,18 @@ void dio_ChkBlock(U2_T Form, U1_T ** Buf, size_t * Size) {
}
void dio_ChkString(U2_T Form) {
- if (Form == FORM_STRING) return;
- if (Form == FORM_STRP) return;
- if (Form == FORM_GNU_STRP_ALT) return;
+ switch (Form) {
+ case FORM_STRING:
+ case FORM_STRP:
+ case FORM_LINE_STRP:
+ case FORM_GNU_STRP_ALT:
+ case FORM_STRX:
+ case FORM_STRX1:
+ case FORM_STRX2:
+ case FORM_STRX3:
+ case FORM_STRX4:
+ return;
+ }
str_exception(ERR_INV_DWARF, "FORM_STRING expected");
}
diff --git a/agent/tcf/services/dwarfio.h b/agent/tcf/services/dwarfio.h
index 60fd13b5..69654d28 100644
--- a/agent/tcf/services/dwarfio.h
+++ b/agent/tcf/services/dwarfio.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2014 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006-2023 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.
@@ -31,14 +31,31 @@ typedef struct DIO_UnitDescriptor {
ELF_Section * mSection;
U2_T mVersion;
U1_T m64bit;
+ U1_T mUnitType;
U1_T mAddressSize;
U8_T mUnitOffs;
U8_T mUnitSize;
- U8_T mAbbrevTableOffs;
+ U8_T mAbbrevTableAddr;
+ U8_T mCompUnitID;
U8_T mTypeSignature;
U8_T mTypeOffset;
+
struct DIO_Abbreviation ** mAbbrevTable;
U4_T mAbbrevTableSize;
+
+ ELF_Section * mStrOffsetsSection;
+ U8_T mStrOffsetsOffs;
+
+ ELF_Section * mAddrInfoSection;
+ U8_T mAddrInfoOffs;
+
+ ELF_Section * mLocListsSection;
+ U8_T mLocListsOffs;
+ U4_T mLocListsOffsetEntryCount;
+
+ ELF_Section * mRngListsSection;
+ U8_T mRngListsOffs;
+ U4_T mRngListsOffsetEntryCount;
} DIO_UnitDescriptor;
extern U8_T dio_gEntryPos;
@@ -56,9 +73,11 @@ extern void dio_SetPos(U8_T Pos);
extern void dio_Read(U1_T * Buf, U4_T Size);
extern U8_T dio_GetPos(void); /* Offset in the section */
extern U1_T * dio_GetDataPtr(void);
+extern ELF_Section * dio_GetSection(void);
extern U1_T dio_ReadU1(void);
extern U2_T dio_ReadU2(void);
+extern U4_T dio_ReadU3(void);
extern U4_T dio_ReadU4(void);
extern U8_T dio_ReadU8(void);
@@ -77,6 +96,8 @@ extern U8_T dio_ReadAddress(ELF_Section ** s);
extern char * dio_ReadString(void);
+extern void dio_ReadSectionPointer(U2_T Form, ELF_Section ** Section, U8_T * Offs, ELF_Section * DefSection);
+
extern void dio_ReadAttribute(U2_T Attr, U2_T Form);
typedef void (*DIO_EntryCallBack)(U2_T /* Tag */, U2_T /* Attr */, U2_T /* Form */);
@@ -93,8 +114,6 @@ extern int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T Attr);
#define DWARF_ENTRY_NO_CHILDREN 2
#define DWARF_ENTRY_HAS_CHILDREN 3
-extern void dio_LoadAbbrevTable(ELF_File * File);
-
extern void dio_ChkFlag(U2_T Form);
extern void dio_ChkRef(U2_T Form);
extern void dio_ChkAddr(U2_T Form);
diff --git a/agent/tcf/services/elf-symbols.h b/agent/tcf/services/elf-symbols.h
index 989e09cb..a199a4a6 100644
--- a/agent/tcf/services/elf-symbols.h
+++ b/agent/tcf/services/elf-symbols.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Wind River Systems, Inc. and others.
+ * Copyright (c) 2012-2021 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.
@@ -49,7 +49,7 @@ extern int elf_enumerate_symbols(Context * ctx, const char * file_name, Enumerat
* On error returns -1 and sets errno.
* On success returns 0.
*/
-extern int elf_symbol_info(Symbol * sym, ELF_SymbolInfo * elf_sym);
+extern int elf_symbol_info(const Symbol * sym, ELF_SymbolInfo * elf_sym);
/*
* Get the TCF Symbol from ELF symbol info.
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index 4bc96d71..61561d20 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -169,7 +169,7 @@ static void ini_value(Value * v) {
v->ctx = expression_context;
}
-void set_value(Value * v, void * data, size_t size, int be) {
+static void set_no_value(Value * v) {
v->sym = NULL;
v->reg = NULL;
v->loc = NULL;
@@ -179,11 +179,18 @@ void set_value(Value * v, void * data, size_t size, int be) {
v->func_cb = NULL;
v->field_cb = NULL;
v->sym_list = NULL;
- v->size = (ContextAddress)size;
- v->big_endian = be;
+ v->size = 0;
+ v->big_endian = 0;
v->binary_scale = 0;
v->decimal_scale = 0;
v->bit_stride = 0;
+ v->value = NULL;
+}
+
+void set_value(Value * v, void * data, size_t size, int be) {
+ set_no_value(v);
+ v->big_endian = be;
+ v->size = (ContextAddress)size;
v->value = tmp_alloc(size);
if (data == NULL) memset(v->value, 0, size);
else memcpy(v->value, data, size);
@@ -202,7 +209,7 @@ static void set_int_value(Value * v, size_t size, uint64_t n) {
case 2: buf.u16 = (uint16_t)n; break;
case 4: buf.u32 = (uint32_t)n; break;
case 8: buf.u64 = n; break;
- default: assert(0);
+ default: buf.u64 = 0; assert(0);
}
set_value(v, &buf, size, big_endian);
}
@@ -215,7 +222,7 @@ static void set_fp_value(Value * v, size_t size, double n) {
switch (size) {
case 4: buf.f = (float)n; break;
case 8: buf.d = n; break;
- default: assert(0);
+ default: buf.d = 0; assert(0);
}
set_value(v, &buf, size, big_endian);
}
@@ -1075,9 +1082,14 @@ static int sym2value(int mode, Symbol * sym, Value * v) {
v->remote = 1;
}
else {
- if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0 &&
- state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
- v->reg = state->pieces->reg;
+ if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0) {
+ LocationPiece * p = state->pieces;
+ if (p->value != NULL) {
+ set_value(v, p->value, p->size, loc_info->big_endian);
+ }
+ if (p->reg != NULL && p->reg->size == p->size && state->ctx == v->ctx) {
+ v->reg = p->reg;
+ }
}
v->loc = state;
}
@@ -1122,9 +1134,14 @@ static int sym2value(int mode, Symbol * sym, Value * v) {
v->remote = 1;
}
else {
- if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0 &&
- state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
- v->reg = state->pieces->reg;
+ if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0) {
+ LocationPiece * p = state->pieces;
+ if (p->value != NULL) {
+ set_value(v, p->value, p->size, loc_info->big_endian);
+ }
+ if (p->reg != NULL && p->reg->size == p->size) {
+ v->reg = p->reg;
+ }
}
v->loc = state;
}
@@ -1228,7 +1245,7 @@ static int builtin_identifier(int mode, char * name, Value * v) {
next_sy();
ini_value(v);
if (mode != MODE_NORMAL) {
- set_ctx_word_value(v, addr);
+ set_ctx_word_value(v, (ContextAddress)addr);
v->type_class = TYPE_CLASS_POINTER;
return SYM_CLASS_VALUE;
}
@@ -1467,7 +1484,6 @@ static int type_name(int mode, Symbol ** type) {
char * name = NULL;
int sym_class;
SYM_FLAGS sym_flags = 0;
- int name_cnt = 0;
while (text_sy == SY_NAME) {
if (strcmp((const char *)(text_val.value), "const") == 0) {
@@ -1510,7 +1526,6 @@ static int type_name(int mode, Symbol ** type) {
name = tmp_strdup2(name, " ");
name = tmp_strdup2(name, (char *)text_val.value);
}
- name_cnt++;
next_sy();
}
while (text_sy == SY_NAME);
@@ -1766,7 +1781,7 @@ static int64_t to_int_fixed_point(int mode, Value * v) {
}
static uint64_t to_uns_fixed_point(int mode, Value * v) {
- if (v->size == 0 || mode != MODE_NORMAL) {
+ if ((v->remote && v->size == 0) || mode != MODE_NORMAL) {
if (v->remote) {
v->value = tmp_alloc_zero((size_t)v->size);
v->remote = 0;
@@ -2306,7 +2321,7 @@ static void evaluate_symbol_location(Symbol * sym, ContextAddress obj_addr,
ContextAddress index, LocationExpressionState ** loc, int * be) {
LocationInfo * loc_info = NULL;
StackFrame * frame_info = NULL;
- uint64_t args[2];
+ uint64_t * args = (uint64_t *)tmp_alloc(sizeof(uint64_t) * 2);
args[0] = obj_addr;
args[1] = index;
if (get_location_info(sym, &loc_info) < 0) {
@@ -2387,16 +2402,11 @@ static void op_field(int mode, Value * v) {
int sym_class = 0;
LocationExpressionState * loc = NULL;
int be = 0;
- void * struct_value = NULL;
- ContextAddress struct_size = 0;
if (v->remote) {
find_field(mode, v->type, v->address, name, id, &sym, &loc, &be);
}
else {
- load_value(v);
- struct_value = v->value;
- struct_size = v->size;
find_field(mode, v->type, 0, name, id, &sym, &loc, &be);
}
if (sym == NULL) {
@@ -2426,6 +2436,17 @@ static void op_field(int mode, Value * v) {
v->sym = sym;
}
else {
+ SYM_FLAGS flags = 0;
+ void * struct_value = NULL;
+ size_t struct_size = 0;
+ if (get_symbol_flags(sym, &flags) < 0) {
+ error(errno, "Cannot retrieve symbol flags");
+ }
+ if (!v->remote && (flags & SYM_FLAG_MEMBER) != 0) {
+ load_value(v);
+ struct_value = v->value;
+ struct_size = (size_t)v->size;
+ }
if (get_symbol_type_class(sym, &v->type_class) < 0) {
error(errno, "Cannot retrieve symbol type class");
}
@@ -2433,21 +2454,20 @@ static void op_field(int mode, Value * v) {
error(errno, "Cannot retrieve field size");
}
if (mode == MODE_NORMAL) {
- if (struct_value == NULL && loc->pieces_cnt > 0) {
+ if (loc->pieces_cnt > 0) {
size_t size = 0;
void * value = NULL;
StackFrame * frame_info = NULL;
if (expression_frame != STACK_NO_FRAME && get_frame_info(expression_context, expression_frame, &frame_info) < 0) {
error(errno, "Cannot get stack frame info");
}
- read_location_pieces(expression_context, frame_info,
- loc->pieces, loc->pieces_cnt, be, &value, &size);
+ read_location_pieces_local(expression_context, frame_info,
+ struct_value, struct_size, loc->pieces, loc->pieces_cnt, be, &value, &size);
if (size > v->size) size = (size_t)v->size;
set_value(v, value, size, be);
sign_extend(v, loc);
}
- else {
- if (loc->stk_pos != 1) error(ERR_OTHER, "Invalid location expression");
+ else if (loc->stk_pos == 1) {
if (struct_value != NULL) {
if (loc->stk[0] + v->size > struct_size) error(ERR_OTHER, "Invalid location expression");
v->value = (uint8_t *)struct_value + (size_t)loc->stk[0];
@@ -2455,10 +2475,14 @@ static void op_field(int mode, Value * v) {
}
else {
v->address = (ContextAddress)loc->stk[0];
- assert(v->remote);
+ assert(v->remote || (flags & SYM_FLAG_MEMBER) == 0);
+ v->remote = 1;
}
set_value_endianness(v, sym, v->type);
}
+ else {
+ error(ERR_OTHER, "Invalid location expression");
+ }
}
}
v->loc = loc;
@@ -2616,23 +2640,27 @@ static void op_index(int mode, Value * v) {
}
static void op_addr(int mode, Value * v) {
+#if ENABLE_Symbols
+ Symbol * type = v->type;
+#endif
if (mode == MODE_SKIP) return;
if (v->function) {
assert(v->type_class == TYPE_CLASS_POINTER);
+#if ENABLE_Symbols
+ type = NULL;
+#endif
+ }
+ else if (mode == MODE_TYPE) {
+ set_no_value(v);
+ v->type_class = TYPE_CLASS_POINTER;
+ v->constant = 0;
+ v->type = NULL;
}
else if (v->remote) {
set_ctx_word_value(v, v->address);
v->type_class = TYPE_CLASS_POINTER;
v->constant = 0;
-#if ENABLE_Symbols
- if (v->type != NULL) {
- if (get_array_symbol(v->type, 0, &v->type)) {
- error(errno, "Cannot get pointer type");
- }
- }
-#else
v->type = NULL;
-#endif
}
else if (v->reg != NULL && v->reg->memory_context != NULL) {
Context * ctx = id2ctx(v->reg->memory_context);
@@ -2647,19 +2675,28 @@ static void op_addr(int mode, Value * v) {
v->loc->pieces_cnt = v->loc->pieces_max = 1;
v->loc->pieces->value = v->value;
v->loc->pieces->size = (size_t)v->size;
+ v->value = NULL;
}
+ v->type = NULL;
}
- else if (v->loc != NULL && v->loc->pieces_cnt == 1 &&
- v->loc->pieces->implicit_pointer == 0 && v->loc->pieces->optimized_away == 0 &&
- v->loc->pieces->reg == NULL && v->loc->pieces->value == NULL && v->loc->pieces->bit_offs == 0) {
- set_ctx_word_value(v, v->loc->pieces->addr);
+ else if (v->loc != NULL) {
+ unsigned i;
+ LocationExpressionState * loc = v->loc;
+ for (i = 0; i < loc->pieces_cnt; i++) loc->pieces[i].implicit_pointer++;
+ set_no_value(v);
v->type_class = TYPE_CLASS_POINTER;
v->constant = 0;
v->type = NULL;
+ v->loc = loc;
}
else {
error(ERR_INV_EXPRESSION, "Invalid '&': the value has no address");
}
+#if ENABLE_Symbols
+ if (type != NULL && get_array_symbol(type, 0, &v->type) < 0) {
+ error(errno, "Cannot get pointer type");
+ }
+#endif
}
static void unary_expression(int mode, Value * v);
@@ -3230,6 +3267,9 @@ static void lazy_unary_expression(int mode, Value * v) {
if (get_symbol_size(type, &type_size) < 0) {
error(errno, "Cannot retrieve symbol size");
}
+ if (type_class == TYPE_CLASS_POINTER && type_size == 0) {
+ error(ERR_OTHER, "Context does not support memory access");
+ }
if (v->remote && v->size == type_size) {
/* A type cast can be an l-value expression as long as the size does not change */
int ok = 0;
diff --git a/agent/tcf/services/filesystem.c b/agent/tcf/services/filesystem.c
index e8bcc71f..dc484fb7 100644
--- a/agent/tcf/services/filesystem.c
+++ b/agent/tcf/services/filesystem.c
@@ -32,7 +32,7 @@
# include <ctype.h>
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
-# include <Windows.h>
+# include <windows.h>
#endif
#if defined(_WRS_KERNEL)
# include <ioLib.h>
diff --git a/agent/tcf/services/linenumbers_elf.c b/agent/tcf/services/linenumbers_elf.c
index 9d08bb8a..e10cca4f 100644
--- a/agent/tcf/services/linenumbers_elf.c
+++ b/agent/tcf/services/linenumbers_elf.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -49,7 +49,6 @@
static int compare_path(Channel * chnl, Context * ctx, const char * file, const char * pwd, const char * dir, const char * name) {
int i, j;
- char buf[FILE_PATH_SIZE];
char * full_name = NULL;
if (file == NULL) return 0;
@@ -66,13 +65,13 @@ static int compare_path(Channel * chnl, Context * ctx, const char * file, const
full_name = (char *)name;
}
else if (dir != NULL && is_absolute_path(dir)) {
- snprintf(full_name = buf, sizeof(buf), "%s/%s", dir, name);
+ full_name = tmp_printf("%s/%s", dir, name);
}
else if (dir != NULL && pwd != NULL) {
- snprintf(full_name = buf, sizeof(buf), "%s/%s/%s", pwd, dir, name);
+ full_name = tmp_printf("%s/%s/%s", pwd, dir, name);
}
else if (pwd != NULL) {
- snprintf(full_name = buf, sizeof(buf), "%s/%s", pwd, name);
+ full_name = tmp_printf("%s/%s", pwd, name);
}
else {
full_name = (char *)name;
@@ -81,10 +80,13 @@ static int compare_path(Channel * chnl, Context * ctx, const char * file, const
j = strlen(full_name);
if (i <= j && strcmp(file, full_name + j - i) == 0) return 1;
#if SERVICE_PathMap
- {
- char * s = apply_path_map(chnl, ctx, full_name, PATH_MAP_TO_CLIENT);
- if (s != full_name) {
- full_name = canonic_path_map_file_name(s);
+ if (apply_path_map(chnl, ctx, full_name, PATH_MAP_TO_CLIENT) != full_name) {
+ unsigned n = 0;
+ unsigned cnt = 0;
+ char ** buf = NULL;
+ get_apply_path_map_results(&cnt, &buf);
+ for (n = 0; n < cnt; n++) {
+ full_name = canonic_path_map_file_name(buf[n]);
j = strlen(full_name);
if (i <= j && strcmp(file, full_name + j - i) == 0) return 1;
}
@@ -175,9 +177,7 @@ static void call_client(Context * ctx, CompUnit * unit, LineNumbersState * state
area.file = file_info->mName;
}
else {
- char buf[FILE_PATH_SIZE];
- snprintf(buf, sizeof(buf), "%s/%s", file_info->mDir, file_info->mName);
- area.file = state->mFileName = loc_strdup(buf);
+ area.file = state->mFileName = loc_printf("%s/%s", file_info->mDir, file_info->mName);
}
area.file_mtime = file_info->mModTime;
@@ -336,7 +336,7 @@ int line_to_address(Context * ctx, const char * file_name, int line, int column,
}
else {
err = trap.error;
- trace(LOG_ALWAYS, "Cannot load DWARF line numbers section: %s", errno_to_str(err));
+ trace(LOG_ALWAYS, "Cannot read line numbers from '%s': %s", file->name, errno_to_str(err));
break;
}
}
diff --git a/agent/tcf/services/pathmap.c b/agent/tcf/services/pathmap.c
index 4018c121..9fda711e 100644
--- a/agent/tcf/services/pathmap.c
+++ b/agent/tcf/services/pathmap.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2013 Wind River Systems, Inc. and others.
+ * Copyright (c) 2010-2021 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.
@@ -34,7 +34,7 @@
#endif
static int is_separator(const char c) {
- return ((c == '/') || (c == '\\'));
+ return c == '/' || c == '\\';
}
char * canonic_path_map_file_name(const char * fnm) {
@@ -80,11 +80,25 @@ char * canonic_path_map_file_name(const char * fnm) {
}
int is_absolute_path(const char * fnm) {
- if (fnm[0] == '/') return 1;
- if (fnm[0] == '\\') return 1;
+ if (is_separator(fnm[0])) return 1;
if (fnm[0] != 0 && fnm[1] == ':') {
- if (fnm[2] == '/') return 1;
- if (fnm[2] == '\\') return 1;
+ /* Windows absolute path like C:/ */
+ if (is_separator(fnm[2])) return 1;
+ }
+ if (fnm[0] == '%') {
+ /* Synopsys compiler uses macros like %PROCDIR% as directory names */
+ /* Such name needs to be treated as an absolute path */
+ unsigned i = 1;
+ for (;;) {
+ char ch = fnm[i++];
+ if (ch == 0) break;
+ if (is_separator(ch)) break;
+ if (ch == '%') {
+ if (fnm[i] == 0) return 1;
+ if (is_separator(fnm[i])) return 1;
+ break;
+ }
+ }
}
return 0;
}
@@ -134,6 +148,10 @@ static unsigned listener_max = 0;
static TCFBroadcastGroup * broadcast_group = NULL;
+static unsigned fnm_max = 0;
+static unsigned fnm_cnt = 0;
+static char ** fnm_buf = NULL;
+
static void event_path_map_changed(void) {
OutputStream * out = &broadcast_group->out;
@@ -332,7 +350,7 @@ static int update_rule(PathMapRule * r, PathMapRuleAttribute * new_attrs) {
return diff;
}
-static char * map_file_name(Context * ctx, PathMap * m, char * fnm, int mode) {
+static void map_file_name(Context * ctx, PathMap * m, char * fnm, int mode) {
unsigned i, k;
for (i = 0; i < m->rules_cnt; i++) {
@@ -400,20 +418,26 @@ static char * map_file_name(Context * ctx, PathMap * m, char * fnm, int mode) {
buf = tmp_strdup2(r->dst, fnm + k);
}
- if (mode != PATH_MAP_TO_LOCAL || stat(buf, &st) == 0) return buf;
+ if (mode != PATH_MAP_TO_LOCAL || stat(buf, &st) == 0) {
+ if (fnm_max <= fnm_cnt) {
+ fnm_max += 16;
+ fnm_buf = (char **)tmp_realloc(fnm_buf, fnm_max * sizeof(char *));
+ }
+ fnm_buf[fnm_cnt++] = buf;
+ }
}
-
- return fnm;
}
char * apply_path_map(Channel * c, Context * ctx, char * fnm, int mode) {
char * cnm = canonic_path_map_file_name(fnm);
+ fnm_cnt = 0;
+ fnm_max = 0;
+ fnm_buf = NULL;
if (c == NULL) {
LINK * l = maps.next;
while (l != &maps) {
PathMap * m = maps2map(l);
- char * lnm = map_file_name(ctx, m, cnm, mode);
- if (lnm != cnm) return lnm;
+ map_file_name(ctx, m, cnm, mode);
l = l->next;
}
}
@@ -423,21 +447,21 @@ char * apply_path_map(Channel * c, Context * ctx, char * fnm, int mode) {
Channel * h = proxy_get_host_channel(c);
if (h != NULL) {
m = find_map(h);
- if (m != NULL) {
- char * lnm = map_file_name(ctx, m, cnm, mode);
- if (lnm != cnm) return lnm;
- }
+ if (m != NULL) map_file_name(ctx, m, cnm, mode);
}
#endif
m = find_map(c);
- if (m != NULL) {
- char * lnm = map_file_name(ctx, m, cnm, mode);
- if (lnm != cnm) return lnm;
- }
+ if (m != NULL) map_file_name(ctx, m, cnm, mode);
}
+ if (fnm_cnt > 0) return fnm_buf[0];
return fnm;
}
+void get_apply_path_map_results(unsigned * cnt, char *** buf) {
+ *cnt = fnm_cnt;
+ *buf = fnm_buf;
+}
+
void iterate_path_map_rules(Channel * channel, IteratePathMapsCallBack * callback, void * args) {
PathMap * m = find_map(channel);
if (m != NULL) {
diff --git a/agent/tcf/services/pathmap.h b/agent/tcf/services/pathmap.h
index cac67313..4c155e36 100644
--- a/agent/tcf/services/pathmap.h
+++ b/agent/tcf/services/pathmap.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2013 Wind River Systems, Inc. and others.
+ * Copyright (c) 2010-2021 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.
@@ -122,8 +122,13 @@ extern void delete_all_path_mappings(void);
* Translate debug file name to local or target file name using file path mapping table of given channel.
* If channel = NULL, search all maps until translation is found.
* Return pointer to tmp_alloc()-ed buffer that contains translated file name.
+ *
+ * In certain cases multiple path mapping match the file name.
+ * The function returns first match.
+ * The rest of translated file names can be retrieved with get_apply_path_map_results().
*/
extern char * apply_path_map(Channel * channel, Context * ctx, char * file_name, int mode);
+extern void get_apply_path_map_results(unsigned * cnt, char *** buf);
/*
* Read new path map from the given input stream.
diff --git a/agent/tcf/services/processes.c b/agent/tcf/services/processes.c
index 94a9dcb6..32f46d3d 100644
--- a/agent/tcf/services/processes.c
+++ b/agent/tcf/services/processes.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -100,7 +100,7 @@ typedef struct AttachDoneArgs {
struct ChildProcess {
LINK link;
- int pid;
+ pid_t pid;
int tty;
int got_output;
TCFBroadcastGroup * bcg;
@@ -149,7 +149,7 @@ static LINK prs_list = TCF_LIST_INIT(prs_list);
static SEM_ID prs_list_lock = NULL;
#endif
-static ChildProcess * find_process(int pid) {
+static ChildProcess * find_process(pid_t pid) {
LINK * qhp = &prs_list;
LINK * qp = qhp->next;
@@ -1528,7 +1528,7 @@ static int start_process_imp(Channel * c, char ** envp, const char * dir, const
#endif
-static void waitpid_listener(int pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
+static void waitpid_listener(pid_t pid, int exited, int exit_code, int signal, int event_code, int syscall, void * args) {
if (exited) {
ChildProcess * prs = find_process(pid);
if (prs) {
diff --git a/agent/tcf/services/registers.c b/agent/tcf/services/registers.c
index 9afd7a6b..c7f0eb73 100644
--- a/agent/tcf/services/registers.c
+++ b/agent/tcf/services/registers.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -442,6 +442,7 @@ void send_event_register_changed(const char * id) {
}
void send_event_register_definitions_changed(void) {
+ invalidate_register_ids();
notify_definitions_changed = 1;
/* Delay notifications until cache transaction is committed */
if (cache_transaction_id() == 0) flush_notifications();
@@ -643,10 +644,10 @@ static void check_location_list(Location * locs, unsigned cnt, int setm) {
if (id2register(loc->id, &loc->ctx, &loc->frame, &loc->reg_def) < 0) exception(errno);
if (loc->ctx->exited) exception(ERR_ALREADY_EXITED);
- if ((loc->ctx->reg_access & setm ? REG_ACCESS_WR_STOP : REG_ACCESS_RD_STOP) != 0) {
+ if ((loc->ctx->reg_access & (setm ? REG_ACCESS_WR_STOP : REG_ACCESS_RD_STOP)) != 0) {
check_all_stopped(loc->ctx);
}
- if ((loc->ctx->reg_access & setm ? REG_ACCESS_WR_RUNNING : REG_ACCESS_RD_RUNNING) == 0) {
+ if ((loc->ctx->reg_access & (setm ? REG_ACCESS_WR_RUNNING : REG_ACCESS_RD_RUNNING)) == 0) {
if (context_has_state(loc->ctx) && !is_ctx_stopped(loc->ctx))
str_fmt_exception(errno, "Cannot %s register if not stopped", setm ? "write" : "read");
}
diff --git a/agent/tcf/services/runctrl.c b/agent/tcf/services/runctrl.c
index 5820467f..9f86c62b 100644
--- a/agent/tcf/services/runctrl.c
+++ b/agent/tcf/services/runctrl.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -94,6 +94,7 @@ typedef struct ContextExtensionRC {
char * step_func_id_out;
int step_inlined;
int step_set_frame_level;
+ int step_range_hidden;
CodeArea * step_code_area;
ErrorReport * step_error;
const char * step_done;
@@ -436,21 +437,27 @@ static const char * get_suspend_reason(Context * ctx) {
return REASON_USER_REQUEST;
}
-static void write_context_state(OutputStream * out, Context * ctx) {
+static void write_context_state(OutputStream * out, Context * ctx, int min) {
int fst = 1;
ContextExtensionRC * ext = EXT(ctx);
assert(!ctx->exited);
if (!ext->intercepted) {
- write_stringz(out, "0");
+ if (!min) {
+ /* Zero as Program Counter */
+ write_stringz(out, "0");
+ }
+
+ /* Reason */
write_stringz(out, "null");
}
else {
-
- /* Number: PC */
- json_write_uint64(out, ext->pc);
- write_stream(out, 0);
+ if (!min) {
+ /* Number: PC */
+ json_write_uint64(out, ext->pc);
+ write_stream(out, 0);
+ }
/* String: Reason */
json_write_string(out, get_suspend_reason(ctx));
@@ -493,7 +500,7 @@ static void write_context_state(OutputStream * out, Context * ctx) {
write_stream(out, ']');
fst = 0;
}
- if (ext->pc_error) {
+ if (!min && ext->pc_error) {
if (!fst) write_stream(out, ',');
json_write_string(out, "PCError");
write_stream(out, ':');
@@ -629,6 +636,7 @@ static void command_get_children(char * token, Channel * c) {
typedef struct CommandGetStateArgs {
char token[256];
char id[256];
+ int min; /* Non-zero for the getMinState. */
} CommandGetStateArgs;
static void command_get_state_cache_client(void * x) {
@@ -644,7 +652,9 @@ static void command_get_state_cache_client(void * x) {
if (ctx == NULL || !context_has_state(ctx)) err = ERR_INV_CONTEXT;
else if (ctx->exited) err = ERR_ALREADY_EXITED;
- if (!err && ext != NULL && ext->intercepted) get_current_pc(ctx);
+ /* Do not retrieve the PC in the "minimal" variant. */
+ if (!err && ext != NULL && ext->intercepted && !args->min)
+ get_current_pc(ctx);
cache_exit();
@@ -657,12 +667,12 @@ static void command_get_state_cache_client(void * x) {
write_stream(&c->out, 0);
if (err) {
- write_stringz(&c->out, "0");
+ if (!args->min) write_stringz(&c->out, "0");
write_stringz(&c->out, "null");
write_stringz(&c->out, "null");
}
else {
- write_context_state(&c->out, ctx);
+ write_context_state(&c->out, ctx, args->min);
}
write_stream(&c->out, MARKER_EOM);
@@ -677,6 +687,20 @@ static void command_get_state(char * token, Channel * c) {
json_test_char(&c->inp, MARKER_EOM);
strlcpy(args.token, token, sizeof(args.token));
+ args.min = 0;
+ cache_enter(command_get_state_cache_client, c, &args, sizeof(args));
+}
+
+static void command_get_min_state(char * token, Channel * c) {
+ CommandGetStateArgs args;
+
+ memset(&args, 0, sizeof(args));
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ json_test_char(&c->inp, MARKER_EOA);
+ json_test_char(&c->inp, MARKER_EOM);
+
+ strlcpy(args.token, token, sizeof(args.token));
+ args.min = 1;
cache_enter(command_get_state_cache_client, c, &args, sizeof(args));
}
@@ -846,6 +870,7 @@ static void cancel_step_mode(Context * ctx) {
ext->step_line_cnt = 0;
ext->step_repeat_cnt = 0;
ext->step_into_hidden = 0;
+ ext->step_range_hidden = 0;
ext->step_range_start = 0;
ext->step_range_end = 0;
ext->step_frame_fp = 0;
@@ -877,6 +902,7 @@ static void start_step_mode(Context * ctx, Channel * c, int mode, int cnt, Conte
ext->step_range_end = range_end;
ext->step_repeat_cnt = cnt;
ext->step_into_hidden = 0;
+ ext->step_range_hidden = 0;
}
int get_stepping_mode(Context * ctx) {
@@ -1279,22 +1305,50 @@ static void send_event_context_removed(Context * ctx) {
write_stream(out, MARKER_EOM);
}
-static void send_event_context_suspended(void) {
- LINK p0; /* List of contexts intercepted by breakpoint or exception */
- LINK p1; /* List of all other intercepted contexts */
- LINK p2; /* List for notify_context_intercepted() */
+static LINK p0; /* List of contexts intercepted by breakpoint or exception */
+static LINK p1; /* List of all other intercepted contexts */
+static LINK p2; /* List for notify_context_intercepted() */
+
+static void get_intercepted_contexts() {
LINK * l = context_root.next;
- unsigned i;
list_init(&p0);
list_init(&p1);
+
+ while (l != &context_root) {
+ Context * ctx = ctxl2ctxp(l);
+ if (!ctx) continue;
+ l = l->next;
+ if (ctx->pending_intercept && ctx->stopped) {
+ LINK * n;
+ ContextExtensionRC * ext = EXT(ctx);
+ if (strcmp(get_suspend_reason(ctx), REASON_USER_REQUEST)) {
+ /* lazily fetch PC */
+ if (ext->pc == 0 && ext->pc_error == ERR_OTHER)
+ get_current_pc(ctx);
+ n = &p0;
+ }
+ else {
+ /* lazily fetch PC of first child of container only */
+ if (list_is_empty(&p1) && ext->pc == 0 && ext->pc_error == ERR_OTHER)
+ get_current_pc(ctx);
+ n = &p1;
+ }
+ list_add_last(&ext->link, n);
+ }
+ }
+}
+
+static void send_event_context_suspended(void) {
+ LINK * l = context_root.next;
+ unsigned i;
+
list_init(&p2);
while (l != &context_root) {
Context * ctx = ctxl2ctxp(l);
l = l->next;
if (ctx->pending_intercept && ctx->stopped) {
- LINK * n = &p1;
ContextExtensionRC * ext = EXT(ctx);
assert(!ctx->exited);
assert(!ext->intercepted);
@@ -1303,8 +1357,6 @@ static void send_event_context_suspended(void) {
assert(!ext->intercepted);
ext->intercepted = 1;
ctx->pending_intercept = 0;
- if (strcmp(get_suspend_reason(ctx), REASON_USER_REQUEST)) n = &p0;
- list_add_last(&ext->link, n);
}
}
@@ -1324,7 +1376,7 @@ static void send_event_context_suspended(void) {
json_write_string(out, ctx->id);
write_stream(out, 0);
- write_context_state(out, ctx);
+ write_context_state(out, ctx, 0);
if (container) {
write_stream(out, '[');
@@ -1633,7 +1685,7 @@ static BreakpointInfo * create_step_machine_breakpoint(ContextAddress addr, Cont
static int update_step_machine_state(Context * ctx) {
ContextExtensionRC * ext = EXT(ctx);
- ContextAddress addr = ext->pc;
+ ContextAddress addr;
int do_reverse = 0;
if (!context_has_state(ctx) || ctx->exited || ctx->pending_intercept) {
@@ -1654,6 +1706,11 @@ static int update_step_machine_state(Context * ctx) {
break;
}
+ // lazily fetch PC
+ if (ext->pc == 0 && ext->pc_error == ERR_OTHER)
+ get_current_pc(ctx);
+ addr = ext->pc;
+
if (ext->pc_error) {
if (ctx->stopped && get_error_code(ext->pc_error) == ERR_NOT_ACTIVE) {
if (!do_reverse) {
@@ -1712,6 +1769,19 @@ static int update_step_machine_state(Context * ctx) {
ext->step_frame_fp = info->fp;
ext->step_set_frame_level = 1;
}
+ else if (ext->step_range_hidden && addr >= ext->step_range_start && addr < ext->step_range_end) {
+ n = get_prev_frame(ctx, n);
+ if (n < 0 && cache_miss_count() > 0) return -1;
+ if (n >= 0) {
+ uint64_t pc = 0;
+ if (get_frame_info(ctx, n, &info) < 0) return -1;
+ if (read_reg_value(info, get_PC_definition(ctx), &pc) < 0) return -1;
+ if (pc >= ext->step_range_start && pc < ext->step_range_end) {
+ /* Function call inside a hidden stepping range - need to step out */
+ step_bp_addr = (ContextAddress)pc;
+ }
+ }
+ }
break;
case RM_STEP_OVER:
case RM_STEP_OVER_RANGE:
@@ -2016,6 +2086,7 @@ static int update_step_machine_state(Context * ctx) {
}
if (hidden_function) {
/* Don't stop in a function that should be hidden during source level stepping */
+ ext->step_range_hidden = 1;
break;
}
}
@@ -2033,6 +2104,7 @@ static int update_step_machine_state(Context * ctx) {
ext->step_code_area = area;
ext->step_range_start = addr;
ext->step_range_end = addr + 1;
+ ext->step_range_hidden = 1;
break;
}
else if (errno) {
@@ -2467,9 +2539,6 @@ static void sync_run_state(void) {
err_cnt++;
}
}
- if (ctx->pending_intercept && ctx->stopped) {
- if (ext->pc_error == ERR_OTHER) get_current_pc(ctx);
- }
}
/* Resume contexts with resume mode other then RM_RESUME */
@@ -2496,6 +2565,7 @@ static void sync_run_state(void) {
static void sync_run_state_cache_client(void * args) {
sync_run_state();
+ get_intercepted_contexts();
cache_exit();
assert(sync_run_state_event_posted > 0);
sync_run_state_event_posted--;
@@ -2553,6 +2623,7 @@ static void run_safe_events(void * arg) {
i = safe_event_list;
while (i != NULL) {
Context * grp = EXT(i->ctx)->stop_group_ctx;
+ /* Note: grp is NULL if the context is not added to the context_root list, e.g. "hidden" context */
if (grp != NULL) EXT(grp)->stop_group_mark = 1;
i = i->next;
}
@@ -2562,6 +2633,7 @@ static void run_safe_events(void * arg) {
ContextExtensionRC * ext = EXT(ctx);
l = l->next;
ext->pending_safe_event = 0;
+ assert(!ext->stop_group_mark || EXT(ext->stop_group_ctx)->stop_group_mark);
ext->stop_group_mark = EXT(ext->stop_group_ctx)->stop_group_mark;
if (ctx->exited || ctx->exiting || ext->cannot_stop) continue;
if (!ext->safe_single_step && !ext->stop_group_mark) continue;
@@ -3020,6 +3092,7 @@ void ini_run_ctrl_service(Protocol * proto, TCFBroadcastGroup * bcg) {
add_command_handler(proto, RUN_CONTROL, "getContext", command_get_context);
add_command_handler(proto, RUN_CONTROL, "getChildren", command_get_children);
add_command_handler(proto, RUN_CONTROL, "getState", command_get_state);
+ add_command_handler(proto, RUN_CONTROL, "getMinState", command_get_min_state);
#if ENABLE_ContextISA
add_command_handler(proto, RUN_CONTROL, "getISA", command_get_isa);
#endif
diff --git a/agent/tcf/services/stacktrace-ext.h b/agent/tcf/services/stacktrace-ext.h
index 44254645..fa1c0073 100644
--- a/agent/tcf/services/stacktrace-ext.h
+++ b/agent/tcf/services/stacktrace-ext.h
@@ -1,3 +1,18 @@
+/*******************************************************************************
+* Copyright (c) 2013-2022 Wind River, 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.
+* The Eclipse Public License is available at
+* http://www.eclipse.org/legal/epl-v10.html
+* and the Eclipse Distribution License is available at
+* http://www.eclipse.org/org/documents/edl-v10.php.
+* You may elect to redistribute this code under either of these licenses.
+*
+* Contributors:
+* Wind River - initial API and implementation
+*******************************************************************************/
+
/*
* Extension point definitions for stacktrace.c.
*
diff --git a/agent/tcf/services/stacktrace.c b/agent/tcf/services/stacktrace.c
index 4a03a340..cac913e8 100644
--- a/agent/tcf/services/stacktrace.c
+++ b/agent/tcf/services/stacktrace.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -80,13 +80,8 @@ static void free_frame(StackFrame * frame) {
}
#if ENABLE_Symbols
-static int get_frame_debug_info(StackFrame * frame, StackTracingInfo ** info) {
- uint64_t ip = 0;
+static int get_frame_debug_info(StackFrame * frame, StackTracingInfo ** info, uint64_t ip) {
Context * ctx = frame->ctx;
- if (read_reg_value(frame, get_PC_definition(ctx), &ip) < 0) {
- if (frame->is_top_frame) return -1;
- return 0;
- }
if (ip > 0 && !frame->is_top_frame) {
StackTrace * stk = EXT(ctx);
if (frame->frame > stk->frame_cnt) {
@@ -119,22 +114,52 @@ static int get_frame_debug_info(StackFrame * frame, StackTracingInfo ** info) {
}
#endif
+static void read_saved_reg(StackFrame * frame, StackFrameRegisterLocation * info, uint8_t ** buf, size_t * size) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ /* If a saved register value cannot be evaluated - ignore it */
+ LocationExpressionState * state = evaluate_location_expression(frame->ctx, frame, info->cmds, info->cmds_cnt, NULL, 0);
+ if (state->stk_pos == 1) {
+ unsigned j;
+ uint64_t v = state->stk[0];
+ RegisterDefinition * reg_def = info->reg;
+ *buf = (uint8_t *)tmp_alloc_zero(reg_def->size);
+ for (j = 0; j < reg_def->size; j++) {
+ (*buf)[reg_def->big_endian ? reg_def->size - j - 1 : j] = (uint8_t)v;
+ v = v >> 8;
+ }
+ *size = reg_def->size;
+ }
+ else if (state->stk_pos == 0 && state->pieces_cnt > 0) {
+ read_location_pieces(state->ctx, state->stack_frame,
+ state->pieces, state->pieces_cnt, state->reg_id_scope.big_endian, (void **)buf, size);
+ }
+ clear_trap(&trap);
+ }
+}
+
int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
#if ENABLE_Symbols
int error = 0;
Context * ctx = frame->ctx;
+ StackTrace * stk = EXT(ctx);
+ int frame_cnt = stk->frame_cnt;
StackTracingInfo * info = NULL;
int frame_idx = frame->frame;
+ uint64_t ip = 0;
memset(down, 0, sizeof(StackFrame));
- if (get_frame_debug_info(frame, &info) < 0) {
+ if (read_reg_value(frame, get_PC_definition(ctx), &ip) < 0) {
+ if (frame->is_top_frame) error = errno;
+ }
+ else if (get_frame_debug_info(frame, &info, ip) < 0) {
error = errno;
}
else if (info != NULL) {
Trap trap;
if (set_trap(&trap)) {
- int i;
+ unsigned i;
LocationExpressionState * state;
state = evaluate_location_expression(ctx, frame, info->fp->cmds, info->fp->cmds_cnt, NULL, 0);
if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid stack trace expression");
@@ -142,7 +167,6 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
if (info->sub_cnt > 0) {
size_t buf_size = 8;
uint8_t * buf = (uint8_t *)tmp_alloc(buf_size);
- StackTrace * stk = EXT(ctx);
#if ENABLE_StackRegisterLocations
LocationExpressionCommand cmd;
memset(&cmd, 0, sizeof(cmd));
@@ -186,41 +210,39 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
}
down->ctx = ctx;
for (i = 0; i < info->reg_cnt; i++) {
- RegisterDefinition * reg_def = info->regs[i]->reg;
+ StackFrameRegisterLocation * loc = info->regs[i];
uint8_t * buf = NULL;
size_t size = 0;
- Trap trap_reg;
#if ENABLE_StackRegisterLocations
- if (write_reg_location(down, reg_def, info->regs[i]->cmds, info->regs[i]->cmds_cnt) == 0) {
+ if (write_reg_location(down, loc->reg, loc->cmds, loc->cmds_cnt) == 0) {
down->has_reg_data = 1;
continue;
}
#endif
- if (set_trap(&trap_reg)) {
- /* If a saved register value cannot be evaluated - ignore it */
- state = evaluate_location_expression(ctx, frame, info->regs[i]->cmds, info->regs[i]->cmds_cnt, NULL, 0);
- if (state->stk_pos == 1) {
- unsigned j;
- uint64_t v = state->stk[0];
- buf = (uint8_t *)tmp_alloc_zero(reg_def->size);
- for (j = 0; j < reg_def->size; j++) {
- buf[reg_def->big_endian ? reg_def->size - j - 1 : j] = (uint8_t)v;
- v = v >> 8;
- }
- size = reg_def->size;
- }
- else if (state->stk_pos == 0 && state->pieces_cnt > 0) {
- read_location_pieces(state->ctx, state->stack_frame,
- state->pieces, state->pieces_cnt, state->reg_id_scope.big_endian, (void **)&buf, &size);
- }
- clear_trap(&trap_reg);
- }
+ read_saved_reg(frame, loc, &buf, &size);
if (buf != NULL && size > 0) {
+ RegisterDefinition * reg_def = loc->reg;
if (size > reg_def->size) size = reg_def->size;
if (write_reg_bytes(down, reg_def, 0, size, buf) < 0) exception(errno);
down->has_reg_data = 1;
}
}
+ if (!frame->is_top_frame) {
+ for (i = 0; i < info->call_cnt; i++) {
+ if (info->calls[i]->addr == ip) {
+ StackFrameRegisterLocation * loc = &info->calls[i]->reg;
+ uint8_t * buf = NULL;
+ size_t size = 0;
+ read_saved_reg(frame, loc, &buf, &size);
+ if (buf != NULL && size > 0) {
+ RegisterDefinition * reg_def = loc->reg;
+ if (size > reg_def->size) size = reg_def->size;
+ if (write_reg_bytes(frame, reg_def, 0, size, buf) < 0) exception(errno);
+ frame->has_reg_data = 1;
+ }
+ }
+ }
+ }
/* Cache miss on register access should not be ignored, abort trace */
if (cache_miss_count() > 0) exception(ERR_CACHE_MISS);
clear_trap(&trap);
@@ -233,6 +255,10 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
}
if (error) {
free_frame(down);
+ /* Free up any additional frames added to the stack */
+ while (frame_cnt < stk->frame_cnt) {
+ free_frame(stk->frames + --stk->frame_cnt);
+ }
errno = error;
return -1;
}
@@ -310,15 +336,13 @@ static void trace_stack(Context * ctx, StackTrace * stack, int max_frames) {
uint8_t * buf1 = (uint8_t *)tmp_alloc(buf_size);
RegisterDefinition * def;
for (def = get_reg_definitions(ctx); def && def->name; def++) {
- int f0, f1;
if (buf_size < def->size) {
buf_size = def->size;
buf0 = (uint8_t *)tmp_realloc(buf0, buf_size);
buf1 = (uint8_t *)tmp_realloc(buf1, buf_size);
}
- f0 = read_reg_bytes(frame, def, 0, def->size, buf0) == 0;
- f1 = read_reg_bytes(&down, def, 0, def->size, buf1) == 0;
- if (f0 != f1 || (f0 && memcmp(buf0, buf1, def->size) != 0)) {
+ if (read_reg_bytes(&down, def, 0, def->size, buf1) < 0) continue;
+ if (read_reg_bytes(frame, def, 0, def->size, buf0) < 0 || memcmp(buf0, buf1, def->size) != 0) {
equ = 0;
break;
}
diff --git a/agent/tcf/services/symbols.c b/agent/tcf/services/symbols.c
index ce5b8efb..2030cd2d 100644
--- a/agent/tcf/services/symbols.c
+++ b/agent/tcf/services/symbols.c
@@ -974,7 +974,7 @@ static void command_find_frame_props_cache_client(void * x) {
}
if (info != NULL && info->regs != NULL) {
- int i;
+ unsigned i;
if (cnt++ > 0) write_stream(&c->out, ',');
json_write_string(&c->out, "Regs");
write_stream(&c->out, ':');
@@ -988,8 +988,37 @@ static void command_find_frame_props_cache_client(void * x) {
write_stream(&c->out, '}');
}
+ if (info != NULL && info->calls != NULL) {
+ unsigned i;
+ if (cnt++ > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Calls");
+ write_stream(&c->out, ':');
+ write_stream(&c->out, '[');
+ for (i = 0; i < info->call_cnt; i++) {
+ if (i > 0) write_stream(&c->out, ',');
+ write_stream(&c->out, '{');
+ json_write_string(&c->out, "CodeAddr");
+ write_stream(&c->out, ':');
+ json_write_uint64(&c->out, info->calls[i]->addr);
+ write_stream(&c->out, ',');
+ json_write_string(&c->out, "CodeSize");
+ write_stream(&c->out, ':');
+ json_write_uint64(&c->out, info->calls[i]->size);
+ write_stream(&c->out, ',');
+ json_write_string(&c->out, "Reg");
+ write_stream(&c->out, ':');
+ json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->calls[i]->reg.reg));
+ write_stream(&c->out, ',');
+ json_write_string(&c->out, "Value");
+ write_stream(&c->out, ':');
+ write_commands(&c->out, ctx, info->calls[i]->reg.cmds, info->calls[i]->reg.cmds_cnt);
+ write_stream(&c->out, '}');
+ }
+ write_stream(&c->out, ']');
+ }
+
if (info != NULL && info->subs != NULL) {
- int i;
+ unsigned i;
if (cnt++ > 0) write_stream(&c->out, ',');
json_write_string(&c->out, "Inlined");
write_stream(&c->out, ':');
@@ -1017,7 +1046,7 @@ static void command_find_frame_props_cache_client(void * x) {
write_stream(&c->out, 0);
if (info != NULL && info->regs != NULL) {
- int i;
+ unsigned i;
write_stream(&c->out, '{');
for (i = 0; i < info->reg_cnt; i++) {
if (i > 0) write_stream(&c->out, ',');
diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h
index c09ca367..10222cb7 100644
--- a/agent/tcf/services/symbols.h
+++ b/agent/tcf/services/symbols.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -86,6 +86,7 @@ typedef uint32_t SYM_FLAGS;
#define SYM_FLAG_BOOL_TYPE 0x04000000
#define SYM_FLAG_INDIRECT 0x08000000
#define SYM_FLAG_RVALUE 0x10000000
+#define SYM_FLAG_MEMBER 0x20000000
/* Additional (uncommon) symbol properties */
typedef struct SymbolProperties {
@@ -138,15 +139,23 @@ typedef struct StackFrameInlinedSubroutine {
CodeArea area;
} StackFrameInlinedSubroutine;
+typedef struct StackFrameCallSiteParameter {
+ ContextAddress addr;
+ ContextAddress size;
+ StackFrameRegisterLocation reg;
+} StackFrameCallSiteParameter;
+
/* Complete stack tracing info for a range of instruction addresses */
typedef struct StackTracingInfo {
ContextAddress addr;
ContextAddress size;
StackFrameRegisterLocation * fp;
StackFrameRegisterLocation ** regs;
- int reg_cnt;
+ unsigned reg_cnt;
+ StackFrameCallSiteParameter ** calls;
+ unsigned call_cnt;
StackFrameInlinedSubroutine ** subs;
- int sub_cnt;
+ unsigned sub_cnt;
} StackTracingInfo;
typedef struct SymbolFileInfo {
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index 1de69793..d98f3931 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 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.
@@ -160,6 +160,19 @@ static struct BaseTypeAlias {
{ "signed long long int", "long long int" },
{ "unsigned long long", "unsigned long long int" },
{ "unsigned long long", "long long unsigned int" },
+ /* LLVM 15 doesn't add 'int' in DWARF type names */
+ { "short int", "short" },
+ { "signed short", "short" },
+ { "signed short int", "short" },
+ { "unsigned short int", "unsigned short" },
+ { "long int", "long" },
+ { "signed long", "long" },
+ { "signed long int", "long" },
+ { "unsigned long int", "unsigned long" },
+ { "long long int", "long long" },
+ { "signed long long", "long long" },
+ { "signed long long int", "long long" },
+ { "unsigned long long int", "unsigned long long" },
{ NULL, NULL }
};
@@ -350,7 +363,7 @@ int elf_tcf_symbol(Context * ctx, ELF_SymbolInfo * sym_info, Symbol ** symbol) {
return 0;
}
-int elf_symbol_info(Symbol * sym, ELF_SymbolInfo * elf_sym) {
+int elf_symbol_info(const Symbol * sym, ELF_SymbolInfo * elf_sym) {
Trap trap;
assert (sym != NULL && sym->magic == SYMBOL_MAGIC && sym->tbl != NULL);
@@ -428,6 +441,8 @@ static int is_frame_based_object(Symbol * sym) {
case TAG_structure_type:
case TAG_class_type:
case TAG_union_type:
+ if (obj->mCompUnit->mLanguage == LANG_C11) return 0;
+ if (obj->mCompUnit->mLanguage == LANG_C99) return 0;
if (obj->mCompUnit->mLanguage == LANG_C89) return 0;
if (obj->mCompUnit->mLanguage == LANG_C) return 0;
break;
@@ -460,6 +475,8 @@ static int is_thread_based_object(Symbol * sym) {
case TAG_structure_type:
case TAG_class_type:
case TAG_union_type:
+ if (obj->mCompUnit->mLanguage == LANG_C11) return 0;
+ if (obj->mCompUnit->mLanguage == LANG_C99) return 0;
if (obj->mCompUnit->mLanguage == LANG_C89) break;
if (obj->mCompUnit->mLanguage == LANG_C) break;
return 1;
@@ -1743,33 +1760,46 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char
}
}
- if (error == 0 && should_continue_pub_names_search()) {
- /* Search in pub names of all other files */
- ELF_File * file = elf_list_first(sym_ctx, 0, ~(ContextAddress)0);
- if (file == NULL) error = errno;
- while (error == 0 && file != NULL) {
- if (file != curr_file) {
- Trap trap;
- if (set_trap(&trap)) {
- DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
- if (strncmp(name, "$relocate:", 10) == 0) {
- find_relocate(file, name + 10);
+ if (error == 0) {
+ /* Some compilers optimize away declaration info for dynamic symbols,
+ * and expect debugger to search for definition in shared libraries */
+ int dynsym = 0;
+ Symbol * sym = find_symbol_list;
+ while (sym != NULL) {
+ if (sym->dynsym) {
+ dynsym = 1;
+ break;
+ }
+ sym = sym->next;
+ }
+ if (dynsym || should_continue_pub_names_search()) {
+ /* Search in pub names of all other files */
+ ELF_File * file = elf_list_first(sym_ctx, 0, ~(ContextAddress)0);
+ if (file == NULL) error = errno;
+ while (error == 0 && file != NULL) {
+ if (file != curr_file) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
+ if (strncmp(name, "$relocate:", 10) == 0) {
+ find_relocate(file, name + 10);
+ }
+ else {
+ find_by_name_in_pub_names(cache, name);
+ find_by_name_in_sym_table(file, name, 0);
+ }
+ clear_trap(&trap);
}
else {
- find_by_name_in_pub_names(cache, name);
- find_by_name_in_sym_table(file, name, 0);
+ error = trap.error;
+ break;
}
- clear_trap(&trap);
- }
- else {
- error = trap.error;
- break;
}
+ file = elf_list_next(sym_ctx);
+ if (file == NULL) error = errno;
}
- file = elf_list_next(sym_ctx);
- if (file == NULL) error = errno;
+ elf_list_done(sym_ctx);
}
- elf_list_done(sym_ctx);
}
if (error == 0 && find_symbol_list == NULL) {
@@ -1929,6 +1959,7 @@ static int find_by_addr_in_unit(ObjectInfo * parent, int level, UnitAddress * ad
case TAG_unspecified_parameters:
case TAG_local_variable:
if (sym_frame == STACK_NO_FRAME) break;
+ // fall through
case TAG_variable:
if (in_range && (obj->mFlags & DOIF_location) != 0) {
U8_T lc = 0;
@@ -2436,11 +2467,65 @@ int id2symbol(const char * id, Symbol ** res) {
ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
ELF_File * file = NULL;
ELF_Section * sec = NULL;
- ContextAddress res = elf_map_to_link_time_address(ctx, addr, 0, &file, &sec);
- if (res == 0 || sec == NULL) return 0;
+ ContextAddress lt_addr = elf_map_to_link_time_address(ctx, addr, 0, &file, &sec);
+ if (lt_addr == 0 || sec == NULL) return 0;
if (sec->name == NULL) return 0;
- if (strcmp(sec->name, ".plt") != 0) return 0;
- return (ContextAddress)sec->addr + (addr - res);
+ if (strcmp(sec->name, ".plt") == 0) return (ContextAddress)sec->addr + (addr - lt_addr);
+ if (sec != NULL && file->machine == EM_PPC) {
+ /*
+ Check for a symbol that marks plt call stubs.
+ For non - PIC code the sym is xxxxxxxx.plt_call32.<callee>,
+ for - fpic code, the sym is xxxxxxxx.plt_pic32.<callee>,
+ and for - fPIC xxxxxxxx.got2.plt_pic32.<callee>,
+ where xxxxxxxx is a hex number specifying the addend on the plt relocation.
+ */
+ ELF_SymbolInfo sym_info;
+ elf_find_symbol_by_address(sec, lt_addr, &sym_info);
+ if (sym_info.section == sec && sym_info.name != NULL) {
+ unsigned i = 0;
+ if (strcmp(sym_info.name, "__glink") == 0 ||
+ strcmp(sym_info.name, "__glink_PLTresolve") == 0)
+ return (ContextAddress)sec->addr + (addr - lt_addr);
+ for (;;) {
+ char ch = sym_info.name[i];
+ if (ch >= '0' && ch <= '9') i++;
+ else if (ch >= 'A' && ch <= 'F') i++;
+ else if (ch >= 'a' && ch <= 'f') i++;
+ else break;
+ }
+ if (i == 8 && sym_info.name[i] == '.') {
+ unsigned n;
+ static const char * const names[] = { ".plt_call32.", ".plt_pic32.", ".got2.plt_call32.", ".got2.plt_pic32.", NULL };
+ for (n = 0; names[n] != NULL; n++) {
+ if (strncmp(sym_info.name + i, names[n], strlen(names[n])) == 0)
+ return (ContextAddress)sec->addr + (addr - lt_addr);
+ }
+ }
+ }
+ }
+ if (sec != NULL && file->machine == EM_PPC64) {
+ ELF_SymbolInfo sym_info;
+ elf_find_symbol_by_address(sec, lt_addr, &sym_info);
+ if (sym_info.section == sec && sym_info.name != NULL) {
+ unsigned i = 0;
+ for (;;) {
+ char ch = sym_info.name[i];
+ if (ch >= '0' && ch <= '9') i++;
+ else if (ch >= 'A' && ch <= 'F') i++;
+ else if (ch >= 'a' && ch <= 'f') i++;
+ else break;
+ }
+ if (i == 8 && sym_info.name[i] == '.') {
+ unsigned n;
+ static const char * const names[] = { ".long_branch.", ".long_branch_r2off.", ".plt_branch.", ".plt_branch_r2off.", ".plt_call." };
+ for (n = 0; names[n] != NULL; n++) {
+ if (strncmp(sym_info.name + i, names[n], strlen(names[n])) == 0)
+ return (ContextAddress)sec->addr + (addr - lt_addr);
+ }
+ }
+ }
+ }
+ return 0;
}
int get_context_isa(Context * ctx, ContextAddress ip, const char ** isa,
@@ -2469,6 +2554,7 @@ int get_context_isa(Context * ctx, ContextAddress ip, const char ** isa,
assert(sym_info.section == sec);
if (sym_info.name != NULL && *sym_info.name == '$') {
if (strcmp(sym_info.name, "$a") == 0) *isa = "ARM";
+ else if (strncmp(sym_info.name, "$a.", 3) == 0) *isa = "ARM"; /* clang-12 */
else if (strcmp(sym_info.name, "$t") == 0) *isa = "Thumb";
else if (strcmp(sym_info.name, "$t.x") == 0) *isa = "ThumbEE";
else if (strcmp(sym_info.name, "$d") == 0) *isa = "Data";
@@ -2479,6 +2565,7 @@ int get_context_isa(Context * ctx, ContextAddress ip, const char ** isa,
for (;;) {
elf_next_symbol_by_address(&sym_info);
if (sym_info.sym_section == NULL) {
+ assert(sec->addr + sec->size > lt_addr);
*range_size = (ContextAddress)(sec->addr + sec->size) - *range_addr;
*range_addr += ip - lt_addr;
return 0;
@@ -2486,6 +2573,12 @@ int get_context_isa(Context * ctx, ContextAddress ip, const char ** isa,
if (sym_info.name != NULL && *sym_info.name == '$') {
ContextAddress sym_addr = (ContextAddress)sym_info.value;
if (file->type == ET_REL) sym_addr += (ContextAddress)sec->addr;
+ if (sym_addr <= lt_addr) {
+ *isa = NULL;
+ *range_addr = ip;
+ *range_size = 1;
+ return 0;
+ }
*range_size = sym_addr - *range_addr;
*range_addr += ip - lt_addr;
return 0;
@@ -2551,7 +2644,7 @@ int get_context_isa(Context * ctx, ContextAddress ip, const char ** isa,
return 0;
}
-static int buf_sub_max = 0;
+static unsigned buf_sub_max = 0;
static void add_inlined_subroutine(ObjectInfo * o, CompUnit * unit, ContextAddress addr0, ContextAddress addr1, StackTracingInfo * buf) {
StackFrameInlinedSubroutine * sub = (StackFrameInlinedSubroutine *)tmp_alloc(sizeof(StackFrameInlinedSubroutine));
@@ -2620,84 +2713,119 @@ static void search_inlined_subroutine(Context * ctx, ObjectInfo * obj, UnitAddre
case TAG_subroutine:
case TAG_subprogram:
case TAG_inlined_subroutine:
- if (o->mFlags & DOIF_ranges) {
- DWARFCache * cache = get_dwarf_cache(addr->file);
- ELF_Section * debug_ranges = cache->mDebugRanges;
- if (debug_ranges != NULL) {
- CompUnit * unit = addr->unit;
- ContextAddress base = unit->mObject->u.mCode.mLowPC;
- dio_EnterSection(&unit->mDesc, debug_ranges, o->u.mCode.mHighPC.mRanges);
- for (;;) {
- ELF_Section * x_sec = NULL;
- ELF_Section * y_sec = NULL;
- U8_T x = dio_ReadAddress(&x_sec);
- U8_T y = dio_ReadAddress(&y_sec);
- if (x == 0 && y == 0) break;
- if (x == ((U8_T)1 << unit->mDesc.mAddressSize * 8) - 1) {
- base = (ContextAddress)y;
+ {
+ ObjectAddressRange range;
+ start_dwarf_addr_ranges(o, &range);
+ while (read_dwarf_addr_range(&range)) {
+ ContextAddress addr0 = range.mAddr - addr->lt_addr + addr->rt_addr;
+ ContextAddress addr1 = range.mAddr + range.mSize - addr->lt_addr + addr->rt_addr;
+ if (addr0 <= addr->rt_addr && addr1 > addr->rt_addr) {
+ U8_T pos = dio_GetPos();
+ dio_ExitSection();
+ if (buf->addr < addr0) {
+ assert(buf->addr + buf->size > addr0);
+ buf->size = buf->addr + buf->size - addr0;
+ buf->addr = addr0;
}
- else {
- if (x_sec == NULL) x_sec = unit->mTextSection;
- if (y_sec == NULL) y_sec = unit->mTextSection;
- if (x_sec == addr->section && y_sec == addr->section && x < y) {
- ContextAddress addr0 = base + x - addr->lt_addr + addr->rt_addr;
- ContextAddress addr1 = base + y - addr->lt_addr + addr->rt_addr;
- if (addr0 <= addr->rt_addr && addr1 > addr->rt_addr) {
- U8_T pos = dio_GetPos();
- dio_ExitSection();
- if (buf->addr < addr0) {
- assert(buf->addr + buf->size > addr0);
- buf->size = buf->addr + buf->size - addr0;
- buf->addr = addr0;
+ if (buf->addr + buf->size > addr1) {
+ assert(addr1 > buf->addr);
+ buf->size = addr1 - buf->addr;
+ }
+ if (o->mTag == TAG_inlined_subroutine) add_inlined_subroutine(o, range.mUnit, addr0, addr1, buf);
+ search_inlined_subroutine(ctx, o, addr, buf);
+ if (range.mRngSection) dio_EnterSection(&range.mUnit->mDesc, range.mRngSection, pos);
+ }
+ else if (addr1 <= addr->rt_addr && addr1 > buf->addr) {
+ buf->size = buf->addr + buf->size - addr1;
+ buf->addr = addr1;
+ }
+ else if (addr0 > addr->rt_addr && addr0 < buf->addr + buf->size) {
+ buf->size = addr0 - buf->addr;
+ }
+ }
+ }
+ break;
+ }
+ o = o->mSibling;
+ }
+}
+
+static unsigned call_site_max = 0;
+static void add_dwarf_location_command(LocationInfo * l, PropertyValue * v);
+
+static void search_stack_tracing_call_sites(Context * ctx, ObjectInfo * obj, UnitAddress * addr, StackTracingInfo * buf) {
+ obj = get_dwarf_children(obj);
+ while (obj != NULL) {
+ switch (obj->mTag) {
+ case TAG_compile_unit:
+ case TAG_partial_unit:
+ case TAG_module:
+ case TAG_global_subroutine:
+ case TAG_lexical_block:
+ case TAG_with_stmt:
+ case TAG_try_block:
+ case TAG_catch_block:
+ case TAG_subprogram:
+ case TAG_subroutine:
+ case TAG_inlined_subroutine:
+ case TAG_GNU_call_site:
+ {
+ ObjectAddressRange range;
+ start_dwarf_addr_ranges(obj, &range);
+ while (read_dwarf_addr_range(&range)) {
+ ContextAddress addr0 = range.mAddr - addr->lt_addr + addr->rt_addr;
+ ContextAddress addr1 = range.mAddr + range.mSize - addr->lt_addr + addr->rt_addr;
+ /* Note: need to use buf->size + 1, see stack trace logic */
+ if (addr0 <= buf->addr + buf->size && addr1 > buf->addr) {
+ dio_ExitSection();
+ if (obj->mTag == TAG_GNU_call_site) {
+ ObjectInfo * args = get_dwarf_children(obj);
+ while (args != NULL) {
+ PropertyValue pv;
+ if (args->mTag == TAG_GNU_call_site_parameter && (args->mFlags & DOIF_location)) {
+ RegisterDefinition * reg_def = NULL;
+ read_dwarf_object_property(ctx, STACK_NO_FRAME, args, AT_location, &pv);
+ if (pv.mAddr != NULL && pv.mSize == 1 && *pv.mAddr >= OP_reg0 && *pv.mAddr <= OP_reg31) {
+ reg_def = get_reg_by_id(ctx, *pv.mAddr - OP_reg0, &obj->mCompUnit->mRegIdScope);
}
- if (buf->addr + buf->size > addr1) {
- assert(addr1 > buf->addr);
- buf->size = addr1 - buf->addr;
+ if (reg_def != NULL) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ LocationInfo info;
+ memset(&info, 0, sizeof(LocationInfo));
+ read_dwarf_object_property(ctx, STACK_NO_FRAME, args, AT_GNU_call_site_value, &pv);
+ add_dwarf_location_command(&info, &pv);
+ if (info.value_cmds.cnt) {
+ StackFrameCallSiteParameter * c = NULL;
+ if (buf->call_cnt >= call_site_max) {
+ call_site_max += 32;
+ buf->calls = (StackFrameCallSiteParameter **)tmp_realloc(buf->calls, sizeof(StackFrameCallSiteParameter *) * call_site_max);
+ }
+ c = buf->calls[buf->call_cnt++] = (StackFrameCallSiteParameter *)tmp_alloc_zero(sizeof(StackFrameCallSiteParameter) + sizeof(LocationExpressionCommand) * (info.value_cmds.cnt - 1));
+ c->addr = obj->u.mCode.mLowPC - addr->lt_addr + addr->rt_addr;
+ c->size = 1;
+ c->reg.reg = reg_def;
+ c->reg.cmds_cnt = info.value_cmds.cnt;
+ c->reg.cmds_max = info.value_cmds.cnt;
+ memcpy(c->reg.cmds, info.value_cmds.cmds, sizeof(LocationExpressionCommand) * info.value_cmds.cnt);
+ }
+ clear_trap(&trap);
+ }
}
- if (o->mTag == TAG_inlined_subroutine) add_inlined_subroutine(o, unit, addr0, addr1, buf);
- search_inlined_subroutine(ctx, o, addr, buf);
- dio_EnterSection(&unit->mDesc, debug_ranges, pos);
- }
- else if (addr1 <= addr->rt_addr && addr1 > buf->addr) {
- buf->size = buf->addr + buf->size - addr1;
- buf->addr = addr1;
- }
- else if (addr0 > addr->rt_addr && addr0 < buf->addr + buf->size) {
- buf->size = addr0 - buf->addr;
}
+ args = args->mSibling;
}
}
+ else {
+ search_stack_tracing_call_sites(ctx, obj, addr, buf);
+ }
+ break;
}
- dio_ExitSection();
- }
- }
- else if ((o->mFlags & DOIF_low_pc) && o->u.mCode.mHighPC.mAddr > o->u.mCode.mLowPC && o->u.mCode.mSection == addr->section) {
- ContextAddress addr0 = o->u.mCode.mLowPC - addr->lt_addr + addr->rt_addr;
- ContextAddress addr1 = o->u.mCode.mHighPC.mAddr - addr->lt_addr + addr->rt_addr;
- if (addr0 <= addr->rt_addr && addr1 > addr->rt_addr) {
- if (buf->addr < addr0) {
- assert(buf->addr + buf->size > addr0);
- buf->size = buf->addr + buf->size - addr0;
- buf->addr = addr0;
- }
- if (buf->addr + buf->size > addr1) {
- assert(addr1 > buf->addr);
- buf->size = addr1 - buf->addr;
- }
- if (o->mTag == TAG_inlined_subroutine) add_inlined_subroutine(o, addr->unit, addr0, addr1, buf);
- search_inlined_subroutine(ctx, o, addr, buf);
- }
- else if (addr1 <= addr->rt_addr && addr1 > buf->addr) {
- buf->size = buf->addr + buf->size - addr1;
- buf->addr = addr1;
- }
- else if (addr0 > addr->rt_addr && addr0 < buf->addr + buf->size) {
- buf->size = addr0 - buf->addr;
}
}
break;
}
- o = o->mSibling;
+ obj = obj->mSibling;
}
}
@@ -2716,6 +2844,7 @@ int get_stack_tracing_info(Context * ctx, ContextAddress rt_addr, StackTracingIn
if (dwarf_stack_trace_fp->cmds_cnt > 0) {
static StackTracingInfo buf;
memset(&buf, 0, sizeof(buf));
+ assert(dwarf_stack_trace_size > 0);
assert(dwarf_stack_trace_addr <= lt_addr);
assert(dwarf_stack_trace_addr + dwarf_stack_trace_size > lt_addr);
buf.addr = (ContextAddress)dwarf_stack_trace_addr - lt_addr + rt_addr;
@@ -2724,16 +2853,18 @@ int get_stack_tracing_info(Context * ctx, ContextAddress rt_addr, StackTracingIn
buf.reg_cnt = dwarf_stack_trace_regs_cnt;
buf.fp = dwarf_stack_trace_fp;
if (get_sym_context(ctx, STACK_NO_FRAME, rt_addr) == 0) {
- /* Search inlined functions info.
+ /* Search inlined functions and call sites.
* Note: when debug info is a separate file,
* 'lt_addr' is not same as 'unit.lt_addr' */
UnitAddress unit;
find_unit(ctx, rt_addr, &unit);
if (unit.unit != NULL) {
buf_sub_max = 0;
+ call_site_max = 0;
assert(buf.addr <= unit.rt_addr);
assert(buf.addr + buf.size == 0 || buf.addr + buf.size > unit.rt_addr);
search_inlined_subroutine(ctx, unit.unit->mObject, &unit, &buf);
+ search_stack_tracing_call_sites(ctx, unit.unit->mObject, &unit, &buf);
}
}
*info = &buf;
@@ -2767,6 +2898,9 @@ int get_symbol_file_info(Context * ctx, ContextAddress addr, SymbolFileInfo ** i
if (l > 6 && strncmp(fnm, "ld-", 3) == 0 && strcmp(fnm + l - 3, ".so") == 0) {
(*info)->dyn_loader = 1;
}
+ else if (l > 6 && strncmp(fnm, "ld.so.", 6) == 0) {
+ (*info)->dyn_loader = 1;
+ }
}
elf_list_done(ctx);
return 0;
@@ -2814,8 +2948,13 @@ static int unpack(const Symbol * sym) {
assert(!is_array_type_pseudo_symbol(sym));
assert(!is_std_type_pseudo_symbol(sym));
assert(!is_constant_pseudo_symbol(sym));
- assert(sym->obj == NULL || sym->obj->mTag != 0);
- assert(sym->obj == NULL || sym->obj->mCompUnit->mFile->dwarf_dt_cache != NULL);
+ if (sym->obj != NULL) {
+ assert(sym->obj->mCompUnit->mFile->dwarf_dt_cache != NULL);
+ if (sym->obj->mTag == 0 || (sym->obj->mFlags & DOIF_inv_reference) != 0) {
+ set_fmt_errno(ERR_INV_DWARF, "Invalid debug info entry at 0x%" PRIx64, (uint64_t)sym->obj->mID);
+ return -1;
+ }
+ }
return get_sym_context(sym->ctx, sym->frame, 0);
}
@@ -3064,7 +3203,7 @@ static U8_T read_string_length(ObjectInfo * obj) {
clear_trap(&trap);
return len;
}
- else if (trap.error != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(trap.error) != ERR_SYM_NOT_FOUND) {
exception(trap.error);
}
if (get_num_prop(obj, AT_byte_size, &len)) return len;
@@ -3282,7 +3421,7 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) {
*type_class = TYPE_CLASS_FUNCTION;
return 0;
}
- unpack_elf_symbol_info(sym->tbl, sym->index, &info);
+ if (elf_symbol_info(sym, &info) < 0) return -1;
if (info.type == STT_FUNC || info.type == STT_GNU_IFUNC) {
*type_class = TYPE_CLASS_FUNCTION;
return 0;
@@ -3320,7 +3459,7 @@ int get_symbol_name(const Symbol * sym, char ** name) {
else if (sym->tbl != NULL) {
ELF_SymbolInfo sym_info;
if (sym->dimension == 0) {
- unpack_elf_symbol_info(sym->tbl, sym->index, &sym_info);
+ if (elf_symbol_info(sym, &sym_info) < 0) return -1;
if (sym_info.name != NULL) {
size_t i;
for (i = 0;; i++) {
@@ -3449,7 +3588,7 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) {
else if (sym->tbl != NULL) {
if (sym->dimension == 0) {
ELF_SymbolInfo info;
- unpack_elf_symbol_info(sym->tbl, sym->index, &info);
+ if (elf_symbol_info(sym, &info) < 0) return -1;
if (IS_PPC64_FUNC_OPD(sym->tbl->file, &info) && info.name != NULL) {
/*
* For PPC64, the size of an ELF symbol is either the size
@@ -3880,31 +4019,65 @@ static void add_dwarf_location_command(LocationInfo * l, PropertyValue * v) {
static void add_member_location_command(LocationInfo * info, ObjectInfo * obj) {
U8_T bit_size = 0;
U8_T bit_offs = 0;
- PropertyValue v;
- read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_data_member_location, &v);
- switch (v.mForm) {
- case FORM_DATA1 :
- case FORM_DATA2 :
- case FORM_DATA4 :
- case FORM_DATA8 :
- case FORM_SDATA :
- case FORM_UDATA :
+ Trap trap;
+ if (get_num_prop(obj, AT_data_bit_offset, &bit_offs)) {
+ U8_T byte_size = 0;
+ U8_T type_byte_size = 0;
+ U8_T type_bit_size = 0;
+ LocationExpressionCommand * cmd;
add_location_command(info, SFT_CMD_ARG)->args.arg_no = 0;
- add_location_command(info, SFT_CMD_NUMBER)->args.num = get_numeric_property_value(&v);
- add_location_command(info, SFT_CMD_ADD);
- break;
- case FORM_BLOCK1 :
- case FORM_BLOCK2 :
- case FORM_BLOCK4 :
- case FORM_BLOCK :
- case FORM_EXPRLOC :
- case FORM_SEC_OFFSET:
+ cmd = add_location_command(info, SFT_CMD_PIECE);
+ cmd->args.piece.bit_offs = (unsigned)bit_offs;
+ if (get_num_prop(obj, AT_bit_size, &bit_size)) {
+ cmd->args.piece.bit_size = (unsigned)bit_size;
+ }
+ else if (get_num_prop(obj, AT_byte_size, &byte_size)) {
+ cmd->args.piece.bit_size = (unsigned)(byte_size * 8);
+ }
+ else if (obj->mType != NULL && get_object_size(obj, obj->mType, 0, &type_byte_size, &type_bit_size)) {
+ cmd->args.piece.bit_size = (unsigned)type_bit_size;
+ }
+ else {
+ str_exception(ERR_INV_DWARF, "Unknown field size");
+ }
+ return;
+ }
+ if (set_trap(&trap)) {
+ PropertyValue v;
+ read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_data_member_location, &v);
+ switch (v.mForm) {
+ case FORM_DATA1:
+ case FORM_DATA2:
+ case FORM_DATA4:
+ case FORM_DATA8:
+ case FORM_SDATA:
+ case FORM_UDATA:
+ case FORM_IMPLICIT_CONST:
+ add_location_command(info, SFT_CMD_ARG)->args.arg_no = 0;
+ add_location_command(info, SFT_CMD_NUMBER)->args.num = get_numeric_property_value(&v);
+ add_location_command(info, SFT_CMD_ADD);
+ break;
+ case FORM_BLOCK1:
+ case FORM_BLOCK2:
+ case FORM_BLOCK4:
+ case FORM_BLOCK:
+ case FORM_EXPRLOC:
+ case FORM_SEC_OFFSET:
+ case FORM_LOCLISTX:
+ add_location_command(info, SFT_CMD_ARG)->args.arg_no = 0;
+ add_dwarf_location_command(info, &v);
+ break;
+ default:
+ str_fmt_exception(ERR_OTHER, "Invalid AT_data_member_location form 0x%04x", v.mForm);
+ break;
+ }
+ clear_trap(&trap);
+ }
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
+ str_exception(errno, "Cannot read AT_data_member_location");
+ }
+ else {
add_location_command(info, SFT_CMD_ARG)->args.arg_no = 0;
- add_dwarf_location_command(info, &v);
- break;
- default:
- str_fmt_exception(ERR_OTHER, "Invalid AT_data_member_location form 0x%04x", v.mForm);
- break;
}
if (get_num_prop(obj, AT_bit_size, &bit_size)) {
LocationExpressionCommand * cmd = add_location_command(info, SFT_CMD_PIECE);
@@ -3961,7 +4134,7 @@ static int read_discriminant_values(ObjectInfo * obj, LocationInfo * info) {
info->discr_lst->x = value;
info->discr_lst->y = value;
}
- else if (errno != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
set_errno(errno, "Cannot read discriminant value");
return -1;
}
@@ -4013,7 +4186,7 @@ static int read_discriminant_values(ObjectInfo * obj, LocationInfo * info) {
dio_ExitSection();
clear_trap(&trap);
}
- else if (errno != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
set_errno(errno, "Cannot read discriminant list");
return -1;
}
@@ -4097,7 +4270,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
LocationExpressionCommand * cmd = NULL;
ObjectInfo * type = get_original_type(sym->var);
if (!set_trap(&trap)) {
- if (errno == ERR_SYM_NOT_FOUND) set_errno(ERR_OTHER, "Location attribute not found");
+ if (get_error_code(errno) == ERR_SYM_NOT_FOUND) set_errno(ERR_OTHER, "Location attribute not found");
set_errno(errno, "Cannot evaluate location of 'this' pointer");
return -1;
}
@@ -4123,7 +4296,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
clear_trap(&trap);
return 0;
}
- else if (errno != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
set_errno(errno, "Cannot read member location expression");
return -1;
}
@@ -4200,12 +4373,12 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
return 0;
}
else {
- if (errno != ERR_SYM_NOT_FOUND) set_errno(errno, "Cannot read member location expression");
+ if (get_error_code(errno) != ERR_SYM_NOT_FOUND) set_errno(errno, "Cannot read member location expression");
else set_errno(ERR_OTHER, "Member location info not available");
return -1;
}
}
- if (obj->mTag == TAG_label && (obj->mFlags & DOIF_ranges) == 0 && (obj->mFlags & DOIF_low_pc) != 0) {
+ if (obj->mTag == TAG_label && !(obj->mFlags & DOIF_ranges) && (obj->mFlags & DOIF_low_pc)) {
ContextAddress addr = elf_map_to_run_time_address(sym_ctx, obj->mCompUnit->mFile, obj->u.mCode.mSection, obj->u.mCode.mLowPC);
if (errno) return -1;
add_location_command(info, SFT_CMD_NUMBER)->args.num = addr;
@@ -4226,8 +4399,11 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
if (tbl->sym_names_hash == NULL) continue;
n = tbl->sym_names_hash[h % tbl->sym_names_hash_size];
while (n) {
+ Trap trap;
ELF_SymbolInfo sym_info;
+ if (!set_trap(&trap)) continue;
unpack_elf_symbol_info(tbl, n, &sym_info);
+ clear_trap(&trap);
n = tbl->sym_names_next[n];
if (sym_info.bind != STB_GLOBAL || sym_info.type != STT_OBJECT) continue;
if (sym_info.section == NULL || sym_info.section->name == NULL) continue;
@@ -4346,7 +4522,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
add_location_command(info, SFT_CMD_NUMBER)->args.num = address;
return 0;
}
- unpack_elf_symbol_info(sym->tbl, sym->index, &elf_sym_info);
+ if (elf_symbol_info(sym, &elf_sym_info) < 0) return -1;
if (elf_sym_info.type == STT_GNU_IFUNC && elf_sym_info.name != NULL) {
int error = 0;
int found = 0;
@@ -4425,12 +4601,9 @@ int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) {
}
if (unpack(sym) < 0) return -1;
if (sym->tbl != NULL && sym->dimension == 0) {
- Trap trap;
ELF_SymbolInfo info;
- if (!set_trap(&trap)) return -1;
- unpack_elf_symbol_info(sym->tbl, sym->index, &info);
+ if (elf_symbol_info(sym, &info) < 0) return -1;
if (info.bind == STB_GLOBAL || info.bind == STB_WEAK) *flags |= SYM_FLAG_EXTERNAL;
- clear_trap(&trap);
}
if (obj != NULL) {
if (obj->mFlags & DOIF_external) *flags |= SYM_FLAG_EXTERNAL;
@@ -4516,6 +4689,9 @@ int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) {
case TAG_inheritance:
*flags |= SYM_FLAG_INHERITANCE;
break;
+ case TAG_member:
+ *flags |= SYM_FLAG_MEMBER;
+ break;
}
}
if (obj != NULL && !(*flags & (SYM_FLAG_BIG_ENDIAN|SYM_FLAG_LITTLE_ENDIAN))) {
diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c
index c82fe3de..a10428f9 100644
--- a/agent/tcf/services/symbols_proxy.c
+++ b/agent/tcf/services/symbols_proxy.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2022 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.
@@ -475,13 +475,19 @@ static void free_stack_frame_cache(StackFrameCache * c) {
c->disposed = 1;
}
if (c->pending == NULL) {
- int i;
+ unsigned i;
c->magic = 0;
cache_dispose(&c->cache);
release_error_report(c->error);
context_unlock(c->ctx);
- for (i = 0; i < c->sti.reg_cnt; i++) free_sft_sequence(c->sti.regs[i]);
free_sft_sequence(c->sti.fp);
+ for (i = 0; i < c->sti.reg_cnt; i++) free_sft_sequence(c->sti.regs[i]);
+ for (i = 0; i < c->sti.call_cnt; i++) {
+ unsigned j = 0;
+ StackFrameCallSiteParameter * info = c->sti.calls[i];
+ while (j < info->reg.cmds_cnt) free_location_command_args(info->reg.cmds + j++);
+ loc_free(info);
+ }
for (i = 0; i < c->sti.sub_cnt; i++) {
StackFrameInlinedSubroutine * info = c->sti.subs[i];
loc_free(info->area.directory);
@@ -489,8 +495,9 @@ static void free_stack_frame_cache(StackFrameCache * c) {
loc_free(info->func_id);
loc_free(info);
}
- loc_free(c->sti.subs);
loc_free(c->sti.regs);
+ loc_free(c->sti.calls);
+ loc_free(c->sti.subs);
loc_free(c);
}
}
@@ -1573,6 +1580,10 @@ static unsigned trace_regs_cnt = 0;
static unsigned trace_regs_max = 0;
static StackFrameRegisterLocation ** trace_regs = NULL;
+static unsigned trace_calls_cnt = 0;
+static unsigned trace_calls_max = 0;
+static StackFrameCallSiteParameter ** trace_calls = NULL;
+
static unsigned trace_subs_cnt = 0;
static unsigned trace_subs_max = 0;
static StackFrameInlinedSubroutine ** trace_subs = NULL;
@@ -1836,6 +1847,44 @@ static void read_stack_trace_register(InputStream * inp, const char * id, void *
}
}
+static void read_stack_trace_call_props(InputStream * inp, const char * name, void * args) {
+ StackFrameCallSiteParameter * s = (StackFrameCallSiteParameter *)args;
+ if (strcmp(name, "CodeAddr") == 0) s->addr = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "CodeSize") == 0) s->size = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "Reg") == 0) {
+ Context * ctx = NULL;
+ int frame = STACK_NO_FRAME;
+ char id[256];
+ json_read_string(inp, id, sizeof(id));
+ if (id2register(id, &ctx, &frame, &s->reg.reg) < 0) {
+ id2register_error = errno;
+ }
+ }
+ else if (strcmp(name, "Value") == 0) {
+ location_cmds.cnt = 0;
+ json_read_array(inp, read_location_command, NULL);
+ }
+ else json_skip_object(inp);
+}
+
+static void read_stack_trace_call_param(InputStream * inp, void * args) {
+ StackFrameCallSiteParameter buf;
+ StackFrameCallSiteParameter * param = NULL;
+ location_cmds.cnt = 0;
+ memset(&buf, 0, sizeof(StackFrameCallSiteParameter));
+ json_read_struct(inp, read_stack_trace_call_props, &buf);
+ param = (StackFrameCallSiteParameter *)loc_alloc(sizeof(StackFrameCallSiteParameter) + (location_cmds.cnt - 1) * sizeof(LocationExpressionCommand));
+ memcpy(param, &buf, sizeof(StackFrameCallSiteParameter));
+ param->reg.cmds_cnt = location_cmds.cnt;
+ param->reg.cmds_max = location_cmds.cnt;
+ memcpy(param->reg.cmds, location_cmds.cmds, location_cmds.cnt * sizeof(LocationExpressionCommand));
+ if (trace_calls_cnt >= trace_calls_max) {
+ trace_calls_max += 16;
+ trace_calls = (StackFrameCallSiteParameter **)loc_realloc(trace_calls, trace_calls_max * sizeof(StackFrameCallSiteParameter *));
+ }
+ trace_calls[trace_calls_cnt++] = param;
+}
+
static void read_inlined_subroutine_props(InputStream * inp, const char * name, void * args) {
StackFrameInlinedSubroutine * s = (StackFrameInlinedSubroutine *)args;
if (strcmp(name, "ID") == 0) s->func_id = json_read_alloc_string(inp);
@@ -1866,13 +1915,22 @@ static void read_stack_frame_fp(InputStream * inp, StackFrameCache * f) {
static void read_stack_frame_regs(InputStream * inp, StackFrameCache * f) {
trace_regs_cnt = 0;
- if (json_read_struct(inp, read_stack_trace_register, NULL)) {
+ if (json_read_struct(inp, read_stack_trace_register, NULL) && trace_regs_cnt > 0) {
f->sti.reg_cnt = trace_regs_cnt;
f->sti.regs = (StackFrameRegisterLocation **)loc_alloc(trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
memcpy(f->sti.regs, trace_regs, trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
}
}
+static void read_stack_frame_calls(InputStream * inp, StackFrameCache * f) {
+ trace_calls_cnt = 0;
+ if (json_read_array(inp, read_stack_trace_call_param, NULL)) {
+ f->sti.call_cnt = trace_calls_cnt;
+ f->sti.calls = (StackFrameCallSiteParameter **)loc_alloc(trace_calls_cnt * sizeof(StackFrameCallSiteParameter *));
+ memcpy(f->sti.calls, trace_calls, trace_calls_cnt * sizeof(StackFrameCallSiteParameter *));
+ }
+}
+
static void read_stack_frame_inlined(InputStream * inp, StackFrameCache * f) {
trace_subs_cnt = 0;
if (json_read_array(inp, read_inlined_subroutine, NULL)) {
@@ -1888,6 +1946,7 @@ static void read_stack_frame_props(InputStream * inp, const char * name, void *
else if (strcmp(name, "CodeSize") == 0) f->sti.size = (ContextAddress)json_read_uint64(inp);
else if (strcmp(name, "FP") == 0) read_stack_frame_fp(inp, f);
else if (strcmp(name, "Regs") == 0) read_stack_frame_regs(inp, f);
+ else if (strcmp(name, "Calls") == 0) read_stack_frame_calls(inp, f);
else if (strcmp(name, "Inlined") == 0) read_stack_frame_inlined(inp, f);
else json_skip_object(inp);
}
diff --git a/agent/tcf/services/sysmon.c b/agent/tcf/services/sysmon.c
index 18902f38..adeebf7d 100644
--- a/agent/tcf/services/sysmon.c
+++ b/agent/tcf/services/sysmon.c
@@ -730,7 +730,7 @@ static void command_get_children(char * token, Channel * c) {
DWORD * prs_ids = NULL;
int prs_cnt = 0;
if (EnumProcessesProc == NULL) {
- HINSTANCE psapi = LoadLibrary("PSAPI.DLL");
+ HINSTANCE psapi = LoadLibrarySystem32("PSAPI.DLL");
if (psapi == NULL) {
err = set_win32_errno(GetLastError());
}
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c
index ce73c470..1b3900ec 100644
--- a/agent/tcf/services/tcf_elf.c
+++ b/agent/tcf/services/tcf_elf.c
@@ -1799,20 +1799,43 @@ ContextAddress elf_run_time_address_in_region(Context * ctx, MemoryRegion * r, E
/* Note: when debug info is in a separate file, debug file link-time addresses are not same as exec file link-time addresses,
* because Linux has a habbit of re-linking execs after extracting debug info */
unsigned i;
+ int same_file = 0;
+ ELF_File * mem_file = file;
errno = 0;
+ if (r->dev == 0) {
+ same_file = file_name_equ(file, r->file_name);
+ }
+ else {
+ ino_t ino = r->ino;
+ if (ino == 0) ino = elf_ino(r->file_name);
+ same_file = file->ino == ino && file->dev == r->dev;
+ }
+ if (!same_file) {
+ /* Check if the memory map entry has a separate debug info file */
+ if (!file->debug_info_file) mem_file = NULL;
+ else mem_file = elf_open_memory_region_file(r, NULL);
+ if (mem_file != NULL && get_dwarf_file(mem_file) != file) mem_file = NULL;
+ if (mem_file == NULL) {
+ errno = ERR_INV_ADDRESS;
+ return 0;
+ }
+ }
if (r->sect_name == NULL) {
ContextAddress rt = 0;
if (r->size == 0) {
errno = ERR_INV_ADDRESS;
return 0;
}
- for (i = 0; i < file->pheader_cnt; i++) {
- ELF_PHeader * p = file->pheaders + i;
- if (!is_p_header_region(file, p, r)) continue;
- if (addr < p->address || addr >= p->address + p->mem_size) continue;
- rt = (ContextAddress)(addr - p->address + p->offset - r->file_offs + r->addr);
- if (rt < r->addr || rt > r->addr + r->size - 1) continue;
- return rt;
+ for (i = 0; i < mem_file->pheader_cnt; i++) {
+ ELF_PHeader * p = mem_file->pheaders + i;
+ if (p->type == PT_LOAD) {
+ U8_T p_addr = i < file->pheader_cnt ? file->pheaders[i].address : p->address;
+ if (addr < p_addr || addr >= p_addr + p->mem_size) continue;
+ if (!is_p_header_region(mem_file, p, r)) continue;
+ rt = (ContextAddress)(addr - p_addr + p->offset - r->file_offs + r->addr);
+ if (rt < r->addr || rt > r->addr + r->size - 1) continue;
+ return rt;
+ }
}
}
else if (sec != NULL) {
@@ -1820,9 +1843,9 @@ ContextAddress elf_run_time_address_in_region(Context * ctx, MemoryRegion * r, E
return (ContextAddress)(addr - sec->addr + r->addr);
}
}
- else if (file->type == ET_EXEC || file->type == ET_DYN) {
- for (i = 1; i < file->section_cnt; i++) {
- ELF_Section * s = file->sections + i;
+ else if (mem_file->type == ET_EXEC || mem_file->type == ET_DYN) {
+ for (i = 1; i < mem_file->section_cnt; i++) {
+ ELF_Section * s = mem_file->sections + i;
if (s->addr <= addr && s->addr + s->size > addr &&
s->name != NULL && strcmp(s->name, r->sect_name) == 0) {
return (ContextAddress)(addr - s->addr + r->addr);
@@ -1842,25 +1865,7 @@ ContextAddress elf_map_to_run_time_address(Context * ctx, ELF_File * file, ELF_S
if (elf_get_map(ctx, 0, ~(ContextAddress)0, &elf_map) < 0) return 0;
for (i = 0; i < elf_map.region_cnt; i++) {
MemoryRegion * r = elf_map.regions + i;
- ContextAddress a = 0;
- int same_file = 0;
- if (r->dev == 0) {
- same_file = file_name_equ(file, r->file_name);
- }
- else {
- ino_t ino = r->ino;
- if (ino == 0) ino = elf_ino(r->file_name);
- same_file = file->ino == ino && file->dev == r->dev;
- }
- if (!same_file) {
- /* Check if the memory map entry has a separate debug info file */
- ELF_File * exec = NULL;
- if (!file->debug_info_file) continue;
- exec = elf_open_memory_region_file(r, NULL);
- if (exec == NULL) continue;
- if (get_dwarf_file(exec) != file) continue;
- }
- a = elf_run_time_address_in_region(ctx, r, file, sec, addr);
+ ContextAddress a = elf_run_time_address_in_region(ctx, r, file, sec, addr);
if (errno == 0) {
rt = a;
cnt++;
diff --git a/agent/tcf/services/tcf_elf.h b/agent/tcf/services/tcf_elf.h
index 530dae8a..a827d2dd 100644
--- a/agent/tcf/services/tcf_elf.h
+++ b/agent/tcf/services/tcf_elf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -29,10 +29,6 @@
#endif
#include <tcf/framework/context.h>
-#ifndef EM_RISCV
-# define EM_RISCV 243 /* RISC-V */
-#endif
-
#if !defined(INCLUDE_NATIVE_ELF_H)
#define EI_MAG0 0
@@ -85,6 +81,7 @@
#define EM_V850 87 /* NEC/Renesas RH850 */
#define EM_AARCH64 183 /* ARM 64-bit architecture */
#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */
+#define EM_ARC_V2 195 /* Synopsys ARC ARCv2 */
#define ET_NONE 0
#define ET_REL 1
@@ -398,6 +395,13 @@ typedef struct {
#ifndef EM_TRICORE
#define EM_TRICORE 44 /* Siemens Tricore */
#endif
+#ifndef EM_ARC_V2
+#define EM_ARC_V2 195 /* Synopsys ARC ARCv2 */
+#endif
+#ifndef EM_RISCV
+#define EM_RISCV 243 /* RISC-V */
+#endif
+
#ifndef STT_GNU_IFUNC
#define STT_GNU_IFUNC 10
#endif
diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c
index 4b69c41e..df375ab7 100644
--- a/agent/tcf/services/vm.c
+++ b/agent/tcf/services/vm.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011-2018 Wind River Systems, Inc. and others.
+ * Copyright (c) 2011-2022 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.
@@ -30,7 +30,7 @@
#include <tcf/services/dwarf.h>
#include <tcf/services/vm.h>
-#define check_e_stack(n) { if (state->stk_pos < n) inv_dwarf("Invalid location expression stack"); }
+#define check_e_stack(n) { if (state->stk_pos < (unsigned)(n)) inv_dwarf("Invalid location expression stack"); }
static LocationExpressionState * state = NULL;
static RegisterDefinition * reg_def = NULL;
@@ -138,6 +138,38 @@ static uint64_t read_ua(void) {
return 0;
}
+static void f32_to_f64(void) {
+ union { float f; uint32_t u; } f32;
+ union { double f; uint64_t u; } f64;
+ f32.u = (uint32_t)state->type_stk[state->stk_pos - 1];
+ f64.f = (double)f32.f;
+ state->type_stk[state->stk_pos - 1] = f64.u;
+}
+
+static void f64_to_u64(void) {
+ union { double f; uint64_t u; } f64;
+ f64.u = state->type_stk[state->stk_pos - 1];
+ state->type_stk[state->stk_pos - 1] = (uint64_t)f64.f;
+}
+
+static void f64_to_i64(void) {
+ union { double f; uint64_t u; } f64;
+ f64.u = state->type_stk[state->stk_pos - 1];
+ state->type_stk[state->stk_pos - 1] = (int64_t)f64.f;
+}
+
+static void i64_to_f64(void) {
+ union { double f; uint64_t u; } f64;
+ f64.f = (double)(int64_t)state->type_stk[state->stk_pos - 1];
+ state->type_stk[state->stk_pos - 1] = f64.u;
+}
+
+static void u64_to_f64(void) {
+ union { double f; uint64_t u; } f64;
+ f64.f = (double)(uint64_t)state->type_stk[state->stk_pos - 1];
+ state->type_stk[state->stk_pos - 1] = f64.u;
+}
+
static LocationPiece * add_piece(void) {
LocationPiece * piece = NULL;
if (state->pieces_cnt >= state->pieces_max) {
@@ -642,6 +674,10 @@ static void evaluate_expression(void) {
piece = add_piece();
piece->bit_size = read_u4leb128();
piece->bit_offs = read_u4leb128();
+ if (piece->reg == NULL && piece->value == NULL && piece->optimized_away == 0) {
+ piece->addr += piece->bit_offs / 8;
+ piece->bit_offs %= 8;
+ }
break;
case OP_implicit_value:
value_size = read_u4leb128();
@@ -666,68 +702,158 @@ static void evaluate_expression(void) {
}
if (!is_end_of_loc_expr()) inv_dwarf("OP_stack_value must be last instruction");
break;
+ case OP_const_type:
case OP_GNU_const_type:
- inv_dwarf("Unsupported type in OP_GNU_const_type");
+ {
+ uint32_t fund_type = read_u4leb128();
+ uint32_t type_size = read_u4leb128();
+ uint64_t size = read_u8leb128();
+ if (type_size == size) {
+ switch (fund_type) {
+ case ATE_address:
+ case ATE_unsigned:
+ case ATE_unsigned_char:
+ case ATE_unsigned_fixed:
+ case ATE_UTF:
+ case ATE_boolean:
+ switch (size) {
+ case 1:
+ state->stk[state->stk_pos++] = (uint8_t)read_u1();
+ break;
+ case 2:
+ state->stk[state->stk_pos++] = (uint16_t)read_u2();
+ break;
+ case 4:
+ state->stk[state->stk_pos++] = (uint32_t)read_u4();
+ break;
+ case 8:
+ state->stk[state->stk_pos++] = read_u8();
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_const_type");
+ break;
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
+ break;
+ case ATE_signed:
+ case ATE_signed_char:
+ case ATE_signed_fixed:
+ switch (size) {
+ case 1:
+ state->stk[state->stk_pos++] = (int8_t)read_u1();
+ break;
+ case 2:
+ state->stk[state->stk_pos++] = (int16_t)read_u2();
+ break;
+ case 4:
+ state->stk[state->stk_pos++] = (int32_t)read_u4();
+ break;
+ case 8:
+ state->stk[state->stk_pos++] = read_u8();
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_const_type");
+ break;
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
+ break;
+ case ATE_float:
+ case ATE_imaginary_float:
+ switch (size) {
+ case 4:
+ state->stk[state->stk_pos++] = read_u4();
+ f32_to_f64();
+ break;
+ case 8:
+ state->stk[state->stk_pos++] = read_u8();
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_const_type");
+ break;
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_REAL;
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_const_type");
+ break;
+ }
+ }
+ else {
+ inv_dwarf("Unsupported type in OP_const_type");
+ }
+ }
break;
+ case OP_regval_type:
case OP_GNU_regval_type:
- inv_dwarf("Unsupported type in OP_GNU_regval_type");
- break;
- case OP_GNU_deref_type:
- check_e_stack(1);
{
- size_t mem_size = (size_t)read_u8leb128();
+ unsigned reg = (unsigned)read_u8leb128();
uint32_t fund_type = read_u4leb128();
uint32_t type_size = read_u4leb128();
+ RegisterDefinition * def = get_reg_by_id(state->ctx, reg, &state->reg_id_scope);
+ if (def == NULL) exception(errno);
+ if (read_reg_value(state->stack_frame, def, state->stk + state->stk_pos++) < 0) exception(errno);
switch (fund_type) {
case ATE_address:
case ATE_unsigned:
case ATE_unsigned_char:
case ATE_unsigned_fixed:
case ATE_UTF:
- if (mem_size > type_size) mem_size = (size_t)type_size;
- state->stk[state->stk_pos - 1] = read_memory(state->stk[state->stk_pos - 1], mem_size);
- state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
- break;
case ATE_boolean:
- if (mem_size > type_size) mem_size = (size_t)type_size;
- state->stk[state->stk_pos - 1] = read_memory(state->stk[state->stk_pos - 1], mem_size);
- if (state->stk[state->stk_pos - 1] != 0) state->stk[state->stk_pos - 1] = 1;
+ if (type_size < 8) {
+ uint64_t mask = ((uint64_t)1 << (type_size * 8)) - 1;
+ state->stk[state->stk_pos - 1] |= ~mask;
+ }
state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
break;
case ATE_signed:
case ATE_signed_char:
case ATE_signed_fixed:
- if (mem_size > type_size) mem_size = (size_t)type_size;
- state->stk[state->stk_pos - 1] = read_memory(state->stk[state->stk_pos - 1], mem_size);
- if (mem_size < 8) {
- uint64_t sign = (uint64_t)1 << (mem_size * 8 - 1);
+ if (type_size < 8) {
+ uint64_t sign = (uint64_t)1 << (type_size * 8 - 1);
if (state->stk[state->stk_pos - 1] & sign) {
state->stk[state->stk_pos - 1] |= ~(sign - 1);
}
}
state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
break;
+ case ATE_float:
+ case ATE_imaginary_float:
+ switch (type_size) {
+ case 4:
+ f32_to_f64();
+ break;
+ case 8:
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_regval_type");
+ break;
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_REAL;
+ break;
default:
- inv_dwarf("Unsupported type in OP_GNU_deref_type");
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
break;
}
}
break;
- case OP_GNU_convert:
- check_e_stack(1);
+ case OP_deref_type:
+ case OP_xderef_type:
+ case OP_GNU_deref_type:
+ check_e_stack(op == OP_xderef_type ? 2 : 1);
{
+ size_t mem_size = (size_t)read_u8leb128();
uint32_t fund_type = read_u4leb128();
uint32_t type_size = read_u4leb128();
+ uint64_t addr = state->stk[state->stk_pos - 1];
+ if (op == OP_xderef_type) state->stk_pos--;
+ if (mem_size > type_size) mem_size = (size_t)type_size;
+ state->stk[state->stk_pos - 1] = read_memory(addr, mem_size);
switch (fund_type) {
case ATE_address:
case ATE_unsigned:
case ATE_unsigned_char:
case ATE_unsigned_fixed:
case ATE_UTF:
- if (type_size < 8) {
- uint64_t sign = (uint64_t)1 << (type_size * 8 - 1);
- state->stk[state->stk_pos - 1] &= sign - 1;
- }
state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
break;
case ATE_boolean:
@@ -737,19 +863,121 @@ static void evaluate_expression(void) {
case ATE_signed:
case ATE_signed_char:
case ATE_signed_fixed:
- if (type_size < 8) {
- uint64_t sign = (uint64_t)1 << (type_size * 8 - 1);
+ if (mem_size < 8) {
+ uint64_t sign = (uint64_t)1 << (mem_size * 8 - 1);
if (state->stk[state->stk_pos - 1] & sign) {
state->stk[state->stk_pos - 1] |= ~(sign - 1);
}
- else {
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
+ break;
+ case ATE_float:
+ case ATE_imaginary_float:
+ switch (type_size) {
+ case 4:
+ f32_to_f64();
+ break;
+ case 8:
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_regval_type");
+ break;
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_REAL;
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_deref_type");
+ break;
+ }
+ }
+ break;
+ case OP_convert:
+ case OP_GNU_convert:
+ check_e_stack(1);
+ {
+ uint32_t fund_type = read_u4leb128();
+ uint32_t type_size = read_u4leb128();
+ switch (state->type_stk[state->stk_pos - 1]) {
+ case TYPE_CLASS_POINTER:
+ case TYPE_CLASS_CARDINAL:
+ case TYPE_CLASS_INTEGER:
+ case TYPE_CLASS_ENUMERATION:
+ switch (fund_type) {
+ case ATE_address:
+ case ATE_unsigned:
+ case ATE_unsigned_char:
+ case ATE_unsigned_fixed:
+ case ATE_UTF:
+ if (type_size < 8) {
+ uint64_t sign = (uint64_t)1 << (type_size * 8 - 1);
state->stk[state->stk_pos - 1] &= sign - 1;
}
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
+ break;
+ case ATE_boolean:
+ if (state->stk[state->stk_pos - 1] != 0) state->stk[state->stk_pos - 1] = 1;
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
+ break;
+ case ATE_signed:
+ case ATE_signed_char:
+ case ATE_signed_fixed:
+ if (type_size < 8) {
+ uint64_t sign = (uint64_t)1 << (type_size * 8 - 1);
+ if (state->stk[state->stk_pos - 1] & sign) {
+ state->stk[state->stk_pos - 1] |= ~(sign - 1);
+ }
+ else {
+ state->stk[state->stk_pos - 1] &= sign - 1;
+ }
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
+ break;
+ case ATE_float:
+ case ATE_imaginary_float:
+ if (state->type_stk[state->stk_pos - 1] == TYPE_CLASS_INTEGER) {
+ i64_to_f64();
+ }
+ else {
+ u64_to_f64();
+ }
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_REAL;
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_convert");
+ break;
+ }
+ break;
+ case TYPE_CLASS_REAL:
+ switch (fund_type) {
+ case ATE_address:
+ case ATE_unsigned:
+ case ATE_unsigned_char:
+ case ATE_unsigned_fixed:
+ case ATE_UTF:
+ f64_to_u64();
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
+ break;
+ case ATE_boolean:
+ f64_to_u64();
+ if (state->stk[state->stk_pos - 1] != 0) state->stk[state->stk_pos - 1] = 1;
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_CARDINAL;
+ break;
+ case ATE_signed:
+ case ATE_signed_char:
+ case ATE_signed_fixed:
+ f64_to_i64();
+ state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
+ break;
+ case ATE_float:
+ case ATE_imaginary_float:
+ break;
+ default:
+ inv_dwarf("Unsupported type in OP_convert");
+ break;
}
- state->type_stk[state->stk_pos - 1] = TYPE_CLASS_INTEGER;
break;
default:
- inv_dwarf("Unsupported type in OP_GNU_convert");
+ inv_dwarf("Unsupported type in OP_convert");
break;
}
}
@@ -851,6 +1079,7 @@ static void evaluate_expression(void) {
implicit_pointer++;
}
break;
+ case OP_entry_value:
case OP_GNU_entry_value:
{
#if SERVICE_StackTrace || ENABLE_ContextProxy

Back to the top