On Tue, 11 Oct 2022 08:18:08 GMT, Christian Hagedorn <chaged...@openjdk.org> 
wrote:

>> The DWARF debugging symbols emitted by Clang is different from what GCC is 
>> emitting. While GCC produces a complete `.debug_aranges` section (which is 
>> required in the DWARF parser), Clang does not. As a result, the DWARF parser 
>> cannot find the necessary information to proceed and create the line number 
>> information:
>> 
>> The `.debug_aranges` section contains address range to compilation unit 
>> offset mappings. The parsing algorithm can just walk through all these 
>> entries to find the correct address range that contains the library offset 
>> of the current pc. This gives us the compilation unit offset into the 
>> `.debug_info` section from where we can proceed to parse the line number 
>> information.
>> 
>> Without a complete `.debug_aranges` section, we fail with an assertion that 
>> we could not find the correct entry. Since 
>> [JDK-8293402](https://bugs.openjdk.org/browse/JDK-8293402), we will still 
>> get the complete stack trace at least. Nevertheless, we should still fix 
>> this assertion failure of course. But that would require a different parsing 
>> approach. We need to parse the entire `.debug_info` section instead to get 
>> to the correct compilation unit. This, however, would require a lot more 
>> work. 
>> 
>> I therefore suggest to disable DWARF parsing for Clang for now and file an 
>> RFE to support Clang in the future with a different parsing approach. I'm 
>> using the `__clang__` `ifdef` to bail out in `get_source_info()` and disable 
>> the `gtests`. I've noticed that we are currently running the `gtests` with 
>> `NOT PRODUCT` which I think is not necessary - the gtests should also work 
>> fine with product builds. I've corrected this as well but that could also be 
>> done separately.
>> 
>> Thanks,
>> Christian
>
> Christian Hagedorn has updated the pull request with a new target base due to 
> a merge or a rebase. The incremental webrev excludes the unrelated changes 
> brought in by the merge/rebase. The pull request contains six additional 
> commits since the last revision:
> 
>  - Always read full filename and strip prefix path and only then cut filename 
> to fit output buffer
>  - Merge branch 'master' into JDK-8293422
>  - Merge branch 'master' into JDK-8293422
>  - Review comments from Thomas
>  - Change old bailout fix to only apply to Clang versions older than 5.0 and 
> add new fix with -gdwarf-aranges + -gdwarf-4 for Clang 5.0+
>  - 8293422: DWARF emitted by Clang cannot be parsed

Changes requested by stuefe (Reviewer).

src/hotspot/share/utilities/elfFile.cpp line 1605:

> 1603:   uint32_t current_index = 1; // file_names start at index 1
> 1604:   const size_t dwarf_filename_len = 1024;
> 1605:   char dwarf_filename[dwarf_filename_len]; // Store the filename read 
> from DWARF which is then copied to 'filename'.

Putting such a large array on the stack is a bit borderline. Especially in 
error reporting, where you may build up stack repeatedly via secondary crash 
handling. I realize though that no good alternatives exist. C-heap may be 
corrupted, ResourceArea is also out of the question. Could we get away with 
using filename directly?

src/hotspot/share/utilities/elfFile.cpp line 1636:

> 1634:   char* last_slash = strrchr(filename, *os::file_separator());
> 1635:   if (last_slash != nullptr) {
> 1636:     uint16_t index_after_slash = (uint16_t)(last_slash + 1 - filename);

Why uint16_t? 

We have `pointer_delta()` for that btw if you want to be super correct. See 
globalDefinitions.hpp

src/hotspot/share/utilities/elfFile.cpp line 1638:

> 1636:     uint16_t index_after_slash = (uint16_t)(last_slash + 1 - filename);
> 1637:     // Copy filename to beginning of buffer.
> 1638:     int bytes_written = jio_snprintf(filename, filename_len - 
> index_after_slash, "%s", filename + index_after_slash);

I don't think this is guaranteed to work since the memory areas you move may 
interleave. You should copy char-wise, or use `memmove(3)`.

src/hotspot/share/utilities/elfFile.cpp line 1651:

> 1649:   int bytes_written = jio_snprintf(dst, count, "%s", src);
> 1650:   // Add null terminator.
> 1651:   dst[count - 1] = '\0';

Does it make sense to return a truncated file name up to the caller of 
`DwarfFile::LineNumberProgram::get_filename_from_header()`? Will this not just 
confuse him? I think it makes more sense to cleanly handle truncation, and e.g. 
skip file parsing for dwarf files with too long names.

src/hotspot/share/utilities/elfFile.hpp line 865:

> 863:     bool get_filename_from_header(uint32_t file_index, char* filename, 
> size_t filename_len);
> 864:     static void strip_path_prefix(char* filename, const size_t 
> filename_len);
> 865:     static void copy_dwarf_filename_to_filename(char* src, size_t 
> src_len, char* dst, size_t dst_len);

Stupid question, do these have to be exposed? Or could they be just static 
helpers in elfFile.cpp?

-------------

PR: https://git.openjdk.org/jdk/pull/10287

Reply via email to