[llvm-branch-commits] [lldb] [LLDB] Support Re-export Symbol for FunctionCall (PR #208998)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Aug 8 04:43:48 PDT 2026
https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/208998
>From 0b85e1e9f569820064e6cbf999a9853e7bdb3f8b Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Sat, 11 Jul 2026 19:11:57 +0800
Subject: [PATCH 1/4] Support Re-export Symbol for FunctionCall
A symbol can be a stub that is re-exported to another library. For
example, ELF can specify an auxiliary library and emit a zero-sized
symbol in the symbol table. This can cause expression evaluation to
resolve the stub instead of the actual function. Fix this by resolving
re-exported symbols to their actual addressed.
---
.../Process/Utility/InferiorCallPOSIX.cpp | 34 +++++++++++++++----
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 5226b9bbe7c78..f190b589ad704 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -33,6 +33,30 @@
using namespace lldb;
using namespace lldb_private;
+/// Pick a call target from \p sc_list. Re-exported symbols have no code of
+/// their own and are resolved through the library that actually defines
+/// them, mirroring what the dynamic linker does.
+static Address GetCallableAddress(Target &target,
+ const SymbolContextList &sc_list) {
+ const uint32_t count = sc_list.GetSize();
+ for (uint32_t i = 0; i < count; ++i) {
+ SymbolContext sc;
+ if (!sc_list.GetContextAtIndex(i, sc))
+ continue;
+ if (sc.symbol && sc.symbol->GetType() == eSymbolTypeReExported) {
+ // Pass the containing module so all of its re-exported libraries
+ // (e.g. an ELF filter library's filtees) are searched in order.
+ if (Symbol *actual =
+ sc.symbol->ResolveReExportedSymbol(target, sc.module_sp))
+ return actual->GetAddress();
+ // Unresolvable re-export: not callable.
+ continue;
+ }
+ return sc.GetFunctionOrSymbolAddress();
+ }
+ return Address();
+}
+
bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
addr_t addr, addr_t length, unsigned prot,
unsigned flags, addr_t fd, addr_t offset) {
@@ -50,8 +74,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list);
const uint32_t count = sc_list.GetSize();
if (count > 0) {
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(0, sc)) {
+ {
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
@@ -74,7 +97,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
prot_arg |= PROT_WRITE;
}
- Address mmap_addr = sc.GetFunctionOrSymbolAddress();
+ Address mmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
if (mmap_addr.IsValid()) {
auto type_system_or_err =
process->GetTarget().GetScratchTypeSystemForLanguage(
@@ -142,8 +165,7 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
ConstString("munmap"), eFunctionNameTypeFull, function_options, sc_list);
const uint32_t count = sc_list.GetSize();
if (count > 0) {
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(0, sc)) {
+ {
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
@@ -153,7 +175,7 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
options.SetTimeout(process->GetUtilityExpressionTimeout());
options.SetTrapExceptions(false);
- Address munmap_addr = sc.GetFunctionOrSymbolAddress();
+ Address munmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
if (munmap_addr.IsValid()) {
lldb::addr_t args[] = {addr, length};
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
>From cff87246629c8aeef17459c99d76b1f88c4a3486 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 14 Jul 2026 21:38:36 +0800
Subject: [PATCH 2/4] fixup! Support Re-export Symbol for FunctionCall
---
.../Plugins/Process/Utility/InferiorCallPOSIX.cpp | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index f190b589ad704..dbc53ce5fcee6 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -33,9 +33,10 @@
using namespace lldb;
using namespace lldb_private;
-/// Pick a call target from \p sc_list. Re-exported symbols have no code of
-/// their own and are resolved through the library that actually defines
-/// them, mirroring what the dynamic linker does.
+/// Pick a call target from \p sc_list. A symbol from an ELF filter/auxiliary
+/// library is resolved through its filtee(s) first, falling back to its own
+/// definition only if none of them provide it, mirroring what the dynamic
+/// linker does.
static Address GetCallableAddress(Target &target,
const SymbolContextList &sc_list) {
const uint32_t count = sc_list.GetSize();
@@ -43,14 +44,16 @@ static Address GetCallableAddress(Target &target,
SymbolContext sc;
if (!sc_list.GetContextAtIndex(i, sc))
continue;
- if (sc.symbol && sc.symbol->GetType() == eSymbolTypeReExported) {
+ if (sc.symbol) {
// Pass the containing module so all of its re-exported libraries
// (e.g. an ELF filter library's filtees) are searched in order.
if (Symbol *actual =
sc.symbol->ResolveReExportedSymbol(target, sc.module_sp))
return actual->GetAddress();
- // Unresolvable re-export: not callable.
- continue;
+ // A pure re-export placeholder with no filtee providing a definition
+ // has no code of its own and isn't callable.
+ if (sc.symbol->GetType() == eSymbolTypeReExported)
+ continue;
}
return sc.GetFunctionOrSymbolAddress();
}
>From 66dc68d21562acbe70b4ae035e46e121603f125c Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 14 Jul 2026 22:31:57 +0800
Subject: [PATCH 3/4] fixup! Support Re-export Symbol for FunctionCall
---
.../Process/Utility/InferiorCallPOSIX.cpp | 123 +++++++++---------
1 file changed, 60 insertions(+), 63 deletions(-)
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index dbc53ce5fcee6..f11594f2327d1 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -77,72 +77,69 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list);
const uint32_t count = sc_list.GetSize();
if (count > 0) {
- {
- EvaluateExpressionOptions options;
- options.SetStopOthers(true);
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTryAllThreads(true);
- options.SetDebug(false);
- options.SetTimeout(process->GetUtilityExpressionTimeout());
- options.SetTrapExceptions(false);
+ EvaluateExpressionOptions options;
+ options.SetStopOthers(true);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTryAllThreads(true);
+ options.SetDebug(false);
+ options.SetTimeout(process->GetUtilityExpressionTimeout());
+ options.SetTrapExceptions(false);
+
+ addr_t prot_arg;
+ if (prot == eMmapProtNone)
+ prot_arg = PROT_NONE;
+ else {
+ prot_arg = 0;
+ if (prot & eMmapProtExec)
+ prot_arg |= PROT_EXEC;
+ if (prot & eMmapProtRead)
+ prot_arg |= PROT_READ;
+ if (prot & eMmapProtWrite)
+ prot_arg |= PROT_WRITE;
+ }
- addr_t prot_arg;
- if (prot == eMmapProtNone)
- prot_arg = PROT_NONE;
- else {
- prot_arg = 0;
- if (prot & eMmapProtExec)
- prot_arg |= PROT_EXEC;
- if (prot & eMmapProtRead)
- prot_arg |= PROT_READ;
- if (prot & eMmapProtWrite)
- prot_arg |= PROT_WRITE;
+ Address mmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
+ if (mmap_addr.IsValid()) {
+ auto type_system_or_err =
+ process->GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC);
+ if (!type_system_or_err) {
+ llvm::consumeError(type_system_or_err.takeError());
+ return false;
}
-
- Address mmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
- if (mmap_addr.IsValid()) {
- auto type_system_or_err =
- process->GetTarget().GetScratchTypeSystemForLanguage(
- eLanguageTypeC);
- if (!type_system_or_err) {
- llvm::consumeError(type_system_or_err.takeError());
- return false;
- }
- auto ts = *type_system_or_err;
- if (!ts)
- return false;
- CompilerType void_ptr_type =
- ts->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
- const ArchSpec arch = process->GetTarget().GetArchitecture();
- MmapArgList args =
- process->GetTarget().GetPlatform()->GetMmapArgumentList(
- arch, addr, length, prot_arg, flags, fd, offset);
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
- *thread, mmap_addr, void_ptr_type, args, options));
- if (call_plan_sp) {
- DiagnosticManager diagnostics;
-
- StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
- if (frame) {
- ExecutionContext exe_ctx;
- frame->CalculateExecutionContext(exe_ctx);
- ExpressionResults result = process->RunThreadPlan(
- exe_ctx, call_plan_sp, options, diagnostics);
- if (result == eExpressionCompleted) {
-
- allocated_addr =
- call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
- LLDB_INVALID_ADDRESS);
- if (process->GetAddressByteSize() == 4) {
- if (allocated_addr == UINT32_MAX)
- return false;
- } else if (process->GetAddressByteSize() == 8) {
- if (allocated_addr == UINT64_MAX)
- return false;
- }
- return true;
+ auto ts = *type_system_or_err;
+ if (!ts)
+ return false;
+ CompilerType void_ptr_type =
+ ts->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
+ const ArchSpec arch = process->GetTarget().GetArchitecture();
+ MmapArgList args =
+ process->GetTarget().GetPlatform()->GetMmapArgumentList(
+ arch, addr, length, prot_arg, flags, fd, offset);
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
+ *thread, mmap_addr, void_ptr_type, args, options));
+ if (call_plan_sp) {
+ DiagnosticManager diagnostics;
+
+ StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+ if (frame) {
+ ExecutionContext exe_ctx;
+ frame->CalculateExecutionContext(exe_ctx);
+ ExpressionResults result = process->RunThreadPlan(
+ exe_ctx, call_plan_sp, options, diagnostics);
+ if (result == eExpressionCompleted) {
+
+ allocated_addr =
+ call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
+ LLDB_INVALID_ADDRESS);
+ if (process->GetAddressByteSize() == 4) {
+ if (allocated_addr == UINT32_MAX)
+ return false;
+ } else if (process->GetAddressByteSize() == 8) {
+ if (allocated_addr == UINT64_MAX)
+ return false;
}
+ return true;
}
}
}
>From 25c3eefe80778940d141af28fd9455eb0baee2ba Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Thu, 16 Jul 2026 22:42:37 +0800
Subject: [PATCH 4/4] fixup! Support Re-export Symbol for FunctionCall
---
.../Process/Utility/InferiorCallPOSIX.cpp | 52 +++++++++----------
1 file changed, 25 insertions(+), 27 deletions(-)
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index f11594f2327d1..d4d79e712a83d 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -165,33 +165,31 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
ConstString("munmap"), eFunctionNameTypeFull, function_options, sc_list);
const uint32_t count = sc_list.GetSize();
if (count > 0) {
- {
- EvaluateExpressionOptions options;
- options.SetStopOthers(true);
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTryAllThreads(true);
- options.SetDebug(false);
- options.SetTimeout(process->GetUtilityExpressionTimeout());
- options.SetTrapExceptions(false);
-
- Address munmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
- if (munmap_addr.IsValid()) {
- lldb::addr_t args[] = {addr, length};
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
- *thread, munmap_addr, CompilerType(), args, options));
- if (call_plan_sp) {
- DiagnosticManager diagnostics;
-
- StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
- if (frame) {
- ExecutionContext exe_ctx;
- frame->CalculateExecutionContext(exe_ctx);
- ExpressionResults result = process->RunThreadPlan(
- exe_ctx, call_plan_sp, options, diagnostics);
- if (result == eExpressionCompleted) {
- return true;
- }
+ EvaluateExpressionOptions options;
+ options.SetStopOthers(true);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTryAllThreads(true);
+ options.SetDebug(false);
+ options.SetTimeout(process->GetUtilityExpressionTimeout());
+ options.SetTrapExceptions(false);
+
+ Address munmap_addr = GetCallableAddress(process->GetTarget(), sc_list);
+ if (munmap_addr.IsValid()) {
+ lldb::addr_t args[] = {addr, length};
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
+ *thread, munmap_addr, CompilerType(), args, options));
+ if (call_plan_sp) {
+ DiagnosticManager diagnostics;
+
+ StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+ if (frame) {
+ ExecutionContext exe_ctx;
+ frame->CalculateExecutionContext(exe_ctx);
+ ExpressionResults result = process->RunThreadPlan(
+ exe_ctx, call_plan_sp, options, diagnostics);
+ if (result == eExpressionCompleted) {
+ return true;
}
}
}
More information about the llvm-branch-commits
mailing list