[RFC] While processing a struct die, store the method's address in its fn_field

Siva Chandra
2014-11-24T15:55:01Z

[-- Attachment #1: Type: text/plain, Size: 2683 bytes --]

[The tests in this patch depend on this patch:
https://sourceware.org/ml/gdb-patches/2014-11/msg00479.html. Also, it
adds a new dwarf2 test which I am not very sure I got it right.]

While processing a struct die, store the method's address in its fn_field.

This enables calling the method when its physname is missing and its
minsym cannot be discovered, but its address (DW_AT_low_pc) is available.
For example, this happens for the operator() methods of c++11 lambdas.
Consider the following C++ code:

int
main ()
{
auto lambda = [] (int j) { return j + 113; };
return lambda (-113);
}

When compiled with g++, the DWARF corresponding to the lambda's operator()
shows up under the DWARF for the function main as follows:

DW_TAG_subprogram
DW_AT_name "operator()"
DW_AT_type <0x0000002d>
DW_AT_artificial yes(1)
DW_AT_low_pc 0x00400566
DW_AT_high_pc <offset-from-lowpc>19
DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa
DW_AT_object_pointer <0x0000010f>
DW_AT_GNU_all_call_sites yes(1)
DW_TAG_pointer_type
DW_AT_byte_size 0x00000008
DW_AT_type <0x000000b9>
DW_TAG_formal_parameter
DW_AT_name "__closure"
DW_AT_type <0x0000011b>
DW_AT_artificial yes(1)
DW_AT_location len 0x0002: 9168: DW_OP_fbreg -24
DW_TAG_const_type
DW_AT_type <0x00000109>
DW_TAG_formal_parameter
DW_AT_name "j"
DW_AT_decl_file 0x00000001
DW_AT_decl_line 0x00000004
DW_AT_type <0x0000002d>
DW_AT_location len 0x0002: 9164:DW_OP_fbreg -28

There is no physname and the minsym corresponding to the the operator()
method does not demangle to its qualified name as specified by the DWARF.
However, since DW_AT_low_pc is available, it can be used to create a value
corresponding to the method in value.c:value_fn_field and subsequently be
passed to call_function_by_hand to invoke it.

gdb/ChangeLog:

2014-11-24 Siva Chandra Reddy <sivachandra@google.com>

* dwarf2read.c (dwarf2_add_member_fn): Note the methods address
if its DT_AT_low_pc is available.
* gdbtypes.h (struct fn_field): New field ADDR.
(TYPE_FN_FIELD_ADDR): New macro.
* value.c (value_fn_field): Use address of the method if
available.

gdb/testsuite/ChangeLog:

2014-11-24 Siva Chandra Reddy <sivachandra@google.com>

* gdb.dwarf2/dw2-member-function-addr.S: New file.
* gdb.dwarf2/dw2-member-function-addr.exp: New file.

[-- Attachment #2: member-function-addr-v1.txt --]
[-- Type: text/plain, Size: 18167 bytes --]

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 0790388..3a36cb1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -12654,6 +12654,11 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
/* Fill in the member function field info. */
fnp = &new_fnfield->fnfield;

+ /* Set the address of the method if die has DW_AT_low_pc. */
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+ if (attr)
+ fnp->addr = attr_value_as_address (attr);
+
/* Delay processing of the physname until later. */
if (cu->language == language_cplus || cu->language == language_java)
{
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index d32c97c..d98887a 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -885,6 +885,9 @@ struct cplus_struct_type

struct fn_field
{
+ /* For methods which are not virtual, then this is the
+ real address of the method if it is non-zero. */
+ CORE_ADDR addr;

/* * If is_stub is clear, this is the mangled name which
we can look up to find the address of the method
@@ -1344,6 +1347,7 @@ extern void allocate_gnat_aux_type (struct type *);

#define TYPE_FN_FIELD(thisfn, n) (thisfn)[n]
#define TYPE_FN_FIELD_PHYSNAME(thisfn, n) (thisfn)[n].physname
+#define TYPE_FN_FIELD_ADDR(thisfn, n) (thisfn)[n].addr
#define TYPE_FN_FIELD_TYPE(thisfn, n) (thisfn)[n].type
#define TYPE_FN_FIELD_ARGS(thisfn, n) TYPE_FIELDS ((thisfn)[n].type)
#define TYPE_FN_FIELD_CONST(thisfn, n) ((thisfn)[n].is_const)
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.S b/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.S
new file mode 100644
index 0000000..a89aa27
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.S
@@ -0,0 +1,460 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* The contents below were generated by compiling the code below with
+ g++ -g-dA -S -std=c++11 lambda.cc
+
+ int
+ main ()
+ {
+ auto lambda = [] (int j) { return j + 113; };
+ return lambda (-113);
+ } */
+
+ .file "lambda.cc"
+ .text
+.Ltext0:
+ .align 2
+ .type _ZZ4mainENKUliE_clEi, @function
+_ZZ4mainENKUliE_clEi:
+.LFB1:
+ .file 1 "lambda.cc"
+ # lambda.cc:4
+ .loc 1 4 0
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movq %rdi, -8(%rbp)
+ movl %esi, -12(%rbp)
+.LBB2:
+ # lambda.cc:4
+ .loc 1 4 0
+ movl -12(%rbp), %eax
+ addl $113, %eax
+.LBE2:
+ popq %rbp
+ .cfi_def_cfa 7, 8
+# SUCC: EXIT [100.0%]
+ ret
+ .cfi_endproc
+.LFE1:
+ .size _ZZ4mainENKUliE_clEi, .-_ZZ4mainENKUliE_clEi
+ .globl main
+ .type main, @function
+main:
+.LFB0:
+ # lambda.cc:3
+ .loc 1 3 0
+ .cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+.LBB3:
+ # lambda.cc:5
+ .loc 1 5 0
+ leaq -1(%rbp), %rax
+ movl $-113, %esi
+ movq %rax, %rdi
+ call _ZZ4mainENKUliE_clEi
+.LBE3:
+ # lambda.cc:6
+ .loc 1 6 0
+ leave
+ .cfi_def_cfa 7, 8
+# SUCC: EXIT [100.0%]
+ ret
+ .cfi_endproc
+.LFE0:
+ .size main, .-main
+.Letext0:
+ .section .debug_info,"",@progbits
+.Ldebug_info0:
+ .long 0x115 # Length of Compilation Unit Info
+ .value 0x4 # DWARF version number
+ .long .Ldebug_abbrev0 # Offset Into Abbrev. Section
+ .byte 0x8 # Pointer Size (in bytes)
+ .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
+ .long .LASF1 # DW_AT_producer: "GNU C++ 4.8.2 -mtune=generic -march=x86-64 -g -std=c++11 -fstack-protector"
+ .byte 0x4 # DW_AT_language
+ .long .LASF2 # DW_AT_name: "lambda.cc"
+ .long .LASF3 # DW_AT_comp_dir: "/home/sivachandra/LAB/c++"
+ .quad .Ltext0 # DW_AT_low_pc
+ .quad .Letext0-.Ltext0 # DW_AT_high_pc
+ .long .Ldebug_line0 # DW_AT_stmt_list
+ .uleb128 0x2 # (DIE (0x2d) DW_TAG_base_type)
+ .byte 0x4 # DW_AT_byte_size
+ .byte 0x5 # DW_AT_encoding
+ .ascii "int\0" # DW_AT_name
+ .uleb128 0x3 # (DIE (0x34) DW_TAG_subprogram)
+ # DW_AT_external
+ .long .LASF4 # DW_AT_name: "main"
+ .byte 0x1 # DW_AT_decl_file (lambda.cc)
+ .byte 0x2 # DW_AT_decl_line
+ .long 0x2d # DW_AT_type
+ .quad .LFB0 # DW_AT_low_pc
+ .quad .LFE0-.LFB0 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ # DW_AT_GNU_all_tail_call_sites
+ .uleb128 0x4 # (DIE (0x51) DW_TAG_lexical_block)
+ .quad .LBB3 # DW_AT_low_pc
+ .quad .LBE3-.LBB3 # DW_AT_high_pc
+ .uleb128 0x5 # (DIE (0x62) DW_TAG_variable)
+ .long .LASF5 # DW_AT_name: "lambda"
+ .byte 0x1 # DW_AT_decl_file (lambda.cc)
+ .byte 0x4 # DW_AT_decl_line
+ .long 0x70 # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -17
+ .uleb128 0x6 # (DIE (0x70) DW_TAG_structure_type)
+ .long .LASF6 # DW_AT_name: "__lambda0"
+ .byte 0x1 # DW_AT_byte_size
+ .byte 0x1 # DW_AT_decl_file (lambda.cc)
+ .byte 0x4 # DW_AT_decl_line
+ .uleb128 0x7 # (DIE (0x78) DW_TAG_subprogram)
+ .long .LASF0 # DW_AT_name: "<lambda>"
+ # DW_AT_artificial
+ # DW_AT_declaration
+ .long 0x85 # DW_AT_object_pointer
+ .long 0x9c # DW_AT_sibling
+ .uleb128 0x8 # (DIE (0x85) DW_TAG_formal_parameter)
+ .long 0x8a # DW_AT_type
+ # DW_AT_artificial
+ .uleb128 0x9 # (DIE (0x8a) DW_TAG_pointer_type)
+ .byte 0x8 # DW_AT_byte_size
+ .long 0x70 # DW_AT_type
+ .uleb128 0xa # (DIE (0x90) DW_TAG_formal_parameter)
+ .long 0x95 # DW_AT_type
+ .uleb128 0xb # (DIE (0x95) DW_TAG_rvalue_reference_type)
+ .byte 0x8 # DW_AT_byte_size
+ .long 0x70 # DW_AT_type
+ .byte 0 # end of children of DIE 0x78
+ .uleb128 0x7 # (DIE (0x9c) DW_TAG_subprogram)
+ .long .LASF0 # DW_AT_name: "<lambda>"
+ # DW_AT_artificial
+ # DW_AT_declaration
+ .long 0xa9 # DW_AT_object_pointer
+ .long 0xbf # DW_AT_sibling
+ .uleb128 0x8 # (DIE (0xa9) DW_TAG_formal_parameter)
+ .long 0x8a # DW_AT_type
+ # DW_AT_artificial
+ .uleb128 0xa # (DIE (0xae) DW_TAG_formal_parameter)
+ .long 0xb3 # DW_AT_type
+ .uleb128 0xc # (DIE (0xb3) DW_TAG_reference_type)
+ .byte 0x8 # DW_AT_byte_size
+ .long 0xb9 # DW_AT_type
+ .uleb128 0xd # (DIE (0xb9) DW_TAG_const_type)
+ .long 0x70 # DW_AT_type
+ .byte 0 # end of children of DIE 0x9c
+ .uleb128 0x7 # (DIE (0xbf) DW_TAG_subprogram)
+ .long .LASF0 # DW_AT_name: "<lambda>"
+ # DW_AT_artificial
+ # DW_AT_declaration
+ .long 0xcc # DW_AT_object_pointer
+ .long 0xd2 # DW_AT_sibling
+ .uleb128 0x8 # (DIE (0xcc) DW_TAG_formal_parameter)
+ .long 0x8a # DW_AT_type
+ # DW_AT_artificial
+ .byte 0 # end of children of DIE 0xbf
+ .uleb128 0xe # (DIE (0xd2) DW_TAG_subprogram)
+ .long .LASF7 # DW_AT_name: "operator()"
+ .long 0x2d # DW_AT_type
+ # DW_AT_artificial
+ .quad .LFB1 # DW_AT_low_pc
+ .quad .LFE1-.LFB1 # DW_AT_high_pc
+ .uleb128 0x1 # DW_AT_frame_base
+ .byte 0x9c # DW_OP_call_frame_cfa
+ .long 0xf7 # DW_AT_object_pointer
+ # DW_AT_GNU_all_call_sites
+ .uleb128 0x9 # (DIE (0xf1) DW_TAG_pointer_type)
+ .byte 0x8 # DW_AT_byte_size
+ .long 0xb9 # DW_AT_type
+ .uleb128 0xf # (DIE (0xf7) DW_TAG_formal_parameter)
+ .long .LASF8 # DW_AT_name: "__closure"
+ .long 0x103 # DW_AT_type
+ # DW_AT_artificial
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -24
+ .uleb128 0xd # (DIE (0x103) DW_TAG_const_type)
+ .long 0xf1 # DW_AT_type
+ .uleb128 0x10 # (DIE (0x108) DW_TAG_formal_parameter)
+ .ascii "j\0" # DW_AT_name
+ .byte 0x1 # DW_AT_decl_file (lambda.cc)
+ .byte 0x4 # DW_AT_decl_line
+ .long 0x2d # DW_AT_type
+ .uleb128 0x2 # DW_AT_location
+ .byte 0x91 # DW_OP_fbreg
+ .sleb128 -28
+ .byte 0 # end of children of DIE 0xd2
+ .byte 0 # end of children of DIE 0x70
+ .byte 0 # end of children of DIE 0x51
+ .byte 0 # end of children of DIE 0x34
+ .byte 0 # end of children of DIE 0xb
+ .section .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+ .uleb128 0x1 # (abbrev code)
+ .uleb128 0x11 # (TAG: DW_TAG_compile_unit)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x25 # (DW_AT_producer)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x13 # (DW_AT_language)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x1b # (DW_AT_comp_dir)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x10 # (DW_AT_stmt_list)
+ .uleb128 0x17 # (DW_FORM_sec_offset)
+ .byte 0
+ .byte 0
+ .uleb128 0x2 # (abbrev code)
+ .uleb128 0x24 # (TAG: DW_TAG_base_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3e # (DW_AT_encoding)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .byte 0
+ .byte 0
+ .uleb128 0x3 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3f # (DW_AT_external)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0x4 # (abbrev code)
+ .uleb128 0xb # (TAG: DW_TAG_lexical_block)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .byte 0
+ .byte 0
+ .uleb128 0x5 # (abbrev code)
+ .uleb128 0x34 # (TAG: DW_TAG_variable)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x6 # (abbrev code)
+ .uleb128 0x13 # (TAG: DW_TAG_structure_type)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .byte 0
+ .byte 0
+ .uleb128 0x7 # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x3c # (DW_AT_declaration)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x64 # (DW_AT_object_pointer)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x1 # (DW_AT_sibling)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0x8 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0x9 # (abbrev code)
+ .uleb128 0xf # (TAG: DW_TAG_pointer_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0xa # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0xb # (abbrev code)
+ .uleb128 0x42 # (TAG: DW_TAG_rvalue_reference_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0xc # (abbrev code)
+ .uleb128 0x10 # (TAG: DW_TAG_reference_type)
+ .byte 0 # DW_children_no
+ .uleb128 0xb # (DW_AT_byte_size)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0xd # (abbrev code)
+ .uleb128 0x26 # (TAG: DW_TAG_const_type)
+ .byte 0 # DW_children_no
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .byte 0
+ .byte 0
+ .uleb128 0xe # (abbrev code)
+ .uleb128 0x2e # (TAG: DW_TAG_subprogram)
+ .byte 0x1 # DW_children_yes
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x11 # (DW_AT_low_pc)
+ .uleb128 0x1 # (DW_FORM_addr)
+ .uleb128 0x12 # (DW_AT_high_pc)
+ .uleb128 0x7 # (DW_FORM_data8)
+ .uleb128 0x40 # (DW_AT_frame_base)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .uleb128 0x64 # (DW_AT_object_pointer)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .byte 0
+ .byte 0
+ .uleb128 0xf # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0xe # (DW_FORM_strp)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x34 # (DW_AT_artificial)
+ .uleb128 0x19 # (DW_FORM_flag_present)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .uleb128 0x10 # (abbrev code)
+ .uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
+ .byte 0 # DW_children_no
+ .uleb128 0x3 # (DW_AT_name)
+ .uleb128 0x8 # (DW_FORM_string)
+ .uleb128 0x3a # (DW_AT_decl_file)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x3b # (DW_AT_decl_line)
+ .uleb128 0xb # (DW_FORM_data1)
+ .uleb128 0x49 # (DW_AT_type)
+ .uleb128 0x13 # (DW_FORM_ref4)
+ .uleb128 0x2 # (DW_AT_location)
+ .uleb128 0x18 # (DW_FORM_exprloc)
+ .byte 0
+ .byte 0
+ .byte 0
+ .section .debug_aranges,"",@progbits
+ .long 0x2c # Length of Address Ranges Info
+ .value 0x2 # DWARF Version
+ .long .Ldebug_info0 # Offset of Compilation Unit Info
+ .byte 0x8 # Size of Address
+ .byte 0 # Size of Segment Descriptor
+ .value 0 # Pad to 16 byte boundary
+ .value 0
+ .quad .Ltext0 # Address
+ .quad .Letext0-.Ltext0 # Length
+ .quad 0
+ .quad 0
+ .section .debug_line,"",@progbits
+.Ldebug_line0:
+ .section .debug_str,"MS",@progbits,1
+.LASF3:
+ .string "/home/sivachandra/LAB/c++"
+.LASF6:
+ .string "__lambda0"
+.LASF7:
+ .string "operator()"
+.LASF2:
+ .string "lambda.cc"
+.LASF0:
+ .string "<lambda>"
+.LASF1:
+ .string "GNU C++ 4.8.2 -mtune=generic -march=x86-64 -g -std=c++11 -fstack-protector"
+.LASF4:
+ .string "main"
+.LASF5:
+ .string "lambda"
+.LASF8:
+ .string "__closure"
+ .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
+ .section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.exp
new file mode 100644
index 0000000..9356e35
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-member-function-addr.exp
@@ -0,0 +1,33 @@
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile .S
+
+if {[prepare_for_testing_full $testfile.exp \
+ [list $testfile debug $srcfile nodebug]]} {
+ return -1
+}
+
+clean_restart $testfile
+
+gdb_test "break main" "Breakpoint 1 .*" "break main"
+gdb_test "run" "Starting program: .*Breakpoint 1.*" "run"
+gdb_test "p lambda(10)" ".* = 123" "p lambda()"
diff --git a/gdb/value.c b/gdb/value.c
index ecfb154..7c83b81 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3068,24 +3068,30 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
struct value *v;
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
- struct symbol *sym;
+ const CORE_ADDR addr = TYPE_FN_FIELD_ADDR (f, j);
+ struct symbol *sym = NULL;
struct bound_minimal_symbol msym;

- sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0);
- if (sym != NULL)
+ if (!addr)
{
- memset (&msym, 0, sizeof (msym));
- }
- else
- {
- gdb_assert (sym == NULL);
- msym = lookup_bound_minimal_symbol (physname);
- if (msym.minsym == NULL)
- return NULL;
+ sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0);
+ if (sym != NULL)
+ {
+ memset (&msym, 0, sizeof (msym));
+ }
+ else
+ {
+ gdb_assert (sym == NULL);
+ msym = lookup_bound_minimal_symbol (physname);
+ if (msym.minsym == NULL)
+ return NULL;
+ }
}

v = allocate_value (ftype);
- if (sym)
+ if (addr)
+ set_value_address (v, f->addr);
+ else if (sym)
{
set_value_address (v, BLOCK_START (SYMBOL_BLOCK_VALUE (sym)));
}