RFC: Considering expanding the inline functions of the frames in hs_err file

Christian Hagedorn christian.hagedorn at oracle.com
Thu Apr 27 08:55:21 UTC 2023


Hi Gaodan

Thanks for looking closer into this! Generally, providing the inlined method
names with their source information in hs_err_files would often simplify the
analysis of stacktrace a lot.

On 20.04.23 09:25, 高丹(昭珏) wrote:
> 
> Hi everyone!
> I noticed the same problem with JDK-8305005[1] that the function name sometimes
> not match with the source line information in hs_err file. As Dean Long
> said, the code that gets the function name is using dladdr(), so it gets the
> outer-most frame. The code that gets the file name and line number is using
> ElfDecoder-->ElfFile-->DwarfFile and gets the inner-most frame. I think the
> problem can be solved by expanding the inline functions of each frame. 
> 
> V  [libjvm.so+0x967d21]  JNI_CreateJavaVM+0x51  (jni.cpp:3571)
> For example, as above, jni.cpp:3571 is in JNI_CreateJavaVM_inner, however,
> because of the inlining of JNI_CreateJavaVM_inner, dladdr() can only get
> the outer-most frame JNI_CreateJavaVM. By expanding the inline functions of the
> frame, we can get the following frames:
> V  [libjvm.so+0x967d21]  JNI_CreateJavaVM_inner(jni.cpp:3571)
> JNI_CreateJavaVM(jni.cpp:3657)
> Thus the function name can be consistent with source line information. But so
> far I don't know how to get the offset of outer frame.

I'm not sure either how to get this information apart from parsing it from the
DWARF file - maybe someone else has some more insights how we could do that.

I've had a closer look at what the DWARF file is providing us. We could get the
offset of the caller from DW_AT_entry_pc from the DW_TAG_inlined_subroutine
block and then use dladdr() on it. But we could also get the function name
directly from DW_AT_name (if present) or from DW_AT_abstract_origin ->
DW_TAG_subprogram -> DW_AT_name (the DWARF 4 spec mentions that some attributes
could be omitted in the inlined instance and can instead be found at the
reference pointed to by DW_AT_abstract_origin which appears to be a
DW_TAG_subprogram block (need to check the spec if this is always the case)).

For your example above, the DW_TAG_inlined_subroutine block looks like this
(using llvm-dwarfdump --debug-info):

                  DW_AT_abstract_origin (0x09d17c46 "JNI_CreateJavaVM_inner")
                  DW_AT_entry_pc        (0x0000000000f51c05)
                  DW_AT_GNU_entry_view  (0x0000)
                  DW_AT_ranges  (0x01e95b80
                     [0x0000000000f51bf1, 0x0000000000f51bf6)
                     [0x0000000000f51c05, 0x0000000000f51c0c)
                     [0x0000000000f51c16, 0x0000000000f51cbf)
                     [0x0000000000f51cd8, 0x0000000000f520c6)
                     [0x0000000000f520cb, 0x0000000000f52192))
                  DW_AT_call_file
("/home/christian/jdk/open/src/hotspot/share/prims/jni.cpp")
                  DW_AT_call_line       (3657)
                  DW_AT_call_column     (0x24)

....

0x09d17c46:   DW_TAG_subprogram
                DW_AT_name      ("JNI_CreateJavaVM_inner")


I'm not sure though how reliable this is and if we always have a DW_AT_entry_pc
entry.

However, when going with this approach of fetching the caller pc and/or method
name from the DWARF file, it would make things more complicated as we are
starting to mix it with the source information retrieval. We would need to be
more careful how to design this correctly.

> I'm doing this work by pyelftools. Firstly we can obtain the compile unit by the
> given offset. And then by recursively traversing the children of top debugging
> information entry of the compile unit, we can obtain the call frames of inline
> functions and get the source file and line number by 'DW_AT_call_file' and 
> 'DW_AT_call_line'. I'm considering implementing this feature on the fundamental
> of JDK-8242181, as I believe it could provide convenience for many users
Anyways, I think your proposed approach here is promising and definitely worth a
try! Hopefully, DW_AT_call_file and DW_AT_call_line are always available as the
DWARF spec is a bit vague here by saying "An inlined subroutine entry *may* also
have DW_AT_call_file, DW_AT_call_line and DW_AT_call_column attributes [..]".
Maybe you can find out more about how reliable that is and what the alternatives
would be in case they are not present. But even when these attributes are
missing in some cases, we could just give up and bail out.

> I wonder what you think about this issue. I'm willing to fix it if it is
> worthy. Any ideas are appreciated. 

Thanks for giving it a shot! If you have questions about the current DWARF
parser implementation, just reach out to me.

Best regards,
Christian

> 
> Best Regards.
> [1]https://bugs.openjdk.org/browse/JDK-8305005
> <https://bugs.openjdk.org/browse/JDK-8305005>
> 


More information about the hotspot-runtime-dev mailing list