Skip to content

[BOLT] Fix LSDA section handling #71821

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 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions bolt/include/bolt/Rewrite/RewriteInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,6 @@ class RewriteInstance {
/// Manage a pipeline of metadata handlers.
class MetadataManager MetadataManager;

/// Get the contents of the LSDA section for this binary.
ArrayRef<uint8_t> getLSDAData();

/// Get the mapped address of the LSDA section for this binary.
uint64_t getLSDAAddress();

static const char TimerGroupName[];

static const char TimerGroupDesc[];
Expand Down Expand Up @@ -540,7 +534,6 @@ class RewriteInstance {
}

/// Exception handling and stack unwinding information in this binary.
ErrorOr<BinarySection &> LSDASection{std::errc::bad_address};
ErrorOr<BinarySection &> EHFrameSection{std::errc::bad_address};

/// .note.gnu.build-id section.
Expand Down
18 changes: 8 additions & 10 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1706,13 +1706,6 @@ void RewriteInstance::relocateEHFrameSection() {
check_error(std::move(E), "failed to patch EH frame");
}

ArrayRef<uint8_t> RewriteInstance::getLSDAData() {
return ArrayRef<uint8_t>(LSDASection->getData(),
LSDASection->getContents().size());
}

uint64_t RewriteInstance::getLSDAAddress() { return LSDASection->getAddress(); }

Error RewriteInstance::readSpecialSections() {
NamedRegionTimer T("readSpecialSections", "read special sections",
TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
Expand Down Expand Up @@ -1751,7 +1744,6 @@ Error RewriteInstance::readSpecialSections() {

HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text");
HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab");
LSDASection = BC->getUniqueSectionByName(".gcc_except_table");
EHFrameSection = BC->getUniqueSectionByName(".eh_frame");
BuildIDSection = BC->getUniqueSectionByName(".note.gnu.build-id");

Expand Down Expand Up @@ -3109,8 +3101,14 @@ void RewriteInstance::disassembleFunctions() {

// Parse LSDA.
if (Function.getLSDAAddress() != 0 &&
!BC->getFragmentsToSkip().count(&Function))
Function.parseLSDA(getLSDAData(), getLSDAAddress());
!BC->getFragmentsToSkip().count(&Function)) {
ErrorOr<BinarySection &> LSDASection =
BC->getSectionForAddress(Function.getLSDAAddress());
check_error(LSDASection.getError(), "failed to get LSDA section");
ArrayRef<uint8_t> LSDAData = ArrayRef<uint8_t>(
LSDASection->getData(), LSDASection->getContents().size());
Function.parseLSDA(LSDAData, LSDASection->getAddress());
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions bolt/test/Inputs/lsda.ldscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SECTIONS {
.text : { *(.text*) }
Copy link
Member

Choose a reason for hiding this comment

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

lld creates a PF_R PT_LOAD. For best portability, the first section of each segment should be specified. I created #93763

.gcc_except_table.main : { *(.gcc_except_table*) }
. = 0x20000;
.eh_frame : { *(.eh_frame) }
. = 0x80000;
}
47 changes: 47 additions & 0 deletions bolt/test/lsda.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// This test check that LSDA section named by .gcc_except_table.main is
// disassembled by BOLT.

// RUN: %clang++ %cxxflags -O3 -flto=thin -no-pie -c %s -o %t.o
// RUN: %clang++ %cxxflags -flto=thin -no-pie -fuse-ld=lld %t.o -o %t.exe \
Comment on lines +4 to +5
Copy link
Contributor

Choose a reason for hiding this comment

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

Is ThinLTO flag needed for this test case?

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently definitely not since I've added @rafaelauler offer to the ld script at least (I'm not sure does the problem has any connection to lto by default, probably not). I've just re-used the test provided in #71804 . Does it raise some problem here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I’ve had an issue on a system where lld’s version didn’t match that of the compiler. Uncommon scenario, but nevertheless it’s better to fix.

// RUN: -Wl,-q -Wl,--script=%S/Inputs/lsda.ldscript
// RUN: llvm-readelf -SW %t.exe | FileCheck %s
// RUN: llvm-bolt %t.exe -o %t.bolt

// CHECK: .gcc_except_table.main

#include <iostream>

class MyException : public std::exception {
public:
const char *what() const throw() {
return "Custom Exception: an error occurred!";
}
};

int divide(int a, int b) {
if (b == 0) {
throw MyException();
}
return a / b;
}

int main() {
try {
int result = divide(10, 2); // normal case
std::cout << "Result: " << result << std::endl;
result = divide(5, 0); // will cause exception
std::cout << "Result: " << result << std::endl;
// this line will not execute
} catch (const MyException &e) {
// catch custom exception
std::cerr << "Caught exception: " << e.what() << std::endl;
} catch (const std::exception &e) {
// catch other C++ exceptions
std::cerr << "Caught exception: " << e.what() << std::endl;
} catch (...) {
// catch all other exceptions
std::cerr << "Caught unknown exception" << std::endl;
}

return 0;
}