[RFC,2/3] Record function descriptor address instead of function address in value
Commit Message
1. Problem statement
Nowadays, function address is recorded in value in GDB. It is convenient
to use GDB on some targets function pointer address isn't function
address, like ppc64 and arm thumb mode. For example, on ppc64,
(gdb) p incr
$4 = {int (int)} 0x1000069c <incr>
(gdb) disassemble incr
Dump of assembler code for function incr:
0x000000001000069c <+0>: mflr r0
"incr" is the address of "incr" function, which differs from its meaning
in C language. In .c file, "incr" is the address of "incr" function
descriptor, if we write
printf ("incr %llx, &incr %llx\n", incr, &incr);
it prints the function descriptor address. Then this brings confusion
in GDB when we do expression evaluation,
int incr (int i) {}
int (*calc) (int) = incr;
in C, the statement above means assign "incr" function descriptor
address to "calc", or "calc" pointers to "incr" function descriptor.
However, if we evaluation expressions in gdb with function involved,
we'll see something interesting,
(gdb) p if calc == incr
this prints 0 because calc pointers to "incr" function descriptor,
but "incr" is its function address, so they are different,
(gdb) set calc = incr
"incr" function address is assigned to "calc", but it is expected
to get function descriptor address.
2. Solution
GCC vs GDB divergence on the meaning of "incr" brings the confusion.
We should reduce such divergence as much as we can. However, this
divergence was added in https://sourceware.org/ml/gdb-patches/2001-11/msg00001.html
I agree with Jim, but I'd like use function descriptor address in value,
which makes the whole expression evaluation look more reasonable and
more close to compiler's behavior.
In this patch, I add a new gdbarch method convert_from_func_addr, which
converts function address back to function descriptor address or
function pointer address. It is the reversed operation of
convert_from_func_ptr_addr. We convert function address to function
descriptor address when,
- we create value for a function,
- we generate ax code for a function,
I don't change the meaning of return value of value_as_address, because
it is widely used, so value_as_address still return the function
address if type is TYPE_CODE_FUNC or TYPE_CODE_METHOD.
3. User visible changes
This patch brings several user visible changes, which look more
accurate, shown by this table below,
COMMAND BEFORE AFTER
p main main function address main function descriptor
address
disass main disassembly function main not changed
disass main+4,+4 disassembly 4 bytes from disassembly 4 bytes from
function main address + 4 main's function descriptor + 4
x/i main show one instruction on show one instruction on main's
function main address function descriptor
Although the latter looks inconvenient, that is consistent to the
meaning on C language level. Due to these changes, test cases are
adjusted accordingly.
gdb:
2016-10-14 Yao Qi <yao.qi@linaro.org>
* arch-utils.c (convert_from_func_addr_identity): New function.
* arch-utils.h (convert_from_func_addr_identity): Declare.
* arm-tdep.c (arm_convert_from_func_addr): New function.
(arm_convert_from_func_ptr_addr): New function.
(arm_gdbarch_init): Install gdbarch hook convert_from_func_addr
and convert_from_func_ptr_addr.
* ax-gdb.c (gen_var_ref): Call gdbarch_convert_from_func_addr.
* findvar.c (default_read_var_value): Likewise.
* gdbarch.sh (convert_from_func_addr): New.
* gdbarch.h, gdbarch.c: Re-generated.
* infcall.c (find_function_addr): Call value_as_address
instead of value_address.
* ppc64-tdep.c (ppc64_convert_from_func_addr): New function.
* ppc64-tdep.h (ppc64_convert_from_func_addr): Declare.
* ppc-linux-tdep.c (ppc_linux_init_abi): Install
convert_from_func_addr.
* ppcfbsd-tdep.c: Likewise.
* value.c (value_as_address): Call gdbarch_convert_from_func_ptr_addr.
---
gdb/arch-utils.c | 6 ++++++
gdb/arch-utils.h | 1 +
gdb/arm-tdep.c | 23 +++++++++++++++++++++++
gdb/ax-gdb.c | 12 +++++++++---
gdb/findvar.c | 5 +++++
gdb/gdbarch.c | 23 +++++++++++++++++++++++
gdb/gdbarch.h | 6 ++++++
gdb/gdbarch.sh | 4 ++++
gdb/infcall.c | 2 +-
gdb/ppc-linux-tdep.c | 2 ++
gdb/ppc64-tdep.c | 30 ++++++++++++++++++++++++++++++
gdb/ppc64-tdep.h | 3 ++-
gdb/ppcfbsd-tdep.c | 2 ++
gdb/value.c | 4 +++-
14 files changed, 117 insertions(+), 6 deletions(-)
Comments
On 2016-10-14 06:53, Yao Qi wrote:
> In this patch, I add a new gdbarch method convert_from_func_addr, which
> converts function address back to function descriptor address or
> function pointer address. It is the reversed operation of
> convert_from_func_ptr_addr. We convert function address to function
> descriptor address when,
I think these could be better named, byt saying what it converts from
_and_ what it converts to. With convert_from_func_addr, we know it
takes as input a function address, but we don't know what it converts it
to. What about something like convert_func_address_to_descriptor (or
convert_func_addr_to_desc if you prefer shorter names)?
I think that it would also be clearer if we always used the same
terminology (address and descriptor seem good). It is not very
intuitive what is the difference between convert_from_func_ptr_addr and
convert_from_func_addr. "function pointer address" and "function
address" sound too close to each other, so it's easy to confuse them...
> 3. User visible changes
>
> This patch brings several user visible changes, which look more
> accurate, shown by this table below,
>
> COMMAND BEFORE AFTER
> p main main function address main function
> descriptor
> address
> disass main disassembly function main not changed
> disass main+4,+4 disassembly 4 bytes from disassembly 4 bytes
> from
> function main address + 4 main's function
> descriptor + 4
> x/i main show one instruction on show one instruction on
> main's
> function main address function descriptor
>
> Although the latter looks inconvenient, that is consistent to the
> meaning on C language level. Due to these changes, test cases are
> adjusted accordingly.
Could you provide example of the actual output of those commands, before
and after? It is not clear to me what the difference will be.
Thanks,
Simon
On Fri, Oct 14, 2016 at 6:35 PM, Simon Marchi <simon.marchi@polymtl.ca> wrote:
> On 2016-10-14 06:53, Yao Qi wrote:
>>
>> In this patch, I add a new gdbarch method convert_from_func_addr, which
>> converts function address back to function descriptor address or
>> function pointer address. It is the reversed operation of
>> convert_from_func_ptr_addr. We convert function address to function
>> descriptor address when,
>
>
> I think these could be better named, byt saying what it converts from _and_
> what it converts to. With convert_from_func_addr, we know it takes as input
> a function address, but we don't know what it converts it to. What about
> something like convert_func_address_to_descriptor (or
> convert_func_addr_to_desc if you prefer shorter names)?
>
> I think that it would also be clearer if we always used the same terminology
> (address and descriptor seem good). It is not very intuitive what is the
> difference between convert_from_func_ptr_addr and convert_from_func_addr.
> "function pointer address" and "function address" sound too close to each
> other, so it's easy to confuse them...
>
If we want to know what these two methods convert to, I'd like to use
"func_addr" and "func_ptr_addr". These two methods can be named as
convert_func_addr_to_func_ptr_addr and
convert_func_ptr_addr_to_func_addr, but they are a little bit long. Maybe,
remove "convert_" from the names?
>> 3. User visible changes
>>
>> This patch brings several user visible changes, which look more
>> accurate, shown by this table below,
>>
>> COMMAND BEFORE AFTER
>> p main main function address main function descriptor
>> address
>> disass main disassembly function main not changed
>> disass main+4,+4 disassembly 4 bytes from disassembly 4 bytes from
>> function main address + 4 main's function descriptor
>> + 4
>> x/i main show one instruction on show one instruction on
>> main's
>> function main address function descriptor
>>
>> Although the latter looks inconvenient, that is consistent to the
>> meaning on C language level. Due to these changes, test cases are
>> adjusted accordingly.
>
>
> Could you provide example of the actual output of those commands, before and
> after? It is not clear to me what the difference will be.
>
"p incr" shows the function descriptor address instead of function address.
old ppc64 gdb:
(gdb) p incr
$2 = {int (int)} 0x1000069c <incr>
(gdb) p &incr
$3 = (int (*)(int)) 0x1000069c <incr>
old arm gdb:
(gdb) p incr
$2 = {int (int)} 0x104fe <incr>
(gdb) p &incr
$3 = (int (*)(int)) 0x104fe <incr>
new ppc64 gdb:
(gdb) p incr
$2 = {int (int)} 0x10020090 <incr>
(gdb) p &incr
$3 = (int (*)(int)) @0x10020090: 0x1000069c <incr>
new arm gdb:
(gdb) p incr
$1 = {int (int)} 0x104ff <incr>
(gdb) p &incr
$2 = (int (*)(int)) @0x104ff: 0x104fe <incr>
"disassemble incr" is not changed,
(gdb) disassemble incr
Dump of assembler code for function incr:
0x000000001000069c <+0>: mflr r0
0x00000000100006a0 <+4>: std r0,16(r1)
"disassemble incr+4,+4" is changed, "incr" means function address
in old gdb, but it means function descriptor address in new gdb.
old gdb:
(gdb) disassemble incr+4,+4
Dump of assembler code from 0x100006a0 to 0x100006a4:
0x00000000100006a0 <incr+4>: std r0,16(r1)
new gdb:
(gdb) disassemble incr+4,+4
Dump of assembler code from 0x10020094 to 0x10020098:
0x0000000010020094 <incr+4>: ps_madds0 f0,f0,f26,f0
... so "disassemble incr+4,+4" makes no sense in new gdb. However,
you can use address instead.
Similarly, in old gdb, "x/i incr" is to show the first instruction at function
incr, but in new gdb, it shows the first instruction at function descriptor.
(gdb) x/i incr
0x1000069c <incr>: mflr r0
(gdb) x/i incr
0x10020090 <incr>: .long 0x0
On 2016-10-17 07:40, Yao Qi wrote:
> On Fri, Oct 14, 2016 at 6:35 PM, Simon Marchi <simon.marchi@polymtl.ca>
> wrote:
>> On 2016-10-14 06:53, Yao Qi wrote:
>>>
>>> In this patch, I add a new gdbarch method convert_from_func_addr,
>>> which
>>> converts function address back to function descriptor address or
>>> function pointer address. It is the reversed operation of
>>> convert_from_func_ptr_addr. We convert function address to function
>>> descriptor address when,
>>
>>
>> I think these could be better named, byt saying what it converts from
>> _and_
>> what it converts to. With convert_from_func_addr, we know it takes as
>> input
>> a function address, but we don't know what it converts it to. What
>> about
>> something like convert_func_address_to_descriptor (or
>> convert_func_addr_to_desc if you prefer shorter names)?
>>
>> I think that it would also be clearer if we always used the same
>> terminology
>> (address and descriptor seem good). It is not very intuitive what is
>> the
>> difference between convert_from_func_ptr_addr and
>> convert_from_func_addr.
>> "function pointer address" and "function address" sound too close to
>> each
>> other, so it's easy to confuse them...
>>
>
> If we want to know what these two methods convert to, I'd like to use
> "func_addr" and "func_ptr_addr". These two methods can be named as
> convert_func_addr_to_func_ptr_addr and
> convert_func_ptr_addr_to_func_addr, but they are a little bit long.
> Maybe,
> remove "convert_" from the names?
As you wish, I think it's still clear if the "convert_" is omitted.
> "p incr" shows the function descriptor address instead of function
> address.
>
> old ppc64 gdb:
> (gdb) p incr
> $2 = {int (int)} 0x1000069c <incr>
> (gdb) p &incr
> $3 = (int (*)(int)) 0x1000069c <incr>
>
> old arm gdb:
> (gdb) p incr
> $2 = {int (int)} 0x104fe <incr>
> (gdb) p &incr
> $3 = (int (*)(int)) 0x104fe <incr>
>
> new ppc64 gdb:
> (gdb) p incr
> $2 = {int (int)} 0x10020090 <incr>
> (gdb) p &incr
> $3 = (int (*)(int)) @0x10020090: 0x1000069c <incr>
>
> new arm gdb:
> (gdb) p incr
> $1 = {int (int)} 0x104ff <incr>
> (gdb) p &incr
> $2 = (int (*)(int)) @0x104ff: 0x104fe <incr>
I am not familiar with ppc64. 0x1000069c is the actual code, and
0x10020090 is the descriptor address? Or is it the other way?
> "disassemble incr" is not changed,
>
> (gdb) disassemble incr
> Dump of assembler code for function incr:
> 0x000000001000069c <+0>: mflr r0
> 0x00000000100006a0 <+4>: std r0,16(r1)
>
> "disassemble incr+4,+4" is changed, "incr" means function address
> in old gdb, but it means function descriptor address in new gdb.
>
> old gdb:
> (gdb) disassemble incr+4,+4
> Dump of assembler code from 0x100006a0 to 0x100006a4:
> 0x00000000100006a0 <incr+4>: std r0,16(r1)
>
> new gdb:
> (gdb) disassemble incr+4,+4
> Dump of assembler code from 0x10020094 to 0x10020098:
> 0x0000000010020094 <incr+4>: ps_madds0 f0,f0,f26,f0
>
> ... so "disassemble incr+4,+4" makes no sense in new gdb. However,
> you can use address instead.
>
> Similarly, in old gdb, "x/i incr" is to show the first instruction at
> function
> incr, but in new gdb, it shows the first instruction at function
> descriptor.
>
> (gdb) x/i incr
> 0x1000069c <incr>: mflr r0
> (gdb) x/i incr
> 0x10020090 <incr>: .long 0x0
Ok, so it is not the best UI-wise. Is there a way we can add
conversions from the descriptor address to the code address in the right
circumstances, in order to make it more useful to the user? For
example, does it ever make sense to apply the operator + to the
descriptor address, or could we always convert to code address for that?
Same for disassembly, it probably never makes sense to disassemble the
descriptors, so could we add an explicit conversion there?
Hi Ulrich,
I did some experiments these days, for all your suggestions, and
comments. I share the results now...
On Mon, Oct 17, 2016 at 4:51 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Yao Qi wrote:
>
>> GCC vs GDB divergence on the meaning of "incr" brings the confusion.
>> We should reduce such divergence as much as we can. However, this
>> divergence was added in https://sourceware.org/ml/gdb-patches/2001-11/msg00001.html
>> I agree with Jim, but I'd like use function descriptor address in value,
>> which makes the whole expression evaluation look more reasonable and
>> more close to compiler's behavior.
>
> I agree that this is a problem. However, the reasons Jim mentions in
> that long comment are still valid: it is in general *not possible* to
> convert an arbitrary function address back to a function descriptor ...
>
>> In this patch, I add a new gdbarch method convert_from_func_addr, which
>> converts function address back to function descriptor address or
>> function pointer address. It is the reversed operation of
>> convert_from_func_ptr_addr.
>
> ... and therefore this function cannot really be implemented on ppc64
> in a fully-general way. In particular, when running stripped binaries
> or code that is otherwise without symbols (e.g. JITted code etc.), this
> conversion may not be possible.
I don't expect convert_from_func_addr working in general, due to the
reasons you mentioned. convert_from_func_addr is only used when
symbol (from debug information) is available. If we want to GDB
handle such complex expression evaluation correctly, debug
information is required.
>
> B.t.w. note that there is already a similar function that attempts this
> conversion (ppc-sysv-tdep.c:convert_code_addr_to_desc_addr), but it is
> currently only used during inferior function calls, so it is not so
> critical if it fails. (With your change, that function may actually
> no longer be necessary at that place since values should already point
> to function descriptors ...)
>
Yes, convert_from_func_addr is similar to convert_code_addr_to_desc_addr.
I removed convert_code_addr_to_desc_addr, but it breaks ifunc
inferior call in my experiment, because ifunc resolver gets the function
address rather than function descriptor address, we still need
convert_code_addr_to_desc_addr to get function descriptor address.
> Note that this checks for presence of an msymbol at the code address,
> while your code checks for presence of a symbol. Maybe the best way
> would be to check for either.
>
Now, convert_from_func_addr does whatever
convert_code_addr_to_desc_addr does.
>> We convert function address to function
>> descriptor address when,
>>
>> - we create value for a function,
>> - we generate ax code for a function,
>
> Since the conversion is problematic in general, I think the best way
> would be to keep descriptor addresses wherever possible, and only
> convert to code addresses at the last minute when necessary.
>
Yes, I agree.
> Your code already *mostly* does that, with the exception of symbol
> addresses. I'm wondering whether we shouldn't push the change one
> step further back and already store descriptor addresses in
> SYMBOL_VALUE_ADDRESS. Note that this is currently already handled
> somewhat inconsistenly on ppc64: msymbols already point to the
> descriptor, and so do symbols read from stabs debug info; only
> symbols read from DWARF debug info actually point to the code
> address.
I tried what you suggested, but failed. SYMBOL_VALUE_ADDRESS
is used to get variable address, rather than function's address. We
get function address from block (BLOCK_START), and get block
from symbol (SYMBOL_BLOCK_VALUE). There is no good way to
store function descriptor address in symbol.
>
>> I don't change the meaning of return value of value_as_address, because
>> it is widely used, so value_as_address still return the function
>> address if type is TYPE_CODE_FUNC or TYPE_CODE_METHOD.
>
> I'm wondering whether this is a good idea; maybe it would be better to
> return descriptor addresses and update those callers that actually need
> code addresses. This would keep the principle that we should keep
> descriptor addresses as long as possible. Also, this might actually
> fix more bugs; if you look at e.g. this code in value_equal:
>
> else if (code1 == TYPE_CODE_PTR && is_int2)
> return value_as_address (arg1) == (CORE_ADDR) value_as_long (arg2);
> else if (code2 == TYPE_CODE_PTR && is_int1)
> return (CORE_ADDR) value_as_long (arg1) == value_as_address (arg2);
>
> this might actually cause invalid evaluation of expressions like
>
> incr == 0x12345678
>
> (as compared to the native C evaluation).
>
How about doing this in a followup patch as an enhancement? My
priority is to get this RFC acceptable, and make PPC64/ARM/MIPS
works well. Propagate descriptor address and bug fixes can be done
later.
>
>> This patch brings several user visible changes, which look more
>> accurate, shown by this table below,
>>
>> COMMAND BEFORE AFTER
>> p main main function address main function descriptor
>> address
>> disass main disassembly function main not changed
>> disass main+4,+4 disassembly 4 bytes from disassembly 4 bytes from
>> function main address + 4 main's function descriptor + 4
>> x/i main show one instruction on show one instruction on main's
>> function main address function descriptor
>>
>> Although the latter looks inconvenient, that is consistent to the
>> meaning on C language level. Due to these changes, test cases are
>> adjusted accordingly.
>
> Those are a bit annoying. I think the underlying problem is that operations
> like "disass" or "x/i" really don't work on "values" in the original sense
> but rather on "PC addresses". Maybe it would make sense to have those
> function enable a special "mode" in the expression evaluator that would
> change the conversion of functions to function pointers to use the code
> address instead of the descriptor address?
>
I think about the special "mode" in the expression evaluation, but I
suspect that there is a case in a single expression, function address
is expected in some symbol, and descriptor address is expected in
some other symbol, like,
int func (int i) { return i;}
(gdb) x/i func + func (1)
the "func" is expected to be function address and the second "func"
is expected to be function descriptor address. I had a heuristics that
VALUE means function address if we do a pointer add with long type
(valarith.c:value_ptradd). It works fine.
I've already managed to get all my patches work. If you agree with
my thoughts above, I'll post my patches next week.
@@ -168,6 +168,12 @@ convert_from_func_ptr_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr,
return addr;
}
+CORE_ADDR
+convert_from_func_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ return addr;
+}
+
int
no_op_reg_to_regnum (struct gdbarch *gdbarch, int reg)
{
@@ -63,6 +63,7 @@ extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
extern CORE_ADDR core_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr);
extern gdbarch_convert_from_func_ptr_addr_ftype convert_from_func_ptr_addr_identity;
+extern gdbarch_convert_from_func_addr_ftype convert_from_func_addr_identity;
/* No-op conversion of reg to regnum. */
@@ -537,6 +537,26 @@ arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
return (val & 0x03fffffc);
}
+/* Implement the convert_from_func_addr gdbarch method. */
+
+static CORE_ADDR
+arm_convert_from_func_addr (struct gdbarch *gdbarch, CORE_ADDR val)
+{
+ if (arm_pc_is_thumb (gdbarch, val))
+ return MAKE_THUMB_ADDR (val);
+ else
+ return val;
+}
+
+/* Implement the convert_from_func_ptr_addr gdbarch method. */
+
+static CORE_ADDR
+arm_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
+ struct target_ops *targ)
+{
+ return IS_THUMB_ADDR (addr) ? UNMAKE_THUMB_ADDR (addr) : addr;
+}
+
/* Return 1 if PC is the start of a compiler helper function which
can be safely ignored during prologue skipping. IS_THUMB is true
if the function is known to be a Thumb function due to the way it
@@ -9396,6 +9416,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Address manipulation. */
set_gdbarch_addr_bits_remove (gdbarch, arm_addr_bits_remove);
+ set_gdbarch_convert_from_func_addr (gdbarch, arm_convert_from_func_addr);
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+ arm_convert_from_func_ptr_addr);
/* Advance PC across function entry code. */
set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
@@ -689,10 +689,16 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax,
break;
case LOC_BLOCK:
- ax_const_l (ax, BLOCK_START (SYMBOL_BLOCK_VALUE (var)));
- value->kind = axs_rvalue;
- break;
+ {
+ CORE_ADDR addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ /* Get address of function pointer rather than function
+ address. */
+ addr = gdbarch_convert_from_func_addr (gdbarch, addr);
+ ax_const_l (ax, addr);
+ value->kind = axs_rvalue;
+ break;
+ }
case LOC_REGISTER:
/* Don't generate any code at all; in the process of treating
this as an lvalue or rvalue, the caller will generate the
@@ -698,6 +698,11 @@ default_read_var_value (struct symbol *var, const struct block *var_block,
SYMBOL_OBJ_SECTION (symbol_objfile (var), var));
else
addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+
+ /* Get address of function pointer rather than function
+ address. */
+ addr = gdbarch_convert_from_func_addr (get_type_arch (type),
+ addr);
break;
case LOC_REGISTER:
@@ -246,6 +246,7 @@ struct gdbarch
gdbarch_stabs_argument_has_addr_ftype *stabs_argument_has_addr;
int frame_red_zone_size;
gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr;
+ gdbarch_convert_from_func_addr_ftype *convert_from_func_addr;
gdbarch_addr_bits_remove_ftype *addr_bits_remove;
gdbarch_software_single_step_ftype *software_single_step;
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
@@ -409,6 +410,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
gdbarch->remote_register_number = default_remote_register_number;
gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
+ gdbarch->convert_from_func_addr = convert_from_func_addr_identity;
gdbarch->addr_bits_remove = core_addr_identity;
gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
gdbarch->skip_solib_resolver = generic_skip_solib_resolver;
@@ -598,6 +600,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of frame_align, has predicate. */
/* Skip verify of stabs_argument_has_addr, invalid_p == 0 */
/* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
+ /* Skip verify of convert_from_func_addr, invalid_p == 0 */
/* Skip verify of addr_bits_remove, invalid_p == 0 */
/* Skip verify of software_single_step, has predicate. */
/* Skip verify of single_step_through_delay, has predicate. */
@@ -820,6 +823,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: coff_make_msymbol_special = <%s>\n",
host_address_to_string (gdbarch->coff_make_msymbol_special));
fprintf_unfiltered (file,
+ "gdbarch_dump: convert_from_func_addr = <%s>\n",
+ host_address_to_string (gdbarch->convert_from_func_addr));
+ fprintf_unfiltered (file,
"gdbarch_dump: convert_from_func_ptr_addr = <%s>\n",
host_address_to_string (gdbarch->convert_from_func_ptr_addr));
fprintf_unfiltered (file,
@@ -3096,6 +3102,23 @@ set_gdbarch_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
}
CORE_ADDR
+gdbarch_convert_from_func_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->convert_from_func_addr != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_convert_from_func_addr called\n");
+ return gdbarch->convert_from_func_addr (gdbarch, addr);
+}
+
+void
+set_gdbarch_convert_from_func_addr (struct gdbarch *gdbarch,
+ gdbarch_convert_from_func_addr_ftype convert_from_func_addr)
+{
+ gdbarch->convert_from_func_addr = convert_from_func_addr;
+}
+
+CORE_ADDR
gdbarch_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
{
gdb_assert (gdbarch != NULL);
@@ -642,6 +642,12 @@ typedef CORE_ADDR (gdbarch_convert_from_func_ptr_addr_ftype) (struct gdbarch *gd
extern CORE_ADDR gdbarch_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, struct target_ops *targ);
extern void set_gdbarch_convert_from_func_ptr_addr (struct gdbarch *gdbarch, gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr);
+/* Convert function address to function pointer address. */
+
+typedef CORE_ADDR (gdbarch_convert_from_func_addr_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern CORE_ADDR gdbarch_convert_from_func_addr (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void set_gdbarch_convert_from_func_addr (struct gdbarch *gdbarch, gdbarch_convert_from_func_addr_ftype *convert_from_func_addr);
+
/* On some machines there are bits in addresses which are not really
part of the address, but are used by the kernel, the hardware, etc.
for special purposes. gdbarch_addr_bits_remove takes out any such bits so
@@ -598,6 +598,10 @@ m:int:stabs_argument_has_addr:struct type *type:type::default_stabs_argument_has
v:int:frame_red_zone_size
#
m:CORE_ADDR:convert_from_func_ptr_addr:CORE_ADDR addr, struct target_ops *targ:addr, targ::convert_from_func_ptr_addr_identity::0
+
+# Convert function address to function pointer address.
+m:CORE_ADDR:convert_from_func_addr:CORE_ADDR addr:addr::convert_from_func_addr_identity::0
+
# On some machines there are bits in addresses which are not really
# part of the address, but are used by the kernel, the hardware, etc.
# for special purposes. gdbarch_addr_bits_remove takes out any such bits so
@@ -260,7 +260,7 @@ find_function_addr (struct value *function, struct type **retval_type)
/* Determine address to call. */
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- funaddr = value_address (function);
+ funaddr = value_as_address (function);
else if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
{
funaddr = value_as_address (function);
@@ -1744,6 +1744,8 @@ ppc_linux_init_abi (struct gdbarch_info info,
function descriptors). */
set_gdbarch_convert_from_func_ptr_addr
(gdbarch, ppc64_convert_from_func_ptr_addr);
+ set_gdbarch_convert_from_func_addr
+ (gdbarch, ppc64_convert_from_func_entry);
set_gdbarch_elf_make_msymbol_special
(gdbarch, ppc64_elf_make_msymbol_special);
@@ -24,6 +24,7 @@
#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "elf-bfd.h"
+#include "objfiles.h"
/* Macros for matching instructions. Note that, since all the
operands are masked off before they're or-ed into the instruction,
@@ -615,6 +616,35 @@ ppc64_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
return addr;
}
+/* Implement the convert_from_func_addr gdbarch method. */
+
+CORE_ADDR
+ppc64_convert_from_func_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ struct symbol *sym = find_pc_function (addr);
+
+ if (sym != NULL)
+ {
+ struct bound_minimal_symbol msym;
+ struct obj_section *dot_fn_section;
+
+ dot_fn_section = find_pc_section (addr);
+ if (dot_fn_section == NULL || dot_fn_section->objfile == NULL)
+ return addr;
+
+ msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), NULL,
+ dot_fn_section->objfile);
+
+ /* That is the address of function descriptor. */
+ if (msym.minsym != NULL)
+ return BMSYMBOL_VALUE_ADDRESS (msym);
+ else
+ return addr;
+ }
+ else
+ return addr;
+}
+
/* A synthetic 'dot' symbols on ppc64 has the udata.p entry pointing
back to the original ELF symbol it was derived from. Get the size
from that symbol. */
@@ -30,7 +30,8 @@ extern CORE_ADDR ppc64_skip_trampoline_code (struct frame_info *frame,
extern CORE_ADDR ppc64_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
CORE_ADDR addr,
struct target_ops *targ);
-
+extern CORE_ADDR ppc64_convert_from_func_addr (struct gdbarch *gdbarch,
+ CORE_ADDR addr);
extern void ppc64_elf_make_msymbol_special (asymbol *,
struct minimal_symbol *);
#endif /* PPC64_TDEP_H */
@@ -320,6 +320,8 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
set_gdbarch_convert_from_func_ptr_addr
(gdbarch, ppc64_convert_from_func_ptr_addr);
+ set_gdbarch_convert_from_func_addr
+ (gdbarch, ppc64_convert_from_func_entry);
set_gdbarch_elf_make_msymbol_special (gdbarch,
ppc64_elf_make_msymbol_special);
@@ -2853,7 +2853,9 @@ value_as_address (struct value *val)
function, just return its address directly. */
if (TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
|| TYPE_CODE (value_type (val)) == TYPE_CODE_METHOD)
- return value_address (val);
+ return gdbarch_convert_from_func_ptr_addr (gdbarch,
+ value_address (val),
+ ¤t_target);
val = coerce_array (val);