diff options
author | Xavier Pouyollon | 2015-05-04 14:42:37 +0000 |
---|---|---|
committer | Xavier Pouyollon | 2015-05-05 09:00:18 +0000 |
commit | a11ae4d89c7899ba975b9f924f340515c21ce28a (patch) | |
tree | b07f5685077b21bda96494f8cf06314031d1289a | |
parent | eafe5eaa4e338d2eaa3e81b4eb0164f9b8013ddc (diff) | |
download | org.eclipse.tcf.agent-a11ae4d89c7899ba975b9f924f340515c21ce28a.tar.gz org.eclipse.tcf.agent-a11ae4d89c7899ba975b9f924f340515c21ce28a.tar.xz org.eclipse.tcf.agent-a11ae4d89c7899ba975b9f924f340515c21ce28a.zip |
PPC64 breakpoint support.
Support LocalEntryPoint for PPC64.
Signed-off-by: Xavier Pouyollon <xavier.pouyollon@windriver.com>
-rw-r--r-- | agent/tcf/services/breakpoints.c | 17 | ||||
-rw-r--r-- | agent/tcf/services/symbols.c | 7 | ||||
-rw-r--r-- | agent/tcf/services/symbols.h | 3 | ||||
-rw-r--r-- | agent/tcf/services/symbols_elf.c | 24 | ||||
-rw-r--r-- | agent/tcf/services/symbols_proxy.c | 1 | ||||
-rw-r--r-- | agent/tcf/services/tcf_elf.c | 4 | ||||
-rw-r--r-- | agent/tcf/services/tcf_elf.h | 1 |
7 files changed, 54 insertions, 3 deletions
diff --git a/agent/tcf/services/breakpoints.c b/agent/tcf/services/breakpoints.c index b74313c6..ed13c22e 100644 --- a/agent/tcf/services/breakpoints.c +++ b/agent/tcf/services/breakpoints.c @@ -1421,10 +1421,18 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp ContextAddress size = 1; int error = 0; Value v; - + SymbolProperties props; + 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 (v.sym != NULL) { + /* We want to add the LocalEntryOffset */ + get_symbol_props(v.sym, &props); + /* If the symbol is not a PPC64 function, offset should be 0, so it is safe to add */ + addr += props.local_entry_offset; + } #if ENABLE_SkipPrologueWhenPlanting + /* Even if addr is incremented by local_entry_offset, we still should be on right code area */ if (!error && bp->skip_prologue && v.sym != NULL && skip_function_prologue(ctx, v.sym, &addr) < 0) error = errno; #endif if (bp->access_size > 0) { @@ -1456,8 +1464,13 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp unsigned n = 0; while (v.sym_list[n] != NULL) { Symbol * sym = v.sym_list[n++]; - if (get_symbol_address(sym, &addr) == 0) { + if (get_symbol_address(sym, &addr) == 0) { + /* We want to add the LocalEntryOffset */ + get_symbol_props(sym, &props); + /* If the symbol is not a PPC64 function, offset should be 0, so it is safe to add */ + addr += props.local_entry_offset; #if ENABLE_SkipPrologueWhenPlanting + /* Even if addr is incremented by local_entry_offset, we still should be on right code area */ if (bp->skip_prologue) skip_function_prologue(ctx, sym, &addr); #endif plant_breakpoint(ctx, bp, addr, size); diff --git a/agent/tcf/services/symbols.c b/agent/tcf/services/symbols.c index d146d7cb..edbf834f 100644 --- a/agent/tcf/services/symbols.c +++ b/agent/tcf/services/symbols.c @@ -303,6 +303,13 @@ static void command_get_context_cache_client(void * x) { write_stream(&c->out, ','); } + if (props.local_entry_offset != 0) { + json_write_string(&c->out, "LocalEntryOffset"); + write_stream(&c->out, ':'); + json_write_ulong(&c->out, props.local_entry_offset); + write_stream(&c->out, ','); + } + if (value != NULL) { json_write_string(&c->out, "Value"); write_stream(&c->out, ':'); diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h index 143e9ac5..33a39972 100644 --- a/agent/tcf/services/symbols.h +++ b/agent/tcf/services/symbols.h @@ -91,7 +91,8 @@ typedef uint32_t SYM_FLAGS; typedef struct SymbolProperties { int binary_scale; /* The exponent of the base two scale factor to be applied to an instance of the type */ int decimal_scale; /* The exponent of the base ten scale factor to be applied to an instance of the type */ - unsigned bit_stride; + unsigned bit_stride; + unsigned int local_entry_offset; /* Only PPC64 v2 supports it */ } SymbolProperties; /* Symbol properties update policies */ diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c index a38655e6..c014961d 100644 --- a/agent/tcf/services/symbols_elf.c +++ b/agent/tcf/services/symbols_elf.c @@ -4147,6 +4147,11 @@ int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) { } int get_symbol_props(const Symbol * sym, SymbolProperties * props) { +#define STO_PPC64_LOCAL_BIT 5 +#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) +#define IS_PPC64_V2(elfsym) ((elfsym->file->machine == EM_PPC64) && (elfsym->file->flags & 0x3) == 2) + + ELF_SymbolInfo elf_sym_info; ObjectInfo * obj = sym->obj; assert(sym->magic == SYMBOL_MAGIC); memset(props, 0, sizeof(SymbolProperties)); @@ -4162,6 +4167,25 @@ int get_symbol_props(const Symbol * sym, SymbolProperties * props) { if (get_num_prop(obj, AT_stride_size, &n)) props->bit_stride = (unsigned)n; } } + + /* PowerPC64 ABIv2 computes local offset from st_other */ + if (sym->tbl != NULL) { + /* Only do that on PPC64 v2 */ + if (!IS_PPC64_V2(sym->tbl)) + return 0; + unpack_elf_symbol_info(sym->tbl, sym->index, &elf_sym_info); + } else { + Symbol *elf_symbol; + /* From Dwarf object to Elf symbol */ + map_to_sym_table(sym->obj, &elf_symbol); + if (elf_symbol == NULL) + return 0; + if (!IS_PPC64_V2(elf_symbol->tbl)) + return 0; + unpack_elf_symbol_info(elf_symbol->tbl, elf_symbol->index, &elf_sym_info); + } + /* We can compute the offset now */ + props->local_entry_offset = (((1 << (((elf_sym_info.other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2); return 0; } diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c index bc398e80..22e6bdd8 100644 --- a/agent/tcf/services/symbols_proxy.c +++ b/agent/tcf/services/symbols_proxy.c @@ -671,6 +671,7 @@ static void read_context_data(InputStream * inp, const char * name, void * args) else if (strcmp(name, "BinaryScale") == 0) s->props.binary_scale = (int)json_read_long(inp); else if (strcmp(name, "DecimalScale") == 0) s->props.decimal_scale = (int)json_read_long(inp); else if (strcmp(name, "BitStride") == 0) s->props.bit_stride = (unsigned)json_read_ulong(inp); + else if (strcmp(name, "LocalEntryOffset") == 0) s->props.local_entry_offset = (unsigned)json_read_ulong(inp); else if (strcmp(name, "Flags") == 0) s->flags = json_read_ulong(inp); else if (strcmp(name, "Frame") == 0) s->frame = (int)json_read_long(inp); else json_skip_object(inp); diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c index 481188c0..a10f2c5c 100644 --- a/agent/tcf/services/tcf_elf.c +++ b/agent/tcf/services/tcf_elf.c @@ -1679,6 +1679,7 @@ void unpack_elf_symbol_info(ELF_Section * sym_sec, U4_T index, ELF_SymbolInfo * SWAP(s.st_shndx); SWAP(s.st_size); SWAP(s.st_value); + SWAP(s.st_other); } st_name = (size_t)s.st_name; info->section_index = s.st_shndx; @@ -1686,6 +1687,7 @@ void unpack_elf_symbol_info(ELF_Section * sym_sec, U4_T index, ELF_SymbolInfo * info->type = ELF64_ST_TYPE(s.st_info); info->value = s.st_value; info->size = s.st_size; + info->other = s.st_other; } else { Elf32_Sym s = *(Elf32_Sym *)((U1_T *)sym_sec->data + sym_sec->entsize * index); @@ -1694,6 +1696,7 @@ void unpack_elf_symbol_info(ELF_Section * sym_sec, U4_T index, ELF_SymbolInfo * SWAP(s.st_shndx); SWAP(s.st_size); SWAP(s.st_value); + SWAP(s.st_other); } st_name = (size_t)s.st_name; info->section_index = s.st_shndx; @@ -1701,6 +1704,7 @@ void unpack_elf_symbol_info(ELF_Section * sym_sec, U4_T index, ELF_SymbolInfo * info->type = ELF32_ST_TYPE(s.st_info); info->value = s.st_value; info->size = s.st_size; + info->other = s.st_other; } if (info->section_index > 0 && info->section_index < file->section_cnt) { diff --git a/agent/tcf/services/tcf_elf.h b/agent/tcf/services/tcf_elf.h index a1129aed..8fe8997b 100644 --- a/agent/tcf/services/tcf_elf.h +++ b/agent/tcf/services/tcf_elf.h @@ -477,6 +477,7 @@ struct ELF_SymbolInfo { U1_T type; U8_T value; U8_T size; + U8_T other; }; struct ELF_Section { |