Skip to content

[libunwind] fix dynamic .eh_frame registration #77185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 16, 2024
Merged

Conversation

SihangZhu
Copy link
Contributor

Fix this issue #76957
Libgcc provides __register_frame to register a dynamic .eh_frame section, while __unw_add_dynamic_eh_frame_section can be used to do the same in libunwind. However, the address after dynamic .eh_frame are padding with 0 value, it will be identified as
legal CIE. And __unw_add_dynamic_eh_frame_section will continue to parse subsequent addresses until illegal memory or other sections are accessed.
This patch adds length formal parameter for dynamic registration.

@SihangZhu SihangZhu requested a review from a team as a code owner January 6, 2024 08:12
Copy link

github-actions bot commented Jan 6, 2024

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Jan 6, 2024

@llvm/pr-subscribers-libunwind

Author: None (SihangZhu)

Changes

Fix this issue #76957
Libgcc provides __register_frame to register a dynamic .eh_frame section, while __unw_add_dynamic_eh_frame_section can be used to do the same in libunwind. However, the address after dynamic .eh_frame are padding with 0 value, it will be identified as
legal CIE. And __unw_add_dynamic_eh_frame_section will continue to parse subsequent addresses until illegal memory or other sections are accessed.
This patch adds length formal parameter for dynamic registration.


Full diff: https://github.com/llvm/llvm-project/pull/77185.diff

2 Files Affected:

  • (modified) libunwind/src/libunwind.cpp (+3-2)
  • (modified) libunwind/src/libunwind_ext.h (+1-1)
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index cd610377b63de8..7d78d167b83434 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -318,13 +318,14 @@ void __unw_remove_dynamic_fde(unw_word_t fde) {
   DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
 }
 
-void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
+void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start, size_t length) {
   // The eh_frame section start serves as the mh_group
   unw_word_t mh_group = eh_frame_start;
   CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
   CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
   auto p = (LocalAddressSpace::pint_t)eh_frame_start;
-  while (true) {
+  auto end = p + length;
+  while (p < end) {
     if (CFI_Parser<LocalAddressSpace>::decodeFDE(
             LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
             true) == NULL) {
diff --git a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h
index 28db43a4f6eef2..1bfb595c46130f 100644
--- a/libunwind/src/libunwind_ext.h
+++ b/libunwind/src/libunwind_ext.h
@@ -55,7 +55,7 @@ extern void __unw_iterate_dwarf_unwind_cache(void (*func)(
 extern void __unw_add_dynamic_fde(unw_word_t fde);
 extern void __unw_remove_dynamic_fde(unw_word_t fde);
 
-extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start);
+extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start, size_t length);
 extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start);
 
 #ifdef __APPLE__

Copy link

github-actions bot commented Jan 6, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I think this is a reasonable change, I don't think we can change this function signature without breaking the ABI. So it probably needs to be a new function instead.

Copy link
Contributor

@lhames lhames left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @arichardson noted this would break the ABI.

The best solution is to fix the implementation of __unw_add_dynamic_eh_frame_section (and __unw_remove_dynamic_eh_frame_section) as described in #76957 (comment).

@SihangZhu SihangZhu force-pushed the libunwind branch 2 times, most recently from 8d718a7 to 98c8249 Compare January 9, 2024 06:42
@SihangZhu SihangZhu changed the title [libunwind] Add length info for dynamic .eh_frame registration [libunwind] fix dynamic .eh_frame registration Jan 9, 2024
@SihangZhu SihangZhu requested a review from lhames January 9, 2024 08:44
@SihangZhu
Copy link
Contributor Author

As @arichardson noted this would break the ABI.

The best solution is to fix the implementation of __unw_add_dynamic_eh_frame_section (and __unw_remove_dynamic_eh_frame_section) as described in #76957 (comment).

thx for advice.

@SihangZhu SihangZhu requested a review from arichardson January 11, 2024 01:14
@SihangZhu
Copy link
Contributor Author

@lhames Could you check again, I have fixed the implementation as you decribed

@lhames
Copy link
Contributor

lhames commented Jan 15, 2024

Hi @SihangZhu. Sorry for the delay — will try to review this tomorrow.

Copy link
Contributor

@lhames lhames left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok -- local testing seems to confirm that this is the right fix. We need to add a testcase for this API, but that can happen as a follow-up.

@hstk30-hw hstk30-hw merged commit 58b33d0 into llvm:main Jan 16, 2024
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
Fix this issue
[llvm#76957](llvm#76957)
Libgcc provides __register_frame to register a dynamic .eh_frame
section, while __unw_add_dynamic_eh_frame_section can be used to do the
same in libunwind. However, the address after dynamic .eh_frame are
padding with 0 value, it will be identified as
legal CIE. And __unw_add_dynamic_eh_frame_section will continue to parse
subsequent addresses until illegal memory or other sections are
accessed.
This patch adds length formal parameter for dynamic registration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants